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: