diff options
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_fil_freebsd.c')
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil_freebsd.c | 1035 |
1 files changed, 413 insertions, 622 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 338b69a..9d26193 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 1993-2003 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12:51:50 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #if defined(KERNEL) || defined(_KERNEL) @@ -25,60 +25,26 @@ static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12 # include "opt_random_ip_id.h" #endif #include <sys/param.h> -#if defined(__FreeBSD__) && !defined(__FreeBSD_version) -# if defined(IPFILTER_LKM) -# ifndef __FreeBSD_cc_version -# include <osreldate.h> -# else -# if __FreeBSD_cc_version < 430000 -# include <osreldate.h> -# endif -# endif -# endif -#endif #include <sys/errno.h> #include <sys/types.h> #include <sys/file.h> -#if __FreeBSD_version >= 220000 # include <sys/fcntl.h> # include <sys/filio.h> -#else -# include <sys/ioctl.h> -#endif #include <sys/time.h> #include <sys/systm.h> -#if (__FreeBSD_version >= 300000) # include <sys/dirent.h> -#else -# include <sys/dir.h> -#endif +# include <sys/mbuf.h> +# include <sys/sockopt.h> #if !defined(__hpux) # include <sys/mbuf.h> #endif -#include <sys/protosw.h> #include <sys/socket.h> -#if __FreeBSD_version >= 500043 # include <sys/selinfo.h> -#else -# include <sys/select.h> -#endif -#if __FreeBSD_version >= 800044 # include <netinet/tcp_var.h> -#else -#define V_path_mtu_discovery path_mtu_discovery -#define V_ipforwarding ipforwarding -#endif #include <net/if.h> -#if __FreeBSD_version >= 300000 # include <net/if_var.h> -# if __FreeBSD_version >= 500043 # include <net/netisr.h> -# endif -# if !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif -#endif #include <net/route.h> #include <netinet/in.h> #include <netinet/in_var.h> @@ -92,9 +58,6 @@ static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12 #include <netinet/udp.h> #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> -#ifndef _KERNEL -# include "netinet/ipf.h" -#endif #include "netinet/ip_compat.h" #ifdef USE_INET6 # include <netinet/icmp6.h> @@ -105,101 +68,94 @@ static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12 #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "netinet/ip_auth.h" -#ifdef IPFILTER_SYNC #include "netinet/ip_sync.h" -#endif +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" #ifdef IPFILTER_SCAN #include "netinet/ip_scan.h" #endif #include "netinet/ip_pool.h" -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) # include <sys/malloc.h> -#endif #include <sys/kernel.h> #ifdef CSUM_DATA_VALID #include <machine/in_cksum.h> #endif extern int ip_optcopy __P((struct ip *, struct ip *)); -#if (__FreeBSD_version > 460000) && (__FreeBSD_version < 800055) -extern int path_mtu_discovery; -#endif # ifdef IPFILTER_M_IPFILTER MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures"); # endif -#if !defined(__osf__) -extern struct protosw inetsw[]; -#endif - -static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); -static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **)); -# ifdef USE_MUTEXES -ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; -ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; -ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens; -ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; -# endif +static u_short ipid = 0; +static int (*ipf_savep) __P((void *, ip_t *, int, void *, int, struct mbuf **)); +static int ipf_send_ip __P((fr_info_t *, mb_t *)); +static void ipf_timer_func __P((void *arg)); int ipf_locks_done = 0; -#if (__FreeBSD_version >= 300000) -struct callout_handle fr_slowtimer_ch; -#endif -struct selinfo ipfselwait[IPL_LOGSIZE]; +ipf_main_softc_t ipfmain; -#if (__FreeBSD_version >= 500011) # include <sys/conf.h> # if defined(NETBSD_PF) # include <net/pfil.h> -# if (__FreeBSD_version < 501108) -# include <netinet/ipprotosw.h> -# endif +# endif /* NETBSD_PF */ /* - * We provide the fr_checkp name just to minimize changes later. + * We provide the ipf_checkp name just to minimize changes later. */ -int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); -# endif /* NETBSD_PF */ -#endif /* __FreeBSD_version >= 500011 */ +int (*ipf_checkp) __P((void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); -#if (__FreeBSD_version >= 502103) static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag; static void ipf_ifevent(void *arg); static void ipf_ifevent(arg) -void *arg; + void *arg; { - frsync(NULL); + ipf_sync(arg, NULL); } -#endif -#if (__FreeBSD_version >= 501108) && defined(_KERNEL) static int -fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) +ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) { struct ip *ip = mtod(*mp, struct ip *); - return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp); + int rv; + + /* + * IPFilter expects evreything in network byte order + */ +#if (__FreeBSD_version < 1000019) + 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), + mp); +#if (__FreeBSD_version < 1000019) + if ((rv == 0) && (*mp != NULL)) { + ip = mtod(*mp, struct ip *); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + } +#endif + return rv; } # ifdef USE_INET6 # include <netinet/ip6.h> static int -fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) +ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) { - return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr), - ifp, (dir == PFIL_OUT), mp)); + return (ipf_check(&ipfmain, mtod(*mp, struct ip *), + sizeof(struct ip6_hdr), ifp, (dir == PFIL_OUT), mp)); } # endif -#endif /* __FreeBSD_version >= 501108 */ #if defined(IPFILTER_LKM) -int iplidentify(s) -char *s; +int ipf_identify(s) + char *s; { if (strcmp(s, "ipl") == 0) return 1; @@ -208,49 +164,67 @@ char *s; #endif /* IPFILTER_LKM */ -int ipfattach() +static void +ipf_timer_func(arg) + void *arg; +{ + ipf_main_softc_t *softc = arg; + SPL_INT(s); + + SPL_NET(s); + READ_ENTER(&softc->ipf_global); + + if (softc->ipf_running > 0) + ipf_slowtimer(softc); + + if (softc->ipf_running == -1 || softc->ipf_running == 1) { +#if FREEBSD_GE_REV(300000) + softc->ipf_slow_ch = timeout(ipf_timer_func, softc, hz/2); +#else + timeout(ipf_timer_func, softc, hz/2); +#endif + } + RWLOCK_EXIT(&softc->ipf_global); + SPL_X(s); +} + + +int +ipfattach(softc) + ipf_main_softc_t *softc; { #ifdef USE_SPL int s; #endif SPL_NET(s); - if (fr_running > 0) { + if (softc->ipf_running > 0) { SPL_X(s); return EBUSY; } - MUTEX_INIT(&ipf_rw, "ipf rw mutex"); - MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex"); - RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); - RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); - ipf_locks_done = 1; - - if (fr_initialise() < 0) { + if (ipf_init_all(softc) < 0) { SPL_X(s); return EIO; } - if (fr_checkp != fr_check) { - fr_savep = fr_checkp; - fr_checkp = fr_check; + if (ipf_checkp != ipf_check) { + ipf_savep = ipf_checkp; + ipf_checkp = ipf_check; } - bzero((char *)ipfselwait, sizeof(ipfselwait)); - bzero((char *)frcache, sizeof(frcache)); - fr_running = 1; + bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait)); + softc->ipf_running = 1; - if (fr_control_forwarding & 1) + if (softc->ipf_control_forwarding & 1) V_ipforwarding = 1; + ipid = 0; + SPL_X(s); -#if (__FreeBSD_version >= 300000) - fr_slowtimer_ch = timeout(fr_slowtimer, NULL, - (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); -#else - timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); -#endif + softc->ipf_slow_ch = timeout(ipf_timer_func, softc, + (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); return 0; } @@ -259,44 +233,32 @@ int ipfattach() * Disable the filter by removing the hooks from the IP input/output * stream. */ -int ipfdetach() +int +ipfdetach(softc) + ipf_main_softc_t *softc; { #ifdef USE_SPL int s; #endif - if (fr_control_forwarding & 2) + + if (softc->ipf_control_forwarding & 2) V_ipforwarding = 0; SPL_NET(s); -#if (__FreeBSD_version >= 300000) - if (fr_slowtimer_ch.callout != NULL) - untimeout(fr_slowtimer, NULL, fr_slowtimer_ch); - bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch)); -#else - untimeout(fr_slowtimer, NULL); -#endif /* FreeBSD */ + if (softc->ipf_slow_ch.callout != NULL) + untimeout(ipf_timer_func, softc, softc->ipf_slow_ch); + bzero(&softc->ipf_slow, sizeof(softc->ipf_slow)); #ifndef NETBSD_PF - if (fr_checkp != NULL) - fr_checkp = fr_savep; - fr_savep = NULL; + if (ipf_checkp != NULL) + ipf_checkp = ipf_savep; + ipf_savep = NULL; #endif - fr_deinitialise(); - - fr_running = -2; - - (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); + ipf_fini_all(softc); - if (ipf_locks_done == 1) { - MUTEX_DESTROY(&ipf_timeoutlock); - MUTEX_DESTROY(&ipf_rw); - RW_DESTROY(&ipf_ipidfrag); - RW_DESTROY(&ipf_tokens); - ipf_locks_done = 0; - } + softc->ipf_running = -2; SPL_X(s); @@ -307,62 +269,51 @@ int ipfdetach() /* * Filter ioctl interface. */ -int iplioctl(dev, cmd, data, mode -# if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000)) +int +ipfioctl(dev, cmd, data, mode , p) -# if (__FreeBSD_version >= 500024) -struct thread *p; -# if (__FreeBSD_version >= 500043) + struct thread *p; # define p_cred td_ucred # define p_uid td_ucred->cr_ruid -# else -# define p_cred t_proc->p_cred -# define p_uid t_proc->p_cred->p_ruid -# endif -# else -struct proc *p; -# define p_uid p_cred->p_ruid -# endif /* __FreeBSD_version >= 500024 */ -# else -) -# endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -ioctlcmd_t cmd; -caddr_t data; -int mode; + struct cdev *dev; + ioctlcmd_t cmd; + caddr_t data; + int mode; { int error = 0, unit = 0; SPL_INT(s); -#if (BSD >= 199306) && defined(_KERNEL) -# if (__FreeBSD_version >= 500034) - if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) -# else - if ((securelevel >= 3) && (mode & FWRITE)) -# endif +#if (BSD >= 199306) + if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) + { + ipfmain.ipf_interror = 130001; return EPERM; + } #endif unit = GET_MINOR(dev); - if ((IPL_LOGMAX < unit) || (unit < 0)) + if ((IPL_LOGMAX < unit) || (unit < 0)) { + ipfmain.ipf_interror = 130002; return ENXIO; + } - if (fr_running <= 0) { - if (unit != IPL_LOGIPF) + if (ipfmain.ipf_running <= 0) { + if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130003; return EIO; + } if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && cmd != SIOCIPFSET && cmd != SIOCFRENB && - cmd != SIOCGETFS && cmd != SIOCGETFF) + cmd != SIOCGETFS && cmd != SIOCGETFF && + cmd != SIOCIPFINTERROR) { + ipfmain.ipf_interror = 130004; return EIO; + } } SPL_NET(s); - error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p); + error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, p->p_uid, p); if (error != -1) { SPL_X(s); return error; @@ -374,182 +325,13 @@ int mode; } -#if 0 -void fr_forgetifp(ifp) -void *ifp; -{ - register frentry_t *f; - - WRITE_ENTER(&ipf_mutex); - for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#ifdef USE_INET6 - for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#endif - RWLOCK_EXIT(&ipf_mutex); - fr_natsync(ifp); -} -#endif - - -/* - * routines below for saving IP headers to buffer - */ -int iplopen(dev, flags -#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) -, devtype, p) -int devtype; -# if (__FreeBSD_version >= 500024) -struct thread *p; -# else -struct proc *p; -# endif /* __FreeBSD_version >= 500024 */ -#else -) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -int flags; -{ - u_int min = GET_MINOR(dev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - - -int iplclose(dev, flags -#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) -, devtype, p) -int devtype; -# if (__FreeBSD_version >= 500024) -struct thread *p; -# else -struct proc *p; -# endif /* __FreeBSD_version >= 500024 */ -#else -) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -int flags; -{ - u_int min = GET_MINOR(dev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - -/* - * iplread/ipllog - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -#if (BSD >= 199306) -int iplread(dev, uio, ioflag) -int ioflag; -#else -int iplread(dev, uio) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -register struct uio *uio; -{ - u_int xmin = GET_MINOR(dev); - - if (fr_running < 1) - return EIO; - - if (xmin < 0) - return ENXIO; - -# ifdef IPFILTER_SYNC - if (xmin == IPL_LOGSYNC) - return ipfsync_read(uio); -# endif - -#ifdef IPFILTER_LOG - return ipflog_read(xmin, uio); -#else - return ENXIO; -#endif -} - - /* - * iplwrite - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -#if (BSD >= 199306) -int iplwrite(dev, uio, ioflag) -int ioflag; -#else -int iplwrite(dev, uio) -#endif -#if defined(_KERNEL) && (__FreeBSD_version >= 502116) -struct cdev *dev; -#else -dev_t dev; -#endif -register struct uio *uio; -{ - - if (fr_running < 1) - return EIO; - -#ifdef IPFILTER_SYNC - if (GET_MINOR(dev) == IPL_LOGSYNC) - return ipfsync_write(uio); -#endif - return ENXIO; -} - - -/* - * fr_send_reset - this could conceivably be a call to tcp_respond(), but that + * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that * requires a large amount of setting up and isn't any more efficient. */ -int fr_send_reset(fin) -fr_info_t *fin; +int +ipf_send_reset(fin) + fr_info_t *fin; { struct tcphdr *tcp, *tcp2; int tlen = 0, hlen; @@ -563,7 +345,7 @@ fr_info_t *fin; if (tcp->th_flags & TH_RST) return -1; /* feedback loop */ - if (fr_checkl4sum(fin) == -1) + if (ipf_checkl4sum(fin) == -1) return -1; tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + @@ -628,11 +410,11 @@ fr_info_t *fin; ip6->ip6_plen = htons(sizeof(struct tcphdr)); ip6->ip6_nxt = IPPROTO_TCP; ip6->ip6_hlim = 0; - ip6->ip6_src = fin->fin_dst6; - ip6->ip6_dst = fin->fin_src6; + ip6->ip6_src = fin->fin_dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*ip6), sizeof(*tcp2)); - return fr_send_ip(fin, m, &m); + return ipf_send_ip(fin, m); } #endif ip->ip_p = IPPROTO_TCP; @@ -640,14 +422,18 @@ fr_info_t *fin; ip->ip_src.s_addr = fin->fin_daddr; ip->ip_dst.s_addr = fin->fin_saddr; tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); - ip->ip_len = hlen + sizeof(*tcp2); - return fr_send_ip(fin, m, &m); + ip->ip_len = htons(hlen + sizeof(*tcp2)); + return ipf_send_ip(fin, m); } -static int fr_send_ip(fin, m, mpp) -fr_info_t *fin; -mb_t *m, **mpp; +/* + * ip_len must be in network byte order when called. + */ +static int +ipf_send_ip(fin, m) + fr_info_t *fin; + mb_t *m; { fr_info_t fnew; ip_t *ip, *oip; @@ -655,24 +441,27 @@ mb_t *m, **mpp; ip = mtod(m, ip_t *); bzero((char *)&fnew, sizeof(fnew)); + fnew.fin_main_soft = fin->fin_main_soft; IP_V_A(ip, fin->fin_v); switch (fin->fin_v) { case 4 : - fnew.fin_v = 4; oip = fin->fin_ip; + hlen = sizeof(*oip); + fnew.fin_v = 4; + fnew.fin_p = ip->ip_p; + fnew.fin_plen = ntohs(ip->ip_len); IP_HL_A(ip, sizeof(*oip) >> 2); ip->ip_tos = oip->ip_tos; ip->ip_id = fin->fin_ip->ip_id; -#if (__FreeBSD_version > 460000) - ip->ip_off = V_path_mtu_discovery ? IP_DF : 0; +#if defined(FreeBSD) && (__FreeBSD_version > 460000) + ip->ip_off = htons(path_mtu_discovery ? IP_DF : 0); #else ip->ip_off = 0; #endif ip->ip_ttl = V_ip_defttl; ip->ip_sum = 0; - hlen = sizeof(*oip); break; #ifdef USE_INET6 case 6 : @@ -682,8 +471,10 @@ mb_t *m, **mpp; ip6->ip6_vfc = 0x60; ip6->ip6_hlim = IPDEFTTL; - fnew.fin_v = 6; hlen = sizeof(*ip6); + fnew.fin_p = ip6->ip6_nxt; + fnew.fin_v = 6; + fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; break; } #endif @@ -698,28 +489,29 @@ mb_t *m, **mpp; fnew.fin_flx = FI_NOCKSUM; fnew.fin_m = m; fnew.fin_ip = ip; - fnew.fin_mp = mpp; + fnew.fin_mp = &m; fnew.fin_hlen = hlen; fnew.fin_dp = (char *)ip + hlen; - (void) fr_makefrip(hlen, ip, &fnew); + (void) ipf_makefrip(hlen, ip, &fnew); - return fr_fastroute(m, mpp, &fnew, NULL); + return ipf_fastroute(m, &m, &fnew, NULL); } -int fr_send_icmp_err(type, fin, dst) -int type; -fr_info_t *fin; -int dst; +int +ipf_send_icmp_err(type, fin, dst) + int type; + fr_info_t *fin; + int dst; { int err, hlen, xtra, iclen, ohlen, avail, code; struct in_addr dst4; struct icmp *icmp; struct mbuf *m; + i6addr_t dst6; void *ifp; #ifdef USE_INET6 ip6_t *ip6; - struct in6_addr dst6; #endif ip_t *ip, *ip2; @@ -728,11 +520,17 @@ int dst; code = fin->fin_icode; #ifdef USE_INET6 - if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) +#if 0 + /* XXX Fix an off by one error: s/>/>=/ + was: + if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) + Fix obtained from NetBSD ip_fil_netbsd.c r1.4: */ +#endif + if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int))) return -1; #endif - if (fr_checkl4sum(fin) == -1) + if (ipf_checkl4sum(fin) == -1) return -1; #ifdef MGETHDR MGETHDR(m, M_DONTWAIT, MT_HEADER); @@ -746,10 +544,10 @@ int dst; xtra = 0; hlen = 0; ohlen = 0; + dst4.s_addr = 0; ifp = fin->fin_ifp; if (fin->fin_v == 4) { - if ((fin->fin_p == IPPROTO_ICMP) && - !(fin->fin_flx & FI_SHORT)) + if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) switch (ntohs(fin->fin_data[0]) >> 8) { case ICMP_ECHO : @@ -763,16 +561,18 @@ int dst; } if (dst == 0) { - if (fr_ifpaddr(4, FRI_NORMAL, ifp, - &dst4, NULL) == -1) { + if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { FREE_MB_T(m); return -1; } + dst4 = dst6.in4; } else dst4.s_addr = fin->fin_daddr; hlen = sizeof(ip_t); ohlen = fin->fin_hlen; + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; if (fin->fin_hlen < fin->fin_plen) xtra = MIN(fin->fin_dlen, 8); else @@ -783,12 +583,12 @@ int dst; else if (fin->fin_v == 6) { hlen = sizeof(ip6_t); ohlen = sizeof(ip6_t); + iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; type = icmptoicmp6types[type]; if (type == ICMP6_DST_UNREACH) code = icmptoicmp6unreach[code]; - if (hlen + sizeof(*icmp) + max_linkhdr + - fin->fin_plen > avail) { + if (iclen + max_linkhdr + fin->fin_plen > avail) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { FREE_MB_T(m); @@ -796,11 +596,11 @@ int dst; } avail = MCLBYTES; } - xtra = MIN(fin->fin_plen, - avail - hlen - sizeof(*icmp) - max_linkhdr); + xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); + xtra = MIN(xtra, IPV6_MMTU - iclen); if (dst == 0) { - if (fr_ifpaddr(6, FRI_NORMAL, ifp, - (struct in_addr *)&dst6, NULL) == -1) { + if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, + &dst6, NULL) == -1) { FREE_MB_T(m); return -1; } @@ -813,7 +613,6 @@ int dst; return -1; } - iclen = hlen + sizeof(*icmp); avail -= (max_linkhdr + iclen); if (avail < 0) { FREE_MB_T(m); @@ -834,9 +633,17 @@ int dst; icmp->icmp_code = fin->fin_icode; icmp->icmp_cksum = 0; #ifdef icmp_nextmtu - if (type == ICMP_UNREACH && - fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp) - icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu); + if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { + if (fin->fin_mtu != 0) { + icmp->icmp_nextmtu = htons(fin->fin_mtu); + + } else if (ifp != NULL) { + icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); + + } else { /* make up a number... */ + icmp->icmp_nextmtu = htons(fin->fin_plen - 20); + } + } #endif bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); @@ -848,8 +655,8 @@ int dst; ip6->ip6_plen = htons(iclen - hlen); ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 0; - ip6->ip6_src = dst6; - ip6->ip6_dst = fin->fin_src6; + ip6->ip6_src = dst6.in6; + ip6->ip6_dst = fin->fin_src6.in6; if (xtra > 0) bcopy((char *)fin->fin_ip + ohlen, (char *)&icmp->icmp_ip + ohlen, xtra); @@ -858,8 +665,6 @@ int dst; } else #endif { - ip2->ip_len = htons(ip2->ip_len); - ip2->ip_off = htons(ip2->ip_off); ip->ip_p = IPPROTO_ICMP; ip->ip_src.s_addr = dst4.s_addr; ip->ip_dst.s_addr = fin->fin_saddr; @@ -869,41 +674,25 @@ int dst; (char *)&icmp->icmp_ip + ohlen, xtra); icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8); - ip->ip_len = iclen; + ip->ip_len = htons(iclen); ip->ip_p = IPPROTO_ICMP; } - err = fr_send_ip(fin, m, &m); + err = ipf_send_ip(fin, m); return err; } -#if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) -# if (BSD < 199306) -int iplinit __P((void)); - -int -# else -void iplinit __P((void)); - -void -# endif -iplinit() -{ - if (ipfattach() != 0) - printf("IP Filter failed to attach\n"); - ip_init(); -} -#endif /* __FreeBSD_version < 300000 */ /* * m0 - pointer to mbuf where the IP packet starts * mpp - pointer to the mbuf pointer that is the start of the mbuf chain */ -int fr_fastroute(m0, mpp, fin, fdp) -mb_t *m0, **mpp; -fr_info_t *fin; -frdest_t *fdp; +int +ipf_fastroute(m0, mpp, fin, fdp) + mb_t *m0, **mpp; + fr_info_t *fin; + frdest_t *fdp; { register struct ip *ip, *mhip; register struct mbuf *m = *mpp; @@ -913,6 +702,7 @@ frdest_t *fdp; struct sockaddr_in *dst; struct route iproute; u_short ip_off; + frdest_t node; frentry_t *fr; ro = NULL; @@ -949,33 +739,36 @@ frdest_t *fdp; * currently "to <if>" and "to <if>:ip#" are not supported * for IPv6 */ -#if (__FreeBSD_version >= 490000) - return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); -#else - return ip6_output(m0, NULL, NULL, 0, NULL, NULL); -#endif + return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); } #endif hlen = fin->fin_hlen; ip = mtod(m0, struct ip *); + ifp = NULL; /* * Route packet. */ ro = &iproute; - bzero((caddr_t)ro, sizeof (*ro)); + bzero(ro, sizeof (*ro)); dst = (struct sockaddr_in *)&ro->ro_dst; dst->sin_family = AF_INET; dst->sin_addr = ip->ip_dst; fr = fin->fin_fr; + if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && + (fdp->fd_type == FRD_DSTLIST)) { + if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) + fdp = &node; + } + if (fdp != NULL) - ifp = fdp->fd_ifp; + ifp = fdp->fd_ptr; else ifp = fin->fin_ifp; - if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) { + if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { error = -2; goto bad; } @@ -1012,21 +805,19 @@ frdest_t *fdp; sifp = fin->fin_ifp; fin->fin_ifp = ifp; fin->fin_out = 1; - (void) fr_acctpkt(fin, NULL); + (void) ipf_acctpkt(fin, NULL); fin->fin_fr = NULL; if (!fr || !(fr->fr_flags & FR_RETMASK)) { u_32_t pass; - if (fr_checkstate(fin, &pass) != NULL) - fr_statederef((ipstate_t **)&fin->fin_state); + (void) ipf_state_check(fin, &pass); } - switch (fr_checknatout(fin, NULL)) + switch (ipf_nat_checkout(fin, NULL)) { case 0 : break; case 1 : - fr_natderef((nat_t **)&fin->fin_nat); ip->ip_sum = 0; break; case -1 : @@ -1042,14 +833,12 @@ frdest_t *fdp; /* * If small enough for interface, can just send directly. */ - if (ip->ip_len <= ifp->if_mtu) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - + if (ntohs(ip->ip_len) <= ifp->if_mtu) { if (!ip->ip_sum) ip->ip_sum = in_cksum(m, hlen); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, - ro); + ro + ); goto done; } /* @@ -1077,7 +866,7 @@ frdest_t *fdp; */ m0 = m; mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { + for (off = hlen + len; off < ntohs(ip->ip_len); off += len) { #ifdef MGETHDR MGETHDR(m, M_DONTWAIT, MT_HEADER); #else @@ -1097,8 +886,8 @@ frdest_t *fdp; } m->m_len = mhlen; mhip->ip_off = ((off - hlen) >> 3) + ip_off; - if (off + len >= ip->ip_len) - len = ip->ip_len - off; + if (off + len >= ntohs(ip->ip_len)) + len = ntohs(ip->ip_len) - off; else mhip->ip_off |= IP_MF; mhip->ip_len = htons((u_short)(len + mhlen)); @@ -1130,21 +919,22 @@ sendorfree: m->m_act = 0; if (error == 0) error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro); + (struct sockaddr *)dst, + ro + ); else FREE_MB_T(m); } - } + } done: if (!error) - fr_frouteok[0]++; + ipfmain.ipf_frouteok[0]++; else - fr_frouteok[1]++; + ipfmain.ipf_frouteok[1]++; if ((ro != NULL) && (ro->ro_rt != NULL)) { RTFREE(ro->ro_rt); } - *mpp = NULL; return 0; bad: if (error == EMSGSIZE) { @@ -1152,7 +942,7 @@ bad: code = fin->fin_icode; fin->fin_icode = ICMP_UNREACH_NEEDFRAG; fin->fin_ifp = ifp; - (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1); + (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); fin->fin_ifp = sifp; fin->fin_icode = code; } @@ -1161,8 +951,9 @@ bad: } -int fr_verifysrc(fin) -fr_info_t *fin; +int +ipf_verifysrc(fin) + fr_info_t *fin; { struct sockaddr_in *dst; struct route iproute; @@ -1182,10 +973,12 @@ fr_info_t *fin; /* * return the first IP Address associated with an interface */ -int fr_ifpaddr(v, atype, ifptr, inp, inpmask) -int v, atype; -void *ifptr; -struct in_addr *inp, *inpmask; +int +ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) + ipf_main_softc_t *softc; + int v, atype; + void *ifptr; + i6addr_t *inp, *inpmask; { #ifdef USE_INET6 struct in6_addr *inp6 = NULL; @@ -1202,16 +995,12 @@ struct in_addr *inp, *inpmask; ifp = ifptr; if (v == 4) - inp->s_addr = 0; + inp->in4.s_addr = 0; #ifdef USE_INET6 else if (v == 6) - bzero((char *)inp, sizeof(struct in6_addr)); + bzero((char *)inp, sizeof(*inp)); #endif -#if (__FreeBSD_version >= 300000) ifa = TAILQ_FIRST(&ifp->if_addrhead); -#else - ifa = ifp->if_addrlist; -#endif /* __FreeBSD_version >= 300000 */ sock = ifa->ifa_addr; while (sock != NULL && ifa != NULL) { @@ -1226,11 +1015,7 @@ struct in_addr *inp, *inpmask; break; } #endif -#if (__FreeBSD_version >= 300000) ifa = TAILQ_NEXT(ifa, ifa_link); -#else - ifa = ifa->ifa_next; -#endif /* __FreeBSD_version >= 300000 */ if (ifa != NULL) sock = ifa->ifa_addr; } @@ -1249,79 +1034,45 @@ struct in_addr *inp, *inpmask; #ifdef USE_INET6 if (v == 6) { - return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, - (struct sockaddr_in6 *)mask, - inp, inpmask); + return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, + (struct sockaddr_in6 *)mask, + inp, inpmask); } #endif - return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock, - (struct sockaddr_in *)mask, inp, inpmask); + return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, + (struct sockaddr_in *)mask, + &inp->in4, &inpmask->in4); } -u_32_t fr_newisn(fin) -fr_info_t *fin; +u_32_t +ipf_newisn(fin) + fr_info_t *fin; { u_32_t newiss; -#if (__FreeBSD_version >= 400000) newiss = arc4random(); -#else - static iss_seq_off = 0; - u_char hash[16]; - MD5_CTX ctx; - - /* - * Compute the base value of the ISS. It is a hash - * of (saddr, sport, daddr, dport, secret). - */ - MD5Init(&ctx); - - MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, - sizeof(fin->fin_fi.fi_src)); - MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, - sizeof(fin->fin_fi.fi_dst)); - MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); - - MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); - - MD5Final(hash, &ctx); - - memcpy(&newiss, hash, sizeof(newiss)); - - /* - * Now increment our "timer", and add it in to - * the computed value. - * - * XXX Use `addin'? - * XXX TCP_ISSINCR too large to use? - */ - iss_seq_off += 0x00010000; - newiss += iss_seq_off; -#endif return newiss; } /* ------------------------------------------------------------------------ */ -/* Function: fr_nextipid */ +/* Function: ipf_nextipid */ /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Returns the next IPv4 ID to use for this packet. */ /* ------------------------------------------------------------------------ */ -u_short fr_nextipid(fin) -fr_info_t *fin; +u_short +ipf_nextipid(fin) + fr_info_t *fin; { -#ifndef RANDOM_IP_ID - static u_short ipid = 0; u_short id; - MUTEX_ENTER(&ipf_rw); +#ifndef RANDOM_IP_ID + MUTEX_ENTER(&ipfmain.ipf_rw); id = ipid++; - MUTEX_EXIT(&ipf_rw); + MUTEX_EXIT(&ipfmain.ipf_rw); #else - u_short id; - id = ip_randomid(); #endif @@ -1329,8 +1080,9 @@ fr_info_t *fin; } -INLINE void fr_checkv4sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkv4sum(fin) + fr_info_t *fin; { #ifdef CSUM_DATA_VALID int manual = 0; @@ -1339,10 +1091,13 @@ fr_info_t *fin; mb_t *m; if ((fin->fin_flx & FI_NOCKSUM) != 0) - return; + return 0; - if (fin->fin_cksum != 0) - return; + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; m = fin->fin_m; if (m == NULL) { @@ -1351,56 +1106,86 @@ fr_info_t *fin; } ip = fin->fin_ip; + if ((m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID)) == + CSUM_IP_CHECKED) { + fin->fin_cksum = FI_CK_BAD; + fin->fin_flx |= FI_BAD; + return -1; + } if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) sum = m->m_pkthdr.csum_data; else sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htonl(m->m_pkthdr.csum_data + - fin->fin_ip->ip_len - - (fin->fin_ip->ip_hl << 2) + - fin->fin_p)); + fin->fin_dlen + fin->fin_p)); sum ^= 0xffff; if (sum != 0) { + fin->fin_cksum = FI_CK_BAD; fin->fin_flx |= FI_BAD; - fin->fin_cksum = -1; } else { - fin->fin_cksum = 1; + fin->fin_cksum = FI_CK_SUMOK; + return 0; } - } else - manual = 1; + } else { + if (m->m_pkthdr.csum_flags == CSUM_DELAY_DATA) { + fin->fin_cksum = FI_CK_L4FULL; + return 0; + } else if (m->m_pkthdr.csum_flags == CSUM_TCP || + m->m_pkthdr.csum_flags == CSUM_UDP) { + fin->fin_cksum = FI_CK_L4PART; + return 0; + } else if (m->m_pkthdr.csum_flags == CSUM_IP) { + fin->fin_cksum = FI_CK_L4PART; + return 0; + } else { + manual = 1; + } + } skipauto: -# ifdef IPFILTER_CKSUM - if (manual != 0) - if (fr_checkl4sum(fin) == -1) + if (manual != 0) { + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; -# else - ; -# endif + return -1; + } + } #else -# ifdef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; -# endif + return -1; + } #endif + return 0; } #ifdef USE_INET6 -INLINE void fr_checkv6sum(fin) -fr_info_t *fin; +INLINE int +ipf_checkv6sum(fin) + fr_info_t *fin; { -# ifdef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) + if ((fin->fin_flx & FI_NOCKSUM) != 0) + return 0; + + if ((fin->fin_flx & FI_SHORT) != 0) + return 1; + + if (fin->fin_cksum != FI_CK_NEEDED) + return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; + + if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; -# endif + return -1; + } + return 0; } #endif /* USE_INET6 */ -size_t mbufchainlen(m0) -struct mbuf *m0; -{ +size_t +mbufchainlen(m0) + struct mbuf *m0; + { size_t len; if ((m0->m_flags & M_PKTHDR) != 0) { @@ -1416,29 +1201,30 @@ struct mbuf *m0; /* ------------------------------------------------------------------------ */ -/* Function: fr_pullup */ +/* Function: ipf_pullup */ /* Returns: NULL == pullup failed, else pointer to protocol header */ -/* Parameters: m(I) - pointer to buffer where data packet starts */ +/* Parameters: xmin(I)- pointer to buffer where data packet starts */ /* fin(I) - pointer to packet information */ /* len(I) - number of bytes to pullup */ /* */ /* Attempt to move at least len bytes (from the start of the buffer) into a */ /* single buffer for ease of access. Operating system native functions are */ /* used to manage buffers - if necessary. If the entire packet ends up in */ -/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */ +/* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ /* and ONLY if the pullup succeeds. */ /* */ -/* We assume that 'min' is a pointer to a buffer that is part of the chain */ +/* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ /* of buffers that starts at *fin->fin_mp. */ /* ------------------------------------------------------------------------ */ -void *fr_pullup(min, fin, len) -mb_t *min; -fr_info_t *fin; -int len; +void * +ipf_pullup(xmin, fin, len) + mb_t *xmin; + fr_info_t *fin; + int len; { - int out = fin->fin_out, dpoff, ipoff; - mb_t *m = min; + int dpoff, ipoff; + mb_t *m = xmin; char *ip; if (m == NULL) @@ -1455,12 +1241,25 @@ int len; dpoff = 0; if (M_LEN(m) < len) { -#ifdef MHLEN + mb_t *n = *fin->fin_mp; /* * Assume that M_PKTHDR is set and just work with what is left * rather than check.. * Should not make any real difference, anyway. */ + if (m != n) { + /* + * Record the mbuf that points to the mbuf that we're + * about to go to work on so that we can update the + * m_next appropriately later. + */ + for (; n->m_next != m; n = n->m_next) + ; + } else { + n = NULL; + } + +#ifdef MHLEN if (len > MHLEN) #else if (len > MLEN) @@ -1472,29 +1271,46 @@ int len; #else FREE_MB_T(*fin->fin_mp); m = NULL; + n = NULL; #endif } else { m = m_pullup(m, len); } - *fin->fin_mp = m; + if (n != NULL) + n->m_next = m; if (m == NULL) { + /* + * When n is non-NULL, it indicates that m pointed to + * a sub-chain (tail) of the mbuf and that the head + * of this chain has not yet been free'd. + */ + if (n != NULL) { + FREE_MB_T(*fin->fin_mp); + } + + *fin->fin_mp = NULL; fin->fin_m = NULL; - ATOMIC_INCL(frstats[out].fr_pull[1]); return NULL; } + if (n == NULL) + *fin->fin_mp = m; + while (M_LEN(m) == 0) { m = m->m_next; } fin->fin_m = m; ip = MTOD(m, char *) + ipoff; - } - ATOMIC_INCL(frstats[out].fr_pull[0]); - fin->fin_ip = (ip_t *)ip; - if (fin->fin_dp != NULL) - fin->fin_dp = (char *)fin->fin_ip + dpoff; + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + if (fin->fin_fraghdr != NULL) + fin->fin_fraghdr = (char *)ip + + ((char *)fin->fin_fraghdr - + (char *)fin->fin_ip); + } if (len == fin->fin_plen) fin->fin_flx |= FI_COALESCE; @@ -1502,45 +1318,19 @@ int len; } -int ipf_inject(fin, m) -fr_info_t *fin; -mb_t *m; +int +ipf_inject(fin, m) + fr_info_t *fin; + mb_t *m; { int error = 0; if (fin->fin_out == 0) { -#if (__FreeBSD_version >= 501000) netisr_dispatch(NETISR_IP, m); -#else - struct ifqueue *ifq; - - ifq = &ipintrq; - -# ifdef _IF_QFULL - if (_IF_QFULL(ifq)) -# else - if (IF_QFULL(ifq)) -# endif - { -# ifdef _IF_DROP - _IF_DROP(ifq); -# else - IF_DROP(ifq); -# endif - FREE_MB_T(m); - error = ENOBUFS; - } else { - IF_ENQUEUE(ifq, m); - } -#endif } else { fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len); fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off); -#if (__FreeBSD_version >= 470102) error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); -#else - error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); -#endif } return error; @@ -1548,38 +1338,22 @@ mb_t *m; int ipf_pfil_unhook(void) { #if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) -# if __FreeBSD_version >= 501108 struct pfil_head *ph_inet; # ifdef USE_INET6 struct pfil_head *ph_inet6; # endif -# endif #endif #ifdef NETBSD_PF -# if (__FreeBSD_version >= 500011) -# if (__FreeBSD_version >= 501108) ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); if (ph_inet != NULL) - pfil_remove_hook((void *)fr_check_wrapper, NULL, + pfil_remove_hook((void *)ipf_check_wrapper, NULL, PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); -# endif # ifdef USE_INET6 -# if (__FreeBSD_version >= 501108) ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); if (ph_inet6 != NULL) - pfil_remove_hook((void *)fr_check_wrapper6, NULL, + pfil_remove_hook((void *)ipf_check_wrapper6, NULL, PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); -# endif # endif #endif @@ -1588,17 +1362,13 @@ int ipf_pfil_unhook(void) { int ipf_pfil_hook(void) { #if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) -# if __FreeBSD_version >= 501108 struct pfil_head *ph_inet; # ifdef USE_INET6 struct pfil_head *ph_inet6; # endif -# endif #endif # ifdef NETBSD_PF -# if __FreeBSD_version >= 500011 -# if __FreeBSD_version >= 501108 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); # ifdef USE_INET6 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); @@ -1607,28 +1377,17 @@ int ipf_pfil_hook(void) { # ifdef USE_INET6 && ph_inet6 == NULL # endif - ) + ) { return ENODEV; + } if (ph_inet != NULL) - pfil_add_hook((void *)fr_check_wrapper, NULL, + pfil_add_hook((void *)ipf_check_wrapper, NULL, PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); -# endif # ifdef USE_INET6 -# if __FreeBSD_version >= 501108 if (ph_inet6 != NULL) - pfil_add_hook((void *)fr_check_wrapper6, NULL, + pfil_add_hook((void *)ipf_check_wrapper6, NULL, PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); -# endif # endif # endif return (0); @@ -1637,22 +1396,19 @@ int ipf_pfil_hook(void) { void ipf_event_reg(void) { -#if (__FreeBSD_version >= 502103) - ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ - ipf_ifevent, NULL, \ + ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ + ipf_ifevent, &ipfmain, \ EVENTHANDLER_PRI_ANY); - ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ - ipf_ifevent, NULL, \ + ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ + ipf_ifevent, &ipfmain, \ EVENTHANDLER_PRI_ANY); - ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ - NULL, EVENTHANDLER_PRI_ANY); -#endif + ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ + &ipfmain, EVENTHANDLER_PRI_ANY); } void ipf_event_dereg(void) { -#if (__FreeBSD_version >= 502103) if (ipf_arrivetag != NULL) { EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag); } @@ -1662,5 +1418,40 @@ ipf_event_dereg(void) if (ipf_clonetag != NULL) { EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); } -#endif +} + + +u_32_t +ipf_random() +{ + return arc4random(); +} + + +u_int +ipf_pcksum(fin, hlen, sum) + fr_info_t *fin; + int hlen; + u_int sum; +{ + struct mbuf *m; + u_int sum2; + int off; + + m = fin->fin_m; + off = (char *)fin->fin_dp - (char *)fin->fin_ip; + m->m_data += hlen; + m->m_len -= hlen; + sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); + m->m_len += hlen; + m->m_data -= hlen; + + /* + * Both sum and sum2 are partial sums, so combine them together. + */ + sum += ~sum2 & 0xffff; + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum2 = ~sum & 0xffff; + return sum2; } |