diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index f97e433ecda7..779d8457ea4d 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -62,6 +62,9 @@ static const char rcsid[] = "@(#)$Id$"; #else #define CURVNET_SET(arg) #define CURVNET_RESTORE() +#define VNET_DEFINE(_t, _v) _t _v +#define VNET_DECLARE(_t, _v) extern _t _v +#define VNET(arg) arg #endif #if defined(__osf__) # include @@ -102,22 +105,40 @@ MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures") static int ipf_send_ip __P((fr_info_t *, mb_t *)); static void ipf_timer_func __P((void *arg)); -ipf_main_softc_t ipfmain; +VNET_DEFINE(ipf_main_softc_t, ipfmain) = { + .ipf_running = -2, +}; +#define V_ipfmain VNET(ipfmain) # include # if defined(NETBSD_PF) # include # endif /* NETBSD_PF */ +static eventhandler_tag ipf_arrivetag, ipf_departtag; +#if 0 +/* + * Disable the "cloner" event handler; we are getting interface + * events before the firewall is fully initiallized and also no vnet + * information thus leading to uninitialised memory accesses. + * In addition it is unclear why we need it in first place. + * If it turns out to be needed, well need a dedicated event handler + * for it to deal with the ifc and the correct vnet. + */ +static eventhandler_tag ipf_clonetag; +#endif -static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag; +static void ipf_ifevent(void *arg, struct ifnet *ifp); -static void ipf_ifevent(void *arg); - -static void ipf_ifevent(arg) +static void ipf_ifevent(arg, ifp) void *arg; + struct ifnet *ifp; { - ipf_sync(arg, NULL); + + CURVNET_SET(ifp->if_vnet); + if (V_ipfmain.ipf_running > 0) + ipf_sync(&V_ipfmain, NULL); + CURVNET_RESTORE(); } @@ -135,8 +156,10 @@ ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); #endif - rv = ipf_check(&ipfmain, ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), + CURVNET_SET(ifp->if_vnet); + rv = ipf_check(&V_ipfmain, ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp); + CURVNET_RESTORE(); #if (__FreeBSD_version < 1000019) if ((rv == 0) && (*mp != NULL)) { ip = mtod(*mp, struct ip *); @@ -153,8 +176,13 @@ ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) static int ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) { - return (ipf_check(&ipfmain, mtod(*mp, struct ip *), - sizeof(struct ip6_hdr), ifp, (dir == PFIL_OUT), mp)); + int error; + + CURVNET_SET(ifp->if_vnet); + error = ipf_check(&V_ipfmain, mtod(*mp, struct ip *), + sizeof(struct ip6_hdr), ifp, (dir == PFIL_OUT), mp); + CURVNET_RESTORE(); + return (error); } # endif #if defined(IPFILTER_LKM) @@ -215,7 +243,7 @@ ipfattach(softc) } - bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait)); + bzero((char *)V_ipfmain.ipf_selwait, sizeof(V_ipfmain.ipf_selwait)); softc->ipf_running = 1; if (softc->ipf_control_forwarding & 1) @@ -284,38 +312,42 @@ ipfioctl(dev, cmd, data, mode int error = 0, unit = 0; SPL_INT(s); + CURVNET_SET(TD_TO_VNET(p)); #if (BSD >= 199306) if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) { - ipfmain.ipf_interror = 130001; + V_ipfmain.ipf_interror = 130001; + CURVNET_RESTORE(); return EPERM; } #endif unit = GET_MINOR(dev); if ((IPL_LOGMAX < unit) || (unit < 0)) { - ipfmain.ipf_interror = 130002; + V_ipfmain.ipf_interror = 130002; + CURVNET_RESTORE(); return ENXIO; } - if (ipfmain.ipf_running <= 0) { + if (V_ipfmain.ipf_running <= 0) { if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { - ipfmain.ipf_interror = 130003; + V_ipfmain.ipf_interror = 130003; + CURVNET_RESTORE(); return EIO; } if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && cmd != SIOCIPFSET && cmd != SIOCFRENB && cmd != SIOCGETFS && cmd != SIOCGETFF && cmd != SIOCIPFINTERROR) { - ipfmain.ipf_interror = 130004; + V_ipfmain.ipf_interror = 130004; + CURVNET_RESTORE(); return EIO; } } SPL_NET(s); - CURVNET_SET(TD_TO_VNET(p)); - error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, p->p_uid, p); + error = ipf_ioctlswitch(&V_ipfmain, unit, data, cmd, mode, p->p_uid, p); CURVNET_RESTORE(); if (error != -1) { SPL_X(s); @@ -563,7 +595,7 @@ ipf_send_icmp_err(type, fin, dst) } if (dst == 0) { - if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + if (ipf_ifpaddr(&V_ipfmain, 4, FRI_NORMAL, ifp, &dst6, NULL) == -1) { FREE_MB_T(m); return -1; @@ -600,7 +632,7 @@ ipf_send_icmp_err(type, fin, dst) xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); xtra = MIN(xtra, IPV6_MMTU - iclen); if (dst == 0) { - if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, + if (ipf_ifpaddr(&V_ipfmain, 6, FRI_NORMAL, ifp, &dst6, NULL) == -1) { FREE_MB_T(m); return -1; @@ -924,9 +956,9 @@ sendorfree: } done: if (!error) - ipfmain.ipf_frouteok[0]++; + V_ipfmain.ipf_frouteok[0]++; else - ipfmain.ipf_frouteok[1]++; + V_ipfmain.ipf_frouteok[1]++; if (has_nhop) fib4_free_nh_ext(fibnum, &nh4); @@ -1388,13 +1420,15 @@ void ipf_event_reg(void) { ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ - ipf_ifevent, &ipfmain, \ + ipf_ifevent, NULL, \ EVENTHANDLER_PRI_ANY); ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ - ipf_ifevent, &ipfmain, \ + ipf_ifevent, NULL, \ EVENTHANDLER_PRI_ANY); +#if 0 ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ - &ipfmain, EVENTHANDLER_PRI_ANY); + NULL, EVENTHANDLER_PRI_ANY); +#endif } void @@ -1406,9 +1440,11 @@ ipf_event_dereg(void) if (ipf_departtag != NULL) { EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag); } +#if 0 if (ipf_clonetag != NULL) { EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); } +#endif } diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index 39addb0f6b28..359c29bdfd3e 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -64,6 +64,15 @@ struct file; # include #endif #include +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000) && defined(_KERNEL) +#include +#else +#define CURVNET_SET(arg) +#define CURVNET_RESTORE() +#define VNET_DEFINE(_t, _v) _t _v +#define VNET_DECLARE(_t, _v) extern _t _v +#define VNET(arg) arg +#endif #ifdef sun # include #endif diff --git a/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c b/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c index 9493d2bfae38..e155771478a3 100644 --- a/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c @@ -80,7 +80,9 @@ static void ipf_p_rpcb_fixlen __P((fr_info_t *, int)); */ static frentry_t rpcbfr; /* Skeleton rule for reference by entities this proxy creates. */ -static int rpcbcnt; /* Upper bound of allocated RPCB sessions. */ +static VNET_DEFINE(int, rpcbcnt); +#define V_rpcbcnt VNET(rpcbcnt) + /* Upper bound of allocated RPCB sessions. */ /* XXX rpcbcnt still requires locking. */ static int rpcb_proxy_init = 0; @@ -107,7 +109,7 @@ static int rpcb_proxy_init = 0; void ipf_p_rpcb_main_load() { - rpcbcnt = 0; + V_rpcbcnt = 0; bzero((char *)&rpcbfr, sizeof(rpcbfr)); rpcbfr.fr_ref = 1; @@ -581,7 +583,7 @@ ipf_p_rpcb_insert(rs, rx) return(0); } - if (rpcbcnt == RPCB_MAXREQS) + if (V_rpcbcnt == RPCB_MAXREQS) return(-1); KMALLOC(rxp, rpcb_xact_t *); @@ -599,7 +601,7 @@ ipf_p_rpcb_insert(rs, rx) rxp->rx_ref = 1; - ++rpcbcnt; + ++V_rpcbcnt; return(0); } @@ -1084,7 +1086,7 @@ ipf_p_rpcb_deref(rs, rx) KFREE(rx); - --rpcbcnt; + --V_rpcbcnt; } /* -------------------------------------------------------------------- */ diff --git a/sys/contrib/ipfilter/netinet/ip_rules.c b/sys/contrib/ipfilter/netinet/ip_rules.c index 434b9de937b9..246b6cd207d2 100644 --- a/sys/contrib/ipfilter/netinet/ip_rules.c +++ b/sys/contrib/ipfilter/netinet/ip_rules.c @@ -32,6 +32,15 @@ #endif #if defined(__FreeBSD__) && (__FreeBSD_version > 220000) # include +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000) && defined(_KERNEL) +#include +#else +#define CURVNET_SET(arg) +#define CURVNET_RESTORE() +#define VNET_DEFINE(_t, _v) _t _v +#define VNET_DECLARE(_t, _v) extern _t _v +#define VNET(arg) arg +#endif #else # include #endif /* FreeBSD */ @@ -51,7 +60,8 @@ #ifdef IPFILTER_COMPILED -extern ipf_main_softc_t ipfmain; +VNET_DECLARE(ipf_main_softc_t, ipfmain); +#define V_ipfmain VNET(ipfmain) static u_long in_rule__0[] = { @@ -129,8 +139,8 @@ int ipfrule_add_out_() fp->fr_dsize = sizeof(ipf_rules_out_[0]); fp->fr_family = AF_INET; fp->fr_func = (ipfunc_t)ipfrule_match_out_; - err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, - ipfmain.ipf_active, 0); + err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, + V_ipfmain.ipf_active, 0); return err; } @@ -156,9 +166,9 @@ int ipfrule_remove_out_() } } if (err == 0) - err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR, + err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR, (caddr_t)&ipfrule_out_, - ipfmain.ipf_active, 0); + V_ipfmain.ipf_active, 0); if (err) return err; @@ -198,8 +208,8 @@ int ipfrule_add_in_() fp->fr_dsize = sizeof(ipf_rules_in_[0]); fp->fr_family = AF_INET; fp->fr_func = (ipfunc_t)ipfrule_match_in_; - err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, - ipfmain.ipf_active, 0); + err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, + V_ipfmain.ipf_active, 0); return err; } @@ -225,9 +235,9 @@ int ipfrule_remove_in_() } } if (err == 0) - err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR, + err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR, (caddr_t)&ipfrule_in_, - ipfmain.ipf_active, 0); + V_ipfmain.ipf_active, 0); if (err) return err; diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 4b0ca842901c..d8c40cdf79ef 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -7,6 +7,12 @@ * See the IPFILTER.LICENCE file for details on licencing. */ +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif #include #include @@ -18,6 +24,16 @@ #include #if __FreeBSD_version >= 500000 # include +# include +#endif +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000) && defined(_KERNEL) +#include +#else +#define CURVNET_SET(arg) +#define CURVNET_RESTORE() +#define VNET_DEFINE(_t, _v) _t _v +#define VNET_DECLARE(_t, _v) extern _t _v +#define VNET(arg) arg #endif #include #include @@ -33,7 +49,8 @@ #include "netinet/ip_frag.h" #include "netinet/ip_sync.h" -extern ipf_main_softc_t ipfmain; +VNET_DECLARE(ipf_main_softc_t, ipfmain); +#define V_ipfmain VNET(ipfmain) #if __FreeBSD_version >= 502116 static struct cdev *ipf_devs[IPL_LOGSIZE]; @@ -42,10 +59,14 @@ static dev_t ipf_devs[IPL_LOGSIZE]; #endif static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ); +static int sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS ); +static int sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS ); +static int sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS ); +static int sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS ); static int ipf_modload(void); static int ipf_modunload(void); -static int ipf_fbsd_sysctl_create(ipf_main_softc_t*); -static int ipf_fbsd_sysctl_destroy(ipf_main_softc_t*); +static int ipf_fbsd_sysctl_create(void); +static int ipf_fbsd_sysctl_destroy(void); #if (__FreeBSD_version >= 500024) # if (__FreeBSD_version >= 502116) @@ -70,40 +91,49 @@ static int ipfwrite __P((dev_t, struct uio *, int)); SYSCTL_DECL(_net_inet); #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \ - SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \ - ptr, val, sysctl_ipf_int, "I", descr); -#define SYSCTL_DYN_IPF(parent, nbr, name, access,ptr, val, descr) \ + SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|CTLFLAG_VNET|access, \ + ptr, val, sysctl_ipf_int, "I", descr) +#define SYSCTL_DYN_IPF_NAT(parent, nbr, name, access,ptr, val, descr) \ SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \ - CTLFLAG_DYN|CTLTYPE_INT|access, ptr, val, sysctl_ipf_int, "I", descr) + CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_nat, "I", descr) +#define SYSCTL_DYN_IPF_STATE(parent, nbr, name, access,ptr, val, descr) \ + SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \ + CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_state, "I", descr) +#define SYSCTL_DYN_IPF_FRAG(parent, nbr, name, access,ptr, val, descr) \ + SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \ + CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_frag, "I", descr) +#define SYSCTL_DYN_IPF_AUTH(parent, nbr, name, access,ptr, val, descr) \ + SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \ + CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_auth, "I", descr) static struct sysctl_ctx_list ipf_clist; #define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ #define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipfmain.ipf_flags, 0, "IPF flags"); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipfmain.ipf_pass, 0, "default pass/block"); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipfmain.ipf_active, 0, "IPF is active"); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_flags), 0, "IPF flags"); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_pass), 0, "default pass/block"); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &VNET_NAME(ipfmain.ipf_active), 0, "IPF is active"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, - &ipfmain.ipf_tcpidletimeout, 0, "TCP idle timeout in seconds"); + &VNET_NAME(ipfmain.ipf_tcpidletimeout), 0, "TCP idle timeout in seconds"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, - &ipfmain.ipf_tcphalfclosed, 0, "timeout for half closed TCP sessions"); + &VNET_NAME(ipfmain.ipf_tcphalfclosed), 0, "timeout for half closed TCP sessions"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, - &ipfmain.ipf_tcpclosewait, 0, "timeout for TCP sessions in closewait status"); + &VNET_NAME(ipfmain.ipf_tcpclosewait), 0, "timeout for TCP sessions in closewait status"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, - &ipfmain.ipf_tcplastack, 0, "timeout for TCP sessions in last ack status"); + &VNET_NAME(ipfmain.ipf_tcplastack), 0, "timeout for TCP sessions in last ack status"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, - &ipfmain.ipf_tcptimeout, 0, ""); + &VNET_NAME(ipfmain.ipf_tcptimeout), 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, - &ipfmain.ipf_tcpclosed, 0, ""); + &VNET_NAME(ipfmain.ipf_tcpclosed), 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, - &ipfmain.ipf_udptimeout, 0, "UDP timeout"); + &VNET_NAME(ipfmain.ipf_udptimeout), 0, "UDP timeout"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO, - &ipfmain.ipf_udpacktimeout, 0, ""); + &VNET_NAME(ipfmain.ipf_udpacktimeout), 0, ""); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, - &ipfmain.ipf_icmptimeout, 0, "ICMP timeout"); + &VNET_NAME(ipfmain.ipf_icmptimeout), 0, "ICMP timeout"); SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, - &ipfmain.ipf_running, 0, "IPF is running"); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipfmain.ipf_chksrc, 0, ""); -SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipfmain.ipf_minttl, 0, ""); + &VNET_NAME(ipfmain.ipf_running), 0, "IPF is running"); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_chksrc), 0, ""); +SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_minttl), 0, ""); #define CDEV_MAJOR 79 #include @@ -178,28 +208,61 @@ ipfilter_modevent(module_t mod, int type, void *unused) } +static void +vnet_ipf_init(void) +{ + char *defpass; + int error; + + if (ipf_create_all(&V_ipfmain) == NULL) + return; + + error = ipfattach(&V_ipfmain); + if (error) { + ipf_destroy_all(&V_ipfmain); + return; + } + + if (FR_ISPASS(V_ipfmain.ipf_pass)) + defpass = "pass"; + else if (FR_ISBLOCK(V_ipfmain.ipf_pass)) + defpass = "block"; + else + defpass = "no-match -> block"; + + if (IS_DEFAULT_VNET(curvnet)) + printf("%s initialized. Default = %s all, Logging = %s%s\n", + ipfilter_version, defpass, +#ifdef IPFILTER_LOG + "enabled", +#else + "disabled", +#endif +#ifdef IPFILTER_COMPILED + " (COMPILED)" +#else + "" +#endif + ); +} +VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD, + vnet_ipf_init, NULL); + static int ipf_modload() { - char *defpass, *c, *str; + char *c, *str; int i, j, error; if (ipf_load_all() != 0) return EIO; - if (ipf_create_all(&ipfmain) == NULL) + if (ipf_fbsd_sysctl_create() != 0) { return EIO; - - if (ipf_fbsd_sysctl_create(&ipfmain) != 0) - return EIO; - - error = ipfattach(&ipfmain); - if (error) - return error; + } for (i = 0; i < IPL_LOGSIZE; i++) ipf_devs[i] = NULL; - for (i = 0; (str = ipf_devfiles[i]); i++) { c = NULL; for(j = strlen(str); j > 0; j--) @@ -217,63 +280,48 @@ ipf_modload() return error; ipf_event_reg(); - if (FR_ISPASS(ipfmain.ipf_pass)) - defpass = "pass"; - else if (FR_ISBLOCK(ipfmain.ipf_pass)) - defpass = "block"; - else - defpass = "no-match -> block"; - - printf("%s initialized. Default = %s all, Logging = %s%s\n", - ipfilter_version, defpass, -#ifdef IPFILTER_LOG - "enabled", -#else - "disabled", -#endif -#ifdef IPFILTER_COMPILED - " (COMPILED)" -#else - "" -#endif - ); return 0; } +static void +vnet_ipf_uninit(void) +{ + + if (V_ipfmain.ipf_refcnt) + return; + + if (V_ipfmain.ipf_running >= 0) { + if (ipfdetach(&V_ipfmain) != 0) + return; + + ipf_destroy_all(&V_ipfmain); + } + + V_ipfmain.ipf_running = -2; +} +VNET_SYSUNINIT(vnet_ipf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD, + vnet_ipf_uninit, NULL); static int ipf_modunload() { int error, i; - if (ipfmain.ipf_refcnt) - return EBUSY; + ipf_event_dereg(); - if (ipf_fbsd_sysctl_destroy(&ipfmain) != 0) - return EIO; + ipf_fbsd_sysctl_destroy(); error = ipf_pfil_unhook(); if (error != 0) return error; - if (ipfmain.ipf_running >= 0) { - error = ipfdetach(&ipfmain); - if (error != 0) - return error; - - ipf_fbsd_sysctl_destroy(&ipfmain); - ipf_destroy_all(&ipfmain); - ipf_unload_all(); - } else - error = 0; - - ipfmain.ipf_running = -2; - for (i = 0; ipf_devfiles[i]; i++) { if (ipf_devs[i] != NULL) destroy_dev(ipf_devs[i]); } + ipf_unload_all(); + printf("%s unloaded\n", ipfilter_version); return error; @@ -287,7 +335,7 @@ static moduledata_t ipfiltermod = { }; -DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_ANY); +DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND); #ifdef MODULE_VERSION MODULE_VERSION(ipfilter, 1); #endif @@ -310,13 +358,87 @@ sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) if (!arg1) error = EPERM; else { - if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0)) + if ((oidp->oid_kind & CTLFLAG_OFF) && (V_ipfmain.ipf_running > 0)) error = EBUSY; else error = SYSCTL_IN(req, arg1, sizeof(int)); } return (error); } + +/* + * In the VIMAGE case kern_sysctl.c already adds the vnet base address given + * we set CTLFLAG_VNET to get proper access checks. Have to undo this. + * Then we add the given offset to the specific malloced struct hanging off + * virtualized ipmain struct. + */ +static int +sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS ) +{ + + if (arg1) { + ipf_nat_softc_t *nat_softc; + + nat_softc = V_ipfmain.ipf_nat_soft; +#ifdef VIMAGE + arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base); +#endif + arg1 = (void *)((uintptr_t)nat_softc + (uintptr_t)arg1); + } + + return (sysctl_ipf_int(oidp, arg1, arg2, req)); +} + +static int +sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS ) +{ + + if (arg1) { + ipf_state_softc_t *state_softc; + + state_softc = V_ipfmain.ipf_state_soft; +#ifdef VIMAGE + arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base); +#endif + arg1 = (void *)((uintptr_t)state_softc + (uintptr_t)arg1); + } + + return (sysctl_ipf_int(oidp, arg1, arg2, req)); +} + +static int +sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS ) +{ + + if (arg1) { + ipf_auth_softc_t *auth_softc; + + auth_softc = V_ipfmain.ipf_auth_soft; +#ifdef VIMAGE + arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base); +#endif + arg1 = (void *)((uintptr_t)auth_softc + (uintptr_t)arg1); + } + + return (sysctl_ipf_int(oidp, arg1, arg2, req)); +} + +static int +sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS ) +{ + + if (arg1) { + ipf_frag_softc_t *frag_softc; + + frag_softc = V_ipfmain.ipf_frag_soft; +#ifdef VIMAGE + arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base); +#endif + arg1 = (void *)((uintptr_t)frag_softc + (uintptr_t)arg1); + } + + return (sysctl_ipf_int(oidp, arg1, arg2, req)); +} #endif @@ -335,24 +457,25 @@ ipfpoll(dev_t dev, int events, struct proc *td) revents = 0; + CURVNET_SET(TD_TO_VNET(td)); switch (unit) { case IPL_LOGIPF : case IPL_LOGNAT : case IPL_LOGSTATE : #ifdef IPFILTER_LOG - if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit)) + if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&V_ipfmain, unit)) revents |= events & (POLLIN | POLLRDNORM); #endif break; case IPL_LOGAUTH : - if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain)) + if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&V_ipfmain)) revents |= events & (POLLIN | POLLRDNORM); break; case IPL_LOGSYNC : - if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain)) + if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&V_ipfmain)) revents |= events & (POLLIN | POLLRDNORM); - if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain)) + if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&V_ipfmain)) revents |= events & (POLLOUT | POLLWRNORM); break; case IPL_LOGSCAN : @@ -362,7 +485,8 @@ ipfpoll(dev_t dev, int events, struct proc *td) } if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0)) - selrecord(td, &ipfmain.ipf_selwait[unit]); + selrecord(td, &V_ipfmain.ipf_selwait[unit]); + CURVNET_RESTORE(); return revents; } @@ -465,22 +589,31 @@ static int ipfread(dev, uio) #endif struct uio *uio; { + int error; int unit = GET_MINOR(dev); if (unit < 0) return ENXIO; - if (ipfmain.ipf_running < 1) + CURVNET_SET(TD_TO_VNET(curthread)); + if (V_ipfmain.ipf_running < 1) { + CURVNET_RESTORE(); return EIO; + } - if (unit == IPL_LOGSYNC) - return ipf_sync_read(&ipfmain, uio); + if (unit == IPL_LOGSYNC) { + error = ipf_sync_read(&V_ipfmain, uio); + CURVNET_RESTORE(); + return error; + } #ifdef IPFILTER_LOG - return ipf_log_read(&ipfmain, unit, uio); + error = ipf_log_read(&V_ipfmain, unit, uio); #else - return ENXIO; + error = ENXIO; #endif + CURVNET_RESTORE(); + return error; } @@ -503,61 +636,57 @@ static int ipfwrite(dev, uio) #endif struct uio *uio; { + int error; - if (ipfmain.ipf_running < 1) + CURVNET_SET(TD_TO_VNET(curthread)); + if (V_ipfmain.ipf_running < 1) { + CURVNET_RESTORE(); return EIO; + } - if (GET_MINOR(dev) == IPL_LOGSYNC) - return ipf_sync_write(&ipfmain, uio); + if (GET_MINOR(dev) == IPL_LOGSYNC) { + error = ipf_sync_write(&V_ipfmain, uio); + CURVNET_RESTORE(); + return error; + } return ENXIO; } static int -ipf_fbsd_sysctl_create(main_softc) - ipf_main_softc_t *main_softc; +ipf_fbsd_sysctl_create(void) { - ipf_nat_softc_t *nat_softc; - ipf_state_softc_t *state_softc; - ipf_auth_softc_t *auth_softc; - ipf_frag_softc_t *frag_softc; - - nat_softc = main_softc->ipf_nat_soft; - state_softc = main_softc->ipf_state_soft; - auth_softc = main_softc->ipf_auth_soft; - frag_softc = main_softc->ipf_frag_soft; sysctl_ctx_init(&ipf_clist); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO, - &nat_softc->ipf_nat_defage, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO, - &state_softc->ipf_state_size, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO, - &state_softc->ipf_state_max, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO, - &nat_softc->ipf_nat_table_max, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO, - &nat_softc->ipf_nat_table_sz, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO, - &nat_softc->ipf_nat_maprules_sz, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO, - &nat_softc->ipf_nat_rdrrules_sz, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO, - &nat_softc->ipf_nat_hostmap_sz, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO, - &auth_softc->ipf_auth_size, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD, - &auth_softc->ipf_auth_used, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW, - &auth_softc->ipf_auth_defaultage, 0, ""); - SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW, - &frag_softc->ipfr_ttl, 0, ""); + SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO, + (void *)offsetof(ipf_nat_softc_t, ipf_nat_defage), 0, ""); + SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO, + (void *)offsetof(ipf_state_softc_t, ipf_state_size), 0, ""); + SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO, + (void *)offsetof(ipf_state_softc_t, ipf_state_max), 0, ""); + SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO, + (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_max), 0, ""); + SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO, + (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_sz), 0, ""); + SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO, + (void *)offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz), 0, ""); + SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO, + (void *)offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), 0, ""); + SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO, + (void *)offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz), 0, ""); + SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO, + (void *)offsetof(ipf_auth_softc_t, ipf_auth_size), 0, ""); + SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD, + (void *)offsetof(ipf_auth_softc_t, ipf_auth_used), 0, ""); + SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW, + (void *)offsetof(ipf_auth_softc_t, ipf_auth_defaultage), 0, ""); + SYSCTL_DYN_IPF_FRAG(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW, + (void *)offsetof(ipf_frag_softc_t, ipfr_ttl), 0, ""); return 0; } static int -ipf_fbsd_sysctl_destroy(main_softc) - ipf_main_softc_t *main_softc; +ipf_fbsd_sysctl_destroy(void) { if (sysctl_ctx_free(&ipf_clist)) { printf("sysctl_ctx_free failed");