File:  [DragonFly] / src / sys / net / ipfw / Attic / ip_fw.c
Revision 1.9: download - view: text, annotated - select for diffs
Thu Apr 22 04:22:02 2004 UTC (10 years, 8 months ago) by dillon
Branches: MAIN
CVS tags: HEAD, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
M_NOWAIT -> M_WAITOK or M_INTWAIT conversions.  There is a whole lot of net
code that is improperly using M_NOWAIT.  Also remove now unneeded NULL checks
since malloc will panic rather then return NULL when M_NULLOK is not set.

Use M_INTWAIT|M_NULLOK in some cases (such as route table allocation) in
order to allow malloc to return NULL when the limit for the malloc type
is reached.

    1: /*
    2:  * Copyright (c) 1993 Daniel Boulet
    3:  * Copyright (c) 1994 Ugen J.S.Antsilevich
    4:  * Copyright (c) 1996 Alex Nash
    5:  * Copyright (c) 2000-2001 Luigi Rizzo
    6:  *
    7:  * Redistribution and use in source forms, with and without modification,
    8:  * are permitted provided that this entire comment appears intact.
    9:  *
   10:  * Redistribution in binary form may occur without any restrictions.
   11:  * Obviously, it would be nice if you gave credit where credit is due
   12:  * but requiring it would be too onerous.
   13:  *
   14:  * This software is provided ``AS IS'' without any warranties of any kind.
   15:  *
   16:  * $FreeBSD: src/sys/netinet/ip_fw.c,v 1.131.2.39 2003/01/20 02:23:07 iedowse Exp $
   17:  * $DragonFly: src/sys/net/ipfw/ip_fw.c,v 1.9 2004/04/22 04:22:02 dillon Exp $
   18:  */
   19: 
   20: #define        DEB(x)
   21: #define        DDB(x) x
   22: 
   23: /*
   24:  * Implement IP packet firewall
   25:  */
   26: 
   27: #if !defined(KLD_MODULE)
   28: #include "opt_ipfw.h"
   29: #include "opt_ipdn.h"
   30: #include "opt_ipdivert.h"
   31: #include "opt_inet.h"
   32: #ifndef INET
   33: #error IPFIREWALL requires INET.
   34: #endif /* INET */
   35: #endif
   36: 
   37: #if !(IPFW2)
   38: 
   39: #include <sys/param.h>
   40: #include <sys/systm.h>
   41: #include <sys/malloc.h>
   42: #include <sys/mbuf.h>
   43: #include <sys/kernel.h>
   44: #include <sys/proc.h>
   45: #include <sys/socket.h>
   46: #include <sys/socketvar.h>
   47: #include <sys/sysctl.h>
   48: #include <sys/syslog.h>
   49: #include <sys/ucred.h>
   50: #include <net/if.h>
   51: #include <net/route.h>
   52: #include <netinet/in.h>
   53: #include <netinet/in_systm.h>
   54: #include <netinet/in_var.h>
   55: #include <netinet/in_pcb.h>
   56: #include <netinet/ip.h>
   57: #include <netinet/ip_var.h>
   58: #include <netinet/ip_icmp.h>
   59: #include "ip_fw.h"
   60: #include <net/dummynet/ip_dummynet.h>
   61: #include <netinet/tcp.h>
   62: #include <netinet/tcp_timer.h>
   63: #include <netinet/tcp_var.h>
   64: #include <netinet/tcpip.h>
   65: #include <netinet/udp.h>
   66: #include <netinet/udp_var.h>
   67: 
   68: #include <netinet/if_ether.h> /* XXX ethertype_ip */
   69: 
   70: static int fw_debug = 1;
   71: #ifdef IPFIREWALL_VERBOSE
   72: static int fw_verbose = 1;
   73: #else
   74: static int fw_verbose = 0;
   75: #endif
   76: #ifdef IPFIREWALL_VERBOSE_LIMIT
   77: static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
   78: #else
   79: static int fw_verbose_limit = 0;
   80: #endif
   81: 
   82: /*
   83:  * Right now, two fields in the IP header are changed to host format
   84:  * by the IP layer before calling the firewall. Ideally, we would like
   85:  * to have them in network format so that the packet can be
   86:  * used as it comes from the device driver (and is thus readonly).
   87:  */
   88: 
   89: static u_int64_t counter;	/* counter for ipfw_report(NULL...) */
   90: 
   91: #define	IPFW_DEFAULT_RULE	((u_int)(u_short)~0)
   92: 
   93: LIST_HEAD (ip_fw_head, ip_fw) ip_fw_chain_head;
   94: 
   95: MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
   96: 
   97: #ifdef SYSCTL_NODE
   98: SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
   99: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, enable, CTLFLAG_RW,
  100:     &fw_enable, 0, "Enable ipfw");
  101: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO,one_pass,CTLFLAG_RW, 
  102:     &fw_one_pass, 0, 
  103:     "Only do a single pass through ipfw when using dummynet(4)");
  104: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, 
  105:     &fw_debug, 0, "Enable printing of debug ip_fw statements");
  106: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, 
  107:     &fw_verbose, 0, "Log matches to ipfw rules");
  108: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, 
  109:     &fw_verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
  110: 
  111: /*
  112:  * Extension for stateful ipfw.
  113:  *
  114:  * Dynamic rules are stored in lists accessed through a hash table
  115:  * (ipfw_dyn_v) whose size is curr_dyn_buckets. This value can
  116:  * be modified through the sysctl variable dyn_buckets which is
  117:  * updated when the table becomes empty.
  118:  *
  119:  * XXX currently there is only one list, ipfw_dyn.
  120:  *
  121:  * When a packet is received, it is first hashed, then matched
  122:  * against the entries in the corresponding list.
  123:  * Matching occurs according to the rule type. The default is to
  124:  * match the four fields and the protocol, and rules are bidirectional.
  125:  *
  126:  * For a busy proxy/web server we will have lots of connections to
  127:  * the server. We could decide for a rule type where we ignore
  128:  * ports (different hashing) and avoid special SYN/RST/FIN handling.
  129:  *
  130:  * XXX when we decide to support more than one rule type, we should
  131:  * repeat the hashing multiple times uing only the useful fields.
  132:  * Or, we could run the various tests in parallel, because the
  133:  * 'move to front' technique should shorten the average search.
  134:  *
  135:  * The lifetime of dynamic rules is regulated by dyn_*_lifetime,
  136:  * measured in seconds and depending on the flags.
  137:  *
  138:  * The total number of dynamic rules is stored in dyn_count.
  139:  * The max number of dynamic rules is dyn_max. When we reach
  140:  * the maximum number of rules we do not create anymore. This is
  141:  * done to avoid consuming too much memory, but also too much
  142:  * time when searching on each packet (ideally, we should try instead
  143:  * to put a limit on the length of the list on each bucket...).
  144:  *
  145:  * Each dynamic rules holds a pointer to the parent ipfw rule so
  146:  * we know what action to perform. Dynamic rules are removed when
  147:  * the parent rule is deleted.
  148:  * There are some limitations with dynamic rules -- we do not
  149:  * obey the 'randomized match', and we do not do multiple
  150:  * passes through the firewall.
  151:  * XXX check the latter!!!
  152:  */
  153: static struct ipfw_dyn_rule **ipfw_dyn_v = NULL ;
  154: static u_int32_t dyn_buckets = 256 ; /* must be power of 2 */
  155: static u_int32_t curr_dyn_buckets = 256 ; /* must be power of 2 */
  156: 
  157: /*
  158:  * timeouts for various events in handing dynamic rules.
  159:  */
  160: static u_int32_t dyn_ack_lifetime = 300 ;
  161: static u_int32_t dyn_syn_lifetime = 20 ;
  162: static u_int32_t dyn_fin_lifetime = 1 ;
  163: static u_int32_t dyn_rst_lifetime = 1 ;
  164: static u_int32_t dyn_udp_lifetime = 10 ;
  165: static u_int32_t dyn_short_lifetime = 5 ;
  166: 
  167: /*
  168:  * after reaching 0, dynamic rules are considered still valid for
  169:  * an additional grace time, unless there is lack of resources.
  170:  */
  171: static u_int32_t dyn_grace_time = 10 ;
  172: 
  173: static u_int32_t static_count = 0 ;	/* # of static rules */
  174: static u_int32_t dyn_count = 0 ;	/* # of dynamic rules */
  175: static u_int32_t dyn_max = 1000 ;	/* max # of dynamic rules */
  176: 
  177: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets, CTLFLAG_RW,
  178:     &dyn_buckets, 0, "Number of dyn. buckets");
  179: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets, CTLFLAG_RD,
  180:     &curr_dyn_buckets, 0, "Current Number of dyn. buckets");
  181: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_count, CTLFLAG_RD,
  182:     &dyn_count, 0, "Number of dyn. rules");
  183: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_max, CTLFLAG_RW,
  184:     &dyn_max, 0, "Max number of dyn. rules");
  185: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, static_count, CTLFLAG_RD,
  186:     &static_count, 0, "Number of static rules");
  187: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime, CTLFLAG_RW,
  188:     &dyn_ack_lifetime, 0, "Lifetime of dyn. rules for acks");
  189: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_syn_lifetime, CTLFLAG_RW,
  190:     &dyn_syn_lifetime, 0, "Lifetime of dyn. rules for syn");
  191: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_fin_lifetime, CTLFLAG_RW,
  192:     &dyn_fin_lifetime, 0, "Lifetime of dyn. rules for fin");
  193: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_rst_lifetime, CTLFLAG_RW,
  194:     &dyn_rst_lifetime, 0, "Lifetime of dyn. rules for rst");
  195: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_udp_lifetime, CTLFLAG_RW,
  196:     &dyn_udp_lifetime, 0, "Lifetime of dyn. rules for UDP");
  197: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, CTLFLAG_RW,
  198:     &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations");
  199: SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_grace_time, CTLFLAG_RD,
  200:     &dyn_grace_time, 0, "Grace time for dyn. rules");
  201: 
  202: #endif /* SYSCTL_NODE */
  203: 
  204: #define dprintf(a)	do {						\
  205: 				if (fw_debug)				\
  206: 					printf a;			\
  207: 			} while (0)
  208: #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0
  209: 
  210: static int	add_entry (struct ip_fw_head *chainptr, struct ip_fw *frwl);
  211: static int	del_entry (struct ip_fw_head *chainptr, u_short number);
  212: static int	zero_entry (struct ip_fw *, int);
  213: static int	check_ipfw_struct (struct ip_fw *m);
  214: static int	iface_match (struct ifnet *ifp, union ip_fw_if *ifu,
  215: 				 int byname);
  216: static int	ipopts_match (struct ip *ip, struct ip_fw *f);
  217: static __inline int
  218: 		port_match (u_short *portptr, int nports, u_short port,
  219: 				int range_flag, int mask);
  220: static int	tcpflg_match (struct tcphdr *tcp, struct ip_fw *f);
  221: static int	icmptype_match (struct icmp *  icmp, struct ip_fw * f);
  222: static void	ipfw_report (struct ip_fw *f, struct ip *ip, int ip_off,
  223: 				int ip_len, struct ifnet *rif,
  224: 				struct ifnet *oif);
  225: 
  226: static void	flush_rule_ptrs(void);
  227: 
  228: static ip_fw_chk_t ip_fw_chk;
  229: static int	ip_fw_ctl (struct sockopt *sopt);
  230: 
  231: ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL;
  232: 
  233: static char err_prefix[] = "ip_fw_ctl:";
  234: 
  235: /*
  236:  * Returns 1 if the port is matched by the vector, 0 otherwise
  237:  */
  238: static __inline int 
  239: port_match(u_short *portptr, int nports, u_short port, int range_flag, int mask)
  240: {
  241: 	if (!nports)
  242: 		return 1;
  243: 	if (mask) {
  244: 		if ( 0 == ((portptr[0] ^ port) & portptr[1]) )
  245: 			return 1;
  246: 		nports -= 2;
  247: 		portptr += 2;
  248: 	}
  249: 	if (range_flag) {
  250: 		if (portptr[0] <= port && port <= portptr[1])
  251: 			return 1;
  252: 		nports -= 2;
  253: 		portptr += 2;
  254: 	}
  255: 	while (nports-- > 0)
  256: 		if (*portptr++ == port)
  257: 			return 1;
  258: 	return 0;
  259: }
  260: 
  261: static int
  262: tcpflg_match(struct tcphdr *tcp, struct ip_fw *f)
  263: {
  264: 	u_char		flg_set, flg_clr;
  265: 
  266: 	/*
  267: 	 * If an established connection is required, reject packets that
  268: 	 * have only SYN of RST|ACK|SYN set.  Otherwise, fall through to
  269: 	 * other flag requirements.
  270: 	 */
  271: 	if ((f->fw_ipflg & IP_FW_IF_TCPEST) &&
  272: 	    ((tcp->th_flags & (IP_FW_TCPF_RST | IP_FW_TCPF_ACK |
  273: 	    IP_FW_TCPF_SYN)) == IP_FW_TCPF_SYN))
  274: 		return 0;
  275: 
  276: 	flg_set = tcp->th_flags & f->fw_tcpf;
  277: 	flg_clr = tcp->th_flags & f->fw_tcpnf;
  278: 
  279: 	if (flg_set != f->fw_tcpf)
  280: 		return 0;
  281: 	if (flg_clr)
  282: 		return 0;
  283: 
  284: 	return 1;
  285: }
  286: 
  287: static int
  288: icmptype_match(struct icmp *icmp, struct ip_fw *f)
  289: {
  290: 	int type;
  291: 
  292: 	if (!(f->fw_flg & IP_FW_F_ICMPBIT))
  293: 		return(1);
  294: 
  295: 	type = icmp->icmp_type;
  296: 
  297: 	/* check for matching type in the bitmap */
  298: 	if (type < IP_FW_ICMPTYPES_MAX &&
  299: 	    (f->fw_uar.fw_icmptypes[type / (sizeof(unsigned) * NBBY)] & 
  300: 	    (1U << (type % (sizeof(unsigned) * NBBY)))))
  301: 		return(1);
  302: 
  303: 	return(0); /* no match */
  304: }
  305: 
  306: static int
  307: is_icmp_query(struct ip *ip)
  308: {
  309: 	const struct icmp *icmp;
  310: 	int icmp_type;
  311: 
  312: 	icmp = (struct icmp *)((u_int32_t *)ip + ip->ip_hl);
  313: 	icmp_type = icmp->icmp_type;
  314: 
  315: 	if (icmp_type == ICMP_ECHO || icmp_type == ICMP_ROUTERSOLICIT ||
  316: 	    icmp_type == ICMP_TSTAMP || icmp_type == ICMP_IREQ ||
  317: 	    icmp_type == ICMP_MASKREQ)
  318: 		return(1);
  319: 
  320: 	return(0);
  321: }
  322: 
  323: static int
  324: ipopts_match(struct ip *ip, struct ip_fw *f)
  325: {
  326: 	u_char *cp;
  327: 	int opt, optlen, cnt;
  328: 	u_char	opts, nopts, nopts_sve;
  329: 
  330: 	cp = (u_char *)(ip + 1);
  331: 	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  332: 	opts = f->fw_ipopt;
  333: 	nopts = nopts_sve = f->fw_ipnopt;
  334: 
  335: 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
  336: 		opt = cp[IPOPT_OPTVAL];
  337: 		if (opt == IPOPT_EOL)
  338: 			break;
  339: 		if (opt == IPOPT_NOP)
  340: 			optlen = 1;
  341: 		else {
  342: 			optlen = cp[IPOPT_OLEN];
  343: 			if (optlen <= 0 || optlen > cnt) {
  344: 				return 0; /*XXX*/
  345: 			}
  346: 		}
  347: 		switch (opt) {
  348: 
  349: 		default:
  350: 			break;
  351: 
  352: 		case IPOPT_LSRR:
  353: 			opts &= ~IP_FW_IPOPT_LSRR;
  354: 			nopts &= ~IP_FW_IPOPT_LSRR;
  355: 			break;
  356: 
  357: 		case IPOPT_SSRR:
  358: 			opts &= ~IP_FW_IPOPT_SSRR;
  359: 			nopts &= ~IP_FW_IPOPT_SSRR;
  360: 			break;
  361: 
  362: 		case IPOPT_RR:
  363: 			opts &= ~IP_FW_IPOPT_RR;
  364: 			nopts &= ~IP_FW_IPOPT_RR;
  365: 			break;
  366: 		case IPOPT_TS:
  367: 			opts &= ~IP_FW_IPOPT_TS;
  368: 			nopts &= ~IP_FW_IPOPT_TS;
  369: 			break;
  370: 		}
  371: 		if (opts == nopts)
  372: 			break;
  373: 	}
  374: 	if (opts == 0 && nopts == nopts_sve)
  375: 		return 1;
  376: 	else
  377: 		return 0;
  378: }
  379: 
  380: static int
  381: tcpopts_match(struct tcphdr *tcp, struct ip_fw *f)
  382: {
  383: 	u_char *cp;
  384: 	int opt, optlen, cnt;
  385: 	u_char	opts, nopts, nopts_sve;
  386: 
  387: 	cp = (u_char *)(tcp + 1);
  388: 	cnt = (tcp->th_off << 2) - sizeof (struct tcphdr);
  389: 	opts = f->fw_tcpopt;
  390: 	nopts = nopts_sve = f->fw_tcpnopt;
  391: 
  392: 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
  393: 		opt = cp[0];
  394: 		if (opt == TCPOPT_EOL)
  395: 			break;
  396: 		if (opt == TCPOPT_NOP)
  397: 			optlen = 1;
  398: 		else {
  399: 			optlen = cp[1];
  400: 			if (optlen <= 0)
  401: 				break;
  402: 		}
  403: 
  404: 
  405: 		switch (opt) {
  406: 
  407: 		default:
  408: 			break;
  409: 
  410: 		case TCPOPT_MAXSEG:
  411: 			opts &= ~IP_FW_TCPOPT_MSS;
  412: 			nopts &= ~IP_FW_TCPOPT_MSS;
  413: 			break;
  414: 
  415: 		case TCPOPT_WINDOW:
  416: 			opts &= ~IP_FW_TCPOPT_WINDOW;
  417: 			nopts &= ~IP_FW_TCPOPT_WINDOW;
  418: 			break;
  419: 
  420: 		case TCPOPT_SACK_PERMITTED:
  421: 		case TCPOPT_SACK:
  422: 			opts &= ~IP_FW_TCPOPT_SACK;
  423: 			nopts &= ~IP_FW_TCPOPT_SACK;
  424: 			break;
  425: 
  426: 		case TCPOPT_TIMESTAMP:
  427: 			opts &= ~IP_FW_TCPOPT_TS;
  428: 			nopts &= ~IP_FW_TCPOPT_TS;
  429: 			break;
  430: 
  431: 		case TCPOPT_CC:
  432: 		case TCPOPT_CCNEW:
  433: 		case TCPOPT_CCECHO:
  434: 			opts &= ~IP_FW_TCPOPT_CC;
  435: 			nopts &= ~IP_FW_TCPOPT_CC;
  436: 			break;
  437: 		}
  438: 		if (opts == nopts)
  439: 			break;
  440: 	}
  441: 	if (opts == 0 && nopts == nopts_sve)
  442: 		return 1;
  443: 	else
  444: 		return 0;
  445: }
  446: 
  447: static int
  448: iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname)
  449: {
  450: 	/* Check by name or by IP address */
  451: 	if (byname) {
  452: 		/* Check name */
  453: 		if (ifu->fu_via_if.glob) {
  454: 			if (fnmatch(ifu->fu_via_if.name, ifp->if_xname, 0)
  455: 			    == FNM_NOMATCH)
  456: 				return(0);
  457: 		} else {
  458: 			if (strncmp(ifp->if_xname, ifu->fu_via_if.name,
  459: 			    FW_IFNLEN) != 0)
  460: 				return(0);
  461: 		}
  462: 		return(1);
  463: 	} else if (ifu->fu_via_ip.s_addr != 0) {	/* Zero == wildcard */
  464: 		struct ifaddr *ia;
  465: 
  466: 		TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
  467: 			if (ia->ifa_addr == NULL)
  468: 				continue;
  469: 			if (ia->ifa_addr->sa_family != AF_INET)
  470: 				continue;
  471: 			if (ifu->fu_via_ip.s_addr != ((struct sockaddr_in *)
  472: 			    (ia->ifa_addr))->sin_addr.s_addr)
  473: 				continue;
  474: 			return(1);
  475: 		}
  476: 		return(0);
  477: 	}
  478: 	return(1);
  479: }
  480: 
  481: static void
  482: ipfw_report(struct ip_fw *f, struct ip *ip, int ip_off, int ip_len,
  483: 	struct ifnet *rif, struct ifnet *oif)
  484: {
  485:     struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl);
  486:     struct udphdr *const udp = (struct udphdr *) ((u_int32_t *) ip+ ip->ip_hl);
  487:     struct icmp *const icmp = (struct icmp *) ((u_int32_t *) ip + ip->ip_hl);
  488:     u_int64_t count;
  489:     char *action;
  490:     char action2[32], proto[47], name[18], fragment[27];
  491:     int len;
  492:     int offset = ip_off & IP_OFFMASK;
  493: 
  494:     count = f ? f->fw_pcnt : ++counter;
  495:     if ((f == NULL && fw_verbose_limit != 0 && count > fw_verbose_limit) ||
  496: 	(f && f->fw_logamount != 0 && count > f->fw_loghighest))
  497: 	    return;
  498: 
  499:     /* Print command name */
  500:     snprintf(SNPARGS(name, 0), "ipfw: %d", f ? f->fw_number : -1);
  501: 
  502:     action = action2;
  503:     if (!f)
  504: 	    action = "Refuse";
  505:     else {
  506: 	    switch (f->fw_flg & IP_FW_F_COMMAND) {
  507: 	    case IP_FW_F_DENY:
  508: 		    action = "Deny";
  509: 		    break;
  510: 	    case IP_FW_F_REJECT:
  511: 		    if (f->fw_reject_code == IP_FW_REJECT_RST)
  512: 			    action = "Reset";
  513: 		    else
  514: 			    action = "Unreach";
  515: 		    break;
  516: 	    case IP_FW_F_ACCEPT:
  517: 		    action = "Accept";
  518: 		    break;
  519: 	    case IP_FW_F_COUNT:
  520: 		    action = "Count";
  521: 		    break;
  522: #ifdef IPDIVERT
  523: 	    case IP_FW_F_DIVERT:
  524: 		    snprintf(SNPARGS(action2, 0), "Divert %d",
  525: 			f->fw_divert_port);
  526: 		    break;
  527: 	    case IP_FW_F_TEE:
  528: 		    snprintf(SNPARGS(action2, 0), "Tee %d",
  529: 			f->fw_divert_port);
  530: 		    break;
  531: #endif
  532: 	    case IP_FW_F_SKIPTO:
  533: 		    snprintf(SNPARGS(action2, 0), "SkipTo %d",
  534: 			f->fw_skipto_rule);
  535: 		    break;
  536: 	    case IP_FW_F_PIPE:
  537: 		    snprintf(SNPARGS(action2, 0), "Pipe %d",
  538: 			f->fw_skipto_rule);
  539: 		    break;
  540: 	    case IP_FW_F_QUEUE:
  541: 		    snprintf(SNPARGS(action2, 0), "Queue %d",
  542: 			f->fw_skipto_rule);
  543: 		    break;
  544: 
  545: 	    case IP_FW_F_FWD:
  546: 		    if (f->fw_fwd_ip.sin_port)
  547: 			    snprintf(SNPARGS(action2, 0),
  548: 				"Forward to %s:%d",
  549: 				inet_ntoa(f->fw_fwd_ip.sin_addr),
  550: 				f->fw_fwd_ip.sin_port);
  551: 		    else
  552: 			    snprintf(SNPARGS(action2, 0), "Forward to %s",
  553: 				inet_ntoa(f->fw_fwd_ip.sin_addr));
  554: 		    break;
  555: 
  556: 	    default:	
  557: 		    action = "UNKNOWN";
  558: 		    break;
  559: 	    }
  560:     }
  561: 
  562:     switch (ip->ip_p) {
  563:     case IPPROTO_TCP:
  564: 	    len = snprintf(SNPARGS(proto, 0), "TCP %s",
  565: 		inet_ntoa(ip->ip_src));
  566: 	    if (offset == 0)
  567: 		    len += snprintf(SNPARGS(proto, len), ":%d ",
  568: 			ntohs(tcp->th_sport));
  569: 	    else
  570: 		    len += snprintf(SNPARGS(proto, len), " ");
  571: 	    len += snprintf(SNPARGS(proto, len), "%s",
  572: 		inet_ntoa(ip->ip_dst));
  573: 	    if (offset == 0)
  574: 		    snprintf(SNPARGS(proto, len), ":%d",
  575: 			ntohs(tcp->th_dport));
  576: 	    break;
  577:     case IPPROTO_UDP:
  578: 	    len = snprintf(SNPARGS(proto, 0), "UDP %s",
  579: 		inet_ntoa(ip->ip_src));
  580: 	    if (offset == 0)
  581: 		    len += snprintf(SNPARGS(proto, len), ":%d ",
  582: 			ntohs(udp->uh_sport));
  583: 	    else
  584: 		    len += snprintf(SNPARGS(proto, len), " ");
  585: 	    len += snprintf(SNPARGS(proto, len), "%s",
  586: 		inet_ntoa(ip->ip_dst));
  587: 	    if (offset == 0)
  588: 		    snprintf(SNPARGS(proto, len), ":%d",
  589: 			ntohs(udp->uh_dport));
  590: 	    break;
  591:     case IPPROTO_ICMP:
  592: 	    if (offset == 0)
  593: 		    len = snprintf(SNPARGS(proto, 0), "ICMP:%u.%u ",
  594: 			icmp->icmp_type, icmp->icmp_code);
  595: 	    else
  596: 		    len = snprintf(SNPARGS(proto, 0), "ICMP ");
  597: 	    len += snprintf(SNPARGS(proto, len), "%s",
  598: 		inet_ntoa(ip->ip_src));
  599: 	    snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
  600: 	    break;
  601:     default:
  602: 	    len = snprintf(SNPARGS(proto, 0), "P:%d %s", ip->ip_p,
  603: 		inet_ntoa(ip->ip_src));
  604: 	    snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
  605: 	    break;
  606:     }
  607: 
  608:     if (ip_off & (IP_MF | IP_OFFMASK))
  609: 	    snprintf(SNPARGS(fragment, 0), " (frag %d:%d@%d%s)",
  610: 		     ntohs(ip->ip_id), ip_len - (ip->ip_hl << 2),
  611: 		     offset << 3,
  612: 		     (ip_off & IP_MF) ? "+" : "");
  613:     else
  614: 	    fragment[0] = '\0';
  615:     if (oif)
  616: 	    log(LOG_SECURITY | LOG_INFO, "%s %s %s out via %s%s\n",
  617: 		name, action, proto, oif->if_xname, fragment);
  618:     else if (rif)
  619: 	    log(LOG_SECURITY | LOG_INFO, "%s %s %s in via %s%s\n", name,
  620: 		action, proto, rif->if_xname, fragment);
  621:     else
  622: 	    log(LOG_SECURITY | LOG_INFO, "%s %s %s%s\n", name, action,
  623: 		proto, fragment);
  624:     if ((f ? f->fw_logamount != 0 : 1) &&
  625: 	count == (f ? f->fw_loghighest : fw_verbose_limit))
  626: 	    log(LOG_SECURITY | LOG_NOTICE,
  627: 		"ipfw: limit %d reached on entry %d\n",
  628: 		f ? f->fw_logamount : fw_verbose_limit,
  629: 		f ? f->fw_number : -1);
  630: }
  631: 
  632: static __inline int
  633: hash_packet(struct ipfw_flow_id *id)
  634: {
  635:     u_int32_t i ;
  636: 
  637:     i = (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port);
  638:     i &= (curr_dyn_buckets - 1) ;
  639:     return i ;
  640: }
  641: 
  642: /**
  643:  * unlink a dynamic rule from a chain. prev is a pointer to
  644:  * the previous one, q is a pointer to the rule to delete,
  645:  * head is a pointer to the head of the queue.
  646:  * Modifies q and potentially also head.
  647:  */
  648: #define UNLINK_DYN_RULE(prev, head, q) {				\
  649: 	struct ipfw_dyn_rule *old_q = q;				\
  650: 									\
  651: 	/* remove a refcount to the parent */				\
  652: 	if (q->dyn_type == DYN_LIMIT)					\
  653: 		q->parent->count--;					\
  654: 	DEB(printf("-- unlink entry 0x%08x %d -> 0x%08x %d, %d left\n", \
  655: 		(q->id.src_ip), (q->id.src_port),			\
  656: 		(q->id.dst_ip), (q->id.dst_port), dyn_count-1 ); )	\
  657: 	if (prev != NULL)						\
  658: 		prev->next = q = q->next ;				\
  659: 	else								\
  660: 		ipfw_dyn_v[i] = q = q->next ;				\
  661: 	dyn_count-- ;							\
  662: 	free(old_q, M_IPFW); }
  663: 
  664: #define TIME_LEQ(a,b)       ((int)((a)-(b)) <= 0)
  665: /**
  666:  * Remove all dynamic rules pointing to a given rule, or all
  667:  * rules if rule == NULL. Second parameter is 1 if we want to
  668:  * delete unconditionally, otherwise only expired rules are removed.
  669:  */
  670: static void
  671: remove_dyn_rule(struct ip_fw *rule, int force)
  672: {
  673:     struct ipfw_dyn_rule *prev, *q;
  674:     int i, pass, max_pass ;
  675:     static u_int32_t last_remove = 0 ;
  676: 
  677:     if (ipfw_dyn_v == NULL || dyn_count == 0)
  678: 	return ;
  679:     /* do not expire more than once per second, it is useless */
  680:     if (force == 0 && last_remove == time_second)
  681: 	return ;
  682:     last_remove = time_second ;
  683: 
  684:     /*
  685:      * because DYN_LIMIT refer to parent rules, during the first pass only
  686:      * remove child and mark any pending LIMIT_PARENT, and remove
  687:      * them in a second pass.
  688:      */
  689:   for (pass = max_pass = 0; pass <= max_pass ; pass++ ) {
  690:     for (i = 0 ; i < curr_dyn_buckets ; i++) {
  691: 	for (prev=NULL, q = ipfw_dyn_v[i] ; q ; ) {
  692: 	    /*
  693: 	     * logic can become complex here, so we split tests.
  694: 	     * First, test if we match any rule,
  695: 	     * then make sure the rule is expired or we want to kill it,
  696: 	     * and possibly more in the future.
  697: 	     */
  698: 	    int zap = ( rule == NULL || rule == q->rule);
  699: 	    if (zap)
  700: 		zap = force || TIME_LEQ( q->expire , time_second );
  701: 	    /* do not zap parent in first pass, record we need a second pass */
  702: 	    if (zap && q->dyn_type == DYN_LIMIT_PARENT) {
  703: 		max_pass = 1; /* we need a second pass */
  704: 		if (pass == 0 || q->count != 0) {
  705: 		    zap = 0 ;
  706: 		    if (pass == 1 && force) /* should not happen */
  707: 			printf("OUCH! cannot remove rule, count %d\n",
  708: 				q->count);
  709: 		}
  710: 	    }
  711: 	    if (zap) {
  712: 		UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q);
  713: 	    } else {
  714: 		prev = q ;
  715: 		q = q->next ;
  716: 	    }
  717: 	}
  718:     }
  719:   }
  720: }
  721: 
  722: #define EXPIRE_DYN_CHAIN(rule) remove_dyn_rule(rule, 0 /* expired ones */)
  723: #define EXPIRE_DYN_CHAINS() remove_dyn_rule(NULL, 0 /* expired ones */)
  724: #define DELETE_DYN_CHAIN(rule) remove_dyn_rule(rule, 1 /* force removal */)
  725: #define DELETE_DYN_CHAINS() remove_dyn_rule(NULL, 1 /* force removal */)
  726: 
  727: /**
  728:  * lookup a dynamic rule.
  729:  */
  730: static struct ipfw_dyn_rule *
  731: lookup_dyn_rule(struct ipfw_flow_id *pkt, int *match_direction)
  732: {
  733:     /*
  734:      * stateful ipfw extensions.
  735:      * Lookup into dynamic session queue
  736:      */
  737:     struct ipfw_dyn_rule *prev, *q ;
  738:     int i, dir = 0;
  739: #define MATCH_FORWARD 1
  740: 
  741:     if (ipfw_dyn_v == NULL)
  742: 	return NULL ;
  743:     i = hash_packet( pkt );
  744:     for (prev=NULL, q = ipfw_dyn_v[i] ; q != NULL ; ) {
  745: 	if (q->dyn_type == DYN_LIMIT_PARENT)
  746: 	    goto next;
  747: 	if (TIME_LEQ( q->expire , time_second ) ) { /* expire entry */
  748: 	    UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q);
  749: 	    continue;
  750: 	}
  751: 	if ( pkt->proto == q->id.proto) {
  752: 	    if (pkt->src_ip == q->id.src_ip &&
  753: 		    pkt->dst_ip == q->id.dst_ip &&
  754: 		    pkt->src_port == q->id.src_port &&
  755: 		    pkt->dst_port == q->id.dst_port ) {
  756: 		dir = MATCH_FORWARD ;
  757: 		goto found ;
  758: 	    }
  759: 	    if (pkt->src_ip == q->id.dst_ip &&
  760: 		    pkt->dst_ip == q->id.src_ip &&
  761: 		    pkt->src_port == q->id.dst_port &&
  762: 		    pkt->dst_port == q->id.src_port ) {
  763: 		dir = 0 ; /* reverse match */
  764: 		goto found ;
  765: 	    }
  766: 	}
  767: next:
  768: 	prev = q ;
  769: 	q = q->next ;
  770:     }
  771:     return NULL ; /* clearly not found */
  772: found:
  773:     if ( prev != NULL) { /* found and not in front */
  774: 	prev->next = q->next ;
  775: 	q->next = ipfw_dyn_v[i] ;
  776: 	ipfw_dyn_v[i] = q ;
  777:     }
  778:     if (pkt->proto == IPPROTO_TCP) {
  779: 	/* update state according to flags */
  780: 	u_char flags = pkt->flags & (TH_FIN|TH_SYN|TH_RST);
  781: 	q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8);
  782: 	switch (q->state) {
  783: 	case TH_SYN :
  784: 	    /* opening */
  785: 	    q->expire = time_second + dyn_syn_lifetime ;
  786: 	    break ;
  787: 	case TH_SYN | (TH_SYN << 8) :
  788: 	    /* move to established */
  789: 	    q->expire = time_second + dyn_ack_lifetime ;
  790: 	    break ;
  791: 	case TH_SYN | (TH_SYN << 8) | TH_FIN :
  792: 	case TH_SYN | (TH_SYN << 8) | (TH_FIN << 8) :
  793: 	    /* one side tries to close */
  794: 	    q->expire = time_second + dyn_ack_lifetime ;
  795: 	    break ;
  796: 	case TH_SYN | (TH_SYN << 8) | TH_FIN | (TH_FIN << 8) :
  797: 	    /* both sides closed */
  798: 	    q->expire = time_second + dyn_fin_lifetime ;
  799: 	    break ;
  800: 	default:
  801: #if 0
  802: 	    /*
  803: 	     * reset or some invalid combination, but can also
  804: 	     * occur if we use keep-state the wrong way.
  805: 	     */
  806: 	    if ( (q->state & ((TH_RST << 8)|TH_RST)) == 0)
  807: 		printf("invalid state: 0x%x\n", q->state);
  808: #endif
  809: 	    q->expire = time_second + dyn_rst_lifetime ;
  810: 	    break ;
  811: 	}
  812:     } else if (pkt->proto == IPPROTO_UDP) {
  813: 	q->expire = time_second + dyn_udp_lifetime ;
  814:     } else {
  815: 	/* other protocols */
  816: 	q->expire = time_second + dyn_short_lifetime ;
  817:     }
  818:     if (match_direction)
  819: 	*match_direction = dir ;
  820:     return q ;
  821: }
  822: 
  823: /**
  824:  * Install state of type 'type' for a dynamic session.
  825:  * The hash table contains two type of rules:
  826:  * - regular rules (DYN_KEEP_STATE)
  827:  * - rules for sessions with limited number of sess per user
  828:  *   (DYN_LIMIT). When they are created, the parent is
  829:  *   increased by 1, and decreased on delete. In this case,
  830:  *   the third parameter is the parent rule and not the chain.
  831:  * - "parent" rules for the above (DYN_LIMIT_PARENT).
  832:  */
  833: 
  834: static struct ipfw_dyn_rule *
  835: add_dyn_rule(struct ipfw_flow_id *id, u_int8_t dyn_type, struct ip_fw *rule)
  836: {
  837:     struct ipfw_dyn_rule *r ;
  838: 
  839:     int i ;
  840:     if (ipfw_dyn_v == NULL ||
  841: 		(dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
  842: 	/* try reallocation, make sure we have a power of 2 */
  843: 	u_int32_t i = dyn_buckets ;
  844: 	while ( i > 0 && (i & 1) == 0 )
  845: 	    i >>= 1 ;
  846: 	if (i != 1) /* not a power of 2 */
  847: 	    dyn_buckets = curr_dyn_buckets ; /* reset */
  848: 	else {
  849: 	    curr_dyn_buckets = dyn_buckets ;
  850: 	    if (ipfw_dyn_v != NULL)
  851: 		free(ipfw_dyn_v, M_IPFW);
  852: 	    ipfw_dyn_v = malloc(curr_dyn_buckets * sizeof r,
  853:                    M_IPFW, M_WAITOK | M_ZERO);
  854: 	    if (ipfw_dyn_v == NULL)
  855: 		return NULL; /* failed ! */
  856: 	}
  857:     }
  858:     i = hash_packet(id);
  859: 
  860:     r = malloc(sizeof *r, M_IPFW, M_WAITOK | M_ZERO);
  861:     if (r == NULL) {
  862: 	printf ("sorry cannot allocate state\n");
  863: 	return NULL ;
  864:     }
  865: 
  866:     /* increase refcount on parent, and set pointer */
  867:     if (dyn_type == DYN_LIMIT) {
  868: 	struct ipfw_dyn_rule *parent = (struct ipfw_dyn_rule *)rule;
  869: 	if ( parent->dyn_type != DYN_LIMIT_PARENT)
  870: 	    panic("invalid parent");
  871: 	parent->count++ ;
  872: 	r->parent = parent ;
  873: 	rule = parent->rule;
  874:     }
  875: 
  876:     r->id = *id ;
  877:     r->expire = time_second + dyn_syn_lifetime ;
  878:     r->rule = rule ;
  879:     r->dyn_type = dyn_type ;
  880:     r->pcnt = r->bcnt = 0 ;
  881:     r->count = 0 ;
  882: 
  883:     r->bucket = i ;
  884:     r->next = ipfw_dyn_v[i] ;
  885:     ipfw_dyn_v[i] = r ;
  886:     dyn_count++ ;
  887:     DEB(printf("-- add entry 0x%08x %d -> 0x%08x %d, total %d\n",
  888:        (r->id.src_ip), (r->id.src_port),
  889:        (r->id.dst_ip), (r->id.dst_port),
  890:        dyn_count ); )
  891:     return r;
  892: }
  893: 
  894: /**
  895:  * lookup dynamic parent rule using pkt and rule as search keys.
  896:  * If the lookup fails, then install one.
  897:  */
  898: static struct ipfw_dyn_rule *
  899: lookup_dyn_parent(struct ipfw_flow_id *pkt, struct ip_fw *rule)
  900: {
  901:     struct ipfw_dyn_rule *q;
  902:     int i;
  903: 
  904:     if (ipfw_dyn_v) {
  905: 	i = hash_packet( pkt );
  906: 	for (q = ipfw_dyn_v[i] ; q != NULL ; q=q->next)
  907: 	    if (q->dyn_type == DYN_LIMIT_PARENT && rule == q->rule &&
  908: 		    pkt->proto == q->id.proto &&
  909: 		    pkt->src_ip == q->id.src_ip &&
  910: 		    pkt->dst_ip == q->id.dst_ip &&
  911: 		    pkt->src_port == q->id.src_port &&
  912: 		    pkt->dst_port == q->id.dst_port) {
  913: 		q->expire = time_second + dyn_short_lifetime ;
  914: 		DEB(printf("lookup_dyn_parent found 0x%p\n", q);)
  915: 		return q;
  916: 	    }
  917:     }
  918:     return add_dyn_rule(pkt, DYN_LIMIT_PARENT, rule);
  919: }
  920: 
  921: /*
  922:  * Install dynamic state.
  923:  * There are different types of dynamic rules which can be installed.
  924:  * The type is in rule->dyn_type.
  925:  * Type 0 (default) is a bidirectional rule
  926:  *
  927:  * Returns 1 (failure) if state is not installed because of errors or because
  928:  * session limitations are enforced.
  929:  */
  930: static int
  931: install_state(struct ip_fw *rule, struct ip_fw_args *args)
  932: {
  933:     struct ipfw_dyn_rule *q ;
  934:     static int last_log ;
  935: 
  936:     u_int8_t type = rule->dyn_type ;
  937: 
  938:     DEB(printf("-- install state type %d 0x%08x %u -> 0x%08x %u\n",
  939:        type,
  940:        (args->f_id.src_ip), (args->f_id.src_port),
  941:        (args->f_id.dst_ip), (args->f_id.dst_port) );)
  942: 
  943:     q = lookup_dyn_rule(&args->f_id, NULL) ;
  944:     if (q != NULL) { /* should never occur */
  945: 	if (last_log != time_second) {
  946: 	    last_log = time_second ;
  947: 	    printf(" entry already present, done\n");
  948: 	}
  949: 	return 0 ;
  950:     }
  951:     if (dyn_count >= dyn_max) /* try remove old ones... */
  952: 	EXPIRE_DYN_CHAINS();
  953:     if (dyn_count >= dyn_max) {
  954: 	if (last_log != time_second) {
  955: 	    last_log = time_second ;
  956: 	    printf(" Too many dynamic rules, sorry\n");
  957: 	}
  958: 	return 1; /* cannot install, notify caller */
  959:     }
  960: 
  961:     switch (type) {
  962:     case DYN_KEEP_STATE: /* bidir rule */
  963: 	add_dyn_rule(&args->f_id, DYN_KEEP_STATE, rule);
  964: 	break ;
  965:     case DYN_LIMIT: /* limit number of sessions */
  966: 	{
  967: 	u_int16_t limit_mask = rule->limit_mask ;
  968: 	u_int16_t conn_limit = rule->conn_limit ;
  969: 	struct ipfw_flow_id id;
  970: 	struct ipfw_dyn_rule *parent;
  971: 
  972: 	DEB(printf("installing dyn-limit rule %d\n", conn_limit);)
  973: 
  974: 	id.dst_ip = id.src_ip = 0;
  975: 	id.dst_port = id.src_port = 0 ;
  976: 	id.proto = args->f_id.proto ;
  977: 
  978: 	if (limit_mask & DYN_SRC_ADDR)
  979: 	    id.src_ip = args->f_id.src_ip;
  980: 	if (limit_mask & DYN_DST_ADDR)
  981: 	    id.dst_ip = args->f_id.dst_ip;
  982: 	if (limit_mask & DYN_SRC_PORT)
  983: 	    id.src_port = args->f_id.src_port;
  984: 	if (limit_mask & DYN_DST_PORT)
  985: 	    id.dst_port = args->f_id.dst_port;
  986: 	parent = lookup_dyn_parent(&id, rule);
  987: 	if (parent == NULL) {
  988: 	    printf("add parent failed\n");
  989: 	    return 1;
  990: 	}
  991: 	if (parent->count >= conn_limit) {
  992: 	    EXPIRE_DYN_CHAIN(rule); /* try to expire some */
  993: 	    /*
  994: 	     * The expiry might have removed the parent too.
  995: 	     * We lookup again, which will re-create if necessary.
  996: 	     */
  997: 	    parent = lookup_dyn_parent(&id, rule);
  998: 	    if (parent == NULL) {
  999: 		printf("add parent failed\n");
 1000: 		return 1;
 1001: 	    }
 1002: 	    if (parent->count >= conn_limit) {
 1003: 		if (fw_verbose && last_log != time_second) {
 1004: 			last_log = time_second;
 1005: 			log(LOG_SECURITY | LOG_DEBUG,
 1006: 			    "drop session, too many entries\n");
 1007: 		}
 1008: 		return 1;
 1009: 	    }
 1010: 	}
 1011: 	add_dyn_rule(&args->f_id, DYN_LIMIT, (struct ip_fw *)parent);
 1012: 	}
 1013: 	break ;
 1014:     default:
 1015: 	printf("unknown dynamic rule type %u\n", type);
 1016: 	return 1 ;
 1017:     }
 1018:     lookup_dyn_rule(&args->f_id, NULL) ; /* XXX just set the lifetime */
 1019:     return 0;
 1020: }
 1021: 
 1022: /*
 1023:  * given an ip_fw *, lookup_next_rule will return a pointer
 1024:  * of the same type to the next one. This can be either the jump
 1025:  * target (for skipto instructions) or the next one in the list (in
 1026:  * all other cases including a missing jump target).
 1027:  * Backward jumps are not allowed, so start looking from the next
 1028:  * rule...
 1029:  */ 
 1030: static struct ip_fw * lookup_next_rule(struct ip_fw *me);
 1031: 
 1032: static struct ip_fw *
 1033: lookup_next_rule(struct ip_fw *me)
 1034: {
 1035:     struct ip_fw *rule ;
 1036:     int rulenum = me->fw_skipto_rule ; /* guess... */
 1037: 
 1038:     if ( (me->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_SKIPTO )
 1039: 	for (rule = LIST_NEXT(me,next); rule ; rule = LIST_NEXT(rule,next))
 1040: 	    if (rule->fw_number >= rulenum)
 1041: 		return rule ;
 1042:     return LIST_NEXT(me,next) ; /* failure or not a skipto */
 1043: }
 1044: 
 1045: /*
 1046:  * Parameters:
 1047:  *
 1048:  *	*m	The packet; we set to NULL when/if we nuke it.
 1049:  *	oif	Outgoing interface, or NULL if packet is incoming
 1050:  *	*cookie Skip up to the first rule past this rule number;
 1051:  *		upon return, non-zero port number for divert or tee.
 1052:  *		Special case: cookie == NULL on input for bridging.
 1053:  *	*flow_id pointer to the last matching rule (in/out)
 1054:  *	*next_hop socket we are forwarding to (in/out).
 1055:  *
 1056:  * Return value:
 1057:  *
 1058:  *	IP_FW_PORT_DENY_FLAG	the packet must be dropped.
 1059:  *	0	The packet is to be accepted and routed normally OR
 1060:  *      	the packet was denied/rejected and has been dropped;
 1061:  *		in the latter case, *m is equal to NULL upon return.
 1062:  *	port	Divert the packet to port, with these caveats:
 1063:  *
 1064:  *		- If IP_FW_PORT_TEE_FLAG is set, tee the packet instead
 1065:  *		  of diverting it (ie, 'ipfw tee').
 1066:  *
 1067:  *		- If IP_FW_PORT_DYNT_FLAG is set, interpret the lower
 1068:  *		  16 bits as a dummynet pipe number instead of diverting
 1069:  */
 1070: 
 1071: static int 
 1072: ip_fw_chk(struct ip_fw_args *args)
 1073: {
 1074: 	/*
 1075: 	 * grab things into variables to minimize diffs.
 1076: 	 * XXX this has to be cleaned up later.
 1077: 	 */
 1078: 	struct mbuf **m = &(args->m);
 1079: 	struct ifnet *oif = args->oif;
 1080: 	u_int16_t *cookie = &(args->divert_rule);
 1081: 	struct ip_fw **flow_id = &(args->rule);
 1082: 	struct sockaddr_in **next_hop = &(args->next_hop);
 1083: 
 1084: 	struct ip_fw *f = NULL;		/* matching rule */
 1085: 	struct ip *ip = mtod(*m, struct ip *);
 1086: 	struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
 1087: 	struct ifnet *tif;
 1088: 	u_int hlen = 0;
 1089: 
 1090: 	u_short ip_off=0, offset = 0;
 1091: 	/* local copy of addresses for faster matching */
 1092: 	u_short src_port = 0, dst_port = 0;
 1093: 	struct in_addr src_ip, dst_ip;
 1094: 	u_int8_t proto= 0, flags = 0;
 1095: 	u_int16_t skipto;
 1096: 	u_int16_t ip_len=0;
 1097: 
 1098: 	int dyn_checked = 0 ; /* set after dyn.rules have been checked. */
 1099: 	int direction = MATCH_FORWARD ; /* dirty trick... */
 1100: 	struct ipfw_dyn_rule *q = NULL ;
 1101: 
 1102: 	/* Special hack for bridging (as usual) */
 1103: #define BRIDGED		(args->eh != NULL)
 1104: 	if (BRIDGED) {	/* this is a bridged packet */
 1105: 		if ( (*m)->m_pkthdr.len >= sizeof(struct ip) &&
 1106: 			    ntohs(args->eh->ether_type) == ETHERTYPE_IP)
 1107: 			hlen = ip->ip_hl << 2;
 1108: 		else
 1109: 			return 0; /* XXX ipfw1 always accepts non-ip pkts */
 1110: 	} else
 1111: 		hlen = ip->ip_hl << 2;
 1112: 
 1113: 	/* Grab and reset cookie */
 1114: 	skipto = *cookie;
 1115: 	*cookie = 0;
 1116: 
 1117: #define PULLUP_TO(len)	do {						\
 1118: 			    if ((*m)->m_len < (len)) {			\
 1119: 				if ((*m = m_pullup(*m, (len))) == 0)	\
 1120: 				    goto bogusfrag;			\
 1121: 				ip = mtod(*m, struct ip *);		\
 1122: 			    }						\
 1123: 			} while (0)
 1124: 
 1125:     if (hlen > 0) { /* this is an IP packet */
 1126: 	/*
 1127: 	 * Collect parameters into local variables for faster matching.
 1128: 	 */
 1129: 	proto = ip->ip_p;
 1130: 	src_ip = ip->ip_src;
 1131: 	dst_ip = ip->ip_dst;
 1132: 	if (BRIDGED) { /* bridged packets are as on the wire */
 1133: 	    ip_off = ntohs(ip->ip_off);
 1134: 	    ip_len = ntohs(ip->ip_len);
 1135: 	} else {
 1136: 	    ip_off = ip->ip_off;
 1137: 	    ip_len = ip->ip_len;
 1138: 	}
 1139: 	offset = ip_off & IP_OFFMASK;
 1140: 	if (offset == 0) {
 1141: 	    switch (proto) {
 1142: 	    case IPPROTO_TCP : {
 1143: 		struct tcphdr *tcp;
 1144: 
 1145: 		PULLUP_TO(hlen + sizeof(struct tcphdr));
 1146: 		tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl);
 1147: 		dst_port = tcp->th_dport ;
 1148: 		src_port = tcp->th_sport ;
 1149: 		flags = tcp->th_flags ;
 1150: 		}
 1151: 		break ;
 1152: 
 1153: 	    case IPPROTO_UDP : {
 1154: 		struct udphdr *udp;
 1155: 
 1156: 		PULLUP_TO(hlen + sizeof(struct udphdr));
 1157: 		udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl);
 1158: 		dst_port = udp->uh_dport ;
 1159: 		src_port = udp->uh_sport ;
 1160: 		}
 1161: 		break;
 1162: 
 1163: 	    case IPPROTO_ICMP:
 1164: 		PULLUP_TO(hlen + 4);	/* type, code and checksum. */
 1165: 		flags = ((struct icmp *)
 1166: 			((u_int32_t *)ip + ip->ip_hl))->icmp_type ;
 1167: 		break ;
 1168: 
 1169: 	    default :
 1170: 		break;
 1171: 	    }
 1172: 	}
 1173:     }
 1174: #undef PULLUP_TO
 1175: 	args->f_id.src_ip = ntohl(src_ip.s_addr);
 1176: 	args->f_id.dst_ip = ntohl(dst_ip.s_addr);
 1177: 	args->f_id.proto = proto;
 1178: 	args->f_id.src_port = ntohs(src_port);
 1179: 	args->f_id.dst_port = ntohs(dst_port);
 1180: 	args->f_id.flags = flags;
 1181: 
 1182: 	if (*flow_id) {
 1183: 	    /*
 1184: 	     * Packet has already been tagged. Look for the next rule
 1185: 	     * to restart processing.
 1186: 	     */
 1187: 	    if (fw_one_pass) /* just accept if fw_one_pass is set */
 1188: 		return 0;
 1189: 
 1190: 	    f = (*flow_id)->next_rule_ptr ;
 1191: 	    if (f == NULL)
 1192: 		f = (*flow_id)->next_rule_ptr = lookup_next_rule(*flow_id);
 1193: 	    if (f == NULL)
 1194: 		goto dropit;
 1195: 	} else {
 1196: 	    /*
 1197: 	     * Go down the list, looking for enlightment.
 1198: 	     * If we've been asked to start at a given rule, do so.
 1199: 	     */
 1200: 	    f = LIST_FIRST(&ip_fw_chain_head);
 1201: 	    if (skipto != 0) {
 1202: 		if (skipto >= IPFW_DEFAULT_RULE)
 1203: 		    goto dropit;
 1204: 		while (f && f->fw_number <= skipto)
 1205: 		    f = LIST_NEXT(f, next);
 1206: 		if (f == NULL)
 1207: 		    goto dropit;
 1208: 	    }
 1209: 	}
 1210: 
 1211: 	for (; f; f = LIST_NEXT(f, next)) {
 1212: again:
 1213: 		if (f->fw_number == IPFW_DEFAULT_RULE)
 1214: 		    goto got_match ;
 1215: 
 1216: 		/*
 1217: 		 * dynamic rules are checked at the first keep-state or
 1218: 		 * check-state occurrence.
 1219: 		 */
 1220: 		if (f->fw_flg & (IP_FW_F_KEEP_S|IP_FW_F_CHECK_S) &&
 1221: 			 dyn_checked == 0 ) {
 1222: 		    dyn_checked = 1 ;
 1223: 		    q = lookup_dyn_rule(&args->f_id, &direction);
 1224: 		    if (q != NULL) {
 1225: 			DEB(printf("-- dynamic match 0x%08x %d %s 0x%08x %d\n",
 1226: 			    (q->id.src_ip), (q->id.src_port),
 1227: 			    (direction == MATCH_FORWARD ? "-->" : "<--"),
 1228: 			    (q->id.dst_ip), (q->id.dst_port) ); )
 1229: 			f = q->rule ;
 1230: 			q->pcnt++ ;
 1231: 			q->bcnt += ip_len;
 1232: 			goto got_match ; /* random not allowed here */
 1233: 		    }
 1234: 		    /* if this was a check-only rule, continue with next */
 1235: 		    if (f->fw_flg & IP_FW_F_CHECK_S)
 1236: 			continue ;
 1237: 		}
 1238: 
 1239: 		/* Check if rule only valid for bridged packets */
 1240: 		if ((f->fw_flg & IP_FW_BRIDGED) != 0 && !(BRIDGED))
 1241: 			continue;
 1242: 
 1243: 		if (oif) {
 1244: 			/* Check direction outbound */
 1245: 			if (!(f->fw_flg & IP_FW_F_OUT))
 1246: 				continue;
 1247: 		} else {
 1248: 			/* Check direction inbound */
 1249: 			if (!(f->fw_flg & IP_FW_F_IN))
 1250: 				continue;
 1251: 		}
 1252: 
 1253: 		/* Fragments */
 1254: 		if ((f->fw_flg & IP_FW_F_FRAG) && offset == 0 )
 1255: 			continue;
 1256: 
 1257: 		if (f->fw_flg & IP_FW_F_SME) {
 1258: 			INADDR_TO_IFP(src_ip, tif);
 1259: 			if (tif == NULL)
 1260: 				continue;
 1261: 		}
 1262: 		if (f->fw_flg & IP_FW_F_DME) {
 1263: 			INADDR_TO_IFP(dst_ip, tif);
 1264: 			if (tif == NULL)
 1265: 				continue;
 1266: 		}
 1267: 		/* If src-addr doesn't match, not this rule. */
 1268: 		if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((src_ip.s_addr
 1269: 		    & f->fw_smsk.s_addr) != f->fw_src.s_addr))
 1270: 			continue;
 1271: 
 1272: 		/* If dest-addr doesn't match, not this rule. */
 1273: 		if (((f->fw_flg & IP_FW_F_INVDST) != 0) ^ ((dst_ip.s_addr
 1274: 		    & f->fw_dmsk.s_addr) != f->fw_dst.s_addr))
 1275: 			continue;
 1276: 
 1277: 		/* Interface check */
 1278: 		if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
 1279: 			struct ifnet *const iface = oif ? oif : rif;
 1280: 
 1281: 			/* Backwards compatibility hack for "via" */
 1282: 			if (!iface || !iface_match(iface,
 1283: 			    &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME))
 1284: 				continue;
 1285: 		} else {
 1286: 			/* Check receive interface */
 1287: 			if ((f->fw_flg & IP_FW_F_IIFACE)
 1288: 			    && (!rif || !iface_match(rif,
 1289: 			      &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME)))
 1290: 				continue;
 1291: 			/* Check outgoing interface */
 1292: 			if ((f->fw_flg & IP_FW_F_OIFACE)
 1293: 			    && (!oif || !iface_match(oif,
 1294: 			      &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME)))
 1295: 				continue;
 1296: 		}
 1297: 
 1298: 		/* Check IP options */
 1299: 		if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f))
 1300: 			continue;
 1301: 
 1302: 		/* Check protocol; if wildcard, and no [ug]id, match */
 1303: 		if (f->fw_prot == IPPROTO_IP) {
 1304: 			if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
 1305: 				goto rnd_then_got_match;
 1306: 		} else
 1307: 		    /* If different, don't match */
 1308: 		    if (proto != f->fw_prot) 
 1309: 			    continue;
 1310: 
 1311: 		/* Protocol specific checks for uid only */
 1312: 		if (f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)) {
 1313: 		    switch (proto) {
 1314: 		    case IPPROTO_TCP:
 1315: 			{
 1316: 			    struct inpcb *P;
 1317: 
 1318: 			    if (offset == 1)	/* cf. RFC 1858 */
 1319: 				    goto bogusfrag;
 1320: 			    if (offset != 0)
 1321: 				    continue;
 1322: 
 1323: 			    if (oif)
 1324: 				P = in_pcblookup_hash(&tcbinfo[mycpu->gd_cpuid],
 1325: 				   dst_ip, dst_port, src_ip, src_port, 0, oif);
 1326: 			    else
 1327: 				P = in_pcblookup_hash(&tcbinfo[mycpu->gd_cpuid],
 1328: 				   src_ip, src_port, dst_ip, dst_port, 0, NULL);
 1329: 
 1330: 			    if (P && P->inp_socket) {
 1331: 				if (f->fw_flg & IP_FW_F_UID) {
 1332: 					if (P->inp_socket->so_cred->cr_uid !=
 1333: 					    f->fw_uid)
 1334: 						continue;
 1335: 				} else if (!groupmember(f->fw_gid,
 1336: 					    P->inp_socket->so_cred))
 1337: 						continue;
 1338: 			    } else
 1339: 				continue;
 1340: 			    break;
 1341: 			}
 1342: 
 1343: 		    case IPPROTO_UDP:
 1344: 			{
 1345: 			    struct inpcb *P;
 1346: 
 1347: 			    if (offset != 0)
 1348: 				continue;
 1349: 
 1350: 			    if (oif)
 1351: 				P = in_pcblookup_hash(&udbinfo, dst_ip,
 1352: 				   dst_port, src_ip, src_port, 1,
 1353: 				   oif);
 1354: 			    else
 1355: 				P = in_pcblookup_hash(&udbinfo, src_ip,
 1356: 				   src_port, dst_ip, dst_port, 1,
 1357: 				   NULL);
 1358: 
 1359: 			    if (P && P->inp_socket) {
 1360: 				if (f->fw_flg & IP_FW_F_UID) {
 1361: 					if (P->inp_socket->so_cred->cr_uid !=
 1362: 					    f->fw_uid)
 1363: 						continue;
 1364: 				} else if (!groupmember(f->fw_gid,
 1365: 					    P->inp_socket->so_cred))
 1366: 						continue;
 1367: 			    } else
 1368: 				continue;
 1369: 			    break;
 1370: 			}
 1371: 
 1372: 		    default:
 1373: 			    continue;
 1374: 		    }
 1375: 		}
 1376: 		    
 1377: 		/* Protocol specific checks */
 1378: 		switch (proto) {
 1379: 		case IPPROTO_TCP:
 1380: 		    {
 1381: 			struct tcphdr *tcp;
 1382: 
 1383: 			if (offset == 1)	/* cf. RFC 1858 */
 1384: 				goto bogusfrag;
 1385: 			if (offset != 0) {
 1386: 				/*
 1387: 				 * TCP flags and ports aren't available in this
 1388: 				 * packet -- if this rule specified either one,
 1389: 				 * we consider the rule a non-match.
 1390: 				 */
 1391: 				if (IP_FW_HAVEPORTS(f) != 0 ||
 1392: 				    f->fw_tcpopt != f->fw_tcpnopt ||
 1393: 				    f->fw_tcpf != f->fw_tcpnf)
 1394: 					continue;
 1395: 
 1396: 				break;
 1397: 			}
 1398: 			tcp = (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
 1399: 
 1400: 			if (f->fw_tcpopt != f->fw_tcpnopt && !tcpopts_match(tcp, f))
 1401: 				continue;
 1402: 			if (((f->fw_tcpf != f->fw_tcpnf) ||
 1403: 			    (f->fw_ipflg & IP_FW_IF_TCPEST)) &&
 1404: 			    !tcpflg_match(tcp, f))
 1405: 				continue;
 1406: 			goto check_ports;
 1407: 		    }
 1408: 
 1409: 		case IPPROTO_UDP:
 1410: 			if (offset != 0) {
 1411: 				/*
 1412: 				 * Port specification is unavailable -- if this
 1413: 				 * rule specifies a port, we consider the rule
 1414: 				 * a non-match.
 1415: 				 */
 1416: 				if (IP_FW_HAVEPORTS(f) )
 1417: 					continue;
 1418: 
 1419: 				break;
 1420: 			}
 1421: check_ports:
 1422: 			if (!port_match(&f->fw_uar.fw_pts[0],
 1423: 			    IP_FW_GETNSRCP(f), ntohs(src_port),
 1424: 			    f->fw_flg & IP_FW_F_SRNG,
 1425: 			    f->fw_flg & IP_FW_F_SMSK))
 1426: 				continue;
 1427: 			if (!port_match(&f->fw_uar.fw_pts[IP_FW_GETNSRCP(f)],
 1428: 			    IP_FW_GETNDSTP(f), ntohs(dst_port),
 1429: 			    f->fw_flg & IP_FW_F_DRNG,
 1430: 			    f->fw_flg & IP_FW_F_DMSK)) 
 1431: 				continue;
 1432: 			break;
 1433: 
 1434: 		case IPPROTO_ICMP:
 1435: 		    {
 1436: 			struct icmp *icmp;
 1437: 
 1438: 			if (offset != 0)	/* Type isn't valid */
 1439: 				break;
 1440: 			icmp = (struct icmp *) ((u_int32_t *)ip + ip->ip_hl);
 1441: 			if (!icmptype_match(icmp, f))
 1442: 				continue;
 1443: 			break;
 1444: 		    }
 1445: 
 1446: 		default:
 1447: 			break;
 1448: 
 1449: bogusfrag:
 1450: 		if (fw_verbose) {
 1451: 			if (m != NULL)
 1452: 				ipfw_report(NULL, ip, ip_off, ip_len, rif, oif);
 1453: 			else
 1454: 				printf("pullup failed\n");
 1455: 		}
 1456: 		goto dropit;
 1457: 
 1458: 		}
 1459: 
 1460: rnd_then_got_match:
 1461: 		if ( f->dont_match_prob && random() < f->dont_match_prob )
 1462: 			continue ;
 1463: got_match:
 1464: 		/*
 1465: 		 * If not a dynamic match (q == NULL) and keep-state, install
 1466: 		 * a new dynamic entry.
 1467: 		 */
 1468: 		if (q == NULL && f->fw_flg & IP_FW_F_KEEP_S) {
 1469: 		    if (install_state(f, args)) /* error or limit violation */
 1470: 			goto dropit;
 1471: 		}
 1472: 		/* Update statistics */
 1473: 		f->fw_pcnt += 1;
 1474: 		f->fw_bcnt += ip_len;
 1475: 		f->timestamp = time_second;
 1476: 
 1477: 		/* Log to console if desired */
 1478: 		if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose && hlen > 0)
 1479: 			ipfw_report(f, ip, offset, ip_len, rif, oif);
 1480: 
 1481: 		/* Take appropriate action */
 1482: 		switch (f->fw_flg & IP_FW_F_COMMAND) {
 1483: 		case IP_FW_F_ACCEPT:
 1484: 			return(0);
 1485: 		case IP_FW_F_COUNT:
 1486: 			continue;
 1487: #ifdef IPDIVERT
 1488: 		case IP_FW_F_DIVERT:
 1489: 			*cookie = f->fw_number;
 1490: 			return(f->fw_divert_port);
 1491: 		case IP_FW_F_TEE:
 1492: 			*cookie = f->fw_number;
 1493: 			return(f->fw_divert_port | IP_FW_PORT_TEE_FLAG);
 1494: #endif
 1495: 		case IP_FW_F_SKIPTO: /* XXX check */
 1496: 			if (f->next_rule_ptr == NULL)
 1497: 			    f->next_rule_ptr = lookup_next_rule(f) ;
 1498: 			f = f->next_rule_ptr;
 1499: 			if (!f)
 1500: 			    goto dropit;
 1501: 			goto again ;
 1502: 
 1503: 		case IP_FW_F_PIPE:
 1504: 		case IP_FW_F_QUEUE:
 1505: 			*flow_id = f ; /* XXX set flow id */
 1506: 			return(f->fw_pipe_nr | IP_FW_PORT_DYNT_FLAG);
 1507: 
 1508: 		case IP_FW_F_FWD:
 1509: 			/* Change the next-hop address for this packet.
 1510: 			 * Initially we'll only worry about directly
 1511: 			 * reachable next-hop's, but ultimately
 1512: 			 * we will work out for next-hops that aren't
 1513: 			 * direct the route we would take for it. We
 1514: 			 * [cs]ould leave this latter problem to
 1515: 			 * ip_output.c. We hope to high [name the abode of
 1516: 			 * your favourite deity] that ip_output doesn't modify
 1517: 			 * the new value of next_hop (which is dst there)
 1518: 			 * XXX warning-- there is a dangerous reference here
 1519: 			 * from next_hop to a field within the rule. If the
 1520: 			 * rule is deleted, weird things might occur.
 1521: 			 */
 1522: 			if (next_hop != NULL /* Make sure, first... */
 1523: 			    && (q == NULL || direction == MATCH_FORWARD) )
 1524: 				*next_hop = &(f->fw_fwd_ip);
 1525: 			return(0); /* Allow the packet */
 1526: 
 1527: 		}
 1528: 
 1529: 		/* Deny/reject this packet using this rule */
 1530: 		break;
 1531: 	}
 1532: 
 1533: 	/* Rule IPFW_DEFAULT_RULE should always be there and match */
 1534: 	KASSERT(f != NULL, ("ip_fw: no chain"));
 1535: 
 1536: 	/*
 1537: 	 * At this point, we're going to drop the packet.
 1538: 	 * Send a reject notice if all of the following are true:
 1539: 	 *
 1540: 	 * - The packet matched a reject rule
 1541: 	 * - The packet is not an ICMP packet, or is an ICMP query packet
 1542: 	 * - The packet is not a multicast or broadcast packet
 1543: 	 */
 1544: 	if ((f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
 1545: 	    && (proto != IPPROTO_ICMP || is_icmp_query(ip))
 1546: 	    && !((*m)->m_flags & (M_BCAST|M_MCAST))
 1547: 	    && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
 1548: 		/* Must convert to host order for icmp_error() etc. */
 1549: 		if (BRIDGED) {
 1550: 			ip->ip_len = ntohs(ip->ip_len);
 1551: 			ip->ip_off = ntohs(ip->ip_off);
 1552: 		}
 1553: 		switch (f->fw_reject_code) {
 1554: 		case IP_FW_REJECT_RST:
 1555: 		  {
 1556: 			/* XXX warning, this code writes into the mbuf */
 1557: 			struct tcphdr *const tcp =
 1558: 				(struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
 1559: 			struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip;
 1560: 
 1561: 			if (offset != 0 || (tcp->th_flags & TH_RST))
 1562: 				break;
 1563: 			ti.ti_i = *((struct ipovly *) ip);
 1564: 			ti.ti_t = *tcp;
 1565: 			bcopy(&ti, ip, sizeof(ti));
 1566: 			NTOHL(tip->ti_seq);
 1567: 			NTOHL(tip->ti_ack);
 1568: 			tip->ti_len = ip_len - hlen - (tip->ti_off << 2);
 1569: 			if (tcp->th_flags & TH_ACK) {
 1570: 				tcp_respond(NULL, (void *)ip, tcp, *m,
 1571: 				    (tcp_seq)0, tcp->th_ack, TH_RST);
 1572: 			} else {
 1573: 				if (tcp->th_flags & TH_SYN)
 1574: 					tip->ti_len++;
 1575: 				tcp_respond(NULL, (void *)ip, tcp, *m, 
 1576: 				    tip->ti_seq + tip->ti_len,
 1577: 				    (tcp_seq)0, TH_RST|TH_ACK);
 1578: 			}
 1579: 			*m = NULL;
 1580: 			break;
 1581: 		  }
 1582: 		default:	/* Send an ICMP unreachable using code */
 1583: 			icmp_error(*m, ICMP_UNREACH,
 1584: 			    f->fw_reject_code, 0L, 0);
 1585: 			*m = NULL;
 1586: 			break;
 1587: 		}
 1588: 	}
 1589: 
 1590: dropit:
 1591: 	/*
 1592: 	 * Finally, drop the packet.
 1593: 	 */
 1594: 	return(IP_FW_PORT_DENY_FLAG);
 1595: #undef BRIDGED
 1596: }
 1597: 
 1598: /*
 1599:  * when a rule is added/deleted, zero the direct pointers within
 1600:  * all firewall rules. These will be reconstructed on the fly
 1601:  * as packets are matched.
 1602:  * Must be called at splimp().
 1603:  */
 1604: static void
 1605: flush_rule_ptrs()
 1606: {
 1607:     struct ip_fw *fcp ;
 1608: 
 1609:     LIST_FOREACH(fcp, &ip_fw_chain_head, next) {
 1610: 	fcp->next_rule_ptr = NULL ;
 1611:     }
 1612: }
 1613: 
 1614: void
 1615: flush_pipe_ptrs(struct dn_flow_set *match)
 1616: {
 1617:     struct ip_fw *fcp ;
 1618: 
 1619:     LIST_FOREACH(fcp, &ip_fw_chain_head, next) {
 1620: 	if (match == NULL || fcp->pipe_ptr == match)
 1621: 		fcp->pipe_ptr = NULL;
 1622:     }
 1623: }
 1624: 
 1625: static int
 1626: add_entry(struct ip_fw_head *head, struct ip_fw *rule)
 1627: {
 1628: 	struct ip_fw *ftmp, *fcp, *fcpl;
 1629: 	u_short nbr = 0;
 1630: 	int s;
 1631: 
 1632: 	ftmp = malloc(sizeof *ftmp, M_IPFW, M_WAITOK | M_ZERO);
 1633: 	if (!ftmp)
 1634: 		return (ENOSPC);
 1635: 	bcopy(rule, ftmp, sizeof(*ftmp));
 1636: 
 1637: 	ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0';
 1638: 	ftmp->fw_pcnt = 0L;
 1639: 	ftmp->fw_bcnt = 0L;
 1640: 	ftmp->next_rule_ptr = NULL ;
 1641: 	ftmp->pipe_ptr = NULL ;
 1642: 	
 1643: 	s = splimp();
 1644: 
 1645: 	if (LIST_FIRST(head) == 0) {
 1646: 		LIST_INSERT_HEAD(head, ftmp, next);
 1647: 		goto done;
 1648:         }
 1649: 
 1650: 	/* If entry number is 0, find highest numbered rule and add 100 */
 1651: 	if (ftmp->fw_number == 0) {
 1652: 		LIST_FOREACH(fcp, head, next) {
 1653: 			if (fcp->fw_number != IPFW_DEFAULT_RULE)
 1654: 				nbr = fcp->fw_number;
 1655: 			else
 1656: 				break;
 1657: 		}
 1658: 		if (nbr < IPFW_DEFAULT_RULE - 100)
 1659: 			nbr += 100;
 1660: 		ftmp->fw_number = rule->fw_number = nbr;
 1661: 	}
 1662: 
 1663: 	/* Got a valid number; now insert it, keeping the list ordered */
 1664: 	fcpl = NULL ;
 1665: 	LIST_FOREACH(fcp, head, next) {
 1666: 		if (fcp->fw_number > ftmp->fw_number) {
 1667: 			if (fcpl) {
 1668: 				LIST_INSERT_AFTER(fcpl, ftmp, next);
 1669: 			} else {
 1670: 				LIST_INSERT_HEAD(head, ftmp, next);
 1671: 			}
 1672: 			break;
 1673: 		} else {
 1674: 			fcpl = fcp;
 1675: 		}
 1676: 	}
 1677: 	flush_rule_ptrs();
 1678: done:
 1679: 	static_count++;
 1680: 	splx(s);
 1681: 	DEB(printf("++ installed rule %d, static count now %d\n",
 1682: 		ftmp->fw_number, static_count);)
 1683: 	return (0);
 1684: }
 1685: 
 1686: /**
 1687:  * free storage associated with a static rule entry (including
 1688:  * dependent dynamic rules), and zeroes rule pointers to avoid
 1689:  * dangling pointer dereferences.
 1690:  * @return a pointer to the next entry.
 1691:  * Must be called at splimp() and with a non-null argument.
 1692:  */
 1693: static struct ip_fw *
 1694: free_chain(struct ip_fw *fcp)
 1695: {
 1696:     struct ip_fw *n;
 1697: 
 1698:     n = LIST_NEXT(fcp, next);
 1699:     DELETE_DYN_CHAIN(fcp);
 1700:     LIST_REMOVE(fcp, next);
 1701:     static_count--;
 1702:     if (DUMMYNET_LOADED)
 1703: 	ip_dn_ruledel_ptr(fcp) ;
 1704:     flush_rule_ptrs(); /* more efficient to do outside the loop */
 1705:     free(fcp, M_IPFW);
 1706:     return n;
 1707: }
 1708: 
 1709: /**
 1710:  * remove all rules with given number.
 1711:  */
 1712: static int
 1713: del_entry(struct ip_fw_head *chainptr, u_short number)
 1714: {
 1715:     struct ip_fw *rule;
 1716: 
 1717:     if (number != IPFW_DEFAULT_RULE) {
 1718: 	LIST_FOREACH(rule, chainptr, next) {
 1719: 	    if (rule->fw_number == number) {
 1720: 		int s ;
 1721: 
 1722: 		s = splimp(); /* prevent access to rules while removing */
 1723: 		while (rule && rule->fw_number == number)
 1724: 		    rule = free_chain(rule);
 1725: 		/* XXX could move flush_rule_ptrs() here */
 1726: 		splx(s);
 1727: 		return 0 ;
 1728: 	    }
 1729: 	}
 1730:     }
 1731:     return (EINVAL);
 1732: }
 1733: 
 1734: /**
 1735:  * Reset some or all counters on firewall rules.
 1736:  * @arg frwl is null to clear all entries, or contains a specific
 1737:  * rule number.
 1738:  * @arg log_only is 1 if we only want to reset logs, zero otherwise.
 1739:  */
 1740: 
 1741: static int
 1742: zero_entry(struct ip_fw *frwl, int log_only)
 1743: {
 1744:     struct ip_fw *rule;
 1745:     int s;
 1746:     u_short number = 0 ;
 1747:     char *msg ;
 1748: 
 1749:     if (frwl == 0) {
 1750: 	s = splimp();
 1751: 	LIST_FOREACH(rule, &ip_fw_chain_head, next) {
 1752: 	    if (log_only == 0) {
 1753: 		rule->fw_bcnt = rule->fw_pcnt = 0;
 1754: 		rule->timestamp = 0;
 1755: 	    }
 1756: 	    rule->fw_loghighest = rule->fw_pcnt+rule->fw_logamount;
 1757: 	}
 1758: 	splx(s);
 1759: 	msg = log_only ? "ipfw: All logging counts cleared.\n" :
 1760: 			"ipfw: Accounting cleared.\n";
 1761:     } else {
 1762: 	int cleared = 0;
 1763: 	number = frwl->fw_number ;
 1764: 	/*
 1765: 	 * It is possible to insert multiple chain entries with the
 1766: 	 * same number, so we don't stop after finding the first
 1767: 	 * match if zeroing a specific entry.
 1768: 	 */
 1769: 	LIST_FOREACH(rule, &ip_fw_chain_head, next)
 1770: 	    if (number == rule->fw_number) {
 1771: 		s = splimp();
 1772: 		while (rule && number == rule->fw_number) {
 1773: 		    if (log_only == 0) {
 1774: 			rule->fw_bcnt = rule->fw_pcnt = 0;
 1775: 			rule->timestamp = 0;
 1776: 		    }
 1777: 		    rule->fw_loghighest = rule->fw_pcnt+ rule->fw_logamount;
 1778: 		    rule = LIST_NEXT(rule, next);
 1779: 		}
 1780: 		splx(s);
 1781: 		cleared = 1;
 1782: 		break;
 1783: 	    }
 1784: 	if (!cleared)	/* we did not find any matching rules */
 1785: 	    return (EINVAL);
 1786: 	msg = log_only ? "ipfw: Entry %d logging count reset.\n" :
 1787: 			"ipfw: Entry %d cleared.\n";
 1788:     }
 1789:     if (fw_verbose)
 1790: 	log(LOG_SECURITY | LOG_NOTICE, msg, number);
 1791:     return (0);
 1792: }
 1793: 
 1794: static int
 1795: check_ipfw_struct(struct ip_fw *frwl)
 1796: {
 1797: 	/* Check for invalid flag bits */
 1798: 	if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) {
 1799: 		dprintf(("%s undefined flag bits set (flags=%x)\n",
 1800: 		    err_prefix, frwl->fw_flg));
 1801: 		return (EINVAL);
 1802: 	}
 1803: 	if (frwl->fw_flg == IP_FW_F_CHECK_S) {
 1804: 		/* check-state */
 1805: 		return 0 ;
 1806: 	}
 1807: 	/* Must apply to incoming or outgoing (or both) */
 1808: 	if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) {
 1809: 		dprintf(("%s neither in nor out\n", err_prefix));
 1810: 		return (EINVAL);
 1811: 	}
 1812: 	/* Empty interface name is no good */
 1813: 	if (((frwl->fw_flg & IP_FW_F_IIFNAME)
 1814: 	      && !*frwl->fw_in_if.fu_via_if.name)
 1815: 	    || ((frwl->fw_flg & IP_FW_F_OIFNAME)
 1816: 	      && !*frwl->fw_out_if.fu_via_if.name)) {
 1817: 		dprintf(("%s empty interface name\n", err_prefix));
 1818: 		return (EINVAL);
 1819: 	}
 1820: 	/* Sanity check interface matching */
 1821: 	if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
 1822: 		;		/* allow "via" backwards compatibility */
 1823: 	} else if ((frwl->fw_flg & IP_FW_F_IN)
 1824: 	    && (frwl->fw_flg & IP_FW_F_OIFACE)) {
 1825: 		dprintf(("%s outgoing interface check on incoming\n",
 1826: 		    err_prefix));
 1827: 		return (EINVAL);
 1828: 	}
 1829: 	/* Sanity check port ranges */
 1830: 	if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) {
 1831: 		dprintf(("%s src range set but n_src_p=%d\n",
 1832: 		    err_prefix, IP_FW_GETNSRCP(frwl)));
 1833: 		return (EINVAL);
 1834: 	}
 1835: 	if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) {
 1836: 		dprintf(("%s dst range set but n_dst_p=%d\n",
 1837: 		    err_prefix, IP_FW_GETNDSTP(frwl)));
 1838: 		return (EINVAL);
 1839: 	}
 1840: 	if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) {
 1841: 		dprintf(("%s too many ports (%d+%d)\n",
 1842: 		    err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl)));
 1843: 		return (EINVAL);
 1844: 	}
 1845: 	/*
 1846: 	 *	Protocols other than TCP/UDP don't use port range
 1847: 	 */
 1848: 	if ((frwl->fw_prot != IPPROTO_TCP) &&
 1849: 	    (frwl->fw_prot != IPPROTO_UDP) &&
 1850: 	    (IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) {
 1851: 		dprintf(("%s port(s) specified for non TCP/UDP rule\n",
 1852: 		    err_prefix));
 1853: 		return (EINVAL);
 1854: 	}
 1855: 
 1856: 	/*
 1857: 	 *	Rather than modify the entry to make such entries work, 
 1858: 	 *	we reject this rule and require user level utilities
 1859: 	 *	to enforce whatever policy they deem appropriate.
 1860: 	 */
 1861: 	if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) || 
 1862: 		(frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) {
 1863: 		dprintf(("%s rule never matches\n", err_prefix));
 1864: 		return (EINVAL);
 1865: 	}
 1866: 
 1867: 	if ((frwl->fw_flg & IP_FW_F_FRAG) &&
 1868: 		(frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {
 1869: 		if (IP_FW_HAVEPORTS(frwl)) {
 1870: 			dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));
 1871: 			return (EINVAL);
 1872: 		}
 1873: 		if (frwl->fw_prot == IPPROTO_TCP &&
 1874: 			frwl->fw_tcpf != frwl->fw_tcpnf) {
 1875: 			dprintf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
 1876: 			return (EINVAL);
 1877: 		}
 1878: 	}
 1879: 
 1880: 	/* Check command specific stuff */
 1881: 	switch (frwl->fw_flg & IP_FW_F_COMMAND) {
 1882: 	case IP_FW_F_REJECT:
 1883: 		if (frwl->fw_reject_code >= 0x100
 1884: 		    && !(frwl->fw_prot == IPPROTO_TCP
 1885: 		      && frwl->fw_reject_code == IP_FW_REJECT_RST)) {
 1886: 			dprintf(("%s unknown reject code\n", err_prefix));
 1887: 			return (EINVAL);
 1888: 		}
 1889: 		break;
 1890: #ifdef IPDIVERT
 1891: 	case IP_FW_F_DIVERT:		/* Diverting to port zero is invalid */
 1892: 	case IP_FW_F_TEE:
 1893: #endif
 1894: 	case IP_FW_F_PIPE:              /* pipe 0 is invalid */
 1895: 	case IP_FW_F_QUEUE:             /* queue 0 is invalid */
 1896: 		if (frwl->fw_divert_port == 0) {
 1897: 			dprintf(("%s 0 is an invalid argument\n", err_prefix));
 1898: 			return (EINVAL);
 1899: 		}
 1900: 		break;
 1901: 	case IP_FW_F_DENY:
 1902: 	case IP_FW_F_ACCEPT:
 1903: 	case IP_FW_F_COUNT:
 1904: 	case IP_FW_F_SKIPTO:
 1905: 	case IP_FW_F_FWD:
 1906: 	case IP_FW_F_UID:
 1907: 	case IP_FW_F_GID:
 1908: 		break;
 1909: 	default:
 1910: 		dprintf(("%s invalid command\n", err_prefix));
 1911: 		return (EINVAL);
 1912: 	}
 1913: 
 1914: 	return 0;
 1915: }
 1916: 
 1917: static int
 1918: ip_fw_ctl(struct sockopt *sopt)
 1919: {
 1920: 	int error, s;
 1921: 	size_t size;
 1922: 	struct ip_fw *fcp;
 1923: 	struct ip_fw frwl, *bp , *buf;
 1924: 
 1925: 	/*
 1926: 	 * Disallow modifications in really-really secure mode, but still allow
 1927: 	 * the logging counters to be reset.
 1928: 	 */
 1929: 	if (securelevel >= 3 && (sopt->sopt_name == IP_FW_ADD ||
 1930: 	    (sopt->sopt_dir == SOPT_SET && sopt->sopt_name != IP_FW_RESETLOG)))
 1931: 			return (EPERM);
 1932: 	error = 0;
 1933: 
 1934: 	switch (sopt->sopt_name) {
 1935: 	case IP_FW_GET:
 1936: 		/*
 1937: 		 * pass up a copy of the current rules. Static rules
 1938: 		 * come first (the last of which has number 65535),
 1939: 		 * followed by a possibly empty list of dynamic rule.
 1940: 		 * The last dynamic rule has NULL in the "next" field.
 1941: 		 */
 1942: 		s = splimp();
 1943: 		/* size of static rules */
 1944: 		size = static_count * sizeof(struct ip_fw) ;
 1945: 		if (ipfw_dyn_v)		/* add size of dyn.rules */
 1946: 		    size += (dyn_count * sizeof(struct ipfw_dyn_rule));
 1947: 
 1948: 		/*
 1949: 		 * XXX todo: if the user passes a short length to know how
 1950: 		 * much room is needed, do not
 1951: 		 * bother filling up the buffer, just jump to the
 1952: 		 * sooptcopyout.
 1953: 		 */
 1954: 		buf = malloc(size, M_TEMP, M_WAITOK);
 1955: 
 1956: 		bp = buf ;
 1957: 		LIST_FOREACH(fcp, &ip_fw_chain_head, next) {
 1958: 		    bcopy(fcp, bp, sizeof *fcp);
 1959: 		    bp++;
 1960: 		}
 1961: 		if (ipfw_dyn_v) {
 1962: 		    int i ;
 1963: 		    struct ipfw_dyn_rule *p, *dst, *last = NULL ;
 1964: 
 1965: 		    dst = (struct ipfw_dyn_rule *)bp ;
 1966: 		    for (i = 0 ; i < curr_dyn_buckets ; i++ )
 1967: 			for ( p = ipfw_dyn_v[i] ; p != NULL ; p = p->next, dst++ ) {
 1968: 			    bcopy(p, dst, sizeof *p);
 1969:                             (int)dst->rule = p->rule->fw_number ;
 1970: 			    /*
 1971: 			     * store a non-null value in "next". The userland
 1972: 			     * code will interpret a NULL here as a marker
 1973: 			     * for the last dynamic rule.
 1974: 			     */
 1975:                             dst->next = dst ;
 1976: 			    last = dst ;
 1977: 			    if (TIME_LEQ(dst->expire, time_second) )
 1978: 				dst->expire = 0 ;
 1979: 			    else
 1980: 				dst->expire -= time_second ;
 1981: 			    }
 1982: 		    if (last != NULL)
 1983: 			last->next = NULL ; /* mark last dynamic rule */
 1984: 		}
 1985: 		splx(s);
 1986: 
 1987: 		error = sooptcopyout(sopt, buf, size);
 1988: 		free(buf, M_TEMP);
 1989: 		break;
 1990: 
 1991: 	case IP_FW_FLUSH:
 1992: 		/*
 1993: 		 * Normally we cannot release the lock on each iteration.
 1994: 		 * We could do it here only because we start from the head all
 1995: 		 * the times so there is no risk of missing some entries.
 1996: 		 * On the other hand, the risk is that we end up with
 1997: 		 * a very inconsistent ruleset, so better keep the lock
 1998: 		 * around the whole cycle.
 1999: 		 * 
 2000: 		 * XXX this code can be improved by resetting the head of
 2001: 		 * the list to point to the default rule, and then freeing
 2002: 		 * the old list without the need for a lock.
 2003: 		 */
 2004: 
 2005: 		s = splimp();
 2006: 		while ( (fcp = LIST_FIRST(&ip_fw_chain_head)) &&
 2007: 			fcp->fw_number != IPFW_DEFAULT_RULE )
 2008: 		    free_chain(fcp);
 2009: 		splx(s);
 2010: 		break;
 2011: 
 2012: 	case IP_FW_ADD:
 2013: 		error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
 2014: 		if (error || (error = check_ipfw_struct(&frwl)))
 2015: 			break;
 2016: 
 2017: 		if (frwl.fw_number == IPFW_DEFAULT_RULE) {
 2018: 			dprintf(("%s can't add rule %u\n", err_prefix,
 2019: 				 (unsigned)IPFW_DEFAULT_RULE));
 2020: 			error = EINVAL;
 2021: 		} else {
 2022: 			error = add_entry(&ip_fw_chain_head, &frwl);
 2023: 			if (!error && sopt->sopt_dir == SOPT_GET)
 2024: 				error = sooptcopyout(sopt, &frwl, sizeof frwl);
 2025: 		}
 2026: 		break;
 2027: 
 2028: 	case IP_FW_DEL:
 2029: 		error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
 2030: 		if (error)
 2031: 			break;
 2032: 
 2033: 		if (frwl.fw_number == IPFW_DEFAULT_RULE) {
 2034: 			dprintf(("%s can't delete rule %u\n", err_prefix,
 2035: 				 (unsigned)IPFW_DEFAULT_RULE));
 2036: 			error = EINVAL;
 2037: 		} else {
 2038: 			error = del_entry(&ip_fw_chain_head, frwl.fw_number);
 2039: 		}
 2040: 		break;
 2041: 
 2042: 	case IP_FW_ZERO:
 2043: 	case IP_FW_RESETLOG:
 2044: 	    {
 2045: 		int cmd = (sopt->sopt_name == IP_FW_RESETLOG );
 2046: 		void *arg = NULL ;
 2047: 
 2048: 		if (sopt->sopt_val != 0) {
 2049: 		    error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
 2050: 		    if (error)
 2051: 			break;
 2052: 		    arg = &frwl ;
 2053: 		}
 2054: 		error = zero_entry(arg, cmd);
 2055: 	    }
 2056: 	    break;
 2057: 
 2058: 	default:
 2059: 		printf("ip_fw_ctl invalid option %d\n", sopt->sopt_name);
 2060: 		error = EINVAL ;
 2061: 	}
 2062: 
 2063: 	return (error);
 2064: }
 2065: 
 2066: /**
 2067:  * dummynet needs a reference to the default rule, because rules can
 2068:  * be deleted while packets hold a reference to them (e.g. to resume
 2069:  * processing at the next rule). When this happens, dummynet changes
 2070:  * the reference to the default rule (probably it could well be a
 2071:  * NULL pointer, but this way we do not need to check for the special
 2072:  * case, plus here he have info on the default behaviour.
 2073:  */
 2074: struct ip_fw *ip_fw_default_rule ;
 2075: 
 2076: void
 2077: ip_fw_init(void)
 2078: {
 2079: 	struct ip_fw default_rule;
 2080: 
 2081: 	ip_fw_chk_ptr = ip_fw_chk;
 2082: 	ip_fw_ctl_ptr = ip_fw_ctl;
 2083: 	LIST_INIT(&ip_fw_chain_head);
 2084: 
 2085: 	bzero(&default_rule, sizeof default_rule);
 2086: 	default_rule.fw_prot = IPPROTO_IP;
 2087: 	default_rule.fw_number = IPFW_DEFAULT_RULE;
 2088: #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
 2089: 	default_rule.fw_flg |= IP_FW_F_ACCEPT;
 2090: #else
 2091: 	default_rule.fw_flg |= IP_FW_F_DENY;
 2092: #endif
 2093: 	default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;
 2094: 	if (check_ipfw_struct(&default_rule) != 0 ||
 2095: 	    add_entry(&ip_fw_chain_head, &default_rule))
 2096: 		panic("ip_fw_init");
 2097: 
 2098: 	ip_fw_default_rule = LIST_FIRST(&ip_fw_chain_head) ;
 2099: 	printf("IP packet filtering initialized, "
 2100: #ifdef IPDIVERT
 2101: 		"divert enabled, "
 2102: #else
 2103: 		"divert disabled, "
 2104: #endif
 2105: 		"rule-based forwarding enabled, "
 2106: #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
 2107: 		"default to accept, ");
 2108: #else
 2109: 		"default to deny, " );
 2110: #endif
 2111: #ifndef IPFIREWALL_VERBOSE
 2112: 	printf("logging disabled\n");
 2113: #else
 2114: 	if (fw_verbose_limit == 0)
 2115: 		printf("unlimited logging\n");
 2116: 	else
 2117: 		printf("logging limited to %d packets/entry by default\n",
 2118: 		    fw_verbose_limit);
 2119: #endif
 2120: }
 2121: 
 2122: static int
 2123: ipfw_modevent(module_t mod, int type, void *unused)
 2124: {
 2125: 	int s;
 2126: 	int err = 0 ;
 2127: #if defined(KLD_MODULE)
 2128: 	struct ip_fw *fcp;
 2129: #endif
 2130: 	
 2131: 	switch (type) {
 2132: 	case MOD_LOAD:
 2133: 		s = splimp();
 2134: 		if (IPFW_LOADED) {
 2135: 			splx(s);
 2136: 			printf("IP firewall already loaded\n");
 2137: 			err = EEXIST ;
 2138: 		} else {
 2139: 			ip_fw_init();
 2140: 			splx(s);
 2141: 		}
 2142: 		break ;
 2143: 	case MOD_UNLOAD:
 2144: #if !defined(KLD_MODULE)
 2145: 		printf("ipfw statically compiled, cannot unload\n");
 2146: 		err = EBUSY;
 2147: #else
 2148: 		s = splimp();
 2149: 		ip_fw_chk_ptr = NULL ;
 2150: 		ip_fw_ctl_ptr = NULL ;
 2151: 		while ( (fcp = LIST_FIRST(&ip_fw_chain_head)) != NULL)
 2152: 			free_chain(fcp);
 2153: 		splx(s);
 2154: 		printf("IP firewall unloaded\n");
 2155: #endif
 2156: 		break ;
 2157: 
 2158: 	default:
 2159: 		break;
 2160: 	}
 2161: 	return err;
 2162: }
 2163: 
 2164: static moduledata_t ipfwmod = {
 2165: 	"ipfw",
 2166: 	ipfw_modevent,
 2167: 	0
 2168: };
 2169: DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
 2170: #endif /* !IPFW2 */