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