Module Name: src
Committed By: roy
Date: Sat Feb 8 14:17:30 UTC 2020
Modified Files:
src/share/man/man4: route.4
src/sys/net: route.h rtsock_shared.c
Log Message:
route(4): add RO_MISSFILTER socket option
This allows filtering of specific RTM_MISS destination sockaddrs.
To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/share/man/man4/route.4
cvs rdiff -u -r1.125 -r1.126 src/sys/net/route.h
cvs rdiff -u -r1.12 -r1.13 src/sys/net/rtsock_shared.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/share/man/man4/route.4
diff -u src/share/man/man4/route.4:1.32 src/share/man/man4/route.4:1.33
--- src/share/man/man4/route.4:1.32 Sun Jul 1 22:27:43 2018
+++ src/share/man/man4/route.4 Sat Feb 8 14:17:30 2020
@@ -1,4 +1,4 @@
-.\" $NetBSD: route.4,v 1.32 2018/07/01 22:27:43 christos Exp $
+.\" $NetBSD: route.4,v 1.33 2020/02/08 14:17:30 roy Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" @(#)route.4 8.6 (Berkeley) 4/19/94
.\"
-.Dd July 11, 2018
+.Dd February 4, 2020
.Dt ROUTE 4
.Os
.Sh NAME
@@ -191,6 +191,35 @@ if (setsockopt(routefd, PF_ROUTE, RO_MSG
err(1, "setsockopt(RO_MSGFILTER)");
.Ed
.Pp
+A process can specify which RTM_MISS destination addresses it's interested in
+by passing an array of struct sockaddr to the
+.Xr setsockopt 2
+call with the
+.Dv RO_MISSFILTER
+option at the
+.Dv PF_ROUTE
+level.
+For example, to only get RTM_MISS messages for specific destinations:
+.Bd -literal -offset indent
+char buf[1024] = { '\\0' }, *cp = buf;
+struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_len = sizeof(sin),
+};
+
+inet_aton("192.168.0.1", &sin.sin_addr);
+memcpy(cp, &sin, sin.sin_len);
+cp += RT_ROUNDUP(sin.sin_len);
+
+inet_aton("192.168.0.2", &sin.sin_addr);
+memcpy(cp, &sin, sin.sin_len);
+cp += RT_ROUNDUP(sin.sin_len);
+
+if (setsockopt(routefd, PF_ROUTE, RO_MISSFILTER,
+ &sin, (socklen_t)(cp - buf)) == -1)
+ err(1, "setsockopt(RO_MISSFILTER)");
+.Ed
+.Pp
If a route is in use when it is deleted,
the routing entry will be marked down and removed from the routing table,
but the resources associated with it will not
Index: src/sys/net/route.h
diff -u src/sys/net/route.h:1.125 src/sys/net/route.h:1.126
--- src/sys/net/route.h:1.125 Thu Sep 19 04:08:29 2019
+++ src/sys/net/route.h Sat Feb 8 14:17:30 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: route.h,v 1.125 2019/09/19 04:08:29 ozaki-r Exp $ */
+/* $NetBSD: route.h,v 1.126 2020/02/08 14:17:30 roy Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -270,6 +270,9 @@ struct rt_msghdr {
* setsockopt defines used for the filtering.
*/
#define RO_MSGFILTER 1 /* array of which rtm_type to send to client */
+#define RO_MISSFILTER 2 /* array of sockaddrs to match miss dst */
+
+#define RO_FILTSA_MAX 30 /* maximum number of sockaddrs per filter */
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
Index: src/sys/net/rtsock_shared.c
diff -u src/sys/net/rtsock_shared.c:1.12 src/sys/net/rtsock_shared.c:1.13
--- src/sys/net/rtsock_shared.c:1.12 Wed Jan 29 04:35:13 2020
+++ src/sys/net/rtsock_shared.c Sat Feb 8 14:17:30 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: rtsock_shared.c,v 1.12 2020/01/29 04:35:13 thorpej Exp $ */
+/* $NetBSD: rtsock_shared.c,v 1.13 2020/02/08 14:17:30 roy Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtsock_shared.c,v 1.12 2020/01/29 04:35:13 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtsock_shared.c,v 1.13 2020/02/08 14:17:30 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -169,6 +169,8 @@ struct routecb {
struct rawcb rocb_rcb;
unsigned int rocb_msgfilter;
#define RTMSGFILTER(m) (1U << (m))
+ char *rocb_missfilter;
+ size_t rocb_missfilterlen;
};
#define sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
@@ -218,7 +220,7 @@ COMPATNAME(route_filter)(struct mbuf *m,
return ENOPROTOOPT;
/* If no filter set, just return. */
- if (rop->rocb_msgfilter == 0)
+ if (rop->rocb_msgfilter == 0 && rop->rocb_missfilterlen == 0)
return 0;
/* Ensure we can access rtm_type */
@@ -230,9 +232,27 @@ COMPATNAME(route_filter)(struct mbuf *m,
if (rtm->rtm_type >= sizeof(rop->rocb_msgfilter) * CHAR_BIT)
return EINVAL;
/* If the rtm type is filtered out, return a positive. */
- if (!(rop->rocb_msgfilter & RTMSGFILTER(rtm->rtm_type)))
+ if (rop->rocb_msgfilter != 0 &&
+ !(rop->rocb_msgfilter & RTMSGFILTER(rtm->rtm_type)))
return EEXIST;
+ if (rop->rocb_missfilterlen != 0 && rtm->rtm_type == RTM_MISS) {
+ __CTASSERT(RTA_DST == 1);
+ struct sockaddr *sa, *dst = (struct sockaddr *)(rtm + 1);
+ char *cp = rop->rocb_missfilter;
+ char *ep = cp + rop->rocb_missfilterlen;
+
+ while (cp < ep) {
+ sa = (struct sockaddr *)cp;
+ if (sa->sa_len == dst->sa_len &&
+ memcmp(sa, dst, sa->sa_len) == 0)
+ break;
+ cp += RT_XROUNDUP(sa->sa_len);
+ }
+ if (cp == ep)
+ return EEXIST;
+ }
+
/* Passed the filter. */
return 0;
}
@@ -291,12 +311,15 @@ static void
COMPATNAME(route_detach)(struct socket *so)
{
struct rawcb *rp = sotorawcb(so);
+ struct routecb *rop = (struct routecb *)rp;
int s;
KASSERT(rp != NULL);
KASSERT(solocked(so));
s = splsoftnet();
+ if (rop->rocb_missfilterlen != 0)
+ kmem_free(rop->rocb_missfilter, rop->rocb_missfilterlen);
rt_adjustcount(rp->rcb_proto.sp_protocol, -1);
raw_detach(so);
splx(s);
@@ -980,9 +1003,10 @@ route_ctloutput(int op, struct socket *s
{
struct routecb *rop = sotoroutecb(so);
int error = 0;
- unsigned char *rtm_type;
+ unsigned char *rtm_type, *cp, *ep;
size_t len;
unsigned int msgfilter;
+ struct sockaddr *sa;
KASSERT(solocked(so));
@@ -1007,6 +1031,46 @@ route_ctloutput(int op, struct socket *s
if (error == 0)
rop->rocb_msgfilter = msgfilter;
break;
+ case RO_MISSFILTER:
+ /* Validate the data */
+ len = 0;
+ cp = sopt->sopt_data;
+ ep = cp + sopt->sopt_size;
+ while (cp < ep) {
+ if (ep - cp <
+ offsetof(struct sockaddr, sa_len) +
+ sizeof(sa->sa_len))
+ break;
+ if (++len > RO_FILTSA_MAX) {
+ error = ENOBUFS;
+ break;
+ }
+ sa = (struct sockaddr *)cp;
+ cp += RT_XROUNDUP(sa->sa_len);
+ }
+ if (cp != ep) {
+ if (error == 0)
+ error = EINVAL;
+ break;
+ }
+ if (rop->rocb_missfilterlen != 0)
+ kmem_free(rop->rocb_missfilter,
+ rop->rocb_missfilterlen);
+ if (sopt->sopt_size != 0) {
+ rop->rocb_missfilter =
+ kmem_alloc(sopt->sopt_size, KM_SLEEP);
+ if (rop->rocb_missfilter == NULL) {
+ rop->rocb_missfilterlen = 0;
+ error = ENOBUFS;
+ break;
+ }
+ } else
+ rop->rocb_missfilter = NULL;
+ rop->rocb_missfilterlen = sopt->sopt_size;
+ if (rop->rocb_missfilterlen != 0)
+ memcpy(rop->rocb_missfilter, sopt->sopt_data,
+ rop->rocb_missfilterlen);
+ break;
default:
error = ENOPROTOOPT;
break;