diff options
Diffstat (limited to 'sys/netinet/fil.c')
-rw-r--r-- | sys/netinet/fil.c | 548 |
1 files changed, 393 insertions, 155 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c index 84bfd975173..f4acf66b495 100644 --- a/sys/netinet/fil.c +++ b/sys/netinet/fil.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fil.c,v 1.16 1999/12/08 06:50:18 itojun Exp $ */ +/* $OpenBSD: fil.c,v 1.17 1999/12/15 05:20:20 kjell Exp $ */ /* * Copyright (C) 1993-1998 by Darren Reed. * @@ -8,7 +8,7 @@ */ #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 1.16 1999/12/08 06:50:18 itojun Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 1.17 1999/12/15 05:20:20 kjell Exp $"; #endif #include <sys/errno.h> @@ -16,7 +16,17 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Ex #include <sys/param.h> #include <sys/time.h> #include <sys/file.h> -#include <sys/ioctl.h> +#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ + defined(_KERNEL) +# include "opt_ipfilter_log.h" +#endif +#if defined(KERNEL) && defined(__FreeBSD_version) && \ + (__FreeBSD_version >= 220000) +# include <sys/filio.h> +# include <sys/fcntl.h> +#else +# include <sys/ioctl.h> +#endif #if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) # include <sys/systm.h> #else @@ -32,9 +42,9 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Ex #else # include <sys/byteorder.h> # if SOLARIS2 < 5 -# include <sys/dditypes.h> +# include <sys/dditypes.h> # endif -# include <sys/stream.h> +# include <sys/stream.h> #endif #ifndef linux # include <sys/protosw.h> @@ -46,9 +56,9 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Ex #endif #include <net/route.h> #ifdef _KERNEL -#ifndef INET -#error ipfilter assumes options INET -#endif +# ifndef INET +# error ipfilter assumes options INET +# endif #endif #include <netinet/in.h> #include <netinet/in_systm.h> @@ -56,14 +66,14 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Ex #ifndef linux # include <netinet/ip_var.h> #endif +#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ +# include <sys/hashing.h> +# include <netinet/in_var.h> +#endif #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> -#if defined(__OpenBSD__) -# include <netinet/ip_fil_compat.h> -#else -# include <netinet/ip_compat.h> -#endif +#include <netinet/ip_fil_compat.h> #include <netinet/tcpip.h> #include <netinet/ip_fil.h> #include <netinet/ip_proxy.h> @@ -71,9 +81,16 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Ex #include <netinet/ip_frag.h> #include <netinet/ip_state.h> #include <netinet/ip_auth.h> +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include <sys/malloc.h> +# if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include "opt_ipfilter.h" +# endif +# endif #ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) +# define MIN(a,b) (((a)<(b))?(a):(b)) #endif +#include <netinet/ipl.h> #ifndef _KERNEL # include "ipf.h" @@ -86,14 +103,9 @@ extern int opts; second; } # define FR_VERBOSE(verb_pr) verbose verb_pr # define FR_DEBUG(verb_pr) debug verb_pr -# define SEND_RESET(ip, qif, if, m) send_reset(ip, if) +# define SEND_RESET(ip, qif, if, m, fin) 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) ; @@ -101,39 +113,25 @@ extern int opts; # define FR_DEBUG(verb_pr) # define IPLLOG(a, c, d, e) ipflog(a, c, d, e) # if SOLARIS || defined(__sgi) -extern KRWLOCK_T ipf_mutex, ipf_auth; +extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat; extern kmutex_t ipf_rw; # endif # if SOLARIS # 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(ip, t, c, if, src) +# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif) +# define ICMP_ERROR(b, ip, t, c, if, dst) \ + icmp_error(ip, t, c, if, dst) # else /* SOLARIS */ # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) # ifdef linux -# define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip,\ - ifp) +# define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp) +# define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if) # else -# define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip) -# endif -# ifdef __sgi -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(b, t, c, if, src, if) -# else -# 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 /* BSD < 199103 */ -# endif /* __sgi */ +# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip) +# define ICMP_ERROR(b, ip, t, c, if, dst) \ + send_icmp_err(ip, t, c, if, dst) +# endif /* linux */ # endif /* SOLARIS || __sgi */ #endif /* _KERNEL */ @@ -148,12 +146,15 @@ int fr_pass = FR_NOMATCH|FR_BLOCK; #else int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); #endif +char ipfilter_version[] = IPL_VERSION; 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 frflushlist __P((int, int, int *, frentry_t *, frentry_t **)); +static int frflushlist __P((int, minor_t, int *, frentry_t **)); +#ifdef _KERNEL +static void frsynclist __P((frentry_t *)); +#endif /* @@ -201,7 +202,7 @@ struct optlist secopt[8] = { * compact the IP header into a structure which contains just the info. * which is useful for comparing IP headers with. */ -static void fr_makefrip(hlen, ip, fin) +void fr_makefrip(hlen, ip, fin) int hlen; ip_t *ip; fr_info_t *fin; @@ -213,6 +214,7 @@ fr_info_t *fin; int i, mv, ol, off; u_char *s, opt; + fin->fin_rev = 0; fin->fin_fr = NULL; fin->fin_tcpf = 0; fin->fin_data[0] = 0; @@ -230,8 +232,8 @@ fr_info_t *fin; tcp = (tcphdr_t *)((char *)ip + hlen); fin->fin_dp = (void *)tcp; (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); - (*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3)); - (*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4)); + fi->fi_src.s_addr = ip->ip_src.s_addr; + fi->fi_dst.s_addr = ip->ip_dst.s_addr; fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; off = (ip->ip_off & IP_OFFMASK) << 3; @@ -280,8 +282,9 @@ getports: } - for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) { - if (!(opt = *s)) + for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen; ) { + opt = *s; + if (opt == '\0') break; ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1); if (opt > 1 && (ol < 2 || ol > hlen)) @@ -426,14 +429,15 @@ fr_info_t *fin; * kernel sauce. */ int fr_scanlist(pass, ip, fin, m) -int pass; +u_32_t pass; ip_t *ip; register fr_info_t *fin; void *m; { register struct frentry *fr; register fr_ip_t *fi = &fin->fin_fi; - int rulen, portcmp = 0, off, skip = 0; + int rulen, portcmp = 0, off, skip = 0, logged = 0; + u_32_t passt; fr = fin->fin_fr; fin->fin_fr = NULL; @@ -457,8 +461,16 @@ void *m; * check that we are working for the right interface */ #ifdef _KERNEL - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; +# if BSD >= 199306 + if (fin->fin_out != 0) { + if ((fr->fr_oifa && + fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) || + (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)) + continue; + } else +# endif + if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) + continue; #else if (opts & (OPT_VERBOSE|OPT_DEBUG)) printf("\n"); @@ -478,10 +490,12 @@ void *m; i = ((lip[0] & lm[0]) != ld[0]); FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n", lip[0], lm[0], ld[0])); - i |= ((lip[1] & lm[1]) != ld[1]) << 21; + i |= ((lip[1] & lm[1]) != ld[1]) << 19; + i ^= (fr->fr_flags & FR_NOTSRCIP); FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n", lip[1], lm[1], ld[1])); - i |= ((lip[2] & lm[2]) != ld[2]) << 22; + i |= ((lip[2] & lm[2]) != ld[2]) << 20; + i ^= (fr->fr_flags & FR_NOTDSTIP); FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n", lip[2], lm[2], ld[2])); i |= ((lip[3] & lm[3]) != ld[3]); @@ -490,7 +504,6 @@ void *m; i |= ((lip[4] & lm[4]) != ld[4]); FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n", lip[4], lm[4], ld[4])); - i ^= (fi->fi_fl & (FR_NOTSRCIP|FR_NOTDSTIP)); if (i) continue; } @@ -520,18 +533,21 @@ void *m; /* * Just log this packet... */ - if (!(skip = fr->fr_skip)) - pass = fr->fr_flags; - if ((pass & FR_CALLNOW) && fr->fr_func) - pass = (*fr->fr_func)(pass, ip, fin); + passt = fr->fr_flags; + if ((passt & FR_CALLNOW) && fr->fr_func) + passt = (*fr->fr_func)(passt, ip, fin); + fin->fin_fr = fr; #ifdef IPFILTER_LOG - if ((pass & FR_LOGMASK) == FR_LOG) { - if (!IPLLOG(fr->fr_flags, ip, fin, m)) { + if ((passt & FR_LOGMASK) == FR_LOG) { + if (!IPLLOG(passt, ip, fin, m)) { ATOMIC_INC(frstats[fin->fin_out].fr_skip); } ATOMIC_INC(frstats[fin->fin_out].fr_pkl); + logged = 1; } #endif /* IPFILTER_LOG */ + if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) + pass = passt; FR_DEBUG(("pass %#x\n", pass)); ATOMIC_INC(fr->fr_hits); if (pass & FR_ACCOUNT) @@ -540,7 +556,6 @@ void *m; 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); @@ -549,10 +564,14 @@ void *m; fin->fin_group = fr->fr_group; fin->fin_fr = fr; } + if (pass & FR_DONTCACHE) + logged = 1; } if (pass & FR_QUICK) break; } + if (logged) + pass |= FR_DONTCACHE; return pass; } @@ -581,7 +600,8 @@ int out; fr_info_t frinfo, *fc; register fr_info_t *fin = &frinfo; frentry_t *fr = NULL; - int pass, changed, apass, error = EHOSTUNREACH; + int changed, error = EHOSTUNREACH; + u_32_t pass, apass; #if !SOLARIS || !defined(_KERNEL) register mb_t *m = *mp; #endif @@ -616,8 +636,8 @@ int out; case IPPROTO_UDP: plen = sizeof(udphdr_t); break; - case IPPROTO_ICMP: /* need enough for complete ICMP error IP header */ + case IPPROTO_ICMP: plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); break; } @@ -653,13 +673,24 @@ int out; # if SOLARIS mb_t *m = qif->qf_m; + if ((u_int)ip & 0x3) + return 2; fin->fin_qfm = m; + fin->fin_qif = qif; # endif #endif /* _KERNEL */ + + /* + * Be careful here: ip_id is in network byte order when called + * from ip_output() + */ + if (out) + ip->ip_id = ntohs(ip->ip_id); fr_makefrip(hlen, ip, fin); fin->fin_ifp = ifp; fin->fin_out = out; fin->fin_mp = mp; + pass = fr_pass; READ_ENTER(&ipf_mutex); @@ -673,15 +704,15 @@ int out; apass = fr_checkauth(ip, fin); if (!out) { - changed = ip_natin(ip, hlen, fin); + changed = ip_natin(ip, fin); if (!apass && (fin->fin_fr = ipacct[0][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { + (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { ATOMIC_INC(frstats[0].fr_acct); } } - if (apass || (!(pass = ipfr_knownfrag(ip, fin)) && - !(pass = fr_checkstate(ip, fin)))) { + if (apass || (!(fr = ipfr_knownfrag(ip, fin)) && + !(fr = 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 @@ -699,13 +730,13 @@ int out; if ((fr = fin->fin_fr)) { ATOMIC_INC(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); + pass = fr_scanlist(fr_pass, ip, fin, m); + if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE))) + bcopy((char *)fin, (char *)fc, + FI_COPYSIZE); if (pass & FR_NOMATCH) { ATOMIC_INC(frstats[out].fr_nom); } @@ -730,7 +761,7 @@ int out; if (pass & FR_PREAUTH) { READ_ENTER(&ipf_auth); if ((fin->fin_fr = ipauth) && - (pass = FR_SCANLIST(0, ip, fin, m))) { + (pass = fr_scanlist(0, ip, fin, m))) { ATOMIC_INC(fr_authstats.fas_hits); } else { ATOMIC_INC(fr_authstats.fas_miss); @@ -738,7 +769,8 @@ int out; RWLOCK_EXIT(&ipf_auth); } - if (pass & FR_KEEPFRAG) { + fin->fin_fr = fr; + if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { if (fin->fin_fi.fi_fl & FI_FRAG) { if (ipfr_newfrag(ip, fin, pass) == -1) { ATOMIC_INC(frstats[out].fr_bnfr); @@ -750,12 +782,16 @@ int out; } } if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, fin, pass) == -1) { + if (fr_addstate(ip, fin, 0) == NULL) { ATOMIC_INC(frstats[out].fr_bads); } else { ATOMIC_INC(frstats[out].fr_ads); } } + } else if (fr != NULL) { + pass = fr->fr_flags; + if (pass & FR_LOGFIRST) + pass &= ~(FR_LOGFIRST|FR_LOG); } if (fr && fr->fr_func && !(pass & FR_CALLNOW)) @@ -767,13 +803,13 @@ int out; */ if (out && (pass & FR_PASS)) { if ((fin->fin_fr = ipacct[1][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { + (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { ATOMIC_INC(frstats[1].fr_acct); } - fin->fin_fr = NULL; - changed = ip_natout(ip, hlen, fin); - } - fin->fin_fr = fr; + fin->fin_fr = fr; + changed = ip_natout(ip, fin); + } else + fin->fin_fr = fr; RWLOCK_EXIT(&ipf_mutex); #ifdef IPFILTER_LOG @@ -803,6 +839,10 @@ logit: } } #endif /* IPFILTER_LOG */ + + if (out) + ip->ip_id = htons(ip->ip_id); + #ifdef _KERNEL /* * Only allow FR_DUP to work if a rule matched - it makes no sense to @@ -835,27 +875,34 @@ logit: if (!out) { #ifdef _KERNEL if (pass & FR_RETICMP) { + struct in_addr dst; + + if ((pass & FR_RETMASK) == FR_FAKEICMP) + dst = ip->ip_dst; + else + dst.s_addr = 0; # if SOLARIS ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode, - qif, ip->ip_src); + qif, dst); # else ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode, - ifp, ip->ip_src); - m = *mp = NULL; /* freed by icmp_error() */ + ifp, dst); # endif - ATOMIC_INC(frstats[0].fr_ret); - } else if ((pass & FR_RETRST) && + } else if (((pass & FR_RETMASK) == FR_RETRST) && !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (SEND_RESET(ip, qif, ifp) == 0) { + if (SEND_RESET(ip, qif, ifp, fin) == 0) { ATOMIC_INC(frstats[1].fr_ret); } } #else - if (pass & FR_RETICMP) { + if ((pass & FR_RETMASK) == FR_RETICMP) { verbose("- ICMP unreachable sent\n"); ATOMIC_INC(frstats[0].fr_ret); - } else if ((pass & FR_RETRST) && + } else if ((pass & FR_RETMASK) == FR_FAKEICMP) { + verbose("- forged ICMP unreachable sent\n"); + ATOMIC_INC(frstats[0].fr_ret); + } else if (((pass & FR_RETMASK) == FR_RETRST) && !(fin->fin_fi.fi_fl & FI_SHORT)) { verbose("- TCP RST sent\n"); ATOMIC_INC(frstats[1].fr_ret); @@ -880,10 +927,10 @@ logit: if (fr) { frdest_t *fdp = &fr->fr_tif; - if ((pass & FR_FASTROUTE) || + if (((pass & FR_FASTROUTE) && !out) || (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - ipfr_fastroute(m, fin, fdp); - m = *mp = NULL; + if (ipfr_fastroute(m, fin, fdp) == 0) + m = *mp = NULL; } if (mc) ipfr_fastroute(mc, fin, &fr->fr_dif); @@ -895,21 +942,20 @@ logit: m_copyback(m, 0, up, hbuf); # endif # endif /* !linux */ - return (pass & FR_PASS) ? 0 : error; # else /* !SOLARIS */ if (fr) { frdest_t *fdp = &fr->fr_tif; - if ((pass & FR_FASTROUTE) || + if (((pass & FR_FASTROUTE) && !out) || (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - ipfr_fastroute(qif, ip, m, mp, fin, fdp); - m = *mp = NULL; + if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0) + m = *mp = NULL; } if (mc) ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif); } - return (pass & FR_PASS) ? changed : error; # endif /* !SOLARIS */ + return (pass & FR_PASS) ? 0 : error; #else /* _KERNEL */ if (pass & FR_NOMATCH) return 1; @@ -954,23 +1000,21 @@ register int len; * and the TCP header. We also assume that data blocks aren't allocated in * odd sizes. */ -u_short fr_tcpsum(m, ip, tcp, len) +u_short fr_tcpsum(m, ip, tcp) mb_t *m; ip_t *ip; tcphdr_t *tcp; -int len; { u_short *sp, slen, ts; u_int sum, sum2; int hlen; - /* * Add up IP Header portion */ hlen = ip->ip_hl << 2; slen = ip->ip_len - hlen; - sum = htons(ip->ip_p); + sum = htons((u_short)ip->ip_p); sum += htons(slen); sp = (u_short *)&ip->ip_src; sum += *sp++; /* ip_src */ @@ -981,7 +1025,7 @@ int len; tcp->th_sum = 0; #ifdef KERNEL # if SOLARIS - sum2 = ip_cksum(m, hlen, sum); + sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ sum2 = (sum2 & 0xffff) + (sum2 >> 16); sum2 = ~sum2 & 0xffff; # else /* SOLARIS */ @@ -1008,13 +1052,11 @@ int len; sum2 = (sum2 & 0xffff) + (sum2 >> 16); # else /* defined(BSD) || defined(sun) */ { - union { u_char c[2]; u_short s; } bytes; - u_32_t sum; - u_short *sp, slen; + u_short len = ip->ip_len; # if defined(__sgi) int add; # endif @@ -1025,7 +1067,7 @@ int len; sp = (u_short *)&ip->ip_src; len -= (ip->ip_hl << 2); sum = ntohs(IPPROTO_TCP); - sum += htons((u_short)len); + sum += htons(len); sum += *sp++; /* ip_src */ sum += *sp++; sum += *sp++; /* ip_dst */ @@ -1039,8 +1081,8 @@ int len; sum += *sp++; /* ack */ sum += *sp++; sum += *sp++; /* off */ - sum += *sp; /* win */ - sp += 2; /* Skip over checksum */ + sum += *sp++; /* win */ + sum += *sp++; /* Skip over checksum */ sum += *sp++; /* urp */ # ifdef __sgi @@ -1098,7 +1140,7 @@ nodata: sum = (sum & 0xffff) + (sum >> 16); sum2 = (u_short)(~sum & 0xffff); } -# endif /* defined(BSD) || defined(sun) */ +# endif /* defined(BSD) || defined(sun) */ # endif /* SOLARIS */ #else /* KERNEL */ sum2 = 0; @@ -1142,7 +1184,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Exp $ + * $Id: fil.c,v 1.17 1999/12/15 05:20:20 kjell Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -1242,9 +1284,10 @@ out: frgroup_t *fr_findgroup(num, flags, which, set, fgpp) -u_short num; +u_int num; u_32_t flags; -int which, set; +minor_t which; +int set; frgroup_t ***fgpp; { frgroup_t *fg, **fgp; @@ -1257,6 +1300,7 @@ frgroup_t ***fgpp; fgp = &ipfgroups[0][set]; else return NULL; + num &= 0xffff; while ((fg = *fgp)) if (fg->fg_num == num) @@ -1270,18 +1314,19 @@ frgroup_t ***fgpp; frgroup_t *fr_addgroup(num, fp, which, set) -u_short num; +u_int num; frentry_t *fp; -int which, set; +minor_t which; +int set; { frgroup_t *fg, **fgp; if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) return fg; - KMALLOC(fg, frgroup_t *, sizeof(*fg)); + KMALLOC(fg, frgroup_t *); if (fg) { - fg->fg_num = num; + fg->fg_num = num & 0xffff; fg->fg_next = *fgp; fg->fg_head = fp; fg->fg_start = &fp->fr_grp; @@ -1292,9 +1337,10 @@ int which, set; void fr_delgroup(num, flags, which, set) -u_short num; +u_int num; u_32_t flags; -int which, set; +minor_t which; +int set; { frgroup_t *fg, **fgp; @@ -1312,63 +1358,255 @@ int which, set; * 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; +static int frflushlist(set, unit, nfreedp, listp) +int set; +minor_t unit; +int *nfreedp; +frentry_t **listp; { - register frentry_t *fp = list, *fpn; - register int freed = 0; + register int freed = 0, i; + register frentry_t *fp; - while (fp) { - fpn = fp->fr_next; + while ((fp = *listp)) { + *listp = fp->fr_next; if (fp->fr_grp) { - fp->fr_ref -= frflushlist(set, unit, nfreedp, - fp->fr_grp, &fp->fr_grp); + i = frflushlist(set, unit, nfreedp, &fp->fr_grp); + MUTEX_ENTER(&ipf_rw); + fp->fr_ref -= i; + MUTEX_EXIT(&ipf_rw); } - if (fp->fr_ref == 1) { - if (fp->fr_grhead) - fr_delgroup(fp->fr_grhead, fp->fr_flags, unit, - set); + ATOMIC_DEC(fp->fr_ref); + if (fp->fr_grhead) { + fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags, + unit, set); + fp->fr_grhead = NULL; + } + if (fp->fr_ref == 0) { KFREE(fp); - *listp = fpn; freed++; - } - fp = fpn; + } else + fp->fr_next = NULL; } *nfreedp += freed; return freed; } -void frflush(unit, result) -int unit; -int *result; +int frflush(unit, flags) +minor_t unit; +int flags; { - int flags = *result, flushed = 0, set = fr_active; + int flushed = 0, set; + if (unit != IPL_LOGIPF) + return 0; WRITE_ENTER(&ipf_mutex); bzero((char *)frcache, sizeof(frcache[0]) * 2); + set = fr_active; 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_OUTQUE) { + (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]); + (void) frflushlist(set, unit, &flushed, &ipacct[1][set]); + } + if (flags & FR_INQUE) { + (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]); + (void) frflushlist(set, unit, &flushed, &ipacct[0][set]); + } + RWLOCK_EXIT(&ipf_mutex); + return flushed; +} + + +char *memstr(src, dst, slen, dlen) +char *src, *dst; +int slen, dlen; +{ + char *s = NULL; + + while (dlen >= slen) { + if (bcmp(src, dst, slen) == 0) { + s = dst; + break; } - 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]); + dst++; + dlen--; + } + return s; +} + + +void fixskip(listp, rp, addremove) +frentry_t **listp, *rp; +int addremove; +{ + frentry_t *fp; + int rules = 0, rn = 0; + + for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) + ; + + if (!fp) + return; + + for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) + if (fp->fr_skip && (rn + fp->fr_skip >= rules)) + fp->fr_skip += addremove; +} + + +#ifdef _KERNEL +/* + * count consecutive 1's in bit mask. If the mask generated by counting + * consecutive 1's is different to that passed, return -1, else return # + * of bits. + */ +int countbits(ip) +u_32_t ip; +{ + u_32_t ipn; + int cnt = 0, i, j; + + ip = ipn = ntohl(ip); + for (i = 32; i; i--, ipn *= 2) + if (ipn & 0x80000000) + cnt++; + else + break; + ipn = 0; + for (i = 32, j = cnt; i; i--, j--) { + ipn *= 2; + if (j > 0) + ipn++; + } + if (ipn == ip) + return cnt; + return -1; +} + + +/* + * return the first IP Address associated with an interface + */ +int fr_ifpaddr(ifptr, inp) +void *ifptr; +struct in_addr *inp; +{ +# if SOLARIS + ill_t *ill = ifptr; +# else + struct ifnet *ifp = ifptr; +# endif + struct in_addr in; + +# if SOLARIS + in.s_addr = ill->ill_ipif->ipif_local_addr; +# else /* SOLARIS */ +# if linux + ; +# else /* linux */ + struct ifaddr *ifa; + struct sockaddr_in *sin; + +# if (__FreeBSD_version >= 300000) + ifa = TAILQ_FIRST(&ifp->if_addrhead); +# else +# if defined(__NetBSD__) || defined(__OpenBSD__) + ifa = ifp->if_addrlist.tqh_first; +# else +# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ + ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; +# else + ifa = ifp->if_addrlist; +# endif +# endif /* __NetBSD__ || __OpenBSD__ */ +# endif /* __FreeBSD_version >= 300000 */ +# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) + sin = (struct sockaddr_in *)&ifa->ifa_addr; +# else + sin = (struct sockaddr_in *)ifa->ifa_addr; + while (sin && ifa && + sin->sin_family != AF_INET) { +# if (__FreeBSD_version >= 300000) + ifa = TAILQ_NEXT(ifa, ifa_link); +# else +# if defined(__NetBSD__) || defined(__OpenBSD__) + ifa = ifa->ifa_list.tqe_next; +# else + ifa = ifa->ifa_next; +# endif +# endif /* __FreeBSD_version >= 300000 */ + if (ifa) + sin = (struct sockaddr_in *)ifa->ifa_addr; + } + if (ifa == NULL) + sin = NULL; + if (sin == NULL) + return -1; +# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ + in = sin->sin_addr; +# endif /* linux */ +# endif /* SOLARIS */ + in.s_addr = ntohl(in.s_addr); + *inp = in; + return 0; +} + + +static void frsynclist(fr) +register frentry_t *fr; +{ + for (; fr; fr = fr->fr_next) { + if (fr->fr_ifa != NULL) { + fr->fr_ifa = GETUNIT(fr->fr_ifname); + if (fr->fr_ifa == NULL) + fr->fr_ifa = (void *)-1; } + if (fr->fr_grp) + frsynclist(fr->fr_grp); } +} + + +void frsync() +{ + register struct ifnet *ifp; + +# if !SOLARIS +# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) +# if (NetBSD >= 199905) || defined(__OpenBSD__) + for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) +# else + for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) +# endif +# else + for (ifp = ifnet; ifp; ifp = ifp->if_next) +# endif + ip_natsync(ifp); +# endif + + WRITE_ENTER(&ipf_mutex); + frsynclist(ipacct[0][fr_active]); + frsynclist(ipacct[1][fr_active]); + frsynclist(ipfilter[0][fr_active]); + frsynclist(ipfilter[1][fr_active]); RWLOCK_EXIT(&ipf_mutex); - *result = flushed; } + +#else + + +/* + * return the first IP Address associated with an interface + */ +int fr_ifpaddr(ifptr, inp) +void *ifptr; +struct in_addr *inp; +{ + return 0; +} +#endif |