On Mon 08/11/2021 11:52, Bjorn Ketelaars wrote:
> Diff below does two things:
> 1. add PPP IPCP extensions for name server addresses (rfc1877) to
>    sppp(4)
> 2. propose negotiated name servers from sppp(4) to resolvd(8) using
>    RTM_PROPOSAL_STATIC route messages.


Updated diff below, based on feedback from kn@ and claudio@:

- fix forgotten parentheses with `sizeof`
- instead of using `u_int32_t` use `struct in_addr` for holding dns
  addresses. Makes it more clear what the data is
- decouple `IPCP_OPT` definitions from the bitmask values to
  enable/disable an option. Makes the code look a bit better
- use `memcpy`
- fit code within 80 columns

While here add RFC to sppp(4)'s STANDARDS section.

@kn, is this still OK for you?

Other OK's?


diff --git share/man/man4/sppp.4 share/man/man4/sppp.4
index 5ca10285953..bccb41eec15 100644
--- share/man/man4/sppp.4
+++ share/man/man4/sppp.4
@@ -230,6 +230,13 @@ take place.
 .Re
 .Pp
 .Rs
+.%A S. Cobb
+.%D December 1995
+.%R RFC 1877
+.%T PPP Internet Protocol Control Protocol Extensions for Name Server Addresses
+.Re
+.Pp
+.Rs
 .%A W. Simpson
 .%D August 1996
 .%R RFC 1994
diff --git sys/net/if_sppp.h sys/net/if_sppp.h
index ff559fcc369..5850a6da963 100644
--- sys/net/if_sppp.h
+++ sys/net/if_sppp.h
@@ -132,6 +132,8 @@ struct sipcp {
                                  * original one here, in network byte order */
        u_int32_t req_hisaddr;  /* remote address requested (IPv4) */
        u_int32_t req_myaddr;   /* local address requested (IPv4) */
+#define IPCP_MAX_DNSSRV        2
+       struct in_addr dns[IPCP_MAX_DNSSRV]; /* IPv4  DNS servers (RFC 1877) */
 #ifdef INET6
        struct in6_aliasreq req_ifid;   /* local ifid requested (IPv6) */
 #endif
diff --git sys/net/if_spppsubr.c sys/net/if_spppsubr.c
index ac1dc9a709d..e460703c089 100644
--- sys/net/if_spppsubr.c
+++ sys/net/if_spppsubr.c
@@ -132,6 +132,14 @@
 #define IPCP_OPT_ADDRESSES     1       /* both IP addresses; deprecated */
 #define IPCP_OPT_COMPRESSION   2       /* IP compression protocol (VJ) */
 #define IPCP_OPT_ADDRESS       3       /* local IP address */
+#define IPCP_OPT_PRIMDNS       129     /* primary remote dns address */
+#define IPCP_OPT_SECDNS                131     /* secondary remote dns address 
*/
+
+#define SPPP_IPCP_OPT_ADDRESSES                1       /* bitmask value */
+#define SPPP_IPCP_OPT_COMPRESSION      2       /* bitmask value */
+#define SPPP_IPCP_OPT_ADDRESS          3       /* bitmask value */
+#define SPPP_IPCP_OPT_PRIMDNS          4       /* bitmask value */
+#define SPPP_IPCP_OPT_SECDNS           5       /* bitmask value */
 
 #define IPV6CP_OPT_IFID                1       /* interface identifier */
 #define IPV6CP_OPT_COMPRESSION 2       /* IPv6 compression protocol */
@@ -338,6 +346,8 @@ void sppp_update_gw(struct ifnet *ifp);
 void sppp_set_ip_addrs(void *);
 void sppp_clear_ip_addrs(void *);
 void sppp_set_phase(struct sppp *sp);
+void sppp_update_dns(struct ifnet *ifp);
+void sppp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt);
 
 /* our control protocol descriptors */
 static const struct cp lcp = {
@@ -701,6 +711,7 @@ sppp_attach(struct ifnet *ifp)
 
        sp->pp_if.if_type = IFT_PPP;
        sp->pp_if.if_output = sppp_output;
+       sp->pp_if.if_rtrequest = sppp_rtrequest;
        ifq_set_maxlen(&sp->pp_if.if_snd, 50);
        mq_init(&sp->pp_cpq, 50, IPL_NET);
        sp->pp_loopcnt = 0;
@@ -2512,13 +2523,19 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header 
*h, int len)
                         * Peer doesn't grok address option.  This is
                         * bad.  XXX  Should we better give up here?
                         */
-                       sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS);
+                       sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_ADDRESS);
                        break;
 #ifdef notyet
                case IPCP_OPT_COMPRESS:
-                       sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS);
+                       sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_COMPRESS);
                        break;
 #endif
+               case IPCP_OPT_PRIMDNS:
+                       sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_PRIMDNS);
+                       break;
+               case IPCP_OPT_SECDNS:
+                       sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_SECDNS);
+                       break;
                }
        }
        if (debug)
@@ -2559,7 +2576,7 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, 
int len)
                        if (len >= 6 && p[1] == 6) {
                                wantaddr = p[2] << 24 | p[3] << 16 |
                                        p[4] << 8 | p[5];
-                               sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
+                               sp->ipcp.opts |= (1 << SPPP_IPCP_OPT_ADDRESS);
                                if (debug)
                                        addlog("[wantaddr %s] ",
                                               sppp_dotted_quad(wantaddr));
@@ -2584,6 +2601,16 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, 
int len)
                         */
                        break;
 #endif
+               case IPCP_OPT_PRIMDNS:
+                       if (len >= 6 && p[1] == 6)
+                               memcpy(&sp->ipcp.dns[0].s_addr, p + 2,
+                                   sizeof(sp->ipcp.dns[0].s_addr));
+                       break;
+               case IPCP_OPT_SECDNS:
+                       if (len >= 6 && p[1] == 6)
+                               memcpy(&sp->ipcp.dns[1].s_addr, p + 2,
+                                   sizeof(sp->ipcp.dns[1].s_addr));
+                       break;
                }
        }
        if (debug)
@@ -2612,6 +2639,7 @@ sppp_ipcp_tls(struct sppp *sp)
            IPCP_MYADDR_DYN|IPCP_HISADDR_DYN);
        sp->ipcp.req_myaddr = 0;
        sp->ipcp.req_hisaddr = 0;
+       memset(&sp->ipcp.dns, 0, sizeof(sp->ipcp.dns));
 
        sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0);
        /*
@@ -2634,7 +2662,7 @@ sppp_ipcp_tls(struct sppp *sp)
                 * negotiate my address.
                 */
                sp->ipcp.flags |= IPCP_MYADDR_DYN;
-               sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
+               sp->ipcp.opts |= (1 << SPPP_IPCP_OPT_ADDRESS);
        }
        if (hisaddr >= 1 && hisaddr <= 255) {
                /*
@@ -2644,6 +2672,10 @@ sppp_ipcp_tls(struct sppp *sp)
                sp->ipcp.flags |= IPCP_HISADDR_DYN;
        }
 
+       /* negotiate name server addresses */
+       sp->ipcp.opts |= (1 << SPPP_IPCP_OPT_PRIMDNS);
+       sp->ipcp.opts |= (1 << SPPP_IPCP_OPT_SECDNS);
+
        /* indicate to LCP that it must stay alive */
        sp->lcp.protos |= (1 << IDX_IPCP);
 }
@@ -2663,12 +2695,13 @@ sppp_ipcp_tlf(struct sppp *sp)
 void
 sppp_ipcp_scr(struct sppp *sp)
 {
-       char opt[6 /* compression */ + 6 /* address */];
+       char opt[6 /* compression */ + 6 /* address */ + 12 /* dns addrs */];
        u_int32_t ouraddr;
+       size_t sz;
        int i = 0;
 
 #ifdef notyet
-       if (sp->ipcp.opts & (1 << IPCP_OPT_COMPRESSION)) {
+       if (sp->ipcp.opts & (1 << SPPP_IPCP_OPT_COMPRESSION)) {
                opt[i++] = IPCP_OPT_COMPRESSION;
                opt[i++] = 6;
                opt[i++] = 0;   /* VJ header compression */
@@ -2678,7 +2711,7 @@ sppp_ipcp_scr(struct sppp *sp)
        }
 #endif
 
-       if (sp->ipcp.opts & (1 << IPCP_OPT_ADDRESS)) {
+       if (sp->ipcp.opts & (1 << SPPP_IPCP_OPT_ADDRESS)) {
                if (sp->ipcp.flags & IPCP_MYADDR_SEEN)
                        /* not sure if this can ever happen */
                        ouraddr = sp->ipcp.req_myaddr;
@@ -2692,6 +2725,22 @@ sppp_ipcp_scr(struct sppp *sp)
                opt[i++] = ouraddr;
        }
 
+       if (sp->ipcp.opts & (1 << SPPP_IPCP_OPT_PRIMDNS)) {
+               opt[i++] = IPCP_OPT_PRIMDNS;
+               opt[i++] = 6;
+               sz = sizeof(sp->ipcp.dns[0].s_addr);
+               memcpy(&opt[i], &sp->ipcp.dns[0].s_addr, sz);
+               i += sz;
+       }
+
+       if (sp->ipcp.opts & (1 << SPPP_IPCP_OPT_SECDNS)) {
+               opt[i++] = IPCP_OPT_SECDNS;
+               opt[i++] = 6;
+               sz = sizeof(sp->ipcp.dns[1].s_addr);
+               memcpy(&opt[i], &sp->ipcp.dns[1].s_addr, sz);
+               i += sz;
+       }
+
        sp->confid[IDX_IPCP] = ++sp->pp_seq;
        sppp_cp_send(sp, PPP_IPCP, CONF_REQ, sp->confid[IDX_IPCP], i, opt);
 }
@@ -4242,6 +4291,7 @@ sppp_set_ip_addrs(void *arg1)
                        goto out;
                }
                sppp_update_gw(ifp);
+               sppp_update_dns(ifp);
        }
 out:
        NET_UNLOCK();
@@ -4302,6 +4352,9 @@ sppp_clear_ip_addrs(void *arg1)
                        goto out;
                }
                sppp_update_gw(ifp);
+
+               memset(sp->ipcp.dns, 0, sizeof(sp->ipcp.dns));
+               sppp_update_dns(ifp);
        }
 out:
        NET_UNLOCK();
@@ -4721,6 +4774,8 @@ sppp_ipcp_opt_name(u_char opt)
        case IPCP_OPT_ADDRESSES:        return "addresses";
        case IPCP_OPT_COMPRESSION:      return "compression";
        case IPCP_OPT_ADDRESS:          return "address";
+       case IPCP_OPT_PRIMDNS:          return "primdns";
+       case IPCP_OPT_SECDNS:           return "secdns";
        }
        snprintf (buf, sizeof buf, "0x%x", opt);
        return buf;
@@ -4851,3 +4906,43 @@ sppp_set_phase(struct sppp *sp)
                if_link_state_change(ifp);
        }
 }
+
+void
+sppp_update_dns(struct ifnet *ifp)
+{
+       struct rt_addrinfo info;
+       struct sockaddr_rtdns rtdns;
+       struct sppp *sp = ifp->if_softc;
+       size_t sz = 0;
+       int i, flag = 0;
+
+       memset(&rtdns, 0, sizeof(rtdns));
+       memset(&info, 0, sizeof(info));
+
+       for (i = 0; i < IPCP_MAX_DNSSRV; i++) {
+               if (sp->ipcp.dns[i].s_addr == INADDR_ANY)
+                       break;
+               sz = sizeof(sp->ipcp.dns[i].s_addr);
+               memcpy(rtdns.sr_dns + i * sz, &sp->ipcp.dns[i].s_addr, sz);
+               flag = RTF_UP;
+       }
+
+       rtdns.sr_family = AF_INET;
+       rtdns.sr_len = 2 + i * sz;
+       info.rti_info[RTAX_DNS] = srtdnstosa(&rtdns);
+
+       rtm_proposal(ifp, &info, flag, RTP_PROPOSAL_STATIC);
+}
+
+void
+sppp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
+{
+       if (req == RTM_PROPOSAL) {
+               KERNEL_LOCK();
+               sppp_update_dns(ifp);
+               KERNEL_UNLOCK();
+               return;
+       }
+
+       p2p_rtrequest(ifp, req, rt);
+}

Reply via email to