Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add RO_MSGFILTER socket option to PF_ROUTE to filter out
details: https://anonhg.NetBSD.org/src/rev/a591135ccc74
branches: trunk
changeset: 352811:a591135ccc74
user: roy <roy%NetBSD.org@localhost>
date: Tue Apr 11 13:55:54 2017 +0000
description:
Add RO_MSGFILTER socket option to PF_ROUTE to filter out
un-wanted route(4) messages.
Inspired by the ROUTE_MSGFILTER equivalent in OpenBSD,
but with an API which allows the full range of potential message types.
diffstat:
share/man/man4/route.4 | 21 ++++++++-
sys/net/raw_cb.h | 4 +-
sys/net/raw_usrreq.c | 7 ++-
sys/net/route.h | 7 ++-
sys/net/rtsock.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++--
5 files changed, 132 insertions(+), 11 deletions(-)
diffs (272 lines):
diff -r a2446ceccd9d -r a591135ccc74 share/man/man4/route.4
--- a/share/man/man4/route.4 Tue Apr 11 11:32:51 2017 +0000
+++ b/share/man/man4/route.4 Tue Apr 11 13:55:54 2017 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: route.4,v 1.28 2016/09/21 10:50:23 roy Exp $
+.\" $NetBSD: route.4,v 1.29 2017/04/11 13:55:54 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 September 15, 2016
+.Dd March 5, 2017
.Dt ROUTE 4
.Os
.Sh NAME
@@ -174,6 +174,23 @@
.Xr shutdown 2
system call for further input.
.Pp
+A process can specify which route message types it's interested in by passing
+an array of route messsage types to the
+.Xr setsockopt 2
+call with the
+.Dv RO_MSGFILTER
+option at the
+.Dv PF_ROUTE
+level.
+For example, to only get specific messages:
+.Bd -literal -offset indent
+unsigned char rtfilter[] = { RTM_IFINFO, RTM_IFANNOUNCE };
+
+if (setsockopt(routefd, PF_ROUTE, RO_MSGFILTER,
+ &rtfilter, sizeof(rtfilter)) == -1)
+ err(1, "setsockopt(RO_MSGFILTER)");
+.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
diff -r a2446ceccd9d -r a591135ccc74 sys/net/raw_cb.h
--- a/sys/net/raw_cb.h Tue Apr 11 11:32:51 2017 +0000
+++ b/sys/net/raw_cb.h Tue Apr 11 13:55:54 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: raw_cb.h,v 1.26 2016/01/20 21:43:59 riastradh Exp $ */
+/* $NetBSD: raw_cb.h,v 1.27 2017/04/11 13:55:54 roy Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -46,6 +46,8 @@
struct sockaddr *rcb_faddr; /* destination address */
struct sockaddr *rcb_laddr; /* socket's address */
struct sockproto rcb_proto; /* protocol family, protocol */
+ int (*rcb_filter)(struct mbuf *, struct sockproto *,
+ struct rawcb *);
size_t rcb_len;
};
diff -r a2446ceccd9d -r a591135ccc74 sys/net/raw_usrreq.c
--- a/sys/net/raw_usrreq.c Tue Apr 11 11:32:51 2017 +0000
+++ b/sys/net/raw_usrreq.c Tue Apr 11 13:55:54 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: raw_usrreq.c,v 1.55 2016/01/20 21:43:59 riastradh Exp $ */
+/* $NetBSD: raw_usrreq.c,v 1.56 2017/04/11 13:55:54 roy Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.55 2016/01/20 21:43:59 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.56 2017/04/11 13:55:54 roy Exp $");
#include <sys/param.h>
#include <sys/mbuf.h>
@@ -107,6 +107,9 @@
continue;
if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
continue;
+ /* Run any filtering that may have been installed. */
+ if (rp->rcb_filter != NULL && rp->rcb_filter(m, proto, rp) != 0)
+ continue;
if (last != NULL) {
struct mbuf *n;
if ((n = m_copy(m, 0, M_COPYALL)) == NULL)
diff -r a2446ceccd9d -r a591135ccc74 sys/net/route.h
--- a/sys/net/route.h Tue Apr 11 11:32:51 2017 +0000
+++ b/sys/net/route.h Tue Apr 11 13:55:54 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: route.h,v 1.111 2016/12/19 11:17:00 roy Exp $ */
+/* $NetBSD: route.h,v 1.112 2017/04/11 13:55:54 roy Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -250,6 +250,11 @@
#define RTM_DELADDR 0x17 /* address being removed from iface */
#define RTM_CHGADDR 0x18 /* address properties changed */
+/*
+ * setsockopt defines used for the filtering.
+ */
+#define RO_MSGFILTER 1 /* array of which rtm_type to send to client */
+
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
#define RTV_EXPIRE 0x4 /* init or lock _expire */
diff -r a2446ceccd9d -r a591135ccc74 sys/net/rtsock.c
--- a/sys/net/rtsock.c Tue Apr 11 11:32:51 2017 +0000
+++ b/sys/net/rtsock.c Tue Apr 11 13:55:54 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtsock.c,v 1.211 2017/03/24 03:45:02 ozaki-r Exp $ */
+/* $NetBSD: rtsock.c,v 1.212 2017/04/11 13:55:55 roy Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.211 2017/03/24 03:45:02 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.212 2017/04/11 13:55:55 roy Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -177,6 +177,13 @@
static const struct protosw COMPATNAME(route_protosw)[];
+struct routecb {
+ struct rawcb rocb_rcb;
+ unsigned int rocb_msgfilter;
+#define RTMSGFILTER(m) (1U << (m))
+};
+#define sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
+
static void
rt_adjustcount(int af, int cnt)
{
@@ -200,14 +207,49 @@
}
static int
+COMPATNAME(route_filter)(struct mbuf *m, struct sockproto *proto,
+ struct rawcb *rp)
+{
+ struct routecb *rop = (struct routecb *)rp;
+ struct rt_xmsghdr *rtm;
+
+ KASSERT(m != NULL);
+ KASSERT(proto != NULL);
+ KASSERT(rp != NULL);
+
+ /* Wrong family for this socket. */
+ if (proto->sp_family != PF_ROUTE)
+ return ENOPROTOOPT;
+
+ /* If no filter set, just return. */
+ if (rop->rocb_msgfilter == 0)
+ return 0;
+
+ /* Ensure we can access rtm_type */
+ if (m->m_len <
+ offsetof(struct rt_xmsghdr, rtm_type) + sizeof(rtm->rtm_type))
+ return EINVAL;
+
+ rtm = mtod(m, struct rt_xmsghdr *);
+ /* If the rtm type is filtered out, return a positive. */
+ if (!(rop->rocb_msgfilter & RTMSGFILTER(rtm->rtm_type)))
+ return EEXIST;
+
+ /* Passed the filter. */
+ return 0;
+}
+
+static int
COMPATNAME(route_attach)(struct socket *so, int proto)
{
struct rawcb *rp;
+ struct routecb *rop;
int s, error;
KASSERT(sotorawcb(so) == NULL);
- rp = kmem_zalloc(sizeof(*rp), KM_SLEEP);
- rp->rcb_len = sizeof(*rp);
+ rop = kmem_zalloc(sizeof(*rop), KM_SLEEP);
+ rp = &rop->rocb_rcb;
+ rp->rcb_len = sizeof(*rop);
so->so_pcb = rp;
s = splsoftnet();
@@ -215,11 +257,12 @@
rt_adjustcount(rp->rcb_proto.sp_protocol, 1);
rp->rcb_laddr = &COMPATNAME(route_info).ri_src;
rp->rcb_faddr = &COMPATNAME(route_info).ri_dst;
+ rp->rcb_filter = COMPATNAME(route_filter);
}
splx(s);
if (error) {
- kmem_free(rp, sizeof(*rp));
+ kmem_free(rop, sizeof(*rop));
so->so_pcb = NULL;
return error;
}
@@ -981,6 +1024,56 @@
return error;
}
+static int
+route_ctloutput(int op, struct socket *so, struct sockopt *sopt)
+{
+ struct routecb *rop = sotoroutecb(so);
+ int error = 0;
+ unsigned char *rtm_type;
+ size_t len;
+ unsigned int msgfilter;
+
+ KASSERT(solocked(so));
+
+ if (sopt->sopt_level != AF_ROUTE) {
+ error = ENOPROTOOPT;
+ } else switch (op) {
+ case PRCO_SETOPT:
+ switch (sopt->sopt_name) {
+ case RO_MSGFILTER:
+ msgfilter = 0;
+ for (rtm_type = sopt->sopt_data, len = sopt->sopt_size;
+ len != 0;
+ rtm_type++, len -= sizeof(*rtm_type))
+ {
+ /* Guard against overflowing our storage. */
+ if (*rtm_type >= sizeof(msgfilter) * CHAR_BIT) {
+ error = EOVERFLOW;
+ break;
+ }
+ msgfilter |= RTMSGFILTER(*rtm_type);
+ }
+ if (error == 0)
+ rop->rocb_msgfilter = msgfilter;
+ break;
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ break;
+ case PRCO_GETOPT:
+ switch (sopt->sopt_name) {
+ case RO_MSGFILTER:
+ error = ENOTSUP;
+ break;
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ }
+ return error;
+}
+
static void
rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out)
{
@@ -1946,6 +2039,7 @@
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = raw_input,
.pr_ctlinput = raw_ctlinput,
+ .pr_ctloutput = route_ctloutput,
.pr_usrreqs = &route_usrreqs,
.pr_init = raw_init,
},
Home |
Main Index |
Thread Index |
Old Index