On Sat, Jun 10, 2017 at 08:35:13AM +0100, Jason McIntyre wrote:
> thanks. the ifconfig.8 bits look good, but i think you should also
> change the examples given in pppoe(4) to show the updated syntax, to
> prepare folks.
>
> actually i think it would be better to discuss the deprecated stuff
> in pppoe(4), rather than adding it to ifconfig(8).
Sure. I think it is also worth pointing out that all this is IPv4 only.
Also document sppp(4) behaviour with respect to the default route.
Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.282
diff -u -p -r1.282 ifconfig.8
--- sbin/ifconfig/ifconfig.8 12 May 2017 15:11:02 -0000 1.282
+++ sbin/ifconfig/ifconfig.8 10 Jun 2017 08:17:32 -0000
@@ -1393,6 +1393,8 @@ Clear a previously set service name.
.Op Cm authkey Ar key
.Op Cm authname Ar name
.Op Cm authproto Ar proto
+.Op Oo Fl Oc Ns Cm dynaddr
+.Op Oo Fl Oc Ns Cm dyndest
.Op Oo Fl Oc Ns Cm peerflag Ar flag
.Op Cm peerkey Ar key
.Op Cm peername Ar name
@@ -1419,6 +1421,19 @@ The protocol name can be either
or
.Ql none .
In the latter case, authentication will be turned off.
+.It Cm dynaddr
+The local IPv4 address will be changed to an address suggested by the peer.
+.It Cm -dynaddr
+Disable dynamic updates of the local IPv4 address.
+This is the default.
+.It Cm dyndest
+The destination IPv4 address will be changed to an address suggested
+by the peer.
+If a default route which uses this interface exists, the gateway will be
+changed to the suggested address as well.
+.It Cm -dyndest
+Disable dynamic updates of the destination IPv4 address.
+This is the default.
.It Cm peerflag Ar flag
Set a specified PPP flag for the remote authenticator.
The flag name can be either
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.342
diff -u -p -r1.342 ifconfig.c
--- sbin/ifconfig/ifconfig.c 5 Jun 2017 05:10:23 -0000 1.342
+++ sbin/ifconfig/ifconfig.c 9 Jun 2017 15:57:40 -0000
@@ -266,6 +266,9 @@ void setsppppeername(const char *, int);
void setsppppeerkey(const char *, int);
void setsppppeerflag(const char *, int);
void unsetsppppeerflag(const char *, int);
+void sipcpinfo(struct sipcpreq *);
+void setspppdynaddr(const char *, int);
+void setspppdyndest(const char *, int);
void sppp_status(void);
void sppp_printproto(const char *, struct sauthreq *);
void setifpriority(const char *, int);
@@ -446,6 +449,10 @@ const struct cmd {
{ "peerkey", NEXTARG, 0, setsppppeerkey },
{ "peerflag", NEXTARG, 0, setsppppeerflag },
{ "-peerflag", NEXTARG, 0, unsetsppppeerflag },
+ { "dynaddr", 1, 0, setspppdynaddr },
+ { "-dynaddr", 0, 0, setspppdynaddr },
+ { "dyndest", 1, 0, setspppdyndest },
+ { "-dyndest", 0, 0, setspppdyndest },
{ "nwflag", NEXTARG, 0, setifnwflag },
{ "-nwflag", NEXTARG, 0, unsetifnwflag },
{ "flowsrc", NEXTARG, 0, setpflow_sender },
@@ -4878,6 +4885,63 @@ unsetsppppeerflag(const char *val, int d
}
void
+sipcpinfo(struct sipcpreq *req)
+{
+ bzero(req, sizeof(*req));
+
+ ifr.ifr_data = (caddr_t)req;
+ req->cmd = SPPPIOGIPCP;
+ if (ioctl(s, SIOCGSPPPPARAMS, &ifr) == -1)
+ err(1, "SIOCGSPPPPARAMS(SPPPIOGIPCP)");
+}
+
+void
+setspppdynaddr(const char *val, int d)
+{
+ struct sipcpreq scp;
+
+ sipcpinfo(&scp);
+
+ if (d == 1) {
+ if (scp.flags & SIPCP_MYADDR_DYN)
+ return;
+ scp.flags |= SIPCP_MYADDR_DYN;
+ } else {
+ if ((scp.flags & SIPCP_MYADDR_DYN) == 0)
+ return;
+ scp.flags &= ~SIPCP_MYADDR_DYN;
+ }
+
+ scp.cmd = SPPPIOSIPCP;
+ if (ioctl(s, SIOCSSPPPPARAMS, &ifr) == -1)
+ err(1, "SIOCSSPPPPARAMS(SPPPIOSIPCP)");
+}
+
+
+void
+setspppdyndest(const char *val, int d)
+{
+ struct sipcpreq scp;
+
+ sipcpinfo(&scp);
+
+ if (d == 1) {
+ if (scp.flags & SIPCP_HISADDR_DYN)
+ return;
+ scp.flags |= SIPCP_HISADDR_DYN;
+ } else {
+ if ((scp.flags & SIPCP_HISADDR_DYN) == 0)
+ return;
+ scp.flags &= ~SIPCP_HISADDR_DYN;
+ }
+
+ scp.cmd = SPPPIOSIPCP;
+ if (ioctl(s, SIOCSSPPPPARAMS, &ifr) == -1)
+ err(1, "SIOCSSPPPPARAMS(SPPPIOSIPCP)");
+}
+
+
+void
sppp_printproto(const char *name, struct sauthreq *auth)
{
if (auth->proto == 0)
@@ -4905,6 +4969,7 @@ sppp_status(void)
{
struct spppreq spr;
struct sauthreq spa;
+ struct sipcpreq scp;
bzero(&spr, sizeof(spr));
@@ -4943,6 +5008,13 @@ sppp_status(void)
printf("callin ");
if (spa.flags & AUTHFLAG_NORECHALLENGE)
printf("norechallenge ");
+
+ sipcpinfo(&scp);
+ if (scp.flags & SIPCP_MYADDR_DYN)
+ printf("dynaddr ");
+ if (scp.flags & SIPCP_HISADDR_DYN)
+ printf("dyndest ");
+
putchar('\n');
}
Index: share/man/man4/pppoe.4
===================================================================
RCS file: /cvs/src/share/man/man4/pppoe.4,v
retrieving revision 1.33
diff -u -p -r1.33 pppoe.4
--- share/man/man4/pppoe.4 22 Mar 2017 21:37:24 -0000 1.33
+++ share/man/man4/pppoe.4 10 Jun 2017 08:11:35 -0000
@@ -99,9 +99,10 @@ A typical file looks like this:
inet 0.0.0.0 255.255.255.255 NONE \e
pppoedev em0 authproto pap \e
authname 'testcaller' authkey 'donttell' up
-dest 0.0.0.1
+dest 10.1.1.1
+dynaddr dyndest
inet6 eui64
-!/sbin/route add default -ifp pppoe0 0.0.0.1
+!/sbin/route add default -ifp pppoe0 10.1.1.1
!/sbin/route add -inet6 default -ifp pppoe0 fe80::%pppoe0
.Ed
.Pp
@@ -111,19 +112,28 @@ The physical interface must also be mark
# echo "up" > /etc/hostname.em0
.Ed
.Pp
+In the above example, 10.1.1.1 is an otherwise unused IP address which
+serves as a placeholder for dynamic address configuration.
Since this is a PPP interface, the addresses assigned to the interface
may change during PPP negotiation.
There is no fine grained control available for deciding
which addresses are acceptable and which are not.
-For the local side and the remote address there is exactly one choice:
-hard coded address or wildcard.
-If a real address is assigned to one side of the connection,
-PPP negotiation will only agree to exactly this address.
-If one side is wildcarded,
-every address suggested by the peer will be accepted.
+For the local address and the remote address each there is exactly one choice:
+hard coded address or dynamic address.
.Pp
+By default, PPP negotiation will only agree to exactly the IPv4 addresses
+which are configured on the interface.
+If dynamic address configuration is enabled for the local address (dynaddr)
+and/or remote address (dyndest), any address suggested by the peer will
+be accepted and overrides the addresses configured on the interface and
+the corresponding default route.
+.Pp
+A deprecated way of enabling dynamic addresses is by using wildcard addresses.
To wildcard the local address set it to 0.0.0.0; to wildcard the remote
-address set it to 0.0.0.1.
+address set it to 0.0.0.1 (multiple
+.Nm
+interfaces configured with this wildcard destination address cannot share
+a routing table).
.Sh KERNEL OPTIONS
.Nm
does not interfere with other PPPoE implementations
Index: sys/net/if_sppp.h
===================================================================
RCS file: /cvs/src/sys/net/if_sppp.h,v
retrieving revision 1.26
diff -u -p -r1.26 if_sppp.h
--- sys/net/if_sppp.h 24 Jan 2017 10:08:30 -0000 1.26
+++ sys/net/if_sppp.h 9 Jun 2017 15:17:31 -0000
@@ -82,12 +82,21 @@ struct spppreq {
enum ppp_phase phase; /* phase we're currently in */
};
+struct sipcpreq {
+ int cmd;
+ uint32_t flags; /* controls some flags in struct sipcp */
+#define SIPCP_MYADDR_DYN 1 /* my address will be dynamically assigned */
+#define SIPCP_HISADDR_DYN 2 /* his address will be dynamically assigned */
+};
+
#define SPPPIOGDEFS ((int)(('S' << 24) + (1 << 16) + sizeof(struct spppreq)))
#define SPPPIOSDEFS ((int)(('S' << 24) + (2 << 16) + sizeof(struct spppreq)))
#define SPPPIOGMAUTH ((int)(('S' << 24) + (3 << 16) + sizeof(struct sauthreq)))
#define SPPPIOSMAUTH ((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq)))
#define SPPPIOGHAUTH ((int)(('S' << 24) + (5 << 16) + sizeof(struct sauthreq)))
#define SPPPIOSHAUTH ((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq)))
+#define SPPPIOGIPCP ((int)(('S' << 24) + (7 << 16) + sizeof(struct sipcpreq)))
+#define SPPPIOSIPCP ((int)(('S' << 24) + (8 << 16) + sizeof(struct sipcpreq)))
#ifdef _KERNEL
Index: sys/net/if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.164
diff -u -p -r1.164 if_spppsubr.c
--- sys/net/if_spppsubr.c 30 May 2017 07:50:37 -0000 1.164
+++ sys/net/if_spppsubr.c 10 Jun 2017 08:04:28 -0000
@@ -72,6 +72,20 @@
#define MAXALIVECNT 3 /* max. missed alive packets */
#define NORECV_TIME 15 /* before we get
worried */
+/*
+ * The IPCP_MYADDR_DYN and IPCP_HISADDR_DYN flags can currently be set
+ * from userspace in two ways:
+ *
+ * 1) via the SIOCSSPPPPARAMS ioctl (SPPPIOSIPCP)
+ * 2) by setting my addr to 0.0.0.0 and/or hisaddr to 0.0.0.1 (DYNADDR_HACK)
+ *
+ * The DYNADDR_HACK is now deprecated but still supported until systems
+ * have had a chance to upgrade to a release which supports the ioctl.
+ * This soft transition helps in cases where the only network interface the
+ * system administrator can reach needs sppp(4) with dynamic addresses.
+ */
+#define SPPP_DYNADDR_HACK /* don't remove before OpenBSD 6.2 is released */
+
/*
* Interface flags that can be set in an ifconfig command.
*
@@ -2601,15 +2615,18 @@ sppp_ipcp_tld(struct sppp *sp)
void
sppp_ipcp_tls(struct sppp *sp)
{
+#ifdef SPPP_DYNADDR_HACK
STDDCL;
+#endif
u_int32_t myaddr, hisaddr;
- sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|
- IPCP_MYADDR_DYN|IPCP_HISADDR_DYN);
+ sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN);
sp->ipcp.req_myaddr = 0;
sp->ipcp.req_hisaddr = 0;
sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
+
+#ifdef SPPP_DYNADDR_HACK
/*
* If we don't have his address, this probably means our
* interface doesn't want to talk IP at all. (This could
@@ -2630,7 +2647,6 @@ sppp_ipcp_tls(struct sppp *sp)
* negotiate my address.
*/
sp->ipcp.flags |= IPCP_MYADDR_DYN;
- sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
}
if (hisaddr == 1) {
/*
@@ -2639,6 +2655,10 @@ sppp_ipcp_tls(struct sppp *sp)
*/
sp->ipcp.flags |= IPCP_HISADDR_DYN;
}
+#endif /* SPPP_DYNADDR_HACK */
+
+ if (sp->ipcp.flags & IPCP_MYADDR_DYN)
+ sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
/* indicate to LCP that it must stay alive */
sp->lcp.protos |= (1 << IDX_IPCP);
@@ -4506,6 +4526,22 @@ sppp_get_params(struct sppp *sp, struct
free(spa, M_DEVBUF, 0);
break;
}
+ case SPPPIOGIPCP: {
+ struct sipcpreq *req;
+
+ req = malloc(sizeof(*req), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (sp->ipcp.flags & IPCP_MYADDR_DYN)
+ req->flags |= SIPCP_MYADDR_DYN;
+ if (sp->ipcp.flags & IPCP_HISADDR_DYN)
+ req->flags |= SIPCP_HISADDR_DYN;
+
+ if (copyout(req, (caddr_t)ifr->ifr_data, sizeof(*req)) != 0) {
+ free(req, M_DEVBUF, 0);
+ return EFAULT;
+ }
+ free(req, M_DEVBUF, 0);
+ break;
+ }
default:
return EINVAL;
}
@@ -4612,6 +4648,28 @@ sppp_set_params(struct sppp *sp, struct
}
}
free(spa, M_DEVBUF, 0);
+ break;
+ }
+ case SPPPIOSIPCP: {
+ struct sipcpreq *req;
+
+ req = malloc(sizeof(*req), M_DEVBUF, M_WAITOK);
+
+ if (copyin((caddr_t)ifr->ifr_data, req, sizeof(*req)) != 0) {
+ free(req, M_DEVBUF, 0);
+ return EFAULT;
+ }
+
+ if (req->flags & SIPCP_MYADDR_DYN)
+ sp->ipcp.flags |= IPCP_MYADDR_DYN;
+ else
+ sp->ipcp.flags &= ~IPCP_MYADDR_DYN;
+
+ if (req->flags & SIPCP_HISADDR_DYN)
+ sp->ipcp.flags |= IPCP_HISADDR_DYN;
+ else
+ sp->ipcp.flags &= ~IPCP_HISADDR_DYN;
+
break;
}
default: