Always create ipfw(4) hooks as long as module is loaded.

Now enabling ipfw(4) with sysctls controls only linkage of hooks to default
heads. When module is loaded fetch sysctls as tunables, to make it possible
to boot with ipfw(4) in kernel, but not linked to any pfil(9) hooks.
This commit is contained in:
Gleb Smirnoff 2019-03-21 16:15:29 +00:00
parent 481572a998
commit 97245d4074
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345381
3 changed files with 81 additions and 41 deletions

View File

@ -3360,7 +3360,7 @@ vnet_ipfw_init(const void *unused)
* is checked on each packet because there are no pfil hooks.
*/
V_ip_fw_ctl_ptr = ipfw_ctl3;
error = ipfw_attach_hooks(1);
error = ipfw_attach_hooks();
return (error);
}
@ -3380,7 +3380,7 @@ vnet_ipfw_uninit(const void *unused)
* Then grab, release and grab again the WLOCK so we make
* sure the update is propagated and nobody will be in.
*/
(void)ipfw_attach_hooks(0 /* detach */);
ipfw_detach_hooks();
V_ip_fw_ctl_ptr = NULL;
last = IS_DEFAULT_VNET(curvnet) ? 1 : 0;

View File

@ -536,29 +536,23 @@ VNET_DEFINE_STATIC(pfil_hook_t, ipfw_inet6_hook);
VNET_DEFINE_STATIC(pfil_hook_t, ipfw_link_hook);
#define V_ipfw_link_hook VNET(ipfw_link_hook)
static int
ipfw_hook(int onoff, int pf)
static void
ipfw_hook(int pf)
{
struct pfil_hook_args pha;
struct pfil_link_args pla;
pfil_hook_t *h;
pha.pa_version = PFIL_VERSION;
pha.pa_flags = PFIL_IN | PFIL_OUT | PFIL_MEMPTR;
pha.pa_flags = PFIL_IN | PFIL_OUT;
pha.pa_modname = "ipfw";
pha.pa_ruleset = NULL;
pla.pa_version = PFIL_VERSION;
pla.pa_flags = PFIL_IN | PFIL_OUT |
PFIL_HEADPTR | PFIL_HOOKPTR;
switch (pf) {
case AF_INET:
pha.pa_func = ipfw_check_packet;
pha.pa_type = PFIL_TYPE_IP4;
pha.pa_rulname = "default";
h = &V_ipfw_inet_hook;
pla.pa_head = V_inet_pfil_head;
break;
#ifdef INET6
case AF_INET6:
@ -566,55 +560,101 @@ ipfw_hook(int onoff, int pf)
pha.pa_type = PFIL_TYPE_IP6;
pha.pa_rulname = "default6";
h = &V_ipfw_inet6_hook;
pla.pa_head = V_inet6_pfil_head;
break;
#endif
case AF_LINK:
pha.pa_func = ipfw_check_frame;
pha.pa_type = PFIL_TYPE_ETHERNET;
pha.pa_rulname = "default-link";
pha.pa_flags |= PFIL_MEMPTR;
h = &V_ipfw_link_hook;
pla.pa_head = V_link_pfil_head;
break;
}
if (onoff) {
*h = pfil_add_hook(&pha);
pla.pa_hook = *h;
(void)pfil_link(&pla);
} else
if (*h != NULL)
pfil_remove_hook(*h);
*h = pfil_add_hook(&pha);
}
return 0;
static void
ipfw_unhook(int pf)
{
switch (pf) {
case AF_INET:
pfil_remove_hook(V_ipfw_inet_hook);
break;
#ifdef INET6
case AF_INET6:
pfil_remove_hook(V_ipfw_inet6_hook);
break;
#endif
case AF_LINK:
pfil_remove_hook(V_ipfw_link_hook);
break;
}
}
static int
ipfw_link(int pf, bool unlink)
{
struct pfil_link_args pla;
pla.pa_version = PFIL_VERSION;
pla.pa_flags = PFIL_IN | PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR;
if (unlink)
pla.pa_flags |= PFIL_UNLINK;
switch (pf) {
case AF_INET:
pla.pa_head = V_inet_pfil_head;
pla.pa_hook = V_ipfw_inet_hook;
break;
#ifdef INET6
case AF_INET6:
pla.pa_head = V_inet6_pfil_head;
pla.pa_hook = V_ipfw_inet6_hook;
break;
#endif
case AF_LINK:
pla.pa_head = V_link_pfil_head;
pla.pa_hook = V_ipfw_link_hook;
break;
}
return (pfil_link(&pla));
}
int
ipfw_attach_hooks(int arg)
ipfw_attach_hooks(void)
{
int error = 0;
if (arg == 0) /* detach */
ipfw_hook(0, AF_INET);
else if (V_fw_enable && ipfw_hook(1, AF_INET) != 0) {
error = ENOENT; /* see ip_fw_pfil.c::ipfw_hook() */
ipfw_hook(AF_INET);
TUNABLE_INT_FETCH("net.inet.ip.fw.enable", &V_fw_enable);
if (V_fw_enable && (error = ipfw_link(AF_INET, false)) != 0)
printf("ipfw_hook() error\n");
}
#ifdef INET6
if (arg == 0) /* detach */
ipfw_hook(0, AF_INET6);
else if (V_fw6_enable && ipfw_hook(1, AF_INET6) != 0) {
error = ENOENT;
ipfw_hook(AF_INET6);
TUNABLE_INT_FETCH("net.inet6.ip6.fw.enable", &V_fw6_enable);
if (V_fw6_enable && (error = ipfw_link(AF_INET6, false)) != 0)
printf("ipfw6_hook() error\n");
}
#endif
if (arg == 0) /* detach */
ipfw_hook(0, AF_LINK);
else if (V_fwlink_enable && ipfw_hook(1, AF_LINK) != 0) {
error = ENOENT;
ipfw_hook(AF_LINK);
TUNABLE_INT_FETCH("net.link.ether.ipfw", &V_fwlink_enable);
if (V_fwlink_enable && (error = ipfw_link(AF_LINK, false)) != 0)
printf("ipfw_link_hook() error\n");
}
return error;
return (error);
}
void
ipfw_detach_hooks(void)
{
ipfw_unhook(AF_INET);
#ifdef INET6
ipfw_unhook(AF_INET6);
#endif
ipfw_unhook(AF_LINK);
}
int
@ -648,7 +688,7 @@ ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
if (*(int *)arg1 == newval)
return (0);
error = ipfw_hook(newval, af);
error = ipfw_link(af, newval == 0 ? true : false);
if (error)
return (error);
*(int *)arg1 = newval;

View File

@ -151,8 +151,8 @@ int ipfw_chk(struct ip_fw_args *args);
struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *,
u_int32_t, u_int32_t, int);
/* attach (arg = 1) or detach (arg = 0) hooks */
int ipfw_attach_hooks(int);
int ipfw_attach_hooks(void);
void ipfw_detach_hooks(void);
#ifdef NOTYET
void ipfw_nat_destroy(void);
#endif