Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/siftr.c
Show First 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
#include <net/pfil.h> | #include <net/pfil.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_kdtrace.h> | #include <netinet/in_kdtrace.h> | ||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#include <netinet/in_systm.h> | #include <netinet/in_systm.h> | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/ip_var.h> | |||||
#include <netinet/tcp_var.h> | #include <netinet/tcp_var.h> | ||||
#ifdef SIFTR_IPV6 | #ifdef SIFTR_IPV6 | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
#include <netinet/ip6_var.h> | |||||
#include <netinet6/in6_pcb.h> | #include <netinet6/in6_pcb.h> | ||||
#endif /* SIFTR_IPV6 */ | #endif /* SIFTR_IPV6 */ | ||||
#include <machine/in_cksum.h> | #include <machine/in_cksum.h> | ||||
/* | /* | ||||
* Three digit version number refers to X.Y.Z where: | * Three digit version number refers to X.Y.Z where: | ||||
* X is the major version number | * X is the major version number | ||||
▲ Show 20 Lines • Show All 712 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* pfil hook that is called for each IPv4 packet making its way through the | * pfil hook that is called for each IPv4 packet making its way through the | ||||
* stack in either direction. | * stack in either direction. | ||||
* The pfil subsystem holds a non-sleepable mutex somewhere when | * The pfil subsystem holds a non-sleepable mutex somewhere when | ||||
* calling our hook function, so we can't sleep at all. | * calling our hook function, so we can't sleep at all. | ||||
* It's very important to use the M_NOWAIT flag with all function calls | * It's very important to use the M_NOWAIT flag with all function calls | ||||
* that support it so that they won't sleep, otherwise you get a panic. | * that support it so that they won't sleep, otherwise you get a panic. | ||||
*/ | */ | ||||
static int | static pfil_return_t | ||||
siftr_chkpkt(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, | siftr_chkpkt(struct mbuf **m, struct ifnet *ifp, int flags, | ||||
struct inpcb *inp) | void *ruleset __unused, struct inpcb *inp) | ||||
{ | { | ||||
struct pkt_node *pn; | struct pkt_node *pn; | ||||
struct ip *ip; | struct ip *ip; | ||||
struct tcphdr *th; | struct tcphdr *th; | ||||
struct tcpcb *tp; | struct tcpcb *tp; | ||||
struct siftr_stats *ss; | struct siftr_stats *ss; | ||||
unsigned int ip_hl; | unsigned int ip_hl; | ||||
int inp_locally_locked; | int inp_locally_locked, dir; | ||||
inp_locally_locked = 0; | inp_locally_locked = 0; | ||||
dir = PFIL_DIR(flags); | |||||
ss = DPCPU_PTR(ss); | ss = DPCPU_PTR(ss); | ||||
/* | /* | ||||
* m_pullup is not required here because ip_{input|output} | * m_pullup is not required here because ip_{input|output} | ||||
* already do the heavy lifting for us. | * already do the heavy lifting for us. | ||||
*/ | */ | ||||
ip = mtod(*m, struct ip *); | ip = mtod(*m, struct ip *); | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | siftr_chkpkt(struct mbuf **m, struct ifnet *ifp, int flags, | ||||
mtx_unlock(&siftr_pkt_queue_mtx); | mtx_unlock(&siftr_pkt_queue_mtx); | ||||
goto ret; | goto ret; | ||||
inp_unlock: | inp_unlock: | ||||
if (inp_locally_locked) | if (inp_locally_locked) | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
ret: | ret: | ||||
/* Returning 0 ensures pfil will not discard the pkt */ | return (PFIL_PASS); | ||||
return (0); | |||||
} | } | ||||
#ifdef SIFTR_IPV6 | #ifdef SIFTR_IPV6 | ||||
static int | static int | ||||
siftr_chkpkt6(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, | siftr_chkpkt6(struct mbuf **m, struct ifnet *ifp, int flags, struct inpcb *inp) | ||||
struct inpcb *inp) | |||||
{ | { | ||||
struct pkt_node *pn; | struct pkt_node *pn; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct tcphdr *th; | struct tcphdr *th; | ||||
struct tcpcb *tp; | struct tcpcb *tp; | ||||
struct siftr_stats *ss; | struct siftr_stats *ss; | ||||
unsigned int ip6_hl; | unsigned int ip6_hl; | ||||
int inp_locally_locked; | int inp_locally_locked, dir; | ||||
inp_locally_locked = 0; | inp_locally_locked = 0; | ||||
dir = PFIL_DIR(flags); | |||||
ss = DPCPU_PTR(ss); | ss = DPCPU_PTR(ss); | ||||
/* | /* | ||||
* m_pullup is not required here because ip6_{input|output} | * m_pullup is not required here because ip6_{input|output} | ||||
* already do the heavy lifting for us. | * already do the heavy lifting for us. | ||||
*/ | */ | ||||
ip6 = mtod(*m, struct ip6_hdr *); | ip6 = mtod(*m, struct ip6_hdr *); | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | if (inp_locally_locked) | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
ret6: | ret6: | ||||
/* Returning 0 ensures pfil will not discard the pkt. */ | /* Returning 0 ensures pfil will not discard the pkt. */ | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif /* #ifdef SIFTR_IPV6 */ | #endif /* #ifdef SIFTR_IPV6 */ | ||||
VNET_DEFINE_STATIC(pfil_hook_t, siftr_inet_hook); | |||||
#define V_siftr_inet_hook VNET(siftr_inet_hook) | |||||
#ifdef INET6 | |||||
VNET_DEFINE_STATIC(pfil_hook_t, siftr_inet6_hook); | |||||
#define V_siftr_inet6_hook VNET(siftr_inet6_hook) | |||||
#endif | |||||
static int | static int | ||||
siftr_pfil(int action) | siftr_pfil(int action) | ||||
{ | { | ||||
struct pfil_head *pfh_inet; | struct pfil_hook_args pha; | ||||
#ifdef SIFTR_IPV6 | struct pfil_link_args pla; | ||||
struct pfil_head *pfh_inet6; | |||||
#endif | pha.pa_version = PFIL_VERSION; | ||||
pha.pa_flags = PFIL_IN | PFIL_OUT; | |||||
pha.pa_modname = "siftr"; | |||||
pha.pa_ruleset = NULL; | |||||
pha.pa_rulname = "default"; | |||||
pla.pa_version = PFIL_VERSION; | |||||
pla.pa_flags = PFIL_IN | PFIL_OUT | | |||||
PFIL_HEADPTR | PFIL_HOOKPTR; | |||||
VNET_ITERATOR_DECL(vnet_iter); | VNET_ITERATOR_DECL(vnet_iter); | ||||
VNET_LIST_RLOCK(); | VNET_LIST_RLOCK(); | ||||
VNET_FOREACH(vnet_iter) { | VNET_FOREACH(vnet_iter) { | ||||
CURVNET_SET(vnet_iter); | CURVNET_SET(vnet_iter); | ||||
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); | |||||
#ifdef SIFTR_IPV6 | |||||
pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); | |||||
#endif | |||||
if (action == HOOK) { | if (action == HOOK) { | ||||
pfil_add_hook(siftr_chkpkt, NULL, | pha.pa_func = siftr_chkpkt; | ||||
PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh_inet); | pha.pa_type = PFIL_TYPE_IP4; | ||||
V_siftr_inet_hook = pfil_add_hook(&pha); | |||||
pla.pa_hook = V_siftr_inet_hook; | |||||
pla.pa_head = V_inet_pfil_head; | |||||
(void)pfil_link(&pla); | |||||
#ifdef SIFTR_IPV6 | #ifdef SIFTR_IPV6 | ||||
pfil_add_hook(siftr_chkpkt6, NULL, | pha.pa_func = siftr_chkpkt6; | ||||
PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh_inet6); | pha.pa_type = PFIL_TYPE_IP6; | ||||
V_siftr_inet6_hook = pfil_add_hook(&pha); | |||||
pla.pa_hook = V_siftr_inet6_hook; | |||||
pla.pa_head = V_inet6_pfil_head; | |||||
(void)pfil_link(&pla); | |||||
#endif | #endif | ||||
} else if (action == UNHOOK) { | } else if (action == UNHOOK) { | ||||
pfil_remove_hook(siftr_chkpkt, NULL, | pfil_remove_hook(V_siftr_inet_hook); | ||||
PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh_inet); | |||||
#ifdef SIFTR_IPV6 | #ifdef SIFTR_IPV6 | ||||
pfil_remove_hook(siftr_chkpkt6, NULL, | pfil_remove_hook(V_siftr_inet6_hook); | ||||
PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh_inet6); | |||||
#endif | #endif | ||||
} | } | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
VNET_LIST_RUNLOCK(); | VNET_LIST_RUNLOCK(); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 417 Lines • Show Last 20 Lines |