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:

Reply via email to