Merge from vendor branch GCC:
[dragonfly.git] / contrib / ipfilter / fil.c
1 /*
2  * Copyright (C) 1993-2001 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  */
6 #if defined(__sgi) && (IRIX > 602)
7 # include <sys/ptimers.h>
8 #endif
9 #include <sys/errno.h>
10 #include <sys/types.h>
11 #include <sys/param.h>
12 #include <sys/time.h>
13 #include <sys/file.h>
14 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
15     defined(_KERNEL)
16 # include "opt_ipfilter_log.h"
17 #endif
18 #if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \
19     (__FreeBSD_version >= 220000)
20 # if (__FreeBSD_version >= 400000)
21 #  ifndef KLD_MODULE
22 #   include "opt_inet6.h"
23 #  endif
24 #  if (__FreeBSD_version == 400019)
25 #   define CSUM_DELAY_DATA
26 #  endif
27 # endif
28 # include <sys/filio.h>
29 # include <sys/fcntl.h>
30 #else
31 # include <sys/ioctl.h>
32 #endif
33 #if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
34 # include <sys/systm.h>
35 #else
36 # include <stdio.h>
37 # include <string.h>
38 # include <stdlib.h>
39 #endif
40 #if !defined(__SVR4) && !defined(__svr4__)
41 # ifndef linux
42 #  include <sys/mbuf.h>
43 # endif
44 #else
45 # include <sys/byteorder.h>
46 # if SOLARIS2 < 5
47 #  include <sys/dditypes.h>
48 # endif
49 #  include <sys/stream.h>
50 #endif
51 #ifndef linux
52 # include <sys/protosw.h>
53 # include <sys/socket.h>
54 #endif
55 #include <net/if.h>
56 #ifdef sun
57 # include <net/af.h>
58 #endif
59 #include <net/route.h>
60 #include <netinet/in.h>
61 #include <netinet/in_systm.h>
62 #include <netinet/ip.h>
63 #ifndef linux
64 # include <netinet/ip_var.h>
65 #endif
66 #if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
67 # include <sys/hashing.h>
68 # include <netinet/in_var.h>
69 #endif
70 #include <netinet/tcp.h>
71 #include <netinet/udp.h>
72 #include <netinet/ip_icmp.h>
73 #include "netinet/ip_compat.h"
74 #ifdef  USE_INET6
75 # include <netinet/icmp6.h>
76 # if !SOLARIS && defined(_KERNEL)
77 #  include <netinet6/in6_var.h>
78 # endif
79 #endif
80 #include <netinet/tcpip.h>
81 #include "netinet/ip_fil.h"
82 #include "netinet/ip_nat.h"
83 #include "netinet/ip_frag.h"
84 #include "netinet/ip_state.h"
85 #include "netinet/ip_proxy.h"
86 #include "netinet/ip_auth.h"
87 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
88 #  include <sys/malloc.h>
89 #  if defined(_KERNEL) && !defined(IPFILTER_LKM)
90 #   include "opt_ipfilter.h"
91 #  endif
92 # endif
93 #ifndef MIN
94 # define        MIN(a,b)        (((a)<(b))?(a):(b))
95 #endif
96 #include "netinet/ipl.h"
97
98 #if !defined(lint)
99 static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
100 static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.67 2002/12/06 13:28:05 darrenr Exp $";
101 #endif
102
103 #ifndef _KERNEL
104 # include "ipf.h"
105 # include "ipt.h"
106 extern  int     opts;
107
108 # define        FR_VERBOSE(verb_pr)                     verbose verb_pr
109 # define        FR_DEBUG(verb_pr)                       debug verb_pr
110 # define        IPLLOG(a, c, d, e)              ipflog(a, c, d, e)
111 #else /* #ifndef _KERNEL */
112 # define        FR_VERBOSE(verb_pr)
113 # define        FR_DEBUG(verb_pr)
114 # define        IPLLOG(a, c, d, e)              ipflog(a, c, d, e)
115 # if SOLARIS || defined(__sgi)
116 extern  KRWLOCK_T       ipf_mutex, ipf_auth, ipf_nat;
117 extern  kmutex_t        ipf_rw;
118 # endif /* SOLARIS || __sgi */
119 #endif /* _KERNEL */
120
121
122 struct  filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
123 struct  frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
124 #ifdef  USE_INET6
125                 *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } },
126                 *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } },
127 #endif
128                 *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
129 struct  frgroup *ipfgroups[3][2];
130 int     fr_flags = IPF_LOGGING;
131 int     fr_active = 0;
132 int     fr_chksrc = 0;
133 int     fr_minttl = 3;
134 int     fr_minttllog = 1;
135 #if defined(IPFILTER_DEFAULT_BLOCK)
136 int     fr_pass = FR_NOMATCH|FR_BLOCK;
137 #else
138 int     fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
139 #endif
140 char    ipfilter_version[] = IPL_VERSION;
141
142 fr_info_t       frcache[2];
143
144 static  int     frflushlist __P((int, minor_t, int *, frentry_t **));
145 #ifdef  _KERNEL
146 static  void    frsynclist __P((frentry_t *));
147 #endif
148
149
150 /*
151  * bit values for identifying presence of individual IP options
152  */
153 struct  optlist ipopts[20] = {
154         { IPOPT_NOP,    0x000001 },
155         { IPOPT_RR,     0x000002 },
156         { IPOPT_ZSU,    0x000004 },
157         { IPOPT_MTUP,   0x000008 },
158         { IPOPT_MTUR,   0x000010 },
159         { IPOPT_ENCODE, 0x000020 },
160         { IPOPT_TS,     0x000040 },
161         { IPOPT_TR,     0x000080 },
162         { IPOPT_SECURITY, 0x000100 },
163         { IPOPT_LSRR,   0x000200 },
164         { IPOPT_E_SEC,  0x000400 },
165         { IPOPT_CIPSO,  0x000800 },
166         { IPOPT_SATID,  0x001000 },
167         { IPOPT_SSRR,   0x002000 },
168         { IPOPT_ADDEXT, 0x004000 },
169         { IPOPT_VISA,   0x008000 },
170         { IPOPT_IMITD,  0x010000 },
171         { IPOPT_EIP,    0x020000 },
172         { IPOPT_FINN,   0x040000 },
173         { 0,            0x000000 }
174 };
175
176 /*
177  * bit values for identifying presence of individual IP security options
178  */
179 struct  optlist secopt[8] = {
180         { IPSO_CLASS_RES4,      0x01 },
181         { IPSO_CLASS_TOPS,      0x02 },
182         { IPSO_CLASS_SECR,      0x04 },
183         { IPSO_CLASS_RES3,      0x08 },
184         { IPSO_CLASS_CONF,      0x10 },
185         { IPSO_CLASS_UNCL,      0x20 },
186         { IPSO_CLASS_RES2,      0x40 },
187         { IPSO_CLASS_RES1,      0x80 }
188 };
189
190
191 /*
192  * compact the IP header into a structure which contains just the info.
193  * which is useful for comparing IP headers with.
194  */
195 void    fr_makefrip(hlen, ip, fin)
196 int hlen;
197 ip_t *ip;
198 fr_info_t *fin;
199 {
200         u_short optmsk = 0, secmsk = 0, auth = 0;
201         int i, mv, ol, off, p, plen, v;
202         fr_ip_t *fi = &fin->fin_fi;
203         struct optlist *op;
204         u_char *s, opt;
205         tcphdr_t *tcp;
206
207         fin->fin_rev = 0;
208         fin->fin_fr = NULL;
209         fin->fin_tcpf = 0;
210         fin->fin_data[0] = 0;
211         fin->fin_data[1] = 0;
212         fin->fin_rule = -1;
213         fin->fin_group = -1;
214         fin->fin_icode = ipl_unreach;
215         v = fin->fin_v;
216         fi->fi_v = v;
217         fin->fin_hlen = hlen;
218         if (v == 4) {
219                 fin->fin_id = ip->ip_id;
220                 fi->fi_tos = ip->ip_tos;
221                 off = (ip->ip_off & IP_OFFMASK);
222                 tcp = (tcphdr_t *)((char *)ip + hlen);
223                 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
224                 fi->fi_src.i6[1] = 0;
225                 fi->fi_src.i6[2] = 0;
226                 fi->fi_src.i6[3] = 0;
227                 fi->fi_dst.i6[1] = 0;
228                 fi->fi_dst.i6[2] = 0;
229                 fi->fi_dst.i6[3] = 0;
230                 fi->fi_saddr = ip->ip_src.s_addr;
231                 fi->fi_daddr = ip->ip_dst.s_addr;
232                 p = ip->ip_p;
233                 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
234                 if (ip->ip_off & (IP_MF|IP_OFFMASK))
235                         fi->fi_fl |= FI_FRAG;
236                 plen = ip->ip_len;
237                 fin->fin_dlen = plen - hlen;
238         }
239 #ifdef  USE_INET6
240         else if (v == 6) {
241                 ip6_t *ip6 = (ip6_t *)ip;
242
243                 off = 0;
244                 p = ip6->ip6_nxt;
245                 fi->fi_p = p;
246                 fi->fi_ttl = ip6->ip6_hlim;
247                 tcp = (tcphdr_t *)(ip6 + 1);
248                 fi->fi_src.in6 = ip6->ip6_src;
249                 fi->fi_dst.in6 = ip6->ip6_dst;
250                 fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff);
251                 fi->fi_tos = 0;
252                 fi->fi_fl = 0;
253                 plen = ntohs(ip6->ip6_plen);
254                 fin->fin_dlen = plen;
255                 plen += sizeof(*ip6);
256         }
257 #endif
258         else
259                 return;
260
261         fin->fin_off = off;
262         fin->fin_plen = plen;
263         fin->fin_dp = (char *)tcp;
264         fin->fin_misc = 0;
265         off <<= 3;
266
267         switch (p)
268         {
269 #ifdef USE_INET6
270         case IPPROTO_ICMPV6 :
271         {
272                 int minicmpsz = sizeof(struct icmp6_hdr);
273                 struct icmp6_hdr *icmp6;
274
275                 if (fin->fin_dlen > 1) {
276                         fin->fin_data[0] = *(u_short *)tcp;
277
278                         icmp6 = (struct icmp6_hdr *)tcp;
279
280                         switch (icmp6->icmp6_type)
281                         {
282                         case ICMP6_ECHO_REPLY :
283                         case ICMP6_ECHO_REQUEST :
284                                 minicmpsz = ICMP6_MINLEN;
285                                 break;
286                         case ICMP6_DST_UNREACH :
287                         case ICMP6_PACKET_TOO_BIG :
288                         case ICMP6_TIME_EXCEEDED :
289                         case ICMP6_PARAM_PROB :
290                                 minicmpsz = ICMP6ERR_IPICMPHLEN;
291                                 break;
292                         default :
293                                 break;
294                         }
295                 }
296
297                 if (!(plen >= minicmpsz))
298                         fi->fi_fl |= FI_SHORT;
299
300                 break;
301         }
302 #endif
303         case IPPROTO_ICMP :
304         {
305                 int minicmpsz = sizeof(struct icmp);
306                 icmphdr_t *icmp;
307
308                 if (!off && (fin->fin_dlen > 1)) {
309                         fin->fin_data[0] = *(u_short *)tcp;
310
311                         icmp = (icmphdr_t *)tcp;
312
313                         switch (icmp->icmp_type)
314                         {
315                         case ICMP_ECHOREPLY :
316                         case ICMP_ECHO :
317                         /* Router discovery messages - RFC 1256 */
318                         case ICMP_ROUTERADVERT :
319                         case ICMP_ROUTERSOLICIT :
320                                 minicmpsz = ICMP_MINLEN;
321                                 break;
322                         /*
323                          * type(1) + code(1) + cksum(2) + id(2) seq(2) +
324                          * 3*timestamp(3*4)
325                          */
326                         case ICMP_TSTAMP :
327                         case ICMP_TSTAMPREPLY :
328                                 minicmpsz = 20;
329                                 break;
330                         /*
331                          * type(1) + code(1) + cksum(2) + id(2) seq(2) +
332                          * mask(4)
333                          */
334                         case ICMP_MASKREQ :
335                         case ICMP_MASKREPLY :
336                                 minicmpsz = 12;
337                                 break;
338                         default :
339                                 break;
340                         }
341                 }
342
343                 if ((!(plen >= hlen + minicmpsz) && !off) ||
344                     (off && off < sizeof(struct icmp)))
345                         fi->fi_fl |= FI_SHORT;
346
347                 break;
348         }
349         case IPPROTO_TCP :
350                 fi->fi_fl |= FI_TCPUDP;
351 #ifdef  USE_INET6
352                 if (v == 6) {
353                         if (plen < sizeof(struct tcphdr))
354                                 fi->fi_fl |= FI_SHORT;
355                 } else
356 #endif
357                 if (v == 4) {
358                         if ((!IPMINLEN(ip, tcphdr) && !off) ||
359                              (off && off < sizeof(struct tcphdr)))
360                                 fi->fi_fl |= FI_SHORT;
361                 }
362                 if (!(fi->fi_fl & FI_SHORT) && !off)
363                         fin->fin_tcpf = tcp->th_flags;
364                 goto getports;
365         case IPPROTO_UDP :
366                 fi->fi_fl |= FI_TCPUDP;
367 #ifdef  USE_INET6
368                 if (v == 6) {
369                         if (plen < sizeof(struct udphdr))
370                                 fi->fi_fl |= FI_SHORT;
371                 } else
372 #endif
373                 if (v == 4) {
374                         if ((!IPMINLEN(ip, udphdr) && !off) ||
375                             (off && off < sizeof(struct udphdr)))
376                                 fi->fi_fl |= FI_SHORT;
377                 }
378 getports:
379                 if (!off && (fin->fin_dlen > 3)) {
380                         fin->fin_data[0] = ntohs(tcp->th_sport);
381                         fin->fin_data[1] = ntohs(tcp->th_dport);
382                 }
383                 break;
384         case IPPROTO_ESP :
385 #ifdef  USE_INET6
386                 if (v == 6) {
387                         if (plen < 8)
388                                 fi->fi_fl |= FI_SHORT;
389                 } else
390 #endif
391                 if (v == 4) {
392                         if (((ip->ip_len < hlen + 8) && !off) ||
393                             (off && off < 8))
394                                 fi->fi_fl |= FI_SHORT;
395                 }
396                 break;
397         default :
398                 break;
399         }
400
401 #ifdef  USE_INET6
402         if (v == 6) {
403                 fi->fi_optmsk = 0;
404                 fi->fi_secmsk = 0;
405                 fi->fi_auth = 0;
406                 return;
407         }
408 #endif
409
410         for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) {
411                 opt = *s;
412                 if (opt == '\0')
413                         break;
414                 else if (opt == IPOPT_NOP)
415                         ol = 1;
416                 else {
417                         if (hlen < 2)
418                                 break;
419                         ol = (int)*(s + 1);
420                         if (ol < 2 || ol > hlen)
421                                 break;
422                 }
423                 for (i = 9, mv = 4; mv >= 0; ) {
424                         op = ipopts + i;
425                         if (opt == (u_char)op->ol_val) {
426                                 optmsk |= op->ol_bit;
427                                 if (opt == IPOPT_SECURITY) {
428                                         struct optlist *sp;
429                                         u_char  sec;
430                                         int j, m;
431
432                                         sec = *(s + 2); /* classification */
433                                         for (j = 3, m = 2; m >= 0; ) {
434                                                 sp = secopt + j;
435                                                 if (sec == sp->ol_val) {
436                                                         secmsk |= sp->ol_bit;
437                                                         auth = *(s + 3);
438                                                         auth *= 256;
439                                                         auth += *(s + 4);
440                                                         break;
441                                                 }
442                                                 if (sec < sp->ol_val)
443                                                         j -= m--;
444                                                 else
445                                                         j += m--;
446                                         }
447                                 }
448                                 break;
449                         }
450                         if (opt < op->ol_val)
451                                 i -= mv--;
452                         else
453                                 i += mv--;
454                 }
455                 hlen -= ol;
456                 s += ol;
457         }
458         if (auth && !(auth & 0x0100))
459                 auth &= 0xff00;
460         fi->fi_optmsk = optmsk;
461         fi->fi_secmsk = secmsk;
462         fi->fi_auth = auth;
463 }
464
465
466 /*
467  * check an IP packet for TCP/UDP characteristics such as ports and flags.
468  */
469 int fr_tcpudpchk(ft, fin)
470 frtuc_t *ft;
471 fr_info_t *fin;
472 {
473         register u_short po, tup;
474         register char i;
475         register int err = 1;
476
477         /*
478          * Both ports should *always* be in the first fragment.
479          * So far, I cannot find any cases where they can not be.
480          *
481          * compare destination ports
482          */
483         if ((i = (int)ft->ftu_dcmp)) {
484                 po = ft->ftu_dport;
485                 tup = fin->fin_data[1];
486                 /*
487                  * Do opposite test to that required and
488                  * continue if that succeeds.
489                  */
490                 if (!--i && tup != po) /* EQUAL */
491                         err = 0;
492                 else if (!--i && tup == po) /* NOTEQUAL */
493                         err = 0;
494                 else if (!--i && tup >= po) /* LESSTHAN */
495                         err = 0;
496                 else if (!--i && tup <= po) /* GREATERTHAN */
497                         err = 0;
498                 else if (!--i && tup > po) /* LT or EQ */
499                         err = 0;
500                 else if (!--i && tup < po) /* GT or EQ */
501                         err = 0;
502                 else if (!--i &&           /* Out of range */
503                          (tup >= po && tup <= ft->ftu_dtop))
504                         err = 0;
505                 else if (!--i &&           /* In range */
506                          (tup <= po || tup >= ft->ftu_dtop))
507                         err = 0;
508         }
509         /*
510          * compare source ports
511          */
512         if (err && (i = (int)ft->ftu_scmp)) {
513                 po = ft->ftu_sport;
514                 tup = fin->fin_data[0];
515                 if (!--i && tup != po)
516                         err = 0;
517                 else if (!--i && tup == po)
518                         err = 0;
519                 else if (!--i && tup >= po)
520                         err = 0;
521                 else if (!--i && tup <= po)
522                         err = 0;
523                 else if (!--i && tup > po)
524                         err = 0;
525                 else if (!--i && tup < po)
526                         err = 0;
527                 else if (!--i &&           /* Out of range */
528                          (tup >= po && tup <= ft->ftu_stop))
529                         err = 0;
530                 else if (!--i &&           /* In range */
531                          (tup <= po || tup >= ft->ftu_stop))
532                         err = 0;
533         }
534
535         /*
536          * If we don't have all the TCP/UDP header, then how can we
537          * expect to do any sort of match on it ?  If we were looking for
538          * TCP flags, then NO match.  If not, then match (which should
539          * satisfy the "short" class too).
540          */
541         if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
542                 if (fin->fin_fl & FI_SHORT)
543                         return !(ft->ftu_tcpf | ft->ftu_tcpfm);
544                 /*
545                  * Match the flags ?  If not, abort this match.
546                  */
547                 if (ft->ftu_tcpfm &&
548                     ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) {
549                         FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
550                                  ft->ftu_tcpfm, ft->ftu_tcpf));
551                         err = 0;
552                 }
553         }
554         return err;
555 }
556
557 /*
558  * Check the input/output list of rules for a match and result.
559  * Could be per interface, but this gets real nasty when you don't have
560  * kernel sauce.
561  */
562 int fr_scanlist(passin, ip, fin, m)
563 u_32_t passin;
564 ip_t *ip;
565 register fr_info_t *fin;
566 void *m;
567 {
568         register struct frentry *fr;
569         register fr_ip_t *fi = &fin->fin_fi;
570         int rulen, portcmp = 0, off, skip = 0, logged = 0;
571         u_32_t pass, passt, passl;
572         frentry_t *frl;
573
574         frl = NULL;
575         pass = passin;
576         fr = fin->fin_fr;
577         fin->fin_fr = NULL;
578         off = fin->fin_off;
579
580         if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
581                 portcmp = 1;
582
583         for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
584                 if (skip) {
585                         FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags));
586                         skip--;
587                         continue;
588                 }
589                 /*
590                  * In all checks below, a null (zero) value in the
591                  * filter struture is taken to mean a wildcard.
592                  *
593                  * check that we are working for the right interface
594                  */
595 #ifdef  _KERNEL
596 # if    (BSD >= 199306)
597                 if (fin->fin_out != 0) {
598                         if ((fr->fr_oifa &&
599                              (fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif)))
600                                 continue;
601                 }
602 # endif
603 #else
604                 if (opts & (OPT_VERBOSE|OPT_DEBUG))
605                         printf("\n");
606 #endif
607
608                 FR_VERBOSE(("%c", fr->fr_skip ? 's' :
609                                   (pass & FR_PASS) ? 'p' : 
610                                   (pass & FR_AUTH) ? 'a' :
611                                   (pass & FR_ACCOUNT) ? 'A' :
612                                   (pass & FR_NOMATCH) ? 'n' : 'b'));
613
614                 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
615                         continue;
616
617                 FR_VERBOSE((":i"));
618                 {
619                         register u_32_t *ld, *lm, *lip;
620                         register int i;
621
622                         lip = (u_32_t *)fi;
623                         lm = (u_32_t *)&fr->fr_mip;
624                         ld = (u_32_t *)&fr->fr_ip;
625                         i = ((*lip & *lm) != *ld);
626                         FR_DEBUG(("0. %#08x & %#08x != %#08x\n",
627                                    *lip, *lm, *ld));
628                         if (i)
629                                 continue;
630                         /*
631                          * We now know whether the packet version and the
632                          * rule version match, along with protocol, ttl and
633                          * tos.
634                          */
635                         lip++, lm++, ld++;
636                         /*
637                          * Unrolled loops (4 each, for 32 bits).
638                          */
639                         FR_DEBUG(("1a. %#08x & %#08x != %#08x\n",
640                                    *lip, *lm, *ld));
641                         i |= ((*lip++ & *lm++) != *ld++) << 5;
642                         if (fi->fi_v == 6) {
643                                 FR_DEBUG(("1b. %#08x & %#08x != %#08x\n",
644                                            *lip, *lm, *ld));
645                                 i |= ((*lip++ & *lm++) != *ld++) << 5;
646                                 FR_DEBUG(("1c. %#08x & %#08x != %#08x\n",
647                                            *lip, *lm, *ld));
648                                 i |= ((*lip++ & *lm++) != *ld++) << 5;
649                                 FR_DEBUG(("1d. %#08x & %#08x != %#08x\n",
650                                            *lip, *lm, *ld));
651                                 i |= ((*lip++ & *lm++) != *ld++) << 5;
652                         } else {
653                                 lip += 3;
654                                 lm += 3;
655                                 ld += 3;
656                         }
657                         i ^= (fr->fr_flags & FR_NOTSRCIP);
658                         if (i)
659                                 continue;
660                         FR_DEBUG(("2a. %#08x & %#08x != %#08x\n",
661                                    *lip, *lm, *ld));
662                         i |= ((*lip++ & *lm++) != *ld++) << 6;
663                         if (fi->fi_v == 6) {
664                                 FR_DEBUG(("2b. %#08x & %#08x != %#08x\n",
665                                            *lip, *lm, *ld));
666                                 i |= ((*lip++ & *lm++) != *ld++) << 6;
667                                 FR_DEBUG(("2c. %#08x & %#08x != %#08x\n",
668                                            *lip, *lm, *ld));
669                                 i |= ((*lip++ & *lm++) != *ld++) << 6;
670                                 FR_DEBUG(("2d. %#08x & %#08x != %#08x\n",
671                                            *lip, *lm, *ld));
672                                 i |= ((*lip++ & *lm++) != *ld++) << 6;
673                         } else {
674                                 lip += 3;
675                                 lm += 3;
676                                 ld += 3;
677                         }
678                         i ^= (fr->fr_flags & FR_NOTDSTIP);
679                         if (i)
680                                 continue;
681                         FR_DEBUG(("3. %#08x & %#08x != %#08x\n",
682                                    *lip, *lm, *ld));
683                         i |= ((*lip++ & *lm++) != *ld++);
684                         FR_DEBUG(("4. %#08x & %#08x != %#08x\n",
685                                    *lip, *lm, *ld));
686                         i |= ((*lip & *lm) != *ld);
687                         if (i)
688                                 continue;
689                 }
690
691                 /*
692                  * If a fragment, then only the first has what we're looking
693                  * for here...
694                  */
695                 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
696                                  fr->fr_tcpfm))
697                         continue;
698                 if (fi->fi_fl & FI_TCPUDP) {
699                         if (!fr_tcpudpchk(&fr->fr_tuc, fin))
700                                 continue;
701                 } else if (fr->fr_icmpm || fr->fr_icmp) {
702                         if (((fi->fi_p != IPPROTO_ICMP) &&
703                             (fi->fi_p != IPPROTO_ICMPV6)) || off ||
704                             (fin->fin_dlen < 2))
705                                 continue;
706                         if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) {
707                                 FR_DEBUG(("i. %#x & %#x != %#x\n",
708                                          fin->fin_data[0], fr->fr_icmpm,
709                                          fr->fr_icmp));
710                                 continue;
711                         }
712                 }
713                 FR_VERBOSE(("*"));
714
715                 if (fr->fr_flags & FR_NOMATCH) {
716                         passt = passl;
717                         passl = passin;
718                         fin->fin_fr = frl;
719                         frl = NULL;
720                         if (fr->fr_flags & FR_QUICK)
721                                 break;
722                         continue;
723                 }
724
725                 passl = passt;
726                 passt = fr->fr_flags;
727                 frl = fin->fin_fr;
728                 fin->fin_fr = fr;
729 #if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL))
730                 if (securelevel <= 0)
731 #endif
732                         if ((passt & FR_CALLNOW) && fr->fr_func)
733                                 passt = (*fr->fr_func)(passt, ip, fin);
734 #ifdef  IPFILTER_LOG
735                 /*
736                  * Just log this packet...
737                  */
738                 if ((passt & FR_LOGMASK) == FR_LOG) {
739                         if (!IPLLOG(passt, ip, fin, m)) {
740                                 if (passt & FR_LOGORBLOCK)
741                                         passt |= FR_BLOCK|FR_QUICK;
742                                 ATOMIC_INCL(frstats[fin->fin_out].fr_skip);
743                         }
744                         ATOMIC_INCL(frstats[fin->fin_out].fr_pkl);
745                         logged = 1;
746                 }
747 #endif /* IPFILTER_LOG */
748                 ATOMIC_INCL(fr->fr_hits);
749                 if (passt & FR_ACCOUNT)
750                         fr->fr_bytes += (U_QUAD_T)ip->ip_len;
751                 else
752                         fin->fin_icode = fr->fr_icode;
753                 fin->fin_rule = rulen;
754                 fin->fin_group = fr->fr_group;
755                 if (fr->fr_grp != NULL) {
756                         fin->fin_fr = fr->fr_grp;
757                         passt = fr_scanlist(passt, ip, fin, m);
758                         if (fin->fin_fr == NULL) {
759                                 fin->fin_rule = rulen;
760                                 fin->fin_group = fr->fr_group;
761                                 fin->fin_fr = fr;
762                         }
763                         if (passt & FR_DONTCACHE)
764                                 logged = 1;
765                 }
766                 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
767                         pass = passt;
768                 FR_DEBUG(("pass %#x\n", pass));
769                 if (passt & FR_QUICK)
770                         break;
771         }
772         if (logged)
773                 pass |= FR_DONTCACHE;
774         pass |= (fi->fi_fl << 24);
775         return pass;
776 }
777
778
779 /*
780  * frcheck - filter check
781  * check using source and destination addresses/ports in a packet whether
782  * or not to pass it on or not.
783  */
784 int fr_check(ip, hlen, ifp, out
785 #if defined(_KERNEL) && SOLARIS
786 , qif, mp)
787 qif_t *qif;
788 #else
789 , mp)
790 #endif
791 mb_t **mp;
792 ip_t *ip;
793 int hlen;
794 void *ifp;
795 int out;
796 {
797         /*
798          * The above really sucks, but short of writing a diff
799          */
800         fr_info_t frinfo, *fc;
801         register fr_info_t *fin = &frinfo;
802         int changed, error = EHOSTUNREACH, v = ip->ip_v;
803         frentry_t *fr = NULL, *list;
804         u_32_t pass, apass;
805 #if !SOLARIS || !defined(_KERNEL)
806         register mb_t *m = *mp;
807 #endif
808
809 #ifdef  _KERNEL
810         int p, len, drop = 0, logit = 0;
811         mb_t *mc = NULL;
812 # if !defined(__SVR4) && !defined(__svr4__)
813 #  ifdef __sgi
814         char hbuf[128];
815 #  endif
816         int up;
817
818 #  if !SOLARIS && !defined(NETBSD_PF) && \
819       ((defined(__FreeBSD__) && (__FreeBSD_version < 500011)) || \
820        defined(__OpenBSD__) || defined(_BSDI_VERSION))
821         if (fr_checkp != fr_check && fr_running > 0) {
822                 static int counter = 0;
823
824                 if (counter == 0) {
825                         printf("WARNING: fr_checkp corrupt: value %lx\n",
826                                 (u_long)fr_checkp);
827                         printf("WARNING: fr_checkp should be %lx\n",
828                                 (u_long)fr_check);
829                         printf("WARNING: fixing fr_checkp\n");
830                 }
831                 fr_checkp = fr_check;
832                 counter++;
833                 if (counter == 10000)
834                         counter = 0;
835         }
836 #  endif
837
838 #  ifdef M_CANFASTFWD
839         /*
840          * XXX For now, IP Filter and fast-forwarding of cached flows
841          * XXX are mutually exclusive.  Eventually, IP Filter should
842          * XXX get a "can-fast-forward" filter rule.
843          */
844         m->m_flags &= ~M_CANFASTFWD;
845 #  endif /* M_CANFASTFWD */
846 #  ifdef CSUM_DELAY_DATA
847         /*
848          * disable delayed checksums.
849          */
850         if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) {
851                 in_delayed_cksum(m);
852                 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
853         }
854 #  endif /* CSUM_DELAY_DATA */
855
856 # ifdef USE_INET6
857         if (v == 6) {
858                 len = ntohs(((ip6_t*)ip)->ip6_plen);
859                 if (!len)
860                         return -1;      /* potential jumbo gram */
861                 len += sizeof(ip6_t);
862                 p = ((ip6_t *)ip)->ip6_nxt;
863         } else
864 # endif
865         {
866                 p = ip->ip_p;
867                 len = ip->ip_len;
868         }
869
870         if ((p == IPPROTO_TCP || p == IPPROTO_UDP ||
871             (v == 4 && p == IPPROTO_ICMP)
872 # ifdef USE_INET6
873             || (v == 6 && p == IPPROTO_ICMPV6)
874 # endif
875            )) {
876                 int plen = 0;
877
878                 if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0)
879                         switch(p)
880                         {
881                         case IPPROTO_TCP:
882                                 plen = sizeof(tcphdr_t);
883                                 break;
884                         case IPPROTO_UDP:
885                                 plen = sizeof(udphdr_t);
886                                 break;
887                         /* 96 - enough for complete ICMP error IP header */
888                         case IPPROTO_ICMP:
889                                 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
890                                 break;
891                         case IPPROTO_ESP:
892                                 plen = 8;
893                                 break;
894 # ifdef USE_INET6
895                         case IPPROTO_ICMPV6 :
896                                 /*
897                                  * XXX does not take intermediate header
898                                  * into account
899                                  */
900                                 plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t);
901                                 break;
902 # endif
903                         }
904                 up = MIN(hlen + plen, len);
905
906                 if (up > m->m_len) {
907 #  ifdef __sgi
908         /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
909                         if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
910                                 ATOMIC_INCL(frstats[out].fr_pull[1]);
911                                 return -1;
912                         }
913                         m_copydata(m, 0, up, hbuf);
914                         ATOMIC_INCL(frstats[out].fr_pull[0]);
915                         ip = (ip_t *)hbuf;
916 #  else /* __ sgi */
917 #   ifndef linux
918                         if ((*mp = m_pullup(m, up)) == 0) {
919                                 ATOMIC_INCL(frstats[out].fr_pull[1]);
920                                 return -1;
921                         } else {
922                                 ATOMIC_INCL(frstats[out].fr_pull[0]);
923                                 m = *mp;
924                                 ip = mtod(m, ip_t *);
925                         }
926 #   endif /* !linux */
927 #  endif /* __sgi */
928                 } else
929                         up = 0;
930         } else
931                 up = 0;
932 # endif /* !defined(__SVR4) && !defined(__svr4__) */
933 # if SOLARIS
934         mb_t *m = qif->qf_m;
935
936         if ((u_int)ip & 0x3)
937                 return 2;
938         fin->fin_qfm = m;
939         fin->fin_qif = qif;
940 # endif
941 #endif /* _KERNEL */
942         
943         changed = 0;
944         fin->fin_ifp = ifp;
945         fin->fin_v = v;
946         fin->fin_out = out;
947         fin->fin_mp = mp;
948         fr_makefrip(hlen, ip, fin);
949
950 #ifdef _KERNEL
951 # ifdef USE_INET6
952         if (v == 6) {
953                 ATOMIC_INCL(frstats[0].fr_ipv6[out]);
954                 if (((ip6_t *)ip)->ip6_hlim < fr_minttl) {
955                         ATOMIC_INCL(frstats[0].fr_badttl);
956                         if (fr_minttllog & 1)
957                                 logit = -3;
958                         if (fr_minttllog & 2)
959                                 drop = 1;
960                 }
961         } else
962 # endif
963         if (!out) {
964                 if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) {
965                         ATOMIC_INCL(frstats[0].fr_badsrc);
966                         if (fr_chksrc & 1)
967                                 drop = 1;
968                         if (fr_chksrc & 2)
969                                 logit = -2;
970                 } else if (ip->ip_ttl < fr_minttl) {
971                         ATOMIC_INCL(frstats[0].fr_badttl);
972                         if (fr_minttllog & 1)
973                                 logit = -3;
974                         if (fr_minttllog & 2)
975                                 drop = 1;
976                 }
977         }
978         if (drop) {
979 # ifdef IPFILTER_LOG
980                 if (logit) {
981                         fin->fin_group = logit;
982                         pass = FR_INQUE|FR_NOMATCH|FR_LOGB;
983                         (void) IPLLOG(pass, ip, fin, m);
984                 }
985 # endif
986 # if !SOLARIS
987                 m_freem(m);
988 # endif
989                 return error;
990         }
991 #endif
992         pass = fr_pass;
993         if (fin->fin_fl & FI_SHORT) {
994                 ATOMIC_INCL(frstats[out].fr_short);
995         }
996
997         READ_ENTER(&ipf_mutex);
998
999         /*
1000          * Check auth now.  This, combined with the check below to see if apass
1001          * is 0 is to ensure that we don't count the packet twice, which can
1002          * otherwise occur when we reprocess it.  As it is, we only count it
1003          * after it has no auth. table matchup.  This also stops NAT from
1004          * occuring until after the packet has been auth'd.
1005          */
1006         apass = fr_checkauth(ip, fin);
1007
1008         if (!out) {
1009 #ifdef  USE_INET6
1010                 if (v == 6)
1011                         list = ipacct6[0][fr_active];
1012                 else
1013 #endif
1014                         list = ipacct[0][fr_active];
1015                 changed = ip_natin(ip, fin);
1016                 if (!apass && (fin->fin_fr = list) &&
1017                     (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
1018                         ATOMIC_INCL(frstats[0].fr_acct);
1019                 }
1020         }
1021
1022         if (!apass) {
1023                 if ((fin->fin_fl & FI_FRAG) == FI_FRAG)
1024                         fr = ipfr_knownfrag(ip, fin);
1025                 if (!fr && !(fin->fin_fl & FI_SHORT))
1026                         fr = fr_checkstate(ip, fin);
1027                 if (fr != NULL)
1028                         pass = fr->fr_flags;
1029                 if (fr && (pass & FR_LOGFIRST))
1030                         pass &= ~(FR_LOGFIRST|FR_LOG);
1031         }
1032
1033         if (apass || !fr) {
1034                 /*
1035                  * If a packet is found in the auth table, then skip checking
1036                  * the access lists for permission but we do need to consider
1037                  * the result as if it were from the ACL's.
1038                  */
1039                 if (!apass) {
1040                         fc = frcache + out;
1041                         if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
1042                                 /*
1043                                  * copy cached data so we can unlock the mutex
1044                                  * earlier.
1045                                  */
1046                                 bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
1047                                 ATOMIC_INCL(frstats[out].fr_chit);
1048                                 if ((fr = fin->fin_fr)) {
1049                                         ATOMIC_INCL(fr->fr_hits);
1050                                         pass = fr->fr_flags;
1051                                 }
1052                         } else {
1053 #ifdef  USE_INET6
1054                                 if (v == 6)
1055                                         list = ipfilter6[out][fr_active];
1056                                 else
1057 #endif
1058                                         list = ipfilter[out][fr_active];
1059                                 if ((fin->fin_fr = list))
1060                                         pass = fr_scanlist(fr_pass, ip, fin, m);
1061                                 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
1062                                         bcopy((char *)fin, (char *)fc,
1063                                               FI_COPYSIZE);
1064                                 if (pass & FR_NOMATCH) {
1065                                         ATOMIC_INCL(frstats[out].fr_nom);
1066                                         fin->fin_fr = NULL;
1067                                 }
1068                         }
1069                 } else
1070                         pass = apass;
1071                 fr = fin->fin_fr;
1072
1073                 /*
1074                  * If we fail to add a packet to the authorization queue,
1075                  * then we drop the packet later.  However, if it was added
1076                  * then pretend we've dropped it already.
1077                  */
1078                 if ((pass & FR_AUTH)) {
1079                         if (fr_newauth((mb_t *)m, fin, ip) != 0) {
1080                                 m = *mp = NULL;
1081                                 error = 0;
1082                         } else
1083                                 error = ENOSPC;
1084                 }
1085
1086                 if (pass & FR_PREAUTH) {
1087                         READ_ENTER(&ipf_auth);
1088                         if ((fin->fin_fr = ipauth) &&
1089                             (pass = fr_scanlist(0, ip, fin, m))) {
1090                                 ATOMIC_INCL(fr_authstats.fas_hits);
1091                         } else {
1092                                 ATOMIC_INCL(fr_authstats.fas_miss);
1093                         }
1094                         RWLOCK_EXIT(&ipf_auth);
1095                 }
1096
1097                 fin->fin_fr = fr;
1098                 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
1099                         if (fin->fin_fl & FI_FRAG) {
1100                                 if (ipfr_newfrag(ip, fin) == -1) {
1101                                         ATOMIC_INCL(frstats[out].fr_bnfr);
1102                                 } else {
1103                                         ATOMIC_INCL(frstats[out].fr_nfr);
1104                                 }
1105                         } else {
1106                                 ATOMIC_INCL(frstats[out].fr_cfr);
1107                         }
1108                 }
1109                 if (pass & FR_KEEPSTATE) {
1110                         if (fr_addstate(ip, fin, NULL, 0) == NULL) {
1111                                 ATOMIC_INCL(frstats[out].fr_bads);
1112                         } else {
1113                                 ATOMIC_INCL(frstats[out].fr_ads);
1114                         }
1115                 }
1116         } else if (fr != NULL) {
1117                 pass = fr->fr_flags;
1118                 if (pass & FR_LOGFIRST)
1119                         pass &= ~(FR_LOGFIRST|FR_LOG);
1120         }
1121
1122 #if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL))
1123         if (securelevel <= 0)
1124 #endif
1125                 if (fr && fr->fr_func && !(pass & FR_CALLNOW))
1126                         pass = (*fr->fr_func)(pass, ip, fin);
1127
1128         /*
1129          * Only count/translate packets which will be passed on, out the
1130          * interface.
1131          */
1132         if (out && (pass & FR_PASS)) {
1133 #ifdef  USE_INET6
1134                 if (v == 6)
1135                         list = ipacct6[1][fr_active];
1136                 else
1137 #endif
1138                         list = ipacct[1][fr_active];
1139                 if (list != NULL) {
1140                         u_32_t sg, sr;
1141
1142                         fin->fin_fr = list;
1143                         sg = fin->fin_group;
1144                         sr = fin->fin_rule;
1145                         if (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT) {
1146                                 ATOMIC_INCL(frstats[1].fr_acct);
1147                         }
1148                         fin->fin_group = sg;
1149                         fin->fin_rule = sr;
1150                         fin->fin_fr = fr;
1151                 }
1152                 changed = ip_natout(ip, fin);
1153         } else
1154                 fin->fin_fr = fr;
1155         RWLOCK_EXIT(&ipf_mutex);
1156
1157 #ifdef  IPFILTER_LOG
1158         if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
1159                 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
1160                         pass |= FF_LOGNOMATCH;
1161                         ATOMIC_INCL(frstats[out].fr_npkl);
1162                         goto logit;
1163                 } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
1164                     ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
1165                         if ((pass & FR_LOGMASK) != FR_LOGP)
1166                                 pass |= FF_LOGPASS;
1167                         ATOMIC_INCL(frstats[out].fr_ppkl);
1168                         goto logit;
1169                 } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
1170                            ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
1171                         if ((pass & FR_LOGMASK) != FR_LOGB)
1172                                 pass |= FF_LOGBLOCK;
1173                         ATOMIC_INCL(frstats[out].fr_bpkl);
1174 logit:
1175                         if (!IPLLOG(pass, ip, fin, m)) {
1176                                 ATOMIC_INCL(frstats[out].fr_skip);
1177                                 if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
1178                                     (FR_PASS|FR_LOGORBLOCK))
1179                                         pass ^= FR_PASS|FR_BLOCK;
1180                         }
1181                 }
1182         }
1183 #endif /* IPFILTER_LOG */
1184
1185 #ifdef  _KERNEL
1186         /*
1187          * Only allow FR_DUP to work if a rule matched - it makes no sense to
1188          * set FR_DUP as a "default" as there are no instructions about where
1189          * to send the packet.
1190          */
1191         if (fr && (pass & FR_DUP))
1192 # if    SOLARIS
1193                 mc = dupmsg(m);
1194 # else
1195 #  if defined(__OpenBSD__) && (OpenBSD >= 199905)
1196                 mc = m_copym2(m, 0, M_COPYALL, M_DONTWAIT);
1197 #  else
1198                 mc = m_copy(m, 0, M_COPYALL);
1199 #  endif
1200 # endif
1201 #endif
1202         if (pass & FR_PASS) {
1203                 ATOMIC_INCL(frstats[out].fr_pass);
1204         } else if (pass & FR_BLOCK) {
1205                 ATOMIC_INCL(frstats[out].fr_block);
1206                 /*
1207                  * Should we return an ICMP packet to indicate error
1208                  * status passing through the packet filter ?
1209                  * WARNING: ICMP error packets AND TCP RST packets should
1210                  * ONLY be sent in repsonse to incoming packets.  Sending them
1211                  * in response to outbound packets can result in a panic on
1212                  * some operating systems.
1213                  */
1214                 if (!out) {
1215                         if (changed == -1)
1216                                 /*
1217                                  * If a packet results in a NAT error, do not
1218                                  * send a reset or ICMP error as it may disrupt
1219                                  * an existing flow.  This is the proxy saying
1220                                  * the content is bad so just drop the packet
1221                                  * silently.
1222                                  */
1223                                 ;
1224                         else if (pass & FR_RETICMP) {
1225                                 int dst;
1226
1227                                 if ((pass & FR_RETMASK) == FR_FAKEICMP)
1228                                         dst = 1;
1229                                 else
1230                                         dst = 0;
1231                                 send_icmp_err(ip, ICMP_UNREACH, fin, dst);
1232                                 ATOMIC_INCL(frstats[0].fr_ret);
1233                         } else if (((pass & FR_RETMASK) == FR_RETRST) &&
1234                                    !(fin->fin_fl & FI_SHORT)) {
1235                                 if (send_reset(ip, fin) == 0) {
1236                                         ATOMIC_INCL(frstats[1].fr_ret);
1237                                 }
1238                         }
1239                 } else {
1240                         if (pass & FR_RETRST)
1241                                 error = ECONNRESET;
1242                 }
1243         }
1244
1245         /*
1246          * If we didn't drop off the bottom of the list of rules (and thus
1247          * the 'current' rule fr is not NULL), then we may have some extra
1248          * instructions about what to do with a packet.
1249          * Once we're finished return to our caller, freeing the packet if
1250          * we are dropping it (* BSD ONLY *).
1251          */
1252         if ((changed == -1) && (pass & FR_PASS)) {
1253                 pass &= ~FR_PASS;
1254                 pass |= FR_BLOCK;
1255         }
1256 #if defined(_KERNEL)
1257 # if !SOLARIS
1258 #  if !defined(linux)
1259         if (fr) {
1260                 frdest_t *fdp = &fr->fr_tif;
1261
1262                 if (((pass & FR_FASTROUTE) && !out) ||
1263                     (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
1264                         (void) ipfr_fastroute(m, mp, fin, fdp);
1265                         m = *mp;
1266                 }
1267
1268                 if (mc != NULL)
1269                         (void) ipfr_fastroute(mc, &mc, fin, &fr->fr_dif);
1270         }
1271
1272         if (!(pass & FR_PASS) && m) {
1273                 m_freem(m);
1274                 m = *mp = NULL;
1275         }
1276 #   ifdef __sgi
1277         else if (changed && up && m)
1278                 m_copyback(m, 0, up, hbuf);
1279 #   endif
1280 #  endif /* !linux */
1281 # else /* !SOLARIS */
1282         if (fr) {
1283                 frdest_t *fdp = &fr->fr_tif;
1284
1285                 if (((pass & FR_FASTROUTE) && !out) ||
1286                     (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))
1287                         (void) ipfr_fastroute(ip, m, mp, fin, fdp);
1288
1289                 if (mc != NULL)
1290                         (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif);
1291         }
1292 # endif /* !SOLARIS */
1293         return (pass & FR_PASS) ? 0 : error;
1294 #else /* _KERNEL */
1295         if (pass & FR_NOMATCH)
1296                 return 1;
1297         if (pass & FR_PASS)
1298                 return 0;
1299         if (pass & FR_AUTH)
1300                 return -2;
1301         if ((pass & FR_RETMASK) == FR_RETRST)
1302                 return -3;
1303         if ((pass & FR_RETMASK) == FR_RETICMP)
1304                 return -4;
1305         if ((pass & FR_RETMASK) == FR_FAKEICMP)
1306                 return -5;
1307         return -1;
1308 #endif /* _KERNEL */
1309 }
1310
1311
1312 /*
1313  * ipf_cksum
1314  * addr should be 16bit aligned and len is in bytes.
1315  * length is in bytes
1316  */
1317 u_short ipf_cksum(addr, len)
1318 register u_short *addr;
1319 register int len;
1320 {
1321         register u_32_t sum = 0;
1322
1323         for (sum = 0; len > 1; len -= 2)
1324                 sum += *addr++;
1325
1326         /* mop up an odd byte, if necessary */
1327         if (len == 1)
1328                 sum += *(u_char *)addr;
1329
1330         /*
1331          * add back carry outs from top 16 bits to low 16 bits
1332          */
1333         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
1334         sum += (sum >> 16);                     /* add carry */
1335         return (u_short)(~sum);
1336 }
1337
1338
1339 /*
1340  * NB: This function assumes we've pullup'd enough for all of the IP header
1341  * and the TCP header.  We also assume that data blocks aren't allocated in
1342  * odd sizes.
1343  */
1344 u_short fr_tcpsum(m, ip, tcp)
1345 mb_t *m;
1346 ip_t *ip;
1347 tcphdr_t *tcp;
1348 {
1349         u_short *sp, slen, ts;
1350         u_int sum, sum2;
1351         int hlen;
1352
1353         /*
1354          * Add up IP Header portion
1355          */
1356         hlen = ip->ip_hl << 2;
1357         slen = ip->ip_len - hlen;
1358         sum = htons((u_short)ip->ip_p);
1359         sum += htons(slen);
1360         sp = (u_short *)&ip->ip_src;
1361         sum += *sp++;   /* ip_src */
1362         sum += *sp++;
1363         sum += *sp++;   /* ip_dst */
1364         sum += *sp++;
1365         ts = tcp->th_sum;
1366         tcp->th_sum = 0;
1367 #ifdef  KERNEL
1368 # if SOLARIS
1369         sum2 = ip_cksum(m, hlen, sum);  /* hlen == offset */
1370         sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1371         sum2 = ~sum2 & 0xffff;
1372 # else /* SOLARIS */
1373 #  if defined(BSD) || defined(sun)
1374 #   if BSD >= 199306
1375         m->m_data += hlen;
1376 #   else
1377         m->m_off += hlen;
1378 #   endif
1379         m->m_len -= hlen;
1380         sum2 = in_cksum(m, slen);
1381         m->m_len += hlen;
1382 #   if BSD >= 199306
1383         m->m_data -= hlen;
1384 #   else
1385         m->m_off -= hlen;
1386 #   endif
1387         /*
1388          * Both sum and sum2 are partial sums, so combine them together.
1389          */
1390         sum = (sum & 0xffff) + (sum >> 16);
1391         sum = ~sum & 0xffff;
1392         sum2 += sum;
1393         sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1394 #  else /* defined(BSD) || defined(sun) */
1395 {
1396         union {
1397                 u_char  c[2];
1398                 u_short s;
1399         } bytes;
1400         u_short len = ip->ip_len;
1401 # if defined(__sgi)
1402         int add;
1403 # endif
1404
1405         /*
1406          * Add up IP Header portion
1407          */
1408         sp = (u_short *)&ip->ip_src;
1409         len -= (ip->ip_hl << 2);
1410         sum = ntohs(IPPROTO_TCP);
1411         sum += htons(len);
1412         sum += *sp++;   /* ip_src */
1413         sum += *sp++;
1414         sum += *sp++;   /* ip_dst */
1415         sum += *sp++;
1416         if (sp != (u_short *)tcp)
1417                 sp = (u_short *)tcp;
1418         sum += *sp++;   /* sport */
1419         sum += *sp++;   /* dport */
1420         sum += *sp++;   /* seq */
1421         sum += *sp++;
1422         sum += *sp++;   /* ack */
1423         sum += *sp++;
1424         sum += *sp++;   /* off */
1425         sum += *sp++;   /* win */
1426         sum += *sp++;   /* Skip over checksum */
1427         sum += *sp++;   /* urp */
1428
1429 # ifdef __sgi
1430         /*
1431          * In case we had to copy the IP & TCP header out of mbufs,
1432          * skip over the mbuf bits which are the header
1433          */
1434         if ((caddr_t)ip != mtod(m, caddr_t)) {
1435                 hlen = (caddr_t)sp - (caddr_t)ip;
1436                 while (hlen) {
1437                         add = MIN(hlen, m->m_len);
1438                         sp = (u_short *)(mtod(m, caddr_t) + add);
1439                         hlen -= add;
1440                         if (add == m->m_len) {
1441                                 m = m->m_next;
1442                                 if (!hlen) {
1443                                         if (!m)
1444                                                 break;
1445                                         sp = mtod(m, u_short *);
1446                                 }
1447                                 PANIC((!m),("fr_tcpsum(1): not enough data"));
1448                         }
1449                 }
1450         }
1451 # endif
1452
1453         if (!(len -= sizeof(*tcp)))
1454                 goto nodata;
1455         while (len > 1) {
1456                 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
1457                         m = m->m_next;
1458                         PANIC((!m),("fr_tcpsum(2): not enough data"));
1459                         sp = mtod(m, u_short *);
1460                 }
1461                 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
1462                         bytes.c[0] = *(u_char *)sp;
1463                         m = m->m_next;
1464                         PANIC((!m),("fr_tcpsum(3): not enough data"));
1465                         sp = mtod(m, u_short *);
1466                         bytes.c[1] = *(u_char *)sp;
1467                         sum += bytes.s;
1468                         sp = (u_short *)((u_char *)sp + 1);
1469                 }
1470                 if ((u_long)sp & 1) {
1471                         bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
1472                         sum += bytes.s;
1473                 } else
1474                         sum += *sp++;
1475                 len -= 2;
1476         }
1477         if (len)
1478                 sum += ntohs(*(u_char *)sp << 8);
1479 nodata:
1480         while (sum > 0xffff)
1481                 sum = (sum & 0xffff) + (sum >> 16);
1482         sum2 = (u_short)(~sum & 0xffff);
1483 }
1484 #  endif /*  defined(BSD) || defined(sun) */
1485 # endif /* SOLARIS */
1486 #else /* KERNEL */
1487         for (; slen > 1; slen -= 2)
1488                 sum += *sp++;
1489         if (slen)
1490                 sum += ntohs(*(u_char *)sp << 8);
1491         while (sum > 0xffff)
1492                 sum = (sum & 0xffff) + (sum >> 16);
1493         sum2 = (u_short)(~sum & 0xffff);
1494 #endif /* KERNEL */
1495         tcp->th_sum = ts;
1496         return sum2;
1497 }
1498
1499
1500 #if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1501 /*
1502  * Copyright (c) 1982, 1986, 1988, 1991, 1993
1503  *      The Regents of the University of California.  All rights reserved.
1504  *
1505  * Redistribution and use in source and binary forms, with or without
1506  * modification, are permitted provided that the following conditions
1507  * are met:
1508  * 1. Redistributions of source code must retain the above copyright
1509  *    notice, this list of conditions and the following disclaimer.
1510  * 2. Redistributions in binary form must reproduce the above copyright
1511  *    notice, this list of conditions and the following disclaimer in the
1512  *    documentation and/or other materials provided with the distribution.
1513  * 3. All advertising materials mentioning features or use of this software
1514  *    must display the following acknowledgement:
1515  *      This product includes software developed by the University of
1516  *      California, Berkeley and its contributors.
1517  * 4. Neither the name of the University nor the names of its contributors
1518  *    may be used to endorse or promote products derived from this software
1519  *    without specific prior written permission.
1520  *
1521  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1522  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1523  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1524  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1525  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1526  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1527  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1528  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1529  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1530  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1531  * SUCH DAMAGE.
1532  *
1533  *      @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1534  * $Id: fil.c,v 2.35.2.67 2002/12/06 13:28:05 darrenr Exp $
1535  */
1536 /*
1537  * Copy data from an mbuf chain starting "off" bytes from the beginning,
1538  * continuing for "len" bytes, into the indicated buffer.
1539  */
1540 void
1541 m_copydata(m, off, len, cp)
1542         register mb_t *m;
1543         register int off;
1544         register int len;
1545         caddr_t cp;
1546 {
1547         register unsigned count;
1548
1549         if (off < 0 || len < 0)
1550                 panic("m_copydata");
1551         while (off > 0) {
1552                 if (m == 0)
1553                         panic("m_copydata");
1554                 if (off < m->m_len)
1555                         break;
1556                 off -= m->m_len;
1557                 m = m->m_next;
1558         }
1559         while (len > 0) {
1560                 if (m == 0)
1561                         panic("m_copydata");
1562                 count = MIN(m->m_len - off, len);
1563                 bcopy(mtod(m, caddr_t) + off, cp, count);
1564                 len -= count;
1565                 cp += count;
1566                 off = 0;
1567                 m = m->m_next;
1568         }
1569 }
1570
1571
1572 # ifndef linux
1573 /*
1574  * Copy data from a buffer back into the indicated mbuf chain,
1575  * starting "off" bytes from the beginning, extending the mbuf
1576  * chain if necessary.
1577  */
1578 void
1579 m_copyback(m0, off, len, cp)
1580         struct  mbuf *m0;
1581         register int off;
1582         register int len;
1583         caddr_t cp;
1584 {
1585         register int mlen;
1586         register struct mbuf *m = m0, *n;
1587         int totlen = 0;
1588
1589         if (m0 == 0)
1590                 return;
1591         while (off > (mlen = m->m_len)) {
1592                 off -= mlen;
1593                 totlen += mlen;
1594                 if (m->m_next == 0) {
1595                         n = m_getclr(M_DONTWAIT, m->m_type);
1596                         if (n == 0)
1597                                 goto out;
1598                         n->m_len = min(MLEN, len + off);
1599                         m->m_next = n;
1600                 }
1601                 m = m->m_next;
1602         }
1603         while (len > 0) {
1604                 mlen = min (m->m_len - off, len);
1605                 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1606                 cp += mlen;
1607                 len -= mlen;
1608                 mlen += off;
1609                 off = 0;
1610                 totlen += mlen;
1611                 if (len == 0)
1612                         break;
1613                 if (m->m_next == 0) {
1614                         n = m_get(M_DONTWAIT, m->m_type);
1615                         if (n == 0)
1616                                 break;
1617                         n->m_len = min(MLEN, len);
1618                         m->m_next = n;
1619                 }
1620                 m = m->m_next;
1621         }
1622 out:
1623 #if 0
1624         if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1625                 m->m_pkthdr.len = totlen;
1626 #endif
1627         return;
1628 }
1629 # endif /* linux */
1630 #endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1631
1632
1633 frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
1634 u_32_t num, flags;
1635 minor_t which;
1636 int set;
1637 frgroup_t ***fgpp;
1638 {
1639         frgroup_t *fg, **fgp;
1640
1641         if (which == IPL_LOGAUTH)
1642                 fgp = &ipfgroups[2][set];
1643         else if (flags & FR_ACCOUNT)
1644                 fgp = &ipfgroups[1][set];
1645         else if (flags & (FR_OUTQUE|FR_INQUE))
1646                 fgp = &ipfgroups[0][set];
1647         else
1648                 return NULL;
1649
1650         while ((fg = *fgp))
1651                 if (fg->fg_num == num)
1652                         break;
1653                 else
1654                         fgp = &fg->fg_next;
1655         if (fgpp)
1656                 *fgpp = fgp;
1657         return fg;
1658 }
1659
1660
1661 frgroup_t *fr_addgroup(num, fp, which, set)
1662 u_32_t num;
1663 frentry_t *fp;
1664 minor_t which;
1665 int set;
1666 {
1667         frgroup_t *fg, **fgp;
1668
1669         if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
1670                 return fg;
1671
1672         KMALLOC(fg, frgroup_t *);
1673         if (fg) {
1674                 fg->fg_num = num;
1675                 fg->fg_next = *fgp;
1676                 fg->fg_head = fp;
1677                 fg->fg_start = &fp->fr_grp;
1678                 *fgp = fg;
1679         }
1680         return fg;
1681 }
1682
1683
1684 void fr_delgroup(num, flags, which, set)
1685 u_32_t num, flags;
1686 minor_t which;
1687 int set;
1688 {
1689         frgroup_t *fg, **fgp;
1690  
1691         if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
1692                 return;
1693  
1694         *fgp = fg->fg_next;
1695         KFREE(fg);
1696 }
1697
1698
1699
1700 /*
1701  * recursively flush rules from the list, descending groups as they are
1702  * encountered.  if a rule is the head of a group and it has lost all its
1703  * group members, then also delete the group reference.
1704  */
1705 static int frflushlist(set, unit, nfreedp, listp)
1706 int set;
1707 minor_t unit;
1708 int *nfreedp;
1709 frentry_t **listp;
1710 {
1711         register int freed = 0, i;
1712         register frentry_t *fp;
1713
1714         while ((fp = *listp)) {
1715                 *listp = fp->fr_next;
1716                 if (fp->fr_grp) {
1717                         i = frflushlist(set, unit, nfreedp, &fp->fr_grp);
1718                         MUTEX_ENTER(&ipf_rw);
1719                         fp->fr_ref -= i;
1720                         MUTEX_EXIT(&ipf_rw);
1721                 }
1722
1723                 ATOMIC_DEC32(fp->fr_ref);
1724                 if (fp->fr_grhead) {
1725                         fr_delgroup(fp->fr_grhead, fp->fr_flags, 
1726                                     unit, set);
1727                         fp->fr_grhead = 0;
1728                 }
1729                 if (fp->fr_ref == 0) {
1730                         KFREE(fp);
1731                         freed++;
1732                 } else
1733                         fp->fr_next = NULL;
1734         }
1735         *nfreedp += freed;
1736         return freed;
1737 }
1738
1739
1740 int frflush(unit, proto, flags)
1741 minor_t unit;
1742 int proto, flags;
1743 {
1744         int flushed = 0, set;
1745
1746         if (unit != IPL_LOGIPF)
1747                 return 0;
1748         WRITE_ENTER(&ipf_mutex);
1749         bzero((char *)frcache, sizeof(frcache[0]) * 2);
1750
1751         set = fr_active;
1752         if (flags & FR_INACTIVE)
1753                 set = 1 - set;
1754
1755         if (flags & FR_OUTQUE) {
1756 #ifdef  USE_INET6
1757                 if (proto == 0 || proto == 6) {
1758                         (void) frflushlist(set, unit,
1759                                            &flushed, &ipfilter6[1][set]);
1760                         (void) frflushlist(set, unit,
1761                                            &flushed, &ipacct6[1][set]);
1762                 }
1763 #endif
1764                 if (proto == 0 || proto == 4) {
1765                         (void) frflushlist(set, unit,
1766                                            &flushed, &ipfilter[1][set]);
1767                         (void) frflushlist(set, unit,
1768                                            &flushed, &ipacct[1][set]);
1769                 }
1770         }
1771         if (flags & FR_INQUE) {
1772 #ifdef  USE_INET6
1773                 if (proto == 0 || proto == 6) {
1774                         (void) frflushlist(set, unit,
1775                                             &flushed, &ipfilter6[0][set]);
1776                         (void) frflushlist(set, unit,
1777                                            &flushed, &ipacct6[0][set]);
1778                 }
1779 #endif
1780                 if (proto == 0 || proto == 4) {
1781                         (void) frflushlist(set, unit,
1782                                            &flushed, &ipfilter[0][set]);
1783                         (void) frflushlist(set, unit,
1784                                            &flushed, &ipacct[0][set]);
1785                 }
1786         }
1787         RWLOCK_EXIT(&ipf_mutex);
1788         return flushed;
1789 }
1790
1791
1792 char *memstr(src, dst, slen, dlen)
1793 char *src, *dst;
1794 int slen, dlen;
1795 {
1796         char *s = NULL;
1797
1798         while (dlen >= slen) {
1799                 if (bcmp(src, dst, slen) == 0) {
1800                         s = dst;
1801                         break;
1802                 }
1803                 dst++;
1804                 dlen--;
1805         }
1806         return s;
1807 }
1808
1809
1810 void fixskip(listp, rp, addremove)
1811 frentry_t **listp, *rp;
1812 int addremove;
1813 {
1814         frentry_t *fp;
1815         int rules = 0, rn = 0;
1816
1817         for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
1818                 ;
1819
1820         if (!fp)
1821                 return;
1822
1823         for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
1824                 if (fp->fr_skip && (rn + fp->fr_skip >= rules))
1825                         fp->fr_skip += addremove;
1826 }
1827
1828
1829 #ifdef  _KERNEL
1830 /*
1831  * count consecutive 1's in bit mask.  If the mask generated by counting
1832  * consecutive 1's is different to that passed, return -1, else return #
1833  * of bits.
1834  */
1835 int     countbits(ip)
1836 u_32_t  ip;
1837 {
1838         u_32_t  ipn;
1839         int     cnt = 0, i, j;
1840
1841         ip = ipn = ntohl(ip);
1842         for (i = 32; i; i--, ipn *= 2)
1843                 if (ipn & 0x80000000)
1844                         cnt++;
1845                 else
1846                         break;
1847         ipn = 0;
1848         for (i = 32, j = cnt; i; i--, j--) {
1849                 ipn *= 2;
1850                 if (j > 0)
1851                         ipn++;
1852         }
1853         if (ipn == ip)
1854                 return cnt;
1855         return -1;
1856 }
1857
1858
1859 /*
1860  * return the first IP Address associated with an interface
1861  */
1862 int fr_ifpaddr(v, ifptr, inp)
1863 int v;
1864 void *ifptr;
1865 struct in_addr *inp;
1866 {
1867 # ifdef USE_INET6
1868         struct in6_addr *inp6 = NULL;
1869 # endif
1870 # if SOLARIS
1871         ill_t *ill = ifptr;
1872 # else
1873         struct ifnet *ifp = ifptr;
1874 # endif
1875         struct in_addr in;
1876
1877 # if SOLARIS
1878 #  ifdef        USE_INET6
1879         if (v == 6) {
1880                 struct in6_addr in6;
1881
1882                 /*
1883                  * First is always link local.
1884                  */
1885                 if (ill->ill_ipif->ipif_next)
1886                         in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr;
1887                 else
1888                         bzero((char *)&in6, sizeof(in6));
1889                 bcopy((char *)&in6, (char *)inp, sizeof(in6));
1890         } else
1891 #  endif
1892         {
1893                 in.s_addr = ill->ill_ipif->ipif_local_addr;
1894                 *inp = in;
1895         }
1896 # else /* SOLARIS */
1897 #  if linux
1898         ;
1899 #  else /* linux */
1900         struct sockaddr_in *sin;
1901         struct ifaddr *ifa;
1902
1903 #   if  (__FreeBSD_version >= 300000)
1904         ifa = TAILQ_FIRST(&ifp->if_addrhead);
1905 #   else
1906 #    if defined(__NetBSD__) || defined(__OpenBSD__)
1907         ifa = ifp->if_addrlist.tqh_first;
1908 #    else
1909 #     if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
1910         ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa;
1911 #     else
1912         ifa = ifp->if_addrlist;
1913 #     endif
1914 #    endif /* __NetBSD__ || __OpenBSD__ */
1915 #   endif /* __FreeBSD_version >= 300000 */
1916 #   if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK))
1917         sin = (struct sockaddr_in *)&ifa->ifa_addr;
1918 #   else
1919         sin = (struct sockaddr_in *)ifa->ifa_addr;
1920         while (sin && ifa) {
1921                 if ((v == 4) && (sin->sin_family == AF_INET))
1922                         break;
1923 #    ifdef USE_INET6
1924                 if ((v == 6) && (sin->sin_family == AF_INET6)) {
1925                         inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
1926                         if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
1927                             !IN6_IS_ADDR_LOOPBACK(inp6))
1928                                 break;
1929                 }
1930 #    endif
1931 #    if (__FreeBSD_version >= 300000)
1932                 ifa = TAILQ_NEXT(ifa, ifa_link);
1933 #    else
1934 #     if defined(__NetBSD__) || defined(__OpenBSD__)
1935                 ifa = ifa->ifa_list.tqe_next;
1936 #     else
1937                 ifa = ifa->ifa_next;
1938 #     endif
1939 #    endif /* __FreeBSD_version >= 300000 */
1940                 if (ifa)
1941                         sin = (struct sockaddr_in *)ifa->ifa_addr;
1942         }
1943         if (ifa == NULL)
1944                 sin = NULL;
1945         if (sin == NULL)
1946                 return -1;
1947 #   endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
1948 #    ifdef      USE_INET6
1949         if (v == 6)
1950                 bcopy((char *)inp6, (char *)inp, sizeof(*inp6));
1951         else
1952 #    endif
1953         {
1954                 in = sin->sin_addr;
1955                 *inp = in;
1956         }
1957 #  endif /* linux */
1958 # endif /* SOLARIS */
1959         return 0;
1960 }
1961
1962
1963 static void frsynclist(fr)
1964 register frentry_t *fr;
1965 {
1966         for (; fr; fr = fr->fr_next) {
1967                 if (fr->fr_ifa != NULL) {
1968                         fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v);
1969                         if (fr->fr_ifa == NULL)
1970                                 fr->fr_ifa = (void *)-1;
1971                 }
1972                 if (fr->fr_grp)
1973                         frsynclist(fr->fr_grp);
1974         }
1975 }
1976
1977
1978 void frsync()
1979 {
1980 # if !SOLARIS
1981         register struct ifnet *ifp;
1982
1983 #  if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
1984      (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
1985 #   if (NetBSD >= 199905) || defined(__OpenBSD__)
1986         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
1987 #   else
1988         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
1989 #   endif
1990 #  else
1991         for (ifp = ifnet; ifp; ifp = ifp->if_next)
1992 #  endif
1993         {
1994                 ip_natsync(ifp);
1995                 ip_statesync(ifp);
1996         }
1997         ip_natsync((struct ifnet *)-1);
1998 # endif /* !SOLARIS */
1999
2000         WRITE_ENTER(&ipf_mutex);
2001         frsynclist(ipacct[0][fr_active]);
2002         frsynclist(ipacct[1][fr_active]);
2003         frsynclist(ipfilter[0][fr_active]);
2004         frsynclist(ipfilter[1][fr_active]);
2005 #ifdef  USE_INET6
2006         frsynclist(ipacct6[0][fr_active]);
2007         frsynclist(ipacct6[1][fr_active]);
2008         frsynclist(ipfilter6[0][fr_active]);
2009         frsynclist(ipfilter6[1][fr_active]);
2010 #endif
2011         RWLOCK_EXIT(&ipf_mutex);
2012 }
2013
2014
2015 /*
2016  * In the functions below, bcopy() is called because the pointer being
2017  * copied _from_ in this instance is a pointer to a char buf (which could
2018  * end up being unaligned) and on the kernel's local stack.
2019  */
2020 int ircopyptr(a, b, c)
2021 void *a, *b;
2022 size_t c;
2023 {
2024         caddr_t ca;
2025         int err;
2026
2027 #if SOLARIS
2028         if (copyin(a, (char *)&ca, sizeof(ca)))
2029                 return EFAULT;
2030 #else
2031         bcopy(a, &ca, sizeof(ca));
2032 #endif
2033         err = copyin(ca, b, c);
2034         if (err)
2035                 err = EFAULT;
2036         return err;
2037 }
2038
2039
2040 int iwcopyptr(a, b, c)
2041 void *a, *b;
2042 size_t c;
2043 {
2044         caddr_t ca;
2045         int err;
2046
2047 #if SOLARIS
2048         if (copyin(b, (char *)&ca, sizeof(ca)))
2049                 return EFAULT;
2050 #else
2051         bcopy(b, &ca, sizeof(ca));
2052 #endif
2053         err = copyout(a, ca, c);
2054         if (err)
2055                 err = EFAULT;
2056         return err;
2057 }
2058
2059 #else /* _KERNEL */
2060
2061
2062 /*
2063  * return the first IP Address associated with an interface
2064  */
2065 int fr_ifpaddr(v, ifptr, inp)
2066 int v;
2067 void *ifptr;
2068 struct in_addr *inp;
2069 {
2070         return 0;
2071 }
2072
2073
2074 int ircopyptr(a, b, c)
2075 void *a, *b;
2076 size_t c;
2077 {
2078         caddr_t ca;
2079
2080         bcopy(a, &ca, sizeof(ca));
2081         bcopy(ca, b, c);
2082         return 0;
2083 }
2084
2085
2086 int iwcopyptr(a, b, c)
2087 void *a, *b;
2088 size_t c;
2089 {
2090         caddr_t ca;
2091
2092         bcopy(b, &ca, sizeof(ca));
2093         bcopy(a, ca, c);
2094         return 0;
2095 }
2096
2097
2098 #endif
2099
2100
2101 int fr_lock(data, lockp)
2102 caddr_t data;
2103 int *lockp;
2104 {
2105         int arg, error;
2106
2107         error = IRCOPY(data, (caddr_t)&arg, sizeof(arg));
2108         if (!error) {
2109                 error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp));
2110                 if (!error)
2111                         *lockp = arg;
2112         }
2113         return error;
2114 }
2115
2116
2117 void fr_getstat(fiop)
2118 friostat_t *fiop;
2119 {
2120         bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2);
2121         fiop->f_locks[0] = fr_state_lock;
2122         fiop->f_locks[1] = fr_nat_lock;
2123         fiop->f_locks[2] = fr_frag_lock;
2124         fiop->f_locks[3] = fr_auth_lock;
2125         fiop->f_fin[0] = ipfilter[0][0];
2126         fiop->f_fin[1] = ipfilter[0][1];
2127         fiop->f_fout[0] = ipfilter[1][0];
2128         fiop->f_fout[1] = ipfilter[1][1];
2129         fiop->f_acctin[0] = ipacct[0][0];
2130         fiop->f_acctin[1] = ipacct[0][1];
2131         fiop->f_acctout[0] = ipacct[1][0];
2132         fiop->f_acctout[1] = ipacct[1][1];
2133 #ifdef  USE_INET6
2134         fiop->f_fin6[0] = ipfilter6[0][0];
2135         fiop->f_fin6[1] = ipfilter6[0][1];
2136         fiop->f_fout6[0] = ipfilter6[1][0];
2137         fiop->f_fout6[1] = ipfilter6[1][1];
2138         fiop->f_acctin6[0] = ipacct6[0][0];
2139         fiop->f_acctin6[1] = ipacct6[0][1];
2140         fiop->f_acctout6[0] = ipacct6[1][0];
2141         fiop->f_acctout6[1] = ipacct6[1][1];
2142 #else
2143         fiop->f_fin6[0] = NULL;
2144         fiop->f_fin6[1] = NULL;
2145         fiop->f_fout6[0] = NULL;
2146         fiop->f_fout6[1] = NULL;
2147         fiop->f_acctin6[0] = NULL;
2148         fiop->f_acctin6[1] = NULL;
2149         fiop->f_acctout6[0] = NULL;
2150         fiop->f_acctout6[1] = NULL;
2151 #endif
2152         fiop->f_active = fr_active;
2153         fiop->f_froute[0] = ipl_frouteok[0];
2154         fiop->f_froute[1] = ipl_frouteok[1];
2155
2156         fiop->f_running = fr_running;
2157         fiop->f_groups[0][0] = ipfgroups[0][0];
2158         fiop->f_groups[0][1] = ipfgroups[0][1];
2159         fiop->f_groups[1][0] = ipfgroups[1][0];
2160         fiop->f_groups[1][1] = ipfgroups[1][1];
2161         fiop->f_groups[2][0] = ipfgroups[2][0];
2162         fiop->f_groups[2][1] = ipfgroups[2][1];
2163 #ifdef  IPFILTER_LOG
2164         fiop->f_logging = 1;
2165 #else
2166         fiop->f_logging = 0;
2167 #endif
2168         fiop->f_defpass = fr_pass;
2169         strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version));
2170 }
2171
2172
2173 #ifdef  USE_INET6
2174 int icmptoicmp6types[ICMP_MAXTYPE+1] = {
2175         ICMP6_ECHO_REPLY,       /* 0: ICMP_ECHOREPLY */
2176         -1,                     /* 1: UNUSED */
2177         -1,                     /* 2: UNUSED */
2178         ICMP6_DST_UNREACH,      /* 3: ICMP_UNREACH */
2179         -1,                     /* 4: ICMP_SOURCEQUENCH */
2180         ND_REDIRECT,            /* 5: ICMP_REDIRECT */
2181         -1,                     /* 6: UNUSED */
2182         -1,                     /* 7: UNUSED */
2183         ICMP6_ECHO_REQUEST,     /* 8: ICMP_ECHO */
2184         -1,                     /* 9: UNUSED */
2185         -1,                     /* 10: UNUSED */
2186         ICMP6_TIME_EXCEEDED,    /* 11: ICMP_TIMXCEED */
2187         ICMP6_PARAM_PROB,       /* 12: ICMP_PARAMPROB */
2188         -1,                     /* 13: ICMP_TSTAMP */
2189         -1,                     /* 14: ICMP_TSTAMPREPLY */
2190         -1,                     /* 15: ICMP_IREQ */
2191         -1,                     /* 16: ICMP_IREQREPLY */
2192         -1,                     /* 17: ICMP_MASKREQ */
2193         -1,                     /* 18: ICMP_MASKREPLY */
2194 };
2195
2196
2197 int     icmptoicmp6unreach[ICMP_MAX_UNREACH] = {
2198         ICMP6_DST_UNREACH_ADDR,         /* 0: ICMP_UNREACH_NET */
2199         ICMP6_DST_UNREACH_ADDR,         /* 1: ICMP_UNREACH_HOST */
2200         -1,                             /* 2: ICMP_UNREACH_PROTOCOL */
2201         ICMP6_DST_UNREACH_NOPORT,       /* 3: ICMP_UNREACH_PORT */
2202         -1,                             /* 4: ICMP_UNREACH_NEEDFRAG */
2203         ICMP6_DST_UNREACH_NOTNEIGHBOR,  /* 5: ICMP_UNREACH_SRCFAIL */
2204         ICMP6_DST_UNREACH_ADDR,         /* 6: ICMP_UNREACH_NET_UNKNOWN */
2205         ICMP6_DST_UNREACH_ADDR,         /* 7: ICMP_UNREACH_HOST_UNKNOWN */
2206         -1,                             /* 8: ICMP_UNREACH_ISOLATED */
2207         ICMP6_DST_UNREACH_ADMIN,        /* 9: ICMP_UNREACH_NET_PROHIB */
2208         ICMP6_DST_UNREACH_ADMIN,        /* 10: ICMP_UNREACH_HOST_PROHIB */
2209         -1,                             /* 11: ICMP_UNREACH_TOSNET */
2210         -1,                             /* 12: ICMP_UNREACH_TOSHOST */
2211         ICMP6_DST_UNREACH_ADMIN,        /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */
2212 };
2213 #endif
2214
2215
2216 #ifndef _KERNEL
2217 int mbuflen(buf)
2218 mb_t *buf;
2219 {
2220         ip_t *ip;
2221
2222         ip = (ip_t *)buf;
2223         return ip->ip_len;
2224 }
2225 #endif