On Wed, Nov 10, 2021 at 07:35:26AM +0100, Bjorn Ketelaars wrote:
> 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 */
Instead of repeating the /* bitmask value */ just add a comment at the
top. Something like "bitmask value to enable or disable individual IPCP
options"
>
> #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;
I would just use sizeof(sp->ipcp.dns[0]) and also put that sizeof in the
two places instead of using the local sz variable.
memcpy(&opt[i], &sp->ipcp.dns[0].s_addr,
sizeof(sp->ipcp.dns[0]));
i += sizeof(sp->ipcp.dns[0]);
> + }
> +
> + 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;
Same as above.
> + }
> +
> 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);
Use sizeof(sp->ipcp.dns[0])
> + 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);
> +}
>
I can't really test this but apart from the above cleanups ok claudio@
--
:wq Claudio