ip_fw_pfil.c revision 200580
11541Srgrimes/*- 21541Srgrimes * Copyright (c) 2004 Andre Oppermann, Internet Business Solutions AG 31541Srgrimes * All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 141541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241541Srgrimes * SUCH DAMAGE. 251541Srgrimes */ 261541Srgrimes 271541Srgrimes#include <sys/cdefs.h> 281541Srgrimes__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_pfil.c 200580 2009-12-15 16:15:14Z luigi $"); 291541Srgrimes 301541Srgrimes#if !defined(KLD_MODULE) 311541Srgrimes#include "opt_ipfw.h" 321541Srgrimes#include "opt_ipdn.h" 331541Srgrimes#include "opt_inet.h" 3450477Speter#ifndef INET 351541Srgrimes#error IPFIREWALL requires INET. 361541Srgrimes#endif /* INET */ 3732358Seivind#endif /* KLD_MODULE */ 3816333Sgpalmer#include "opt_inet6.h" 3941793Sluigi 4030966Sjoerg#include <sys/param.h> 4134746Speter#include <sys/systm.h> 4250561Sdes#include <sys/malloc.h> 4355009Sshin#include <sys/mbuf.h> 44101095Srwatson#include <sys/module.h> 4564060Sdarrenr#include <sys/kernel.h> 4677574Skris#include <sys/lock.h> 4716333Sgpalmer#include <sys/rwlock.h> 481541Srgrimes#include <sys/socket.h> 491541Srgrimes#include <sys/socketvar.h> 50101095Srwatson#include <sys/sysctl.h> 511541Srgrimes#include <sys/ucred.h> 5241793Sluigi 531541Srgrimes#include <net/if.h> 541541Srgrimes#include <net/route.h> 551541Srgrimes#include <net/pfil.h> 561541Srgrimes#include <net/vnet.h> 571541Srgrimes 587091Swollman#include <netinet/in.h> 597090Sbde#include <netinet/in_systm.h> 601541Srgrimes#include <netinet/ip.h> 6164075Sache#include <netinet/ip_var.h> 621541Srgrimes#include <netinet/ip_fw.h> 6383934Sbrooks#include <netinet/ipfw/ip_fw_private.h> 6430948Sjulian#include <netinet/ip_divert.h> 6519622Sfenner#include <netinet/ip_dummynet.h> 661541Srgrimes 678426Swollman#include <netgraph/ng_ipfw.h> 681541Srgrimes 691541Srgrimes#include <machine/in_cksum.h> 701541Srgrimes 717090SbdeVNET_DEFINE(int, fw_enable) = 1; 721541Srgrimes#ifdef INET6 731541SrgrimesVNET_DEFINE(int, fw6_enable) = 1; 741541Srgrimes#endif 751541Srgrimes 7618797Swollmanint ipfw_chg_hook(SYSCTL_HANDLER_ARGS); 771541Srgrimes 782531Swollman/* Divert hooks. */ 7915680Sgpalmerip_divert_packet_t *ip_divert_ptr = NULL; 8015680Sgpalmer 8184516Sps/* ng_ipfw hooks. */ 8215680Sgpalmerng_ipfw_input_t *ng_ipfw_input_p = NULL; 8355009Sshin 8455009Sshin/* Forward declarations. */ 8555009Sshinstatic int ipfw_divert(struct mbuf **, int, int); 8655009Sshin#define DIV_DIR_IN 1 8755009Sshin#define DIV_DIR_OUT 0 88105199Ssam 89105199Ssamint 90105199Ssamipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, 91105199Ssam struct inpcb *inp) 92105199Ssam{ 939209Swollman struct ip_fw_args args; 942531Swollman struct ng_ipfw_tag *ng_tag; 9536192Sdg struct m_tag *dn_tag; 9612296Sphk int ipfw = 0; 9746381Sbillf int divert; 9812296Sphk int tee; 9913266Swollman#ifdef IPFIREWALL_FORWARD 10012296Sphk struct m_tag *fwd_tag; 10146381Sbillf#endif 10212296Sphk 1031541Srgrimes KASSERT(dir == PFIL_IN, ("ipfw_check_in wrong direction!")); 10412296Sphk 10546381Sbillf bzero(&args, sizeof(args)); 10612296Sphk 10712296Sphk ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, 10812296Sphk NULL); 10946381Sbillf if (ng_tag != NULL) { 11033440Sguido KASSERT(ng_tag->dir == NG_IPFW_IN, 11133440Sguido ("ng_ipfw tag with wrong direction")); 11246381Sbillf args.rule = ng_tag->rule; 11346381Sbillf args.rule_id = ng_tag->rule_id; 11446381Sbillf args.chain_id = ng_tag->chain_id; 11555009Sshin m_tag_delete(*m0, (struct m_tag *)ng_tag); 11655009Sshin } 11755009Sshin 11855009Sshinagain: 11955009Sshin dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); 12055009Sshin if (dn_tag != NULL){ 121109843Ssilby struct dn_pkt_tag *dt; 122109843Ssilby 12377665Sjesper dt = (struct dn_pkt_tag *)(dn_tag+1); 124109843Ssilby args.rule = dt->rule; 12577665Sjesper args.rule_id = dt->rule_id; 12677665Sjesper args.chain_id = dt->chain_id; 127111244Ssilby 128111244Ssilby m_tag_delete(*m0, dn_tag); 129111244Ssilby } 130111244Ssilby 131111244Ssilby args.m = *m0; 132107081Ssilby args.inp = inp; 133107081Ssilby tee = 0; 134107081Ssilby 135107081Ssilby if (V_fw_one_pass == 0 || args.rule == NULL) { 136107081Ssilby ipfw = ipfw_chk(&args); 13773399Struckman *m0 = args.m; 13873399Struckman } else 13973399Struckman ipfw = IP_FW_PASS; 14073791Struckman 14173399Struckman KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", 14273626Struckman __func__)); 14373791Struckman 14473791Struckman switch (ipfw) { 14573626Struckman case IP_FW_PASS: 14673626Struckman if (args.next_hop == NULL) 14773626Struckman goto pass; 14873626Struckman 14973399Struckman#ifdef IPFIREWALL_FORWARD 15073357Sjlemon fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, 15173357Sjlemon sizeof(struct sockaddr_in), M_NOWAIT); 15273357Sjlemon if (fwd_tag == NULL) 15373357Sjlemon goto drop; 1541541Srgrimes bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); 15512296Sphk m_tag_prepend(*m0, fwd_tag); 1561541Srgrimes 157120386Ssam if (in_localip(args.next_hop->sin_addr)) 158120386Ssam (*m0)->m_flags |= M_FASTFWD_OURS; 159120386Ssam goto pass; 1601541Srgrimes#endif 161111888Sjlemon break; /* not reached */ 16284102Sjlemon 16384102Sjlemon case IP_FW_DENY: 1641541Srgrimes goto drop; 16582884Sjulian break; /* not reached */ 1661541Srgrimes 16784102Sjlemon case IP_FW_DUMMYNET: 16884102Sjlemon if (ip_dn_io_ptr == NULL) 16984102Sjlemon goto drop; 17084102Sjlemon if (mtod(*m0, struct ip *)->ip_v == 4) 17147546Sdg ip_dn_io_ptr(m0, DN_TO_IP_IN, &args); 17246381Sbillf else if (mtod(*m0, struct ip *)->ip_v == 6) 17312296Sphk ip_dn_io_ptr(m0, DN_TO_IP6_IN, &args); 17446381Sbillf if (*m0 != NULL) 1751541Srgrimes goto again; 1762112Swollman return 0; /* packet consumed */ 17778667Sru 17846381Sbillf case IP_FW_TEE: 1792112Swollman tee = 1; 18029480Sache /* fall through */ 18129480Sache 18229480Sache case IP_FW_DIVERT: 18329480Sache divert = ipfw_divert(m0, DIV_DIR_IN, tee); 18429480Sache if (divert) { 18543305Sdillon *m0 = NULL; 18629480Sache return 0; /* packet consumed */ 18774362Sphk } else { 188119753Ssam args.rule = NULL; 18929480Sache goto again; /* continue with packet */ 190119753Ssam } 191119753Ssam 192121091Ssam case IP_FW_NGTEE: 193121091Ssam if (!NG_IPFW_LOADED) 194119753Ssam goto drop; 19512296Sphk (void)ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 1); 19612296Sphk goto again; /* continue with packet */ 19746381Sbillf 19812296Sphk case IP_FW_NETGRAPH: 19912296Sphk if (!NG_IPFW_LOADED) 20044219Sdes goto drop; 20144219Sdes return ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 0); 20244219Sdes 20344219Sdes case IP_FW_NAT: 20444219Sdes goto again; /* continue with packet */ 20544219Sdes 20618797Swollman case IP_FW_REASS: 20715026Sphk goto again; 20815026Sphk 20957117Sluigi default: 210107114Sluigi KASSERT(0, ("%s: unknown retval", __func__)); 21114209Sphk } 21284516Sps 21384516Spsdrop: 21441793Sluigi if (*m0) 215121093Ssam m_freem(*m0); 216121093Ssam *m0 = NULL; 217121093Ssam return (EACCES); 218121093Ssampass: 219121093Ssam return 0; /* not filtered */ 220121093Ssam} 221121093Ssam 22222531Sdarrenrint 223121093Ssamipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, 224121093Ssam struct inpcb *inp) 225121093Ssam{ 226121093Ssam struct ip_fw_args args; 227121093Ssam struct ng_ipfw_tag *ng_tag; 228121093Ssam struct m_tag *dn_tag; 22914209Sphk int ipfw = 0; 230121093Ssam int divert; 231121093Ssam int tee; 232121093Ssam#ifdef IPFIREWALL_FORWARD 233121093Ssam struct m_tag *fwd_tag; 234121093Ssam#endif 235121093Ssam 236121119Ssam KASSERT(dir == PFIL_OUT, ("ipfw_check_out wrong direction!")); 237121093Ssam 238121093Ssam bzero(&args, sizeof(args)); 239121093Ssam 240121093Ssam ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, 241121093Ssam NULL); 242121093Ssam if (ng_tag != NULL) { 243121119Ssam KASSERT(ng_tag->dir == NG_IPFW_OUT, 244121093Ssam ("ng_ipfw tag with wrong direction")); 245121093Ssam args.rule = ng_tag->rule; 246121093Ssam args.rule_id = ng_tag->rule_id; 247121093Ssam args.chain_id = ng_tag->chain_id; 248121119Ssam m_tag_delete(*m0, (struct m_tag *)ng_tag); 249121093Ssam } 250121093Ssam 25198701Sluigiagain: 25298701Sluigi dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); 25398701Sluigi if (dn_tag != NULL) { 25498701Sluigi struct dn_pkt_tag *dt; 25598701Sluigi 25698701Sluigi dt = (struct dn_pkt_tag *)(dn_tag+1); 2571541Srgrimes args.rule = dt->rule; 2581541Srgrimes args.rule_id = dt->rule_id; 2591541Srgrimes args.chain_id = dt->chain_id; 2601541Srgrimes 2611541Srgrimes m_tag_delete(*m0, dn_tag); 2621541Srgrimes } 26312296Sphk 2641541Srgrimes args.m = *m0; 2651541Srgrimes args.oif = ifp; 2661541Srgrimes args.inp = inp; 2671541Srgrimes tee = 0; 2681541Srgrimes 2691541Srgrimes if (V_fw_one_pass == 0 || args.rule == NULL) { 2701541Srgrimes ipfw = ipfw_chk(&args); 27192723Salfred *m0 = args.m; 27298613Sluigi } else 27398613Sluigi ipfw = IP_FW_PASS; 274121093Ssam 27598613Sluigi KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", 27692723Salfred __func__)); 27798613Sluigi 27898613Sluigi switch (ipfw) { 27917072Sjulian case IP_FW_PASS: 2801541Srgrimes if (args.next_hop == NULL) 2811541Srgrimes goto pass; 2821541Srgrimes#ifdef IPFIREWALL_FORWARD 2831541Srgrimes /* Overwrite existing tag. */ 2841541Srgrimes fwd_tag = m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL); 2851541Srgrimes if (fwd_tag == NULL) { 2861541Srgrimes fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, 28782884Sjulian sizeof(struct sockaddr_in), M_NOWAIT); 2881541Srgrimes if (fwd_tag == NULL) 2891541Srgrimes goto drop; 29020407Swollman } else 29184102Sjlemon m_tag_unlink(*m0, fwd_tag); 29282884Sjulian bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); 2931541Srgrimes m_tag_prepend(*m0, fwd_tag); 2941541Srgrimes 2951541Srgrimes if (in_localip(args.next_hop->sin_addr)) 2961541Srgrimes (*m0)->m_flags |= M_FASTFWD_OURS; 29782884Sjulian goto pass; 29882884Sjulian#endif 2991541Srgrimes break; /* not reached */ 3001541Srgrimes 3011541Srgrimes case IP_FW_DENY: 30229480Sache goto drop; 303120386Ssam break; /* not reached */ 304120386Ssam 305120386Ssam case IP_FW_DUMMYNET: 306120386Ssam if (ip_dn_io_ptr == NULL) 307120386Ssam break; 308120386Ssam if (mtod(*m0, struct ip *)->ip_v == 4) 309120386Ssam ip_dn_io_ptr(m0, DN_TO_IP_OUT, &args); 310120386Ssam else if (mtod(*m0, struct ip *)->ip_v == 6) 311119753Ssam ip_dn_io_ptr(m0, DN_TO_IP6_OUT, &args); 31229480Sache if (*m0 != NULL) 31374362Sphk goto again; 31429480Sache return 0; /* packet consumed */ 315121093Ssam 316121093Ssam break; 317121093Ssam 318111244Ssilby case IP_FW_TEE: 319111244Ssilby tee = 1; 32029480Sache /* fall through */ 32177574Skris 32234961Sphk case IP_FW_DIVERT: 32377574Skris divert = ipfw_divert(m0, DIV_DIR_OUT, tee); 3241541Srgrimes if (divert) { 32593818Sjhb *m0 = NULL; 326111888Sjlemon return 0; /* packet consumed */ 3271541Srgrimes } else { 3281541Srgrimes args.rule = NULL; 32998701Sluigi goto again; /* continue with packet */ 330121093Ssam } 33198701Sluigi 332121093Ssam case IP_FW_NGTEE: 333121093Ssam if (!NG_IPFW_LOADED) 334121093Ssam goto drop; 335121093Ssam (void)ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 1); 3361541Srgrimes goto again; /* continue with packet */ 337121093Ssam 338121093Ssam case IP_FW_NETGRAPH: 339121093Ssam if (!NG_IPFW_LOADED) 340121093Ssam goto drop; 341121093Ssam return ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 0); 342121093Ssam 343121093Ssam case IP_FW_NAT: 344121093Ssam goto again; /* continue with packet */ 345121093Ssam 3461541Srgrimes case IP_FW_REASS: 3471541Srgrimes goto again; 3481541Srgrimes 3491541Srgrimes default: 35013929Swollman KASSERT(0, ("%s: unknown retval", __func__)); 35113929Swollman } 3521541Srgrimes 35315026Sphkdrop: 35415026Sphk if (*m0) 35567334Sjoe m_freem(*m0); 35684102Sjlemon *m0 = NULL; 35773399Struckman return (EACCES); 35822333Sbrianpass: 35973172Sjlemon return 0; /* not filtered */ 36054175Sarchie} 36198613Sluigi 362121093Ssamstatic int 363121141Ssamipfw_divert(struct mbuf **m, int incoming, int tee) 364121141Ssam{ 365121141Ssam /* 366121141Ssam * ipfw_chk() has already tagged the packet with the divert tag. 367105199Ssam * If tee is set, copy packet and return original. 368105199Ssam * If not tee, consume packet and send it to divert socket. 369105199Ssam */ 370105199Ssam struct mbuf *clone, *reass; 371105199Ssam struct ip *ip; 372105199Ssam int hlen; 3731541Srgrimes 37498613Sluigi reass = NULL; 37598613Sluigi 37698613Sluigi /* Is divert module loaded? */ 37798613Sluigi if (ip_divert_ptr == NULL) 37898613Sluigi goto nodivert; 37954175Sarchie 38098666Sluigi /* Cloning needed for tee? */ 38198666Sluigi if (tee) 382105194Ssam clone = m_dup(*m, M_DONTWAIT); 38398613Sluigi else 38498613Sluigi clone = *m; 385105194Ssam 38698613Sluigi /* In case m_dup was unable to allocate mbufs. */ 38741793Sluigi if (clone == NULL) 38898613Sluigi goto teeout; 38998613Sluigi 39098613Sluigi /* 39198613Sluigi * Divert listeners can only handle non-fragmented packets. 39298613Sluigi * However when tee is set we will *not* de-fragment the packets; 39398904Smux * Doing do would put the reassembly into double-jeopardy. On top 39498613Sluigi * of that someone doing a tee will probably want to get the packet 39598613Sluigi * in its original form. 39698613Sluigi */ 39798613Sluigi ip = mtod(clone, struct ip *); 39898613Sluigi if (!tee && ip->ip_off & (IP_MF | IP_OFFMASK)) { 39998613Sluigi 40098666Sluigi /* Reassemble packet. */ 40198613Sluigi reass = ip_reass(clone); 402113255Sdes 40397074Sarr /* 40498613Sluigi * IP header checksum fixup after reassembly and leave header 40598613Sluigi * in network byte order. 406105586Sphk */ 40798613Sluigi if (reass != NULL) { 40898613Sluigi ip = mtod(reass, struct ip *); 40998613Sluigi hlen = ip->ip_hl << 2; 4101541Srgrimes ip->ip_len = htons(ip->ip_len); 41118797Swollman ip->ip_off = htons(ip->ip_off); 41218797Swollman ip->ip_sum = 0; 41318797Swollman if (hlen == sizeof(struct ip)) 41418797Swollman ip->ip_sum = in_cksum_hdr(ip); 4151541Srgrimes else 4161541Srgrimes ip->ip_sum = in_cksum(reass, hlen); 4171541Srgrimes clone = reass; 41813929Swollman } else 4191541Srgrimes clone = NULL; 4201541Srgrimes } else { 42118797Swollman /* Convert header to network byte order. */ 422105586Sphk ip->ip_len = htons(ip->ip_len); 4231541Srgrimes ip->ip_off = htons(ip->ip_off); 4241541Srgrimes } 4251541Srgrimes 42618797Swollman /* Do the dirty job... */ 427105586Sphk if (clone && ip_divert_ptr != NULL) 4281541Srgrimes ip_divert_ptr(clone, incoming); 4291541Srgrimes 4301541Srgrimesteeout: 4311541Srgrimes /* 4321541Srgrimes * For tee we leave the divert tag attached to original packet. 4331541Srgrimes * It will then continue rule evaluation after the tee rule. 4341541Srgrimes */ 43513929Swollman if (tee) 4361541Srgrimes return 0; 4371541Srgrimes 4381541Srgrimes /* Packet diverted and consumed */ 43978064Sume return 1; 44078064Sume 44178064Sumenodivert: 44278064Sume m_freem(*m); 44378064Sume return 1; 44478064Sume} 44578064Sume 44678064Sumeint 44778064Sumeipfw_hook(void) 44878064Sume{ 44958698Sjlemon struct pfil_head *pfh_inet; 45058698Sjlemon 45118797Swollman pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 45258698Sjlemon if (pfh_inet == NULL) 45358698Sjlemon return ENOENT; 45458698Sjlemon 45558698Sjlemon (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, 45658698Sjlemon pfh_inet); 45718797Swollman (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, 45822333Sbrian pfh_inet); 4591541Srgrimes 4601541Srgrimes return 0; 4611541Srgrimes} 4621541Srgrimes 4631541Srgrimesint 4641541Srgrimesipfw_unhook(void) 4651541Srgrimes{ 46690868Smike struct pfil_head *pfh_inet; 4671541Srgrimes 4681541Srgrimes pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 4691541Srgrimes if (pfh_inet == NULL) 4701541Srgrimes return ENOENT; 47190868Smike 4721541Srgrimes (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, 4731541Srgrimes pfh_inet); 4741541Srgrimes (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, 4751541Srgrimes pfh_inet); 4761541Srgrimes 4771541Srgrimes return 0; 4781541Srgrimes} 4791541Srgrimes 48018797Swollman#ifdef INET6 4811541Srgrimesint 4821541Srgrimesipfw6_hook(void) 4831541Srgrimes{ 4841541Srgrimes struct pfil_head *pfh_inet6; 4851541Srgrimes 4861541Srgrimes pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 4871541Srgrimes if (pfh_inet6 == NULL) 4881541Srgrimes return ENOENT; 4891541Srgrimes 4901541Srgrimes (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, 491111275Ssam pfh_inet6); 492111275Ssam (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, 493111275Ssam pfh_inet6); 494111275Ssam 495111275Ssam return 0; 496111275Ssam} 497111275Ssam 498117897Ssamint 499117897Ssamipfw6_unhook(void) 500117897Ssam{ 501117897Ssam struct pfil_head *pfh_inet6; 502117897Ssam 503117897Ssam pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 504117897Ssam if (pfh_inet6 == NULL) 50573626Struckman return ENOENT; 50673626Struckman 5075543Sugen (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, 5085543Sugen pfh_inet6); 5095543Sugen (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, 5105543Sugen pfh_inet6); 51117072Sjulian 51217758Ssos return 0; 51341793Sluigi} 5145543Sugen#endif /* INET6 */ 5155543Sugen 5165543Sugenint 51741793Sluigiipfw_chg_hook(SYSCTL_HANDLER_ARGS) 51841793Sluigi{ 51964060Sdarrenr int enable; 52064060Sdarrenr int oldenable; 52124590Sdarrenr int error; 522120386Ssam 523121141Ssam if (arg1 == &VNET_NAME(fw_enable)) { 524121141Ssam enable = V_fw_enable; 525121141Ssam } 526121141Ssam#ifdef INET6 52724590Sdarrenr else if (arg1 == &VNET_NAME(fw6_enable)) { 528121141Ssam enable = V_fw6_enable; 529120386Ssam } 530120386Ssam#endif 531120386Ssam else 532120386Ssam return (EINVAL); 533120386Ssam 534120386Ssam oldenable = enable; 535121141Ssam 53664060Sdarrenr error = sysctl_handle_int(oidp, &enable, 0, req); 5371541Srgrimes 53886047Sluigi if (error) 53937409Sjulian return (error); 54037409Sjulian 54137409Sjulian enable = (enable) ? 1 : 0; 54237409Sjulian 54398613Sluigi if (enable == oldenable) 54437409Sjulian return (0); 54598613Sluigi 54698613Sluigi if (arg1 == &VNET_NAME(fw_enable)) { 54798613Sluigi if (enable) 54898613Sluigi error = ipfw_hook(); 54998613Sluigi else 55096245Sluigi error = ipfw_unhook(); 55187915Sjlemon if (error) 55287915Sjlemon return (error); 55387915Sjlemon V_fw_enable = enable; 55471909Sluigi } 55596245Sluigi#ifdef INET6 55698613Sluigi else if (arg1 == &VNET_NAME(fw6_enable)) { 55754175Sarchie if (enable) 55886047Sluigi error = ipfw6_hook(); 55998666Sluigi else 56098666Sluigi error = ipfw6_unhook(); 56154175Sarchie if (error) 56241793Sluigi return (error); 56326359Sjulian V_fw6_enable = enable; 56454175Sarchie } 56554175Sarchie#endif 56654175Sarchie 56726359Sjulian return (0); 56826359Sjulian} 56941793Sluigi 57098613Sluigi