From owner-p4-projects@FreeBSD.ORG Thu Jan 11 18:11:58 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3A15516A4B3; Thu, 11 Jan 2007 18:11:58 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EACAF16A4A0 for ; Thu, 11 Jan 2007 18:11:57 +0000 (UTC) (envelope-from zec@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id DB34D13C44C for ; Thu, 11 Jan 2007 18:11:57 +0000 (UTC) (envelope-from zec@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id l0BIBvld028818 for ; Thu, 11 Jan 2007 18:11:57 GMT (envelope-from zec@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id l0BIBv7w028815 for perforce@freebsd.org; Thu, 11 Jan 2007 18:11:57 GMT (envelope-from zec@FreeBSD.org) Date: Thu, 11 Jan 2007 18:11:57 GMT Message-Id: <200701111811.l0BIBv7w028815@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to zec@FreeBSD.org using -f From: Marko Zec To: Perforce Change Reviews Cc: Subject: PERFORCE change 112781 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jan 2007 18:11:58 -0000 http://perforce.freebsd.org/chv.cgi?CH=112781 Change 112781 by zec@zec_tca51 on 2007/01/11 18:11:40 First pass at virtualizing ipfw. Affected files ... .. //depot/projects/vimage/src/sys/net/if_ethersubr.c#6 edit .. //depot/projects/vimage/src/sys/netinet/ip_fw.h#3 edit .. //depot/projects/vimage/src/sys/netinet/ip_fw2.c#5 edit .. //depot/projects/vimage/src/sys/netinet/ip_fw_pfil.c#3 edit .. //depot/projects/vimage/src/sys/sys/vimage.h#10 edit Differences ... ==== //depot/projects/vimage/src/sys/net/if_ethersubr.c#6 (text+ko) ==== @@ -131,8 +131,10 @@ int ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, struct ip_fw **rule, int shared); +#ifndef VIMAGE static int ether_ipfw; #endif +#endif /* * Ethernet output routine. @@ -380,9 +382,10 @@ { int error; #if defined(INET) || defined(INET6) + INIT_VNET_IPFW(ifp->if_vnetb); struct ip_fw *rule = ip_dn_claim_rule(m); - if (IPFW_LOADED && ether_ipfw != 0) { + if (IPFW_LOADED && V_ether_ipfw != 0) { if (ether_ipfw_chk(&m, ifp, &rule, 0) == 0) { if (m) { m_freem(m); @@ -411,13 +414,14 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, struct ip_fw **rule, int shared) { + INIT_VNET_IPFW(dst->if_vnetb); struct ether_header *eh; struct ether_header save_eh; struct mbuf *m; int i; struct ip_fw_args args; - if (*rule != NULL && fw_one_pass) + if (*rule != NULL && V_fw_one_pass) return 1; /* dummynet packet, already partially processed */ /* @@ -704,7 +708,8 @@ #if defined(INET) || defined(INET6) post_stats: - if (IPFW_LOADED && ether_ipfw != 0) { + INIT_VNET_IPFW(ifp->if_vnetb); + if (IPFW_LOADED && V_ether_ipfw != 0) { if (ether_ipfw_chk(&m, NULL, &rule, 0) == 0) { if (m) m_freem(m); @@ -930,8 +935,8 @@ SYSCTL_DECL(_net_link); SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); #if defined(INET) || defined(INET6) -SYSCTL_INT(_net_link_ether, OID_AUTO, ipfw, CTLFLAG_RW, - ðer_ipfw,0,"Pass ether pkts through firewall"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_link_ether, OID_AUTO, ipfw, CTLFLAG_RW, + ether_ipfw, 0, "Pass ether pkts through firewall"); #endif #if 0 ==== //depot/projects/vimage/src/sys/netinet/ip_fw.h#3 (text+ko) ==== @@ -28,6 +28,9 @@ #ifndef _IPFW2_H #define _IPFW2_H +#include +#include + /* * The kernel representation of ipfw rules is made of a list of * 'instructions' (for all practical purposes equivalent to BPF @@ -533,6 +536,34 @@ */ #ifdef _KERNEL +/* + * Data structure to cache our ucred related + * information. This structure only gets used if + * the user specified UID/GID based constraints in + * a firewall rule. + */ +struct ip_fw_ugid { + gid_t fw_groups[NGROUPS]; + int fw_ngroups; + uid_t fw_uid; + int fw_prid; +}; + +#define IPFW_TABLES_MAX 128 +struct ip_fw_chain { + struct ip_fw *rules; /* list of rules */ + struct ip_fw *reap; /* list of rules to reap */ + LIST_HEAD(, cfg_nat) nat; /* list of nat entries */ + struct radix_node_head *tables[IPFW_TABLES_MAX]; + struct rwlock rwmtx; +}; + +struct table_entry { + struct radix_node rn[2]; + struct sockaddr_in addr, mask; + u_int32_t value; +}; + /* Return values from ipfw_chk() */ enum { IP_FW_PASS = 0, @@ -602,16 +633,109 @@ typedef int ip_fw_ctl_t(struct sockopt *); extern ip_fw_ctl_t *ip_fw_ctl_ptr; + +#ifndef VIMAGE extern int fw_one_pass; extern int fw_enable; #ifdef INET6 extern int fw6_enable; #endif +#endif /* For kernel ipfw_ether and ipfw_bridge. */ typedef int ip_fw_chk_t(struct ip_fw_args *args); extern ip_fw_chk_t *ip_fw_chk_ptr; #define IPFW_LOADED (ip_fw_chk_ptr != NULL) +/* + * Stack virtualization support. + */ + +#ifdef VIMAGE +struct vnet_ipfw { + struct vnet_base *parent_vnetb; + + int _fw_one_pass; + int _fw_enable; + int _fw6_enable; + int _ether_ipfw; + + u_int32_t _set_disable; + int _fw_deny_unknown_exthdrs; + int _fw_verbose; + int _verbose_limit; + int _fw_debug; + int _autoinc_step; + + ipfw_dyn_rule **_ipfw_dyn_v; + struct ip_fw_chain _layer3_chain; + u_int32_t _dyn_buckets; + u_int32_t _curr_dyn_buckets; + + u_int32_t _dyn_ack_lifetime; + u_int32_t _dyn_syn_lifetime; + u_int32_t _dyn_fin_lifetime; + u_int32_t _dyn_rst_lifetime; + u_int32_t _dyn_udp_lifetime; + u_int32_t _dyn_short_lifetime; + u_int32_t _dyn_keepalive_interval; + u_int32_t _dyn_keepalive_period; + u_int32_t _dyn_keepalive; + u_int32_t _static_count; + u_int32_t _static_len; + u_int32_t _dyn_count; + u_int32_t _dyn_max; + + u_int64_t _norule_counter; + + struct callout _ipfw_timeout; +}; +#endif + +/* + * Symbol translation macros + */ + +#define INIT_VNET_IPFW(vnetb) \ + INIT_FROM_VNET_BASE(vnetb, VNET_MOD_IPFW, \ + struct vnet_ipfw, vnet_ipfw) + +#define VNET_IPFW(sym) VSYM(vnet_ipfw, sym) + +#define V_fw_one_pass VNET_IPFW(fw_one_pass) +#define V_fw_enable VNET_IPFW(fw_enable) +#define V_fw6_enable VNET_IPFW(fw6_enable) +#define V_ether_ipfw VNET_IPFW(ether_ipfw) + +#define V_set_disable VNET_IPFW(set_disable) +#define V_fw_deny_unknown_exthdrs VNET_IPFW(fw_deny_unknown_exthdrs) +#define V_fw_verbose VNET_IPFW(fw_verbose) +#define V_verbose_limit VNET_IPFW(verbose_limit) + +#define V_fw_debug VNET_IPFW(fw_debug) +#define V_autoinc_step VNET_IPFW(autoinc_step) + +#define V_ipfw_dyn_v VNET_IPFW(ipfw_dyn_v) +#define V_layer3_chain VNET_IPFW(layer3_chain) +#define V_dyn_buckets VNET_IPFW(dyn_buckets) +#define V_curr_dyn_buckets VNET_IPFW(curr_dyn_buckets) + +#define V_dyn_ack_lifetime VNET_IPFW(dyn_ack_lifetime) +#define V_dyn_syn_lifetime VNET_IPFW(dyn_syn_lifetime) +#define V_dyn_fin_lifetime VNET_IPFW(dyn_fin_lifetime) +#define V_dyn_rst_lifetime VNET_IPFW(dyn_rst_lifetime) +#define V_dyn_udp_lifetime VNET_IPFW(dyn_udp_lifetime) +#define V_dyn_short_lifetime VNET_IPFW(dyn_short_lifetime) +#define V_dyn_keepalive_interval VNET_IPFW(dyn_keepalive_interval) +#define V_dyn_keepalive_period VNET_IPFW(dyn_keepalive_period) +#define V_dyn_keepalive VNET_IPFW(dyn_keepalive) +#define V_static_count VNET_IPFW(static_count) +#define V_static_len VNET_IPFW(static_len) +#define V_dyn_count VNET_IPFW(dyn_count) +#define V_dyn_max VNET_IPFW(dyn_max) + +#define V_norule_counter VNET_IPFW(norule_counter) +#define V_ipfw_timeout VNET_IPFW(ipfw_timeout) + #endif /* _KERNEL */ #endif /* _IPFW2_H */ ==== //depot/projects/vimage/src/sys/netinet/ip_fw2.c#5 (text+ko) ==== @@ -114,6 +114,19 @@ #include +static int vnet_ipfw_iattach(void); + +#ifdef VIMAGE +static struct vnet_modinfo vnet_ipfw_modinfo = { + .id = VNET_MOD_IPFW, + .flags = VNET_MFLAG_ORDER_2ND, + .name = "ipfw", + .symmap = NULL, + .i_attach = vnet_ipfw_iattach, + .i_detach = NULL, +}; +#endif + /* * set_disable contains one bit per set value (0..31). * If the bit is set, all rules with the corresponding set @@ -122,41 +135,23 @@ * and CANNOT be disabled. * Rules in set RESVD_SET can only be deleted explicitly. */ +#ifndef VIMAGE static u_int32_t set_disable; static int fw_verbose; static int verbose_limit; static struct callout ipfw_timeout; +#endif + static uma_zone_t ipfw_dyn_rule_zone; #define IPFW_DEFAULT_RULE 65535 -/* - * Data structure to cache our ucred related - * information. This structure only gets used if - * the user specified UID/GID based constraints in - * a firewall rule. - */ -struct ip_fw_ugid { - gid_t fw_groups[NGROUPS]; - int fw_ngroups; - uid_t fw_uid; - int fw_prid; -}; - -#define IPFW_TABLES_MAX 128 -struct ip_fw_chain { - struct ip_fw *rules; /* list of rules */ - struct ip_fw *reap; /* list of rules to reap */ - LIST_HEAD(, cfg_nat) nat; /* list of nat entries */ - struct radix_node_head *tables[IPFW_TABLES_MAX]; - struct rwlock rwmtx; -}; #define IPFW_LOCK_INIT(_chain) \ rw_init(&(_chain)->rwmtx, "IPFW static rules") #define IPFW_LOCK_DESTROY(_chain) rw_destroy(&(_chain)->rwmtx) #define IPFW_WLOCK_ASSERT(_chain) do { \ - rw_assert(&(_chain)->rwmtx, RA_WLOCKED); \ + rw_assert(&(_chain)->rwmtx, RA_WLOCKED); \ NET_ASSERT_GIANT(); \ } while (0) @@ -168,40 +163,42 @@ /* * list of rules for layer 3 */ +#ifndef VIMAGE static struct ip_fw_chain layer3_chain; +#endif MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's"); MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables"); -struct table_entry { - struct radix_node rn[2]; - struct sockaddr_in addr, mask; - u_int32_t value; -}; +#ifndef VIMAGE +static int fw_debug; +static int autoinc_step; +#endif -static int fw_debug = 1; -static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */ - +#ifdef VIMAGE +extern int ipfw_chg_hook(SYSCTL_HANDLER_V_ARGS); +#else extern int ipfw_chg_hook(SYSCTL_HANDLER_ARGS); +#endif #ifdef SYSCTL_NODE SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall"); -SYSCTL_PROC(_net_inet_ip_fw, OID_AUTO, enable, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &fw_enable, 0, +SYSCTL_V_PROC(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, enable, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, fw_enable, 0, ipfw_chg_hook, "I", "Enable ipfw"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step, CTLFLAG_RW, - &autoinc_step, 0, "Rule number autincrement step"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, one_pass, - CTLFLAG_RW | CTLFLAG_SECURE3, - &fw_one_pass, 0, +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, autoinc_step, + CTLFLAG_RW, autoinc_step, 0, "Rule number autincrement step"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, one_pass, + CTLFLAG_RW | CTLFLAG_SECURE3, fw_one_pass, 0, "Only do a single pass through ipfw when using dummynet(4)"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, - &fw_debug, 0, "Enable printing of debug ip_fw statements"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose, +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, + fw_debug, 0, "Enable printing of debug ip_fw statements"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW | CTLFLAG_SECURE3, - &fw_verbose, 0, "Log matches to ipfw rules"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, - &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged"); + fw_verbose, 0, "Log matches to ipfw rules"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose_limit, + CTLFLAG_RW, + verbose_limit, 0, "Set upper limit of matches of ipfw rules logged"); /* * Description of dynamic rules. @@ -239,9 +236,11 @@ * obey the 'randomized match', and we do not do multiple * passes through the firewall. XXX check the latter!!! */ +#ifndef VIMAGE static ipfw_dyn_rule **ipfw_dyn_v = NULL; -static u_int32_t dyn_buckets = 256; /* must be power of 2 */ -static u_int32_t curr_dyn_buckets = 256; /* must be power of 2 */ +static u_int32_t dyn_buckets; +static u_int32_t curr_dyn_buckets; +#endif static struct mtx ipfw_dyn_mtx; /* mutex guarding dynamic rules */ #define IPFW_DYN_LOCK_INIT() \ @@ -254,12 +253,14 @@ /* * Timeouts for various events in handing dynamic rules. */ -static u_int32_t dyn_ack_lifetime = 300; -static u_int32_t dyn_syn_lifetime = 20; -static u_int32_t dyn_fin_lifetime = 1; -static u_int32_t dyn_rst_lifetime = 1; -static u_int32_t dyn_udp_lifetime = 10; -static u_int32_t dyn_short_lifetime = 5; +#ifndef VIMAGE +static u_int32_t dyn_ack_lifetime; +static u_int32_t dyn_syn_lifetime; +static u_int32_t dyn_fin_lifetime; +static u_int32_t dyn_rst_lifetime; +static u_int32_t dyn_udp_lifetime; +static u_int32_t dyn_short_lifetime; +#endif /* * Keepalives are sent if dyn_keepalive is set. They are sent every @@ -268,40 +269,42 @@ * dyn_rst_lifetime and dyn_fin_lifetime should be strictly lower * than dyn_keepalive_period. */ - -static u_int32_t dyn_keepalive_interval = 20; -static u_int32_t dyn_keepalive_period = 5; -static u_int32_t dyn_keepalive = 1; /* do send keepalives */ +#ifndef VIMAGE +static u_int32_t dyn_keepalive_interval; +static u_int32_t dyn_keepalive_period; +static u_int32_t dyn_keepalive; static u_int32_t static_count; /* # of static rules */ static u_int32_t static_len; /* size in bytes of static rules */ -static u_int32_t dyn_count; /* # of dynamic rules */ -static u_int32_t dyn_max = 4096; /* max # of dynamic rules */ +static u_int32_t dyn_count; /* # of dynamic rules */ +static u_int32_t dyn_max; /* max # of dynamic rules */ +#endif -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets, CTLFLAG_RW, - &dyn_buckets, 0, "Number of dyn. buckets"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets, CTLFLAG_RD, - &curr_dyn_buckets, 0, "Current Number of dyn. buckets"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_count, CTLFLAG_RD, - &dyn_count, 0, "Number of dyn. rules"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_max, CTLFLAG_RW, - &dyn_max, 0, "Max number of dyn. rules"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, static_count, CTLFLAG_RD, - &static_count, 0, "Number of static rules"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime, CTLFLAG_RW, - &dyn_ack_lifetime, 0, "Lifetime of dyn. rules for acks"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_syn_lifetime, CTLFLAG_RW, - &dyn_syn_lifetime, 0, "Lifetime of dyn. rules for syn"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_fin_lifetime, CTLFLAG_RW, - &dyn_fin_lifetime, 0, "Lifetime of dyn. rules for fin"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_rst_lifetime, CTLFLAG_RW, - &dyn_rst_lifetime, 0, "Lifetime of dyn. rules for rst"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_udp_lifetime, CTLFLAG_RW, - &dyn_udp_lifetime, 0, "Lifetime of dyn. rules for UDP"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, CTLFLAG_RW, - &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations"); -SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW, - &dyn_keepalive, 0, "Enable keepalives for dyn. rules"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_buckets, + CTLFLAG_RW, dyn_buckets, 0, "Number of dyn. buckets"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, curr_dyn_buckets, + CTLFLAG_RD, curr_dyn_buckets, 0, "Current Number of dyn. buckets"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_count, + CTLFLAG_RD, dyn_count, 0, "Number of dyn. rules"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_max, + CTLFLAG_RW, dyn_max, 0, "Max number of dyn. rules"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, static_count, + CTLFLAG_RD, static_count, 0, "Number of static rules"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime, + CTLFLAG_RW, dyn_ack_lifetime, 0, "Lifetime of dyn. rules for acks"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_syn_lifetime, + CTLFLAG_RW, dyn_syn_lifetime, 0, "Lifetime of dyn. rules for syn"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_fin_lifetime, + CTLFLAG_RW, dyn_fin_lifetime, 0, "Lifetime of dyn. rules for fin"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_rst_lifetime, + CTLFLAG_RW, dyn_rst_lifetime, 0, "Lifetime of dyn. rules for rst"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_udp_lifetime, + CTLFLAG_RW, dyn_udp_lifetime, 0, "Lifetime of dyn. rules for UDP"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, + CTLFLAG_RW, dyn_short_lifetime, 0, + "Lifetime of dyn. rules for other situations"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_keepalive, + CTLFLAG_RW, dyn_keepalive, 0, "Enable keepalives for dyn. rules"); #ifdef INET6 /* @@ -317,8 +320,9 @@ #ifdef IPFIREWALL_NAT MODULE_DEPEND(ipfw, libalias, 1, 1, 1); #endif -static int fw_deny_unknown_exthdrs = 1; - +#ifndef VIMAGE +static int fw_deny_unknown_exthdrs; +#endif /* * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T @@ -655,6 +659,7 @@ return 1; } + static __inline int hash_packet6(struct ipfw_flow_id *id) { @@ -765,7 +770,9 @@ #endif /* INET6 */ +#ifndef VIMAGE static u_int64_t norule_counter; /* counter for ipfw_log(NULL...) */ +#endif #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0 #define SNP(buf) buf, sizeof(buf) @@ -779,6 +786,7 @@ struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg, struct ip *ip) { + INIT_VNET_IPFW(curvnetb); struct ether_header *eh = args->eh; char *action; int limit_reached = 0; @@ -788,11 +796,11 @@ proto[0] = '\0'; if (f == NULL) { /* bogus pkt */ - if (verbose_limit != 0 && norule_counter >= verbose_limit) + if (V_verbose_limit != 0 && V_norule_counter >= V_verbose_limit) return; - norule_counter++; - if (norule_counter == verbose_limit) - limit_reached = verbose_limit; + V_norule_counter++; + if (V_norule_counter == V_verbose_limit) + limit_reached = V_verbose_limit; action = "Refuse"; } else { /* O_LOG is the first action, find the real one */ ipfw_insn *cmd = ACTION_PTR(f); @@ -1047,6 +1055,7 @@ static __inline int hash_packet(struct ipfw_flow_id *id) { + INIT_VNET_IPFW(curvnetb); u_int32_t i; #ifdef INET6 @@ -1055,7 +1064,7 @@ else #endif /* INET6 */ i = (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port); - i &= (curr_dyn_buckets - 1); + i &= (V_curr_dyn_buckets - 1); return i; } @@ -1073,12 +1082,12 @@ q->parent->count--; \ DEB(printf("ipfw: unlink entry 0x%08x %d -> 0x%08x %d, %d left\n",\ (q->id.src_ip), (q->id.src_port), \ - (q->id.dst_ip), (q->id.dst_port), dyn_count-1 ); ) \ + (q->id.dst_ip), (q->id.dst_port), V_dyn_count-1 ); ) \ if (prev != NULL) \ prev->next = q = q->next; \ else \ head = q = q->next; \ - dyn_count--; \ + V_dyn_count--; \ uma_zfree(ipfw_dyn_rule_zone, old_q); } #define TIME_LEQ(a,b) ((int)((a)-(b)) <= 0) @@ -1098,6 +1107,7 @@ static void remove_dyn_rule(struct ip_fw *rule, ipfw_dyn_rule *keep_me) { + INIT_VNET_IPFW(curvnetb); static u_int32_t last_remove = 0; #define FORCE (keep_me == NULL) @@ -1107,7 +1117,7 @@ IPFW_DYN_LOCK_ASSERT(); - if (ipfw_dyn_v == NULL || dyn_count == 0) + if (V_ipfw_dyn_v == NULL || V_dyn_count == 0) return; /* do not expire more than once per second, it is useless */ if (!FORCE && last_remove == time_uptime) @@ -1120,8 +1130,8 @@ * them in a second pass. */ next_pass: - for (i = 0 ; i < curr_dyn_buckets ; i++) { - for (prev=NULL, q = ipfw_dyn_v[i] ; q ; ) { + for (i = 0 ; i < V_curr_dyn_buckets ; i++) { + for (prev=NULL, q = V_ipfw_dyn_v[i] ; q ; ) { /* * Logic can become complex here, so we split tests. */ @@ -1148,7 +1158,7 @@ goto next; } if (q->dyn_type != O_LIMIT_PARENT || !q->count) { - UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q); + UNLINK_DYN_RULE(prev, V_ipfw_dyn_v[i], q); continue; } next: @@ -1168,6 +1178,7 @@ lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int *match_direction, struct tcphdr *tcp) { + INIT_VNET_IPFW(curvnetb); /* * stateful ipfw extensions. * Lookup into dynamic session queue @@ -1181,14 +1192,14 @@ IPFW_DYN_LOCK_ASSERT(); - if (ipfw_dyn_v == NULL) + if (V_ipfw_dyn_v == NULL) goto done; /* not found */ i = hash_packet( pkt ); - for (prev=NULL, q = ipfw_dyn_v[i] ; q != NULL ; ) { + for (prev=NULL, q = V_ipfw_dyn_v[i] ; q != NULL ; ) { if (q->dyn_type == O_LIMIT_PARENT && q->count) goto next; if (TIME_LEQ( q->expire, time_uptime)) { /* expire entry */ - UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q); + UNLINK_DYN_RULE(prev, V_ipfw_dyn_v[i], q); continue; } if (pkt->proto == q->id.proto && @@ -1238,8 +1249,8 @@ if ( prev != NULL) { /* found and not in front */ prev->next = q->next; - q->next = ipfw_dyn_v[i]; - ipfw_dyn_v[i] = q; + q->next = V_ipfw_dyn_v[i]; + V_ipfw_dyn_v[i] = q; } if (pkt->proto == IPPROTO_TCP) { /* update state according to flags */ u_char flags = pkt->flags & (TH_FIN|TH_SYN|TH_RST); @@ -1249,7 +1260,7 @@ q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8); switch (q->state) { case TH_SYN: /* opening */ - q->expire = time_uptime + dyn_syn_lifetime; + q->expire = time_uptime + V_dyn_syn_lifetime; break; case BOTH_SYN: /* move to established */ @@ -1272,13 +1283,13 @@ } } } - q->expire = time_uptime + dyn_ack_lifetime; + q->expire = time_uptime + V_dyn_ack_lifetime; break; case BOTH_SYN | BOTH_FIN: /* both sides closed */ - if (dyn_fin_lifetime >= dyn_keepalive_period) - dyn_fin_lifetime = dyn_keepalive_period - 1; - q->expire = time_uptime + dyn_fin_lifetime; + if (V_dyn_fin_lifetime >= V_dyn_keepalive_period) + V_dyn_fin_lifetime = V_dyn_keepalive_period - 1; + q->expire = time_uptime + V_dyn_fin_lifetime; break; default: @@ -1290,16 +1301,16 @@ if ( (q->state & ((TH_RST << 8)|TH_RST)) == 0) printf("invalid state: 0x%x\n", q->state); #endif - if (dyn_rst_lifetime >= dyn_keepalive_period) - dyn_rst_lifetime = dyn_keepalive_period - 1; - q->expire = time_uptime + dyn_rst_lifetime; + if (V_dyn_rst_lifetime >= V_dyn_keepalive_period) + V_dyn_rst_lifetime = V_dyn_keepalive_period - 1; + q->expire = time_uptime + V_dyn_rst_lifetime; break; } } else if (pkt->proto == IPPROTO_UDP) { - q->expire = time_uptime + dyn_udp_lifetime; + q->expire = time_uptime + V_dyn_udp_lifetime; } else { /* other protocols */ - q->expire = time_uptime + dyn_short_lifetime; + q->expire = time_uptime + V_dyn_short_lifetime; } done: if (match_direction) @@ -1324,6 +1335,7 @@ static void realloc_dynamic_table(void) { + INIT_VNET_IPFW(curvnetb); IPFW_DYN_LOCK_ASSERT(); /* @@ -1332,21 +1344,21 @@ * default to 1024. */ - if (dyn_buckets > 65536) - dyn_buckets = 1024; - if ((dyn_buckets & (dyn_buckets-1)) != 0) { /* not a power of 2 */ - dyn_buckets = curr_dyn_buckets; /* reset */ + if (V_dyn_buckets > 65536) + V_dyn_buckets = 1024; + if ((V_dyn_buckets & (V_dyn_buckets-1)) != 0) { /* not a power of 2 */ + V_dyn_buckets = V_curr_dyn_buckets; /* reset */ return; } - curr_dyn_buckets = dyn_buckets; - if (ipfw_dyn_v != NULL) - free(ipfw_dyn_v, M_IPFW); + V_curr_dyn_buckets = V_dyn_buckets; + if (V_ipfw_dyn_v != NULL) + free(V_ipfw_dyn_v, M_IPFW); for (;;) { - ipfw_dyn_v = malloc(curr_dyn_buckets * sizeof(ipfw_dyn_rule *), + V_ipfw_dyn_v = malloc(V_curr_dyn_buckets * sizeof(ipfw_dyn_rule *), M_IPFW, M_NOWAIT | M_ZERO); - if (ipfw_dyn_v != NULL || curr_dyn_buckets <= 2) + if (V_ipfw_dyn_v != NULL || V_curr_dyn_buckets <= 2) break; - curr_dyn_buckets /= 2; + V_curr_dyn_buckets /= 2; } } @@ -1363,15 +1375,16 @@ static ipfw_dyn_rule * add_dyn_rule(struct ipfw_flow_id *id, u_int8_t dyn_type, struct ip_fw *rule) { + INIT_VNET_IPFW(curvnetb); ipfw_dyn_rule *r; int i; IPFW_DYN_LOCK_ASSERT(); - if (ipfw_dyn_v == NULL || - (dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) { + if (V_ipfw_dyn_v == NULL || + (V_dyn_count == 0 && V_dyn_buckets != V_curr_dyn_buckets)) { realloc_dynamic_table(); - if (ipfw_dyn_v == NULL) + if (V_ipfw_dyn_v == NULL) return NULL; /* failed ! */ } i = hash_packet(id); @@ -1393,21 +1406,21 @@ } r->id = *id; - r->expire = time_uptime + dyn_syn_lifetime; + r->expire = time_uptime + V_dyn_syn_lifetime; r->rule = rule; r->dyn_type = dyn_type; r->pcnt = r->bcnt = 0; r->count = 0; r->bucket = i; - r->next = ipfw_dyn_v[i]; - ipfw_dyn_v[i] = r; - dyn_count++; + r->next = V_ipfw_dyn_v[i]; + V_ipfw_dyn_v[i] = r; + V_dyn_count++; DEB(printf("ipfw: add dyn entry ty %d 0x%08x %d -> 0x%08x %d, total %d\n", dyn_type, (r->id.src_ip), (r->id.src_port), (r->id.dst_ip), (r->id.dst_port), - dyn_count ); ) + V_dyn_count ); ) return r; } @@ -1418,15 +1431,16 @@ static ipfw_dyn_rule * lookup_dyn_parent(struct ipfw_flow_id *pkt, struct ip_fw *rule) { + INIT_VNET_IPFW(curvnetb); ipfw_dyn_rule *q; int i; IPFW_DYN_LOCK_ASSERT(); - if (ipfw_dyn_v) { + if (V_ipfw_dyn_v) { int is_v6 = IS_IP6_FLOW_ID(pkt); i = hash_packet( pkt ); - for (q = ipfw_dyn_v[i] ; q != NULL ; q=q->next) + for (q = V_ipfw_dyn_v[i] ; q != NULL ; q=q->next) if (q->dyn_type == O_LIMIT_PARENT && rule== q->rule && pkt->proto == q->id.proto && @@ -1443,7 +1457,7 @@ pkt->dst_ip == q->id.dst_ip) ) ) { - q->expire = time_uptime + dyn_short_lifetime; + q->expire = time_uptime + V_dyn_short_lifetime; DEB(printf("ipfw: lookup_dyn_parent found 0x%p\n",q);) return q; } @@ -1461,6 +1475,7 @@ install_state(struct ip_fw *rule, ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg) { + INIT_VNET_IPFW(curvnetb); static int last_log; ipfw_dyn_rule *q; struct in_addr da; @@ -1490,11 +1505,11 @@ return (0); } - if (dyn_count >= dyn_max) + if (V_dyn_count >= V_dyn_max) /* Run out of slots, try to remove any expired rule. */ remove_dyn_rule(NULL, (ipfw_dyn_rule *)1); - if (dyn_count >= dyn_max) { + if (V_dyn_count >= V_dyn_max) { if (last_log != time_uptime) { last_log = time_uptime; printf("ipfw: %s: Too many dynamic rules\n", __func__); @@ -1555,7 +1570,7 @@ /* See if we can remove some expired rule. */ remove_dyn_rule(rule, parent); if (parent->count >= conn_limit) { - if (fw_verbose && last_log != time_uptime) { + if (V_fw_verbose && last_log != time_uptime) { last_log = time_uptime; #ifdef INET6 /* @@ -1786,6 +1801,7 @@ add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, uint8_t mlen, uint32_t value) { + INIT_VNET_IPFW(curvnetb); struct radix_node_head *rnh; struct table_entry *ent; @@ -1799,14 +1815,14 @@ ent->addr.sin_len = ent->mask.sin_len = 8; ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0); ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr; - IPFW_WLOCK(&layer3_chain); + IPFW_WLOCK(&V_layer3_chain); if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) == NULL) { - IPFW_WUNLOCK(&layer3_chain); + IPFW_WUNLOCK(&V_layer3_chain); free(ent, M_IPFW_TBL); return (EEXIST); } - IPFW_WUNLOCK(&layer3_chain); + IPFW_WUNLOCK(&V_layer3_chain); return (0); } @@ -2079,9 +2095,9 @@ struct cfg_nat *ptr; struct ifaddr *ifa; - IPFW_WLOCK(&layer3_chain); + IPFW_WLOCK(&V_layer3_chain); /* Check every nat entry... */ - LIST_FOREACH(ptr, &layer3_chain.nat, _next) { + LIST_FOREACH(ptr, &V_layer3_chain.nat, _next) { /* ...using nic 'ifp->if_xname' as dynamic alias address. */ if (strncmp(ptr->if_name, ifp->if_xname, IF_NAMESIZE) == 0) { mtx_lock(&ifp->if_addr_mtx); @@ -2097,15 +2113,15 @@ mtx_unlock(&ifp->if_addr_mtx); } } - IPFW_WUNLOCK(&layer3_chain); + IPFW_WUNLOCK(&V_layer3_chain); } static void flush_nat_ptrs(const int i) { struct ip_fw *rule; - IPFW_WLOCK_ASSERT(&layer3_chain); - for (rule = layer3_chain.rules; rule; rule = rule->next) { + IPFW_WLOCK_ASSERT(&V_layer3_chain); + for (rule = V_layer3_chain.rules; rule; rule = rule->next) { ipfw_insn_nat *cmd = (ipfw_insn_nat *)ACTION_PTR(rule); if (cmd->o.opcode != O_NAT) continue; @@ -2118,19 +2134,19 @@ lookup_nat(const int i) { struct cfg_nat *ptr; - LIST_FOREACH(ptr, &layer3_chain.nat, _next) + LIST_FOREACH(ptr, &V_layer3_chain.nat, _next) if (ptr->id == i) return(ptr); return (NULL); } #define HOOK_NAT(b, p) do { \ - IPFW_WLOCK_ASSERT(&layer3_chain); \ + IPFW_WLOCK_ASSERT(&V_layer3_chain); \ LIST_INSERT_HEAD(b, p, _next); \ } while (0) #define UNHOOK_NAT(p) do { \ - IPFW_WLOCK_ASSERT(&layer3_chain); \ + IPFW_WLOCK_ASSERT(&V_layer3_chain); \ LIST_REMOVE(p, _next); \ } while (0) @@ -2283,6 +2299,7 @@ ipfw_chk(struct ip_fw_args *args) { INIT_VNET_INET(curvnetb); + INIT_VNET_IPFW(curvnetb); /* * Local variables holding state during the processing of a packet: @@ -2386,7 +2403,7 @@ */ int dyn_dir = MATCH_UNKNOWN; ipfw_dyn_rule *q = NULL; - struct ip_fw_chain *chain = &layer3_chain; + struct ip_fw_chain *chain = &V_layer3_chain; struct m_tag *mtag; /* @@ -2485,7 +2502,7 @@ printf("IPFW2: IPV6 - Unknown Routing " "Header type(%d)\n", ((struct ip6_rthdr *)ulp)->ip6r_type); - if (fw_deny_unknown_exthdrs) + if (V_fw_deny_unknown_exthdrs) return (IP_FW_DENY); break; } @@ -2509,7 +2526,7 @@ if (offset == 0) { printf("IPFW2: IPV6 - Invalid Fragment " "Header\n"); - if (fw_deny_unknown_exthdrs) + if (V_fw_deny_unknown_exthdrs) return (IP_FW_DENY); break; } @@ -2578,7 +2595,7 @@ default: printf("IPFW2: IPV6 - Unknown Extension " "Header(%d), ext_hd=%x\n", proto, ext_hd); - if (fw_deny_unknown_exthdrs) + if (V_fw_deny_unknown_exthdrs) return (IP_FW_DENY); PULLUP_TO(hlen, ulp, struct ip6_ext); break; @@ -2659,7 +2676,7 @@ * XXX should not happen here, but optimized out in * the caller. */ - if (fw_one_pass) { + if (V_fw_one_pass) { IPFW_RUNLOCK(chain); return (IP_FW_PASS); } @@ -2704,7 +2721,7 @@ int l, cmdlen, skip_or; /* skip rest of OR block */ again: - if (set_disable & (1 << f->set) ) + if (V_set_disable & (1 << f->set) ) continue; skip_or = 0; @@ -3094,7 +3111,7 @@ } case O_LOG: - if (fw_verbose) + if (V_fw_verbose) ipfw_log(f, hlen, args, m, oif, offset, tablearg, ip); match = 1; @@ -3695,7 +3712,7 @@ return (retval); pullup_failed: - if (fw_verbose) + if (V_fw_verbose) printf("ipfw: pullup failed\n"); return (IP_FW_DENY); } @@ -3723,6 +3740,7 @@ static int add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule) { + INIT_VNET_IPFW(curvnetb); struct ip_fw *rule, *f, *prev; int l = RULESIZE(input_rule); @@ -3753,10 +3771,10 @@ * If rulenum is 0, find highest numbered rule before the >>> TRUNCATED FOR MAIL (1000 lines) <<<