From 70c459ce27112ccc74336c383f102427e557effe Mon Sep 17 00:00:00 2001 From: benno Date: Wed, 4 Aug 2021 18:17:23 +0000 Subject: [PATCH] Add a new 'nameserver' command to route(8). It sends nameserver proposals to resolvd(8) using the dns proposal protocol over the route socket. Based on a seperate program written by florian@. deraadt noticed some whitespace issues. more fixes and ok florian@ --- sbin/route/keywords.h | 5 +- sbin/route/keywords.sh | 3 +- sbin/route/route.8 | 27 +++++++- sbin/route/route.c | 146 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 174 insertions(+), 7 deletions(-) diff --git a/sbin/route/keywords.h b/sbin/route/keywords.h index 0fd50932596..eb2901f9e21 100644 --- a/sbin/route/keywords.h +++ b/sbin/route/keywords.h @@ -1,4 +1,4 @@ -/* $OpenBSD: keywords.h,v 1.35 2020/10/29 21:15:26 denis Exp $ */ +/* $OpenBSD: keywords.h,v 1.36 2021/08/04 18:17:23 benno Exp $ */ /* WARNING! This file was generated by keywords.sh */ @@ -45,6 +45,7 @@ enum { K_MPLS, K_MPLSLABEL, K_MTU, + K_NAMESERVER, K_NET, K_NETMASK, K_NOBFD, @@ -109,6 +110,7 @@ struct keytab keywords[] = { { "mpls", K_MPLS }, { "mplslabel", K_MPLSLABEL }, { "mtu", K_MTU }, + { "nameserver", K_NAMESERVER }, { "net", K_NET }, { "netmask", K_NETMASK }, { "nobfd", K_NOBFD }, @@ -135,4 +137,3 @@ struct keytab keywords[] = { { "static", K_STATIC }, { "swap", K_SWAP }, }; - diff --git a/sbin/route/keywords.sh b/sbin/route/keywords.sh index 369f1b08aaa..6f9f5a21e4d 100644 --- a/sbin/route/keywords.sh +++ b/sbin/route/keywords.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: keywords.sh,v 1.33 2020/10/29 21:15:26 denis Exp $ +# $OpenBSD: keywords.sh,v 1.34 2021/08/04 18:17:23 benno Exp $ # $NetBSD: keywords.sh,v 1.2 1996/11/15 18:57:21 gwr Exp $ # @(#)keywords 8.2 (Berkeley) 3/19/94 # @@ -46,6 +46,7 @@ mpath mpls mplslabel mtu +nameserver net netmask nobfd diff --git a/sbin/route/route.8 b/sbin/route/route.8 index 83e48ec883d..3624e4eaf18 100644 --- a/sbin/route/route.8 +++ b/sbin/route/route.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: route.8,v 1.95 2021/01/02 15:35:24 schwarze Exp $ +.\" $OpenBSD: route.8,v 1.96 2021/08/04 18:17:23 benno Exp $ .\" $NetBSD: route.8,v 1.6 1995/03/18 15:00:13 cgd Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)route.8 8.3 (Berkeley) 3/19/94 .\" -.Dd $Mdocdate: January 2 2021 $ +.Dd $Mdocdate: August 4 2021 $ .Dt ROUTE 8 .Os .Sh NAME @@ -215,7 +215,6 @@ priority are shown. .Fl ifp .Ar interface .Xc -.Pp Set the preferred source address. If .Ar address @@ -237,6 +236,26 @@ destination is on-link source address is assigned to a disabled interface .El .El +.Bl -tag -width Fl -compact +.It Xo +.Ic route +.Op Fl dtv +.Op Fl T Ar rtable +.Tg +.Cm nameserver +.Op Ar address +.Op Ar ... +.Xc +Send a list of up to five nameserver addresses proposals to +.Xr resolvd 8 . +.Xr resolvd 8 +will react upon this request by writing the nameservers to +.Pa /etc/resolv.conf . +If no +.Ar address +argument is given, a request to remove the nameservers previously entered for +the given interface is sent. +.El .Pp .Tg destination .Tg gateway @@ -603,9 +622,11 @@ to create the new entry. .Xr route 4 , .Xr tcp 4 , .Xr hosts 5 , +.Xr resolv.conf 5 , .Xr mygate 5 , .Xr bgpd 8 , .Xr ospfd 8 , +.Xr resolvd 8 , .Xr ripd 8 , .Xr sysctl 8 .Sh HISTORY diff --git a/sbin/route/route.c b/sbin/route/route.c index 8af7c93dc9e..376fb37f74d 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.255 2021/06/26 15:42:58 deraadt Exp $ */ +/* $OpenBSD: route.c,v 1.256 2021/08/04 18:17:23 benno Exp $ */ /* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */ /* @@ -93,6 +93,7 @@ int show(int, char *[]); int keycmp(const void *, const void *); int keyword(char *); void monitor(int, char *[]); +int nameserver(int, char **); int prefixlen(int, char *); void sockaddr(char *, struct sockaddr *); void sodump(sup, char *); @@ -282,6 +283,9 @@ main(int argc, char **argv) case K_MONITOR: monitor(argc, argv); break; + case K_NAMESERVER: + rval = nameserver(argc, argv); + break; default: usage(*argv); /* NOTREACHED */ @@ -1129,6 +1133,146 @@ monitor(int argc, char *argv[]) } } + +int +nameserver(int argc, char *argv[]) +{ + struct rt_msghdr rtm; + struct sockaddr_rtdns rtdns; + struct iovec iov[3]; + struct addrinfo hints, *res; + struct in_addr ns4[5]; + struct in6_addr ns6[5]; + size_t ns4_count = 0, ns6_count = 0; + long pad = 0; + unsigned int if_index; + int error = 0, iovcnt = 0, padlen, i; + char *if_name, buf[INET6_ADDRSTRLEN]; + + + argc--; + argv++; + if (argc == 0) + usage(NULL); + + if_name = *argv; + argc--; + argv++; + + if ((if_index = if_nametoindex(if_name)) == 0) + errx(1, "unknown interface: %s", if_name); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + + for (; argc > 0; argc--, argv++) { + error = getaddrinfo(*argv, NULL, &hints, &res); + if (error) { + errx(1, "%s", gai_strerror(error)); + } + if (res == NULL) { + errx(1, "%s: unknown", *argv); + } + + switch (res->ai_addr->sa_family) { + case AF_INET: + if (ns4_count >= nitems(ns4)) { + warnx("ignoring superflous nameserver: %s", + *argv); + break; + } + memcpy(&ns4[ns4_count++], + &((struct sockaddr_in *)res->ai_addr)->sin_addr, + sizeof(struct in_addr)); + break; + case AF_INET6: + if (ns6_count >= nitems(ns6)) { + warnx("ignoring superflous nameserver: %s", + *argv); + break; + } + memcpy(&ns6[ns6_count++], + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + sizeof(struct in6_addr)); + break; + default: + errx(1, "unknown address family"); + } + freeaddrinfo(res); + } + + if (argc > 0) + warnx("ignoring additional nameservers"); + + if (verbose) { + for (i = 0; i < ns4_count; i++) + warnx("v4: %s", inet_ntop(AF_INET, &ns4[i], buf, + sizeof(buf))); + for (i = 0; i < ns6_count; i++) + warnx("v6: %s", inet_ntop(AF_INET6, &ns6[i], buf, + sizeof(buf))); + } + + memset(&rtm, 0, sizeof(rtm)); + + rtm.rtm_version = RTM_VERSION; + rtm.rtm_type = RTM_PROPOSAL; + rtm.rtm_msglen = sizeof(rtm); + rtm.rtm_tableid = tableid; + rtm.rtm_index = if_index; + rtm.rtm_seq = 1; + rtm.rtm_priority = RTP_PROPOSAL_STATIC; + rtm.rtm_addrs = RTA_DNS; + rtm.rtm_flags = RTF_UP; + + iov[iovcnt].iov_base = &rtm; + iov[iovcnt++].iov_len = sizeof(rtm); + + iov[iovcnt].iov_base = &rtdns; + iov[iovcnt++].iov_len = sizeof(rtdns); + rtm.rtm_msglen += sizeof(rtdns); + + padlen = ROUNDUP(sizeof(rtdns)) - sizeof(rtdns); + if (padlen > 0) { + iov[iovcnt].iov_base = &pad; + iov[iovcnt++].iov_len = padlen; + rtm.rtm_msglen += padlen; + } + + memset(&rtdns, 0, sizeof(rtdns)); + rtdns.sr_family = AF_INET; + rtdns.sr_len = 2 + ns4_count * sizeof(struct in_addr); + memcpy(rtdns.sr_dns, ns4, rtdns.sr_len - 2); + + if (debugonly) + return (0); + + if (writev(s, iov, iovcnt) == -1) { + warn("failed to send route message"); + error = 1; + } + + rtm.rtm_seq++; + + memset(&rtdns, 0, sizeof(rtdns)); + rtdns.sr_family = AF_INET6; + rtdns.sr_len = 2 + ns6_count * sizeof(struct in6_addr); + memcpy(rtdns.sr_dns, ns6, rtdns.sr_len - 2); + + if (writev(s, iov, iovcnt) == -1) { + warn("failed to send route message"); + error = 1; + } + + return (error); +} + struct { struct rt_msghdr m_rtm; char m_space[512]; -- 2.20.1