Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src route(4): add RO_MISSFILTER socket option
details: https://anonhg.NetBSD.org/src/rev/95bd91799d0d
branches: trunk
changeset: 848765:95bd91799d0d
user: roy <roy%NetBSD.org@localhost>
date: Sat Feb 08 14:17:30 2020 +0000
description:
route(4): add RO_MISSFILTER socket option
This allows filtering of specific RTM_MISS destination sockaddrs.
diffstat:
share/man/man4/route.4 | 33 ++++++++++++++++++++-
sys/net/route.h | 5 ++-
sys/net/rtsock_shared.c | 74 +++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 104 insertions(+), 8 deletions(-)
diffs (213 lines):
diff -r 30b248d04434 -r 95bd91799d0d share/man/man4/route.4
--- a/share/man/man4/route.4 Sat Feb 08 13:44:35 2020 +0000
+++ b/share/man/man4/route.4 Sat Feb 08 14:17:30 2020 +0000
@@ -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 @@
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
diff -r 30b248d04434 -r 95bd91799d0d sys/net/route.h
--- a/sys/net/route.h Sat Feb 08 13:44:35 2020 +0000
+++ b/sys/net/route.h Sat Feb 08 14:17:30 2020 +0000
@@ -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 @@
* 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 */
diff -r 30b248d04434 -r 95bd91799d0d sys/net/rtsock_shared.c
--- a/sys/net/rtsock_shared.c Sat Feb 08 13:44:35 2020 +0000
+++ b/sys/net/rtsock_shared.c Sat Feb 08 14:17:30 2020 +0000
@@ -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 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 @@
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 @@
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 @@
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 @@
{
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 @@
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;
Home |
Main Index |
Thread Index |
Old Index