diff options
Diffstat (limited to 'contrib/ipfilter/ip_fil_freebsd.c')
-rw-r--r-- | contrib/ipfilter/ip_fil_freebsd.c | 1692 |
1 files changed, 0 insertions, 1692 deletions
diff --git a/contrib/ipfilter/ip_fil_freebsd.c b/contrib/ipfilter/ip_fil_freebsd.c deleted file mode 100644 index 3b36b93..0000000 --- a/contrib/ipfilter/ip_fil_freebsd.c +++ /dev/null @@ -1,1692 +0,0 @@ -/* $NetBSD$ */ - -/* - * Copyright (C) 1993-2003 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.25 2005/02/01 03:15:56 darrenr Exp"; -#endif - -#if defined(KERNEL) || defined(_KERNEL) -# undef KERNEL -# undef _KERNEL -# define KERNEL 1 -# define _KERNEL 1 -#endif -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \ - !defined(KLD_MODULE) && !defined(IPFILTER_LKM) -# include "opt_inet6.h" -#endif -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 440000) && \ - !defined(KLD_MODULE) && !defined(IPFILTER_LKM) -# 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 -#if !defined(__hpux) -# include <sys/mbuf.h> -#endif -#include <sys/protosw.h> -#include <sys/socket.h> - -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -# if !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#if defined(__osf__) -# include <netinet/tcp_timer.h> -#endif -#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> -#endif -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_auth.h" -#ifdef IPFILTER_SYNC -#include "netinet/ip_sync.h" -#endif -#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) -extern int path_mtu_discovery; -#endif - -# ifdef IPFILTER_M_IPFILTER -MALLOC_DEFINE(M_IPFILTER, "IP Filter", "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; -ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; -# endif -int ipf_locks_done = 0; - -#if (__FreeBSD_version >= 300000) -struct callout_handle fr_slowtimer_ch; -#endif - -#if (__FreeBSD_version >= 500011) -# include <sys/conf.h> -# if defined(NETBSD_PF) -# include <net/pfil.h> -# include <netinet/ipprotosw.h> -/* - * We provide the fr_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 */ - - -#if (__FreeBSD_version >= 501108) && defined(_KERNEL) - -static int -fr_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); -} - -# ifdef USE_INET6 -# include <netinet/ip6.h> - -static int -fr_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)); -} -# endif -#endif /* __FreeBSD_version >= 501108 */ -#if defined(IPFILTER_LKM) -int iplidentify(s) -char *s; -{ - if (strcmp(s, "ipl") == 0) - return 1; - return 0; -} -#endif /* IPFILTER_LKM */ - - -int iplattach() -{ -#ifdef USE_SPL - int s; -#endif -#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) - int error = 0; -# if __FreeBSD_version >= 501108 - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -# endif -#endif - - SPL_NET(s); - if (fr_running > 0) { - SPL_X(s); - return EBUSY; - } - - MUTEX_INIT(&ipf_rw, "ipf rw mutex"); - RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); - MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex"); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); - RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); - ipf_locks_done = 1; - - if (fr_initialise() < 0) { - SPL_X(s); - return EIO; - } - - -# 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); -# endif - if (ph_inet == NULL -# ifdef USE_INET6 - && ph_inet6 == NULL -# endif - ) - return ENODEV; - - if (ph_inet != NULL) - error = pfil_add_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { -# ifdef USE_INET6 - goto pfil_error; -# else - fr_deinitialise(); - SPL_X(s); - return error; -# endif - } -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if __FreeBSD_version >= 501108 - if (ph_inet6 != NULL) - error = pfil_add_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; - if (error) { - pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); -# else - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); - if (error) { - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif -pfil_error: - fr_deinitialise(); - SPL_X(s); - return error; - } -# endif -# endif - if (fr_checkp != fr_check) { - fr_savep = fr_checkp; - fr_checkp = fr_check; - } - - bzero((char *)frcache, sizeof(frcache)); - fr_running = 1; - - if (fr_control_forwarding & 1) - ipforwarding = 1; - - 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 - return 0; -} - - -/* - * Disable the filter by removing the hooks from the IP input/output - * stream. - */ -int ipldetach() -{ -#ifdef USE_SPL - int s; -#endif -#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) - int error = 0; -# if __FreeBSD_version >= 501108 - struct pfil_head *ph_inet; -# ifdef USE_INET6 - struct pfil_head *ph_inet6; -# endif -# endif -#endif - - if (fr_control_forwarding & 2) - 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 */ - -#ifndef NETBSD_PF - if (fr_checkp != NULL) - fr_checkp = fr_savep; - fr_savep = NULL; -#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) - error = pfil_remove_hook((void *)fr_check_wrapper, NULL, - PFIL_IN|PFIL_OUT, ph_inet); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 -# if (__FreeBSD_version >= 501108) - ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); - if (ph_inet6 != NULL) - error = pfil_remove_hook((void *)fr_check_wrapper6, NULL, - PFIL_IN|PFIL_OUT, ph_inet6); - else - error = 0; -# else - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); -# endif - if (error) { - SPL_X(s); - return error; - } -# endif -#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); - - if (ipf_locks_done == 1) { - MUTEX_DESTROY(&ipf_timeoutlock); - MUTEX_DESTROY(&ipf_rw); - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_ipidfrag); - RW_DESTROY(&ipf_global); - ipf_locks_done = 0; - } - - SPL_X(s); - - return 0; -} - - -/* - * Filter ioctl interface. - */ -int iplioctl(dev, cmd, data, mode -# if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000)) -, p) -# 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 -ioctlcmd_t cmd; -caddr_t data; -int mode; -{ -#ifdef USE_SPL - int s; -#endif - int error = 0, unit = 0, tmp; - friostat_t fio; - -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 2) && (mode & FWRITE)) - return EPERM; -#endif - - unit = GET_MINOR(dev); - if ((IPL_LOGMAX < unit) || (unit < 0)) - return ENXIO; - - if (fr_running <= 0) { - if (unit != IPL_LOGIPF) - return EIO; - if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && - cmd != SIOCIPFSET && cmd != SIOCFRENB && - cmd != SIOCGETFS && cmd != SIOCGETFF) - return EIO; - } - - SPL_NET(s); - - error = fr_ioctlswitch(unit, data, cmd, mode); - if (error != -1) { - SPL_X(s); - return error; - } - error = 0; - - switch (cmd) - { - case FIONREAD : -#ifdef IPFILTER_LOG - BCOPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data, - sizeof(iplused[IPL_LOGIPF])); -#endif - break; - case SIOCFRENB : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - if (tmp) { - if (fr_running > 0) - error = 0; - else - error = iplattach(); - if (error == 0) - fr_running = 1; - else - (void) ipldetach(); - } else { - error = ipldetach(); - if (error == 0) - fr_running = -1; - } - } - break; - case SIOCIPFSET : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - case SIOCIPFGETNEXT : - case SIOCIPFGET : - error = fr_ipftune(cmd, data); - break; - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else - BCOPYIN(data, &fr_flags, sizeof(fr_flags)); - break; - case SIOCGETFF : - BCOPYOUT(&fr_flags, data, sizeof(fr_flags)); - break; - case SIOCFUNCL : - error = fr_resolvefunc(data); - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - case SIOCZRLST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, fr_active, 1); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, 1 - fr_active, 1); - break; - case SIOCSWAPA : - if (!(mode & FWRITE)) - error = EPERM; - else { - bzero((char *)frcache, sizeof(frcache[0]) * 2); - *(u_int *)data = fr_active; - fr_active = 1 - fr_active; - } - break; - case SIOCGETFS : - fr_getstat(&fio); - error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); - break; - case SIOCFRZST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = fr_zerostats(data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - tmp = frflush(unit, 4, tmp); - BCOPYOUT(&tmp, data, sizeof(tmp)); - } - break; -#ifdef USE_INET6 - case SIOCIPFL6 : - if (!(mode & FWRITE)) - error = EPERM; - else { - BCOPYIN(data, &tmp, sizeof(tmp)); - tmp = frflush(unit, 6, tmp); - BCOPYOUT(&tmp, data, sizeof(tmp)); - } - break; -#endif - case SIOCSTLCK : - BCOPYIN(data, &tmp, sizeof(tmp)); - fr_state_lock = tmp; - fr_nat_lock = tmp; - fr_frag_lock = tmp; - fr_auth_lock = tmp; - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else - *(int *)data = ipflog_clear(unit); - break; -#endif /* IPFILTER_LOG */ - case SIOCGFRST : - error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT); - break; - case SIOCFRSYN : - if (!(mode & FWRITE)) - error = EPERM; - else { - frsync(NULL); - } - break; - default : - error = EINVAL; - break; - } - SPL_X(s); - return error; -} - - -#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; -{ - -# ifdef IPFILTER_SYNC - if (GET_MINOR(dev) == IPL_LOGSYNC) - return ipfsync_read(uio); -# endif - -#ifdef IPFILTER_LOG - return ipflog_read(GET_MINOR(dev), 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; -{ - -#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 - * requires a large amount of setting up and isn't any more efficient. - */ -int fr_send_reset(fin) -fr_info_t *fin; -{ - struct tcphdr *tcp, *tcp2; - int tlen = 0, hlen; - struct mbuf *m; -#ifdef USE_INET6 - ip6_t *ip6; -#endif - ip_t *ip; - - tcp = fin->fin_dp; - if (tcp->th_flags & TH_RST) - return -1; /* feedback loop */ - -#ifndef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) - return -1; -#endif - - tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + - ((tcp->th_flags & TH_SYN) ? 1 : 0) + - ((tcp->th_flags & TH_FIN) ? 1 : 0); - -#ifdef USE_INET6 - hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); -#else - hlen = sizeof(ip_t); -#endif -#ifdef MGETHDR - MGETHDR(m, M_DONTWAIT, MT_HEADER); -#else - MGET(m, M_DONTWAIT, MT_HEADER); -#endif - if (m == NULL) - return -1; - if (sizeof(*tcp2) + hlen > MLEN) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - FREE_MB_T(m); - return -1; - } - } - - m->m_len = sizeof(*tcp2) + hlen; -#if (BSD >= 199103) - m->m_data += max_linkhdr; - m->m_pkthdr.len = m->m_len; - m->m_pkthdr.rcvif = (struct ifnet *)0; -#endif - ip = mtod(m, struct ip *); - bzero((char *)ip, hlen); -#ifdef USE_INET6 - ip6 = (ip6_t *)ip; -#endif - tcp2 = (struct tcphdr *)((char *)ip + hlen); - tcp2->th_sport = tcp->th_dport; - tcp2->th_dport = tcp->th_sport; - - if (tcp->th_flags & TH_ACK) { - tcp2->th_seq = tcp->th_ack; - tcp2->th_flags = TH_RST; - tcp2->th_ack = 0; - } else { - tcp2->th_seq = 0; - tcp2->th_ack = ntohl(tcp->th_seq); - tcp2->th_ack += tlen; - tcp2->th_ack = htonl(tcp2->th_ack); - tcp2->th_flags = TH_RST|TH_ACK; - } - TCP_X2_A(tcp2, 0); - TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); - tcp2->th_win = tcp->th_win; - tcp2->th_sum = 0; - tcp2->th_urp = 0; - -#ifdef USE_INET6 - if (fin->fin_v == 6) { - ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; - 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; - tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, - sizeof(*ip6), sizeof(*tcp2)); - return fr_send_ip(fin, m, &m); - } -#endif - ip->ip_p = IPPROTO_TCP; - ip->ip_len = htons(sizeof(struct tcphdr)); - 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); -} - - -static int fr_send_ip(fin, m, mpp) -fr_info_t *fin; -mb_t *m, **mpp; -{ - fr_info_t fnew; - ip_t *ip, *oip; - int hlen; - - ip = mtod(m, ip_t *); - bzero((char *)&fnew, sizeof(fnew)); - - IP_V_A(ip, fin->fin_v); - switch (fin->fin_v) - { - case 4 : - fnew.fin_v = 4; - oip = fin->fin_ip; - 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 = path_mtu_discovery ? IP_DF : 0; -#else - ip->ip_off = 0; -#endif - ip->ip_ttl = ip_defttl; - ip->ip_sum = 0; - hlen = sizeof(*oip); - break; -#ifdef USE_INET6 - case 6 : - { - ip6_t *ip6 = (ip6_t *)ip; - - ip6->ip6_vfc = 0x60; - ip6->ip6_hlim = IPDEFTTL; - - fnew.fin_v = 6; - hlen = sizeof(*ip6); - break; - } -#endif - default : - return EINVAL; - } -#ifdef IPSEC - m->m_pkthdr.rcvif = NULL; -#endif - - fnew.fin_ifp = fin->fin_ifp; - fnew.fin_flx = FI_NOCKSUM; - fnew.fin_m = m; - fnew.fin_ip = ip; - fnew.fin_mp = mpp; - fnew.fin_hlen = hlen; - fnew.fin_dp = (char *)ip + hlen; - (void) fr_makefrip(hlen, ip, &fnew); - - return fr_fastroute(m, mpp, &fnew, NULL); -} - - -int fr_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; - void *ifp; -#ifdef USE_INET6 - ip6_t *ip6; - struct in6_addr dst6; -#endif - ip_t *ip, *ip2; - - if ((type < 0) || (type > ICMP_MAXTYPE)) - return -1; - - code = fin->fin_icode; -#ifdef USE_INET6 - if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) - return -1; -#endif - -#ifndef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) - return -1; -#endif -#ifdef MGETHDR - MGETHDR(m, M_DONTWAIT, MT_HEADER); -#else - MGET(m, M_DONTWAIT, MT_HEADER); -#endif - if (m == NULL) - return -1; - avail = MHLEN; - - xtra = 0; - hlen = 0; - ohlen = 0; - ifp = fin->fin_ifp; - if (fin->fin_v == 4) { - if ((fin->fin_p == IPPROTO_ICMP) && - !(fin->fin_flx & FI_SHORT)) - switch (ntohs(fin->fin_data[0]) >> 8) - { - case ICMP_ECHO : - case ICMP_TSTAMP : - case ICMP_IREQ : - case ICMP_MASKREQ : - break; - default : - FREE_MB_T(m); - return 0; - } - - if (dst == 0) { - if (fr_ifpaddr(4, FRI_NORMAL, ifp, - &dst4, NULL) == -1) { - FREE_MB_T(m); - return -1; - } - } else - dst4.s_addr = fin->fin_daddr; - - hlen = sizeof(ip_t); - ohlen = fin->fin_hlen; - if (fin->fin_hlen < fin->fin_plen) - xtra = MIN(fin->fin_dlen, 8); - else - xtra = 0; - } - -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - hlen = sizeof(ip6_t); - ohlen = sizeof(ip6_t); - type = icmptoicmp6types[type]; - if (type == ICMP6_DST_UNREACH) - code = icmptoicmp6unreach[code]; - - if (hlen + sizeof(*icmp) + max_linkhdr + - fin->fin_plen > avail) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - FREE_MB_T(m); - return -1; - } - avail = MCLBYTES; - } - xtra = MIN(fin->fin_plen, - avail - hlen - sizeof(*icmp) - max_linkhdr); - if (dst == 0) { - if (fr_ifpaddr(6, FRI_NORMAL, ifp, - (struct in_addr *)&dst6, NULL) == -1) { - FREE_MB_T(m); - return -1; - } - } else - dst6 = fin->fin_dst6; - } -#endif - else { - FREE_MB_T(m); - return -1; - } - - iclen = hlen + sizeof(*icmp); - avail -= (max_linkhdr + iclen); - if (avail < 0) { - FREE_MB_T(m); - return -1; - } - if (xtra > avail) - xtra = avail; - iclen += xtra; - m->m_data += max_linkhdr; - m->m_pkthdr.rcvif = (struct ifnet *)0; - m->m_pkthdr.len = iclen; - m->m_len = iclen; - ip = mtod(m, ip_t *); - icmp = (struct icmp *)((char *)ip + hlen); - ip2 = (ip_t *)&icmp->icmp_ip; - - icmp->icmp_type = type; - 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); -#endif - - bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); - -#ifdef USE_INET6 - ip6 = (ip6_t *)ip; - if (fin->fin_v == 6) { - ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; - 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; - if (xtra > 0) - bcopy((char *)fin->fin_ip + ohlen, - (char *)&icmp->icmp_ip + ohlen, xtra); - icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, - sizeof(*ip6), iclen - hlen); - } 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; - - if (xtra > 0) - bcopy((char *)fin->fin_ip + ohlen, - (char *)&icmp->icmp_ip + ohlen, xtra); - icmp->icmp_cksum = ipf_cksum((u_short *)icmp, - sizeof(*icmp) + 8); - ip->ip_len = iclen; - ip->ip_p = IPPROTO_ICMP; - } - err = fr_send_ip(fin, m, &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 (iplattach() != 0) - printf("IP Filter failed to attach\n"); - ip_init(); -} -#endif /* __FreeBSD_version < 300000 */ - - -int fr_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 = m0; - register struct route *ro; - int len, off, error = 0, hlen, code; - struct ifnet *ifp, *sifp; - struct sockaddr_in *dst; - struct route iproute; - u_short ip_off; - frentry_t *fr; - -#ifdef M_WRITABLE - /* - * HOT FIX/KLUDGE: - * - * If the mbuf we're about to send is not writable (because of - * a cluster reference, for example) we'll need to make a copy - * of it since this routine modifies the contents. - * - * If you have non-crappy network hardware that can transmit data - * from the mbuf, rather than making a copy, this is gonna be a - * problem. - */ - if (M_WRITABLE(m) == 0) { - if ((m0 = m_dup(m, M_DONTWAIT)) != 0) { - FREE_MB_T(m); - m = m0; - *mpp = m; - } else { - error = ENOBUFS; - FREE_MB_T(m); - *mpp = NULL; - fr_frouteok[1]++; - } - } -#endif - -#ifdef USE_INET6 - if (fin->fin_v == 6) { - /* - * 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 - } -#endif - - hlen = fin->fin_hlen; - ip = mtod(m0, struct ip *); - - /* - * Route packet. - */ - ro = &iproute; - bzero((caddr_t)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 (fdp != NULL) - ifp = fdp->fd_ifp; - else - ifp = fin->fin_ifp; - - if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) { - error = -2; - goto bad; - } - - /* - * In case we're here due to "to <if>" being used with "keep state", - * check that we're going in the correct direction. - */ - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) - return -1; - } - if (fdp != NULL) { - if (fdp->fd_ip.s_addr != 0) - dst->sin_addr = fdp->fd_ip; - } - - dst->sin_len = sizeof(*dst); - rtalloc(ro); - - if ((ifp == NULL) && (ro->ro_rt != NULL)) - ifp = ro->ro_rt->rt_ifp; - - if ((ro->ro_rt == NULL) || (ifp == NULL)) { - if (in_localaddr(ip->ip_dst)) - error = EHOSTUNREACH; - else - error = ENETUNREACH; - goto bad; - } - if (ro->ro_rt->rt_flags & RTF_GATEWAY) - dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; - if (ro->ro_rt) - ro->ro_rt->rt_use++; - - /* - * For input packets which are being "fastrouted", they won't - * go back through output filtering and miss their chance to get - * NAT'd and counted. - */ - if (fin->fin_out == 0) { - sifp = fin->fin_ifp; - fin->fin_ifp = ifp; - fin->fin_out = 1; - (void) fr_acctpkt(fin, NULL); - fin->fin_fr = NULL; - if (!fr || !(fr->fr_flags & FR_RETMASK)) { - u_32_t pass; - - (void) fr_checkstate(fin, &pass); - } - - switch (fr_checknatout(fin, NULL)) - { - case 0 : - break; - case 1 : - ip->ip_sum = 0; - break; - case -1 : - error = -1; - goto done; - break; - } - - fin->fin_ifp = sifp; - fin->fin_out = 0; - } else - ip->ip_sum = 0; - /* - * 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 (!ip->ip_sum) - ip->ip_sum = in_cksum(m, hlen); - error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, - ro->ro_rt); - goto done; - } - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - ip_off = ntohs(ip->ip_off); - if (ip_off & IP_DF) { - error = EMSGSIZE; - goto bad; - } - len = (ifp->if_mtu - hlen) &~ 7; - if (len < 8) { - error = EMSGSIZE; - goto bad; - } - - { - int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_act; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { -#ifdef MGETHDR - MGETHDR(m, M_DONTWAIT, MT_HEADER); -#else - MGET(m, M_DONTWAIT, MT_HEADER); -#endif - if (m == 0) { - m = m0; - error = ENOBUFS; - goto bad; - } - m->m_data += max_linkhdr; - mhip = mtod(m, struct ip *); - bcopy((char *)ip, (char *)mhip, sizeof(*ip)); - if (hlen > sizeof (struct ip)) { - mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); - IP_HL_A(mhip, mhlen >> 2); - } - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + ip_off; - if (off + len >= ip->ip_len) - len = ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((u_short)(len + mhlen)); - m->m_next = m_copy(m0, off, len); - if (m->m_next == 0) { - error = ENOBUFS; /* ??? */ - goto sendorfree; - } - m->m_pkthdr.len = mhlen + len; - m->m_pkthdr.rcvif = NULL; - mhip->ip_off = htons((u_short)mhip->ip_off); - mhip->ip_sum = 0; - mhip->ip_sum = in_cksum(m, mhlen); - *mnext = m; - mnext = &m->m_act; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m_adj(m0, hlen + firstlen - ip->ip_len); - ip->ip_len = htons((u_short)(hlen + firstlen)); - ip->ip_off = htons((u_short)IP_MF); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m0, hlen); -sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_act; - m->m_act = 0; - if (error == 0) - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro->ro_rt); - else - FREE_MB_T(m); - } - } -done: - if (!error) - fr_frouteok[0]++; - else - fr_frouteok[1]++; - - if (ro->ro_rt) { - RTFREE(ro->ro_rt); - } - *mpp = NULL; - return 0; -bad: - if (error == EMSGSIZE) { - sifp = fin->fin_ifp; - code = fin->fin_icode; - fin->fin_icode = ICMP_UNREACH_NEEDFRAG; - fin->fin_ifp = ifp; - (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1); - fin->fin_ifp = sifp; - fin->fin_icode = code; - } - FREE_MB_T(m); - goto done; -} - - -int fr_verifysrc(fin) -fr_info_t *fin; -{ - struct sockaddr_in *dst; - struct route iproute; - - bzero((char *)&iproute, sizeof(iproute)); - dst = (struct sockaddr_in *)&iproute.ro_dst; - dst->sin_len = sizeof(*dst); - dst->sin_family = AF_INET; - dst->sin_addr = fin->fin_src; - rtalloc(&iproute); - if (iproute.ro_rt == NULL) - return 0; - return (fin->fin_ifp == iproute.ro_rt->rt_ifp); -} - - -/* - * 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; -{ -#ifdef USE_INET6 - struct in6_addr *inp6 = NULL; -#endif - struct sockaddr *sock, *mask; - struct sockaddr_in *sin; - struct ifaddr *ifa; - struct ifnet *ifp; - - if ((ifptr == NULL) || (ifptr == (void *)-1)) - return -1; - - sin = NULL; - ifp = ifptr; - - if (v == 4) - inp->s_addr = 0; -#ifdef USE_INET6 - else if (v == 6) - bzero((char *)inp, sizeof(struct in6_addr)); -#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) { - sin = (struct sockaddr_in *)sock; - if ((v == 4) && (sin->sin_family == AF_INET)) - break; -#ifdef USE_INET6 - if ((v == 6) && (sin->sin_family == AF_INET6)) { - inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; - if (!IN6_IS_ADDR_LINKLOCAL(inp6) && - !IN6_IS_ADDR_LOOPBACK(inp6)) - 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; - } - - if (ifa == NULL || sin == NULL) - return -1; - - mask = ifa->ifa_netmask; - if (atype == FRI_BROADCAST) - sock = ifa->ifa_broadaddr; - else if (atype == FRI_PEERADDR) - sock = ifa->ifa_dstaddr; - -#ifdef USE_INET6 - if (v == 6) { - return fr_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); -} - - -u_32_t fr_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 */ -/* 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; -{ -#ifndef RANDOM_IP_ID - static u_short ipid = 0; - u_short id; - - MUTEX_ENTER(&ipf_rw); - id = ipid++; - MUTEX_EXIT(&ipf_rw); -#else - u_short id; - - id = ip_randomid(); -#endif - - return id; -} - - -INLINE void fr_checkv4sum(fin) -fr_info_t *fin; -{ -#ifdef CSUM_DATA_VALID - int manual = 0; - u_short sum; - ip_t *ip; - mb_t *m; - - if ((fin->fin_flx & FI_NOCKSUM) != 0) - return; - - m = fin->fin_m; - if (m == NULL) { - manual = 1; - goto skipauto; - } - ip = fin->fin_ip; - - 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_p)); - sum ^= 0xffff; - if (sum != 0) - fin->fin_flx |= FI_BAD; - } else - manual = 1; -skipauto: -# ifdef IPFILTER_CKSUM - if (manual != 0) - if (fr_checkl4sum(fin) == -1) - fin->fin_flx |= FI_BAD; -# else - ; -# endif -#else -# ifdef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) - fin->fin_flx |= FI_BAD; -# endif -#endif -} - - -#ifdef USE_INET6 -INLINE void fr_checkv6sum(fin) -fr_info_t *fin; -{ -# ifdef IPFILTER_CKSUM - if (fr_checkl4sum(fin) == -1) - fin->fin_flx |= FI_BAD; -# endif -} -#endif /* USE_INET6 */ - - -size_t mbufchainlen(m0) -struct mbuf *m0; -{ - size_t len; - - if ((m0->m_flags & M_PKTHDR) != 0) { - len = m0->m_pkthdr.len; - } else { - struct mbuf *m; - - for (m = m0, len = 0; m != NULL; m = m->m_next) - len += m->m_len; - } - return len; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: fr_pullup */ -/* Returns: NULL == pullup failed, else pointer to protocol header */ -/* Parameters: m(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 */ -/* 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 */ -/* of buffers that starts at *fin->fin_mp. */ -/* ------------------------------------------------------------------------ */ -void *fr_pullup(min, fin, len) -mb_t *min; -fr_info_t *fin; -int len; -{ - int out = fin->fin_out, dpoff, ipoff; - mb_t *m = min; - char *ip; - - if (m == NULL) - return NULL; - - ip = (char *)fin->fin_ip; - if ((fin->fin_flx & FI_COALESCE) != 0) - return ip; - - ipoff = fin->fin_ipoff; - if (fin->fin_dp != NULL) - dpoff = (char *)fin->fin_dp - (char *)ip; - else - dpoff = 0; - - if (M_LEN(m) < len) { -#ifdef MHLEN - /* - * Assume that M_PKTHDR is set and just work with what is left - * rather than check.. - * Should not make any real difference, anyway. - */ - if (len > MHLEN) -#else - if (len > MLEN) -#endif - { -#ifdef HAVE_M_PULLDOWN - if (m_pulldown(m, 0, len, NULL) == NULL) - m = NULL; -#else - FREE_MB_T(*fin->fin_mp); - m = NULL; -#endif - } else - { - m = m_pullup(m, len); - } - *fin->fin_mp = m; - fin->fin_m = m; - if (m == NULL) { - ATOMIC_INCL(frstats[out].fr_pull[1]); - return NULL; - } - 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; - - if (len == fin->fin_plen) - fin->fin_flx |= FI_COALESCE; - return ip; -} |