diff options
Diffstat (limited to 'sys/contrib/ipfilter/netinet/fil.c')
-rw-r--r-- | sys/contrib/ipfilter/netinet/fil.c | 201 |
1 files changed, 116 insertions, 85 deletions
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index bd7cd1f..dd5cad1 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -3,6 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. */ +#ifdef __sgi +# include <sys/ptimers.h> +#endif #include <sys/errno.h> #include <sys/types.h> #include <sys/param.h> @@ -34,7 +37,6 @@ # include <string.h> # include <stdlib.h> #endif -#include <sys/uio.h> #if !defined(__SVR4) && !defined(__svr4__) # ifndef linux # include <sys/mbuf.h> @@ -77,10 +79,10 @@ #endif #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_proxy.h" #include "netinet/ip_auth.h" # if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) # include <sys/malloc.h> @@ -97,7 +99,6 @@ #if !defined(lint) static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; -/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.39 2001/07/18 13:30:32 darrenr Exp $"; */ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -108,7 +109,7 @@ extern int opts; # define FR_VERBOSE(verb_pr) verbose verb_pr # define FR_DEBUG(verb_pr) debug verb_pr -# define IPLLOG(a, c, d, e) ipllog() +# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) #else /* #ifndef _KERNEL */ # define FR_VERBOSE(verb_pr) # define FR_DEBUG(verb_pr) @@ -263,7 +264,7 @@ fr_info_t *fin; fin->fin_off = off; fin->fin_plen = plen; - fin->fin_dp = (void *)tcp; + fin->fin_dp = (char *)tcp; off <<= 3; switch (p) @@ -283,7 +284,7 @@ fr_info_t *fin; { case ICMP6_ECHO_REPLY : case ICMP6_ECHO_REQUEST : - minicmpsz = ICMP6ERR_MINPKTLEN; + minicmpsz = ICMP6_MINLEN; break; case ICMP6_DST_UNREACH : case ICMP6_PACKET_TOO_BIG : @@ -383,6 +384,19 @@ getports: fin->fin_data[1] = ntohs(tcp->th_dport); } break; + case IPPROTO_ESP : +#ifdef USE_INET6 + if (v == 6) { + if (plen < 8) + fi->fi_fl |= FI_SHORT; + } else +#endif + if (v == 4) { + if (((ip->ip_len < hlen + 8) && !off) || + (off && off < 8)) + fi->fi_fl |= FI_SHORT; + } + break; default : break; } @@ -548,8 +562,8 @@ fr_info_t *fin; * Could be per interface, but this gets real nasty when you don't have * kernel sauce. */ -int fr_scanlist(pass, ip, fin, m) -u_32_t pass; +int fr_scanlist(passin, ip, fin, m) +u_32_t passin; ip_t *ip; register fr_info_t *fin; void *m; @@ -557,20 +571,21 @@ void *m; register struct frentry *fr; register fr_ip_t *fi = &fin->fin_fi; int rulen, portcmp = 0, off, skip = 0, logged = 0; - u_32_t passt; + u_32_t pass, passt, passl; + frentry_t *frl; + frl = NULL; + pass = passin; fr = fin->fin_fr; fin->fin_fr = NULL; - fin->fin_rule = 0; - fin->fin_group = 0; off = fin->fin_off; - 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) { + FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags)); skip--; continue; } @@ -581,25 +596,28 @@ void *m; * check that we are working for the right interface */ #ifdef _KERNEL -# if BSD >= 199306 +# 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)) + (fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif))) continue; - } else + } # endif - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; #else if (opts & (OPT_VERBOSE|OPT_DEBUG)) printf("\n"); - FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : - (pass & FR_AUTH) ? 'a' : 'b')); +#endif + + FR_VERBOSE(("%c", fr->fr_skip ? 's' : + (pass & FR_PASS) ? 'p' : + (pass & FR_AUTH) ? 'a' : + (pass & FR_ACCOUNT) ? 'A' : + (pass & FR_NOMATCH) ? 'n' : 'b')); + if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) continue; + FR_VERBOSE((":i")); -#endif { register u_32_t *ld, *lm, *lip; register int i; @@ -621,22 +639,19 @@ void *m; /* * Unrolled loops (4 each, for 32 bits). */ - i |= ((*lip & *lm) != *ld) << 19; FR_DEBUG(("1a. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 5; if (fi->fi_v == 6) { - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; FR_DEBUG(("1b. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; + i |= ((*lip++ & *lm++) != *ld++) << 5; FR_DEBUG(("1c. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; + i |= ((*lip++ & *lm++) != *ld++) << 5; FR_DEBUG(("1d. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 5; } else { lip += 3; lm += 3; @@ -645,23 +660,19 @@ void *m; i ^= (fr->fr_flags & FR_NOTSRCIP); if (i) continue; - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 6; if (fi->fi_v == 6) { - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; + i |= ((*lip++ & *lm++) != *ld++) << 6; FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; + i |= ((*lip++ & *lm++) != *ld++) << 6; FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 6; } else { lip += 3; lm += 3; @@ -670,14 +681,12 @@ void *m; i ^= (fr->fr_flags & FR_NOTDSTIP); if (i) continue; - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); FR_DEBUG(("3. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); + i |= ((*lip++ & *lm++) != *ld++); FR_DEBUG(("4. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip & *lm) != *ld); if (i) continue; } @@ -704,17 +713,30 @@ void *m; } } FR_VERBOSE(("*")); - /* - * Just log this packet... - */ + + if (fr->fr_flags & FR_NOMATCH) { + passt = passl; + passl = passin; + fin->fin_fr = frl; + frl = NULL; + if (fr->fr_flags & FR_QUICK) + break; + continue; + } + + passl = passt; passt = fr->fr_flags; + frl = fin->fin_fr; + fin->fin_fr = fr; #if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) if (securelevel <= 0) #endif if ((passt & FR_CALLNOW) && fr->fr_func) passt = (*fr->fr_func)(passt, ip, fin); - fin->fin_fr = fr; #ifdef IPFILTER_LOG + /* + * Just log this packet... + */ if ((passt & FR_LOGMASK) == FR_LOG) { if (!IPLLOG(passt, ip, fin, m)) { if (passt & FR_LOGORBLOCK) @@ -725,32 +747,33 @@ void *m; logged = 1; } #endif /* IPFILTER_LOG */ - if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) - pass = passt; - FR_DEBUG(("pass %#x\n", pass)); ATOMIC_INCL(fr->fr_hits); - if (pass & FR_ACCOUNT) + if (passt & FR_ACCOUNT) fr->fr_bytes += (U_QUAD_T)ip->ip_len; else fin->fin_icode = fr->fr_icode; fin->fin_rule = rulen; fin->fin_group = fr->fr_group; - if (fr->fr_grp) { + if (fr->fr_grp != NULL) { fin->fin_fr = fr->fr_grp; - pass = fr_scanlist(pass, ip, fin, m); + passt = fr_scanlist(passt, 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_DONTCACHE) + if (passt & FR_DONTCACHE) logged = 1; } - if (pass & FR_QUICK) + if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) + pass = passt; + FR_DEBUG(("pass %#x\n", pass)); + if (passt & FR_QUICK) break; } if (logged) pass |= FR_DONTCACHE; + pass |= (fi->fi_fl << 24); return pass; } @@ -806,7 +829,7 @@ int out; /* * disable delayed checksums. */ - if (out && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { + if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { in_delayed_cksum(m); m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } @@ -847,6 +870,9 @@ int out; case IPPROTO_ICMP: plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); break; + case IPPROTO_ESP: + plen = 8; + break; # ifdef USE_INET6 case IPPROTO_ICMPV6 : /* @@ -918,20 +944,26 @@ int out; ATOMIC_INCL(frstats[0].fr_ipv6[out]); if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { ATOMIC_INCL(frstats[0].fr_badttl); - if (fr_minttllog) - logit = -2; + if (fr_minttllog & 1) + logit = -3; + if (fr_minttllog & 2) + drop = 1; } } else # endif if (!out) { if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { ATOMIC_INCL(frstats[0].fr_badsrc); - if (fr_chksrc == 2) + if (fr_chksrc & 1) + drop = 1; + if (fr_chksrc & 2) logit = -2; } else if (ip->ip_ttl < fr_minttl) { ATOMIC_INCL(frstats[0].fr_badttl); - if (fr_minttllog) + if (fr_minttllog & 1) logit = -3; + if (fr_minttllog & 2) + drop = 1; } } if (drop) { @@ -1022,6 +1054,7 @@ int out; FI_COPYSIZE); if (pass & FR_NOMATCH) { ATOMIC_INCL(frstats[out].fr_nom); + fin->fin_fr = NULL; } } } else @@ -1035,11 +1068,7 @@ int out; */ if ((pass & FR_AUTH)) { if (fr_newauth((mb_t *)m, fin, ip) != 0) { -#ifdef _KERNEL m = *mp = NULL; -#else - ; -#endif error = 0; } else error = ENOSPC; @@ -1069,7 +1098,7 @@ int out; } } if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, fin, 0) == NULL) { + if (fr_addstate(ip, fin, NULL, 0) == NULL) { ATOMIC_INCL(frstats[out].fr_bads); } else { ATOMIC_INCL(frstats[out].fr_ads); @@ -1098,11 +1127,19 @@ int out; else #endif list = ipacct[1][fr_active]; - if ((fin->fin_fr = list) && - (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { - ATOMIC_INCL(frstats[1].fr_acct); + if (list != NULL) { + u_32_t sg, sr; + + fin->fin_fr = list; + sg = fin->fin_group; + sr = fin->fin_rule; + if (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT) { + ATOMIC_INCL(frstats[1].fr_acct); + } + fin->fin_group = sg; + fin->fin_rule = sr; + fin->fin_fr = fr; } - fin->fin_fr = fr; changed = ip_natout(ip, fin); } else fin->fin_fr = fr; @@ -1151,10 +1188,10 @@ logit: # if SOLARIS mc = dupmsg(m); # else -# ifndef linux - mc = m_copy(m, 0, M_COPYALL); +# if defined(__OpenBSD__) && (OpenBSD >= 199905) + mc = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); # else - ; + mc = m_copy(m, 0, M_COPYALL); # endif # endif #endif @@ -1171,7 +1208,6 @@ logit: * some operating systems. */ if (!out) { -#ifdef _KERNEL if (pass & FR_RETICMP) { int dst; @@ -1187,19 +1223,6 @@ logit: ATOMIC_INCL(frstats[1].fr_ret); } } -#else - if ((pass & FR_RETMASK) == FR_RETICMP) { - verbose("- ICMP unreachable sent\n"); - ATOMIC_INCL(frstats[0].fr_ret); - } else if ((pass & FR_RETMASK) == FR_FAKEICMP) { - verbose("- forged ICMP unreachable sent\n"); - ATOMIC_INCL(frstats[0].fr_ret); - } else if (((pass & FR_RETMASK) == FR_RETRST) && - !(fin->fin_fl & FI_SHORT)) { - verbose("- TCP RST sent\n"); - ATOMIC_INCL(frstats[1].fr_ret); - } -#endif } else { if (pass & FR_RETRST) error = ECONNRESET; @@ -1224,8 +1247,10 @@ logit: frdest_t *fdp = &fr->fr_tif; if (((pass & FR_FASTROUTE) && !out) || - (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) + (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { (void) ipfr_fastroute(m, mp, fin, fdp); + m = *mp; + } if (mc != NULL) (void) ipfr_fastroute(mc, &mc, fin, &fr->fr_dif); @@ -1260,6 +1285,12 @@ logit: return 0; if (pass & FR_AUTH) return -2; + if ((pass & FR_RETMASK) == FR_RETRST) + return -3; + if ((pass & FR_RETMASK) == FR_RETICMP) + return -4; + if ((pass & FR_RETMASK) == FR_FAKEICMP) + return -5; return -1; #endif /* _KERNEL */ } @@ -1481,7 +1512,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.39 2001/07/18 13:30:32 darrenr Exp $ + * $Id: fil.c,v 2.35.2.58 2002/03/13 02:23:13 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, |