Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/pf/pf_ioctl.c
Show First 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | |||||
static void pf_clear_srcnodes(struct pf_src_node *); | static void pf_clear_srcnodes(struct pf_src_node *); | ||||
static void pf_kill_srcnodes(struct pfioc_src_node_kill *); | static void pf_kill_srcnodes(struct pfioc_src_node_kill *); | ||||
static void pf_tbladdr_copyout(struct pf_addr_wrap *); | static void pf_tbladdr_copyout(struct pf_addr_wrap *); | ||||
/* | /* | ||||
* Wrapper functions for pfil(9) hooks | * Wrapper functions for pfil(9) hooks | ||||
*/ | */ | ||||
#ifdef INET | #ifdef INET | ||||
static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, | static pfil_return_t pf_check_in(struct mbuf **m, struct ifnet *ifp, | ||||
int dir, int flags, struct inpcb *inp); | int flags, void *ruleset __unused, struct inpcb *inp); | ||||
static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, | static pfil_return_t pf_check_out(struct mbuf **m, struct ifnet *ifp, | ||||
int dir, int flags, struct inpcb *inp); | int flags, void *ruleset __unused, struct inpcb *inp); | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, | static pfil_return_t pf_check6_in(struct mbuf **m, struct ifnet *ifp, | ||||
int dir, int flags, struct inpcb *inp); | int flags, void *ruleset __unused, struct inpcb *inp); | ||||
static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, | static pfil_return_t pf_check6_out(struct mbuf **m, struct ifnet *ifp, | ||||
int dir, int flags, struct inpcb *inp); | int flags, void *ruleset __unused, struct inpcb *inp); | ||||
#endif | #endif | ||||
static int hook_pf(void); | static int hook_pf(void); | ||||
static int dehook_pf(void); | static int dehook_pf(void); | ||||
static int shutdown_pf(void); | static int shutdown_pf(void); | ||||
static int pf_load(void); | static int pf_load(void); | ||||
static void pf_unload(void); | static void pf_unload(void); | ||||
▲ Show 20 Lines • Show All 3,814 Lines • ▼ Show 20 Lines | #endif | ||||
for (int i = 0; i < SCNT_MAX; i++) | for (int i = 0; i < SCNT_MAX; i++) | ||||
counter_u64_free(V_pf_status.scounters[i]); | counter_u64_free(V_pf_status.scounters[i]); | ||||
} while(0); | } while(0); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
static int | static pfil_return_t | ||||
pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags, | pf_check_in(struct mbuf **m, struct ifnet *ifp, int flags, | ||||
struct inpcb *inp) | void *ruleset __unused, struct inpcb *inp) | ||||
{ | { | ||||
int chk; | int chk; | ||||
chk = pf_test(PF_IN, flags, ifp, m, inp); | chk = pf_test(PF_IN, flags, ifp, m, inp); | ||||
if (chk && *m) { | if (chk && *m) { | ||||
m_freem(*m); | m_freem(*m); | ||||
*m = NULL; | *m = NULL; | ||||
} | } | ||||
if (chk != PF_PASS) | return (chk == PF_PASS ? PFIL_PASS : PFIL_DROPPED); | ||||
return (EACCES); | |||||
return (0); | |||||
} | } | ||||
static int | static pfil_return_t | ||||
pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags, | pf_check_out(struct mbuf **m, struct ifnet *ifp, int flags, | ||||
struct inpcb *inp) | void *ruleset __unused, struct inpcb *inp) | ||||
{ | { | ||||
int chk; | int chk; | ||||
chk = pf_test(PF_OUT, flags, ifp, m, inp); | chk = pf_test(PF_OUT, flags, ifp, m, inp); | ||||
if (chk && *m) { | if (chk && *m) { | ||||
m_freem(*m); | m_freem(*m); | ||||
*m = NULL; | *m = NULL; | ||||
} | } | ||||
if (chk != PF_PASS) | return (chk == PF_PASS ? PFIL_PASS : PFIL_DROPPED); | ||||
return (EACCES); | |||||
return (0); | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static int | static pfil_return_t | ||||
pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags, | pf_check6_in(struct mbuf **m, struct ifnet *ifp, int flags, | ||||
struct inpcb *inp) | void *ruleset __unused, struct inpcb *inp) | ||||
{ | { | ||||
int chk; | int chk; | ||||
/* | /* | ||||
* In case of loopback traffic IPv6 uses the real interface in | * In case of loopback traffic IPv6 uses the real interface in | ||||
* order to support scoped addresses. In order to support stateful | * order to support scoped addresses. In order to support stateful | ||||
* filtering we have change this to lo0 as it is the case in IPv4. | * filtering we have change this to lo0 as it is the case in IPv4. | ||||
*/ | */ | ||||
CURVNET_SET(ifp->if_vnet); | CURVNET_SET(ifp->if_vnet); | ||||
chk = pf_test6(PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp, m, inp); | chk = pf_test6(PF_IN, flags, (*m)->m_flags & M_LOOP ? V_loif : ifp, m, inp); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
if (chk && *m) { | if (chk && *m) { | ||||
m_freem(*m); | m_freem(*m); | ||||
*m = NULL; | *m = NULL; | ||||
} | } | ||||
if (chk != PF_PASS) | |||||
return (EACCES); | return (chk == PF_PASS ? PFIL_PASS : PFIL_DROPPED); | ||||
return (0); | |||||
} | } | ||||
static int | static pfil_return_t | ||||
pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir, int flags, | pf_check6_out(struct mbuf **m, struct ifnet *ifp, int flags, | ||||
struct inpcb *inp) | void *ruleset __unused, struct inpcb *inp) | ||||
{ | { | ||||
int chk; | int chk; | ||||
CURVNET_SET(ifp->if_vnet); | CURVNET_SET(ifp->if_vnet); | ||||
chk = pf_test6(PF_OUT, flags, ifp, m, inp); | chk = pf_test6(PF_OUT, flags, ifp, m, inp); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
if (chk && *m) { | if (chk && *m) { | ||||
m_freem(*m); | m_freem(*m); | ||||
*m = NULL; | *m = NULL; | ||||
} | } | ||||
if (chk != PF_PASS) | |||||
return (EACCES); | return (chk == PF_PASS ? PFIL_PASS : PFIL_DROPPED); | ||||
return (0); | |||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
static int | |||||
hook_pf(void) | |||||
{ | |||||
#ifdef INET | #ifdef INET | ||||
struct pfil_head *pfh_inet; | VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_in_hook); | ||||
VNET_DEFINE_STATIC(pfil_hook_t, pf_ip4_out_hook); | |||||
#define V_pf_ip4_in_hook VNET(pf_ip4_in_hook) | |||||
#define V_pf_ip4_out_hook VNET(pf_ip4_out_hook) | |||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct pfil_head *pfh_inet6; | VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_in_hook); | ||||
VNET_DEFINE_STATIC(pfil_hook_t, pf_ip6_out_hook); | |||||
#define V_pf_ip6_in_hook VNET(pf_ip6_in_hook) | |||||
#define V_pf_ip6_out_hook VNET(pf_ip6_out_hook) | |||||
#endif | #endif | ||||
static int | |||||
hook_pf(void) | |||||
{ | |||||
struct pfil_hook_args pha; | |||||
struct pfil_link_args pla; | |||||
if (V_pf_pfil_hooked) | if (V_pf_pfil_hooked) | ||||
return (0); | return (0); | ||||
pha.pa_version = PFIL_VERSION; | |||||
pha.pa_modname = "pf"; | |||||
pha.pa_ruleset = NULL; | |||||
pla.pa_version = PFIL_VERSION; | |||||
#ifdef INET | #ifdef INET | ||||
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); | pha.pa_type = PFIL_TYPE_IP4; | ||||
if (pfh_inet == NULL) | pha.pa_func = pf_check_in; | ||||
return (ESRCH); /* XXX */ | pha.pa_flags = PFIL_IN; | ||||
pfil_add_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); | pha.pa_rulname = "default-in"; | ||||
pfil_add_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); | V_pf_ip4_in_hook = pfil_add_hook(&pha); | ||||
pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR; | |||||
pla.pa_head = V_inet_pfil_head; | |||||
pla.pa_hook = V_pf_ip4_in_hook; | |||||
(void)pfil_link(&pla); | |||||
pha.pa_func = pf_check_out; | |||||
pha.pa_flags = PFIL_OUT; | |||||
pha.pa_rulname = "default-out"; | |||||
V_pf_ip4_out_hook = pfil_add_hook(&pha); | |||||
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR; | |||||
pla.pa_head = V_inet_pfil_head; | |||||
pla.pa_hook = V_pf_ip4_out_hook; | |||||
(void)pfil_link(&pla); | |||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); | pha.pa_type = PFIL_TYPE_IP6; | ||||
if (pfh_inet6 == NULL) { | pha.pa_func = pf_check6_in; | ||||
#ifdef INET | pha.pa_flags = PFIL_IN; | ||||
pfil_remove_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, | pha.pa_rulname = "default-in6"; | ||||
pfh_inet); | V_pf_ip6_in_hook = pfil_add_hook(&pha); | ||||
pfil_remove_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, | pla.pa_flags = PFIL_IN | PFIL_HEADPTR | PFIL_HOOKPTR; | ||||
pfh_inet); | pla.pa_head = V_inet6_pfil_head; | ||||
pla.pa_hook = V_pf_ip6_in_hook; | |||||
(void)pfil_link(&pla); | |||||
pha.pa_func = pf_check6_out; | |||||
pha.pa_rulname = "default-out6"; | |||||
pha.pa_flags = PFIL_OUT; | |||||
V_pf_ip6_out_hook = pfil_add_hook(&pha); | |||||
pla.pa_flags = PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR; | |||||
pla.pa_head = V_inet6_pfil_head; | |||||
pla.pa_hook = V_pf_ip6_out_hook; | |||||
(void)pfil_link(&pla); | |||||
#endif | #endif | ||||
return (ESRCH); /* XXX */ | |||||
} | |||||
pfil_add_hook_flags(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); | |||||
pfil_add_hook_flags(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); | |||||
#endif | |||||
V_pf_pfil_hooked = 1; | V_pf_pfil_hooked = 1; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
dehook_pf(void) | dehook_pf(void) | ||||
{ | { | ||||
#ifdef INET | |||||
struct pfil_head *pfh_inet; | |||||
#endif | |||||
#ifdef INET6 | |||||
struct pfil_head *pfh_inet6; | |||||
#endif | |||||
if (V_pf_pfil_hooked == 0) | if (V_pf_pfil_hooked == 0) | ||||
return (0); | return (0); | ||||
#ifdef INET | #ifdef INET | ||||
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); | pfil_remove_hook(V_pf_ip4_in_hook); | ||||
if (pfh_inet == NULL) | pfil_remove_hook(V_pf_ip4_out_hook); | ||||
return (ESRCH); /* XXX */ | |||||
pfil_remove_hook_flags(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, | |||||
pfh_inet); | |||||
pfil_remove_hook_flags(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, | |||||
pfh_inet); | |||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); | pfil_remove_hook(V_pf_ip6_in_hook); | ||||
if (pfh_inet6 == NULL) | pfil_remove_hook(V_pf_ip6_out_hook); | ||||
return (ESRCH); /* XXX */ | |||||
pfil_remove_hook_flags(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, | |||||
pfh_inet6); | |||||
pfil_remove_hook_flags(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, | |||||
pfh_inet6); | |||||
#endif | #endif | ||||
V_pf_pfil_hooked = 0; | V_pf_pfil_hooked = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
pf_load_vnet(void) | pf_load_vnet(void) | ||||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |