Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131597312
D15617.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
44 KB
Referenced Files
None
Subscribers
None
D15617.diff
View Options
Index: head/sys/net/if_gif.c
===================================================================
--- head/sys/net/if_gif.c
+++ head/sys/net/if_gif.c
@@ -923,12 +923,24 @@
}
static void
-gif_detach(struct gif_softc *sc)
+gif_detach(struct gif_softc *sc, int family)
{
sx_assert(&gif_ioctl_sx, SA_XLOCKED);
- if (sc->gif_ecookie != NULL)
- encap_detach(sc->gif_ecookie);
+ if (sc->gif_ecookie != NULL) {
+ switch (family) {
+#ifdef INET
+ case AF_INET:
+ ip_encap_detach(sc->gif_ecookie);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ip6_encap_detach(sc->gif_ecookie);
+ break;
+#endif
+ }
+ }
sc->gif_ecookie = NULL;
}
@@ -1020,7 +1032,7 @@
}
if (sc->gif_family != src->sa_family)
- gif_detach(sc);
+ gif_detach(sc, sc->gif_family);
if (sc->gif_family == 0 ||
sc->gif_family != src->sa_family)
error = gif_attach(sc, src->sa_family);
@@ -1058,7 +1070,7 @@
sc->gif_family = 0;
GIF_WUNLOCK(sc);
if (family != 0) {
- gif_detach(sc);
+ gif_detach(sc, family);
free(sc->gif_hdr, M_GIF);
}
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
Index: head/sys/net/if_gre.h
===================================================================
--- head/sys/net/if_gre.h
+++ head/sys/net/if_gre.h
@@ -101,7 +101,7 @@
#define gre_oip gre_gihdr->gi_ip
#define gre_oip6 gre_gi6hdr->gi6_ip6
-int gre_input(struct mbuf **, int *, int);
+int gre_input(struct mbuf *, int, int, void *);
#ifdef INET
int in_gre_attach(struct gre_softc *);
int in_gre_output(struct mbuf *, int, int);
Index: head/sys/net/if_gre.c
===================================================================
--- head/sys/net/if_gre.c
+++ head/sys/net/if_gre.c
@@ -551,12 +551,24 @@
}
static void
-gre_detach(struct gre_softc *sc)
+gre_detach(struct gre_softc *sc, int family)
{
sx_assert(&gre_ioctl_sx, SA_XLOCKED);
- if (sc->gre_ecookie != NULL)
- encap_detach(sc->gre_ecookie);
+ if (sc->gre_ecookie != NULL) {
+ switch (family) {
+#ifdef INET
+ case AF_INET:
+ ip_encap_detach(sc->gre_ecookie);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ip6_encap_detach(sc->gre_ecookie);
+ break;
+#endif
+ }
+ }
sc->gre_ecookie = NULL;
}
@@ -624,7 +636,7 @@
return (EAFNOSUPPORT);
}
if (sc->gre_family != 0)
- gre_detach(sc);
+ gre_detach(sc, sc->gre_family);
GRE_WLOCK(sc);
if (sc->gre_family != 0)
free(sc->gre_hdr, M_GRE);
@@ -666,7 +678,7 @@
sc->gre_family = 0;
GRE_WUNLOCK(sc);
if (family != 0) {
- gre_detach(sc);
+ gre_detach(sc, family);
free(sc->gre_hdr, M_GRE);
}
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
@@ -674,12 +686,11 @@
}
int
-gre_input(struct mbuf **mp, int *offp, int proto)
+gre_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct gre_softc *sc;
+ struct gre_softc *sc = arg;
struct grehdr *gh;
struct ifnet *ifp;
- struct mbuf *m;
uint32_t *opts;
#ifdef notyet
uint32_t key;
@@ -687,12 +698,8 @@
uint16_t flags;
int hlen, isr, af;
- m = *mp;
- sc = encap_getarg(m);
- KASSERT(sc != NULL, ("encap_getarg returned NULL"));
-
ifp = GRE2IFP(sc);
- hlen = *offp + sizeof(struct grehdr) + 4 * sizeof(uint32_t);
+ hlen = off + sizeof(struct grehdr) + 4 * sizeof(uint32_t);
if (m->m_pkthdr.len < hlen)
goto drop;
if (m->m_len < hlen) {
@@ -700,7 +707,7 @@
if (m == NULL)
goto drop;
}
- gh = (struct grehdr *)mtodo(m, *offp);
+ gh = (struct grehdr *)mtodo(m, off);
flags = ntohs(gh->gre_flags);
if (flags & ~GRE_FLAGS_MASK)
goto drop;
@@ -710,7 +717,7 @@
/* reserved1 field must be zero */
if (((uint16_t *)opts)[1] != 0)
goto drop;
- if (in_cksum_skip(m, m->m_pkthdr.len, *offp) != 0)
+ if (in_cksum_skip(m, m->m_pkthdr.len, off) != 0)
goto drop;
hlen += 2 * sizeof(uint16_t);
opts++;
@@ -760,7 +767,7 @@
default:
goto drop;
}
- m_adj(m, *offp + hlen);
+ m_adj(m, off + hlen);
m_clrprotoflags(m);
m->m_pkthdr.rcvif = ifp;
M_SETFIB(m, ifp->if_fib);
Index: head/sys/net/if_me.c
===================================================================
--- head/sys/net/if_me.c
+++ head/sys/net/if_me.c
@@ -37,7 +37,6 @@
#include <sys/mbuf.h>
#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/protosw.h>
#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -122,12 +121,23 @@
static int me_ioctl(struct ifnet *, u_long, caddr_t);
static int me_output(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
-static int me_input(struct mbuf **, int *, int);
+static int me_input(struct mbuf *, int, int, void *);
static int me_set_tunnel(struct ifnet *, struct sockaddr_in *,
struct sockaddr_in *);
static void me_delete_tunnel(struct ifnet *);
+static int me_encapcheck(const struct mbuf *, int, int, void *);
+#define ME_MINLEN (sizeof(struct ip) + sizeof(struct mobhdr) -\
+ sizeof(in_addr_t))
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_MOBILE,
+ .min_length = ME_MINLEN,
+ .exact_match = (sizeof(in_addr_t) << 4) + 8,
+ .check = me_encapcheck,
+ .input = me_input
+};
+
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, IFT_TUNNEL, me, CTLFLAG_RW, 0,
"Minimal Encapsulation for IP (RFC 2004)");
@@ -140,19 +150,6 @@
SYSCTL_INT(_net_link_me, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
&VNET_NAME(max_me_nesting), 0, "Max nested tunnels");
-extern struct domain inetdomain;
-static const struct protosw in_mobile_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_MOBILE,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = me_input,
- .pr_output = rip_output,
- .pr_ctlinput = rip_ctlinput,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
static void
vnet_me_init(const void *unused __unused)
{
@@ -334,17 +331,13 @@
M_ASSERTPKTHDR(m);
- if (m->m_pkthdr.len < sizeof(struct ip) + sizeof(struct mobhdr) -
- sizeof(struct in_addr))
- return (0);
-
ret = 0;
ME_RLOCK(sc);
if (ME_READY(sc)) {
ip = mtod(m, struct ip *);
if (sc->me_src.s_addr == ip->ip_dst.s_addr &&
sc->me_dst.s_addr == ip->ip_src.s_addr)
- ret = 32 * 2;
+ ret = 32 * 2 + 8;
}
ME_RUNLOCK(sc);
return (ret);
@@ -376,8 +369,8 @@
ME_WUNLOCK(sc);
if (sc->me_ecookie == NULL)
- sc->me_ecookie = encap_attach_func(AF_INET, IPPROTO_MOBILE,
- me_encapcheck, &in_mobile_protosw, sc);
+ sc->me_ecookie = ip_encap_attach(&ipv4_encap_cfg,
+ sc, M_WAITOK);
if (sc->me_ecookie != NULL) {
ifp->if_drv_flags |= IFF_DRV_RUNNING;
if_link_state_change(ifp, LINK_STATE_UP);
@@ -392,7 +385,7 @@
sx_assert(&me_ioctl_sx, SA_XLOCKED);
if (sc->me_ecookie != NULL)
- encap_detach(sc->me_ecookie);
+ ip_encap_detach(sc->me_ecookie);
sc->me_ecookie = NULL;
ME_WLOCK(sc);
sc->me_src.s_addr = 0;
@@ -414,19 +407,14 @@
return (~sum);
}
-int
-me_input(struct mbuf **mp, int *offp, int proto)
+static int
+me_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct me_softc *sc;
+ struct me_softc *sc = arg;
struct mobhdr *mh;
struct ifnet *ifp;
- struct mbuf *m;
struct ip *ip;
int hlen;
-
- m = *mp;
- sc = encap_getarg(m);
- KASSERT(sc != NULL, ("encap_getarg returned NULL"));
ifp = ME2IFP(sc);
/* checks for short packets */
Index: head/sys/net/if_stf.c
===================================================================
--- head/sys/net/if_stf.c
+++ head/sys/net/if_stf.c
@@ -85,7 +85,6 @@
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
-#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/rmlock.h>
@@ -151,19 +150,7 @@
static MALLOC_DEFINE(M_STF, stfname, "6to4 Tunnel Interface");
static const int ip_stf_ttl = 40;
-extern struct domain inetdomain;
-static int in_stf_input(struct mbuf **, int *, int);
-static struct protosw in_stf_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_IPV6,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = in_stf_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
+static int in_stf_input(struct mbuf *, int, int, void *);
static char *stfnames[] = {"stf0", "stf", "6to4", NULL};
static int stfmodevent(module_t, int, void *);
@@ -183,6 +170,14 @@
static int stf_clone_destroy(struct if_clone *, struct ifnet *);
static struct if_clone *stf_cloner;
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_IPV6,
+ .min_length = sizeof(struct ip),
+ .exact_match = (sizeof(in_addr_t) << 3) + 8,
+ .check = stf_encapcheck,
+ .input = in_stf_input
+};
+
static int
stf_clone_match(struct if_clone *ifc, const char *name)
{
@@ -250,8 +245,7 @@
ifp->if_dname = stfname;
ifp->if_dunit = IF_DUNIT_NONE;
- sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
- stf_encapcheck, &in_stf_protosw, sc);
+ sc->encap_cookie = ip_encap_attach(&ipv4_encap_cfg, sc, M_WAITOK);
if (sc->encap_cookie == NULL) {
if_printf(ifp, "attach failed\n");
free(sc, M_STF);
@@ -274,7 +268,7 @@
struct stf_softc *sc = ifp->if_softc;
int err __unused;
- err = encap_detach(sc->encap_cookie);
+ err = ip_encap_detach(sc->encap_cookie);
KASSERT(err == 0, ("Unexpected error detaching encap_cookie"));
bpfdetach(ifp);
if_detach(ifp);
@@ -608,28 +602,20 @@
}
static int
-in_stf_input(struct mbuf **mp, int *offp, int proto)
+in_stf_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct stf_softc *sc;
+ struct stf_softc *sc = arg;
struct ip *ip;
struct ip6_hdr *ip6;
- struct mbuf *m;
u_int8_t otos, itos;
struct ifnet *ifp;
- int off;
- m = *mp;
- off = *offp;
-
if (proto != IPPROTO_IPV6) {
m_freem(m);
return (IPPROTO_DONE);
}
ip = mtod(m, struct ip *);
-
- sc = (struct stf_softc *)encap_getarg(m);
-
if (sc == NULL || (STF2IFP(sc)->if_flags & IFF_UP) == 0) {
m_freem(m);
return (IPPROTO_DONE);
@@ -680,7 +666,7 @@
ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
m->m_pkthdr.rcvif = ifp;
-
+
if (bpf_peers_present(ifp->if_bpf)) {
/*
* We need to prepend the address family as
Index: head/sys/netinet/in_gif.c
===================================================================
--- head/sys/netinet/in_gif.c
+++ head/sys/netinet/in_gif.c
@@ -47,7 +47,6 @@
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
-#include <sys/protosw.h>
#include <sys/malloc.h>
#include <net/if.h>
@@ -70,25 +69,11 @@
#include <net/if_gif.h>
-static int in_gif_input(struct mbuf **, int *, int);
-
-extern struct domain inetdomain;
-static struct protosw in_gif_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = 0/* IPPROTO_IPV[46] */,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = in_gif_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
#define GIF_TTL 30
static VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
#define V_ip_gif_ttl VNET(ip_gif_ttl)
SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip_gif_ttl), 0, "");
+ &VNET_NAME(ip_gif_ttl), 0, "Default TTL value for encapsulated packets");
int
in_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
@@ -136,15 +121,13 @@
}
static int
-in_gif_input(struct mbuf **mp, int *offp, int proto)
+in_gif_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct mbuf *m = *mp;
- struct gif_softc *sc;
+ struct gif_softc *sc = arg;
struct ifnet *gifp;
struct ip *ip;
uint8_t ecn;
- sc = encap_getarg(m);
if (sc == NULL) {
m_freem(m);
KMOD_IPSTAT_INC(ips_nogif);
@@ -154,7 +137,7 @@
if ((gifp->if_flags & IFF_UP) != 0) {
ip = mtod(m, struct ip *);
ecn = ip->ip_tos;
- m_adj(m, *offp);
+ m_adj(m, off);
gif_input(m, gifp, proto, ecn);
} else {
m_freem(m);
@@ -182,7 +165,7 @@
ip = mtod(m, const struct ip *);
if (sc->gif_iphdr->ip_src.s_addr != ip->ip_dst.s_addr)
return (0);
- ret = 32;
+ ret = 32 + 8; /* src + proto */
if (sc->gif_iphdr->ip_dst.s_addr != ip->ip_src.s_addr) {
if ((sc->gif_options & GIF_IGNORE_SOURCE) == 0)
return (0);
@@ -205,14 +188,19 @@
return (ret);
}
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = -1,
+ .min_length = sizeof(struct ip),
+ .exact_match = (sizeof(in_addr_t) << 4) + 8,
+ .check = gif_encapcheck,
+ .input = in_gif_input
+};
+
int
in_gif_attach(struct gif_softc *sc)
{
KASSERT(sc->gif_ecookie == NULL, ("gif_ecookie isn't NULL"));
- sc->gif_ecookie = encap_attach_func(AF_INET, -1, gif_encapcheck,
- &in_gif_protosw, sc);
- if (sc->gif_ecookie == NULL)
- return (EEXIST);
+ sc->gif_ecookie = ip_encap_attach(&ipv4_encap_cfg, sc, M_WAITOK);
return (0);
}
Index: head/sys/netinet/ip_encap.h
===================================================================
--- head/sys/netinet/ip_encap.h
+++ head/sys/netinet/ip_encap.h
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,29 +38,33 @@
#ifdef _KERNEL
-struct encaptab {
- LIST_ENTRY(encaptab) chain;
- int af;
- int proto; /* -1: don't care, I'll check myself */
- struct sockaddr_storage src; /* my addr */
- struct sockaddr_storage srcmask;
- struct sockaddr_storage dst; /* remote addr */
- struct sockaddr_storage dstmask;
- int (*func)(const struct mbuf *, int, int, void *);
- const struct protosw *psw; /* only pr_input will be used */
- void *arg; /* passed via m->m_pkthdr.aux */
-};
-
int encap4_input(struct mbuf **, int *, int);
int encap6_input(struct mbuf **, int *, int);
-const struct encaptab *encap_attach(int, int, const struct sockaddr *,
- const struct sockaddr *, const struct sockaddr *,
- const struct sockaddr *, const struct protosw *, void *);
-const struct encaptab *encap_attach_func(int, int,
- int (*)(const struct mbuf *, int, int, void *),
- const struct protosw *, void *);
-int encap_detach(const struct encaptab *);
-void *encap_getarg(struct mbuf *);
+
+typedef int (*encap_lookup_t)(const struct mbuf *, int, int, void **);
+typedef int (*encap_check_t)(const struct mbuf *, int, int, void *);
+typedef int (*encap_input_t)(struct mbuf *, int , int, void *);
+
+struct encap_config {
+ int proto; /* protocol */
+ int min_length; /* minimum packet length */
+ int exact_match; /* a packet is exactly matched */
+#define ENCAP_DRV_LOOKUP 0x7fffffff
+
+ encap_lookup_t lookup;
+ encap_check_t check;
+ encap_input_t input;
+};
+
+struct encaptab;
+
+const struct encaptab *ip_encap_attach(const struct encap_config *,
+ void *arg, int mflags);
+const struct encaptab *ip6_encap_attach(const struct encap_config *,
+ void *arg, int mflags);
+
+int ip_encap_detach(const struct encaptab *);
+int ip6_encap_detach(const struct encaptab *);
#endif
#endif /*_NETINET_IP_ENCAP_H_*/
Index: head/sys/netinet/ip_encap.c
===================================================================
--- head/sys/netinet/ip_encap.c
+++ head/sys/netinet/ip_encap.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2018 Andrey V. Elsukov <ae@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,417 +57,214 @@
* So, clearly good old protosw does not work for protocol #4 and #41.
* The code will let you match protocol via src/dst address pair.
*/
-/* XXX is M_NETADDR correct? */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_mrouting.h"
#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
-#include <sys/protosw.h>
-#include <sys/queue.h>
+#include <sys/socket.h>
#include <net/if.h>
-#include <net/route.h>
+#include <net/if_var.h>
#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_encap.h>
#ifdef INET6
-#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#endif
-#include <machine/stdarg.h>
+static MALLOC_DEFINE(M_NETADDR, "encap_export_host",
+ "Export host address structure");
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-static MALLOC_DEFINE(M_NETADDR, "encap_export_host", "Export host address structure");
+struct encaptab {
+ CK_LIST_ENTRY(encaptab) chain;
+ int proto;
+ int min_length;
+ int exact_match;
+ void *arg;
-static void encap_add(struct encaptab *);
-static int mask_match(const struct encaptab *, const struct sockaddr *,
- const struct sockaddr *);
-static void encap_fillarg(struct mbuf *, void *);
+ encap_lookup_t lookup;
+ encap_check_t check;
+ encap_input_t input;
+};
-/*
- * All global variables in ip_encap.c are locked using encapmtx.
- */
+CK_LIST_HEAD(encaptab_head, encaptab);
+#ifdef INET
+static struct encaptab_head ipv4_encaptab = CK_LIST_HEAD_INITIALIZER();
+#endif
+#ifdef INET6
+static struct encaptab_head ipv6_encaptab = CK_LIST_HEAD_INITIALIZER();
+#endif
+
static struct mtx encapmtx;
MTX_SYSINIT(encapmtx, &encapmtx, "encapmtx", MTX_DEF);
-static LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(encaptab);
+#define ENCAP_WLOCK() mtx_lock(&encapmtx)
+#define ENCAP_WUNLOCK() mtx_unlock(&encapmtx)
+#define ENCAP_RLOCK() epoch_enter_preempt(net_epoch_preempt)
+#define ENCAP_RUNLOCK() epoch_exit_preempt(net_epoch_preempt)
+#define ENCAP_WAIT() epoch_wait_preempt(net_epoch_preempt)
-#ifdef INET
-int
-encap4_input(struct mbuf **mp, int *offp, int proto)
+static struct encaptab *
+encap_attach(struct encaptab_head *head, const struct encap_config *cfg,
+ void *arg, int mflags)
{
- struct ip *ip;
- struct mbuf *m;
- struct sockaddr_in s, d;
- const struct protosw *psw;
- struct encaptab *ep, *match;
- void *arg;
- int matchprio, off, prio;
+ struct encaptab *ep, *tmp;
- m = *mp;
- off = *offp;
- ip = mtod(m, struct ip *);
+ if (cfg == NULL || cfg->input == NULL ||
+ (cfg->check == NULL && cfg->lookup == NULL) ||
+ (cfg->lookup != NULL && cfg->exact_match != ENCAP_DRV_LOOKUP) ||
+ (cfg->exact_match == ENCAP_DRV_LOOKUP && cfg->lookup == NULL))
+ return (NULL);
- bzero(&s, sizeof(s));
- s.sin_family = AF_INET;
- s.sin_len = sizeof(struct sockaddr_in);
- s.sin_addr = ip->ip_src;
- bzero(&d, sizeof(d));
- d.sin_family = AF_INET;
- d.sin_len = sizeof(struct sockaddr_in);
- d.sin_addr = ip->ip_dst;
+ ep = malloc(sizeof(*ep), M_NETADDR, mflags);
+ if (ep == NULL)
+ return (NULL);
- arg = NULL;
- psw = NULL;
- match = NULL;
- matchprio = 0;
- mtx_lock(&encapmtx);
- LIST_FOREACH(ep, &encaptab, chain) {
- if (ep->af != AF_INET)
- continue;
- if (ep->proto >= 0 && ep->proto != proto)
- continue;
- if (ep->func)
- prio = (*ep->func)(m, off, proto, ep->arg);
- else {
- /*
- * it's inbound traffic, we need to match in reverse
- * order
- */
- prio = mask_match(ep, (struct sockaddr *)&d,
- (struct sockaddr *)&s);
- }
+ ep->proto = cfg->proto;
+ ep->min_length = cfg->min_length;
+ ep->exact_match = cfg->exact_match;
+ ep->arg = arg;
+ ep->lookup = cfg->exact_match == ENCAP_DRV_LOOKUP ? cfg->lookup: NULL;
+ ep->check = cfg->exact_match != ENCAP_DRV_LOOKUP ? cfg->check: NULL;
+ ep->input = cfg->input;
- /*
- * We prioritize the matches by using bit length of the
- * matches. mask_match() and user-supplied matching function
- * should return the bit length of the matches (for example,
- * if both src/dst are matched for IPv4, 64 should be returned).
- * 0 or negative return value means "it did not match".
- *
- * The question is, since we have two "mask" portion, we
- * cannot really define total order between entries.
- * For example, which of these should be preferred?
- * mask_match() returns 48 (32 + 16) for both of them.
- * src=3ffe::/16, dst=3ffe:501::/32
- * src=3ffe:501::/32, dst=3ffe::/16
- *
- * We need to loop through all the possible candidates
- * to get the best match - the search takes O(n) for
- * n attachments (i.e. interfaces).
- */
- if (prio <= 0)
- continue;
- if (prio > matchprio) {
- matchprio = prio;
- match = ep;
- }
+ ENCAP_WLOCK();
+ CK_LIST_FOREACH(tmp, head, chain) {
+ if (tmp->exact_match <= ep->exact_match)
+ break;
}
- if (match != NULL) {
- psw = match->psw;
- arg = match->arg;
- }
- mtx_unlock(&encapmtx);
+ if (tmp == NULL)
+ CK_LIST_INSERT_HEAD(head, ep, chain);
+ else
+ CK_LIST_INSERT_BEFORE(tmp, ep, chain);
+ ENCAP_WUNLOCK();
+ return (ep);
+}
- if (match != NULL) {
- /* found a match, "match" has the best one */
- if (psw != NULL && psw->pr_input != NULL) {
- encap_fillarg(m, arg);
- (*psw->pr_input)(mp, offp, proto);
- } else
- m_freem(m);
- return (IPPROTO_DONE);
- }
+static int
+encap_detach(struct encaptab_head *head, const struct encaptab *cookie)
+{
+ struct encaptab *ep;
- /* last resort: inject to raw socket */
- return (rip_input(mp, offp, proto));
+ ENCAP_WLOCK();
+ CK_LIST_FOREACH(ep, head, chain) {
+ if (ep == cookie) {
+ CK_LIST_REMOVE(ep, chain);
+ ENCAP_WUNLOCK();
+ ENCAP_WAIT();
+ free(ep, M_NETADDR);
+ return (0);
+ }
+ }
+ ENCAP_WUNLOCK();
+ return (EINVAL);
}
-#endif
-#ifdef INET6
-int
-encap6_input(struct mbuf **mp, int *offp, int proto)
+static int
+encap_input(struct encaptab_head *head, struct mbuf *m, int off, int proto)
{
- struct mbuf *m = *mp;
- struct ip6_hdr *ip6;
- struct sockaddr_in6 s, d;
- const struct protosw *psw;
struct encaptab *ep, *match;
void *arg;
- int prio, matchprio;
+ int matchprio, ret;
- ip6 = mtod(m, struct ip6_hdr *);
-
- bzero(&s, sizeof(s));
- s.sin6_family = AF_INET6;
- s.sin6_len = sizeof(struct sockaddr_in6);
- s.sin6_addr = ip6->ip6_src;
- bzero(&d, sizeof(d));
- d.sin6_family = AF_INET6;
- d.sin6_len = sizeof(struct sockaddr_in6);
- d.sin6_addr = ip6->ip6_dst;
-
- arg = NULL;
- psw = NULL;
match = NULL;
matchprio = 0;
- mtx_lock(&encapmtx);
- LIST_FOREACH(ep, &encaptab, chain) {
- if (ep->af != AF_INET6)
- continue;
+
+ ENCAP_RLOCK();
+ CK_LIST_FOREACH(ep, head, chain) {
if (ep->proto >= 0 && ep->proto != proto)
continue;
- if (ep->func)
- prio = (*ep->func)(m, *offp, proto, ep->arg);
- else {
+ if (ep->min_length > m->m_pkthdr.len)
+ continue;
+ if (ep->exact_match == ENCAP_DRV_LOOKUP)
+ ret = (*ep->lookup)(m, off, proto, &arg);
+ else
+ ret = (*ep->check)(m, off, proto, ep->arg);
+ if (ret <= 0)
+ continue;
+ if (ret > matchprio) {
+ match = ep;
+ if (ep->exact_match != ENCAP_DRV_LOOKUP)
+ arg = ep->arg;
/*
- * it's inbound traffic, we need to match in reverse
- * order
+ * No need to continue the search, we got the
+ * exact match.
*/
- prio = mask_match(ep, (struct sockaddr *)&d,
- (struct sockaddr *)&s);
+ if (ret >= ep->exact_match)
+ break;
+ matchprio = ret;
}
-
- /* see encap4_input() for issues here */
- if (prio <= 0)
- continue;
- if (prio > matchprio) {
- matchprio = prio;
- match = ep;
- }
}
- if (match != NULL) {
- psw = match->psw;
- arg = match->arg;
- }
- mtx_unlock(&encapmtx);
if (match != NULL) {
- /* found a match */
- if (psw != NULL && psw->pr_input != NULL) {
- encap_fillarg(m, arg);
- return (*psw->pr_input)(mp, offp, proto);
- } else {
- m_freem(m);
- return (IPPROTO_DONE);
- }
+ /* found a match, "match" has the best one */
+ ret = (*match->input)(m, off, proto, arg);
+ ENCAP_RUNLOCK();
+ MPASS(ret == IPPROTO_DONE);
+ return (IPPROTO_DONE);
}
-
- /* last resort: inject to raw socket */
- return rip6_input(mp, offp, proto);
+ ENCAP_RUNLOCK();
+ return (0);
}
-#endif
-/*lint -sem(encap_add, custodial(1)) */
-static void
-encap_add(struct encaptab *ep)
-{
-
- mtx_assert(&encapmtx, MA_OWNED);
- LIST_INSERT_HEAD(&encaptab, ep, chain);
-}
-
-/*
- * sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
- * length of mask (sm and dm) is assumed to be same as sp/dp.
- * Return value will be necessary as input (cookie) for encap_detach().
- */
+#ifdef INET
const struct encaptab *
-encap_attach(int af, int proto, const struct sockaddr *sp,
- const struct sockaddr *sm, const struct sockaddr *dp,
- const struct sockaddr *dm, const struct protosw *psw, void *arg)
+ip_encap_attach(const struct encap_config *cfg, void *arg, int mflags)
{
- struct encaptab *ep;
- /* sanity check on args */
- if (sp->sa_len > sizeof(ep->src) || dp->sa_len > sizeof(ep->dst))
- return (NULL);
- if (sp->sa_len != dp->sa_len)
- return (NULL);
- if (af != sp->sa_family || af != dp->sa_family)
- return (NULL);
-
- /* check if anyone have already attached with exactly same config */
- mtx_lock(&encapmtx);
- LIST_FOREACH(ep, &encaptab, chain) {
- if (ep->af != af)
- continue;
- if (ep->proto != proto)
- continue;
- if (ep->src.ss_len != sp->sa_len ||
- bcmp(&ep->src, sp, sp->sa_len) != 0 ||
- bcmp(&ep->srcmask, sm, sp->sa_len) != 0)
- continue;
- if (ep->dst.ss_len != dp->sa_len ||
- bcmp(&ep->dst, dp, dp->sa_len) != 0 ||
- bcmp(&ep->dstmask, dm, dp->sa_len) != 0)
- continue;
-
- mtx_unlock(&encapmtx);
- return (NULL);
- }
-
- ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/
- if (ep == NULL) {
- mtx_unlock(&encapmtx);
- return (NULL);
- }
- bzero(ep, sizeof(*ep));
-
- ep->af = af;
- ep->proto = proto;
- bcopy(sp, &ep->src, sp->sa_len);
- bcopy(sm, &ep->srcmask, sp->sa_len);
- bcopy(dp, &ep->dst, dp->sa_len);
- bcopy(dm, &ep->dstmask, dp->sa_len);
- ep->psw = psw;
- ep->arg = arg;
-
- encap_add(ep);
- mtx_unlock(&encapmtx);
- return (ep);
+ return (encap_attach(&ipv4_encaptab, cfg, arg, mflags));
}
-const struct encaptab *
-encap_attach_func(int af, int proto,
- int (*func)(const struct mbuf *, int, int, void *),
- const struct protosw *psw, void *arg)
+int
+ip_encap_detach(const struct encaptab *cookie)
{
- struct encaptab *ep;
- /* sanity check on args */
- if (!func)
- return (NULL);
-
- ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/
- if (ep == NULL)
- return (NULL);
- bzero(ep, sizeof(*ep));
-
- ep->af = af;
- ep->proto = proto;
- ep->func = func;
- ep->psw = psw;
- ep->arg = arg;
-
- mtx_lock(&encapmtx);
- encap_add(ep);
- mtx_unlock(&encapmtx);
- return (ep);
+ return (encap_detach(&ipv4_encaptab, cookie));
}
int
-encap_detach(const struct encaptab *cookie)
+encap4_input(struct mbuf **mp, int *offp, int proto)
{
- const struct encaptab *ep = cookie;
- struct encaptab *p;
- mtx_lock(&encapmtx);
- LIST_FOREACH(p, &encaptab, chain) {
- if (p == ep) {
- LIST_REMOVE(p, chain);
- mtx_unlock(&encapmtx);
- free(p, M_NETADDR); /*XXX*/
- return 0;
- }
- }
- mtx_unlock(&encapmtx);
-
- return EINVAL;
+ if (encap_input(&ipv4_encaptab, *mp, *offp, proto) != IPPROTO_DONE)
+ return (rip_input(mp, offp, proto));
+ return (IPPROTO_DONE);
}
+#endif /* INET */
-static int
-mask_match(const struct encaptab *ep, const struct sockaddr *sp,
- const struct sockaddr *dp)
+#ifdef INET6
+const struct encaptab *
+ip6_encap_attach(const struct encap_config *cfg, void *arg, int mflags)
{
- struct sockaddr_storage s;
- struct sockaddr_storage d;
- int i;
- const u_int8_t *p, *q;
- u_int8_t *r;
- int matchlen;
- if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d))
- return 0;
- if (sp->sa_family != ep->af || dp->sa_family != ep->af)
- return 0;
- if (sp->sa_len != ep->src.ss_len || dp->sa_len != ep->dst.ss_len)
- return 0;
-
- matchlen = 0;
-
- p = (const u_int8_t *)sp;
- q = (const u_int8_t *)&ep->srcmask;
- r = (u_int8_t *)&s;
- for (i = 0 ; i < sp->sa_len; i++) {
- r[i] = p[i] & q[i];
- /* XXX estimate */
- matchlen += (q[i] ? 8 : 0);
- }
-
- p = (const u_int8_t *)dp;
- q = (const u_int8_t *)&ep->dstmask;
- r = (u_int8_t *)&d;
- for (i = 0 ; i < dp->sa_len; i++) {
- r[i] = p[i] & q[i];
- /* XXX rough estimate */
- matchlen += (q[i] ? 8 : 0);
- }
-
- /* need to overwrite len/family portion as we don't compare them */
- s.ss_len = sp->sa_len;
- s.ss_family = sp->sa_family;
- d.ss_len = dp->sa_len;
- d.ss_family = dp->sa_family;
-
- if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 &&
- bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) {
- return matchlen;
- } else
- return 0;
+ return (encap_attach(&ipv6_encaptab, cfg, arg, mflags));
}
-static void
-encap_fillarg(struct mbuf *m, void *arg)
+int
+ip6_encap_detach(const struct encaptab *cookie)
{
- struct m_tag *tag;
- if (arg != NULL) {
- tag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT);
- if (tag != NULL) {
- *(void**)(tag+1) = arg;
- m_tag_prepend(m, tag);
- }
- }
+ return (encap_detach(&ipv6_encaptab, cookie));
}
-void *
-encap_getarg(struct mbuf *m)
+int
+encap6_input(struct mbuf **mp, int *offp, int proto)
{
- void *p = NULL;
- struct m_tag *tag;
- tag = m_tag_find(m, PACKET_TAG_ENCAP, NULL);
- if (tag) {
- p = *(void**)(tag+1);
- m_tag_delete(m, tag);
- }
- return p;
+ if (encap_input(&ipv6_encaptab, *mp, *offp, proto) != IPPROTO_DONE)
+ return (rip6_input(mp, offp, proto));
+ return (IPPROTO_DONE);
}
+#endif /* INET6 */
Index: head/sys/netinet/ip_gre.c
===================================================================
--- head/sys/netinet/ip_gre.c
+++ head/sys/netinet/ip_gre.c
@@ -45,7 +45,6 @@
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <sys/protosw.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
@@ -69,24 +68,11 @@
#include <net/if_gre.h>
-extern struct domain inetdomain;
-static const struct protosw in_gre_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_GRE,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = gre_input,
- .pr_output = rip_output,
- .pr_ctlinput = rip_ctlinput,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
#define GRE_TTL 30
VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL;
#define V_ip_gre_ttl VNET(ip_gre_ttl)
SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip_gre_ttl), 0, "");
+ &VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets");
static int
in_gre_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
@@ -100,12 +86,6 @@
return (0);
M_ASSERTPKTHDR(m);
- /*
- * We expect that payload contains at least IPv4
- * or IPv6 packet.
- */
- if (m->m_pkthdr.len < sizeof(struct greip) + sizeof(struct ip))
- return (0);
GRE_RLOCK(sc);
if (sc->gre_family == 0)
@@ -120,7 +100,7 @@
goto bad;
GRE_RUNLOCK(sc);
- return (32 * 2);
+ return (32 * 3); /* src + dst + gre_hdr */
bad:
GRE_RUNLOCK(sc);
return (0);
@@ -156,14 +136,19 @@
return (ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL));
}
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_GRE,
+ .min_length = sizeof(struct greip) + sizeof(struct ip),
+ .exact_match = (sizeof(in_addr_t) << 4) + 32,
+ .check = in_gre_encapcheck,
+ .input = gre_input
+};
+
int
in_gre_attach(struct gre_softc *sc)
{
KASSERT(sc->gre_ecookie == NULL, ("gre_ecookie isn't NULL"));
- sc->gre_ecookie = encap_attach_func(AF_INET, IPPROTO_GRE,
- in_gre_encapcheck, &in_gre_protosw, sc);
- if (sc->gre_ecookie == NULL)
- return (EEXIST);
+ sc->gre_ecookie = ip_encap_attach(&ipv4_encap_cfg, sc, M_WAITOK);
return (0);
}
Index: head/sys/netinet/ip_mroute.c
===================================================================
--- head/sys/netinet/ip_mroute.c
+++ head/sys/netinet/ip_mroute.c
@@ -242,21 +242,18 @@
&pim_squelch_wholepkt, 0,
"Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified");
-extern struct domain inetdomain;
-static const struct protosw in_pim_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = IPPROTO_PIM,
- .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
- .pr_input = pim_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
static const struct encaptab *pim_encap_cookie;
-
static int pim_encapcheck(const struct mbuf *, int, int, void *);
+static int pim_input(struct mbuf *, int, int, void *);
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = IPPROTO_PIM,
+ .min_length = sizeof(struct ip) + PIM_MINLEN,
+ .exact_match = 8,
+ .check = pim_encapcheck,
+ .input = pim_input
+};
+
/*
* Note: the PIM Register encapsulation adds the following in front of a
* data packet:
@@ -2544,16 +2541,12 @@
* into the kernel.
*/
static int
-pim_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+pim_encapcheck(const struct mbuf *m __unused, int off __unused,
+ int proto __unused, void *arg __unused)
{
-#ifdef DIAGNOSTIC
KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
-#endif
- if (proto != IPPROTO_PIM)
- return 0; /* not for us; reject the datagram. */
-
- return 64; /* claim the datagram. */
+ return (8); /* claim the datagram. */
}
/*
@@ -2564,18 +2557,15 @@
* (used by PIM-SM): the PIM header is stripped off, and the inner packet
* is passed to if_simloop().
*/
-int
-pim_input(struct mbuf **mp, int *offp, int proto)
+static int
+pim_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
- struct mbuf *m = *mp;
struct ip *ip = mtod(m, struct ip *);
struct pim *pim;
- int iphlen = *offp;
+ int iphlen = off;
int minlen;
int datalen = ntohs(ip->ip_len) - iphlen;
int ip_tos;
-
- *mp = NULL;
/* Keep statistics */
PIMSTAT_INC(pims_rcv_total_msgs);
@@ -2779,10 +2769,7 @@
* XXX: the outer IP header pkt size of a Register is not adjust to
* reflect the fact that the inner multicast data is truncated.
*/
- *mp = m;
- rip_input(mp, offp, proto);
-
- return (IPPROTO_DONE);
+ return (rip_input(&m, &off, proto));
}
static int
@@ -2873,8 +2860,7 @@
TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt",
&pim_squelch_wholepkt);
- pim_encap_cookie = encap_attach_func(AF_INET, IPPROTO_PIM,
- pim_encapcheck, &in_pim_protosw, NULL);
+ pim_encap_cookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
if (pim_encap_cookie == NULL) {
printf("ip_mroute: unable to attach pim encap\n");
VIF_LOCK_DESTROY();
@@ -2917,7 +2903,7 @@
EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag);
if (pim_encap_cookie) {
- encap_detach(pim_encap_cookie);
+ ip_encap_detach(pim_encap_cookie);
pim_encap_cookie = NULL;
}
Index: head/sys/netinet/pim_var.h
===================================================================
--- head/sys/netinet/pim_var.h
+++ head/sys/netinet/pim_var.h
@@ -73,8 +73,6 @@
#define PIMCTL_STATS 1 /* statistics (read-only) */
#ifdef _KERNEL
-
-int pim_input(struct mbuf **, int *, int);
SYSCTL_DECL(_net_inet_pim);
#endif
Index: head/sys/netinet6/in6_gif.c
===================================================================
--- head/sys/netinet6/in6_gif.c
+++ head/sys/netinet6/in6_gif.c
@@ -49,7 +49,6 @@
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
-#include <sys/protosw.h>
#include <sys/malloc.h>
#include <net/if.h>
@@ -81,23 +80,10 @@
#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
SYSCTL_DECL(_net_inet6_ip6);
-SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_VNET | CTLFLAG_RW,
- &VNET_NAME(ip6_gif_hlim), 0, "");
+SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_gif_hlim), 0,
+ "Default hop limit for encapsulated packets");
-static int in6_gif_input(struct mbuf **, int *, int);
-
-extern struct domain inet6domain;
-static struct protosw in6_gif_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = 0, /* IPPROTO_IPV[46] */
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = in6_gif_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
-
int
in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
{
@@ -147,15 +133,13 @@
}
static int
-in6_gif_input(struct mbuf **mp, int *offp, int proto)
+in6_gif_input(struct mbuf *m, int off, int proto, void *arg)
{
- struct mbuf *m = *mp;
+ struct gif_softc *sc = arg;
struct ifnet *gifp;
- struct gif_softc *sc;
struct ip6_hdr *ip6;
uint8_t ecn;
- sc = encap_getarg(m);
if (sc == NULL) {
m_freem(m);
IP6STAT_INC(ip6s_nogif);
@@ -165,7 +149,7 @@
if ((gifp->if_flags & IFF_UP) != 0) {
ip6 = mtod(m, struct ip6_hdr *);
ecn = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
- m_adj(m, *offp);
+ m_adj(m, off);
gif_input(m, gifp, proto, ecn);
} else {
m_freem(m);
@@ -219,14 +203,19 @@
return (ret);
}
+static const struct encap_config ipv6_encap_cfg = {
+ .proto = -1,
+ .min_length = sizeof(struct ip6_hdr),
+ .exact_match = (sizeof(struct in6_addr) << 4) + 8,
+ .check = gif_encapcheck,
+ .input = in6_gif_input
+};
+
int
in6_gif_attach(struct gif_softc *sc)
{
KASSERT(sc->gif_ecookie == NULL, ("gif_ecookie isn't NULL"));
- sc->gif_ecookie = encap_attach_func(AF_INET6, -1, gif_encapcheck,
- (void *)&in6_gif_protosw, sc);
- if (sc->gif_ecookie == NULL)
- return (EEXIST);
+ sc->gif_ecookie = ip6_encap_attach(&ipv6_encap_cfg, sc, M_WAITOK);
return (0);
}
Index: head/sys/netinet6/ip6_gre.c
===================================================================
--- head/sys/netinet6/ip6_gre.c
+++ head/sys/netinet6/ip6_gre.c
@@ -42,7 +42,6 @@
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
-#include <sys/protosw.h>
#include <sys/malloc.h>
#include <net/if.h>
@@ -61,18 +60,6 @@
#include <netinet6/in6_var.h>
#include <net/if_gre.h>
-extern struct domain inet6domain;
-struct protosw in6_gre_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = IPPROTO_GRE,
- .pr_flags = PR_ATOMIC|PR_ADDR,
- .pr_input = gre_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
-
VNET_DEFINE(int, ip6_gre_hlim) = IPV6_DEFHLIM;
#define V_ip6_gre_hlim VNET(ip6_gre_hlim)
@@ -117,7 +104,7 @@
goto bad;
GRE_RUNLOCK(sc);
- return (128 * 2);
+ return (128 * 2 + 32);
bad:
GRE_RUNLOCK(sc);
return (0);
@@ -133,14 +120,19 @@
return (ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL, NULL));
}
+static const struct encap_config ipv6_encap_cfg = {
+ .proto = IPPROTO_GRE,
+ .min_length = sizeof(struct greip6) + sizeof(struct ip),
+ .exact_match = (sizeof(struct in6_addr) << 4) + 32,
+ .check = in6_gre_encapcheck,
+ .input = gre_input
+};
+
int
in6_gre_attach(struct gre_softc *sc)
{
KASSERT(sc->gre_ecookie == NULL, ("gre_ecookie isn't NULL"));
- sc->gre_ecookie = encap_attach_func(AF_INET6, IPPROTO_GRE,
- in6_gre_encapcheck, &in6_gre_protosw, sc);
- if (sc->gre_ecookie == NULL)
- return (EEXIST);
+ sc->gre_ecookie = ip6_encap_attach(&ipv6_encap_cfg, sc, M_WAITOK);
return (0);
}
Index: head/sys/netinet6/ip6_mroute.c
===================================================================
--- head/sys/netinet6/ip6_mroute.c
+++ head/sys/netinet6/ip6_mroute.c
@@ -109,7 +109,6 @@
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
-#include <net/raw_cb.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -139,18 +138,18 @@
extern struct domain inet6domain;
static const struct encaptab *pim6_encap_cookie;
-static const struct protosw in6_pim_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = IPPROTO_PIM,
- .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
- .pr_input = pim6_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
static int pim6_encapcheck(const struct mbuf *, int, int, void *);
+static int pim6_input(struct mbuf *, int, int, void *);
+static const struct encap_config ipv6_encap_cfg = {
+ .proto = IPPROTO_PIM,
+ .min_length = sizeof(struct ip6_hdr) + PIM_MINLEN,
+ .exact_match = 8,
+ .check = pim6_encapcheck,
+ .input = pim6_input
+};
+
+
static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver)
@@ -1695,16 +1694,12 @@
* into the kernel.
*/
static int
-pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+pim6_encapcheck(const struct mbuf *m __unused, int off __unused,
+ int proto __unused, void *arg __unused)
{
-#ifdef DIAGNOSTIC
KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
-#endif
- if (proto != IPPROTO_PIM)
- return 0; /* not for us; reject the datagram. */
-
- return 64; /* claim the datagram. */
+ return (8); /* claim the datagram. */
}
/*
@@ -1714,20 +1709,18 @@
* The only message processed is the REGISTER pim message; the pim header
* is stripped off, and the inner packet is passed to register_mforward.
*/
-int
-pim6_input(struct mbuf **mp, int *offp, int proto)
+static int
+pim6_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
struct pim *pim; /* pointer to a pim struct */
struct ip6_hdr *ip6;
int pimlen;
- struct mbuf *m = *mp;
int minlen;
- int off = *offp;
PIM6STAT_INC(pim6s_rcv_total);
ip6 = mtod(m, struct ip6_hdr *);
- pimlen = m->m_pkthdr.len - *offp;
+ pimlen = m->m_pkthdr.len - off;
/*
* Validate lengths
@@ -1904,8 +1897,7 @@
* encapsulated ip6 header.
*/
pim6_input_to_daemon:
- rip6_input(&m, offp, proto);
- return (IPPROTO_DONE);
+ return (rip6_input(&m, &off, proto));
}
static int
@@ -1918,9 +1910,8 @@
MFC6_LOCK_INIT();
MIF6_LOCK_INIT();
- pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
- pim6_encapcheck,
- (const struct protosw *)&in6_pim_protosw, NULL);
+ pim6_encap_cookie = ip6_encap_attach(&ipv6_encap_cfg,
+ NULL, M_WAITOK);
if (pim6_encap_cookie == NULL) {
printf("ip6_mroute: unable to attach pim6 encap\n");
MIF6_LOCK_DESTROY();
@@ -1941,7 +1932,7 @@
return EINVAL;
if (pim6_encap_cookie) {
- encap_detach(pim6_encap_cookie);
+ ip6_encap_detach(pim6_encap_cookie);
pim6_encap_cookie = NULL;
}
X_ip6_mrouter_done();
Index: head/sys/netinet6/pim6_var.h
===================================================================
--- head/sys/netinet6/pim6_var.h
+++ head/sys/netinet6/pim6_var.h
@@ -53,10 +53,6 @@
uint64_t pim6s_snd_registers; /* sent registers */
};
-#if (defined(KERNEL)) || (defined(_KERNEL))
-int pim6_input(struct mbuf **, int*, int);
-#endif /* KERNEL */
-
/*
* Identifiers for PIM sysctl nodes
*/
Index: head/sys/netipsec/xform_ipcomp.c
===================================================================
--- head/sys/netipsec/xform_ipcomp.c
+++ head/sys/netipsec/xform_ipcomp.c
@@ -118,7 +118,7 @@
}
static int
-ipcomp_nonexp_input(struct mbuf **mp, int *offp, int proto)
+ipcomp_nonexp_input(struct mbuf *m, int off, int proto, void *arg __unused)
{
int isr;
@@ -135,13 +135,13 @@
#endif
default:
IPCOMPSTAT_INC(ipcomps_nopf);
- m_freem(*mp);
+ m_freem(m);
return (IPPROTO_DONE);
}
- m_adj(*mp, *offp);
- IPCOMPSTAT_ADD(ipcomps_ibytes, (*mp)->m_pkthdr.len);
+ m_adj(m, off);
+ IPCOMPSTAT_ADD(ipcomps_ibytes, m->m_pkthdr.len);
IPCOMPSTAT_INC(ipcomps_input);
- netisr_dispatch(isr, *mp);
+ netisr_dispatch(isr, m);
return (IPPROTO_DONE);
}
@@ -662,19 +662,6 @@
}
#ifdef INET
-static const struct encaptab *ipe4_cookie = NULL;
-extern struct domain inetdomain;
-static struct protosw ipcomp4_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inetdomain,
- .pr_protocol = 0 /* IPPROTO_IPV[46] */,
- .pr_flags = PR_ATOMIC | PR_ADDR | PR_LASTHDR,
- .pr_input = ipcomp_nonexp_input,
- .pr_output = rip_output,
- .pr_ctloutput = rip_ctloutput,
- .pr_usrreqs = &rip_usrreqs
-};
-
static int
ipcomp4_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
void *arg __unused)
@@ -695,21 +682,17 @@
dst.sin.sin_addr = ip->ip_dst;
return (ipcomp_encapcheck(&src, &dst));
}
+
+static const struct encaptab *ipe4_cookie = NULL;
+static const struct encap_config ipv4_encap_cfg = {
+ .proto = -1,
+ .min_length = sizeof(struct ip),
+ .exact_match = sizeof(in_addr_t) << 4,
+ .check = ipcomp4_nonexp_encapcheck,
+ .input = ipcomp_nonexp_input
+};
#endif
#ifdef INET6
-static const struct encaptab *ipe6_cookie = NULL;
-extern struct domain inet6domain;
-static struct protosw ipcomp6_protosw = {
- .pr_type = SOCK_RAW,
- .pr_domain = &inet6domain,
- .pr_protocol = 0 /* IPPROTO_IPV[46] */,
- .pr_flags = PR_ATOMIC | PR_ADDR | PR_LASTHDR,
- .pr_input = ipcomp_nonexp_input,
- .pr_output = rip6_output,
- .pr_ctloutput = rip6_ctloutput,
- .pr_usrreqs = &rip6_usrreqs
-};
-
static int
ipcomp6_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
void *arg __unused)
@@ -742,6 +725,15 @@
}
return (ipcomp_encapcheck(&src, &dst));
}
+
+static const struct encaptab *ipe6_cookie = NULL;
+static const struct encap_config ipv6_encap_cfg = {
+ .proto = -1,
+ .min_length = sizeof(struct ip6_hdr),
+ .exact_match = sizeof(struct in6_addr) << 4,
+ .check = ipcomp6_nonexp_encapcheck,
+ .input = ipcomp_nonexp_input
+};
#endif
static struct xformsw ipcomp_xformsw = {
@@ -758,12 +750,10 @@
{
#ifdef INET
- ipe4_cookie = encap_attach_func(AF_INET, -1,
- ipcomp4_nonexp_encapcheck, &ipcomp4_protosw, NULL);
+ ipe4_cookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
#endif
#ifdef INET6
- ipe6_cookie = encap_attach_func(AF_INET6, -1,
- ipcomp6_nonexp_encapcheck, &ipcomp6_protosw, NULL);
+ ipe6_cookie = ip6_encap_attach(&ipv6_encap_cfg, NULL, M_WAITOK);
#endif
xform_attach(&ipcomp_xformsw);
}
@@ -773,10 +763,10 @@
{
#ifdef INET
- encap_detach(ipe4_cookie);
+ ip_encap_detach(ipe4_cookie);
#endif
#ifdef INET6
- encap_detach(ipe6_cookie);
+ ip6_encap_detach(ipe6_cookie);
#endif
xform_detach(&ipcomp_xformsw);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 10, 2:50 PM (19 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23535599
Default Alt Text
D15617.diff (44 KB)
Attached To
Mode
D15617: Overhaul ip_encap KPI to be lockless on data path
Attached
Detach File
Event Timeline
Log In to Comment