From owner-freebsd-current@FreeBSD.ORG Sat May 17 02:44:03 2008 Return-Path: Delivered-To: current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2F41F1065674 for ; Sat, 17 May 2008 02:44:03 +0000 (UTC) (envelope-from nork@ninth-nine.com) Received: from sakura.ninth-nine.com (unknown [IPv6:2001:2f0:104:80a0:230:48ff:fe41:2455]) by mx1.freebsd.org (Postfix) with ESMTP id B8AEF8FC13 for ; Sat, 17 May 2008 02:43:51 +0000 (UTC) (envelope-from nork@ninth-nine.com) Received: from nadesico.ninth-nine.com (nadesico.ninth-nine.com [219.127.74.122]) by sakura.ninth-nine.com (8.14.1/8.14.1/NinthNine) with ESMTP id m4H2hmQR054360; Sat, 17 May 2008 11:43:48 +0900 (JST) (envelope-from nork@ninth-nine.com) Date: Sat, 17 May 2008 11:43:48 +0900 From: Norikatsu Shigemura To: Julian Elischer Message-Id: <20080517114348.e69e3705.nork@ninth-nine.com> In-Reply-To: <20080517113201.7f7bc2d6.nork@FreeBSD.org> References: <482D7FE6.6020405@elischer.org> <20080517081548.ce75ffd7.nork@FreeBSD.org> <20080517083938.9fd7ae60.nork@FreeBSD.org> <20080517113201.7f7bc2d6.nork@FreeBSD.org> X-Mailer: Sylpheed 2.5.0beta3 (GTK+ 2.12.9; i386-portbld-freebsd8.0) Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Multipart=_Sat__17_May_2008_11_43_48_+0900_J3nATx4F2vmYvrlF" X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-2.0.2 (sakura.ninth-nine.com [219.127.74.121]); Sat, 17 May 2008 11:43:48 +0900 (JST) Cc: FreeBSD Current Subject: Re: vimage patches and example run. X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 May 2008 02:44:03 -0000 This is a multi-part message in MIME format. --Multipart=_Sat__17_May_2008_11_43_48_+0900_J3nATx4F2vmYvrlF Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Sat, 17 May 2008 11:32:01 +0900 Norikatsu Shigemura wrote: > Please replace my attached patches for your vimage.diff. Sorry. I forgot to attach patches. --Multipart=_Sat__17_May_2008_11_43_48_+0900_J3nATx4F2vmYvrlF Content-Type: text/plain; name="DIFF.sys-netinet-ip_fw.h" Content-Disposition: attachment; filename="DIFF.sys-netinet-ip_fw.h" Content-Transfer-Encoding: 7bit --- sys/netinet/ip_fw.h.orig 2008-05-10 16:10:53.000000000 +0900 +++ sys/netinet/ip_fw.h 2008-05-17 10:49:58.974783431 +0900 @@ -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 @@ -550,6 +553,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, @@ -619,11 +650,14 @@ 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); @@ -632,14 +666,6 @@ #ifdef IPFW_INTERNAL -#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) @@ -662,5 +688,89 @@ typedef int ipfw_nat_cfg_t(struct sockopt *); #endif +/* + * Stack virtualization support. + */ +#ifdef VIMAGE +struct vnet_ipfw { + int _fw_one_pass; + int _fw_enable; + int _fw6_enable; + + 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(vnet) \ + INIT_FROM_VNET(vnet, 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_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 */ --Multipart=_Sat__17_May_2008_11_43_48_+0900_J3nATx4F2vmYvrlF Content-Type: text/plain; name="DIFF.sys-netinet-ip_fw2.c" Content-Disposition: attachment; filename="DIFF.sys-netinet-ip_fw2.c" Content-Transfer-Encoding: 7bit --- sys/netinet/ip_fw2.c.orig 2008-05-10 16:10:53.000000000 +0900 +++ sys/netinet/ip_fw2.c 2008-05-17 11:13:34.347364537 +0900 @@ -45,6 +45,7 @@ #include "opt_inet6.h" #include "opt_ipsec.h" #include "opt_mac.h" +#include "opt_vimage.h" #include #include @@ -64,6 +65,9 @@ #include #include #include +#include + +#include #include #include #include @@ -71,6 +75,7 @@ #define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */ +#include #include #include #include @@ -106,6 +111,11 @@ #include +static int vnet_ipfw_iattach(const void *); +static int vnet_ipfw_idetach(const void *); + +VNET_MOD_DECLARE(IPFW, ipfw, vnet_ipfw_iattach, vnet_ipfw_idetach, INET, NULL) + /* * set_disable contains one bit per set value (0..31). * If the bit is set, all rules with the corresponding set @@ -114,32 +124,24 @@ * 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; -}; - -/* * list of rules for layer 3 */ +#ifndef VIMAGE 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"); @@ -150,35 +152,35 @@ ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr; ipfw_nat_cfg_t *ipfw_nat_get_log_ptr; -struct table_entry { - struct radix_node rn[2]; - struct sockaddr_in addr, mask; - u_int32_t value; -}; - -static int fw_debug = 1; -static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */ +#ifndef VIMAGE +static int fw_debug; +static int autoinc_step; +#endif +#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. @@ -216,9 +218,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() \ @@ -231,12 +235,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 @@ -245,54 +251,65 @@ * 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"); + +#ifndef VIMAGE +static int fw_deny_unknown_exthdrs; +#endif #ifdef INET6 /* * IPv6 specific variables */ -SYSCTL_DECL(_net_inet6_ip6); -static struct sysctl_ctx_list ip6_fw_sysctl_ctx; -static struct sysctl_oid *ip6_fw_sysctl_tree; +SYSCTL_DECL(_net_inet6_ip6); +SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW | CTLFLAG_SECURE, + 0, "Firewall"); +SYSCTL_V_PROC(V_NET, vnet_ipfw, _net_inet6_ip6_fw, OID_AUTO, enable, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, fw6_enable, 0, + ipfw_chg_hook, "I", "Enable ipfw+6"); +SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet6_ip6_fw, OID_AUTO, + deny_unknown_exthdrs, CTLFLAG_RW | CTLFLAG_SECURE, + fw_deny_unknown_exthdrs, 0, + "Deny packets with unknown IPv6 Extension Headers"); #endif /* INET6 */ #endif /* SYSCTL_NODE */ -static int fw_deny_unknown_exthdrs = 1; - /* * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T @@ -562,12 +579,13 @@ static int search_ip6_addr_net (struct in6_addr * ip6_addr) { + INIT_VNET_NET(curvnet); struct ifnet *mdc; struct ifaddr *mdc2; struct in6_ifaddr *fdm; struct in6_addr copia; - TAILQ_FOREACH(mdc, &ifnet, if_link) + TAILQ_FOREACH(mdc, &V_ifnet, if_link) TAILQ_FOREACH(mdc2, &mdc->if_addrlist, ifa_list) { if (mdc2->ifa_addr->sa_family == AF_INET6) { fdm = (struct in6_ifaddr *)mdc2; @@ -629,6 +647,7 @@ return 1; } + static __inline int hash_packet6(struct ipfw_flow_id *id) { @@ -739,7 +758,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) @@ -753,6 +774,7 @@ struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg, struct ip *ip) { + INIT_VNET_IPFW(curvnet); struct ether_header *eh = args->eh; char *action; int limit_reached = 0; @@ -762,11 +784,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); @@ -1023,6 +1045,7 @@ static __inline int hash_packet(struct ipfw_flow_id *id) { + INIT_VNET_IPFW(curvnet); u_int32_t i; #ifdef INET6 @@ -1031,7 +1054,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; } @@ -1049,12 +1072,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) @@ -1074,6 +1097,7 @@ static void remove_dyn_rule(struct ip_fw *rule, ipfw_dyn_rule *keep_me) { + INIT_VNET_IPFW(curvnet); static u_int32_t last_remove = 0; #define FORCE (keep_me == NULL) @@ -1083,7 +1107,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) @@ -1096,8 +1120,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. */ @@ -1124,7 +1148,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: @@ -1144,6 +1168,7 @@ lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int *match_direction, struct tcphdr *tcp) { + INIT_VNET_IPFW(curvnet); /* * stateful ipfw extensions. * Lookup into dynamic session queue @@ -1157,14 +1182,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 && @@ -1214,8 +1239,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); @@ -1225,7 +1250,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 */ @@ -1248,13 +1273,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: @@ -1266,16 +1291,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) @@ -1300,6 +1325,7 @@ static void realloc_dynamic_table(void) { + INIT_VNET_IPFW(curvnet); IPFW_DYN_LOCK_ASSERT(); /* @@ -1308,21 +1334,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; } } @@ -1339,15 +1365,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(curvnet); 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); @@ -1369,21 +1396,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; } @@ -1394,15 +1421,16 @@ static ipfw_dyn_rule * lookup_dyn_parent(struct ipfw_flow_id *pkt, struct ip_fw *rule) { + INIT_VNET_IPFW(curvnet); 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 && @@ -1419,7 +1447,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; } @@ -1437,6 +1465,7 @@ install_state(struct ip_fw *rule, ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg) { + INIT_VNET_IPFW(curvnet); static int last_log; ipfw_dyn_rule *q; struct in_addr da; @@ -1466,11 +1495,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__); @@ -1532,7 +1561,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 /* @@ -1598,6 +1627,7 @@ send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq, u_int32_t ack, int flags) { + INIT_VNET_INET(curvnet); struct mbuf *m; struct ip *ip; struct tcphdr *tcp; @@ -1675,7 +1705,7 @@ /* * now fill fields left out earlier */ - ip->ip_ttl = ip_defttl; + ip->ip_ttl = V_ip_defttl; ip->ip_len = m->m_pkthdr.len; m->m_flags |= M_SKIP_FIREWALL; return (m); @@ -1765,6 +1795,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(curvnet); struct radix_node_head *rnh; struct table_entry *ent; @@ -1778,14 +1809,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); } @@ -1969,6 +2000,7 @@ u_int16_t src_port, struct ip_fw_ugid *ugp, int *lookup, struct inpcb *inp) { + INIT_VNET_INET(curvnet); struct inpcbinfo *pi; int wildcard; struct inpcb *pcb; @@ -1996,10 +2028,10 @@ return (0); if (proto == IPPROTO_TCP) { wildcard = 0; - pi = &tcbinfo; + pi = &V_tcbinfo; } else if (proto == IPPROTO_UDP) { wildcard = INPLOOKUP_WILDCARD; - pi = &udbinfo; + pi = &V_udbinfo; } else return 0; match = 0; @@ -2085,6 +2117,9 @@ int ipfw_chk(struct ip_fw_args *args) { + INIT_VNET_INET(curvnet); + INIT_VNET_IPFW(curvnet); + /* * Local variables holding state during the processing of a packet: * @@ -2187,7 +2222,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; /* @@ -2291,7 +2326,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; } @@ -2315,7 +2350,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; } @@ -2387,7 +2422,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; @@ -2468,7 +2503,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); } @@ -2513,7 +2548,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; @@ -2899,7 +2934,7 @@ } case O_LOG: - if (fw_verbose) + if (V_fw_verbose) ipfw_log(f, hlen, args, m, oif, offset, tablearg, ip); match = 1; @@ -3315,7 +3350,7 @@ if (t == NULL) { nat_id = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; - LOOKUP_NAT(layer3_chain, nat_id, t); + LOOKUP_NAT(V_layer3_chain, nat_id, t); if (t == NULL) { retval = IP_FW_DENY; goto done; @@ -3362,7 +3397,7 @@ return (retval); pullup_failed: - if (fw_verbose) + if (V_fw_verbose) printf("ipfw: pullup failed\n"); return (IP_FW_DENY); } @@ -3390,6 +3425,7 @@ static int add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule) { + INIT_VNET_IPFW(curvnet); struct ip_fw *rule, *f, *prev; int l = RULESIZE(input_rule); @@ -3420,10 +3456,10 @@ * If rulenum is 0, find highest numbered rule before the * default rule, and add autoinc_step */ - if (autoinc_step < 1) - autoinc_step = 1; - else if (autoinc_step > 1000) - autoinc_step = 1000; + if (V_autoinc_step < 1) + V_autoinc_step = 1; + else if (V_autoinc_step > 1000) + V_autoinc_step = 1000; if (rule->rulenum == 0) { /* * locate the highest numbered rule before default @@ -3433,8 +3469,8 @@ break; rule->rulenum = f->rulenum; } - if (rule->rulenum < IPFW_DEFAULT_RULE - autoinc_step) - rule->rulenum += autoinc_step; + if (rule->rulenum < IPFW_DEFAULT_RULE - V_autoinc_step) + rule->rulenum += V_autoinc_step; input_rule->rulenum = rule->rulenum; } @@ -3455,11 +3491,11 @@ } flush_rule_ptrs(chain); done: - static_count++; - static_len += l; + V_static_count++; + V_static_len += l; IPFW_WUNLOCK(chain); DEB(printf("ipfw: installed rule %d, static count now %d\n", - rule->rulenum, static_count);) + rule->rulenum, V_static_count);) return (0); } @@ -3475,6 +3511,7 @@ remove_rule(struct ip_fw_chain *chain, struct ip_fw *rule, struct ip_fw *prev) { + INIT_VNET_IPFW(curvnet); struct ip_fw *n; int l = RULESIZE(rule); @@ -3488,8 +3525,8 @@ chain->rules = n; else prev->next = n; - static_count--; - static_len -= l; + V_static_count--; + V_static_len -= l; rule->next = chain->reap; chain->reap = rule; @@ -3689,6 +3726,7 @@ static int zero_entry(struct ip_fw_chain *chain, u_int32_t arg, int log_only) { + INIT_VNET_IPFW(curvnet); struct ip_fw *rule; char *msg; @@ -3703,7 +3741,7 @@ IPFW_WLOCK(chain); if (rulenum == 0) { - norule_counter = 0; + V_norule_counter = 0; for (rule = chain->rules; rule; rule = rule->next) { /* Skip rules from another set. */ if (cmd == 1 && rule->set != set) @@ -3737,7 +3775,7 @@ } IPFW_WUNLOCK(chain); - if (fw_verbose) + if (V_fw_verbose) log(LOG_SECURITY | LOG_NOTICE, msg, rulenum); return (0); } @@ -4056,6 +4094,7 @@ static size_t ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space) { + INIT_VNET_IPFW(curvnet); char *bp = buf; char *ep = bp + space; struct ip_fw *rule; @@ -4080,20 +4119,21 @@ * in a wild attempt to keep the ABI the same. * Why do we do this on EVERY rule? */ - bcopy(&set_disable, &(((struct ip_fw *)bp)->next_rule), - sizeof(set_disable)); + bcopy(&V_set_disable, + &(((struct ip_fw *)bp)->next_rule), + sizeof(V_set_disable)); if (((struct ip_fw *)bp)->timestamp) ((struct ip_fw *)bp)->timestamp += boot_seconds; bp += i; } } IPFW_RUNLOCK(chain); - if (ipfw_dyn_v) { + if (V_ipfw_dyn_v) { ipfw_dyn_rule *p, *last = NULL; IPFW_DYN_LOCK(); - for (i = 0 ; i < curr_dyn_buckets; i++) - for (p = ipfw_dyn_v[i] ; p != NULL; p = p->next) { + for (i = 0 ; i < V_curr_dyn_buckets; i++) + for (p = V_ipfw_dyn_v[i] ; p != NULL; p = p->next) { if (bp + sizeof *p <= ep) { ipfw_dyn_rule *dst = (ipfw_dyn_rule *)bp; @@ -4136,6 +4176,7 @@ static int ipfw_ctl(struct sockopt *sopt) { + INIT_VNET_IPFW(curvnet); #define RULE_MAXSIZE (256*sizeof(u_int32_t)) int error; size_t size; @@ -4172,9 +4213,9 @@ * change between calculating the size and returning the * data in which case we'll just return what fits. */ - size = static_len; /* size of static rules */ - if (ipfw_dyn_v) /* add size of dyn.rules */ - size += (dyn_count * sizeof(ipfw_dyn_rule)); + size = V_static_len; /* size of static rules */ + if (V_ipfw_dyn_v) /* add size of dyn.rules */ + size += (V_dyn_count * sizeof(ipfw_dyn_rule)); /* * XXX todo: if the user passes a short length just to know @@ -4183,7 +4224,7 @@ */ buf = malloc(size, M_TEMP, M_WAITOK); error = sooptcopyout(sopt, buf, - ipfw_getrules(&layer3_chain, buf, size)); + ipfw_getrules(&V_layer3_chain, buf, size)); free(buf, M_TEMP); break; @@ -4201,12 +4242,12 @@ * the old list without the need for a lock. */ - IPFW_WLOCK(&layer3_chain); - layer3_chain.reap = NULL; - free_chain(&layer3_chain, 0 /* keep default rule */); - rule = layer3_chain.reap; - layer3_chain.reap = NULL; - IPFW_WUNLOCK(&layer3_chain); + IPFW_WLOCK(&V_layer3_chain); + V_layer3_chain.reap = NULL; + free_chain(&V_layer3_chain, 0 /* keep default rule */); + rule = V_layer3_chain.reap; + V_layer3_chain.reap = NULL; + IPFW_WUNLOCK(&V_layer3_chain); if (rule != NULL) reap_rules(rule); break; @@ -4218,7 +4259,7 @@ if (error == 0) error = check_ipfw_struct(rule, sopt->sopt_valsize); if (error == 0) { - error = add_rule(&layer3_chain, rule); + error = add_rule(&V_layer3_chain, rule); size = RULESIZE(rule); if (!error && sopt->sopt_dir == SOPT_GET) error = sooptcopyout(sopt, rule, size); @@ -4245,10 +4286,10 @@ break; size = sopt->sopt_valsize; if (size == sizeof(u_int32_t)) /* delete or reassign */ - error = del_entry(&layer3_chain, rulenum[0]); + error = del_entry(&V_layer3_chain, rulenum[0]); else if (size == 2*sizeof(u_int32_t)) /* set enable/disable */ - set_disable = - (set_disable | rulenum[0]) & ~rulenum[1] & + V_set_disable = + (V_set_disable | rulenum[0]) & ~rulenum[1] & ~(1<sopt_name == IP_FW_RESETLOG); break; @@ -4275,7 +4316,7 @@ sizeof(ent), sizeof(ent)); if (error) break; - error = add_table_entry(&layer3_chain, ent.tbl, + error = add_table_entry(&V_layer3_chain, ent.tbl, ent.addr, ent.masklen, ent.value); } break; @@ -4288,7 +4329,7 @@ sizeof(ent), sizeof(ent)); if (error) break; - error = del_table_entry(&layer3_chain, ent.tbl, + error = del_table_entry(&V_layer3_chain, ent.tbl, ent.addr, ent.masklen); } break; @@ -4301,9 +4342,9 @@ sizeof(tbl), sizeof(tbl)); if (error) break; - IPFW_WLOCK(&layer3_chain); - error = flush_table(&layer3_chain, tbl); - IPFW_WUNLOCK(&layer3_chain); + IPFW_WLOCK(&V_layer3_chain); + error = flush_table(&V_layer3_chain, tbl); + IPFW_WUNLOCK(&V_layer3_chain); } break; @@ -4314,9 +4355,9 @@ if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl), sizeof(tbl)))) break; - IPFW_RLOCK(&layer3_chain); - error = count_table(&layer3_chain, tbl, &cnt); - IPFW_RUNLOCK(&layer3_chain); + IPFW_RLOCK(&V_layer3_chain); + error = count_table(&V_layer3_chain, tbl, &cnt); + IPFW_RUNLOCK(&V_layer3_chain); if (error) break; error = sooptcopyout(sopt, &cnt, sizeof(cnt)); @@ -4340,9 +4381,9 @@ } tbl->size = (size - sizeof(*tbl)) / sizeof(ipfw_table_entry); - IPFW_RLOCK(&layer3_chain); - error = dump_table(&layer3_chain, tbl); - IPFW_RUNLOCK(&layer3_chain); + IPFW_RLOCK(&V_layer3_chain); + error = dump_table(&V_layer3_chain, tbl); + IPFW_RUNLOCK(&V_layer3_chain); if (error) { free(tbl, M_TEMP); break; @@ -4420,13 +4461,16 @@ * every dyn_keepalive_period */ static void -ipfw_tick(void * __unused unused) +ipfw_tick(void *arg) { +#ifdef VIMAGE + struct vnet_ipfw *vnet_ipfw = arg; +#endif struct mbuf *m0, *m, *mnext, **mtailp; int i; ipfw_dyn_rule *q; - if (dyn_keepalive == 0 || ipfw_dyn_v == NULL || dyn_count == 0) + if (V_dyn_keepalive == 0 || V_ipfw_dyn_v == NULL || V_dyn_count == 0) goto done; /* @@ -4438,15 +4482,15 @@ m0 = NULL; mtailp = &m0; IPFW_DYN_LOCK(); - for (i = 0 ; i < curr_dyn_buckets ; i++) { - for (q = ipfw_dyn_v[i] ; q ; q = q->next ) { + for (i = 0 ; i < V_curr_dyn_buckets ; i++) { + for (q = V_ipfw_dyn_v[i] ; q ; q = q->next ) { if (q->dyn_type == O_LIMIT_PARENT) continue; if (q->id.proto != IPPROTO_TCP) continue; if ( (q->state & BOTH_SYN) != BOTH_SYN) continue; - if (TIME_LEQ( time_uptime+dyn_keepalive_interval, + if (TIME_LEQ( time_uptime + V_dyn_keepalive_interval, q->expire)) continue; /* too early */ if (TIME_LEQ(q->expire, time_uptime)) @@ -4469,37 +4513,40 @@ ip_output(m, NULL, NULL, 0, NULL, NULL); } done: - callout_reset(&ipfw_timeout, dyn_keepalive_period*hz, ipfw_tick, NULL); + callout_reset(&V_ipfw_timeout, V_dyn_keepalive_period * hz, + ipfw_tick, arg); } -int -ipfw_init(void) +static int vnet_ipfw_iattach(const void *unused) { + INIT_VNET_IPFW(curvnet); struct ip_fw default_rule; int error; -#ifdef INET6 - /* Setup IPv6 fw sysctl tree. */ - sysctl_ctx_init(&ip6_fw_sysctl_ctx); - ip6_fw_sysctl_tree = SYSCTL_ADD_NODE(&ip6_fw_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_net_inet6_ip6), OID_AUTO, "fw", - CTLFLAG_RW | CTLFLAG_SECURE, 0, "Firewall"); - SYSCTL_ADD_PROC(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree), - OID_AUTO, "enable", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, - &fw6_enable, 0, ipfw_chg_hook, "I", "Enable ipfw+6"); - SYSCTL_ADD_INT(&ip6_fw_sysctl_ctx, SYSCTL_CHILDREN(ip6_fw_sysctl_tree), - OID_AUTO, "deny_unknown_exthdrs", CTLFLAG_RW | CTLFLAG_SECURE, - &fw_deny_unknown_exthdrs, 0, - "Deny packets with unknown IPv6 Extension Headers"); -#endif - - layer3_chain.rules = NULL; - IPFW_LOCK_INIT(&layer3_chain); + V_fw_debug = 1; + V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */ + V_dyn_buckets = 256; /* must be power of 2 */ + V_curr_dyn_buckets = 256; /* must be power of 2 */ + V_dyn_ack_lifetime = 300; + V_dyn_syn_lifetime = 20; + V_dyn_fin_lifetime = 1; + V_dyn_rst_lifetime = 1; + V_dyn_udp_lifetime = 10; + V_dyn_short_lifetime = 5; + V_dyn_keepalive_interval = 20; + V_dyn_keepalive_period = 5; + V_dyn_keepalive = 1; /* do send keepalives */ + V_dyn_max = 4096; /* max # of dynamic rules */ + V_fw_deny_unknown_exthdrs = 1; + + V_layer3_chain.rules = NULL; + IPFW_LOCK_INIT(&V_layer3_chain); +#if 0 /* XXX Marko fix this! */ ipfw_dyn_rule_zone = uma_zcreate("IPFW dynamic rule", sizeof(ipfw_dyn_rule), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - IPFW_DYN_LOCK_INIT(); - callout_init(&ipfw_timeout, CALLOUT_MPSAFE); +#endif + callout_init(&V_ipfw_timeout, CALLOUT_MPSAFE); bzero(&default_rule, sizeof default_rule); @@ -4515,17 +4562,66 @@ #endif O_DENY; - error = add_rule(&layer3_chain, &default_rule); + error = add_rule(&V_layer3_chain, &default_rule); if (error != 0) { printf("ipfw2: error %u initializing default rule " "(support disabled)\n", error); IPFW_DYN_LOCK_DESTROY(); - IPFW_LOCK_DESTROY(&layer3_chain); + IPFW_LOCK_DESTROY(&V_layer3_chain); uma_zdestroy(ipfw_dyn_rule_zone); return (error); } - ip_fw_default_rule = layer3_chain.rules; + ip_fw_default_rule = V_layer3_chain.rules; + +#ifdef IPFIREWALL_VERBOSE + V_fw_verbose = 1; +#endif +#ifdef IPFIREWALL_VERBOSE_LIMIT + V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT; +#endif + + error = init_tables(&V_layer3_chain); + if (error) { + panic("init_tables"); /* XXX Marko fix this ! */ + } +#ifdef VIMAGE + callout_reset(&V_ipfw_timeout, hz, ipfw_tick, (void *) vnet_ipfw); +#else + callout_reset(&V_ipfw_timeout, hz, ipfw_tick, NULL); +#endif + +#ifdef IPFIREWALL_NAT + LIST_INIT(&V_layer3_chain.nat); +#endif + + return 0; +} + +int +ipfw_init(void) +{ + ipfw_dyn_rule_zone = uma_zcreate("IPFW dynamic rule", + sizeof(ipfw_dyn_rule), NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); + IPFW_DYN_LOCK_INIT(); + +#if 0 /* MARKO XXX */ + /* error = init_tables(&V_layer3_chain); moved to _iattach() */ + if (error) { + IPFW_DYN_LOCK_DESTROY(); + IPFW_LOCK_DESTROY(&V_layer3_chain); + uma_zdestroy(ipfw_dyn_rule_zone); + return (error); + } +#endif + +#ifdef VIMAGE + vnet_mod_register(&vnet_ipfw_modinfo); +#else + vnet_ipfw_iattach(NULL); +#endif + printf("ipfw2 " #ifdef INET6 "(+ipv6) " @@ -4543,68 +4639,74 @@ #else "loadable", #endif + #ifdef IPFIREWALL_NAT "enabled", #else - "loadable", + "disabled, ", #endif - default_rule.cmd[0].opcode == O_ACCEPT ? "accept" : "deny"); +#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT + "accept" +#else + "deny" +#endif + ); #ifdef IPFIREWALL_VERBOSE - fw_verbose = 1; -#endif -#ifdef IPFIREWALL_VERBOSE_LIMIT - verbose_limit = IPFIREWALL_VERBOSE_LIMIT; -#endif - if (fw_verbose == 0) printf("disabled\n"); - else if (verbose_limit == 0) +#else +# ifndef IPFIREWALL_VERBOSE_LIMIT printf("unlimited\n"); - else +# else printf("limited to %d packets/entry by default\n", - verbose_limit); + IPFIREWALL_VERBOSE_LIMIT); +# endif +#endif - error = init_tables(&layer3_chain); - if (error) { - IPFW_DYN_LOCK_DESTROY(); - IPFW_LOCK_DESTROY(&layer3_chain); - uma_zdestroy(ipfw_dyn_rule_zone); - return (error); - } ip_fw_ctl_ptr = ipfw_ctl; ip_fw_chk_ptr = ipfw_chk; - callout_reset(&ipfw_timeout, hz, ipfw_tick, NULL); - LIST_INIT(&layer3_chain.nat); return (0); } -void -ipfw_destroy(void) +static int vnet_ipfw_idetach(const void *unused) { + INIT_VNET_IPFW(curvnet); struct ip_fw *reap; - ip_fw_chk_ptr = NULL; - ip_fw_ctl_ptr = NULL; - callout_drain(&ipfw_timeout); - IPFW_WLOCK(&layer3_chain); - flush_tables(&layer3_chain); - layer3_chain.reap = NULL; - free_chain(&layer3_chain, 1 /* kill default rule */); - reap = layer3_chain.reap, layer3_chain.reap = NULL; - IPFW_WUNLOCK(&layer3_chain); + callout_drain(&V_ipfw_timeout); + IPFW_WLOCK(&V_layer3_chain); + flush_tables(&V_layer3_chain); + V_layer3_chain.reap = NULL; + free_chain(&V_layer3_chain, 1 /* kill default rule */); + reap = V_layer3_chain.reap, V_layer3_chain.reap = NULL; + IPFW_WUNLOCK(&V_layer3_chain); if (reap != NULL) reap_rules(reap); - IPFW_DYN_LOCK_DESTROY(); - uma_zdestroy(ipfw_dyn_rule_zone); - if (ipfw_dyn_v != NULL) - free(ipfw_dyn_v, M_IPFW); - IPFW_LOCK_DESTROY(&layer3_chain); + IPFW_LOCK_DESTROY(&V_layer3_chain); + if (V_ipfw_dyn_v != NULL) + free(V_ipfw_dyn_v, M_IPFW); -#ifdef INET6 - /* Free IPv6 fw sysctl tree. */ - sysctl_ctx_free(&ip6_fw_sysctl_ctx); + return 0; +} + +void +ipfw_destroy(void) +{ + ip_fw_chk_ptr = NULL; + ip_fw_ctl_ptr = NULL; + +#ifdef VIMAGE + vnet_mod_deregister(&vnet_ipfw_modinfo); +#else + vnet_ipfw_idetach(NULL); +#endif + +#ifdef IPFIREWALL_NAT + EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_event_tag); #endif + IPFW_DYN_LOCK_DESTROY(); + uma_zdestroy(ipfw_dyn_rule_zone); printf("IP firewall unloaded\n"); } --Multipart=_Sat__17_May_2008_11_43_48_+0900_J3nATx4F2vmYvrlF--