]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/fil.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (C) 1993-1997 by Darren Reed.
25 * Redistribution and use in source and binary forms are permitted
26 * provided that this notice is preserved and due credit is given
27 * to the original author and the contributors.
30 /* static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; */
33 #include "opt_ipfilter.h"
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
40 #if !defined(__FreeBSD__)
41 # include <sys/ioctl.h>
44 # include <sys/systm.h>
47 #if !defined(__SVR4) && !defined(__svr4__)
49 # include <sys/mbuf.h>
52 # include <sys/byteorder.h>
53 # include <sys/dditypes.h>
54 # include <sys/stream.h>
56 #if defined(__FreeBSD__)
57 # include <sys/malloc.h>
60 # include <sys/protosw.h>
61 # include <sys/socket.h>
67 #include <net/route.h>
68 #include <netinet/in.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/ip.h>
72 # include <netinet/ip_var.h>
74 #include <netinet/tcp.h>
75 #include <netinet/udp.h>
76 #include <netinet/ip_icmp.h>
77 #include "netinet/ip_compat.h"
78 #include <netinet/tcpip.h>
79 #include "netinet/ip_fil.h"
80 #include "netinet/ip_proxy.h"
81 #include "netinet/ip_nat.h"
82 #include "netinet/ip_frag.h"
83 #include "netinet/ip_state.h"
84 #include "netinet/ip_auth.h"
86 #define MIN(a,b) (((a)<(b))?(a):(b))
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) 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)
104 # define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(ip)
106 # define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(b, ip, if)
108 #else /* #ifndef KERNEL */
109 # define FR_IFVERBOSE(ex,second,verb_pr) ;
110 # define FR_IFDEBUG(ex,second,verb_pr) ;
111 # define FR_VERBOSE(verb_pr)
112 # define FR_DEBUG(verb_pr)
113 # define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
114 # if SOLARIS || defined(__sgi)
115 extern kmutex_t ipf_mutex
, ipf_auth
;
118 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
120 # define SEND_RESET(ip, qif, if) send_reset(ip, qif)
121 # define ICMP_ERROR(b, ip, t, c, if, src) \
122 icmp_error(ip, t, c, if, src)
124 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
126 # define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip,\
129 # define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip)
132 # define ICMP_ERROR(b, ip, t, c, if, src) \
133 icmp_error(b, t, c, if, src, if)
137 # define ICMP_ERROR(b, ip, t, c, if, src) icmp_send(b,t,c,0,if)
139 # define ICMP_ERROR(b, ip, t, c, if, src) \
140 icmp_error(mtod(b, ip_t *), t, c, if, src)
143 # define ICMP_ERROR(b, ip, t, c, if, src) \
144 icmp_error(b, t, c, (src).s_addr, if)
145 # endif /* BSD < 199103 */
147 # endif /* SOLARIS || __sgi */
151 struct filterstats frstats
[2] = {{0,0,0,0,0},{0,0,0,0,0}};
152 struct frentry
*ipfilter
[2][2] = { { NULL
, NULL
}, { NULL
, NULL
} },
153 *ipacct
[2][2] = { { NULL
, NULL
}, { NULL
, NULL
} };
154 struct frgroup
*ipfgroups
[3][2];
155 int fr_flags
= IPF_LOGGING
, fr_active
= 0;
156 #if defined(IPFILTER_DEFAULT_BLOCK)
157 int fr_pass
= FR_NOMATCH
|FR_BLOCK
;
159 int fr_pass
= (IPF_DEFAULT_PASS
|FR_NOMATCH
);
162 fr_info_t frcache
[2];
164 static void fr_makefrip
__P((int, ip_t
*, fr_info_t
*));
165 static int fr_tcpudpchk
__P((frentry_t
*, fr_info_t
*));
166 static int frflushlist
__P((int, int, int *, frentry_t
*, frentry_t
**));
170 * bit values for identifying presence of individual IP options
172 static struct optlist ipopts
[20] = {
173 { IPOPT_NOP
, 0x000001 },
174 { IPOPT_RR
, 0x000002 },
175 { IPOPT_ZSU
, 0x000004 },
176 { IPOPT_MTUP
, 0x000008 },
177 { IPOPT_MTUR
, 0x000010 },
178 { IPOPT_ENCODE
, 0x000020 },
179 { IPOPT_TS
, 0x000040 },
180 { IPOPT_TR
, 0x000080 },
181 { IPOPT_SECURITY
, 0x000100 },
182 { IPOPT_LSRR
, 0x000200 },
183 { IPOPT_E_SEC
, 0x000400 },
184 { IPOPT_CIPSO
, 0x000800 },
185 { IPOPT_SATID
, 0x001000 },
186 { IPOPT_SSRR
, 0x002000 },
187 { IPOPT_ADDEXT
, 0x004000 },
188 { IPOPT_VISA
, 0x008000 },
189 { IPOPT_IMITD
, 0x010000 },
190 { IPOPT_EIP
, 0x020000 },
191 { IPOPT_FINN
, 0x040000 },
196 * bit values for identifying presence of individual IP security options
198 static struct optlist secopt
[8] = {
199 { IPSO_CLASS_RES4
, 0x01 },
200 { IPSO_CLASS_TOPS
, 0x02 },
201 { IPSO_CLASS_SECR
, 0x04 },
202 { IPSO_CLASS_RES3
, 0x08 },
203 { IPSO_CLASS_CONF
, 0x10 },
204 { IPSO_CLASS_UNCL
, 0x20 },
205 { IPSO_CLASS_RES2
, 0x40 },
206 { IPSO_CLASS_RES1
, 0x80 }
211 * compact the IP header into a structure which contains just the info.
212 * which is useful for comparing IP headers with.
214 static void fr_makefrip(hlen
, ip
, fin
)
222 fr_ip_t
*fi
= &fin
->fin_fi
;
223 u_short optmsk
= 0, secmsk
= 0, auth
= 0;
229 fin
->fin_data
[0] = 0;
230 fin
->fin_data
[1] = 0;
233 fin
->fin_id
= ip
->ip_id
;
235 fin
->fin_icode
= ipl_unreach
;
238 fi
->fi_tos
= ip
->ip_tos
;
239 fin
->fin_hlen
= hlen
;
240 fin
->fin_dlen
= ip
->ip_len
- hlen
;
241 tcp
= (tcphdr_t
*)((char *)ip
+ hlen
);
242 icmp
= (icmphdr_t
*)tcp
;
243 fin
->fin_dp
= (void *)tcp
;
244 (*(((u_short
*)fi
) + 1)) = (*(((u_short
*)ip
) + 4));
245 (*(((u_32_t
*)fi
) + 1)) = (*(((u_32_t
*)ip
) + 3));
246 (*(((u_32_t
*)fi
) + 2)) = (*(((u_32_t
*)ip
) + 4));
248 fi
->fi_fl
= (hlen
> sizeof(ip_t
)) ? FI_OPTIONS
: 0;
249 off
= (ip
->ip_off
& 0x1fff) << 3;
250 if (ip
->ip_off
& 0x3fff)
251 fi
->fi_fl
|= FI_FRAG
;
256 int minicmpsz
= sizeof(struct icmp
);
258 if (!off
&& ip
->ip_len
> ICMP_MINLEN
+ hlen
&&
259 (icmp
->icmp_type
== ICMP_ECHOREPLY
||
260 icmp
->icmp_type
== ICMP_UNREACH
))
261 minicmpsz
= ICMP_MINLEN
;
262 if ((!(ip
->ip_len
>= hlen
+ minicmpsz
) && !off
) ||
263 (off
&& off
< sizeof(struct icmp
)))
264 fi
->fi_fl
|= FI_SHORT
;
265 if (fin
->fin_dlen
> 1)
266 fin
->fin_data
[0] = *(u_short
*)tcp
;
270 fi
->fi_fl
|= FI_TCPUDP
;
271 if ((!IPMINLEN(ip
, tcphdr
) && !off
) ||
272 (off
&& off
< sizeof(struct tcphdr
)))
273 fi
->fi_fl
|= FI_SHORT
;
274 if (!(fi
->fi_fl
& FI_SHORT
) && !off
)
275 fin
->fin_tcpf
= tcp
->th_flags
;
278 fi
->fi_fl
|= FI_TCPUDP
;
279 if ((!IPMINLEN(ip
, udphdr
) && !off
) ||
280 (off
&& off
< sizeof(struct udphdr
)))
281 fi
->fi_fl
|= FI_SHORT
;
283 if (!off
&& (fin
->fin_dlen
> 3)) {
284 fin
->fin_data
[0] = ntohs(tcp
->th_sport
);
285 fin
->fin_data
[1] = ntohs(tcp
->th_dport
);
293 for (s
= (u_char
*)(ip
+ 1), hlen
-= sizeof(*ip
); hlen
; ) {
296 ol
= (opt
== IPOPT_NOP
) ? 1 : (int)*(s
+1);
297 if (opt
> 1 && (ol
< 2 || ol
> hlen
))
299 for (i
= 9, mv
= 4; mv
>= 0; ) {
301 if (opt
== (u_char
)op
->ol_val
) {
302 optmsk
|= op
->ol_bit
;
303 if (opt
== IPOPT_SECURITY
) {
308 sec
= *(s
+ 2); /* classification */
309 for (j
= 3, m
= 2; m
>= 0; ) {
311 if (sec
== sp
->ol_val
) {
312 secmsk
|= sp
->ol_bit
;
318 if (sec
< sp
->ol_val
)
326 if (opt
< op
->ol_val
)
334 if (auth
&& !(auth
& 0x0100))
336 fi
->fi_optmsk
= optmsk
;
337 fi
->fi_secmsk
= secmsk
;
343 * check an IP packet for TCP/UDP characteristics such as ports and flags.
345 static int fr_tcpudpchk(fr
, fin
)
349 register u_short po
, tup
;
351 register int err
= 1;
354 * Both ports should *always* be in the first fragment.
355 * So far, I cannot find any cases where they can not be.
357 * compare destination ports
359 if ((i
= (int)fr
->fr_dcmp
)) {
361 tup
= fin
->fin_data
[1];
363 * Do opposite test to that required and
364 * continue if that succeeds.
366 if (!--i
&& tup
!= po
) /* EQUAL */
368 else if (!--i
&& tup
== po
) /* NOTEQUAL */
370 else if (!--i
&& tup
>= po
) /* LESSTHAN */
372 else if (!--i
&& tup
<= po
) /* GREATERTHAN */
374 else if (!--i
&& tup
> po
) /* LT or EQ */
376 else if (!--i
&& tup
< po
) /* GT or EQ */
378 else if (!--i
&& /* Out of range */
379 (tup
>= po
&& tup
<= fr
->fr_dtop
))
381 else if (!--i
&& /* In range */
382 (tup
<= po
|| tup
>= fr
->fr_dtop
))
386 * compare source ports
388 if (err
&& (i
= (int)fr
->fr_scmp
)) {
390 tup
= fin
->fin_data
[0];
391 if (!--i
&& tup
!= po
)
393 else 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
&& /* Out of range */
404 (tup
>= po
&& tup
<= fr
->fr_stop
))
406 else if (!--i
&& /* In range */
407 (tup
<= po
|| tup
>= fr
->fr_stop
))
412 * If we don't have all the TCP/UDP header, then how can we
413 * expect to do any sort of match on it ? If we were looking for
414 * TCP flags, then NO match. If not, then match (which should
415 * satisfy the "short" class too).
417 if (err
&& (fin
->fin_fi
.fi_p
== IPPROTO_TCP
)) {
418 if (fin
->fin_fi
.fi_fl
& FI_SHORT
)
419 return !(fr
->fr_tcpf
| fr
->fr_tcpfm
);
421 * Match the flags ? If not, abort this match.
424 fr
->fr_tcpf
!= (fin
->fin_tcpf
& fr
->fr_tcpfm
)) {
425 FR_DEBUG(("f. %#x & %#x != %#x\n", fin
->fin_tcpf
,
426 fr
->fr_tcpfm
, fr
->fr_tcpf
));
434 * Check the input/output list of rules for a match and result.
435 * Could be per interface, but this gets real nasty when you don't have
438 int fr_scanlist(pass
, ip
, fin
, m
)
441 register fr_info_t
*fin
;
444 register struct frentry
*fr
;
445 register fr_ip_t
*fi
= &fin
->fin_fi
;
446 int rulen
, portcmp
= 0, off
, skip
= 0;
452 off
= ip
->ip_off
& 0x1fff;
453 pass
|= (fi
->fi_fl
<< 24);
455 if ((fi
->fi_fl
& FI_TCPUDP
) && (fin
->fin_dlen
> 3) && !off
)
458 for (rulen
= 0; fr
; fr
= fr
->fr_next
, rulen
++) {
464 * In all checks below, a null (zero) value in the
465 * filter struture is taken to mean a wildcard.
467 * check that we are working for the right interface
470 if (fr
->fr_ifa
&& fr
->fr_ifa
!= fin
->fin_ifp
)
473 if (opts
& (OPT_VERBOSE
|OPT_DEBUG
))
475 FR_VERBOSE(("%c", (pass
& FR_PASS
) ? 'p' :
476 (pass
& FR_AUTH
) ? 'a' : 'b'));
477 if (fr
->fr_ifa
&& fr
->fr_ifa
!= fin
->fin_ifp
)
482 register u_32_t
*ld
, *lm
, *lip
;
486 lm
= (u_32_t
*)&fr
->fr_mip
;
487 ld
= (u_32_t
*)&fr
->fr_ip
;
488 i
= ((lip
[0] & lm
[0]) != ld
[0]);
489 FR_IFDEBUG(i
,continue,("0. %#08x & %#08x != %#08x\n",
490 lip
[0], lm
[0], ld
[0]));
491 i
|= ((lip
[1] & lm
[1]) != ld
[1]) << 21;
492 FR_IFDEBUG(i
,continue,("1. %#08x & %#08x != %#08x\n",
493 lip
[1], lm
[1], ld
[1]));
494 i
|= ((lip
[2] & lm
[2]) != ld
[2]) << 22;
495 FR_IFDEBUG(i
,continue,("2. %#08x & %#08x != %#08x\n",
496 lip
[2], lm
[2], ld
[2]));
497 i
|= ((lip
[3] & lm
[3]) != ld
[3]);
498 FR_IFDEBUG(i
,continue,("3. %#08x & %#08x != %#08x\n",
499 lip
[3], lm
[3], ld
[3]));
500 i
|= ((lip
[4] & lm
[4]) != ld
[4]);
501 FR_IFDEBUG(i
,continue,("4. %#08x & %#08x != %#08x\n",
502 lip
[4], lm
[4], ld
[4]));
503 i
^= (fi
->fi_fl
& (FR_NOTSRCIP
|FR_NOTDSTIP
));
509 * If a fragment, then only the first has what we're looking
512 if (!portcmp
&& (fr
->fr_dcmp
|| fr
->fr_scmp
|| fr
->fr_tcpf
||
515 if (fi
->fi_fl
& FI_TCPUDP
) {
516 if (!fr_tcpudpchk(fr
, fin
))
518 } else if (fr
->fr_icmpm
|| fr
->fr_icmp
) {
519 if ((fi
->fi_p
!= IPPROTO_ICMP
) || off
||
522 if ((fin
->fin_data
[0] & fr
->fr_icmpm
) != fr
->fr_icmp
) {
523 FR_DEBUG(("i. %#x & %#x != %#x\n",
524 fin
->fin_data
[0], fr
->fr_icmpm
,
531 * Just log this packet...
533 if (!(skip
= fr
->fr_skip
))
535 if ((pass
& FR_CALLNOW
) && fr
->fr_func
)
536 pass
= (*fr
->fr_func
)(pass
, ip
, fin
);
538 if ((pass
& FR_LOGMASK
) == FR_LOG
) {
539 if (!IPLLOG(fr
->fr_flags
, ip
, fin
, m
))
540 frstats
[fin
->fin_out
].fr_skip
++;
541 frstats
[fin
->fin_out
].fr_pkl
++;
543 #endif /* IPFILTER_LOG */
544 FR_DEBUG(("pass %#x\n", pass
));
546 if (pass
& FR_ACCOUNT
)
547 fr
->fr_bytes
+= (U_QUAD_T
)ip
->ip_len
;
549 fin
->fin_icode
= fr
->fr_icode
;
550 fin
->fin_rule
= rulen
;
551 fin
->fin_group
= fr
->fr_group
;
554 fin
->fin_fr
= fr
->fr_grp
;
555 pass
= fr_scanlist(pass
, ip
, fin
, m
);
556 if (fin
->fin_fr
== NULL
) {
557 fin
->fin_rule
= rulen
;
558 fin
->fin_group
= fr
->fr_group
;
570 * frcheck - filter check
571 * check using source and destination addresses/pors in a packet whether
572 * or not to pass it on or not.
574 int fr_check(ip
, hlen
, ifp
, out
575 #if defined(KERNEL) && SOLARIS
588 * The above is really bad, but short of writing a diff
590 fr_info_t frinfo
, *fc
;
591 register fr_info_t
*fin
= &frinfo
;
592 frentry_t
*fr
= NULL
;
593 int pass
, changed
, apass
, error
= EHOSTUNREACH
;
594 #if !SOLARIS || !defined(KERNEL)
595 register mb_t
*m
= *mp
;
600 # if !defined(__SVR4) && !defined(__svr4__)
602 char hbuf
[(0xf << 2) + sizeof(struct icmp
) + sizeof(ip_t
) + 8];
608 * XXX For now, IP Filter and fast-forwarding of cached flows
609 * XXX are mutually exclusive. Eventually, IP Filter should
610 * XXX get a "can-fast-forward" filter rule.
612 m
->m_flags
&= ~M_CANFASTFWD
;
613 #endif /* M_CANFASTFWD */
615 if ((ip
->ip_p
== IPPROTO_TCP
|| ip
->ip_p
== IPPROTO_UDP
||
616 ip
->ip_p
== IPPROTO_ICMP
)) {
622 plen
= sizeof(tcphdr_t
);
625 plen
= sizeof(udphdr_t
);
628 /* 96 - enough for complete ICMP error IP header */
629 plen
= sizeof(struct icmp
) + sizeof(ip_t
) + 8;
632 up
= MIN(hlen
+ plen
, ip
->ip_len
);
635 #ifdef __sgi /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
636 if ((up
> sizeof(hbuf
)) || (m_length(m
) < up
)) {
637 frstats
[out
].fr_pull
[1]++;
640 m_copydata(m
, 0, up
, hbuf
);
641 frstats
[out
].fr_pull
[0]++;
645 if ((*mp
= m_pullup(m
, up
)) == 0) {
646 frstats
[out
].fr_pull
[1]++;
649 frstats
[out
].fr_pull
[0]++;
651 ip
= mtod(m
, ip_t
*);
664 fr_makefrip(hlen
, ip
, fin
);
669 MUTEX_ENTER(&ipf_mutex
);
672 * Check auth now. This, combined with the check below to see if apass
673 * is 0 is to ensure that we don't count the packet twice, which can
674 * otherwise occur when we reprocess it. As it is, we only count it
675 * after it has no auth. table matchup. This also stops NAT from
676 * occuring until after the packet has been auth'd.
678 apass
= fr_checkauth(ip
, fin
);
681 changed
= ip_natin(ip
, hlen
, fin
);
682 if (!apass
&& (fin
->fin_fr
= ipacct
[0][fr_active
]) &&
683 (FR_SCANLIST(FR_NOMATCH
, ip
, fin
, m
) & FR_ACCOUNT
))
684 frstats
[0].fr_acct
++;
687 if (apass
|| (!(pass
= ipfr_knownfrag(ip
, fin
)) &&
688 !(pass
= fr_checkstate(ip
, fin
)))) {
690 * If a packet is found in the auth table, then skip checking
691 * the access lists for permission but we do need to consider
692 * the result as if it were from the ACL's.
696 if (!bcmp((char *)fin
, (char *)fc
, FI_CSIZE
)) {
698 * copy cached data so we can unlock the mutex
701 bcopy((char *)fc
, (char *)fin
, FI_COPYSIZE
);
702 frstats
[out
].fr_chit
++;
703 if ((fr
= fin
->fin_fr
)) {
710 if ((fin
->fin_fr
= ipfilter
[out
][fr_active
]))
711 pass
= FR_SCANLIST(fr_pass
, ip
, fin
, m
);
712 bcopy((char *)fin
, (char *)fc
, FI_COPYSIZE
);
713 if (pass
& FR_NOMATCH
)
714 frstats
[out
].fr_nom
++;
721 * If we fail to add a packet to the authorization queue,
722 * then we drop the packet later. However, if it was added
723 * then pretend we've dropped it already.
725 if ((pass
& FR_AUTH
))
726 if (FR_NEWAUTH(m
, fin
, ip
, qif
) != 0)
733 if (pass
& FR_PREAUTH
) {
734 MUTEX_ENTER(&ipf_auth
);
735 if ((fin
->fin_fr
= ipauth
) &&
736 (pass
= FR_SCANLIST(0, ip
, fin
, m
)))
737 fr_authstats
.fas_hits
++;
739 fr_authstats
.fas_miss
++;
740 MUTEX_EXIT(&ipf_auth
);
743 if (pass
& FR_KEEPFRAG
) {
744 if (fin
->fin_fi
.fi_fl
& FI_FRAG
) {
745 if (ipfr_newfrag(ip
, fin
, pass
) == -1)
746 frstats
[out
].fr_bnfr
++;
748 frstats
[out
].fr_nfr
++;
750 frstats
[out
].fr_cfr
++;
752 if (pass
& FR_KEEPSTATE
) {
753 if (fr_addstate(ip
, fin
, pass
) == -1)
754 frstats
[out
].fr_bads
++;
756 frstats
[out
].fr_ads
++;
760 if (fr
&& fr
->fr_func
&& !(pass
& FR_CALLNOW
))
761 pass
= (*fr
->fr_func
)(pass
, ip
, fin
);
764 * Only count/translate packets which will be passed on, out the
767 if (out
&& (pass
& FR_PASS
)) {
768 if ((fin
->fin_fr
= ipacct
[1][fr_active
]) &&
769 (FR_SCANLIST(FR_NOMATCH
, ip
, fin
, m
) & FR_ACCOUNT
))
770 frstats
[1].fr_acct
++;
772 changed
= ip_natout(ip
, hlen
, fin
);
775 MUTEX_EXIT(&ipf_mutex
);
778 if ((fr_flags
& FF_LOGGING
) || (pass
& FR_LOGMASK
)) {
779 if ((fr_flags
& FF_LOGNOMATCH
) && (pass
& FR_NOMATCH
)) {
780 pass
|= FF_LOGNOMATCH
;
781 frstats
[out
].fr_npkl
++;
783 } else if (((pass
& FR_LOGMASK
) == FR_LOGP
) ||
784 ((pass
& FR_PASS
) && (fr_flags
& FF_LOGPASS
))) {
785 if ((pass
& FR_LOGMASK
) != FR_LOGP
)
787 frstats
[out
].fr_ppkl
++;
789 } else if (((pass
& FR_LOGMASK
) == FR_LOGB
) ||
790 ((pass
& FR_BLOCK
) && (fr_flags
& FF_LOGBLOCK
))) {
791 if ((pass
& FR_LOGMASK
) != FR_LOGB
)
793 frstats
[out
].fr_bpkl
++;
795 if (!IPLLOG(pass
, ip
, fin
, m
)) {
796 frstats
[out
].fr_skip
++;
797 if ((pass
& (FR_PASS
|FR_LOGORBLOCK
)) ==
798 (FR_PASS
|FR_LOGORBLOCK
))
799 pass
^= FR_PASS
|FR_BLOCK
;
803 #endif /* IPFILTER_LOG */
806 * Only allow FR_DUP to work if a rule matched - it makes no sense to
807 * set FR_DUP as a "default" as there are no instructions about where
808 * to send the packet.
810 if (fr
&& (pass
& FR_DUP
))
815 mc
= m_copy(m
, 0, M_COPYALL
);
822 frstats
[out
].fr_pass
++;
823 else if (pass
& FR_BLOCK
) {
824 frstats
[out
].fr_block
++;
826 * Should we return an ICMP packet to indicate error
827 * status passing through the packet filter ?
828 * WARNING: ICMP error packets AND TCP RST packets should
829 * ONLY be sent in repsonse to incoming packets. Sending them
830 * in response to outbound packets can result in a panic on
831 * some operating systems.
835 if (pass
& FR_RETICMP
) {
837 ICMP_ERROR(q
, ip
, ICMP_UNREACH
, fin
->fin_icode
,
840 ICMP_ERROR(m
, ip
, ICMP_UNREACH
, fin
->fin_icode
,
842 m
= *mp
= NULL
; /* freed by icmp_error() */
846 } else if ((pass
& FR_RETRST
) &&
847 !(fin
->fin_fi
.fi_fl
& FI_SHORT
)) {
848 if (SEND_RESET(ip
, qif
, ifp
) == 0)
852 if (pass
& FR_RETICMP
) {
853 verbose("- ICMP unreachable sent\n");
855 } else if ((pass
& FR_RETRST
) &&
856 !(fin
->fin_fi
.fi_fl
& FI_SHORT
)) {
857 verbose("- TCP RST sent\n");
862 if (pass
& FR_RETRST
)
868 * If we didn't drop off the bottom of the list of rules (and thus
869 * the 'current' rule fr is not NULL), then we may have some extra
870 * instructions about what to do with a packet.
871 * Once we're finished return to our caller, freeing the packet if
872 * we are dropping it (* BSD ONLY *).
878 frdest_t
*fdp
= &fr
->fr_tif
;
880 if ((pass
& FR_FASTROUTE
) ||
881 (fdp
->fd_ifp
&& fdp
->fd_ifp
!= (struct ifnet
*)-1)) {
882 ipfr_fastroute(m
, fin
, fdp
);
886 ipfr_fastroute(mc
, fin
, &fr
->fr_dif
);
888 if (!(pass
& FR_PASS
) && m
)
891 else if (changed
&& up
&& m
)
892 m_copyback(m
, 0, up
, hbuf
);
895 return (pass
& FR_PASS
) ? 0 : error
;
896 # else /* !SOLARIS */
898 frdest_t
*fdp
= &fr
->fr_tif
;
900 if ((pass
& FR_FASTROUTE
) ||
901 (fdp
->fd_ifp
&& fdp
->fd_ifp
!= (struct ifnet
*)-1)) {
902 ipfr_fastroute(qif
, ip
, m
, mp
, fin
, fdp
);
906 ipfr_fastroute(qif
, ip
, mc
, mp
, fin
, &fr
->fr_dif
);
908 return (pass
& FR_PASS
) ? changed
: error
;
909 # endif /* !SOLARIS */
911 if (pass
& FR_NOMATCH
)
924 * addr should be 16bit aligned and len is in bytes.
927 u_short
ipf_cksum(addr
, len
)
928 register u_short
*addr
;
931 register u_32_t sum
= 0;
933 for (sum
= 0; len
> 1; len
-= 2)
936 /* mop up an odd byte, if necessary */
938 sum
+= *(u_char
*)addr
;
941 * add back carry outs from top 16 bits to low 16 bits
943 sum
= (sum
>> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
944 sum
+= (sum
>> 16); /* add carry */
945 return (u_short
)(~sum
);
950 * NB: This function assumes we've pullup'd enough for all of the IP header
951 * and the TCP header. We also assume that data blocks aren't allocated in
954 u_short
fr_tcpsum(m
, ip
, tcp
, len
)
966 # if SOLARIS || defined(__sgi)
971 /* skip any leading M_PROTOs */
972 while(m
&& (MTYPE(m
) != M_DATA
))
974 PANIC((!m
),("fr_tcpsum: no M_DATA"));
978 * Add up IP Header portion
981 bytes
.c
[1] = IPPROTO_TCP
;
982 len
-= (ip
->ip_hl
<< 2);
984 sum
+= htons((u_short
)len
);
985 sp
= (u_short
*)&ip
->ip_src
;
990 if (sp
!= (u_short
*)tcp
)
1000 sp
+= 2; /* Skip over checksum */
1005 * In case we had to copy the IP & TCP header out of mblks,
1006 * skip over the mblk bits which are the header
1008 if ((caddr_t
)ip
!= (caddr_t
)m
->b_rptr
) {
1009 hlen
= (caddr_t
)sp
- (caddr_t
)ip
;
1011 add
= MIN(hlen
, m
->b_wptr
- m
->b_rptr
);
1012 sp
= (u_short
*)((caddr_t
)m
->b_rptr
+ add
);
1014 if ((caddr_t
)sp
>= (caddr_t
)m
->b_wptr
) {
1016 PANIC((!m
),("fr_tcpsum: not enough data"));
1018 sp
= (u_short
*)m
->b_rptr
;
1025 * In case we had to copy the IP & TCP header out of mbufs,
1026 * skip over the mbuf bits which are the header
1028 if ((caddr_t
)ip
!= mtod(m
, caddr_t
)) {
1029 hlen
= (caddr_t
)sp
- (caddr_t
)ip
;
1031 add
= MIN(hlen
, m
->m_len
);
1032 sp
= (u_short
*)(mtod(m
, caddr_t
) + add
);
1034 if (add
>= m
->m_len
) {
1036 PANIC((!m
),("fr_tcpsum: not enough data"));
1038 sp
= mtod(m
, u_short
*);
1044 if (!(len
-= sizeof(*tcp
)))
1048 while ((caddr_t
)sp
>= (caddr_t
)m
->b_wptr
) {
1050 PANIC((!m
),("fr_tcpsum: not enough data"));
1051 sp
= (u_short
*)m
->b_rptr
;
1054 while (((caddr_t
)sp
- mtod(m
, caddr_t
)) >= m
->m_len
)
1057 PANIC((!m
),("fr_tcpsum: not enough data"));
1058 sp
= mtod(m
, u_short
*);
1060 #endif /* SOLARIS */
1063 if((u_32_t
)sp
& 1) {
1064 bcopy((char *)sp
++, (char *)&bytes
.s
, sizeof(bytes
.s
));
1072 bytes
.c
[0] = *(u_char
*)sp
;
1076 sum
= (sum
>> 16) + (sum
& 0xffff);
1078 sum
= (u_short
)((~sum
) & 0xffff);
1083 #if defined(KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1085 * Copyright (c) 1982, 1986, 1988, 1991, 1993
1086 * The Regents of the University of California. All rights reserved.
1088 * Redistribution and use in source and binary forms, with or without
1089 * modification, are permitted provided that the following conditions
1091 * 1. Redistributions of source code must retain the above copyright
1092 * notice, this list of conditions and the following disclaimer.
1093 * 2. Redistributions in binary form must reproduce the above copyright
1094 * notice, this list of conditions and the following disclaimer in the
1095 * documentation and/or other materials provided with the distribution.
1096 * 3. All advertising materials mentioning features or use of this software
1097 * must display the following acknowledgement:
1098 * This product includes software developed by the University of
1099 * California, Berkeley and its contributors.
1100 * 4. Neither the name of the University nor the names of its contributors
1101 * may be used to endorse or promote products derived from this software
1102 * without specific prior written permission.
1104 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1105 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1106 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1107 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1108 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1109 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1110 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1111 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1112 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1113 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1116 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1119 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1120 * continuing for "len" bytes, into the indicated buffer.
1123 m_copydata(m
, off
, len
, cp
)
1129 register unsigned count
;
1131 if (off
< 0 || len
< 0)
1132 panic("m_copydata");
1135 panic("m_copydata");
1143 panic("m_copydata");
1144 count
= MIN(m
->m_len
- off
, len
);
1145 bcopy(mtod(m
, caddr_t
) + off
, cp
, count
);
1156 * Copy data from a buffer back into the indicated mbuf chain,
1157 * starting "off" bytes from the beginning, extending the mbuf
1158 * chain if necessary.
1161 m_copyback(m0
, off
, len
, cp
)
1168 register struct mbuf
*m
= m0
, *n
;
1173 while (off
> (mlen
= m
->m_len
)) {
1176 if (m
->m_next
== 0) {
1177 n
= m_getclr(M_DONTWAIT
, m
->m_type
);
1180 n
->m_len
= min(MLEN
, len
+ off
);
1186 mlen
= min (m
->m_len
- off
, len
);
1187 bcopy(cp
, off
+ mtod(m
, caddr_t
), (unsigned)mlen
);
1195 if (m
->m_next
== 0) {
1196 n
= m_get(M_DONTWAIT
, m
->m_type
);
1199 n
->m_len
= min(MLEN
, len
);
1206 if (((m
= m0
)->m_flags
& M_PKTHDR
) && (m
->m_pkthdr
.len
< totlen
))
1207 m
->m_pkthdr
.len
= totlen
;
1212 #endif /* (KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1215 frgroup_t
*fr_findgroup(num
, flags
, which
, set
, fgpp
)
1221 frgroup_t
*fg
, **fgp
;
1223 if (which
== IPL_LOGAUTH
)
1224 fgp
= &ipfgroups
[2][set
];
1225 else if (flags
& FR_ACCOUNT
)
1226 fgp
= &ipfgroups
[1][set
];
1227 else if (flags
& (FR_OUTQUE
|FR_INQUE
))
1228 fgp
= &ipfgroups
[0][set
];
1233 if (fg
->fg_num
== num
)
1243 frgroup_t
*fr_addgroup(num
, fp
, which
, set
)
1248 frgroup_t
*fg
, **fgp
;
1250 if ((fg
= fr_findgroup(num
, fp
->fr_flags
, which
, set
, &fgp
)))
1253 KMALLOC(fg
, frgroup_t
*, sizeof(*fg
));
1258 fg
->fg_start
= &fp
->fr_grp
;
1265 void fr_delgroup(num
, flags
, which
, set
)
1270 frgroup_t
*fg
, **fgp
;
1272 if (!(fg
= fr_findgroup(num
, flags
, which
, set
, &fgp
)))
1282 * recursively flush rules from the list, descending groups as they are
1283 * encountered. if a rule is the head of a group and it has lost all its
1284 * group members, then also delete the group reference.
1286 static int frflushlist(set
, unit
, nfreedp
, list
, listp
)
1287 int set
, unit
, *nfreedp
;
1288 frentry_t
*list
, **listp
;
1290 register frentry_t
*fp
= list
, *fpn
;
1291 register int freed
= 0;
1296 fp
->fr_ref
-= frflushlist(set
, unit
, nfreedp
,
1297 fp
->fr_grp
, &fp
->fr_grp
);
1300 if (fp
->fr_ref
== 1) {
1302 fr_delgroup(fp
->fr_grhead
, fp
->fr_flags
, unit
,
1315 void frflush(unit
, result
)
1319 int flags
= *result
, flushed
= 0, set
= fr_active
;
1321 bzero((char *)frcache
, sizeof(frcache
[0]) * 2);
1323 if (flags
& FR_INACTIVE
)
1326 if (unit
== IPL_LOGIPF
) {
1327 if (flags
& FR_OUTQUE
) {
1328 (void) frflushlist(set
, unit
, &flushed
,
1331 (void) frflushlist(set
, unit
, &flushed
,
1332 ipacct
[1][set
], &ipacct
[1][set
]);
1334 if (flags
& FR_INQUE
) {
1335 (void) frflushlist(set
, unit
, &flushed
,
1338 (void) frflushlist(set
, unit
, &flushed
,
1339 ipacct
[0][set
], &ipacct
[0][set
]);