summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjorn Ketelaars <bket@cvs.openbsd.org>2021-11-10 15:04:27 +0000
committerBjorn Ketelaars <bket@cvs.openbsd.org>2021-11-10 15:04:27 +0000
commit7ec38a64f68a733ee7ea09861b08abe2b8fbee4a (patch)
treefa47222edfdd053cd64a22d699df7f57334cad8c
parent705ed96a44379cb8efed618324f04e8941641588 (diff)
sppp(4) - support PPP IPCP extensions for DNS
RFC 1877 extends the family of network control protocols for establishing and configuring the IPCP over PPP, defining the negotiation of primary and secondary DNS addresses. After negotiation, rtm_proposal() is used to send out DNS updates. Feedback from claudio@ and kn@. OK claudio@, kn@
-rw-r--r--share/man/man4/sppp.411
-rw-r--r--sys/net/if_sppp.h4
-rw-r--r--sys/net/if_spppsubr.c111
3 files changed, 115 insertions, 11 deletions
diff --git a/share/man/man4/sppp.4 b/share/man/man4/sppp.4
index 5ca10285953..1f55986af79 100644
--- a/share/man/man4/sppp.4
+++ b/share/man/man4/sppp.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sppp.4,v 1.25 2021/11/08 15:33:36 kn Exp $
+.\" $OpenBSD: sppp.4,v 1.26 2021/11/10 15:04:26 bket Exp $
.\"
.\" Copyright (c) 1997 Joerg Wunsch
.\"
@@ -25,7 +25,7 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\"
-.Dd $Mdocdate: November 8 2021 $
+.Dd $Mdocdate: November 10 2021 $
.Dt SPPP 4
.Os
.Sh NAME
@@ -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 a/sys/net/if_sppp.h b/sys/net/if_sppp.h
index ff559fcc369..6b5e7d41a4a 100644
--- a/sys/net/if_sppp.h
+++ b/sys/net/if_sppp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sppp.h,v 1.28 2021/03/10 10:21:48 jsg Exp $ */
+/* $OpenBSD: if_sppp.h,v 1.29 2021/11/10 15:04:26 bket Exp $ */
/* $NetBSD: if_sppp.h,v 1.2.2.1 1999/04/04 06:57:39 explorer Exp $ */
/*
@@ -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 a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index ac1dc9a709d..0d30ac99bfd 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_spppsubr.c,v 1.187 2020/09/12 13:44:38 kn Exp $ */
+/* $OpenBSD: if_spppsubr.c,v 1.188 2021/11/10 15:04:26 bket Exp $ */
/*
* Synchronous PPP link level subroutines.
*
@@ -132,6 +132,15 @@
#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 */
+
+/* bitmask value to enable or disable individual IPCP options */
+#define SPPP_IPCP_OPT_ADDRESSES 1
+#define SPPP_IPCP_OPT_COMPRESSION 2
+#define SPPP_IPCP_OPT_ADDRESS 3
+#define SPPP_IPCP_OPT_PRIMDNS 4
+#define SPPP_IPCP_OPT_SECDNS 5
#define IPV6CP_OPT_IFID 1 /* interface identifier */
#define IPV6CP_OPT_COMPRESSION 2 /* IPv6 compression protocol */
@@ -338,6 +347,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 +712,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 +2524,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 +2577,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 +2602,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]));
+ 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]));
+ break;
}
}
if (debug)
@@ -2612,6 +2640,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 +2663,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 +2673,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 +2696,12 @@ 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;
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;
+ 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;
+ memcpy(&opt[i], &sp->ipcp.dns[1].s_addr,
+ sizeof(sp->ipcp.dns[1]));
+ i += sizeof(sp->ipcp.dns[1]);
+ }
+
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]);
+ 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);
+}