aboutsummaryrefslogtreecommitdiffstats
path: root/sys/netinet/fil.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1997-11-16 05:55:52 +0000
committerPeter Wemm <peter@FreeBSD.org>1997-11-16 05:55:52 +0000
commit52aef1787c0595837b11765452444e18c4687baa (patch)
treec8cdc77281d6ea71cae48ee9fcc2e4ae8430414f /sys/netinet/fil.c
parente10102a12a980dc84a95a4a831769c1058c946c0 (diff)
downloadsrc-52aef1787c0595837b11765452444e18c4687baa.tar.gz
src-52aef1787c0595837b11765452444e18c4687baa.zip
Import kernel parts of ipfilter-3.2.1
Notes
Notes: svn path=/vendor-sys/ipfilter/dist-old/; revision=31187
Diffstat (limited to 'sys/netinet/fil.c')
-rw-r--r--sys/netinet/fil.c670
1 files changed, 531 insertions, 139 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c
index b40695f829e3..4c0f8c1b74d6 100644
--- a/sys/netinet/fil.c
+++ b/sys/netinet/fil.c
@@ -1,13 +1,13 @@
/*
- * (C)opyright 1993-1996 by Darren Reed.
+ * Copyright (C) 1993-1997 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
-#if !defined(lint) && defined(LIBC_SCCS)
-static char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
-static char rcsid[] = "$Id: fil.c,v 2.0.2.13 1997/05/24 07:33:37 darrenr Exp $";
+#if !defined(lint)
+static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
+static const char rcsid[] = "@(#)$Id: fil.c,v 2.0.2.41.2.3 1997/11/12 10:44:22 darrenr Exp $";
#endif
#include <sys/errno.h>
@@ -16,7 +16,7 @@ static char rcsid[] = "$Id: fil.c,v 2.0.2.13 1997/05/24 07:33:37 darrenr Exp $";
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
-#if defined(_KERNEL) || defined(KERNEL)
+#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
# include <sys/systm.h>
#else
# include <stdio.h>
@@ -24,14 +24,18 @@ static char rcsid[] = "$Id: fil.c,v 2.0.2.13 1997/05/24 07:33:37 darrenr Exp $";
#endif
#include <sys/uio.h>
#if !defined(__SVR4) && !defined(__svr4__)
-# include <sys/mbuf.h>
+# ifndef linux
+# include <sys/mbuf.h>
+# endif
#else
# include <sys/byteorder.h>
# include <sys/dditypes.h>
# include <sys/stream.h>
#endif
-#include <sys/protosw.h>
-#include <sys/socket.h>
+#ifndef linux
+# include <sys/protosw.h>
+# include <sys/socket.h>
+#endif
#include <net/if.h>
#ifdef sun
# include <net/af.h>
@@ -40,17 +44,20 @@ static char rcsid[] = "$Id: fil.c,v 2.0.2.13 1997/05/24 07:33:37 darrenr Exp $";
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#include <netinet/ip_var.h>
+#ifndef linux
+# include <netinet/ip_var.h>
+#endif
#include <netinet/tcp.h>
#include <netinet/udp.h>
-#include <netinet/tcpip.h>
#include <netinet/ip_icmp.h>
#include "netinet/ip_compat.h"
+#include <netinet/tcpip.h>
#include "netinet/ip_fil.h"
#include "netinet/ip_proxy.h"
#include "netinet/ip_nat.h"
#include "netinet/ip_frag.h"
#include "netinet/ip_state.h"
+#include "netinet/ip_auth.h"
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
@@ -66,52 +73,68 @@ extern int opts;
second; }
# define FR_VERBOSE(verb_pr) verbose verb_pr
# define FR_DEBUG(verb_pr) debug verb_pr
-# define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m)
-# define SEND_RESET(ip, qif, q, if) send_reset(ip, if)
+# define SEND_RESET(ip, qif, if) send_reset(ip, if)
# define IPLLOG(a, c, d, e) ipllog()
+# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
# if SOLARIS
# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(ip)
# else
# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(b, ip, if)
# endif
-
#else /* #ifndef _KERNEL */
# define FR_IFVERBOSE(ex,second,verb_pr) ;
# define FR_IFDEBUG(ex,second,verb_pr) ;
# define FR_VERBOSE(verb_pr)
# define FR_DEBUG(verb_pr)
-# define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m)
-# define IPLLOG(a, c, d, e) ipllog(a, IPL_LOGIPF, c, d, e)
+# define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
+# if SOLARIS || defined(__sgi)
+extern kmutex_t ipf_mutex, ipf_auth;
+# endif
# if SOLARIS
-extern kmutex_t ipf_mutex;
-# define SEND_RESET(ip, qif, q, if) send_reset(ip, qif, q)
+# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
+ ip, qif)
+# define SEND_RESET(ip, qif, if) send_reset(ip, qif)
# define ICMP_ERROR(b, ip, t, c, if, src) \
- icmp_error(b, ip, t, c, if, src)
-# else
-# define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m)
-# define SEND_RESET(ip, qif, q, if) send_reset((struct tcpiphdr *)ip)
-# if BSD < 199103
+ icmp_error(ip, t, c, if, src)
+# else /* SOLARIS */
+# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
+# define SEND_RESET(ip, qif, if) send_reset((struct tcpiphdr *)ip)
+# ifdef __sgi
# define ICMP_ERROR(b, ip, t, c, if, src) \
- icmp_error(mtod(b, ip_t *), t, c, if, src)
+ icmp_error(b, t, c, if, src, if)
# else
-# define ICMP_ERROR(b, ip, t, c, if, src) \
+# if BSD < 199103
+# ifdef linux
+# define ICMP_ERROR(b, ip, t, c, if, src) icmp_send(b,t,c,0,if)
+# else
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(mtod(b, ip_t *), t, c, if, src)
+# endif /* linux */
+# else
+# define ICMP_ERROR(b, ip, t, c, if, src) \
icmp_error(b, t, c, (src).s_addr, if)
-# endif
-# endif
-#endif
+# endif /* BSD < 199103 */
+# endif /* __sgi */
+# endif /* SOLARIS || __sgi */
+#endif /* _KERNEL */
struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
*ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
+struct frgroup *ipfgroups[3][2];
int fr_flags = IPF_LOGGING, fr_active = 0;
+#if defined(IPFILTER_DEFAULT_BLOCK)
+int fr_pass = FR_NOMATCH|FR_BLOCK;
+#else
int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
+#endif
fr_info_t frcache[2];
static void fr_makefrip __P((int, ip_t *, fr_info_t *));
static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
-static int fr_scanlist __P((int, ip_t *, fr_info_t *, void *));
+static int frflushlist __P((int, int, int *, frentry_t *, frentry_t **));
/*
@@ -176,6 +199,8 @@ fr_info_t *fin;
fin->fin_data[0] = 0;
fin->fin_data[1] = 0;
fin->fin_rule = -1;
+ fin->fin_group = -1;
+ fin->fin_id = ip->ip_id;
#ifdef _KERNEL
fin->fin_icode = ipl_unreach;
#endif
@@ -186,10 +211,10 @@ fr_info_t *fin;
tcp = (tcphdr_t *)((char *)ip + hlen);
fin->fin_dp = (void *)tcp;
(*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
- (*(((u_long *)fi) + 1)) = (*(((u_long *)ip) + 3));
- (*(((u_long *)fi) + 2)) = (*(((u_long *)ip) + 4));
+ (*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3));
+ (*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4));
- fi->fi_fl = (hlen > sizeof(struct ip)) ? FI_OPTIONS : 0;
+ fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
off = (ip->ip_off & 0x1fff) << 3;
if (ip->ip_off & 0x3fff)
fi->fi_fl |= FI_FRAG;
@@ -371,7 +396,7 @@ fr_info_t *fin;
* Could be per interface, but this gets real nasty when you don't have
* kernel sauce.
*/
-static int fr_scanlist(pass, ip, fin, m)
+int fr_scanlist(pass, ip, fin, m)
int pass;
ip_t *ip;
register fr_info_t *fin;
@@ -379,18 +404,23 @@ void *m;
{
register struct frentry *fr;
register fr_ip_t *fi = &fin->fin_fi;
- int rulen, portcmp = 0, off;
+ int rulen, portcmp = 0, off, skip = 0;
fr = fin->fin_fr;
fin->fin_fr = NULL;
fin->fin_rule = 0;
+ fin->fin_group = 0;
off = ip->ip_off & 0x1fff;
- pass |= (fi->fi_fl << 20);
+ pass |= (fi->fi_fl << 24);
if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
portcmp = 1;
for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
+ if (skip) {
+ skip--;
+ continue;
+ }
/*
* In all checks below, a null (zero) value in the
* filter struture is taken to mean a wildcard.
@@ -403,18 +433,19 @@ void *m;
#else
if (opts & (OPT_VERBOSE|OPT_DEBUG))
printf("\n");
- FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 'b'));
+ FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' :
+ (pass & FR_AUTH) ? 'a' : 'b'));
if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
continue;
FR_VERBOSE((":i"));
#endif
{
- register u_long *ld, *lm, *lip;
- register int i, j;
+ register u_32_t *ld, *lm, *lip;
+ register int i;
- lip = (u_long *)fi;
- lm = (u_long *)&fr->fr_mip;
- ld = (u_long *)&fr->fr_ip;
+ lip = (u_32_t *)fi;
+ lm = (u_32_t *)&fr->fr_mip;
+ ld = (u_32_t *)&fr->fr_ip;
i = ((lip[0] & lm[0]) != ld[0]);
FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
lip[0], lm[0], ld[0]));
@@ -462,7 +493,8 @@ void *m;
/*
* Just log this packet...
*/
- pass = fr->fr_flags;
+ if (!(skip = fr->fr_skip))
+ pass = fr->fr_flags;
if ((pass & FR_CALLNOW) && fr->fr_func)
pass = (*fr->fr_func)(pass, ip, fin);
#ifdef IPFILTER_LOG
@@ -479,7 +511,17 @@ void *m;
else
fin->fin_icode = fr->fr_icode;
fin->fin_rule = rulen;
+ fin->fin_group = fr->fr_group;
fin->fin_fr = fr;
+ if (fr->fr_grp) {
+ fin->fin_fr = fr->fr_grp;
+ pass = fr_scanlist(pass, ip, fin, m);
+ if (fin->fin_fr == NULL) {
+ fin->fin_rule = rulen;
+ fin->fin_group = fr->fr_group;
+ fin->fin_fr = fr;
+ }
+ }
if (pass & FR_QUICK)
break;
}
@@ -493,23 +535,16 @@ void *m;
* or not to pass it on or not.
*/
int fr_check(ip, hlen, ifp, out
-#ifdef _KERNEL
-# if SOLARIS
-, qif, q, mp)
+#if defined(_KERNEL) && SOLARIS
+, qif, mp)
qif_t *qif;
-queue_t *q;
-mblk_t **mp;
-# else
-, mp)
-struct mbuf **mp;
-# endif
#else
, mp)
-char *mp;
#endif
+mb_t **mp;
ip_t *ip;
int hlen;
-struct ifnet *ifp;
+void *ifp;
int out;
{
/*
@@ -518,34 +553,66 @@ int out;
fr_info_t frinfo, *fc;
register fr_info_t *fin = &frinfo;
frentry_t *fr = NULL;
- int pass, changed;
-#ifndef _KERNEL
- char *mc = mp, *m = mp;
+ int pass, changed, apass;
+#if !SOLARIS || !defined(_KERNEL)
+ register mb_t *m = *mp;
#endif
#ifdef _KERNEL
+ mb_t *mc = NULL;
# if !defined(__SVR4) && !defined(__svr4__)
- register struct mbuf *m = *mp;
- struct mbuf *mc = NULL;
+# ifdef __sgi
+ char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
+# endif
+ int up;
if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
ip->ip_p == IPPROTO_ICMP)) {
- register int up = MIN(hlen + 8, ip->ip_len);
+ int plen = 0;
+
+ switch(ip->ip_p)
+ {
+ case IPPROTO_TCP:
+ plen = sizeof(tcphdr_t);
+ break;
+ case IPPROTO_UDP:
+ plen = sizeof(udphdr_t);
+ break;
+ case IPPROTO_ICMP:
+ /* 96 - enough for complete ICMP error IP header */
+ plen = sizeof(struct icmp) + sizeof(ip_t) + 8;
+ break;
+ }
+ up = MIN(hlen + plen, ip->ip_len);
if (up > m->m_len) {
+#ifdef __sgi /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
+ if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
+ frstats[out].fr_pull[1]++;
+ return -1;
+ }
+ m_copydata(m, 0, up, hbuf);
+ frstats[out].fr_pull[0]++;
+ ip = (ip_t *)hbuf;
+#else
+# ifndef linux
if ((*mp = m_pullup(m, up)) == 0) {
frstats[out].fr_pull[1]++;
return -1;
} else {
frstats[out].fr_pull[0]++;
m = *mp;
- ip = mtod(m, struct ip *);
+ ip = mtod(m, ip_t *);
}
- }
- }
+# endif
+#endif
+ } else
+ up = 0;
+ } else
+ up = 0;
# endif
# if SOLARIS
- mblk_t *mc = NULL, *m = qif->qf_m;
+ mb_t *m = qif->qf_m;
# endif
#endif
fr_makefrip(hlen, ip, fin);
@@ -554,33 +621,78 @@ int out;
fin->fin_mp = mp;
MUTEX_ENTER(&ipf_mutex);
+
+ /*
+ * Check auth now. This, combined with the check below to see if apass
+ * is 0 is to ensure that we don't count the packet twice, which can
+ * otherwise occur when we reprocess it. As it is, we only count it
+ * after it has no auth. table matchup. This also stops NAT from
+ * occuring until after the packet has been auth'd.
+ */
+ apass = fr_checkauth(ip, fin);
+
if (!out) {
changed = ip_natin(ip, hlen, fin);
- if ((fin->fin_fr = ipacct[0][fr_active]) &&
+ if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
(FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
frstats[0].fr_acct++;
}
- if (!(pass = ipfr_knownfrag(ip, fin)) &&
- !(pass = fr_checkstate(ip, fin))) {
- fc = frcache + out;
- if (fc->fin_fr && !bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
- /*
- * copy cached data so we can unlock the mutex
- * earlier.
- */
- bcopy((char *)fc, (char *)fin, sizeof(*fin));
- frstats[out].fr_chit++;
- pass = fin->fin_fr->fr_flags;
- } else {
- pass = fr_pass;
- if ((fin->fin_fr = ipfilter[out][fr_active]))
- pass = FR_SCANLIST(fr_pass, ip, fin, m);
- bcopy((char *)fin, (char *)fc, FI_CSIZE);
- if (pass & FR_NOMATCH)
- frstats[out].fr_nom++;
+ if (apass || (!(pass = ipfr_knownfrag(ip, fin)) &&
+ !(pass = fr_checkstate(ip, fin)))) {
+ /*
+ * If a packet is found in the auth table, then skip checking
+ * the access lists for permission but we do need to consider
+ * the result as if it were from the ACL's.
+ */
+ if (!apass) {
+ fc = frcache + out;
+ if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
+ /*
+ * copy cached data so we can unlock the mutex
+ * earlier.
+ */
+ bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
+ frstats[out].fr_chit++;
+ if ((fr = fin->fin_fr)) {
+ fr->fr_hits++;
+ pass = fr->fr_flags;
+ } else
+ pass = fr_pass;
+ } else {
+ pass = fr_pass;
+ if ((fin->fin_fr = ipfilter[out][fr_active]))
+ pass = FR_SCANLIST(fr_pass, ip, fin, m);
+ bcopy((char *)fin, (char *)fc, FI_COPYSIZE);
+ if (pass & FR_NOMATCH)
+ frstats[out].fr_nom++;
+ }
+ fr = fin->fin_fr;
+ } else
+ pass = apass;
+
+ /*
+ * If we fail to add a packet to the authorization queue,
+ * then we drop the packet later. However, if it was added
+ * then pretend we've dropped it already.
+ */
+ if ((pass & FR_AUTH))
+ if (FR_NEWAUTH(m, fin, ip, qif) != 0)
+#ifdef _KERNEL
+ m = *mp = NULL;
+#else
+ ;
+#endif
+
+ if (pass & FR_PREAUTH) {
+ MUTEX_ENTER(&ipf_auth);
+ if ((fin->fin_fr = ipauth) &&
+ (pass = FR_SCANLIST(0, ip, fin, m)))
+ fr_authstats.fas_hits++;
+ else
+ fr_authstats.fas_miss++;
+ MUTEX_EXIT(&ipf_auth);
}
- fr = fin->fin_fr;
if (pass & FR_KEEPFRAG) {
if (fin->fin_fi.fi_fl & FI_FRAG) {
@@ -602,7 +714,11 @@ int out;
if (fr && fr->fr_func && !(pass & FR_CALLNOW))
pass = (*fr->fr_func)(pass, ip, fin);
- if (out) {
+ /*
+ * Only count/translate packets which will be passed on, out the
+ * interface.
+ */
+ if (out && (pass & FR_PASS)) {
if ((fin->fin_fr = ipacct[1][fr_active]) &&
(FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
frstats[1].fr_acct++;
@@ -649,7 +765,9 @@ logit:
# if SOLARIS
mc = dupmsg(m);
# else
+# ifndef linux
mc = m_copy(m, 0, M_COPYALL);
+# endif
# endif
#endif
@@ -680,7 +798,7 @@ logit:
frstats[0].fr_ret++;
} else if ((pass & FR_RETRST) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
- if (SEND_RESET(ip, qif, q, ifp) == 0)
+ if (SEND_RESET(ip, qif, ifp) == 0)
frstats[1].fr_ret++;
}
#else
@@ -703,8 +821,9 @@ logit:
* Once we're finished return to our caller, freeing the packet if
* we are dropping it (* BSD ONLY *).
*/
-#ifdef _KERNEL
-# if !SOLARIS
+#if defined(_KERNEL)
+# if !SOLARIS
+# if !defined(linux)
if (fr) {
frdest_t *fdp = &fr->fr_tif;
@@ -718,8 +837,13 @@ logit:
}
if (!(pass & FR_PASS) && m)
m_freem(m);
+# ifdef __sgi
+ else if (changed && up && m)
+ m_copyback(m, 0, up, hbuf);
+# endif
+# endif /* !linux */
return (pass & FR_PASS) ? 0 : -1;
-# else
+# else /* !SOLARIS */
if (fr) {
frdest_t *fdp = &fr->fr_tif;
@@ -732,49 +856,23 @@ logit:
ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
}
return (pass & FR_PASS) ? changed : -1;
-# endif
-#else
+# endif /* !SOLARIS */
+#else /* _KERNEL */
if (pass & FR_NOMATCH)
return 1;
if (pass & FR_PASS)
return 0;
+ if (pass & FR_AUTH)
+ return -2;
return -1;
-#endif
+#endif /* _KERNEL */
}
-#ifdef IPFILTER_LOG
-int fr_copytolog(dev, buf, len)
-int dev;
-char *buf;
-int len;
-{
- register char *bufp = iplbuf[dev], *tp = iplt[dev], *hp = iplh[dev];
- register int clen, tail;
-
- tail = (hp >= tp) ? (bufp + IPLLOGSIZE - hp) : (tp - hp);
- clen = MIN(tail, len);
- bcopy(buf, hp, clen);
- len -= clen;
- tail -= clen;
- hp += clen;
- buf += clen;
- if (hp == bufp + IPLLOGSIZE) {
- hp = bufp;
- tail = tp - hp;
- }
- if (len && tail) {
- clen = MIN(tail, len);
- bcopy(buf, hp, clen);
- len -= clen;
- hp += clen;
- }
- iplh[dev] = hp;
- return len;
-}
-#endif
-
-
+/*
+ * ipf_cksum
+ * addr should be 16bit aligned and len is in bytes.
+ */
u_short ipf_cksum(addr, len)
register u_short *addr;
register int len;
@@ -803,11 +901,7 @@ register int len;
* odd sizes.
*/
u_short fr_tcpsum(m, ip, tcp)
-#if SOLARIS
-mblk_t *m;
-#else
-struct mbuf *m;
-#endif
+mb_t *m;
ip_t *ip;
tcphdr_t *tcp;
{
@@ -817,12 +911,22 @@ tcphdr_t *tcp;
} bytes;
u_long sum;
u_short *sp;
- int len, add, hlen, ilen;
+ int len;
+# if SOLARIS || defined(__sgi)
+ int add, hlen;
+# endif
+
+# if SOLARIS
+ /* skip any leading M_PROTOs */
+ while(m && (MTYPE(m) != M_DATA))
+ m = m->b_cont;
+ PANIC((!m),("fr_tcpsum: no M_DATA"));
+# endif
/*
* Add up IP Header portion
*/
- ilen = len = ip->ip_len - (ip->ip_hl << 2);
+ len = ip->ip_len - (ip->ip_hl << 2);
bytes.c[0] = 0;
bytes.c[1] = IPPROTO_TCP;
sum = bytes.s;
@@ -855,35 +959,58 @@ tcphdr_t *tcp;
while (hlen) {
add = MIN(hlen, m->b_wptr - m->b_rptr);
sp = (u_short *)((caddr_t)m->b_rptr + add);
- if ((hlen -= add))
+ hlen -= add;
+ if ((caddr_t)sp >= (caddr_t)m->b_wptr) {
m = m->b_cont;
+ PANIC((!m),("fr_tcpsum: not enough data"));
+ if (!hlen)
+ sp = (u_short *)m->b_rptr;
+ }
+ }
+ }
+#endif
+#ifdef __sgi
+ /*
+ * In case we had to copy the IP & TCP header out of mbufs,
+ * skip over the mbuf bits which are the header
+ */
+ if ((caddr_t)ip != mtod(m, caddr_t)) {
+ hlen = (caddr_t)sp - (caddr_t)ip;
+ while (hlen) {
+ add = MIN(hlen, m->m_len);
+ sp = (u_short *)(mtod(m, caddr_t) + add);
+ hlen -= add;
+ if (add >= m->m_len) {
+ m = m->m_next;
+ PANIC((!m),("fr_tcpsum: not enough data"));
+ if (!hlen)
+ sp = mtod(m, u_short *);
+ }
}
}
#endif
if (!(len -= sizeof(*tcp)))
goto nodata;
- while (len > 1) {
- sum += *sp++;
- len -= 2;
+ while (len > 0) {
#if SOLARIS
- if ((caddr_t)sp > (caddr_t)m->b_wptr) {
+ if ((caddr_t)sp >= (caddr_t)m->b_wptr) {
m = m->b_cont;
PANIC((!m),("fr_tcpsum: not enough data"));
sp = (u_short *)m->b_rptr;
}
#else
-# ifdef m_data
- if ((caddr_t)sp > (m->m_data + m->m_len))
-# else
- if ((caddr_t)sp > (caddr_t)(m->m_dat + m->m_off + m->m_len))
-# endif
+ if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len)
{
m = m->m_next;
PANIC((!m),("fr_tcpsum: not enough data"));
sp = mtod(m, u_short *);
}
#endif /* SOLARIS */
+ if (len < 2)
+ break;
+ sum += *sp++;
+ len -= 2;
}
if (len) {
bytes.c[1] = 0;
@@ -896,3 +1023,268 @@ nodata:
sum = (u_short)((~sum) & 0xffff);
return sum;
}
+
+
+#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
+/*
+ * Copyright (c) 1982, 1986, 1988, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
+ * $Id: fil.c,v 2.0.2.41.2.3 1997/11/12 10:44:22 darrenr Exp $
+ */
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ */
+void
+m_copydata(m, off, len, cp)
+ register mb_t *m;
+ register int off;
+ register int len;
+ caddr_t cp;
+{
+ register unsigned count;
+
+ if (off < 0 || len < 0)
+ panic("m_copydata");
+ while (off > 0) {
+ if (m == 0)
+ panic("m_copydata");
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ while (len > 0) {
+ if (m == 0)
+ panic("m_copydata");
+ count = MIN(m->m_len - off, len);
+ bcopy(mtod(m, caddr_t) + off, cp, count);
+ len -= count;
+ cp += count;
+ off = 0;
+ m = m->m_next;
+ }
+}
+
+
+# ifndef linux
+/*
+ * Copy data from a buffer back into the indicated mbuf chain,
+ * starting "off" bytes from the beginning, extending the mbuf
+ * chain if necessary.
+ */
+void
+m_copyback(m0, off, len, cp)
+ struct mbuf *m0;
+ register int off;
+ register int len;
+ caddr_t cp;
+{
+ register int mlen;
+ register struct mbuf *m = m0, *n;
+ int totlen = 0;
+
+ if (m0 == 0)
+ return;
+ while (off > (mlen = m->m_len)) {
+ off -= mlen;
+ totlen += mlen;
+ if (m->m_next == 0) {
+ n = m_getclr(M_DONTWAIT, m->m_type);
+ if (n == 0)
+ goto out;
+ n->m_len = min(MLEN, len + off);
+ m->m_next = n;
+ }
+ m = m->m_next;
+ }
+ while (len > 0) {
+ mlen = min (m->m_len - off, len);
+ bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
+ cp += mlen;
+ len -= mlen;
+ mlen += off;
+ off = 0;
+ totlen += mlen;
+ if (len == 0)
+ break;
+ if (m->m_next == 0) {
+ n = m_get(M_DONTWAIT, m->m_type);
+ if (n == 0)
+ break;
+ n->m_len = min(MLEN, len);
+ m->m_next = n;
+ }
+ m = m->m_next;
+ }
+out:
+#if 0
+ if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
+ m->m_pkthdr.len = totlen;
+#endif
+ return;
+}
+# endif /* linux */
+#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
+
+
+frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
+u_short num;
+u_32_t flags;
+int which, set;
+frgroup_t ***fgpp;
+{
+ frgroup_t *fg, **fgp;
+
+ if (which == IPL_LOGAUTH)
+ fgp = &ipfgroups[2][set];
+ else if (flags & FR_ACCOUNT)
+ fgp = &ipfgroups[1][set];
+ else if (flags & (FR_OUTQUE|FR_INQUE))
+ fgp = &ipfgroups[0][set];
+ else
+ return NULL;
+
+ while ((fg = *fgp))
+ if (fg->fg_num == num)
+ break;
+ else
+ fgp = &fg->fg_next;
+ if (fgpp)
+ *fgpp = fgp;
+ return fg;
+}
+
+
+frgroup_t *fr_addgroup(num, fp, which, set)
+u_short num;
+frentry_t *fp;
+int which, set;
+{
+ frgroup_t *fg, **fgp;
+
+ if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
+ return fg;
+
+ KMALLOC(fg, frgroup_t *, sizeof(*fg));
+ if (fg) {
+ fg->fg_num = num;
+ fg->fg_next = *fgp;
+ fg->fg_head = fp;
+ fg->fg_start = &fp->fr_grp;
+ *fgp = fg;
+ }
+ return fg;
+}
+
+
+void fr_delgroup(num, flags, which, set)
+u_short num;
+u_32_t flags;
+int which, set;
+{
+ frgroup_t *fg, **fgp;
+
+ if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
+ return;
+
+ *fgp = fg->fg_next;
+ KFREE(fg);
+}
+
+
+
+/*
+ * recursively flush rules from the list, descending groups as they are
+ * encountered. if a rule is the head of a group and it has lost all its
+ * group members, then also delete the group reference.
+ */
+static int frflushlist(set, unit, nfreedp, list, listp)
+int set, unit, *nfreedp;
+frentry_t *list, **listp;
+{
+ register frentry_t *fp = list, *fpn;
+ register int freed = 0;
+
+ while (fp) {
+ fpn = fp->fr_next;
+ if (fp->fr_grp) {
+ fp->fr_ref -= frflushlist(set, unit, nfreedp,
+ fp->fr_grp, &fp->fr_grp);
+ }
+
+ if (fp->fr_ref == 1) {
+ if (fp->fr_grhead)
+ fr_delgroup(fp->fr_grhead, fp->fr_flags, unit,
+ set);
+ KFREE(fp);
+ *listp = fpn;
+ freed++;
+ }
+ fp = fpn;
+ }
+ *nfreedp += freed;
+ return freed;
+}
+
+
+void frflush(unit, data)
+int unit;
+caddr_t data;
+{
+ int flags = *(int *)data, flushed = 0, set = fr_active;
+
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+
+ if (flags & FR_INACTIVE)
+ set = 1 - set;
+
+ if (unit == IPL_LOGIPF) {
+ if (flags & FR_OUTQUE) {
+ (void) frflushlist(set, unit, &flushed,
+ ipfilter[1][set],
+ &ipfilter[1][set]);
+ (void) frflushlist(set, unit, &flushed,
+ ipacct[1][set], &ipacct[1][set]);
+ }
+ if (flags & FR_INQUE) {
+ (void) frflushlist(set, unit, &flushed,
+ ipfilter[0][set],
+ &ipfilter[0][set]);
+ (void) frflushlist(set, unit, &flushed,
+ ipacct[0][set], &ipacct[0][set]);
+ }
+ }
+
+ *(int *)data = flushed;
+}