2 * Copyright (C) 1993-1998 by Darren Reed.
4 * Redistribution and use in source and binary forms are permitted
5 * provided that this notice is preserved and due credit is given
6 * to the original author and the contributors.
9 static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $";
13 #include <sys/errno.h>
14 #include <sys/types.h>
15 #include <sys/param.h>
18 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
20 # include "opt_ipfilter_log.h"
22 #if defined(_KERNEL) && defined(__FreeBSD_version) && \
23 (__FreeBSD_version >= 220000)
24 # include <sys/filio.h>
25 # include <sys/fcntl.h>
27 # include <sys/ioctl.h>
29 #if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
30 # include <sys/systm.h>
37 #if !defined(__SVR4) && !defined(__svr4__)
39 # include <sys/mbuf.h>
42 # include <sys/byteorder.h>
44 # include <sys/dditypes.h>
46 # include <sys/stream.h>
49 # include <sys/protosw.h>
50 # include <sys/socket.h>
56 #include <net/route.h>
57 #include <netinet/in.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/ip.h>
61 # include <netinet/ip_var.h>
63 #if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
64 # include <sys/hashing.h>
65 # include <netinet/in_var.h>
67 #include <netinet/tcp.h>
68 #include <netinet/udp.h>
69 #include <netinet/ip_icmp.h>
70 #include "netinet/ip_compat.h"
71 #include <netinet/tcpip.h>
72 #include "netinet/ip_fil.h"
73 #include "netinet/ip_proxy.h"
74 #include "netinet/ip_nat.h"
75 #include "netinet/ip_frag.h"
76 #include "netinet/ip_state.h"
77 #include "netinet/ip_auth.h"
78 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
79 # include <sys/malloc.h>
80 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
81 # include "opt_ipfilter.h"
85 # define MIN(a,b) (((a)<(b))?(a):(b))
87 #include "netinet/ipl.h"
94 # define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
96 # define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
98 # define FR_VERBOSE(verb_pr) verbose verb_pr
99 # define FR_DEBUG(verb_pr) debug verb_pr
100 # define SEND_RESET(ip, qif, if, m, fin) send_reset(ip, if)
101 # define IPLLOG(a, c, d, e) ipllog()
102 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
103 #else /* #ifndef _KERNEL */
104 # define FR_IFVERBOSE(ex,second,verb_pr) ;
105 # define FR_IFDEBUG(ex,second,verb_pr) ;
106 # define FR_VERBOSE(verb_pr)
107 # define FR_DEBUG(verb_pr)
108 # define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
109 # if SOLARIS || defined(__sgi)
110 extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat;
111 extern kmutex_t ipf_rw;
114 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
116 # define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif)
117 # define ICMP_ERROR(b, ip, t, c, if, dst) \
118 icmp_error(ip, t, c, if, dst)
120 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
122 # define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp)
123 # define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if)
125 # define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
126 # define ICMP_ERROR(b, ip, t, c, if, dst) \
127 send_icmp_err(ip, t, c, if, dst)
129 # endif /* SOLARIS || __sgi */
133 struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
134 struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
135 *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
136 struct frgroup *ipfgroups[3][2];
137 int fr_flags = IPF_LOGGING, fr_active = 0;
138 #if defined(IPFILTER_DEFAULT_BLOCK)
139 int fr_pass = FR_NOMATCH|FR_BLOCK;
141 int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
143 char ipfilter_version[] = IPL_VERSION;
145 fr_info_t frcache[2];
147 static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
148 static int frflushlist __P((int, minor_t, int *, frentry_t **));
150 static void frsynclist __P((frentry_t *));
155 * bit values for identifying presence of individual IP options
157 struct optlist ipopts[20] = {
158 { IPOPT_NOP, 0x000001 },
159 { IPOPT_RR, 0x000002 },
160 { IPOPT_ZSU, 0x000004 },
161 { IPOPT_MTUP, 0x000008 },
162 { IPOPT_MTUR, 0x000010 },
163 { IPOPT_ENCODE, 0x000020 },
164 { IPOPT_TS, 0x000040 },
165 { IPOPT_TR, 0x000080 },
166 { IPOPT_SECURITY, 0x000100 },
167 { IPOPT_LSRR, 0x000200 },
168 { IPOPT_E_SEC, 0x000400 },
169 { IPOPT_CIPSO, 0x000800 },
170 { IPOPT_SATID, 0x001000 },
171 { IPOPT_SSRR, 0x002000 },
172 { IPOPT_ADDEXT, 0x004000 },
173 { IPOPT_VISA, 0x008000 },
174 { IPOPT_IMITD, 0x010000 },
175 { IPOPT_EIP, 0x020000 },
176 { IPOPT_FINN, 0x040000 },
181 * bit values for identifying presence of individual IP security options
183 struct optlist secopt[8] = {
184 { IPSO_CLASS_RES4, 0x01 },
185 { IPSO_CLASS_TOPS, 0x02 },
186 { IPSO_CLASS_SECR, 0x04 },
187 { IPSO_CLASS_RES3, 0x08 },
188 { IPSO_CLASS_CONF, 0x10 },
189 { IPSO_CLASS_UNCL, 0x20 },
190 { IPSO_CLASS_RES2, 0x40 },
191 { IPSO_CLASS_RES1, 0x80 }
196 * compact the IP header into a structure which contains just the info.
197 * which is useful for comparing IP headers with.
199 void fr_makefrip(hlen, ip, fin)
206 fr_ip_t *fi = &fin->fin_fi;
207 u_short optmsk = 0, secmsk = 0, auth = 0;
214 fin->fin_data[0] = 0;
215 fin->fin_data[1] = 0;
218 fin->fin_id = ip->ip_id;
220 fin->fin_icode = ipl_unreach;
223 fi->fi_tos = ip->ip_tos;
224 fin->fin_hlen = hlen;
225 fin->fin_dlen = ip->ip_len - hlen;
226 tcp = (tcphdr_t *)((char *)ip + hlen);
227 fin->fin_dp = (void *)tcp;
228 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
229 fi->fi_src.s_addr = ip->ip_src.s_addr;
230 fi->fi_dst.s_addr = ip->ip_dst.s_addr;
232 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
233 off = (ip->ip_off & IP_OFFMASK) << 3;
234 if (ip->ip_off & 0x3fff)
235 fi->fi_fl |= FI_FRAG;
240 int minicmpsz = sizeof(struct icmp);
243 icmp = (icmphdr_t *)tcp;
245 if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
246 icmp->icmp_type == ICMP_ECHO))
247 minicmpsz = ICMP_MINLEN;
248 if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
249 icmp->icmp_type == ICMP_TSTAMPREPLY))
250 minicmpsz = 20; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
251 if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
252 icmp->icmp_type == ICMP_MASKREPLY))
253 minicmpsz = 12; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
254 if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
255 (off && off < sizeof(struct icmp)))
256 fi->fi_fl |= FI_SHORT;
257 if (fin->fin_dlen > 1)
258 fin->fin_data[0] = *(u_short *)tcp;
262 fi->fi_fl |= FI_TCPUDP;
263 if ((!IPMINLEN(ip, tcphdr) && !off) ||
264 (off && off < sizeof(struct tcphdr)))
265 fi->fi_fl |= FI_SHORT;
266 if (!(fi->fi_fl & FI_SHORT) && !off)
267 fin->fin_tcpf = tcp->th_flags;
270 fi->fi_fl |= FI_TCPUDP;
271 if ((!IPMINLEN(ip, udphdr) && !off) ||
272 (off && off < sizeof(struct udphdr)))
273 fi->fi_fl |= FI_SHORT;
275 if (!off && (fin->fin_dlen > 3)) {
276 fin->fin_data[0] = ntohs(tcp->th_sport);
277 fin->fin_data[1] = ntohs(tcp->th_dport);
285 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen; ) {
289 ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
290 if (opt > 1 && (ol < 2 || ol > hlen))
292 for (i = 9, mv = 4; mv >= 0; ) {
294 if (opt == (u_char)op->ol_val) {
295 optmsk |= op->ol_bit;
296 if (opt == IPOPT_SECURITY) {
301 sec = *(s + 2); /* classification */
302 for (j = 3, m = 2; m >= 0; ) {
304 if (sec == sp->ol_val) {
305 secmsk |= sp->ol_bit;
311 if (sec < sp->ol_val)
319 if (opt < op->ol_val)
327 if (auth && !(auth & 0x0100))
329 fi->fi_optmsk = optmsk;
330 fi->fi_secmsk = secmsk;
336 * check an IP packet for TCP/UDP characteristics such as ports and flags.
338 static int fr_tcpudpchk(fr, fin)
342 register u_short po, tup;
344 register int err = 1;
347 * Both ports should *always* be in the first fragment.
348 * So far, I cannot find any cases where they can not be.
350 * compare destination ports
352 if ((i = (int)fr->fr_dcmp)) {
354 tup = fin->fin_data[1];
356 * Do opposite test to that required and
357 * continue if that succeeds.
359 if (!--i && tup != po) /* EQUAL */
361 else if (!--i && tup == po) /* NOTEQUAL */
363 else if (!--i && tup >= po) /* LESSTHAN */
365 else if (!--i && tup <= po) /* GREATERTHAN */
367 else if (!--i && tup > po) /* LT or EQ */
369 else if (!--i && tup < po) /* GT or EQ */
371 else if (!--i && /* Out of range */
372 (tup >= po && tup <= fr->fr_dtop))
374 else if (!--i && /* In range */
375 (tup <= po || tup >= fr->fr_dtop))
379 * compare source ports
381 if (err && (i = (int)fr->fr_scmp)) {
383 tup = fin->fin_data[0];
384 if (!--i && tup != po)
386 else if (!--i && tup == po)
388 else if (!--i && tup >= po)
390 else if (!--i && tup <= po)
392 else if (!--i && tup > po)
394 else if (!--i && tup < po)
396 else if (!--i && /* Out of range */
397 (tup >= po && tup <= fr->fr_stop))
399 else if (!--i && /* In range */
400 (tup <= po || tup >= fr->fr_stop))
405 * If we don't have all the TCP/UDP header, then how can we
406 * expect to do any sort of match on it ? If we were looking for
407 * TCP flags, then NO match. If not, then match (which should
408 * satisfy the "short" class too).
410 if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
411 if (fin->fin_fi.fi_fl & FI_SHORT)
412 return !(fr->fr_tcpf | fr->fr_tcpfm);
414 * Match the flags ? If not, abort this match.
417 fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
418 FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
419 fr->fr_tcpfm, fr->fr_tcpf));
427 * Check the input/output list of rules for a match and result.
428 * Could be per interface, but this gets real nasty when you don't have
431 int fr_scanlist(pass, ip, fin, m)
434 register fr_info_t *fin;
437 register struct frentry *fr;
438 register fr_ip_t *fi = &fin->fin_fi;
439 int rulen, portcmp = 0, off, skip = 0, logged = 0;
446 off = ip->ip_off & IP_OFFMASK;
447 pass |= (fi->fi_fl << 24);
449 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
452 for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
458 * In all checks below, a null (zero) value in the
459 * filter struture is taken to mean a wildcard.
461 * check that we are working for the right interface
465 if (fin->fin_out != 0) {
467 fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) ||
468 (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp))
472 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
475 if (opts & (OPT_VERBOSE|OPT_DEBUG))
477 FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' :
478 (pass & FR_AUTH) ? 'a' : 'b'));
479 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
484 register u_32_t *ld, *lm, *lip;
488 lm = (u_32_t *)&fr->fr_mip;
489 ld = (u_32_t *)&fr->fr_ip;
490 i = ((lip[0] & lm[0]) != ld[0]);
491 FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
492 lip[0], lm[0], ld[0]));
493 i |= ((lip[1] & lm[1]) != ld[1]) << 19;
494 i ^= (fr->fr_flags & FR_NOTSRCIP);
495 FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
496 lip[1], lm[1], ld[1]));
497 i |= ((lip[2] & lm[2]) != ld[2]) << 20;
498 i ^= (fr->fr_flags & FR_NOTDSTIP);
499 FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
500 lip[2], lm[2], ld[2]));
501 i |= ((lip[3] & lm[3]) != ld[3]);
502 FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
503 lip[3], lm[3], ld[3]));
504 i |= ((lip[4] & lm[4]) != ld[4]);
505 FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
506 lip[4], lm[4], ld[4]));
512 * If a fragment, then only the first has what we're looking
515 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
518 if (fi->fi_fl & FI_TCPUDP) {
519 if (!fr_tcpudpchk(fr, fin))
521 } else if (fr->fr_icmpm || fr->fr_icmp) {
522 if ((fi->fi_p != IPPROTO_ICMP) || off ||
525 if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) {
526 FR_DEBUG(("i. %#x & %#x != %#x\n",
527 fin->fin_data[0], fr->fr_icmpm,
534 * Just log this packet...
536 passt = fr->fr_flags;
537 if ((passt & FR_CALLNOW) && fr->fr_func)
538 passt = (*fr->fr_func)(passt, ip, fin);
541 if ((passt & FR_LOGMASK) == FR_LOG) {
542 if (!IPLLOG(passt, ip, fin, m)) {
543 ATOMIC_INC(frstats[fin->fin_out].fr_skip);
545 ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
548 #endif /* IPFILTER_LOG */
549 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
551 FR_DEBUG(("pass %#x\n", pass));
552 ATOMIC_INC(fr->fr_hits);
553 if (pass & FR_ACCOUNT)
554 fr->fr_bytes += (U_QUAD_T)ip->ip_len;
556 fin->fin_icode = fr->fr_icode;
557 fin->fin_rule = rulen;
558 fin->fin_group = fr->fr_group;
560 fin->fin_fr = fr->fr_grp;
561 pass = fr_scanlist(pass, ip, fin, m);
562 if (fin->fin_fr == NULL) {
563 fin->fin_rule = rulen;
564 fin->fin_group = fr->fr_group;
567 if (pass & FR_DONTCACHE)
574 pass |= FR_DONTCACHE;
580 * frcheck - filter check
581 * check using source and destination addresses/ports in a packet whether
582 * or not to pass it on or not.
584 int fr_check(ip, hlen, ifp, out
585 #if defined(_KERNEL) && SOLARIS
598 * The above really sucks, but short of writing a diff
600 fr_info_t frinfo, *fc;
601 register fr_info_t *fin = &frinfo;
602 frentry_t *fr = NULL;
603 int changed, error = EHOSTUNREACH;
605 #if !SOLARIS || !defined(_KERNEL)
606 register mb_t *m = *mp;
611 # if !defined(__SVR4) && !defined(__svr4__)
613 char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
619 * XXX For now, IP Filter and fast-forwarding of cached flows
620 * XXX are mutually exclusive. Eventually, IP Filter should
621 * XXX get a "can-fast-forward" filter rule.
623 m->m_flags &= ~M_CANFASTFWD;
624 # endif /* M_CANFASTFWD */
626 if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
627 ip->ip_p == IPPROTO_ICMP)) {
630 if ((ip->ip_off & IP_OFFMASK) == 0)
634 plen = sizeof(tcphdr_t);
637 plen = sizeof(udphdr_t);
639 /* 96 - enough for complete ICMP error IP header */
641 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
644 up = MIN(hlen + plen, ip->ip_len);
648 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
649 if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
650 ATOMIC_INC(frstats[out].fr_pull[1]);
653 m_copydata(m, 0, up, hbuf);
654 ATOMIC_INC(frstats[out].fr_pull[0]);
658 if ((*mp = m_pullup(m, up)) == 0) {
659 ATOMIC_INC(frstats[out].fr_pull[1]);
662 ATOMIC_INC(frstats[out].fr_pull[0]);
664 ip = mtod(m, ip_t *);
672 # endif /* !defined(__SVR4) && !defined(__svr4__) */
684 * Be careful here: ip_id is in network byte order when called
688 ip->ip_id = ntohs(ip->ip_id);
689 fr_makefrip(hlen, ip, fin);
695 READ_ENTER(&ipf_mutex);
697 if (fin->fin_fi.fi_fl & FI_SHORT)
698 ATOMIC_INC(frstats[out].fr_short);
701 * Check auth now. This, combined with the check below to see if apass
702 * is 0 is to ensure that we don't count the packet twice, which can
703 * otherwise occur when we reprocess it. As it is, we only count it
704 * after it has no auth. table matchup. This also stops NAT from
705 * occuring until after the packet has been auth'd.
707 apass = fr_checkauth(ip, fin);
710 changed = ip_natin(ip, fin);
711 if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
712 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
713 ATOMIC_INC(frstats[0].fr_acct);
717 if (apass || (!(fr = ipfr_knownfrag(ip, fin)) &&
718 !(fr = fr_checkstate(ip, fin)))) {
720 * If a packet is found in the auth table, then skip checking
721 * the access lists for permission but we do need to consider
722 * the result as if it were from the ACL's.
726 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
728 * copy cached data so we can unlock the mutex
731 bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
732 ATOMIC_INC(frstats[out].fr_chit);
733 if ((fr = fin->fin_fr)) {
734 ATOMIC_INC(fr->fr_hits);
738 if ((fin->fin_fr = ipfilter[out][fr_active]))
739 pass = fr_scanlist(fr_pass, ip, fin, m);
740 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
741 bcopy((char *)fin, (char *)fc,
743 if (pass & FR_NOMATCH) {
744 ATOMIC_INC(frstats[out].fr_nom);
752 * If we fail to add a packet to the authorization queue,
753 * then we drop the packet later. However, if it was added
754 * then pretend we've dropped it already.
756 if ((pass & FR_AUTH))
757 if (FR_NEWAUTH(m, fin, ip, qif) != 0)
764 if (pass & FR_PREAUTH) {
765 READ_ENTER(&ipf_auth);
766 if ((fin->fin_fr = ipauth) &&
767 (pass = fr_scanlist(0, ip, fin, m))) {
768 ATOMIC_INC(fr_authstats.fas_hits);
770 ATOMIC_INC(fr_authstats.fas_miss);
772 RWLOCK_EXIT(&ipf_auth);
776 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
777 if (fin->fin_fi.fi_fl & FI_FRAG) {
778 if (ipfr_newfrag(ip, fin, pass) == -1) {
779 ATOMIC_INC(frstats[out].fr_bnfr);
781 ATOMIC_INC(frstats[out].fr_nfr);
784 ATOMIC_INC(frstats[out].fr_cfr);
787 if (pass & FR_KEEPSTATE) {
788 if (fr_addstate(ip, fin, 0) == NULL) {
789 ATOMIC_INC(frstats[out].fr_bads);
791 ATOMIC_INC(frstats[out].fr_ads);
794 } else if (fr != NULL) {
796 if (pass & FR_LOGFIRST)
797 pass &= ~(FR_LOGFIRST|FR_LOG);
800 if (fr && fr->fr_func && !(pass & FR_CALLNOW))
801 pass = (*fr->fr_func)(pass, ip, fin);
804 * Only count/translate packets which will be passed on, out the
807 if (out && (pass & FR_PASS)) {
808 if ((fin->fin_fr = ipacct[1][fr_active]) &&
809 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
810 ATOMIC_INC(frstats[1].fr_acct);
813 changed = ip_natout(ip, fin);
816 RWLOCK_EXIT(&ipf_mutex);
819 if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
820 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
821 pass |= FF_LOGNOMATCH;
822 ATOMIC_INC(frstats[out].fr_npkl);
824 } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
825 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
826 if ((pass & FR_LOGMASK) != FR_LOGP)
828 ATOMIC_INC(frstats[out].fr_ppkl);
830 } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
831 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
832 if ((pass & FR_LOGMASK) != FR_LOGB)
834 ATOMIC_INC(frstats[out].fr_bpkl);
836 if (!IPLLOG(pass, ip, fin, m)) {
837 ATOMIC_INC(frstats[out].fr_skip);
838 if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
839 (FR_PASS|FR_LOGORBLOCK))
840 pass ^= FR_PASS|FR_BLOCK;
844 #endif /* IPFILTER_LOG */
847 ip->ip_id = htons(ip->ip_id);
851 * Only allow FR_DUP to work if a rule matched - it makes no sense to
852 * set FR_DUP as a "default" as there are no instructions about where
853 * to send the packet.
855 if (fr && (pass & FR_DUP))
860 mc = m_copy(m, 0, M_COPYALL);
866 if (pass & FR_PASS) {
867 ATOMIC_INC(frstats[out].fr_pass);
868 } else if (pass & FR_BLOCK) {
869 ATOMIC_INC(frstats[out].fr_block);
871 * Should we return an ICMP packet to indicate error
872 * status passing through the packet filter ?
873 * WARNING: ICMP error packets AND TCP RST packets should
874 * ONLY be sent in repsonse to incoming packets. Sending them
875 * in response to outbound packets can result in a panic on
876 * some operating systems.
880 if (pass & FR_RETICMP) {
883 if ((pass & FR_RETMASK) == FR_FAKEICMP)
888 ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
891 ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
894 ATOMIC_INC(frstats[0].fr_ret);
895 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
896 !(fin->fin_fi.fi_fl & FI_SHORT)) {
897 if (SEND_RESET(ip, qif, ifp, fin) == 0) {
898 ATOMIC_INC(frstats[1].fr_ret);
902 if ((pass & FR_RETMASK) == FR_RETICMP) {
903 verbose("- ICMP unreachable sent\n");
904 ATOMIC_INC(frstats[0].fr_ret);
905 } else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
906 verbose("- forged ICMP unreachable sent\n");
907 ATOMIC_INC(frstats[0].fr_ret);
908 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
909 !(fin->fin_fi.fi_fl & FI_SHORT)) {
910 verbose("- TCP RST sent\n");
911 ATOMIC_INC(frstats[1].fr_ret);
915 if (pass & FR_RETRST)
921 * If we didn't drop off the bottom of the list of rules (and thus
922 * the 'current' rule fr is not NULL), then we may have some extra
923 * instructions about what to do with a packet.
924 * Once we're finished return to our caller, freeing the packet if
925 * we are dropping it (* BSD ONLY *).
931 frdest_t *fdp = &fr->fr_tif;
933 if (((pass & FR_FASTROUTE) && !out) ||
934 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
935 if (ipfr_fastroute(m, fin, fdp) == 0)
939 ipfr_fastroute(mc, fin, &fr->fr_dif);
941 if (!(pass & FR_PASS) && m)
944 else if (changed && up && m)
945 m_copyback(m, 0, up, hbuf);
948 # else /* !SOLARIS */
950 frdest_t *fdp = &fr->fr_tif;
952 if (((pass & FR_FASTROUTE) && !out) ||
953 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
954 if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0)
958 ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
960 # endif /* !SOLARIS */
961 return (pass & FR_PASS) ? 0 : error;
963 if (pass & FR_NOMATCH)
976 * addr should be 16bit aligned and len is in bytes.
979 u_short ipf_cksum(addr, len)
980 register u_short *addr;
983 register u_32_t sum = 0;
985 for (sum = 0; len > 1; len -= 2)
988 /* mop up an odd byte, if necessary */
990 sum += *(u_char *)addr;
993 * add back carry outs from top 16 bits to low 16 bits
995 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
996 sum += (sum >> 16); /* add carry */
997 return (u_short)(~sum);
1002 * NB: This function assumes we've pullup'd enough for all of the IP header
1003 * and the TCP header. We also assume that data blocks aren't allocated in
1006 u_short fr_tcpsum(m, ip, tcp)
1011 u_short *sp, slen, ts;
1016 * Add up IP Header portion
1018 hlen = ip->ip_hl << 2;
1019 slen = ip->ip_len - hlen;
1020 sum = htons((u_short)ip->ip_p);
1022 sp = (u_short *)&ip->ip_src;
1023 sum += *sp++; /* ip_src */
1025 sum += *sp++; /* ip_dst */
1031 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */
1032 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1033 sum2 = ~sum2 & 0xffff;
1034 # else /* SOLARIS */
1035 # if defined(BSD) || defined(sun)
1042 sum2 = in_cksum(m, slen);
1050 * Both sum and sum2 are partial sums, so combine them together.
1052 sum = (sum & 0xffff) + (sum >> 16);
1053 sum = ~sum & 0xffff;
1055 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1056 # else /* defined(BSD) || defined(sun) */
1062 u_short len = ip->ip_len;
1068 * Add up IP Header portion
1070 sp = (u_short *)&ip->ip_src;
1071 len -= (ip->ip_hl << 2);
1072 sum = ntohs(IPPROTO_TCP);
1074 sum += *sp++; /* ip_src */
1076 sum += *sp++; /* ip_dst */
1078 if (sp != (u_short *)tcp)
1079 sp = (u_short *)tcp;
1080 sum += *sp++; /* sport */
1081 sum += *sp++; /* dport */
1082 sum += *sp++; /* seq */
1084 sum += *sp++; /* ack */
1086 sum += *sp++; /* off */
1087 sum += *sp++; /* win */
1088 sum += *sp++; /* Skip over checksum */
1089 sum += *sp++; /* urp */
1093 * In case we had to copy the IP & TCP header out of mbufs,
1094 * skip over the mbuf bits which are the header
1096 if ((caddr_t)ip != mtod(m, caddr_t)) {
1097 hlen = (caddr_t)sp - (caddr_t)ip;
1099 add = MIN(hlen, m->m_len);
1100 sp = (u_short *)(mtod(m, caddr_t) + add);
1102 if (add == m->m_len) {
1107 sp = mtod(m, u_short *);
1109 PANIC((!m),("fr_tcpsum(1): not enough data"));
1115 if (!(len -= sizeof(*tcp)))
1118 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
1120 PANIC((!m),("fr_tcpsum(2): not enough data"));
1121 sp = mtod(m, u_short *);
1123 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
1124 bytes.c[0] = *(u_char *)sp;
1126 PANIC((!m),("fr_tcpsum(3): not enough data"));
1127 sp = mtod(m, u_short *);
1128 bytes.c[1] = *(u_char *)sp;
1130 sp = (u_short *)((u_char *)sp + 1);
1132 if ((u_long)sp & 1) {
1133 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
1140 sum += ntohs(*(u_char *)sp << 8);
1142 while (sum > 0xffff)
1143 sum = (sum & 0xffff) + (sum >> 16);
1144 sum2 = (u_short)(~sum & 0xffff);
1146 # endif /* defined(BSD) || defined(sun) */
1147 # endif /* SOLARIS */
1156 #if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1158 * Copyright (c) 1982, 1986, 1988, 1991, 1993
1159 * The Regents of the University of California. All rights reserved.
1161 * Redistribution and use in source and binary forms, with or without
1162 * modification, are permitted provided that the following conditions
1164 * 1. Redistributions of source code must retain the above copyright
1165 * notice, this list of conditions and the following disclaimer.
1166 * 2. Redistributions in binary form must reproduce the above copyright
1167 * notice, this list of conditions and the following disclaimer in the
1168 * documentation and/or other materials provided with the distribution.
1169 * 3. All advertising materials mentioning features or use of this software
1170 * must display the following acknowledgement:
1171 * This product includes software developed by the University of
1172 * California, Berkeley and its contributors.
1173 * 4. Neither the name of the University nor the names of its contributors
1174 * may be used to endorse or promote products derived from this software
1175 * without specific prior written permission.
1177 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1178 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1179 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1180 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1181 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1182 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1183 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1184 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1185 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1186 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1189 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1190 * $Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $
1193 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1194 * continuing for "len" bytes, into the indicated buffer.
1197 m_copydata(m, off, len, cp)
1203 register unsigned count;
1205 if (off < 0 || len < 0)
1206 panic("m_copydata");
1209 panic("m_copydata");
1217 panic("m_copydata");
1218 count = MIN(m->m_len - off, len);
1219 bcopy(mtod(m, caddr_t) + off, cp, count);
1230 * Copy data from a buffer back into the indicated mbuf chain,
1231 * starting "off" bytes from the beginning, extending the mbuf
1232 * chain if necessary.
1235 m_copyback(m0, off, len, cp)
1242 register struct mbuf *m = m0, *n;
1247 while (off > (mlen = m->m_len)) {
1250 if (m->m_next == 0) {
1251 n = m_getclr(M_DONTWAIT, m->m_type);
1254 n->m_len = min(MLEN, len + off);
1260 mlen = min (m->m_len - off, len);
1261 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1269 if (m->m_next == 0) {
1270 n = m_get(M_DONTWAIT, m->m_type);
1273 n->m_len = min(MLEN, len);
1280 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1281 m->m_pkthdr.len = totlen;
1286 #endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1289 frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
1296 frgroup_t *fg, **fgp;
1298 if (which == IPL_LOGAUTH)
1299 fgp = &ipfgroups[2][set];
1300 else if (flags & FR_ACCOUNT)
1301 fgp = &ipfgroups[1][set];
1302 else if (flags & (FR_OUTQUE|FR_INQUE))
1303 fgp = &ipfgroups[0][set];
1309 if (fg->fg_num == num)
1319 frgroup_t *fr_addgroup(num, fp, which, set)
1325 frgroup_t *fg, **fgp;
1327 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
1330 KMALLOC(fg, frgroup_t *);
1332 fg->fg_num = num & 0xffff;
1335 fg->fg_start = &fp->fr_grp;
1342 void fr_delgroup(num, flags, which, set)
1348 frgroup_t *fg, **fgp;
1350 if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
1360 * recursively flush rules from the list, descending groups as they are
1361 * encountered. if a rule is the head of a group and it has lost all its
1362 * group members, then also delete the group reference.
1364 static int frflushlist(set, unit, nfreedp, listp)
1370 register int freed = 0, i;
1371 register frentry_t *fp;
1373 while ((fp = *listp)) {
1374 *listp = fp->fr_next;
1376 i = frflushlist(set, unit, nfreedp, &fp->fr_grp);
1377 MUTEX_ENTER(&ipf_rw);
1379 MUTEX_EXIT(&ipf_rw);
1382 ATOMIC_DEC(fp->fr_ref);
1383 if (fp->fr_grhead) {
1384 fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags,
1386 fp->fr_grhead = NULL;
1388 if (fp->fr_ref == 0) {
1399 int frflush(unit, flags)
1403 int flushed = 0, set;
1405 if (unit != IPL_LOGIPF)
1407 WRITE_ENTER(&ipf_mutex);
1408 bzero((char *)frcache, sizeof(frcache[0]) * 2);
1411 if (flags & FR_INACTIVE)
1414 if (flags & FR_OUTQUE) {
1415 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
1416 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
1418 if (flags & FR_INQUE) {
1419 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
1420 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
1422 RWLOCK_EXIT(&ipf_mutex);
1427 char *memstr(src, dst, slen, dlen)
1433 while (dlen >= slen) {
1434 if (bcmp(src, dst, slen) == 0) {
1445 void fixskip(listp, rp, addremove)
1446 frentry_t **listp, *rp;
1450 int rules = 0, rn = 0;
1452 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
1458 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
1459 if (fp->fr_skip && (rn + fp->fr_skip >= rules))
1460 fp->fr_skip += addremove;
1466 * count consecutive 1's in bit mask. If the mask generated by counting
1467 * consecutive 1's is different to that passed, return -1, else return #
1476 ip = ipn = ntohl(ip);
1477 for (i = 32; i; i--, ipn *= 2)
1478 if (ipn & 0x80000000)
1483 for (i = 32, j = cnt; i; i--, j--) {
1495 * return the first IP Address associated with an interface
1497 int fr_ifpaddr(ifptr, inp)
1499 struct in_addr *inp;
1504 struct ifnet *ifp = ifptr;
1509 in.s_addr = ill->ill_ipif->ipif_local_addr;
1510 # else /* SOLARIS */
1515 struct sockaddr_in *sin;
1517 # if (__FreeBSD_version >= 300000)
1518 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1520 # if defined(__NetBSD__) || defined(__OpenBSD__)
1521 ifa = ifp->if_addrlist.tqh_first;
1523 # if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
1524 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa;
1526 ifa = ifp->if_addrlist;
1528 # endif /* __NetBSD__ || __OpenBSD__ */
1529 # endif /* __FreeBSD_version >= 300000 */
1530 # if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK))
1531 sin = (struct sockaddr_in *)&ifa->ifa_addr;
1533 sin = (struct sockaddr_in *)ifa->ifa_addr;
1534 while (sin && ifa &&
1535 sin->sin_family != AF_INET) {
1536 # if (__FreeBSD_version >= 300000)
1537 ifa = TAILQ_NEXT(ifa, ifa_link);
1539 # if defined(__NetBSD__) || defined(__OpenBSD__)
1540 ifa = ifa->ifa_list.tqe_next;
1542 ifa = ifa->ifa_next;
1544 # endif /* __FreeBSD_version >= 300000 */
1546 sin = (struct sockaddr_in *)ifa->ifa_addr;
1552 # endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
1555 # endif /* SOLARIS */
1561 static void frsynclist(fr)
1562 register frentry_t *fr;
1564 for (; fr; fr = fr->fr_next) {
1565 if (fr->fr_ifa != NULL) {
1566 fr->fr_ifa = GETUNIT(fr->fr_ifname);
1567 if (fr->fr_ifa == NULL)
1568 fr->fr_ifa = (void *)-1;
1571 frsynclist(fr->fr_grp);
1578 register struct ifnet *ifp;
1581 # if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
1582 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
1583 # if (NetBSD >= 199905) || defined(__OpenBSD__)
1584 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
1586 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
1589 for (ifp = ifnet; ifp; ifp = ifp->if_next)
1597 WRITE_ENTER(&ipf_mutex);
1598 frsynclist(ipacct[0][fr_active]);
1599 frsynclist(ipacct[1][fr_active]);
1600 frsynclist(ipfilter[0][fr_active]);
1601 frsynclist(ipfilter[1][fr_active]);
1602 RWLOCK_EXIT(&ipf_mutex);
1609 * return the first IP Address associated with an interface
1611 int fr_ifpaddr(ifptr, inp)
1613 struct in_addr *inp;