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 $"; */
11 static const char rcsid[] = "@(#)$FreeBSD$";
14 #include <sys/errno.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
19 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
21 # include "opt_ipfilter_log.h"
23 #if defined(_KERNEL) && defined(__FreeBSD_version) && \
24 (__FreeBSD_version >= 220000)
25 # include <sys/filio.h>
26 # include <sys/fcntl.h>
28 # include <sys/ioctl.h>
30 #if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
31 # include <sys/systm.h>
38 #if !defined(__SVR4) && !defined(__svr4__)
40 # include <sys/mbuf.h>
43 # include <sys/byteorder.h>
45 # include <sys/dditypes.h>
47 # include <sys/stream.h>
50 # include <sys/protosw.h>
51 # include <sys/socket.h>
57 #include <net/route.h>
58 #include <netinet/in.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/ip.h>
62 # include <netinet/ip_var.h>
64 #if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
65 # include <sys/hashing.h>
66 # include <netinet/in_var.h>
68 #include <netinet/tcp.h>
69 #include <netinet/udp.h>
70 #include <netinet/ip_icmp.h>
71 #include "netinet/ip_compat.h"
72 #include <netinet/tcpip.h>
73 #include "netinet/ip_fil.h"
74 #include "netinet/ip_proxy.h"
75 #include "netinet/ip_nat.h"
76 #include "netinet/ip_frag.h"
77 #include "netinet/ip_state.h"
78 #include "netinet/ip_auth.h"
79 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
80 # include <sys/malloc.h>
81 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
82 # include "opt_ipfilter.h"
86 # define MIN(a,b) (((a)<(b))?(a):(b))
88 #include "netinet/ipl.h"
90 #include <machine/in_cksum.h>
97 # define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
99 # define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
101 # define FR_VERBOSE(verb_pr) verbose verb_pr
102 # define FR_DEBUG(verb_pr) debug verb_pr
103 # define SEND_RESET(ip, qif, if, m, fin) send_reset(ip, if)
104 # define IPLLOG(a, c, d, e) ipllog()
105 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
106 #else /* #ifndef _KERNEL */
107 # define FR_IFVERBOSE(ex,second,verb_pr) ;
108 # define FR_IFDEBUG(ex,second,verb_pr) ;
109 # define FR_VERBOSE(verb_pr)
110 # define FR_DEBUG(verb_pr)
111 # define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
112 # if SOLARIS || defined(__sgi)
113 extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat;
114 extern kmutex_t ipf_rw;
117 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
119 # define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif)
120 # define ICMP_ERROR(b, ip, t, c, if, dst) \
121 icmp_error(ip, t, c, if, dst)
123 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
125 # define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp)
126 # define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if)
128 # define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
129 # define ICMP_ERROR(b, ip, t, c, if, dst) \
130 send_icmp_err(ip, t, c, if, dst)
132 # endif /* SOLARIS || __sgi */
136 struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
137 struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
138 *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
139 struct frgroup *ipfgroups[3][2];
140 int fr_flags = IPF_LOGGING, fr_active = 0;
141 #if defined(IPFILTER_DEFAULT_BLOCK)
142 int fr_pass = FR_NOMATCH|FR_BLOCK;
144 int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
146 char ipfilter_version[] = IPL_VERSION;
148 fr_info_t frcache[2];
150 static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
151 static int frflushlist __P((int, minor_t, int *, frentry_t **));
153 static void frsynclist __P((frentry_t *));
158 * bit values for identifying presence of individual IP options
160 struct optlist ipopts[20] = {
161 { IPOPT_NOP, 0x000001 },
162 { IPOPT_RR, 0x000002 },
163 { IPOPT_ZSU, 0x000004 },
164 { IPOPT_MTUP, 0x000008 },
165 { IPOPT_MTUR, 0x000010 },
166 { IPOPT_ENCODE, 0x000020 },
167 { IPOPT_TS, 0x000040 },
168 { IPOPT_TR, 0x000080 },
169 { IPOPT_SECURITY, 0x000100 },
170 { IPOPT_LSRR, 0x000200 },
171 { IPOPT_E_SEC, 0x000400 },
172 { IPOPT_CIPSO, 0x000800 },
173 { IPOPT_SATID, 0x001000 },
174 { IPOPT_SSRR, 0x002000 },
175 { IPOPT_ADDEXT, 0x004000 },
176 { IPOPT_VISA, 0x008000 },
177 { IPOPT_IMITD, 0x010000 },
178 { IPOPT_EIP, 0x020000 },
179 { IPOPT_FINN, 0x040000 },
184 * bit values for identifying presence of individual IP security options
186 struct optlist secopt[8] = {
187 { IPSO_CLASS_RES4, 0x01 },
188 { IPSO_CLASS_TOPS, 0x02 },
189 { IPSO_CLASS_SECR, 0x04 },
190 { IPSO_CLASS_RES3, 0x08 },
191 { IPSO_CLASS_CONF, 0x10 },
192 { IPSO_CLASS_UNCL, 0x20 },
193 { IPSO_CLASS_RES2, 0x40 },
194 { IPSO_CLASS_RES1, 0x80 }
199 * compact the IP header into a structure which contains just the info.
200 * which is useful for comparing IP headers with.
202 void fr_makefrip(hlen, ip, fin)
209 fr_ip_t *fi = &fin->fin_fi;
210 u_short optmsk = 0, secmsk = 0, auth = 0;
217 fin->fin_data[0] = 0;
218 fin->fin_data[1] = 0;
221 fin->fin_id = ip->ip_id;
223 fin->fin_icode = ipl_unreach;
226 fi->fi_tos = ip->ip_tos;
227 fin->fin_hlen = hlen;
228 fin->fin_dlen = ip->ip_len - hlen;
229 tcp = (tcphdr_t *)((char *)ip + hlen);
230 fin->fin_dp = (void *)tcp;
231 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
232 fi->fi_src.s_addr = ip->ip_src.s_addr;
233 fi->fi_dst.s_addr = ip->ip_dst.s_addr;
235 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
236 off = (ip->ip_off & IP_OFFMASK) << 3;
237 if (ip->ip_off & 0x3fff)
238 fi->fi_fl |= FI_FRAG;
243 int minicmpsz = sizeof(struct icmp);
246 icmp = (icmphdr_t *)tcp;
248 if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
249 icmp->icmp_type == ICMP_ECHO))
250 minicmpsz = ICMP_MINLEN;
251 if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
252 icmp->icmp_type == ICMP_TSTAMPREPLY))
253 minicmpsz = 20; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
254 if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
255 icmp->icmp_type == ICMP_MASKREPLY))
256 minicmpsz = 12; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
257 if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
258 (off && off < sizeof(struct icmp)))
259 fi->fi_fl |= FI_SHORT;
260 if (fin->fin_dlen > 1)
261 fin->fin_data[0] = *(u_short *)tcp;
265 fi->fi_fl |= FI_TCPUDP;
266 if ((!IPMINLEN(ip, tcphdr) && !off) ||
267 (off && off < sizeof(struct tcphdr)))
268 fi->fi_fl |= FI_SHORT;
269 if (!(fi->fi_fl & FI_SHORT) && !off)
270 fin->fin_tcpf = tcp->th_flags;
273 fi->fi_fl |= FI_TCPUDP;
274 if ((!IPMINLEN(ip, udphdr) && !off) ||
275 (off && off < sizeof(struct udphdr)))
276 fi->fi_fl |= FI_SHORT;
278 if (!off && (fin->fin_dlen > 3)) {
279 fin->fin_data[0] = ntohs(tcp->th_sport);
280 fin->fin_data[1] = ntohs(tcp->th_dport);
288 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) {
292 else if (opt == IPOPT_NOP)
298 if (ol < 2 || ol > hlen)
301 for (i = 9, mv = 4; mv >= 0; ) {
303 if (opt == (u_char)op->ol_val) {
304 optmsk |= op->ol_bit;
305 if (opt == IPOPT_SECURITY) {
310 sec = *(s + 2); /* classification */
311 for (j = 3, m = 2; m >= 0; ) {
313 if (sec == sp->ol_val) {
314 secmsk |= sp->ol_bit;
320 if (sec < sp->ol_val)
328 if (opt < op->ol_val)
336 if (auth && !(auth & 0x0100))
338 fi->fi_optmsk = optmsk;
339 fi->fi_secmsk = secmsk;
345 * check an IP packet for TCP/UDP characteristics such as ports and flags.
347 static int fr_tcpudpchk(fr, fin)
351 register u_short po, tup;
353 register int err = 1;
356 * Both ports should *always* be in the first fragment.
357 * So far, I cannot find any cases where they can not be.
359 * compare destination ports
361 if ((i = (int)fr->fr_dcmp)) {
363 tup = fin->fin_data[1];
365 * Do opposite test to that required and
366 * continue if that succeeds.
368 if (!--i && tup != po) /* EQUAL */
370 else if (!--i && tup == po) /* NOTEQUAL */
372 else if (!--i && tup >= po) /* LESSTHAN */
374 else if (!--i && tup <= po) /* GREATERTHAN */
376 else if (!--i && tup > po) /* LT or EQ */
378 else if (!--i && tup < po) /* GT or EQ */
380 else if (!--i && /* Out of range */
381 (tup >= po && tup <= fr->fr_dtop))
383 else if (!--i && /* In range */
384 (tup <= po || tup >= fr->fr_dtop))
388 * compare source ports
390 if (err && (i = (int)fr->fr_scmp)) {
392 tup = fin->fin_data[0];
393 if (!--i && tup != po)
395 else if (!--i && tup == po)
397 else if (!--i && tup >= po)
399 else if (!--i && tup <= po)
401 else if (!--i && tup > po)
403 else if (!--i && tup < po)
405 else if (!--i && /* Out of range */
406 (tup >= po && tup <= fr->fr_stop))
408 else if (!--i && /* In range */
409 (tup <= po || tup >= fr->fr_stop))
414 * If we don't have all the TCP/UDP header, then how can we
415 * expect to do any sort of match on it ? If we were looking for
416 * TCP flags, then NO match. If not, then match (which should
417 * satisfy the "short" class too).
419 if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
420 if (fin->fin_fi.fi_fl & FI_SHORT)
421 return !(fr->fr_tcpf | fr->fr_tcpfm);
423 * Match the flags ? If not, abort this match.
426 fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
427 FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
428 fr->fr_tcpfm, fr->fr_tcpf));
436 * Check the input/output list of rules for a match and result.
437 * Could be per interface, but this gets real nasty when you don't have
440 int fr_scanlist(pass, ip, fin, m)
443 register fr_info_t *fin;
446 register struct frentry *fr;
447 register fr_ip_t *fi = &fin->fin_fi;
448 int rulen, portcmp = 0, off, skip = 0, logged = 0;
455 off = ip->ip_off & IP_OFFMASK;
456 pass |= (fi->fi_fl << 24);
458 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
461 for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
467 * In all checks below, a null (zero) value in the
468 * filter struture is taken to mean a wildcard.
470 * check that we are working for the right interface
474 if (fin->fin_out != 0) {
476 fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) ||
477 (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp))
481 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
484 if (opts & (OPT_VERBOSE|OPT_DEBUG))
486 FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' :
487 (pass & FR_AUTH) ? 'a' : 'b'));
488 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
493 register u_32_t *ld, *lm, *lip;
497 lm = (u_32_t *)&fr->fr_mip;
498 ld = (u_32_t *)&fr->fr_ip;
499 i = ((lip[0] & lm[0]) != ld[0]);
500 FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
501 lip[0], lm[0], ld[0]));
502 i |= ((lip[1] & lm[1]) != ld[1]) << 19;
503 i ^= (fr->fr_flags & FR_NOTSRCIP);
504 FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
505 lip[1], lm[1], ld[1]));
506 i |= ((lip[2] & lm[2]) != ld[2]) << 20;
507 i ^= (fr->fr_flags & FR_NOTDSTIP);
508 FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
509 lip[2], lm[2], ld[2]));
510 i |= ((lip[3] & lm[3]) != ld[3]);
511 FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
512 lip[3], lm[3], ld[3]));
513 i |= ((lip[4] & lm[4]) != ld[4]);
514 FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
515 lip[4], lm[4], ld[4]));
521 * If a fragment, then only the first has what we're looking
524 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
527 if (fi->fi_fl & FI_TCPUDP) {
528 if (!fr_tcpudpchk(fr, fin))
530 } else if (fr->fr_icmpm || fr->fr_icmp) {
531 if ((fi->fi_p != IPPROTO_ICMP) || off ||
534 if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) {
535 FR_DEBUG(("i. %#x & %#x != %#x\n",
536 fin->fin_data[0], fr->fr_icmpm,
543 * Just log this packet...
545 passt = fr->fr_flags;
546 if ((passt & FR_CALLNOW) && fr->fr_func)
547 passt = (*fr->fr_func)(passt, ip, fin);
550 if ((passt & FR_LOGMASK) == FR_LOG) {
551 if (!IPLLOG(passt, ip, fin, m)) {
552 ATOMIC_INC(frstats[fin->fin_out].fr_skip);
554 ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
557 #endif /* IPFILTER_LOG */
558 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
560 FR_DEBUG(("pass %#x\n", pass));
561 ATOMIC_INC(fr->fr_hits);
562 if (pass & FR_ACCOUNT)
563 fr->fr_bytes += (U_QUAD_T)ip->ip_len;
565 fin->fin_icode = fr->fr_icode;
566 fin->fin_rule = rulen;
567 fin->fin_group = fr->fr_group;
569 fin->fin_fr = fr->fr_grp;
570 pass = fr_scanlist(pass, ip, fin, m);
571 if (fin->fin_fr == NULL) {
572 fin->fin_rule = rulen;
573 fin->fin_group = fr->fr_group;
576 if (pass & FR_DONTCACHE)
583 pass |= FR_DONTCACHE;
589 * frcheck - filter check
590 * check using source and destination addresses/ports in a packet whether
591 * or not to pass it on or not.
593 int fr_check(ip, hlen, ifp, out
594 #if defined(_KERNEL) && SOLARIS
607 * The above really sucks, but short of writing a diff
609 fr_info_t frinfo, *fc;
610 register fr_info_t *fin = &frinfo;
611 frentry_t *fr = NULL;
612 int changed, error = EHOSTUNREACH;
614 #if !SOLARIS || !defined(_KERNEL)
615 register mb_t *m = *mp;
620 # if !defined(__SVR4) && !defined(__svr4__)
622 char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
628 * XXX For now, IP Filter and fast-forwarding of cached flows
629 * XXX are mutually exclusive. Eventually, IP Filter should
630 * XXX get a "can-fast-forward" filter rule.
632 m->m_flags &= ~M_CANFASTFWD;
633 # endif /* M_CANFASTFWD */
636 * disable delayed checksums.
638 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
640 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
643 if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
644 ip->ip_p == IPPROTO_ICMP)) {
647 if ((ip->ip_off & IP_OFFMASK) == 0)
651 plen = sizeof(tcphdr_t);
654 plen = sizeof(udphdr_t);
656 /* 96 - enough for complete ICMP error IP header */
658 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
661 up = MIN(hlen + plen, ip->ip_len);
665 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
666 if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
667 ATOMIC_INC(frstats[out].fr_pull[1]);
670 m_copydata(m, 0, up, hbuf);
671 ATOMIC_INC(frstats[out].fr_pull[0]);
675 if ((*mp = m_pullup(m, up)) == 0) {
676 ATOMIC_INC(frstats[out].fr_pull[1]);
679 ATOMIC_INC(frstats[out].fr_pull[0]);
681 ip = mtod(m, ip_t *);
689 # endif /* !defined(__SVR4) && !defined(__svr4__) */
701 * Be careful here: ip_id is in network byte order when called
705 ip->ip_id = ntohs(ip->ip_id);
706 fr_makefrip(hlen, ip, fin);
712 READ_ENTER(&ipf_mutex);
714 if (fin->fin_fi.fi_fl & FI_SHORT)
715 ATOMIC_INC(frstats[out].fr_short);
718 * Check auth now. This, combined with the check below to see if apass
719 * is 0 is to ensure that we don't count the packet twice, which can
720 * otherwise occur when we reprocess it. As it is, we only count it
721 * after it has no auth. table matchup. This also stops NAT from
722 * occuring until after the packet has been auth'd.
724 apass = fr_checkauth(ip, fin);
727 changed = ip_natin(ip, fin);
728 if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
729 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
730 ATOMIC_INC(frstats[0].fr_acct);
734 if (apass || (!(fr = ipfr_knownfrag(ip, fin)) &&
735 !(fr = fr_checkstate(ip, fin)))) {
737 * If a packet is found in the auth table, then skip checking
738 * the access lists for permission but we do need to consider
739 * the result as if it were from the ACL's.
743 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
745 * copy cached data so we can unlock the mutex
748 bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
749 ATOMIC_INC(frstats[out].fr_chit);
750 if ((fr = fin->fin_fr)) {
751 ATOMIC_INC(fr->fr_hits);
755 if ((fin->fin_fr = ipfilter[out][fr_active]))
756 pass = fr_scanlist(fr_pass, ip, fin, m);
757 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
758 bcopy((char *)fin, (char *)fc,
760 if (pass & FR_NOMATCH) {
761 ATOMIC_INC(frstats[out].fr_nom);
769 * If we fail to add a packet to the authorization queue,
770 * then we drop the packet later. However, if it was added
771 * then pretend we've dropped it already.
773 if ((pass & FR_AUTH))
774 if (FR_NEWAUTH(m, fin, ip, qif) != 0)
781 if (pass & FR_PREAUTH) {
782 READ_ENTER(&ipf_auth);
783 if ((fin->fin_fr = ipauth) &&
784 (pass = fr_scanlist(0, ip, fin, m))) {
785 ATOMIC_INC(fr_authstats.fas_hits);
787 ATOMIC_INC(fr_authstats.fas_miss);
789 RWLOCK_EXIT(&ipf_auth);
793 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
794 if (fin->fin_fi.fi_fl & FI_FRAG) {
795 if (ipfr_newfrag(ip, fin, pass) == -1) {
796 ATOMIC_INC(frstats[out].fr_bnfr);
798 ATOMIC_INC(frstats[out].fr_nfr);
801 ATOMIC_INC(frstats[out].fr_cfr);
804 if (pass & FR_KEEPSTATE) {
805 if (fr_addstate(ip, fin, 0) == NULL) {
806 ATOMIC_INC(frstats[out].fr_bads);
808 ATOMIC_INC(frstats[out].fr_ads);
811 } else if (fr != NULL) {
813 if (pass & FR_LOGFIRST)
814 pass &= ~(FR_LOGFIRST|FR_LOG);
817 if (fr && fr->fr_func && !(pass & FR_CALLNOW))
818 pass = (*fr->fr_func)(pass, ip, fin);
821 * Only count/translate packets which will be passed on, out the
824 if (out && (pass & FR_PASS)) {
825 if ((fin->fin_fr = ipacct[1][fr_active]) &&
826 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
827 ATOMIC_INC(frstats[1].fr_acct);
830 changed = ip_natout(ip, fin);
833 RWLOCK_EXIT(&ipf_mutex);
836 if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
837 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
838 pass |= FF_LOGNOMATCH;
839 ATOMIC_INC(frstats[out].fr_npkl);
841 } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
842 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
843 if ((pass & FR_LOGMASK) != FR_LOGP)
845 ATOMIC_INC(frstats[out].fr_ppkl);
847 } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
848 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
849 if ((pass & FR_LOGMASK) != FR_LOGB)
851 ATOMIC_INC(frstats[out].fr_bpkl);
853 if (!IPLLOG(pass, ip, fin, m)) {
854 ATOMIC_INC(frstats[out].fr_skip);
855 if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
856 (FR_PASS|FR_LOGORBLOCK))
857 pass ^= FR_PASS|FR_BLOCK;
861 #endif /* IPFILTER_LOG */
864 ip->ip_id = htons(ip->ip_id);
868 * Only allow FR_DUP to work if a rule matched - it makes no sense to
869 * set FR_DUP as a "default" as there are no instructions about where
870 * to send the packet.
872 if (fr && (pass & FR_DUP))
877 mc = m_copy(m, 0, M_COPYALL);
883 if (pass & FR_PASS) {
884 ATOMIC_INC(frstats[out].fr_pass);
885 } else if (pass & FR_BLOCK) {
886 ATOMIC_INC(frstats[out].fr_block);
888 * Should we return an ICMP packet to indicate error
889 * status passing through the packet filter ?
890 * WARNING: ICMP error packets AND TCP RST packets should
891 * ONLY be sent in repsonse to incoming packets. Sending them
892 * in response to outbound packets can result in a panic on
893 * some operating systems.
897 if (pass & FR_RETICMP) {
900 if ((pass & FR_RETMASK) == FR_FAKEICMP)
905 ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
908 ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
911 ATOMIC_INC(frstats[0].fr_ret);
912 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
913 !(fin->fin_fi.fi_fl & FI_SHORT)) {
914 if (SEND_RESET(ip, qif, ifp, fin) == 0) {
915 ATOMIC_INC(frstats[1].fr_ret);
919 if ((pass & FR_RETMASK) == FR_RETICMP) {
920 verbose("- ICMP unreachable sent\n");
921 ATOMIC_INC(frstats[0].fr_ret);
922 } else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
923 verbose("- forged ICMP unreachable sent\n");
924 ATOMIC_INC(frstats[0].fr_ret);
925 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
926 !(fin->fin_fi.fi_fl & FI_SHORT)) {
927 verbose("- TCP RST sent\n");
928 ATOMIC_INC(frstats[1].fr_ret);
932 if (pass & FR_RETRST)
938 * If we didn't drop off the bottom of the list of rules (and thus
939 * the 'current' rule fr is not NULL), then we may have some extra
940 * instructions about what to do with a packet.
941 * Once we're finished return to our caller, freeing the packet if
942 * we are dropping it (* BSD ONLY *).
948 frdest_t *fdp = &fr->fr_tif;
950 if (((pass & FR_FASTROUTE) && !out) ||
951 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
952 if (ipfr_fastroute(m, fin, fdp) == 0)
956 ipfr_fastroute(mc, fin, &fr->fr_dif);
958 if (!(pass & FR_PASS) && m)
961 else if (changed && up && m)
962 m_copyback(m, 0, up, hbuf);
965 # else /* !SOLARIS */
967 frdest_t *fdp = &fr->fr_tif;
969 if (((pass & FR_FASTROUTE) && !out) ||
970 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
971 if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0)
975 ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
977 # endif /* !SOLARIS */
978 return (pass & FR_PASS) ? 0 : error;
980 if (pass & FR_NOMATCH)
993 * addr should be 16bit aligned and len is in bytes.
996 u_short ipf_cksum(addr, len)
997 register u_short *addr;
1000 register u_32_t sum = 0;
1002 for (sum = 0; len > 1; len -= 2)
1005 /* mop up an odd byte, if necessary */
1007 sum += *(u_char *)addr;
1010 * add back carry outs from top 16 bits to low 16 bits
1012 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1013 sum += (sum >> 16); /* add carry */
1014 return (u_short)(~sum);
1019 * NB: This function assumes we've pullup'd enough for all of the IP header
1020 * and the TCP header. We also assume that data blocks aren't allocated in
1023 u_short fr_tcpsum(m, ip, tcp)
1028 u_short *sp, slen, ts;
1033 * Add up IP Header portion
1035 hlen = ip->ip_hl << 2;
1036 slen = ip->ip_len - hlen;
1037 sum = htons((u_short)ip->ip_p);
1039 sp = (u_short *)&ip->ip_src;
1040 sum += *sp++; /* ip_src */
1042 sum += *sp++; /* ip_dst */
1048 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */
1049 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1050 sum2 = ~sum2 & 0xffff;
1051 # else /* SOLARIS */
1052 # if defined(BSD) || defined(sun)
1059 sum2 = in_cksum(m, slen);
1067 * Both sum and sum2 are partial sums, so combine them together.
1069 sum = (sum & 0xffff) + (sum >> 16);
1070 sum = ~sum & 0xffff;
1072 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1073 # else /* defined(BSD) || defined(sun) */
1079 u_short len = ip->ip_len;
1085 * Add up IP Header portion
1087 sp = (u_short *)&ip->ip_src;
1088 len -= (ip->ip_hl << 2);
1089 sum = ntohs(IPPROTO_TCP);
1091 sum += *sp++; /* ip_src */
1093 sum += *sp++; /* ip_dst */
1095 if (sp != (u_short *)tcp)
1096 sp = (u_short *)tcp;
1097 sum += *sp++; /* sport */
1098 sum += *sp++; /* dport */
1099 sum += *sp++; /* seq */
1101 sum += *sp++; /* ack */
1103 sum += *sp++; /* off */
1104 sum += *sp++; /* win */
1105 sum += *sp++; /* Skip over checksum */
1106 sum += *sp++; /* urp */
1110 * In case we had to copy the IP & TCP header out of mbufs,
1111 * skip over the mbuf bits which are the header
1113 if ((caddr_t)ip != mtod(m, caddr_t)) {
1114 hlen = (caddr_t)sp - (caddr_t)ip;
1116 add = MIN(hlen, m->m_len);
1117 sp = (u_short *)(mtod(m, caddr_t) + add);
1119 if (add == m->m_len) {
1124 sp = mtod(m, u_short *);
1126 PANIC((!m),("fr_tcpsum(1): not enough data"));
1132 if (!(len -= sizeof(*tcp)))
1135 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
1137 PANIC((!m),("fr_tcpsum(2): not enough data"));
1138 sp = mtod(m, u_short *);
1140 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
1141 bytes.c[0] = *(u_char *)sp;
1143 PANIC((!m),("fr_tcpsum(3): not enough data"));
1144 sp = mtod(m, u_short *);
1145 bytes.c[1] = *(u_char *)sp;
1147 sp = (u_short *)((u_char *)sp + 1);
1149 if ((u_long)sp & 1) {
1150 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
1157 sum += ntohs(*(u_char *)sp << 8);
1159 while (sum > 0xffff)
1160 sum = (sum & 0xffff) + (sum >> 16);
1161 sum2 = (u_short)(~sum & 0xffff);
1163 # endif /* defined(BSD) || defined(sun) */
1164 # endif /* SOLARIS */
1173 #if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1175 * Copyright (c) 1982, 1986, 1988, 1991, 1993
1176 * The Regents of the University of California. All rights reserved.
1178 * Redistribution and use in source and binary forms, with or without
1179 * modification, are permitted provided that the following conditions
1181 * 1. Redistributions of source code must retain the above copyright
1182 * notice, this list of conditions and the following disclaimer.
1183 * 2. Redistributions in binary form must reproduce the above copyright
1184 * notice, this list of conditions and the following disclaimer in the
1185 * documentation and/or other materials provided with the distribution.
1186 * 3. All advertising materials mentioning features or use of this software
1187 * must display the following acknowledgement:
1188 * This product includes software developed by the University of
1189 * California, Berkeley and its contributors.
1190 * 4. Neither the name of the University nor the names of its contributors
1191 * may be used to endorse or promote products derived from this software
1192 * without specific prior written permission.
1194 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1195 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1196 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1197 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1198 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1199 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1200 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1201 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1202 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1203 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1206 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1207 * $Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $
1210 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1211 * continuing for "len" bytes, into the indicated buffer.
1214 m_copydata(m, off, len, cp)
1220 register unsigned count;
1222 if (off < 0 || len < 0)
1223 panic("m_copydata");
1226 panic("m_copydata");
1234 panic("m_copydata");
1235 count = MIN(m->m_len - off, len);
1236 bcopy(mtod(m, caddr_t) + off, cp, count);
1247 * Copy data from a buffer back into the indicated mbuf chain,
1248 * starting "off" bytes from the beginning, extending the mbuf
1249 * chain if necessary.
1252 m_copyback(m0, off, len, cp)
1259 register struct mbuf *m = m0, *n;
1264 while (off > (mlen = m->m_len)) {
1267 if (m->m_next == 0) {
1268 n = m_getclr(M_DONTWAIT, m->m_type);
1271 n->m_len = min(MLEN, len + off);
1277 mlen = min (m->m_len - off, len);
1278 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1286 if (m->m_next == 0) {
1287 n = m_get(M_DONTWAIT, m->m_type);
1290 n->m_len = min(MLEN, len);
1297 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1298 m->m_pkthdr.len = totlen;
1303 #endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1306 frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
1313 frgroup_t *fg, **fgp;
1315 if (which == IPL_LOGAUTH)
1316 fgp = &ipfgroups[2][set];
1317 else if (flags & FR_ACCOUNT)
1318 fgp = &ipfgroups[1][set];
1319 else if (flags & (FR_OUTQUE|FR_INQUE))
1320 fgp = &ipfgroups[0][set];
1326 if (fg->fg_num == num)
1336 frgroup_t *fr_addgroup(num, fp, which, set)
1342 frgroup_t *fg, **fgp;
1344 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
1347 KMALLOC(fg, frgroup_t *);
1349 fg->fg_num = num & 0xffff;
1352 fg->fg_start = &fp->fr_grp;
1359 void fr_delgroup(num, flags, which, set)
1365 frgroup_t *fg, **fgp;
1367 if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
1377 * recursively flush rules from the list, descending groups as they are
1378 * encountered. if a rule is the head of a group and it has lost all its
1379 * group members, then also delete the group reference.
1381 static int frflushlist(set, unit, nfreedp, listp)
1387 register int freed = 0, i;
1388 register frentry_t *fp;
1390 while ((fp = *listp)) {
1391 *listp = fp->fr_next;
1393 i = frflushlist(set, unit, nfreedp, &fp->fr_grp);
1394 MUTEX_ENTER(&ipf_rw);
1396 MUTEX_EXIT(&ipf_rw);
1399 ATOMIC_DEC(fp->fr_ref);
1400 if (fp->fr_grhead) {
1401 fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags,
1403 fp->fr_grhead = NULL;
1405 if (fp->fr_ref == 0) {
1416 int frflush(unit, flags)
1420 int flushed = 0, set;
1422 if (unit != IPL_LOGIPF)
1424 WRITE_ENTER(&ipf_mutex);
1425 bzero((char *)frcache, sizeof(frcache[0]) * 2);
1428 if (flags & FR_INACTIVE)
1431 if (flags & FR_OUTQUE) {
1432 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
1433 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
1435 if (flags & FR_INQUE) {
1436 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
1437 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
1439 RWLOCK_EXIT(&ipf_mutex);
1444 char *memstr(src, dst, slen, dlen)
1450 while (dlen >= slen) {
1451 if (bcmp(src, dst, slen) == 0) {
1462 void fixskip(listp, rp, addremove)
1463 frentry_t **listp, *rp;
1467 int rules = 0, rn = 0;
1469 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
1475 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
1476 if (fp->fr_skip && (rn + fp->fr_skip >= rules))
1477 fp->fr_skip += addremove;
1483 * count consecutive 1's in bit mask. If the mask generated by counting
1484 * consecutive 1's is different to that passed, return -1, else return #
1493 ip = ipn = ntohl(ip);
1494 for (i = 32; i; i--, ipn *= 2)
1495 if (ipn & 0x80000000)
1500 for (i = 32, j = cnt; i; i--, j--) {
1512 * return the first IP Address associated with an interface
1514 int fr_ifpaddr(ifptr, inp)
1516 struct in_addr *inp;
1521 struct ifnet *ifp = ifptr;
1526 in.s_addr = ill->ill_ipif->ipif_local_addr;
1527 # else /* SOLARIS */
1532 struct sockaddr_in *sin;
1534 # if (__FreeBSD_version >= 300000)
1535 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1537 # if defined(__NetBSD__) || defined(__OpenBSD__)
1538 ifa = ifp->if_addrlist.tqh_first;
1540 # if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
1541 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa;
1543 ifa = ifp->if_addrlist;
1545 # endif /* __NetBSD__ || __OpenBSD__ */
1546 # endif /* __FreeBSD_version >= 300000 */
1547 # if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK))
1548 sin = (struct sockaddr_in *)&ifa->ifa_addr;
1550 sin = (struct sockaddr_in *)ifa->ifa_addr;
1551 while (sin && ifa &&
1552 sin->sin_family != AF_INET) {
1553 # if (__FreeBSD_version >= 300000)
1554 ifa = TAILQ_NEXT(ifa, ifa_link);
1556 # if defined(__NetBSD__) || defined(__OpenBSD__)
1557 ifa = ifa->ifa_list.tqe_next;
1559 ifa = ifa->ifa_next;
1561 # endif /* __FreeBSD_version >= 300000 */
1563 sin = (struct sockaddr_in *)ifa->ifa_addr;
1569 # endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
1572 # endif /* SOLARIS */
1578 static void frsynclist(fr)
1579 register frentry_t *fr;
1581 for (; fr; fr = fr->fr_next) {
1582 if (fr->fr_ifa != NULL) {
1583 fr->fr_ifa = GETUNIT(fr->fr_ifname);
1584 if (fr->fr_ifa == NULL)
1585 fr->fr_ifa = (void *)-1;
1588 frsynclist(fr->fr_grp);
1595 register struct ifnet *ifp;
1598 # if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
1599 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
1600 # if (NetBSD >= 199905) || defined(__OpenBSD__)
1601 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
1603 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
1606 for (ifp = ifnet; ifp; ifp = ifp->if_next)
1614 WRITE_ENTER(&ipf_mutex);
1615 frsynclist(ipacct[0][fr_active]);
1616 frsynclist(ipacct[1][fr_active]);
1617 frsynclist(ipfilter[0][fr_active]);
1618 frsynclist(ipfilter[1][fr_active]);
1619 RWLOCK_EXIT(&ipf_mutex);
1626 * return the first IP Address associated with an interface
1628 int fr_ifpaddr(ifptr, inp)
1630 struct in_addr *inp;