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);
+}