ip_fw_pfil.c revision 173399
1139823Simp/*- 2133920Sandre * Copyright (c) 2004 Andre Oppermann, Internet Business Solutions AG 3133920Sandre * All rights reserved. 4133920Sandre * 5133920Sandre * Redistribution and use in source and binary forms, with or without 6133920Sandre * modification, are permitted provided that the following conditions 7133920Sandre * are met: 8133920Sandre * 1. Redistributions of source code must retain the above copyright 9133920Sandre * notice, this list of conditions and the following disclaimer. 10133920Sandre * 2. Redistributions in binary form must reproduce the above copyright 11133920Sandre * notice, this list of conditions and the following disclaimer in the 12133920Sandre * documentation and/or other materials provided with the distribution. 13133920Sandre * 14133920Sandre * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15133920Sandre * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16133920Sandre * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17133920Sandre * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18133920Sandre * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19133920Sandre * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20133920Sandre * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21133920Sandre * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22133920Sandre * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23133920Sandre * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24133920Sandre * SUCH DAMAGE. 25133920Sandre */ 26133920Sandre 27172467Ssilby#include <sys/cdefs.h> 28172467Ssilby__FBSDID("$FreeBSD: head/sys/netinet/ip_fw_pfil.c 173399 2007-11-06 23:01:42Z oleg $"); 29172467Ssilby 30134346Sru#if !defined(KLD_MODULE) 31133920Sandre#include "opt_ipfw.h" 32133920Sandre#include "opt_ipdn.h" 33133920Sandre#include "opt_inet.h" 34133920Sandre#ifndef INET 35133920Sandre#error IPFIREWALL requires INET. 36133920Sandre#endif /* INET */ 37134383Sandre#endif /* KLD_MODULE */ 38152928Sume#include "opt_inet6.h" 39133920Sandre 40133920Sandre#include <sys/param.h> 41133920Sandre#include <sys/systm.h> 42133920Sandre#include <sys/malloc.h> 43133920Sandre#include <sys/mbuf.h> 44133920Sandre#include <sys/module.h> 45133920Sandre#include <sys/kernel.h> 46133920Sandre#include <sys/socket.h> 47133920Sandre#include <sys/socketvar.h> 48133920Sandre#include <sys/sysctl.h> 49133920Sandre#include <sys/ucred.h> 50133920Sandre 51133920Sandre#include <net/if.h> 52133920Sandre#include <net/route.h> 53133920Sandre#include <net/pfil.h> 54133920Sandre 55133920Sandre#include <netinet/in.h> 56133920Sandre#include <netinet/in_systm.h> 57133920Sandre#include <netinet/in_var.h> 58133920Sandre#include <netinet/ip.h> 59133920Sandre#include <netinet/ip_var.h> 60133920Sandre#include <netinet/ip_fw.h> 61133920Sandre#include <netinet/ip_divert.h> 62133920Sandre#include <netinet/ip_dummynet.h> 63133920Sandre 64141351Sglebius#include <netgraph/ng_ipfw.h> 65141351Sglebius 66133920Sandre#include <machine/in_cksum.h> 67133920Sandre 68158470Smlaierint fw_enable = 1; 69158470Smlaier#ifdef INET6 70158470Smlaierint fw6_enable = 1; 71158470Smlaier#endif 72133920Sandre 73158470Smlaierint ipfw_chg_hook(SYSCTL_HANDLER_ARGS); 74158470Smlaier 75133920Sandre/* Dummynet hooks. */ 76133920Sandreip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL; 77133920Sandre 78136714Sandre/* Divert hooks. */ 79136714Sandreip_divert_packet_t *ip_divert_ptr = NULL; 80136714Sandre 81141351Sglebius/* ng_ipfw hooks. */ 82141351Sglebiusng_ipfw_input_t *ng_ipfw_input_p = NULL; 83141351Sglebius 84136714Sandre/* Forward declarations. */ 85136714Sandrestatic int ipfw_divert(struct mbuf **, int, int); 86133920Sandre#define DIV_DIR_IN 1 87133920Sandre#define DIV_DIR_OUT 0 88133920Sandre 89133920Sandreint 90135920Smlaieripfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, 91135920Smlaier struct inpcb *inp) 92133920Sandre{ 93133920Sandre struct ip_fw_args args; 94141351Sglebius struct ng_ipfw_tag *ng_tag; 95133920Sandre struct m_tag *dn_tag; 96133920Sandre int ipfw = 0; 97133920Sandre int divert; 98140224Sglebius int tee; 99133920Sandre#ifdef IPFIREWALL_FORWARD 100133920Sandre struct m_tag *fwd_tag; 101133920Sandre#endif 102133920Sandre 103133920Sandre KASSERT(dir == PFIL_IN, ("ipfw_check_in wrong direction!")); 104133920Sandre 105133920Sandre bzero(&args, sizeof(args)); 106133920Sandre 107173399Soleg ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, 108173399Soleg NULL); 109173399Soleg if (ng_tag != NULL) { 110173399Soleg KASSERT(ng_tag->dir == NG_IPFW_IN, 111173399Soleg ("ng_ipfw tag with wrong direction")); 112173399Soleg args.rule = ng_tag->rule; 113173399Soleg m_tag_delete(*m0, (struct m_tag *)ng_tag); 114173399Soleg } 115173399Soleg 116173399Solegagain: 117138652Sglebius dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); 118138652Sglebius if (dn_tag != NULL){ 119133920Sandre struct dn_pkt_tag *dt; 120133920Sandre 121133920Sandre dt = (struct dn_pkt_tag *)(dn_tag+1); 122133920Sandre args.rule = dt->rule; 123133920Sandre 124133920Sandre m_tag_delete(*m0, dn_tag); 125133920Sandre } 126133920Sandre 127133920Sandre args.m = *m0; 128135920Smlaier args.inp = inp; 129133920Sandre ipfw = ipfw_chk(&args); 130133920Sandre *m0 = args.m; 131140224Sglebius tee = 0; 132133920Sandre 133140224Sglebius KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", 134140224Sglebius __func__)); 135133920Sandre 136140224Sglebius switch (ipfw) { 137140224Sglebius case IP_FW_PASS: 138140224Sglebius if (args.next_hop == NULL) 139140224Sglebius goto pass; 140133920Sandre 141133920Sandre#ifdef IPFIREWALL_FORWARD 142133920Sandre fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, 143133920Sandre sizeof(struct sockaddr_in), M_NOWAIT); 144133920Sandre if (fwd_tag == NULL) 145133920Sandre goto drop; 146133920Sandre bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); 147133920Sandre m_tag_prepend(*m0, fwd_tag); 148133920Sandre 149133920Sandre if (in_localip(args.next_hop->sin_addr)) 150133920Sandre (*m0)->m_flags |= M_FASTFWD_OURS; 151133920Sandre goto pass; 152133920Sandre#endif 153140224Sglebius break; /* not reached */ 154133920Sandre 155140224Sglebius case IP_FW_DENY: 156140224Sglebius goto drop; 157140224Sglebius break; /* not reached */ 158140224Sglebius 159140224Sglebius case IP_FW_DUMMYNET: 160140224Sglebius if (!DUMMYNET_LOADED) 161140224Sglebius goto drop; 162145246Sbrooks if (mtod(*m0, struct ip *)->ip_v == 4) 163173399Soleg ip_dn_io_ptr(m0, DN_TO_IP_IN, &args); 164145246Sbrooks else if (mtod(*m0, struct ip *)->ip_v == 6) 165173399Soleg ip_dn_io_ptr(m0, DN_TO_IP6_IN, &args); 166173399Soleg if (*m0 != NULL) 167173399Soleg goto again; 168140224Sglebius return 0; /* packet consumed */ 169140224Sglebius 170140224Sglebius case IP_FW_TEE: 171140224Sglebius tee = 1; 172140224Sglebius /* fall through */ 173140224Sglebius 174140224Sglebius case IP_FW_DIVERT: 175140224Sglebius divert = ipfw_divert(m0, DIV_DIR_IN, tee); 176140224Sglebius if (divert) { 177140224Sglebius *m0 = NULL; 178140224Sglebius return 0; /* packet consumed */ 179144712Sglebius } else { 180144712Sglebius args.rule = NULL; 181140224Sglebius goto again; /* continue with packet */ 182144712Sglebius } 183140224Sglebius 184141351Sglebius case IP_FW_NGTEE: 185141351Sglebius if (!NG_IPFW_LOADED) 186141351Sglebius goto drop; 187141351Sglebius (void)ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 1); 188141351Sglebius goto again; /* continue with packet */ 189141351Sglebius 190141351Sglebius case IP_FW_NETGRAPH: 191141351Sglebius if (!NG_IPFW_LOADED) 192141351Sglebius goto drop; 193141351Sglebius return ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 0); 194165648Spiso 195165648Spiso case IP_FW_NAT: 196165648Spiso goto again; /* continue with packet */ 197141351Sglebius 198140224Sglebius default: 199140224Sglebius KASSERT(0, ("%s: unknown retval", __func__)); 200140224Sglebius } 201140224Sglebius 202133920Sandredrop: 203133920Sandre if (*m0) 204133920Sandre m_freem(*m0); 205133920Sandre *m0 = NULL; 206133920Sandre return (EACCES); 207133920Sandrepass: 208133920Sandre return 0; /* not filtered */ 209133920Sandre} 210133920Sandre 211133920Sandreint 212135920Smlaieripfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, 213135920Smlaier struct inpcb *inp) 214133920Sandre{ 215133920Sandre struct ip_fw_args args; 216141351Sglebius struct ng_ipfw_tag *ng_tag; 217133920Sandre struct m_tag *dn_tag; 218133920Sandre int ipfw = 0; 219133920Sandre int divert; 220140224Sglebius int tee; 221133920Sandre#ifdef IPFIREWALL_FORWARD 222133920Sandre struct m_tag *fwd_tag; 223133920Sandre#endif 224133920Sandre 225133920Sandre KASSERT(dir == PFIL_OUT, ("ipfw_check_out wrong direction!")); 226133920Sandre 227133920Sandre bzero(&args, sizeof(args)); 228133920Sandre 229173399Soleg ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, 230173399Soleg NULL); 231173399Soleg if (ng_tag != NULL) { 232173399Soleg KASSERT(ng_tag->dir == NG_IPFW_OUT, 233173399Soleg ("ng_ipfw tag with wrong direction")); 234173399Soleg args.rule = ng_tag->rule; 235173399Soleg m_tag_delete(*m0, (struct m_tag *)ng_tag); 236173399Soleg } 237173399Soleg 238173399Solegagain: 239138652Sglebius dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); 240138652Sglebius if (dn_tag != NULL) { 241133920Sandre struct dn_pkt_tag *dt; 242133920Sandre 243133920Sandre dt = (struct dn_pkt_tag *)(dn_tag+1); 244133920Sandre args.rule = dt->rule; 245133920Sandre 246133920Sandre m_tag_delete(*m0, dn_tag); 247133920Sandre } 248133920Sandre 249133920Sandre args.m = *m0; 250133920Sandre args.oif = ifp; 251135920Smlaier args.inp = inp; 252133920Sandre ipfw = ipfw_chk(&args); 253133920Sandre *m0 = args.m; 254140224Sglebius tee = 0; 255133920Sandre 256140224Sglebius KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", 257140224Sglebius __func__)); 258133920Sandre 259140224Sglebius switch (ipfw) { 260140224Sglebius case IP_FW_PASS: 261140224Sglebius if (args.next_hop == NULL) 262140224Sglebius goto pass; 263133920Sandre#ifdef IPFIREWALL_FORWARD 264133920Sandre /* Overwrite existing tag. */ 265133920Sandre fwd_tag = m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL); 266135167Sandre if (fwd_tag == NULL) { 267133920Sandre fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, 268133920Sandre sizeof(struct sockaddr_in), M_NOWAIT); 269135167Sandre if (fwd_tag == NULL) 270135167Sandre goto drop; 271135167Sandre } else 272135167Sandre m_tag_unlink(*m0, fwd_tag); 273133920Sandre bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); 274133920Sandre m_tag_prepend(*m0, fwd_tag); 275133920Sandre 276133920Sandre if (in_localip(args.next_hop->sin_addr)) 277133920Sandre (*m0)->m_flags |= M_FASTFWD_OURS; 278133920Sandre goto pass; 279133920Sandre#endif 280140224Sglebius break; /* not reached */ 281133920Sandre 282140224Sglebius case IP_FW_DENY: 283140224Sglebius goto drop; 284140224Sglebius break; /* not reached */ 285140224Sglebius 286140224Sglebius case IP_FW_DUMMYNET: 287140224Sglebius if (!DUMMYNET_LOADED) 288140224Sglebius break; 289145246Sbrooks if (mtod(*m0, struct ip *)->ip_v == 4) 290173399Soleg ip_dn_io_ptr(m0, DN_TO_IP_OUT, &args); 291145246Sbrooks else if (mtod(*m0, struct ip *)->ip_v == 6) 292173399Soleg ip_dn_io_ptr(m0, DN_TO_IP6_OUT, &args); 293173399Soleg if (*m0 != NULL) 294173399Soleg goto again; 295140224Sglebius return 0; /* packet consumed */ 296140224Sglebius 297140224Sglebius break; 298140224Sglebius 299140224Sglebius case IP_FW_TEE: 300140224Sglebius tee = 1; 301140224Sglebius /* fall through */ 302140224Sglebius 303140224Sglebius case IP_FW_DIVERT: 304140224Sglebius divert = ipfw_divert(m0, DIV_DIR_OUT, tee); 305140224Sglebius if (divert) { 306140224Sglebius *m0 = NULL; 307140224Sglebius return 0; /* packet consumed */ 308144712Sglebius } else { 309144712Sglebius args.rule = NULL; 310140224Sglebius goto again; /* continue with packet */ 311144712Sglebius } 312140224Sglebius 313141351Sglebius case IP_FW_NGTEE: 314141351Sglebius if (!NG_IPFW_LOADED) 315141351Sglebius goto drop; 316141351Sglebius (void)ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 1); 317141351Sglebius goto again; /* continue with packet */ 318141351Sglebius 319141351Sglebius case IP_FW_NETGRAPH: 320141351Sglebius if (!NG_IPFW_LOADED) 321141351Sglebius goto drop; 322141351Sglebius return ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 0); 323141351Sglebius 324165648Spiso case IP_FW_NAT: 325165648Spiso goto again; /* continue with packet */ 326165648Spiso 327140224Sglebius default: 328140224Sglebius KASSERT(0, ("%s: unknown retval", __func__)); 329140224Sglebius } 330140224Sglebius 331133920Sandredrop: 332133920Sandre if (*m0) 333133920Sandre m_freem(*m0); 334133920Sandre *m0 = NULL; 335133920Sandre return (EACCES); 336133920Sandrepass: 337133920Sandre return 0; /* not filtered */ 338133920Sandre} 339133920Sandre 340133920Sandrestatic int 341133920Sandreipfw_divert(struct mbuf **m, int incoming, int tee) 342133920Sandre{ 343133920Sandre /* 344135154Sandre * ipfw_chk() has already tagged the packet with the divert tag. 345133920Sandre * If tee is set, copy packet and return original. 346133920Sandre * If not tee, consume packet and send it to divert socket. 347133920Sandre */ 348133920Sandre struct mbuf *clone, *reass; 349133920Sandre struct ip *ip; 350133920Sandre int hlen; 351133920Sandre 352133920Sandre reass = NULL; 353133920Sandre 354136714Sandre /* Is divert module loaded? */ 355136714Sandre if (ip_divert_ptr == NULL) 356136714Sandre goto nodivert; 357136714Sandre 358133920Sandre /* Cloning needed for tee? */ 359133920Sandre if (tee) 360133920Sandre clone = m_dup(*m, M_DONTWAIT); 361133920Sandre else 362133920Sandre clone = *m; 363133920Sandre 364133920Sandre /* In case m_dup was unable to allocate mbufs. */ 365133920Sandre if (clone == NULL) 366133920Sandre goto teeout; 367133920Sandre 368133920Sandre /* 369133920Sandre * Divert listeners can only handle non-fragmented packets. 370133920Sandre * However when tee is set we will *not* de-fragment the packets; 371133920Sandre * Doing do would put the reassembly into double-jeopardy. On top 372133920Sandre * of that someone doing a tee will probably want to get the packet 373133920Sandre * in its original form. 374133920Sandre */ 375133920Sandre ip = mtod(clone, struct ip *); 376133920Sandre if (!tee && ip->ip_off & (IP_MF | IP_OFFMASK)) { 377133920Sandre 378133920Sandre /* Reassemble packet. */ 379133920Sandre reass = ip_reass(clone); 380133920Sandre 381133920Sandre /* 382133920Sandre * IP header checksum fixup after reassembly and leave header 383133920Sandre * in network byte order. 384133920Sandre */ 385133920Sandre if (reass != NULL) { 386133920Sandre ip = mtod(reass, struct ip *); 387133920Sandre hlen = ip->ip_hl << 2; 388133920Sandre ip->ip_len = htons(ip->ip_len); 389133920Sandre ip->ip_off = htons(ip->ip_off); 390133920Sandre ip->ip_sum = 0; 391133920Sandre if (hlen == sizeof(struct ip)) 392133920Sandre ip->ip_sum = in_cksum_hdr(ip); 393133920Sandre else 394133920Sandre ip->ip_sum = in_cksum(reass, hlen); 395133920Sandre clone = reass; 396133920Sandre } else 397133920Sandre clone = NULL; 398133920Sandre } else { 399133920Sandre /* Convert header to network byte order. */ 400133920Sandre ip->ip_len = htons(ip->ip_len); 401133920Sandre ip->ip_off = htons(ip->ip_off); 402133920Sandre } 403133920Sandre 404133920Sandre /* Do the dirty job... */ 405136714Sandre if (clone && ip_divert_ptr != NULL) 406136714Sandre ip_divert_ptr(clone, incoming); 407133920Sandre 408133920Sandreteeout: 409135154Sandre /* 410135154Sandre * For tee we leave the divert tag attached to original packet. 411135154Sandre * It will then continue rule evaluation after the tee rule. 412135154Sandre */ 413135154Sandre if (tee) 414135154Sandre return 0; 415133920Sandre 416133920Sandre /* Packet diverted and consumed */ 417133920Sandre return 1; 418136714Sandre 419136714Sandrenodivert: 420133920Sandre m_freem(*m); 421133920Sandre return 1; 422133920Sandre} 423133920Sandre 424133920Sandrestatic int 425133920Sandreipfw_hook(void) 426133920Sandre{ 427133920Sandre struct pfil_head *pfh_inet; 428133920Sandre 429133920Sandre pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 430133920Sandre if (pfh_inet == NULL) 431133920Sandre return ENOENT; 432133920Sandre 433133920Sandre pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); 434133920Sandre pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); 435133920Sandre 436133920Sandre return 0; 437133920Sandre} 438133920Sandre 439133920Sandrestatic int 440133920Sandreipfw_unhook(void) 441133920Sandre{ 442133920Sandre struct pfil_head *pfh_inet; 443133920Sandre 444133920Sandre pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 445133920Sandre if (pfh_inet == NULL) 446133920Sandre return ENOENT; 447158470Smlaier 448158470Smlaier pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); 449158470Smlaier pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); 450158470Smlaier 451158470Smlaier return 0; 452158470Smlaier} 453158470Smlaier 454145246Sbrooks#ifdef INET6 455158470Smlaierstatic int 456158470Smlaieripfw6_hook(void) 457158470Smlaier{ 458158470Smlaier struct pfil_head *pfh_inet6; 459158470Smlaier 460145246Sbrooks pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 461145246Sbrooks if (pfh_inet6 == NULL) 462145246Sbrooks return ENOENT; 463133920Sandre 464158470Smlaier pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); 465158470Smlaier pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); 466158470Smlaier 467158470Smlaier return 0; 468158470Smlaier} 469158470Smlaier 470158470Smlaierstatic int 471158470Smlaieripfw6_unhook(void) 472158470Smlaier{ 473158470Smlaier struct pfil_head *pfh_inet6; 474158470Smlaier 475158470Smlaier pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 476158470Smlaier if (pfh_inet6 == NULL) 477158470Smlaier return ENOENT; 478158470Smlaier 479145246Sbrooks pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); 480145246Sbrooks pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); 481133920Sandre 482133920Sandre return 0; 483133920Sandre} 484158470Smlaier#endif /* INET6 */ 485133920Sandre 486158470Smlaierint 487158470Smlaieripfw_chg_hook(SYSCTL_HANDLER_ARGS) 488158470Smlaier{ 489158470Smlaier int enable = *(int *)arg1; 490158470Smlaier int error; 491158470Smlaier 492158470Smlaier error = sysctl_handle_int(oidp, &enable, 0, req); 493158470Smlaier if (error) 494158470Smlaier return (error); 495158470Smlaier 496158470Smlaier enable = (enable) ? 1 : 0; 497158470Smlaier 498158470Smlaier if (enable == *(int *)arg1) 499158470Smlaier return (0); 500158470Smlaier 501158470Smlaier if (arg1 == &fw_enable) { 502158470Smlaier if (enable) 503158470Smlaier error = ipfw_hook(); 504158470Smlaier else 505158470Smlaier error = ipfw_unhook(); 506158470Smlaier } 507158470Smlaier#ifdef INET6 508158470Smlaier if (arg1 == &fw6_enable) { 509158470Smlaier if (enable) 510158470Smlaier error = ipfw6_hook(); 511158470Smlaier else 512158470Smlaier error = ipfw6_unhook(); 513158470Smlaier } 514158470Smlaier#endif 515158470Smlaier 516158470Smlaier if (error) 517158470Smlaier return (error); 518158470Smlaier 519158470Smlaier *(int *)arg1 = enable; 520158470Smlaier 521158470Smlaier return (0); 522158470Smlaier} 523158470Smlaier 524133920Sandrestatic int 525133920Sandreipfw_modevent(module_t mod, int type, void *unused) 526133920Sandre{ 527133920Sandre int err = 0; 528133920Sandre 529133920Sandre switch (type) { 530133920Sandre case MOD_LOAD: 531158470Smlaier if ((err = ipfw_init()) != 0) { 532158470Smlaier printf("ipfw_init() error\n"); 533158470Smlaier break; 534133920Sandre } 535158470Smlaier if ((err = ipfw_hook()) != 0) { 536158470Smlaier printf("ipfw_hook() error\n"); 537158470Smlaier break; 538158470Smlaier } 539158470Smlaier#ifdef INET6 540158470Smlaier if ((err = ipfw6_hook()) != 0) { 541158470Smlaier printf("ipfw_hook() error\n"); 542158470Smlaier break; 543158470Smlaier } 544158470Smlaier#endif 545133920Sandre break; 546133920Sandre 547133920Sandre case MOD_UNLOAD: 548158470Smlaier if ((err = ipfw_unhook()) > 0) 549158470Smlaier break; 550158470Smlaier#ifdef INET6 551158470Smlaier if ((err = ipfw6_unhook()) > 0) 552158470Smlaier break; 553158470Smlaier#endif 554158470Smlaier ipfw_destroy(); 555133920Sandre break; 556133920Sandre 557133920Sandre default: 558133920Sandre return EOPNOTSUPP; 559133920Sandre break; 560133920Sandre } 561133920Sandre return err; 562133920Sandre} 563133920Sandre 564133920Sandrestatic moduledata_t ipfwmod = { 565133920Sandre "ipfw", 566133920Sandre ipfw_modevent, 567133920Sandre 0 568133920Sandre}; 569133920SandreDECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); 570133920SandreMODULE_VERSION(ipfw, 2); 571