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