summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkrw <krw@openbsd.org>2017-03-02 17:09:21 +0000
committerkrw <krw@openbsd.org>2017-03-02 17:09:21 +0000
commit46c62a11c36c34beb2d403777db75ed08acd9022 (patch)
tree6aa06affaea28162af8970ce25f884c2f1644156
parentDocument some installation quirks for the EdgeRouter Lite in INSTALL.octeon: (diff)
downloadwireguard-openbsd-46c62a11c36c34beb2d403777db75ed08acd9022.tar.xz
wireguard-openbsd-46c62a11c36c34beb2d403777db75ed08acd9022.zip
Implement a new routing message RTM_PROPOSAL that communicates
information that can be used to configure an interface and related network components. ok bluhm@, ok for various older versions mpi@ florian@ claudio@
-rw-r--r--sbin/route/route.c220
-rw-r--r--sys/net/route.h38
-rw-r--r--sys/net/rtsock.c107
3 files changed, 358 insertions, 7 deletions
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 3a82c0414c0..10fae42ba01 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.196 2017/01/23 00:10:07 krw Exp $ */
+/* $OpenBSD: route.c,v 1.197 2017/03/02 17:09:21 krw Exp $ */
/* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */
/*
@@ -119,6 +119,9 @@ void interfaces(void);
void getlabel(char *);
int gettable(const char *);
int rdomain(int, char **);
+void print_rtdns(struct sockaddr_rtdns *);
+void print_rtstatic(struct sockaddr_rtstatic *);
+void print_rtsearch(struct sockaddr_rtsearch *);
__dead void
usage(char *cp)
@@ -1258,6 +1261,7 @@ char *msgtypes[] = {
"RTM_DESYNC: route socket overflow",
"RTM_INVALIDATE: invalidate cache of L2 route",
"RTM_BFD: bidirectional forwarding detection",
+ "RTM_PROPOSAL: config proposal"
};
char metricnames[] =
@@ -1271,7 +1275,7 @@ char ifnetflags[] =
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC"
"\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST";
char addrnames[] =
-"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC\12SRCMASK\013LABEL";
+"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC\012SRCMASK\013LABEL\014BFD\015DNS\016STATIC\017SEARCH";
const char *
get_linkstate(int mt, int link_state)
@@ -1355,6 +1359,87 @@ print_rtmsg(struct rt_msghdr *rtm, int msglen)
print_bfdmsg(rtm);
break;
#endif
+ case RTM_PROPOSAL:
+ printf(", source ");
+ switch (rtm->rtm_priority) {
+ case RTP_PROPOSAL_STATIC:
+ printf("static");
+ break;
+ case RTP_PROPOSAL_DHCLIENT:
+ printf("dhcp");
+ break;
+ case RTP_PROPOSAL_SLAAC:
+ printf("slaac");
+ break;
+ default:
+ printf("unknown");
+ break;
+ }
+ printf(" table %u, ifidx %u, ",
+ rtm->rtm_tableid, rtm->rtm_index);
+ printf("pid: %ld, seq %d, errno %d\nflags:",
+ (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
+ bprintf(stdout, rtm->rtm_flags, routeflags);
+ printf("\nfmask:");
+ bprintf(stdout, rtm->rtm_fmask, routeflags);
+ if (verbose) {
+#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
+ relative_expire = rtm->rtm_rmx.rmx_expire ?
+ rtm->rtm_rmx.rmx_expire - time(NULL) : 0;
+ printf("\nuse: %8llu mtu: %8u%c expire: %8lld%c",
+ rtm->rtm_rmx.rmx_pksent,
+ rtm->rtm_rmx.rmx_mtu, lock(MTU),
+ relative_expire, lock(EXPIRE));
+#undef lock
+ }
+ printf("\nlocks: ");
+ bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
+ printf(" inits: ");
+ bprintf(stdout, rtm->rtm_inits, metricnames);
+ pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen),
+ rtm->rtm_addrs & ~(RTA_STATIC | RTA_SEARCH | RTA_DNS));
+ printf("Static Routes:\n");
+ if (rtm->rtm_addrs & RTA_STATIC) {
+ char *next = (char *)rtm + rtm->rtm_hdrlen;
+ struct sockaddr *sa, *rti_info[RTAX_MAX];
+ struct sockaddr_rtstatic *rtstatic;
+ sa = (struct sockaddr *)next;
+ get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
+ rtstatic = (struct sockaddr_rtstatic *)
+ rti_info[RTAX_STATIC];
+ if (rtstatic != NULL) {
+ printf(" ");
+ print_rtstatic(rtstatic);
+ }
+ }
+ printf("Domain search:\n");
+ if (rtm->rtm_addrs & RTA_SEARCH) {
+ char *next = (char *)rtm + rtm->rtm_hdrlen;
+ struct sockaddr *sa, *rti_info[RTAX_MAX];
+ struct sockaddr_rtsearch *rtsearch;
+ sa = (struct sockaddr *)next;
+ get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
+ rtsearch = (struct sockaddr_rtsearch *)
+ rti_info[RTAX_SEARCH];
+ if (rtsearch != NULL) {
+ printf(" ");
+ print_rtsearch(rtsearch);
+ }
+ }
+ printf("Domain Name Servers:\n");
+ if (rtm->rtm_addrs & RTA_DNS) {
+ char *next = (char *)rtm + rtm->rtm_hdrlen;
+ struct sockaddr *sa, *rti_info[RTAX_MAX];
+ struct sockaddr_rtdns *rtdns;
+ sa = (struct sockaddr *)next;
+ get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
+ rtdns = (struct sockaddr_rtdns *)rti_info[RTAX_DNS];
+ if (rtdns != NULL) {
+ printf(" ");
+ print_rtdns(rtdns);
+ }
+ }
+ break;
default:
printf(", priority %d, table %u, ifidx %u, ",
rtm->rtm_priority, rtm->rtm_tableid, rtm->rtm_index);
@@ -1918,3 +2003,134 @@ rdomain(int argc, char **argv)
warn("%s", argv[0]);
return (errno == ENOENT ? 127 : 126);
}
+
+/*
+ * Print RTM_PROPOSAL DNS server addresses.
+ */
+void
+print_rtdns(struct sockaddr_rtdns *rtdns)
+{
+ struct in_addr server;
+ char *src = rtdns->sr_dns;
+ size_t srclen, offset;
+ unsigned int servercnt;
+ int i;
+
+ offset = offsetof(struct sockaddr_rtdns, sr_dns);
+ if (rtdns->sr_len <= offset) {
+ printf("<invalid sr_len (%d <= %zu)>\n", rtdns->sr_len,
+ offset);
+ return;
+ }
+ srclen = rtdns->sr_len - offset;
+ if (srclen > sizeof(rtdns->sr_dns)) {
+ printf("<invalid sr_len (%zu > %zu)>\n", srclen,
+ sizeof(rtdns->sr_dns));
+ return;
+ }
+
+ switch (rtdns->sr_family) {
+ case AF_INET:
+ /* An array of IPv4 addresses. */
+ servercnt = srclen / sizeof(struct in_addr);
+ if (servercnt * sizeof(struct in_addr) != srclen) {
+ printf("<invalid server count>\n");
+ return;
+ }
+ for (i = 0; i < servercnt; i++) {
+ memcpy(&server.s_addr, src, sizeof(server.s_addr));
+ printf("%s ", inet_ntoa(server));
+ src += sizeof(struct in_addr);
+ }
+ break;
+ case AF_INET6:
+ printf("<AF_INET6> printing not yet implemented\n");
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+}
+
+/*
+ * Print RTM_PROPOSAL static routes.
+ */
+void
+print_rtstatic(struct sockaddr_rtstatic *rtstatic)
+{
+ struct in_addr dest, gateway;
+ unsigned char *src = rtstatic->sr_static;
+ size_t srclen, offset;
+ int bits, bytes;
+ char ntoabuf[INET_ADDRSTRLEN];
+
+ offset = offsetof(struct sockaddr_rtstatic, sr_static);
+ if (rtstatic->sr_len <= offset) {
+ printf("<invalid sr_len (%d <= %zu)>\n", rtstatic->sr_len,
+ offset);
+ return;
+ }
+ srclen = rtstatic->sr_len - offset;
+ if (srclen > sizeof(rtstatic->sr_static)) {
+ printf("<invalid sr_len (%zu > %zu)>\n", srclen,
+ sizeof(rtstatic->sr_static));
+ return;
+ }
+
+ switch (rtstatic->sr_family) {
+ case AF_INET:
+ /* AF_INET -> RFC 3442 encoded static routes. */
+ while (srclen) {
+ bits = *src;
+ src++;
+ srclen--;
+ bytes = (bits + 7) / 8;
+ if (srclen < bytes || bytes > sizeof(dest.s_addr))
+ break;
+ memset(&dest, 0, sizeof(dest));
+ memcpy(&dest.s_addr, src, bytes);
+ src += bytes;
+ srclen -= bytes;
+ strlcpy(ntoabuf, inet_ntoa(dest), sizeof(ntoabuf));
+ if (srclen < sizeof(gateway.s_addr))
+ break;
+ memcpy(&gateway.s_addr, src, sizeof(gateway.s_addr));
+ src += sizeof(gateway.s_addr);
+ srclen -= sizeof(gateway.s_addr);
+ printf("%s/%u %s ", ntoabuf, bits, inet_ntoa(gateway));
+ }
+ break;
+ case AF_INET6:
+ printf("<AF_INET6 printing not yet implemented>");
+ break;
+ default:
+ printf("<unknown address family %d>", rtstatic->sr_family);
+ break;
+ }
+ printf("\n");
+}
+
+/*
+ * Print RTM_PROPOSAL domain search list.
+ */
+void
+print_rtsearch(struct sockaddr_rtsearch *rtsearch)
+{
+ char *src = rtsearch->sr_search;
+ size_t srclen, offset;
+
+ offset = offsetof(struct sockaddr_rtsearch, sr_search);
+ if (rtsearch->sr_len <= offset) {
+ printf("<invalid sr_len (%d <= %zu)>\n", rtsearch->sr_len,
+ offset);
+ return;
+ }
+ srclen = rtsearch->sr_len - offset;
+ if (srclen > sizeof(rtsearch->sr_search)) {
+ printf("<invalid sr_len (%zu > %zu)>\n", srclen,
+ sizeof(rtsearch->sr_search));
+ return;
+ }
+
+ printf("%*s\n", (int)srclen, src);
+}
diff --git a/sys/net/route.h b/sys/net/route.h
index 8e5ee2d7ba2..a67f3af27a5 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.h,v 1.156 2017/01/23 00:59:22 krw Exp $ */
+/* $OpenBSD: route.h,v 1.157 2017/03/02 17:09:21 krw Exp $ */
/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */
/*
@@ -168,6 +168,9 @@ struct rtentry {
#define RTP_RIP 40 /* RIP routes */
#define RTP_BGP 48 /* BGP routes */
#define RTP_DEFAULT 56 /* routes that have nothing set */
+#define RTP_PROPOSAL_STATIC 57
+#define RTP_PROPOSAL_DHCLIENT 58
+#define RTP_PROPOSAL_SLAAC 59
#define RTP_MAX 63 /* maximum priority */
#define RTP_ANY 64 /* any of the above */
#define RTP_MASK 0x7f
@@ -237,6 +240,7 @@ struct rt_msghdr {
#define RTM_DESYNC 0x10 /* route socket buffer overflow */
#define RTM_INVALIDATE 0x11 /* Invalidate cache of L2 route */
#define RTM_BFD 0x12 /* bidirectional forwarding detection */
+#define RTM_PROPOSAL 0x13 /* proposal for netconfigd */
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
@@ -262,6 +266,9 @@ struct rt_msghdr {
#define RTA_SRCMASK 0x200 /* source netmask present */
#define RTA_LABEL 0x400 /* route label present */
#define RTA_BFD 0x800 /* bfd present */
+#define RTA_DNS 0x1000 /* DNS Servers sockaddr present */
+#define RTA_STATIC 0x2000 /* RFC 3442 encoded static routes present */
+#define RTA_SEARCH 0x4000 /* RFC 3397 encoded search path present */
/*
* Index offsets for sockaddr array for alternate internal encoding.
@@ -278,7 +285,10 @@ struct rt_msghdr {
#define RTAX_SRCMASK 9 /* source netmask present */
#define RTAX_LABEL 10 /* route label present */
#define RTAX_BFD 11 /* bfd present */
-#define RTAX_MAX 12 /* size of array to allocate */
+#define RTAX_DNS 12 /* DNS Server(s) sockaddr present */
+#define RTAX_STATIC 13 /* RFC 3442 encoded static routes present */
+#define RTAX_SEARCH 14 /* RFC 3397 encoded search path present */
+#define RTAX_MAX 15 /* size of array to allocate */
/*
* setsockopt defines used for the filtering.
@@ -299,6 +309,30 @@ struct sockaddr_rtlabel {
char sr_label[RTLABEL_LEN];
};
+#define RTDNS_LEN 128
+
+struct sockaddr_rtdns {
+ u_int8_t sr_len; /* total length */
+ sa_family_t sr_family; /* address family */
+ char sr_dns[RTDNS_LEN];
+};
+
+#define RTSTATIC_LEN 128
+
+struct sockaddr_rtstatic {
+ u_int8_t sr_len; /* total length */
+ sa_family_t sr_family; /* address family */
+ char sr_static[RTSTATIC_LEN];
+};
+
+#define RTSEARCH_LEN 128
+
+struct sockaddr_rtsearch {
+ u_int8_t sr_len; /* total length */
+ sa_family_t sr_family; /* address family */
+ char sr_search[RTSEARCH_LEN];
+};
+
/*
* A route consists of a destination address and a reference
* to a routing entry. These are often held by protocols
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 89c6a0bef0d..27338b49e35 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.225 2017/03/02 09:37:04 mpi Exp $ */
+/* $OpenBSD: rtsock.c,v 1.226 2017/03/02 17:09:21 krw Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -108,10 +108,14 @@ int rt_msg2(int, int, struct rt_addrinfo *, caddr_t,
struct walkarg *);
void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
+void rt_proposalmsg(struct rt_msghdr *, struct rt_addrinfo *);
+
int sysctl_iflist(int, struct walkarg *);
int sysctl_ifnames(struct walkarg *);
int sysctl_rtable_rtstat(void *, size_t *, void *);
+int validate_proposal(struct rt_addrinfo *);
+
struct routecb {
struct rawcb rcb;
struct timeout timeout;
@@ -597,6 +601,7 @@ route_output(struct mbuf *m, ...)
case RTM_GET:
case RTM_CHANGE:
case RTM_LOCK:
+ case RTM_PROPOSAL:
break;
default:
error = EOPNOTSUPP;
@@ -652,11 +657,12 @@ route_output(struct mbuf *m, ...)
info.rti_addrs = rtm->rtm_addrs;
rt_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm, len + (caddr_t)rtm, &info);
info.rti_flags = rtm->rtm_flags;
- if (info.rti_info[RTAX_DST] == NULL ||
+ if (rtm->rtm_type != RTM_PROPOSAL &&
+ (info.rti_info[RTAX_DST] == NULL ||
info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX) ||
- info.rti_info[RTAX_GENMASK] != NULL) {
+ info.rti_info[RTAX_GENMASK] != NULL)) {
error = EINVAL;
goto fail;
}
@@ -675,6 +681,18 @@ route_output(struct mbuf *m, ...)
* may be not consistent and could cause unexpected behaviour in other
* userland clients. Use goto fail instead.
*/
+
+ /*
+ * Validate RTM_PROPOSAL and pass it along or error out.
+ */
+ if (rtm->rtm_type == RTM_PROPOSAL) {
+ if (validate_proposal(&info) == -1) {
+ error = EINVAL;
+ goto fail;
+ }
+ goto flush;
+ }
+
switch (rtm->rtm_type) {
case RTM_ADD:
if (info.rti_info[RTAX_GATEWAY] == NULL) {
@@ -1642,6 +1660,89 @@ sysctl_rtable_rtstat(void *oldp, size_t *oldlenp, void *newp)
return (sysctl_rdstruct(oldp, oldlenp, newp, &rtstat, sizeof(rtstat)));
}
+int
+validate_proposal(struct rt_addrinfo *info)
+{
+ if (info->rti_addrs & ~(RTA_NETMASK | RTA_IFA | RTA_DNS | RTA_STATIC |
+ RTA_SEARCH)) {
+ return -1;
+ }
+
+ if (ISSET(info->rti_addrs, RTA_NETMASK)) {
+ struct sockaddr *sa = info->rti_info[RTAX_NETMASK];
+ if (sa == NULL)
+ return -1;
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (sa->sa_len != sizeof(struct sockaddr_in))
+ return -1;
+ break;
+ case AF_INET6:
+ if (sa->sa_len != sizeof(struct sockaddr_in6))
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ if (ISSET(info->rti_addrs, RTA_IFA)) {
+ struct sockaddr *sa = info->rti_info[RTAX_IFA];
+ if (sa == NULL)
+ return -1;
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (sa->sa_len != sizeof(struct sockaddr_in))
+ return -1;
+ break;
+ case AF_INET6:
+ if (sa->sa_len != sizeof(struct sockaddr_in6))
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ if (ISSET(info->rti_addrs, RTA_DNS)) {
+ struct sockaddr_rtdns *rtdns =
+ (struct sockaddr_rtdns *)info->rti_info[RTAX_DNS];
+ if (rtdns == NULL)
+ return -1;
+ if (rtdns->sr_len > sizeof(*rtdns))
+ return -1;
+ if (rtdns->sr_len <=
+ offsetof(struct sockaddr_rtdns, sr_dns))
+ return -1;
+ }
+
+ if (ISSET(info->rti_addrs, RTA_STATIC)) {
+ struct sockaddr_rtstatic *rtstatic =
+ (struct sockaddr_rtstatic *)info->rti_info[RTAX_STATIC];
+ if (rtstatic == NULL)
+ return -1;
+ if (rtstatic->sr_len > sizeof(*rtstatic))
+ return -1;
+ if (rtstatic->sr_len <=
+ offsetof(struct sockaddr_rtstatic, sr_static))
+ return -1;
+ }
+
+ if (ISSET(info->rti_addrs, RTA_SEARCH)) {
+ struct sockaddr_rtsearch *rtsearch =
+ (struct sockaddr_rtsearch *)info->rti_info[RTAX_SEARCH];
+ if (rtsearch == NULL)
+ return -1;
+ if (rtsearch->sr_len > sizeof(*rtsearch))
+ return -1;
+ if (rtsearch->sr_len <=
+ offsetof(struct sockaddr_rtsearch, sr_search))
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* Definitions of protocols supported in the ROUTE domain.
*/