]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/fil.c
xnu-124.13.tar.gz
[apple/xnu.git] / bsd / netinet / fil.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (C) 1993-1997 by Darren Reed.
24 *
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.
28 */
29 #if !defined(lint)
30 /* static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; */
31 #endif
32
33 #include "opt_ipfilter.h"
34
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/time.h>
39 #include <sys/file.h>
40 #if !defined(__FreeBSD__)
41 # include <sys/ioctl.h>
42 #endif
43
44 # include <sys/systm.h>
45
46 #include <sys/uio.h>
47 #if !defined(__SVR4) && !defined(__svr4__)
48 # ifndef linux
49 # include <sys/mbuf.h>
50 # endif
51 #else
52 # include <sys/byteorder.h>
53 # include <sys/dditypes.h>
54 # include <sys/stream.h>
55 #endif
56 #if defined(__FreeBSD__)
57 # include <sys/malloc.h>
58 #endif
59 #ifndef linux
60 # include <sys/protosw.h>
61 # include <sys/socket.h>
62 #endif
63 #include <net/if.h>
64 #ifdef sun
65 # include <net/af.h>
66 #endif
67 #include <net/route.h>
68 #include <netinet/in.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/ip.h>
71 #ifndef linux
72 # include <netinet/ip_var.h>
73 #endif
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"
85 #ifndef MIN
86 #define MIN(a,b) (((a)<(b))?(a):(b))
87 #endif
88
89 #ifndef KERNEL
90 # include "ipf.h"
91 # include "ipt.h"
92 extern int opts;
93
94 # define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
95 second; }
96 # define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
97 second; }
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)
103 # if SOLARIS
104 # define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(ip)
105 # else
106 # define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(b, ip, if)
107 # endif
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;
116 # endif
117 # if SOLARIS
118 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
119 ip, qif)
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)
123 # else /* SOLARIS */
124 # define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
125 # ifdef linux
126 # define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip,\
127 ifp)
128 # else
129 # define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip)
130 # endif
131 # ifdef __sgi
132 # define ICMP_ERROR(b, ip, t, c, if, src) \
133 icmp_error(b, t, c, if, src, if)
134 # else
135 # if BSD < 199103
136 # ifdef linux
137 # define ICMP_ERROR(b, ip, t, c, if, src) icmp_send(b,t,c,0,if)
138 # else
139 # define ICMP_ERROR(b, ip, t, c, if, src) \
140 icmp_error(mtod(b, ip_t *), t, c, if, src)
141 # endif /* linux */
142 # else
143 # define ICMP_ERROR(b, ip, t, c, if, src) \
144 icmp_error(b, t, c, (src).s_addr, if)
145 # endif /* BSD < 199103 */
146 # endif /* __sgi */
147 # endif /* SOLARIS || __sgi */
148 #endif /* KERNEL */
149
150
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;
158 #else
159 int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
160 #endif
161
162 fr_info_t frcache[2];
163
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 **));
167
168
169 /*
170 * bit values for identifying presence of individual IP options
171 */
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 },
192 { 0, 0x000000 }
193 };
194
195 /*
196 * bit values for identifying presence of individual IP security options
197 */
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 }
207 };
208
209
210 /*
211 * compact the IP header into a structure which contains just the info.
212 * which is useful for comparing IP headers with.
213 */
214 static void fr_makefrip(hlen, ip, fin)
215 int hlen;
216 ip_t *ip;
217 fr_info_t *fin;
218 {
219 struct optlist *op;
220 tcphdr_t *tcp;
221 icmphdr_t *icmp;
222 fr_ip_t *fi = &fin->fin_fi;
223 u_short optmsk = 0, secmsk = 0, auth = 0;
224 int i, mv, ol, off;
225 u_char *s, opt;
226
227 fin->fin_fr = NULL;
228 fin->fin_tcpf = 0;
229 fin->fin_data[0] = 0;
230 fin->fin_data[1] = 0;
231 fin->fin_rule = -1;
232 fin->fin_group = -1;
233 fin->fin_id = ip->ip_id;
234 #ifdef KERNEL
235 fin->fin_icode = ipl_unreach;
236 #endif
237 fi->fi_v = ip->ip_v;
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));
247
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;
252 switch (ip->ip_p)
253 {
254 case IPPROTO_ICMP :
255 {
256 int minicmpsz = sizeof(struct icmp);
257
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;
267 break;
268 }
269 case IPPROTO_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;
276 goto getports;
277 case IPPROTO_UDP :
278 fi->fi_fl |= FI_TCPUDP;
279 if ((!IPMINLEN(ip, udphdr) && !off) ||
280 (off && off < sizeof(struct udphdr)))
281 fi->fi_fl |= FI_SHORT;
282 getports:
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);
286 }
287 break;
288 default :
289 break;
290 }
291
292
293 for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) {
294 if (!(opt = *s))
295 break;
296 ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
297 if (opt > 1 && (ol < 2 || ol > hlen))
298 break;
299 for (i = 9, mv = 4; mv >= 0; ) {
300 op = ipopts + i;
301 if (opt == (u_char)op->ol_val) {
302 optmsk |= op->ol_bit;
303 if (opt == IPOPT_SECURITY) {
304 struct optlist *sp;
305 u_char sec;
306 int j, m;
307
308 sec = *(s + 2); /* classification */
309 for (j = 3, m = 2; m >= 0; ) {
310 sp = secopt + j;
311 if (sec == sp->ol_val) {
312 secmsk |= sp->ol_bit;
313 auth = *(s + 3);
314 auth *= 256;
315 auth += *(s + 4);
316 break;
317 }
318 if (sec < sp->ol_val)
319 j -= m--;
320 else
321 j += m--;
322 }
323 }
324 break;
325 }
326 if (opt < op->ol_val)
327 i -= mv--;
328 else
329 i += mv--;
330 }
331 hlen -= ol;
332 s += ol;
333 }
334 if (auth && !(auth & 0x0100))
335 auth &= 0xff00;
336 fi->fi_optmsk = optmsk;
337 fi->fi_secmsk = secmsk;
338 fi->fi_auth = auth;
339 }
340
341
342 /*
343 * check an IP packet for TCP/UDP characteristics such as ports and flags.
344 */
345 static int fr_tcpudpchk(fr, fin)
346 frentry_t *fr;
347 fr_info_t *fin;
348 {
349 register u_short po, tup;
350 register char i;
351 register int err = 1;
352
353 /*
354 * Both ports should *always* be in the first fragment.
355 * So far, I cannot find any cases where they can not be.
356 *
357 * compare destination ports
358 */
359 if ((i = (int)fr->fr_dcmp)) {
360 po = fr->fr_dport;
361 tup = fin->fin_data[1];
362 /*
363 * Do opposite test to that required and
364 * continue if that succeeds.
365 */
366 if (!--i && tup != po) /* EQUAL */
367 err = 0;
368 else if (!--i && tup == po) /* NOTEQUAL */
369 err = 0;
370 else if (!--i && tup >= po) /* LESSTHAN */
371 err = 0;
372 else if (!--i && tup <= po) /* GREATERTHAN */
373 err = 0;
374 else if (!--i && tup > po) /* LT or EQ */
375 err = 0;
376 else if (!--i && tup < po) /* GT or EQ */
377 err = 0;
378 else if (!--i && /* Out of range */
379 (tup >= po && tup <= fr->fr_dtop))
380 err = 0;
381 else if (!--i && /* In range */
382 (tup <= po || tup >= fr->fr_dtop))
383 err = 0;
384 }
385 /*
386 * compare source ports
387 */
388 if (err && (i = (int)fr->fr_scmp)) {
389 po = fr->fr_sport;
390 tup = fin->fin_data[0];
391 if (!--i && tup != po)
392 err = 0;
393 else if (!--i && tup == po)
394 err = 0;
395 else if (!--i && tup >= po)
396 err = 0;
397 else if (!--i && tup <= po)
398 err = 0;
399 else if (!--i && tup > po)
400 err = 0;
401 else if (!--i && tup < po)
402 err = 0;
403 else if (!--i && /* Out of range */
404 (tup >= po && tup <= fr->fr_stop))
405 err = 0;
406 else if (!--i && /* In range */
407 (tup <= po || tup >= fr->fr_stop))
408 err = 0;
409 }
410
411 /*
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).
416 */
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);
420 /*
421 * Match the flags ? If not, abort this match.
422 */
423 if (fr->fr_tcpf &&
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));
427 err = 0;
428 }
429 }
430 return err;
431 }
432
433 /*
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
436 * kernel sauce.
437 */
438 int fr_scanlist(pass, ip, fin, m)
439 int pass;
440 ip_t *ip;
441 register fr_info_t *fin;
442 void *m;
443 {
444 register struct frentry *fr;
445 register fr_ip_t *fi = &fin->fin_fi;
446 int rulen, portcmp = 0, off, skip = 0;
447
448 fr = fin->fin_fr;
449 fin->fin_fr = NULL;
450 fin->fin_rule = 0;
451 fin->fin_group = 0;
452 off = ip->ip_off & 0x1fff;
453 pass |= (fi->fi_fl << 24);
454
455 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
456 portcmp = 1;
457
458 for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
459 if (skip) {
460 skip--;
461 continue;
462 }
463 /*
464 * In all checks below, a null (zero) value in the
465 * filter struture is taken to mean a wildcard.
466 *
467 * check that we are working for the right interface
468 */
469 #ifdef KERNEL
470 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
471 continue;
472 #else
473 if (opts & (OPT_VERBOSE|OPT_DEBUG))
474 printf("\n");
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)
478 continue;
479 FR_VERBOSE((":i"));
480 #endif
481 {
482 register u_32_t *ld, *lm, *lip;
483 register int i;
484
485 lip = (u_32_t *)fi;
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));
504 if (i)
505 continue;
506 }
507
508 /*
509 * If a fragment, then only the first has what we're looking
510 * for here...
511 */
512 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
513 fr->fr_tcpfm))
514 continue;
515 if (fi->fi_fl & FI_TCPUDP) {
516 if (!fr_tcpudpchk(fr, fin))
517 continue;
518 } else if (fr->fr_icmpm || fr->fr_icmp) {
519 if ((fi->fi_p != IPPROTO_ICMP) || off ||
520 (fin->fin_dlen < 2))
521 continue;
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,
525 fr->fr_icmp));
526 continue;
527 }
528 }
529 FR_VERBOSE(("*"));
530 /*
531 * Just log this packet...
532 */
533 if (!(skip = fr->fr_skip))
534 pass = fr->fr_flags;
535 if ((pass & FR_CALLNOW) && fr->fr_func)
536 pass = (*fr->fr_func)(pass, ip, fin);
537 #if IPFILTER_LOG
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++;
542 }
543 #endif /* IPFILTER_LOG */
544 FR_DEBUG(("pass %#x\n", pass));
545 fr->fr_hits++;
546 if (pass & FR_ACCOUNT)
547 fr->fr_bytes += (U_QUAD_T)ip->ip_len;
548 else
549 fin->fin_icode = fr->fr_icode;
550 fin->fin_rule = rulen;
551 fin->fin_group = fr->fr_group;
552 fin->fin_fr = fr;
553 if (fr->fr_grp) {
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;
559 fin->fin_fr = fr;
560 }
561 }
562 if (pass & FR_QUICK)
563 break;
564 }
565 return pass;
566 }
567
568
569 /*
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.
573 */
574 int fr_check(ip, hlen, ifp, out
575 #if defined(KERNEL) && SOLARIS
576 , qif, mp)
577 qif_t *qif;
578 #else
579 , mp)
580 #endif
581 mb_t **mp;
582 ip_t *ip;
583 int hlen;
584 void *ifp;
585 int out;
586 {
587 /*
588 * The above is really bad, but short of writing a diff
589 */
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;
596 #endif
597
598 #if KERNEL
599 mb_t *mc = NULL;
600 # if !defined(__SVR4) && !defined(__svr4__)
601 # ifdef __sgi
602 char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
603 # endif
604 int up;
605
606 #if M_CANFASTFWD
607 /*
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.
611 */
612 m->m_flags &= ~M_CANFASTFWD;
613 #endif /* M_CANFASTFWD */
614
615 if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
616 ip->ip_p == IPPROTO_ICMP)) {
617 int plen = 0;
618
619 switch(ip->ip_p)
620 {
621 case IPPROTO_TCP:
622 plen = sizeof(tcphdr_t);
623 break;
624 case IPPROTO_UDP:
625 plen = sizeof(udphdr_t);
626 break;
627 case IPPROTO_ICMP:
628 /* 96 - enough for complete ICMP error IP header */
629 plen = sizeof(struct icmp) + sizeof(ip_t) + 8;
630 break;
631 }
632 up = MIN(hlen + plen, ip->ip_len);
633
634 if (up > m->m_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]++;
638 return -1;
639 }
640 m_copydata(m, 0, up, hbuf);
641 frstats[out].fr_pull[0]++;
642 ip = (ip_t *)hbuf;
643 #else
644 # ifndef linux
645 if ((*mp = m_pullup(m, up)) == 0) {
646 frstats[out].fr_pull[1]++;
647 return -1;
648 } else {
649 frstats[out].fr_pull[0]++;
650 m = *mp;
651 ip = mtod(m, ip_t *);
652 }
653 # endif
654 #endif
655 } else
656 up = 0;
657 } else
658 up = 0;
659 # endif
660 # if SOLARIS
661 mb_t *m = qif->qf_m;
662 # endif
663 #endif
664 fr_makefrip(hlen, ip, fin);
665 fin->fin_ifp = ifp;
666 fin->fin_out = out;
667 fin->fin_mp = mp;
668
669 MUTEX_ENTER(&ipf_mutex);
670
671 /*
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.
677 */
678 apass = fr_checkauth(ip, fin);
679
680 if (!out) {
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++;
685 }
686
687 if (apass || (!(pass = ipfr_knownfrag(ip, fin)) &&
688 !(pass = fr_checkstate(ip, fin)))) {
689 /*
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.
693 */
694 if (!apass) {
695 fc = frcache + out;
696 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
697 /*
698 * copy cached data so we can unlock the mutex
699 * earlier.
700 */
701 bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
702 frstats[out].fr_chit++;
703 if ((fr = fin->fin_fr)) {
704 fr->fr_hits++;
705 pass = fr->fr_flags;
706 } else
707 pass = fr_pass;
708 } else {
709 pass = fr_pass;
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++;
715 }
716 fr = fin->fin_fr;
717 } else
718 pass = apass;
719
720 /*
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.
724 */
725 if ((pass & FR_AUTH))
726 if (FR_NEWAUTH(m, fin, ip, qif) != 0)
727 #ifdef KERNEL
728 m = *mp = NULL;
729 #else
730 ;
731 #endif
732
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++;
738 else
739 fr_authstats.fas_miss++;
740 MUTEX_EXIT(&ipf_auth);
741 }
742
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++;
747 else
748 frstats[out].fr_nfr++;
749 } else
750 frstats[out].fr_cfr++;
751 }
752 if (pass & FR_KEEPSTATE) {
753 if (fr_addstate(ip, fin, pass) == -1)
754 frstats[out].fr_bads++;
755 else
756 frstats[out].fr_ads++;
757 }
758 }
759
760 if (fr && fr->fr_func && !(pass & FR_CALLNOW))
761 pass = (*fr->fr_func)(pass, ip, fin);
762
763 /*
764 * Only count/translate packets which will be passed on, out the
765 * interface.
766 */
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++;
771 fin->fin_fr = NULL;
772 changed = ip_natout(ip, hlen, fin);
773 }
774 fin->fin_fr = fr;
775 MUTEX_EXIT(&ipf_mutex);
776
777 #if IPFILTER_LOG
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++;
782 goto logit;
783 } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
784 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
785 if ((pass & FR_LOGMASK) != FR_LOGP)
786 pass |= FF_LOGPASS;
787 frstats[out].fr_ppkl++;
788 goto logit;
789 } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
790 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
791 if ((pass & FR_LOGMASK) != FR_LOGB)
792 pass |= FF_LOGBLOCK;
793 frstats[out].fr_bpkl++;
794 logit:
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;
800 }
801 }
802 }
803 #endif /* IPFILTER_LOG */
804 #ifdef KERNEL
805 /*
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.
809 */
810 if (fr && (pass & FR_DUP))
811 # if SOLARIS
812 mc = dupmsg(m);
813 # else
814 # ifndef linux
815 mc = m_copy(m, 0, M_COPYALL);
816 # else
817 ;
818 # endif
819 # endif
820 #endif
821 if (pass & FR_PASS)
822 frstats[out].fr_pass++;
823 else if (pass & FR_BLOCK) {
824 frstats[out].fr_block++;
825 /*
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.
832 */
833 if (!out) {
834 #ifdef KERNEL
835 if (pass & FR_RETICMP) {
836 # if SOLARIS
837 ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
838 qif, ip->ip_src);
839 # else
840 ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
841 ifp, ip->ip_src);
842 m = *mp = NULL; /* freed by icmp_error() */
843 # endif
844
845 frstats[0].fr_ret++;
846 } else if ((pass & FR_RETRST) &&
847 !(fin->fin_fi.fi_fl & FI_SHORT)) {
848 if (SEND_RESET(ip, qif, ifp) == 0)
849 frstats[1].fr_ret++;
850 }
851 #else
852 if (pass & FR_RETICMP) {
853 verbose("- ICMP unreachable sent\n");
854 frstats[0].fr_ret++;
855 } else if ((pass & FR_RETRST) &&
856 !(fin->fin_fi.fi_fl & FI_SHORT)) {
857 verbose("- TCP RST sent\n");
858 frstats[1].fr_ret++;
859 }
860 #endif
861 } else {
862 if (pass & FR_RETRST)
863 error = ECONNRESET;
864 }
865 }
866
867 /*
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 *).
873 */
874 #if defined(KERNEL)
875 # if !SOLARIS
876 # if !defined(linux)
877 if (fr) {
878 frdest_t *fdp = &fr->fr_tif;
879
880 if ((pass & FR_FASTROUTE) ||
881 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
882 ipfr_fastroute(m, fin, fdp);
883 m = *mp = NULL;
884 }
885 if (mc)
886 ipfr_fastroute(mc, fin, &fr->fr_dif);
887 }
888 if (!(pass & FR_PASS) && m)
889 m_freem(m);
890 # ifdef __sgi
891 else if (changed && up && m)
892 m_copyback(m, 0, up, hbuf);
893 # endif
894 # endif /* !linux */
895 return (pass & FR_PASS) ? 0 : error;
896 # else /* !SOLARIS */
897 if (fr) {
898 frdest_t *fdp = &fr->fr_tif;
899
900 if ((pass & FR_FASTROUTE) ||
901 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
902 ipfr_fastroute(qif, ip, m, mp, fin, fdp);
903 m = *mp = NULL;
904 }
905 if (mc)
906 ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
907 }
908 return (pass & FR_PASS) ? changed : error;
909 # endif /* !SOLARIS */
910 #else /* KERNEL */
911 if (pass & FR_NOMATCH)
912 return 1;
913 if (pass & FR_PASS)
914 return 0;
915 if (pass & FR_AUTH)
916 return -2;
917 return -1;
918 #endif /* KERNEL */
919 }
920
921
922 /*
923 * ipf_cksum
924 * addr should be 16bit aligned and len is in bytes.
925 * length is in bytes
926 */
927 u_short ipf_cksum(addr, len)
928 register u_short *addr;
929 register int len;
930 {
931 register u_32_t sum = 0;
932
933 for (sum = 0; len > 1; len -= 2)
934 sum += *addr++;
935
936 /* mop up an odd byte, if necessary */
937 if (len == 1)
938 sum += *(u_char *)addr;
939
940 /*
941 * add back carry outs from top 16 bits to low 16 bits
942 */
943 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
944 sum += (sum >> 16); /* add carry */
945 return (u_short)(~sum);
946 }
947
948
949 /*
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
952 * odd sizes.
953 */
954 u_short fr_tcpsum(m, ip, tcp, len)
955 mb_t *m;
956 ip_t *ip;
957 tcphdr_t *tcp;
958 int len;
959 {
960 union {
961 u_char c[2];
962 u_short s;
963 } bytes;
964 u_32_t sum;
965 u_short *sp;
966 # if SOLARIS || defined(__sgi)
967 int add, hlen;
968 # endif
969
970 # if SOLARIS
971 /* skip any leading M_PROTOs */
972 while(m && (MTYPE(m) != M_DATA))
973 m = m->b_cont;
974 PANIC((!m),("fr_tcpsum: no M_DATA"));
975 # endif
976
977 /*
978 * Add up IP Header portion
979 */
980 bytes.c[0] = 0;
981 bytes.c[1] = IPPROTO_TCP;
982 len -= (ip->ip_hl << 2);
983 sum = bytes.s;
984 sum += htons((u_short)len);
985 sp = (u_short *)&ip->ip_src;
986 sum += *sp++;
987 sum += *sp++;
988 sum += *sp++;
989 sum += *sp++;
990 if (sp != (u_short *)tcp)
991 sp = (u_short *)tcp;
992 sum += *sp++;
993 sum += *sp++;
994 sum += *sp++;
995 sum += *sp++;
996 sum += *sp++;
997 sum += *sp++;
998 sum += *sp++;
999 sum += *sp;
1000 sp += 2; /* Skip over checksum */
1001 sum += *sp++;
1002
1003 #if SOLARIS
1004 /*
1005 * In case we had to copy the IP & TCP header out of mblks,
1006 * skip over the mblk bits which are the header
1007 */
1008 if ((caddr_t)ip != (caddr_t)m->b_rptr) {
1009 hlen = (caddr_t)sp - (caddr_t)ip;
1010 while (hlen) {
1011 add = MIN(hlen, m->b_wptr - m->b_rptr);
1012 sp = (u_short *)((caddr_t)m->b_rptr + add);
1013 hlen -= add;
1014 if ((caddr_t)sp >= (caddr_t)m->b_wptr) {
1015 m = m->b_cont;
1016 PANIC((!m),("fr_tcpsum: not enough data"));
1017 if (!hlen)
1018 sp = (u_short *)m->b_rptr;
1019 }
1020 }
1021 }
1022 #endif
1023 #ifdef __sgi
1024 /*
1025 * In case we had to copy the IP & TCP header out of mbufs,
1026 * skip over the mbuf bits which are the header
1027 */
1028 if ((caddr_t)ip != mtod(m, caddr_t)) {
1029 hlen = (caddr_t)sp - (caddr_t)ip;
1030 while (hlen) {
1031 add = MIN(hlen, m->m_len);
1032 sp = (u_short *)(mtod(m, caddr_t) + add);
1033 hlen -= add;
1034 if (add >= m->m_len) {
1035 m = m->m_next;
1036 PANIC((!m),("fr_tcpsum: not enough data"));
1037 if (!hlen)
1038 sp = mtod(m, u_short *);
1039 }
1040 }
1041 }
1042 #endif
1043
1044 if (!(len -= sizeof(*tcp)))
1045 goto nodata;
1046 while (len > 0) {
1047 #if SOLARIS
1048 while ((caddr_t)sp >= (caddr_t)m->b_wptr) {
1049 m = m->b_cont;
1050 PANIC((!m),("fr_tcpsum: not enough data"));
1051 sp = (u_short *)m->b_rptr;
1052 }
1053 #else
1054 while (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len)
1055 {
1056 m = m->m_next;
1057 PANIC((!m),("fr_tcpsum: not enough data"));
1058 sp = mtod(m, u_short *);
1059 }
1060 #endif /* SOLARIS */
1061 if (len < 2)
1062 break;
1063 if((u_32_t)sp & 1) {
1064 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
1065 sum += bytes.s;
1066 } else
1067 sum += *sp++;
1068 len -= 2;
1069 }
1070 if (len) {
1071 bytes.c[1] = 0;
1072 bytes.c[0] = *(u_char *)sp;
1073 sum += bytes.s;
1074 }
1075 nodata:
1076 sum = (sum >> 16) + (sum & 0xffff);
1077 sum += (sum >> 16);
1078 sum = (u_short)((~sum) & 0xffff);
1079 return sum;
1080 }
1081
1082
1083 #if defined(KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1084 /*
1085 * Copyright (c) 1982, 1986, 1988, 1991, 1993
1086 * The Regents of the University of California. All rights reserved.
1087 *
1088 * Redistribution and use in source and binary forms, with or without
1089 * modification, are permitted provided that the following conditions
1090 * are met:
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.
1103 *
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
1114 * SUCH DAMAGE.
1115 *
1116 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1117 */
1118 /*
1119 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1120 * continuing for "len" bytes, into the indicated buffer.
1121 */
1122 void
1123 m_copydata(m, off, len, cp)
1124 register mb_t *m;
1125 register int off;
1126 register int len;
1127 caddr_t cp;
1128 {
1129 register unsigned count;
1130
1131 if (off < 0 || len < 0)
1132 panic("m_copydata");
1133 while (off > 0) {
1134 if (m == 0)
1135 panic("m_copydata");
1136 if (off < m->m_len)
1137 break;
1138 off -= m->m_len;
1139 m = m->m_next;
1140 }
1141 while (len > 0) {
1142 if (m == 0)
1143 panic("m_copydata");
1144 count = MIN(m->m_len - off, len);
1145 bcopy(mtod(m, caddr_t) + off, cp, count);
1146 len -= count;
1147 cp += count;
1148 off = 0;
1149 m = m->m_next;
1150 }
1151 }
1152
1153
1154 # ifndef linux
1155 /*
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.
1159 */
1160 void
1161 m_copyback(m0, off, len, cp)
1162 struct mbuf *m0;
1163 register int off;
1164 register int len;
1165 caddr_t cp;
1166 {
1167 register int mlen;
1168 register struct mbuf *m = m0, *n;
1169 int totlen = 0;
1170
1171 if (m0 == 0)
1172 return;
1173 while (off > (mlen = m->m_len)) {
1174 off -= mlen;
1175 totlen += mlen;
1176 if (m->m_next == 0) {
1177 n = m_getclr(M_DONTWAIT, m->m_type);
1178 if (n == 0)
1179 goto out;
1180 n->m_len = min(MLEN, len + off);
1181 m->m_next = n;
1182 }
1183 m = m->m_next;
1184 }
1185 while (len > 0) {
1186 mlen = min (m->m_len - off, len);
1187 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1188 cp += mlen;
1189 len -= mlen;
1190 mlen += off;
1191 off = 0;
1192 totlen += mlen;
1193 if (len == 0)
1194 break;
1195 if (m->m_next == 0) {
1196 n = m_get(M_DONTWAIT, m->m_type);
1197 if (n == 0)
1198 break;
1199 n->m_len = min(MLEN, len);
1200 m->m_next = n;
1201 }
1202 m = m->m_next;
1203 }
1204 out:
1205 #if 0
1206 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1207 m->m_pkthdr.len = totlen;
1208 #endif
1209 return;
1210 }
1211 # endif /* linux */
1212 #endif /* (KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1213
1214
1215 frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
1216 u_short num;
1217 u_32_t flags;
1218 int which, set;
1219 frgroup_t ***fgpp;
1220 {
1221 frgroup_t *fg, **fgp;
1222
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];
1229 else
1230 return NULL;
1231
1232 while ((fg = *fgp))
1233 if (fg->fg_num == num)
1234 break;
1235 else
1236 fgp = &fg->fg_next;
1237 if (fgpp)
1238 *fgpp = fgp;
1239 return fg;
1240 }
1241
1242
1243 frgroup_t *fr_addgroup(num, fp, which, set)
1244 u_short num;
1245 frentry_t *fp;
1246 int which, set;
1247 {
1248 frgroup_t *fg, **fgp;
1249
1250 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
1251 return fg;
1252
1253 KMALLOC(fg, frgroup_t *, sizeof(*fg));
1254 if (fg) {
1255 fg->fg_num = num;
1256 fg->fg_next = *fgp;
1257 fg->fg_head = fp;
1258 fg->fg_start = &fp->fr_grp;
1259 *fgp = fg;
1260 }
1261 return fg;
1262 }
1263
1264
1265 void fr_delgroup(num, flags, which, set)
1266 u_short num;
1267 u_32_t flags;
1268 int which, set;
1269 {
1270 frgroup_t *fg, **fgp;
1271
1272 if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
1273 return;
1274
1275 *fgp = fg->fg_next;
1276 KFREE(fg);
1277 }
1278
1279
1280
1281 /*
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.
1285 */
1286 static int frflushlist(set, unit, nfreedp, list, listp)
1287 int set, unit, *nfreedp;
1288 frentry_t *list, **listp;
1289 {
1290 register frentry_t *fp = list, *fpn;
1291 register int freed = 0;
1292
1293 while (fp) {
1294 fpn = fp->fr_next;
1295 if (fp->fr_grp) {
1296 fp->fr_ref -= frflushlist(set, unit, nfreedp,
1297 fp->fr_grp, &fp->fr_grp);
1298 }
1299
1300 if (fp->fr_ref == 1) {
1301 if (fp->fr_grhead)
1302 fr_delgroup(fp->fr_grhead, fp->fr_flags, unit,
1303 set);
1304 KFREE(fp);
1305 *listp = fpn;
1306 freed++;
1307 }
1308 fp = fpn;
1309 }
1310 *nfreedp += freed;
1311 return freed;
1312 }
1313
1314
1315 void frflush(unit, result)
1316 int unit;
1317 int *result;
1318 {
1319 int flags = *result, flushed = 0, set = fr_active;
1320
1321 bzero((char *)frcache, sizeof(frcache[0]) * 2);
1322
1323 if (flags & FR_INACTIVE)
1324 set = 1 - set;
1325
1326 if (unit == IPL_LOGIPF) {
1327 if (flags & FR_OUTQUE) {
1328 (void) frflushlist(set, unit, &flushed,
1329 ipfilter[1][set],
1330 &ipfilter[1][set]);
1331 (void) frflushlist(set, unit, &flushed,
1332 ipacct[1][set], &ipacct[1][set]);
1333 }
1334 if (flags & FR_INQUE) {
1335 (void) frflushlist(set, unit, &flushed,
1336 ipfilter[0][set],
1337 &ipfilter[0][set]);
1338 (void) frflushlist(set, unit, &flushed,
1339 ipacct[0][set], &ipacct[0][set]);
1340 }
1341 }
1342
1343 *result = flushed;
1344 }