Currently, sppp(4) interfaces use a destination address of 0.0.0.1 to
indicate that the destination address should be assigned by the peer:

           inet 0.0.0.0 255.255.255.255 NONE \
                   pppoedev em0 authproto pap \
                   authname 'testcaller' authkey 'donttell' up
           dest 0.0.0.1

As a side effect a route to 0.0.0.1 is added to the routing table.

Apparently, in 5.7 this still used to work with mulitple pppoe interfaces
which shared a routing table:
http://marc.info/?l=openbsd-misc&m=149386503001033&w=2

At present only one pppoe interface can be used in this way because
setting a dest address of 0.0.0.1 on additional interfaces now causes
an error: ifconfig: SIOCAIFADDR: File exists

This diff changes the way dynamic addresses are configured in sppp(4).
Instead of using magic IP addresses as wildcards, we allow userland to
control behavior via new ifconfig command flags. 'dynaddr' enables a
dynamic local address, and 'dyndest' enables a dynamic destination address.
To disable either of these again, prepend a minus (e.g. -dynaddr).

The above example becomes:

           inet 0.0.0.0 255.255.255.255 NONE \
                   pppoedev em0 authproto pap \
                   authname 'testcaller' authkey 'donttell' \
                   dynaddr dyndest up

Tested on my ADSL line and it works as expected.

I cannot test it on multiple links until next week, but since no route
for 0.0.0.1 is in the routing table anymore, I expect this to work.

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    9 Jun 2017 16:02:23 -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,16 @@ The protocol name can be either
 or
 .Ql none .
 In the latter case, authentication will be turned off.
+.It Cm dynaddr
+The local address will be assigned by the peer.
+.It Cm -dynaddr
+Disable dynamic assignment of the local address.
+This is the default.
+.It Cm dyndest
+The destination address will be assigned by the peer.
+.It Cm -dyndest
+Disable dynamic assignment of the destination 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: 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       9 Jun 2017 15:23:05 -0000
@@ -2601,44 +2601,16 @@ sppp_ipcp_tld(struct sppp *sp)
 void
 sppp_ipcp_tls(struct sppp *sp)
 {
-       STDDCL;
        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);
-       /*
-        * If we don't have his address, this probably means our
-        * interface doesn't want to talk IP at all.  (This could
-        * be the case if somebody wants to speak only IPX, for
-        * example.)  Don't open IPCP in this case.
-        */
-       if (hisaddr == 0) {
-               /* XXX this message should go away */
-               if (debug)
-                       log(LOG_DEBUG, SPP_FMT "ipcp_open(): no IP interface\n",
-                           SPP_ARGS(ifp));
-               return;
-       }
 
-       if (myaddr == 0) {
-               /*
-                * I don't have an assigned address, so i need to
-                * negotiate my address.
-                */
-               sp->ipcp.flags |= IPCP_MYADDR_DYN;
+       if (sp->ipcp.flags & IPCP_MYADDR_DYN)
                sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
-       }
-       if (hisaddr == 1) {
-               /*
-                * XXX - remove this hack!
-                * remote has no valid address, we need to get one assigned.
-                */
-               sp->ipcp.flags |= IPCP_HISADDR_DYN;
-       }
 
        /* indicate to LCP that it must stay alive */
        sp->lcp.protos |= (1 << IDX_IPCP);
@@ -4506,6 +4478,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 +4600,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