Deleted Added
full compact
fil.c (57096) fil.c (59874)
1/*
2 * Copyright (C) 1993-1998 by Darren Reed.
3 *
4 * Redistribution and use in source and binary forms are permitted
5 * provided that this notice is preserved and due credit is given
6 * to the original author and the contributors.
7 */
8#if !defined(lint)
9static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
1/*
2 * Copyright (C) 1993-1998 by Darren Reed.
3 *
4 * Redistribution and use in source and binary forms are permitted
5 * provided that this notice is preserved and due credit is given
6 * to the original author and the contributors.
7 */
8#if !defined(lint)
9static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
10static const char rcsid[] = "@(#)$Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $";
10/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $"; */
11static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/fil.c 59874 2000-05-01 20:32:07Z peter $";
11#endif
12
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(__FreeBSD_version) && \
23 (__FreeBSD_version >= 220000)
24# include <sys/filio.h>
25# include <sys/fcntl.h>
26#else
27# include <sys/ioctl.h>
28#endif
29#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
30# include <sys/systm.h>
31#else
32# include <stdio.h>
33# include <string.h>
34# include <stdlib.h>
35#endif
36#include <sys/uio.h>
37#if !defined(__SVR4) && !defined(__svr4__)
38# ifndef linux
39# include <sys/mbuf.h>
40# endif
41#else
42# include <sys/byteorder.h>
43# if SOLARIS2 < 5
44# include <sys/dditypes.h>
45# endif
46# include <sys/stream.h>
47#endif
48#ifndef linux
49# include <sys/protosw.h>
50# include <sys/socket.h>
51#endif
52#include <net/if.h>
53#ifdef sun
54# include <net/af.h>
55#endif
56#include <net/route.h>
57#include <netinet/in.h>
58#include <netinet/in_systm.h>
59#include <netinet/ip.h>
60#ifndef linux
61# include <netinet/ip_var.h>
62#endif
63#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
64# include <sys/hashing.h>
65# include <netinet/in_var.h>
66#endif
67#include <netinet/tcp.h>
68#include <netinet/udp.h>
69#include <netinet/ip_icmp.h>
70#include "netinet/ip_compat.h"
71#include <netinet/tcpip.h>
72#include "netinet/ip_fil.h"
73#include "netinet/ip_proxy.h"
74#include "netinet/ip_nat.h"
75#include "netinet/ip_frag.h"
76#include "netinet/ip_state.h"
77#include "netinet/ip_auth.h"
78# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
79# include <sys/malloc.h>
80# if defined(_KERNEL) && !defined(IPFILTER_LKM)
81# include "opt_ipfilter.h"
82# endif
83# endif
84#ifndef MIN
85# define MIN(a,b) (((a)<(b))?(a):(b))
86#endif
87#include "netinet/ipl.h"
88
89#ifndef _KERNEL
90# include "ipf.h"
91# include "ipt.h"
92extern int opts;
93
94# define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
95 second; }
96# define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
97 second; }
98# define FR_VERBOSE(verb_pr) verbose verb_pr
99# define FR_DEBUG(verb_pr) debug verb_pr
100# define SEND_RESET(ip, qif, if, m, fin) send_reset(ip, if)
101# define IPLLOG(a, c, d, e) ipllog()
102# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
103#else /* #ifndef _KERNEL */
104# define FR_IFVERBOSE(ex,second,verb_pr) ;
105# define FR_IFDEBUG(ex,second,verb_pr) ;
106# define FR_VERBOSE(verb_pr)
107# define FR_DEBUG(verb_pr)
108# define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
109# if SOLARIS || defined(__sgi)
110extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat;
111extern kmutex_t ipf_rw;
112# endif
113# if SOLARIS
114# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
115 ip, qif)
116# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif)
117# define ICMP_ERROR(b, ip, t, c, if, dst) \
118 icmp_error(ip, t, c, if, dst)
119# else /* SOLARIS */
120# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
121# ifdef linux
122# define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp)
123# define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if)
124# else
125# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
126# define ICMP_ERROR(b, ip, t, c, if, dst) \
127 send_icmp_err(ip, t, c, if, dst)
128# endif /* linux */
129# endif /* SOLARIS || __sgi */
130#endif /* _KERNEL */
131
132
133struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
134struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
135 *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
136struct frgroup *ipfgroups[3][2];
137int fr_flags = IPF_LOGGING, fr_active = 0;
138#if defined(IPFILTER_DEFAULT_BLOCK)
139int fr_pass = FR_NOMATCH|FR_BLOCK;
140#else
141int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
142#endif
143char ipfilter_version[] = IPL_VERSION;
144
145fr_info_t frcache[2];
146
147static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
148static int frflushlist __P((int, minor_t, int *, frentry_t **));
149#ifdef _KERNEL
150static void frsynclist __P((frentry_t *));
151#endif
152
153
154/*
155 * bit values for identifying presence of individual IP options
156 */
157struct optlist ipopts[20] = {
158 { IPOPT_NOP, 0x000001 },
159 { IPOPT_RR, 0x000002 },
160 { IPOPT_ZSU, 0x000004 },
161 { IPOPT_MTUP, 0x000008 },
162 { IPOPT_MTUR, 0x000010 },
163 { IPOPT_ENCODE, 0x000020 },
164 { IPOPT_TS, 0x000040 },
165 { IPOPT_TR, 0x000080 },
166 { IPOPT_SECURITY, 0x000100 },
167 { IPOPT_LSRR, 0x000200 },
168 { IPOPT_E_SEC, 0x000400 },
169 { IPOPT_CIPSO, 0x000800 },
170 { IPOPT_SATID, 0x001000 },
171 { IPOPT_SSRR, 0x002000 },
172 { IPOPT_ADDEXT, 0x004000 },
173 { IPOPT_VISA, 0x008000 },
174 { IPOPT_IMITD, 0x010000 },
175 { IPOPT_EIP, 0x020000 },
176 { IPOPT_FINN, 0x040000 },
177 { 0, 0x000000 }
178};
179
180/*
181 * bit values for identifying presence of individual IP security options
182 */
183struct optlist secopt[8] = {
184 { IPSO_CLASS_RES4, 0x01 },
185 { IPSO_CLASS_TOPS, 0x02 },
186 { IPSO_CLASS_SECR, 0x04 },
187 { IPSO_CLASS_RES3, 0x08 },
188 { IPSO_CLASS_CONF, 0x10 },
189 { IPSO_CLASS_UNCL, 0x20 },
190 { IPSO_CLASS_RES2, 0x40 },
191 { IPSO_CLASS_RES1, 0x80 }
192};
193
194
195/*
196 * compact the IP header into a structure which contains just the info.
197 * which is useful for comparing IP headers with.
198 */
199void fr_makefrip(hlen, ip, fin)
200int hlen;
201ip_t *ip;
202fr_info_t *fin;
203{
204 struct optlist *op;
205 tcphdr_t *tcp;
206 fr_ip_t *fi = &fin->fin_fi;
207 u_short optmsk = 0, secmsk = 0, auth = 0;
208 int i, mv, ol, off;
209 u_char *s, opt;
210
211 fin->fin_rev = 0;
212 fin->fin_fr = NULL;
213 fin->fin_tcpf = 0;
214 fin->fin_data[0] = 0;
215 fin->fin_data[1] = 0;
216 fin->fin_rule = -1;
217 fin->fin_group = -1;
218 fin->fin_id = ip->ip_id;
219#ifdef _KERNEL
220 fin->fin_icode = ipl_unreach;
221#endif
222 fi->fi_v = ip->ip_v;
223 fi->fi_tos = ip->ip_tos;
224 fin->fin_hlen = hlen;
225 fin->fin_dlen = ip->ip_len - hlen;
226 tcp = (tcphdr_t *)((char *)ip + hlen);
227 fin->fin_dp = (void *)tcp;
228 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
229 fi->fi_src.s_addr = ip->ip_src.s_addr;
230 fi->fi_dst.s_addr = ip->ip_dst.s_addr;
231
232 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
233 off = (ip->ip_off & IP_OFFMASK) << 3;
234 if (ip->ip_off & 0x3fff)
235 fi->fi_fl |= FI_FRAG;
236 switch (ip->ip_p)
237 {
238 case IPPROTO_ICMP :
239 {
240 int minicmpsz = sizeof(struct icmp);
241 icmphdr_t *icmp;
242
243 icmp = (icmphdr_t *)tcp;
244
245 if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
246 icmp->icmp_type == ICMP_ECHO))
247 minicmpsz = ICMP_MINLEN;
248 if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
249 icmp->icmp_type == ICMP_TSTAMPREPLY))
250 minicmpsz = 20; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
251 if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
252 icmp->icmp_type == ICMP_MASKREPLY))
253 minicmpsz = 12; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
254 if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
255 (off && off < sizeof(struct icmp)))
256 fi->fi_fl |= FI_SHORT;
257 if (fin->fin_dlen > 1)
258 fin->fin_data[0] = *(u_short *)tcp;
259 break;
260 }
261 case IPPROTO_TCP :
262 fi->fi_fl |= FI_TCPUDP;
263 if ((!IPMINLEN(ip, tcphdr) && !off) ||
264 (off && off < sizeof(struct tcphdr)))
265 fi->fi_fl |= FI_SHORT;
266 if (!(fi->fi_fl & FI_SHORT) && !off)
267 fin->fin_tcpf = tcp->th_flags;
268 goto getports;
269 case IPPROTO_UDP :
270 fi->fi_fl |= FI_TCPUDP;
271 if ((!IPMINLEN(ip, udphdr) && !off) ||
272 (off && off < sizeof(struct udphdr)))
273 fi->fi_fl |= FI_SHORT;
274getports:
275 if (!off && (fin->fin_dlen > 3)) {
276 fin->fin_data[0] = ntohs(tcp->th_sport);
277 fin->fin_data[1] = ntohs(tcp->th_dport);
278 }
279 break;
280 default :
281 break;
282 }
283
284
285 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen; ) {
286 opt = *s;
287 if (opt == '\0')
288 break;
289 ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
290 if (opt > 1 && (ol < 2 || ol > hlen))
291 break;
292 for (i = 9, mv = 4; mv >= 0; ) {
293 op = ipopts + i;
294 if (opt == (u_char)op->ol_val) {
295 optmsk |= op->ol_bit;
296 if (opt == IPOPT_SECURITY) {
297 struct optlist *sp;
298 u_char sec;
299 int j, m;
300
301 sec = *(s + 2); /* classification */
302 for (j = 3, m = 2; m >= 0; ) {
303 sp = secopt + j;
304 if (sec == sp->ol_val) {
305 secmsk |= sp->ol_bit;
306 auth = *(s + 3);
307 auth *= 256;
308 auth += *(s + 4);
309 break;
310 }
311 if (sec < sp->ol_val)
312 j -= m--;
313 else
314 j += m--;
315 }
316 }
317 break;
318 }
319 if (opt < op->ol_val)
320 i -= mv--;
321 else
322 i += mv--;
323 }
324 hlen -= ol;
325 s += ol;
326 }
327 if (auth && !(auth & 0x0100))
328 auth &= 0xff00;
329 fi->fi_optmsk = optmsk;
330 fi->fi_secmsk = secmsk;
331 fi->fi_auth = auth;
332}
333
334
335/*
336 * check an IP packet for TCP/UDP characteristics such as ports and flags.
337 */
338static int fr_tcpudpchk(fr, fin)
339frentry_t *fr;
340fr_info_t *fin;
341{
342 register u_short po, tup;
343 register char i;
344 register int err = 1;
345
346 /*
347 * Both ports should *always* be in the first fragment.
348 * So far, I cannot find any cases where they can not be.
349 *
350 * compare destination ports
351 */
352 if ((i = (int)fr->fr_dcmp)) {
353 po = fr->fr_dport;
354 tup = fin->fin_data[1];
355 /*
356 * Do opposite test to that required and
357 * continue if that succeeds.
358 */
359 if (!--i && tup != po) /* EQUAL */
360 err = 0;
361 else if (!--i && tup == po) /* NOTEQUAL */
362 err = 0;
363 else if (!--i && tup >= po) /* LESSTHAN */
364 err = 0;
365 else if (!--i && tup <= po) /* GREATERTHAN */
366 err = 0;
367 else if (!--i && tup > po) /* LT or EQ */
368 err = 0;
369 else if (!--i && tup < po) /* GT or EQ */
370 err = 0;
371 else if (!--i && /* Out of range */
372 (tup >= po && tup <= fr->fr_dtop))
373 err = 0;
374 else if (!--i && /* In range */
375 (tup <= po || tup >= fr->fr_dtop))
376 err = 0;
377 }
378 /*
379 * compare source ports
380 */
381 if (err && (i = (int)fr->fr_scmp)) {
382 po = fr->fr_sport;
383 tup = fin->fin_data[0];
384 if (!--i && tup != po)
385 err = 0;
386 else if (!--i && tup == po)
387 err = 0;
388 else if (!--i && tup >= po)
389 err = 0;
390 else if (!--i && tup <= po)
391 err = 0;
392 else if (!--i && tup > po)
393 err = 0;
394 else if (!--i && tup < po)
395 err = 0;
396 else if (!--i && /* Out of range */
397 (tup >= po && tup <= fr->fr_stop))
398 err = 0;
399 else if (!--i && /* In range */
400 (tup <= po || tup >= fr->fr_stop))
401 err = 0;
402 }
403
404 /*
405 * If we don't have all the TCP/UDP header, then how can we
406 * expect to do any sort of match on it ? If we were looking for
407 * TCP flags, then NO match. If not, then match (which should
408 * satisfy the "short" class too).
409 */
410 if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
411 if (fin->fin_fi.fi_fl & FI_SHORT)
412 return !(fr->fr_tcpf | fr->fr_tcpfm);
413 /*
414 * Match the flags ? If not, abort this match.
415 */
416 if (fr->fr_tcpfm &&
417 fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
418 FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
419 fr->fr_tcpfm, fr->fr_tcpf));
420 err = 0;
421 }
422 }
423 return err;
424}
425
426/*
427 * Check the input/output list of rules for a match and result.
428 * Could be per interface, but this gets real nasty when you don't have
429 * kernel sauce.
430 */
431int fr_scanlist(pass, ip, fin, m)
432u_32_t pass;
433ip_t *ip;
434register fr_info_t *fin;
435void *m;
436{
437 register struct frentry *fr;
438 register fr_ip_t *fi = &fin->fin_fi;
439 int rulen, portcmp = 0, off, skip = 0, logged = 0;
440 u_32_t passt;
441
442 fr = fin->fin_fr;
443 fin->fin_fr = NULL;
444 fin->fin_rule = 0;
445 fin->fin_group = 0;
446 off = ip->ip_off & IP_OFFMASK;
447 pass |= (fi->fi_fl << 24);
448
449 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
450 portcmp = 1;
451
452 for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
453 if (skip) {
454 skip--;
455 continue;
456 }
457 /*
458 * In all checks below, a null (zero) value in the
459 * filter struture is taken to mean a wildcard.
460 *
461 * check that we are working for the right interface
462 */
463#ifdef _KERNEL
464# if BSD >= 199306
465 if (fin->fin_out != 0) {
466 if ((fr->fr_oifa &&
467 fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) ||
468 (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp))
469 continue;
470 } else
471# endif
472 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
473 continue;
474#else
475 if (opts & (OPT_VERBOSE|OPT_DEBUG))
476 printf("\n");
477 FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' :
478 (pass & FR_AUTH) ? 'a' : 'b'));
479 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
480 continue;
481 FR_VERBOSE((":i"));
482#endif
483 {
484 register u_32_t *ld, *lm, *lip;
485 register int i;
486
487 lip = (u_32_t *)fi;
488 lm = (u_32_t *)&fr->fr_mip;
489 ld = (u_32_t *)&fr->fr_ip;
490 i = ((lip[0] & lm[0]) != ld[0]);
491 FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
492 lip[0], lm[0], ld[0]));
493 i |= ((lip[1] & lm[1]) != ld[1]) << 19;
494 i ^= (fr->fr_flags & FR_NOTSRCIP);
495 FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
496 lip[1], lm[1], ld[1]));
497 i |= ((lip[2] & lm[2]) != ld[2]) << 20;
498 i ^= (fr->fr_flags & FR_NOTDSTIP);
499 FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
500 lip[2], lm[2], ld[2]));
501 i |= ((lip[3] & lm[3]) != ld[3]);
502 FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
503 lip[3], lm[3], ld[3]));
504 i |= ((lip[4] & lm[4]) != ld[4]);
505 FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
506 lip[4], lm[4], ld[4]));
507 if (i)
508 continue;
509 }
510
511 /*
512 * If a fragment, then only the first has what we're looking
513 * for here...
514 */
515 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
516 fr->fr_tcpfm))
517 continue;
518 if (fi->fi_fl & FI_TCPUDP) {
519 if (!fr_tcpudpchk(fr, fin))
520 continue;
521 } else if (fr->fr_icmpm || fr->fr_icmp) {
522 if ((fi->fi_p != IPPROTO_ICMP) || off ||
523 (fin->fin_dlen < 2))
524 continue;
525 if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) {
526 FR_DEBUG(("i. %#x & %#x != %#x\n",
527 fin->fin_data[0], fr->fr_icmpm,
528 fr->fr_icmp));
529 continue;
530 }
531 }
532 FR_VERBOSE(("*"));
533 /*
534 * Just log this packet...
535 */
536 passt = fr->fr_flags;
537 if ((passt & FR_CALLNOW) && fr->fr_func)
538 passt = (*fr->fr_func)(passt, ip, fin);
539 fin->fin_fr = fr;
540#ifdef IPFILTER_LOG
541 if ((passt & FR_LOGMASK) == FR_LOG) {
542 if (!IPLLOG(passt, ip, fin, m)) {
543 ATOMIC_INC(frstats[fin->fin_out].fr_skip);
544 }
545 ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
546 logged = 1;
547 }
548#endif /* IPFILTER_LOG */
549 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
550 pass = passt;
551 FR_DEBUG(("pass %#x\n", pass));
552 ATOMIC_INC(fr->fr_hits);
553 if (pass & FR_ACCOUNT)
554 fr->fr_bytes += (U_QUAD_T)ip->ip_len;
555 else
556 fin->fin_icode = fr->fr_icode;
557 fin->fin_rule = rulen;
558 fin->fin_group = fr->fr_group;
559 if (fr->fr_grp) {
560 fin->fin_fr = fr->fr_grp;
561 pass = fr_scanlist(pass, ip, fin, m);
562 if (fin->fin_fr == NULL) {
563 fin->fin_rule = rulen;
564 fin->fin_group = fr->fr_group;
565 fin->fin_fr = fr;
566 }
567 if (pass & FR_DONTCACHE)
568 logged = 1;
569 }
570 if (pass & FR_QUICK)
571 break;
572 }
573 if (logged)
574 pass |= FR_DONTCACHE;
575 return pass;
576}
577
578
579/*
580 * frcheck - filter check
581 * check using source and destination addresses/ports in a packet whether
582 * or not to pass it on or not.
583 */
584int fr_check(ip, hlen, ifp, out
585#if defined(_KERNEL) && SOLARIS
586, qif, mp)
587qif_t *qif;
588#else
589, mp)
590#endif
591mb_t **mp;
592ip_t *ip;
593int hlen;
594void *ifp;
595int out;
596{
597 /*
598 * The above really sucks, but short of writing a diff
599 */
600 fr_info_t frinfo, *fc;
601 register fr_info_t *fin = &frinfo;
602 frentry_t *fr = NULL;
603 int changed, error = EHOSTUNREACH;
604 u_32_t pass, apass;
605#if !SOLARIS || !defined(_KERNEL)
606 register mb_t *m = *mp;
607#endif
608
609#ifdef _KERNEL
610 mb_t *mc = NULL;
611# if !defined(__SVR4) && !defined(__svr4__)
612# ifdef __sgi
613 char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
614# endif
615 int up;
616
617# ifdef M_CANFASTFWD
618 /*
619 * XXX For now, IP Filter and fast-forwarding of cached flows
620 * XXX are mutually exclusive. Eventually, IP Filter should
621 * XXX get a "can-fast-forward" filter rule.
622 */
623 m->m_flags &= ~M_CANFASTFWD;
624# endif /* M_CANFASTFWD */
625
626 if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
627 ip->ip_p == IPPROTO_ICMP)) {
628 int plen = 0;
629
630 if ((ip->ip_off & IP_OFFMASK) == 0)
631 switch(ip->ip_p)
632 {
633 case IPPROTO_TCP:
634 plen = sizeof(tcphdr_t);
635 break;
636 case IPPROTO_UDP:
637 plen = sizeof(udphdr_t);
638 break;
639 /* 96 - enough for complete ICMP error IP header */
640 case IPPROTO_ICMP:
641 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
642 break;
643 }
644 up = MIN(hlen + plen, ip->ip_len);
645
646 if (up > m->m_len) {
647# ifdef __sgi
648 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
649 if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
650 ATOMIC_INC(frstats[out].fr_pull[1]);
651 return -1;
652 }
653 m_copydata(m, 0, up, hbuf);
654 ATOMIC_INC(frstats[out].fr_pull[0]);
655 ip = (ip_t *)hbuf;
656# else /* __ sgi */
657# ifndef linux
658 if ((*mp = m_pullup(m, up)) == 0) {
659 ATOMIC_INC(frstats[out].fr_pull[1]);
660 return -1;
661 } else {
662 ATOMIC_INC(frstats[out].fr_pull[0]);
663 m = *mp;
664 ip = mtod(m, ip_t *);
665 }
666# endif /* !linux */
667# endif /* __sgi */
668 } else
669 up = 0;
670 } else
671 up = 0;
672# endif /* !defined(__SVR4) && !defined(__svr4__) */
673# if SOLARIS
674 mb_t *m = qif->qf_m;
675
676 if ((u_int)ip & 0x3)
677 return 2;
678 fin->fin_qfm = m;
679 fin->fin_qif = qif;
680# endif
681#endif /* _KERNEL */
682
683 /*
684 * Be careful here: ip_id is in network byte order when called
685 * from ip_output()
686 */
687 if (out)
688 ip->ip_id = ntohs(ip->ip_id);
689 fr_makefrip(hlen, ip, fin);
690 fin->fin_ifp = ifp;
691 fin->fin_out = out;
692 fin->fin_mp = mp;
693 pass = fr_pass;
694
695 READ_ENTER(&ipf_mutex);
696
697 if (fin->fin_fi.fi_fl & FI_SHORT)
698 ATOMIC_INC(frstats[out].fr_short);
699
700 /*
701 * Check auth now. This, combined with the check below to see if apass
702 * is 0 is to ensure that we don't count the packet twice, which can
703 * otherwise occur when we reprocess it. As it is, we only count it
704 * after it has no auth. table matchup. This also stops NAT from
705 * occuring until after the packet has been auth'd.
706 */
707 apass = fr_checkauth(ip, fin);
708
709 if (!out) {
710 changed = ip_natin(ip, fin);
711 if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
712 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
713 ATOMIC_INC(frstats[0].fr_acct);
714 }
715 }
716
717 if (apass || (!(fr = ipfr_knownfrag(ip, fin)) &&
718 !(fr = fr_checkstate(ip, fin)))) {
719 /*
720 * If a packet is found in the auth table, then skip checking
721 * the access lists for permission but we do need to consider
722 * the result as if it were from the ACL's.
723 */
724 if (!apass) {
725 fc = frcache + out;
726 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
727 /*
728 * copy cached data so we can unlock the mutex
729 * earlier.
730 */
731 bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
732 ATOMIC_INC(frstats[out].fr_chit);
733 if ((fr = fin->fin_fr)) {
734 ATOMIC_INC(fr->fr_hits);
735 pass = fr->fr_flags;
736 }
737 } else {
738 if ((fin->fin_fr = ipfilter[out][fr_active]))
739 pass = fr_scanlist(fr_pass, ip, fin, m);
740 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
741 bcopy((char *)fin, (char *)fc,
742 FI_COPYSIZE);
743 if (pass & FR_NOMATCH) {
744 ATOMIC_INC(frstats[out].fr_nom);
745 }
746 }
747 fr = fin->fin_fr;
748 } else
749 pass = apass;
750
751 /*
752 * If we fail to add a packet to the authorization queue,
753 * then we drop the packet later. However, if it was added
754 * then pretend we've dropped it already.
755 */
756 if ((pass & FR_AUTH))
757 if (FR_NEWAUTH(m, fin, ip, qif) != 0)
758#ifdef _KERNEL
759 m = *mp = NULL;
760#else
761 ;
762#endif
763
764 if (pass & FR_PREAUTH) {
765 READ_ENTER(&ipf_auth);
766 if ((fin->fin_fr = ipauth) &&
767 (pass = fr_scanlist(0, ip, fin, m))) {
768 ATOMIC_INC(fr_authstats.fas_hits);
769 } else {
770 ATOMIC_INC(fr_authstats.fas_miss);
771 }
772 RWLOCK_EXIT(&ipf_auth);
773 }
774
775 fin->fin_fr = fr;
776 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
777 if (fin->fin_fi.fi_fl & FI_FRAG) {
778 if (ipfr_newfrag(ip, fin, pass) == -1) {
779 ATOMIC_INC(frstats[out].fr_bnfr);
780 } else {
781 ATOMIC_INC(frstats[out].fr_nfr);
782 }
783 } else {
784 ATOMIC_INC(frstats[out].fr_cfr);
785 }
786 }
787 if (pass & FR_KEEPSTATE) {
788 if (fr_addstate(ip, fin, 0) == NULL) {
789 ATOMIC_INC(frstats[out].fr_bads);
790 } else {
791 ATOMIC_INC(frstats[out].fr_ads);
792 }
793 }
794 } else if (fr != NULL) {
795 pass = fr->fr_flags;
796 if (pass & FR_LOGFIRST)
797 pass &= ~(FR_LOGFIRST|FR_LOG);
798 }
799
800 if (fr && fr->fr_func && !(pass & FR_CALLNOW))
801 pass = (*fr->fr_func)(pass, ip, fin);
802
803 /*
804 * Only count/translate packets which will be passed on, out the
805 * interface.
806 */
807 if (out && (pass & FR_PASS)) {
808 if ((fin->fin_fr = ipacct[1][fr_active]) &&
809 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
810 ATOMIC_INC(frstats[1].fr_acct);
811 }
812 fin->fin_fr = fr;
813 changed = ip_natout(ip, fin);
814 } else
815 fin->fin_fr = fr;
816 RWLOCK_EXIT(&ipf_mutex);
817
818#ifdef IPFILTER_LOG
819 if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
820 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
821 pass |= FF_LOGNOMATCH;
822 ATOMIC_INC(frstats[out].fr_npkl);
823 goto logit;
824 } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
825 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
826 if ((pass & FR_LOGMASK) != FR_LOGP)
827 pass |= FF_LOGPASS;
828 ATOMIC_INC(frstats[out].fr_ppkl);
829 goto logit;
830 } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
831 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
832 if ((pass & FR_LOGMASK) != FR_LOGB)
833 pass |= FF_LOGBLOCK;
834 ATOMIC_INC(frstats[out].fr_bpkl);
835logit:
836 if (!IPLLOG(pass, ip, fin, m)) {
837 ATOMIC_INC(frstats[out].fr_skip);
838 if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
839 (FR_PASS|FR_LOGORBLOCK))
840 pass ^= FR_PASS|FR_BLOCK;
841 }
842 }
843 }
844#endif /* IPFILTER_LOG */
845
846 if (out)
847 ip->ip_id = htons(ip->ip_id);
848
849#ifdef _KERNEL
850 /*
851 * Only allow FR_DUP to work if a rule matched - it makes no sense to
852 * set FR_DUP as a "default" as there are no instructions about where
853 * to send the packet.
854 */
855 if (fr && (pass & FR_DUP))
856# if SOLARIS
857 mc = dupmsg(m);
858# else
859# ifndef linux
860 mc = m_copy(m, 0, M_COPYALL);
861# else
862 ;
863# endif
864# endif
865#endif
866 if (pass & FR_PASS) {
867 ATOMIC_INC(frstats[out].fr_pass);
868 } else if (pass & FR_BLOCK) {
869 ATOMIC_INC(frstats[out].fr_block);
870 /*
871 * Should we return an ICMP packet to indicate error
872 * status passing through the packet filter ?
873 * WARNING: ICMP error packets AND TCP RST packets should
874 * ONLY be sent in repsonse to incoming packets. Sending them
875 * in response to outbound packets can result in a panic on
876 * some operating systems.
877 */
878 if (!out) {
879#ifdef _KERNEL
880 if (pass & FR_RETICMP) {
881 struct in_addr dst;
882
883 if ((pass & FR_RETMASK) == FR_FAKEICMP)
884 dst = ip->ip_dst;
885 else
886 dst.s_addr = 0;
887# if SOLARIS
888 ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
889 qif, dst);
890# else
891 ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
892 ifp, dst);
893# endif
894 ATOMIC_INC(frstats[0].fr_ret);
895 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
896 !(fin->fin_fi.fi_fl & FI_SHORT)) {
897 if (SEND_RESET(ip, qif, ifp, fin) == 0) {
898 ATOMIC_INC(frstats[1].fr_ret);
899 }
900 }
901#else
902 if ((pass & FR_RETMASK) == FR_RETICMP) {
903 verbose("- ICMP unreachable sent\n");
904 ATOMIC_INC(frstats[0].fr_ret);
905 } else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
906 verbose("- forged ICMP unreachable sent\n");
907 ATOMIC_INC(frstats[0].fr_ret);
908 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
909 !(fin->fin_fi.fi_fl & FI_SHORT)) {
910 verbose("- TCP RST sent\n");
911 ATOMIC_INC(frstats[1].fr_ret);
912 }
913#endif
914 } else {
915 if (pass & FR_RETRST)
916 error = ECONNRESET;
917 }
918 }
919
920 /*
921 * If we didn't drop off the bottom of the list of rules (and thus
922 * the 'current' rule fr is not NULL), then we may have some extra
923 * instructions about what to do with a packet.
924 * Once we're finished return to our caller, freeing the packet if
925 * we are dropping it (* BSD ONLY *).
926 */
927#if defined(_KERNEL)
928# if !SOLARIS
929# if !defined(linux)
930 if (fr) {
931 frdest_t *fdp = &fr->fr_tif;
932
933 if (((pass & FR_FASTROUTE) && !out) ||
934 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
935 if (ipfr_fastroute(m, fin, fdp) == 0)
936 m = *mp = NULL;
937 }
938 if (mc)
939 ipfr_fastroute(mc, fin, &fr->fr_dif);
940 }
941 if (!(pass & FR_PASS) && m)
942 m_freem(m);
943# ifdef __sgi
944 else if (changed && up && m)
945 m_copyback(m, 0, up, hbuf);
946# endif
947# endif /* !linux */
948# else /* !SOLARIS */
949 if (fr) {
950 frdest_t *fdp = &fr->fr_tif;
951
952 if (((pass & FR_FASTROUTE) && !out) ||
953 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
954 if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0)
955 m = *mp = NULL;
956 }
957 if (mc)
958 ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
959 }
960# endif /* !SOLARIS */
961 return (pass & FR_PASS) ? 0 : error;
962#else /* _KERNEL */
963 if (pass & FR_NOMATCH)
964 return 1;
965 if (pass & FR_PASS)
966 return 0;
967 if (pass & FR_AUTH)
968 return -2;
969 return -1;
970#endif /* _KERNEL */
971}
972
973
974/*
975 * ipf_cksum
976 * addr should be 16bit aligned and len is in bytes.
977 * length is in bytes
978 */
979u_short ipf_cksum(addr, len)
980register u_short *addr;
981register int len;
982{
983 register u_32_t sum = 0;
984
985 for (sum = 0; len > 1; len -= 2)
986 sum += *addr++;
987
988 /* mop up an odd byte, if necessary */
989 if (len == 1)
990 sum += *(u_char *)addr;
991
992 /*
993 * add back carry outs from top 16 bits to low 16 bits
994 */
995 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
996 sum += (sum >> 16); /* add carry */
997 return (u_short)(~sum);
998}
999
1000
1001/*
1002 * NB: This function assumes we've pullup'd enough for all of the IP header
1003 * and the TCP header. We also assume that data blocks aren't allocated in
1004 * odd sizes.
1005 */
1006u_short fr_tcpsum(m, ip, tcp)
1007mb_t *m;
1008ip_t *ip;
1009tcphdr_t *tcp;
1010{
1011 u_short *sp, slen, ts;
1012 u_int sum, sum2;
1013 int hlen;
1014
1015 /*
1016 * Add up IP Header portion
1017 */
1018 hlen = ip->ip_hl << 2;
1019 slen = ip->ip_len - hlen;
1020 sum = htons((u_short)ip->ip_p);
1021 sum += htons(slen);
1022 sp = (u_short *)&ip->ip_src;
1023 sum += *sp++; /* ip_src */
1024 sum += *sp++;
1025 sum += *sp++; /* ip_dst */
1026 sum += *sp++;
1027 ts = tcp->th_sum;
1028 tcp->th_sum = 0;
1029#ifdef KERNEL
1030# if SOLARIS
1031 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */
1032 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1033 sum2 = ~sum2 & 0xffff;
1034# else /* SOLARIS */
1035# if defined(BSD) || defined(sun)
1036# if BSD >= 199306
1037 m->m_data += hlen;
1038# else
1039 m->m_off += hlen;
1040# endif
1041 m->m_len -= hlen;
1042 sum2 = in_cksum(m, slen);
1043 m->m_len += hlen;
1044# if BSD >= 199306
1045 m->m_data -= hlen;
1046# else
1047 m->m_off -= hlen;
1048# endif
1049 /*
1050 * Both sum and sum2 are partial sums, so combine them together.
1051 */
1052 sum = (sum & 0xffff) + (sum >> 16);
1053 sum = ~sum & 0xffff;
1054 sum2 += sum;
1055 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1056# else /* defined(BSD) || defined(sun) */
1057{
1058 union {
1059 u_char c[2];
1060 u_short s;
1061 } bytes;
1062 u_short len = ip->ip_len;
1063# if defined(__sgi)
1064 int add;
1065# endif
1066
1067 /*
1068 * Add up IP Header portion
1069 */
1070 sp = (u_short *)&ip->ip_src;
1071 len -= (ip->ip_hl << 2);
1072 sum = ntohs(IPPROTO_TCP);
1073 sum += htons(len);
1074 sum += *sp++; /* ip_src */
1075 sum += *sp++;
1076 sum += *sp++; /* ip_dst */
1077 sum += *sp++;
1078 if (sp != (u_short *)tcp)
1079 sp = (u_short *)tcp;
1080 sum += *sp++; /* sport */
1081 sum += *sp++; /* dport */
1082 sum += *sp++; /* seq */
1083 sum += *sp++;
1084 sum += *sp++; /* ack */
1085 sum += *sp++;
1086 sum += *sp++; /* off */
1087 sum += *sp++; /* win */
1088 sum += *sp++; /* Skip over checksum */
1089 sum += *sp++; /* urp */
1090
1091# ifdef __sgi
1092 /*
1093 * In case we had to copy the IP & TCP header out of mbufs,
1094 * skip over the mbuf bits which are the header
1095 */
1096 if ((caddr_t)ip != mtod(m, caddr_t)) {
1097 hlen = (caddr_t)sp - (caddr_t)ip;
1098 while (hlen) {
1099 add = MIN(hlen, m->m_len);
1100 sp = (u_short *)(mtod(m, caddr_t) + add);
1101 hlen -= add;
1102 if (add == m->m_len) {
1103 m = m->m_next;
1104 if (!hlen) {
1105 if (!m)
1106 break;
1107 sp = mtod(m, u_short *);
1108 }
1109 PANIC((!m),("fr_tcpsum(1): not enough data"));
1110 }
1111 }
1112 }
1113# endif
1114
1115 if (!(len -= sizeof(*tcp)))
1116 goto nodata;
1117 while (len > 1) {
1118 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
1119 m = m->m_next;
1120 PANIC((!m),("fr_tcpsum(2): not enough data"));
1121 sp = mtod(m, u_short *);
1122 }
1123 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
1124 bytes.c[0] = *(u_char *)sp;
1125 m = m->m_next;
1126 PANIC((!m),("fr_tcpsum(3): not enough data"));
1127 sp = mtod(m, u_short *);
1128 bytes.c[1] = *(u_char *)sp;
1129 sum += bytes.s;
1130 sp = (u_short *)((u_char *)sp + 1);
1131 }
1132 if ((u_long)sp & 1) {
1133 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
1134 sum += bytes.s;
1135 } else
1136 sum += *sp++;
1137 len -= 2;
1138 }
1139 if (len)
1140 sum += ntohs(*(u_char *)sp << 8);
1141nodata:
1142 while (sum > 0xffff)
1143 sum = (sum & 0xffff) + (sum >> 16);
1144 sum2 = (u_short)(~sum & 0xffff);
1145}
1146# endif /* defined(BSD) || defined(sun) */
1147# endif /* SOLARIS */
1148#else /* KERNEL */
1149 sum2 = 0;
1150#endif /* KERNEL */
1151 tcp->th_sum = ts;
1152 return sum2;
1153}
1154
1155
1156#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1157/*
1158 * Copyright (c) 1982, 1986, 1988, 1991, 1993
1159 * The Regents of the University of California. All rights reserved.
1160 *
1161 * Redistribution and use in source and binary forms, with or without
1162 * modification, are permitted provided that the following conditions
1163 * are met:
1164 * 1. Redistributions of source code must retain the above copyright
1165 * notice, this list of conditions and the following disclaimer.
1166 * 2. Redistributions in binary form must reproduce the above copyright
1167 * notice, this list of conditions and the following disclaimer in the
1168 * documentation and/or other materials provided with the distribution.
1169 * 3. All advertising materials mentioning features or use of this software
1170 * must display the following acknowledgement:
1171 * This product includes software developed by the University of
1172 * California, Berkeley and its contributors.
1173 * 4. Neither the name of the University nor the names of its contributors
1174 * may be used to endorse or promote products derived from this software
1175 * without specific prior written permission.
1176 *
1177 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1178 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1179 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1180 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1181 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1182 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1183 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1184 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1185 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1186 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1187 * SUCH DAMAGE.
1188 *
1189 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1190 * $Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $
1191 */
1192/*
1193 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1194 * continuing for "len" bytes, into the indicated buffer.
1195 */
1196void
1197m_copydata(m, off, len, cp)
1198 register mb_t *m;
1199 register int off;
1200 register int len;
1201 caddr_t cp;
1202{
1203 register unsigned count;
1204
1205 if (off < 0 || len < 0)
1206 panic("m_copydata");
1207 while (off > 0) {
1208 if (m == 0)
1209 panic("m_copydata");
1210 if (off < m->m_len)
1211 break;
1212 off -= m->m_len;
1213 m = m->m_next;
1214 }
1215 while (len > 0) {
1216 if (m == 0)
1217 panic("m_copydata");
1218 count = MIN(m->m_len - off, len);
1219 bcopy(mtod(m, caddr_t) + off, cp, count);
1220 len -= count;
1221 cp += count;
1222 off = 0;
1223 m = m->m_next;
1224 }
1225}
1226
1227
1228# ifndef linux
1229/*
1230 * Copy data from a buffer back into the indicated mbuf chain,
1231 * starting "off" bytes from the beginning, extending the mbuf
1232 * chain if necessary.
1233 */
1234void
1235m_copyback(m0, off, len, cp)
1236 struct mbuf *m0;
1237 register int off;
1238 register int len;
1239 caddr_t cp;
1240{
1241 register int mlen;
1242 register struct mbuf *m = m0, *n;
1243 int totlen = 0;
1244
1245 if (m0 == 0)
1246 return;
1247 while (off > (mlen = m->m_len)) {
1248 off -= mlen;
1249 totlen += mlen;
1250 if (m->m_next == 0) {
1251 n = m_getclr(M_DONTWAIT, m->m_type);
1252 if (n == 0)
1253 goto out;
1254 n->m_len = min(MLEN, len + off);
1255 m->m_next = n;
1256 }
1257 m = m->m_next;
1258 }
1259 while (len > 0) {
1260 mlen = min (m->m_len - off, len);
1261 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1262 cp += mlen;
1263 len -= mlen;
1264 mlen += off;
1265 off = 0;
1266 totlen += mlen;
1267 if (len == 0)
1268 break;
1269 if (m->m_next == 0) {
1270 n = m_get(M_DONTWAIT, m->m_type);
1271 if (n == 0)
1272 break;
1273 n->m_len = min(MLEN, len);
1274 m->m_next = n;
1275 }
1276 m = m->m_next;
1277 }
1278out:
1279#if 0
1280 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1281 m->m_pkthdr.len = totlen;
1282#endif
1283 return;
1284}
1285# endif /* linux */
1286#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1287
1288
1289frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
1290u_int num;
1291u_32_t flags;
1292minor_t which;
1293int set;
1294frgroup_t ***fgpp;
1295{
1296 frgroup_t *fg, **fgp;
1297
1298 if (which == IPL_LOGAUTH)
1299 fgp = &ipfgroups[2][set];
1300 else if (flags & FR_ACCOUNT)
1301 fgp = &ipfgroups[1][set];
1302 else if (flags & (FR_OUTQUE|FR_INQUE))
1303 fgp = &ipfgroups[0][set];
1304 else
1305 return NULL;
1306 num &= 0xffff;
1307
1308 while ((fg = *fgp))
1309 if (fg->fg_num == num)
1310 break;
1311 else
1312 fgp = &fg->fg_next;
1313 if (fgpp)
1314 *fgpp = fgp;
1315 return fg;
1316}
1317
1318
1319frgroup_t *fr_addgroup(num, fp, which, set)
1320u_int num;
1321frentry_t *fp;
1322minor_t which;
1323int set;
1324{
1325 frgroup_t *fg, **fgp;
1326
1327 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
1328 return fg;
1329
1330 KMALLOC(fg, frgroup_t *);
1331 if (fg) {
1332 fg->fg_num = num & 0xffff;
1333 fg->fg_next = *fgp;
1334 fg->fg_head = fp;
1335 fg->fg_start = &fp->fr_grp;
1336 *fgp = fg;
1337 }
1338 return fg;
1339}
1340
1341
1342void fr_delgroup(num, flags, which, set)
1343u_int num;
1344u_32_t flags;
1345minor_t which;
1346int set;
1347{
1348 frgroup_t *fg, **fgp;
1349
1350 if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
1351 return;
1352
1353 *fgp = fg->fg_next;
1354 KFREE(fg);
1355}
1356
1357
1358
1359/*
1360 * recursively flush rules from the list, descending groups as they are
1361 * encountered. if a rule is the head of a group and it has lost all its
1362 * group members, then also delete the group reference.
1363 */
1364static int frflushlist(set, unit, nfreedp, listp)
1365int set;
1366minor_t unit;
1367int *nfreedp;
1368frentry_t **listp;
1369{
1370 register int freed = 0, i;
1371 register frentry_t *fp;
1372
1373 while ((fp = *listp)) {
1374 *listp = fp->fr_next;
1375 if (fp->fr_grp) {
1376 i = frflushlist(set, unit, nfreedp, &fp->fr_grp);
1377 MUTEX_ENTER(&ipf_rw);
1378 fp->fr_ref -= i;
1379 MUTEX_EXIT(&ipf_rw);
1380 }
1381
1382 ATOMIC_DEC(fp->fr_ref);
1383 if (fp->fr_grhead) {
1384 fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags,
1385 unit, set);
1386 fp->fr_grhead = NULL;
1387 }
1388 if (fp->fr_ref == 0) {
1389 KFREE(fp);
1390 freed++;
1391 } else
1392 fp->fr_next = NULL;
1393 }
1394 *nfreedp += freed;
1395 return freed;
1396}
1397
1398
1399int frflush(unit, flags)
1400minor_t unit;
1401int flags;
1402{
1403 int flushed = 0, set;
1404
1405 if (unit != IPL_LOGIPF)
1406 return 0;
1407 WRITE_ENTER(&ipf_mutex);
1408 bzero((char *)frcache, sizeof(frcache[0]) * 2);
1409
1410 set = fr_active;
1411 if (flags & FR_INACTIVE)
1412 set = 1 - set;
1413
1414 if (flags & FR_OUTQUE) {
1415 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
1416 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
1417 }
1418 if (flags & FR_INQUE) {
1419 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
1420 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
1421 }
1422 RWLOCK_EXIT(&ipf_mutex);
1423 return flushed;
1424}
1425
1426
1427char *memstr(src, dst, slen, dlen)
1428char *src, *dst;
1429int slen, dlen;
1430{
1431 char *s = NULL;
1432
1433 while (dlen >= slen) {
1434 if (bcmp(src, dst, slen) == 0) {
1435 s = dst;
1436 break;
1437 }
1438 dst++;
1439 dlen--;
1440 }
1441 return s;
1442}
1443
1444
1445void fixskip(listp, rp, addremove)
1446frentry_t **listp, *rp;
1447int addremove;
1448{
1449 frentry_t *fp;
1450 int rules = 0, rn = 0;
1451
1452 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
1453 ;
1454
1455 if (!fp)
1456 return;
1457
1458 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
1459 if (fp->fr_skip && (rn + fp->fr_skip >= rules))
1460 fp->fr_skip += addremove;
1461}
1462
1463
1464#ifdef _KERNEL
1465/*
1466 * count consecutive 1's in bit mask. If the mask generated by counting
1467 * consecutive 1's is different to that passed, return -1, else return #
1468 * of bits.
1469 */
1470int countbits(ip)
1471u_32_t ip;
1472{
1473 u_32_t ipn;
1474 int cnt = 0, i, j;
1475
1476 ip = ipn = ntohl(ip);
1477 for (i = 32; i; i--, ipn *= 2)
1478 if (ipn & 0x80000000)
1479 cnt++;
1480 else
1481 break;
1482 ipn = 0;
1483 for (i = 32, j = cnt; i; i--, j--) {
1484 ipn *= 2;
1485 if (j > 0)
1486 ipn++;
1487 }
1488 if (ipn == ip)
1489 return cnt;
1490 return -1;
1491}
1492
1493
1494/*
1495 * return the first IP Address associated with an interface
1496 */
1497int fr_ifpaddr(ifptr, inp)
1498void *ifptr;
1499struct in_addr *inp;
1500{
1501# if SOLARIS
1502 ill_t *ill = ifptr;
1503# else
1504 struct ifnet *ifp = ifptr;
1505# endif
1506 struct in_addr in;
1507
1508# if SOLARIS
1509 in.s_addr = ill->ill_ipif->ipif_local_addr;
1510# else /* SOLARIS */
1511# if linux
1512 ;
1513# else /* linux */
1514 struct ifaddr *ifa;
1515 struct sockaddr_in *sin;
1516
1517# if (__FreeBSD_version >= 300000)
1518 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1519# else
1520# if defined(__NetBSD__) || defined(__OpenBSD__)
1521 ifa = ifp->if_addrlist.tqh_first;
1522# else
1523# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
1524 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa;
1525# else
1526 ifa = ifp->if_addrlist;
1527# endif
1528# endif /* __NetBSD__ || __OpenBSD__ */
1529# endif /* __FreeBSD_version >= 300000 */
1530# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK))
1531 sin = (struct sockaddr_in *)&ifa->ifa_addr;
1532# else
1533 sin = (struct sockaddr_in *)ifa->ifa_addr;
1534 while (sin && ifa &&
1535 sin->sin_family != AF_INET) {
1536# if (__FreeBSD_version >= 300000)
1537 ifa = TAILQ_NEXT(ifa, ifa_link);
1538# else
1539# if defined(__NetBSD__) || defined(__OpenBSD__)
1540 ifa = ifa->ifa_list.tqe_next;
1541# else
1542 ifa = ifa->ifa_next;
1543# endif
1544# endif /* __FreeBSD_version >= 300000 */
1545 if (ifa)
1546 sin = (struct sockaddr_in *)ifa->ifa_addr;
1547 }
1548 if (ifa == NULL)
1549 sin = NULL;
1550 if (sin == NULL)
1551 return -1;
1552# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
1553 in = sin->sin_addr;
1554# endif /* linux */
1555# endif /* SOLARIS */
1556 *inp = in;
1557 return 0;
1558}
1559
1560
1561static void frsynclist(fr)
1562register frentry_t *fr;
1563{
1564 for (; fr; fr = fr->fr_next) {
1565 if (fr->fr_ifa != NULL) {
1566 fr->fr_ifa = GETUNIT(fr->fr_ifname);
1567 if (fr->fr_ifa == NULL)
1568 fr->fr_ifa = (void *)-1;
1569 }
1570 if (fr->fr_grp)
1571 frsynclist(fr->fr_grp);
1572 }
1573}
1574
1575
1576void frsync()
1577{
1578 register struct ifnet *ifp;
1579
1580# if !SOLARIS
1581# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
1582 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
1583# if (NetBSD >= 199905) || defined(__OpenBSD__)
1584 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
1585# else
1586 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
1587# endif
1588# else
1589 for (ifp = ifnet; ifp; ifp = ifp->if_next)
1590# endif
1591 {
1592 ip_natsync(ifp);
1593 ip_statesync(ifp);
1594 }
1595# endif
1596
1597 WRITE_ENTER(&ipf_mutex);
1598 frsynclist(ipacct[0][fr_active]);
1599 frsynclist(ipacct[1][fr_active]);
1600 frsynclist(ipfilter[0][fr_active]);
1601 frsynclist(ipfilter[1][fr_active]);
1602 RWLOCK_EXIT(&ipf_mutex);
1603}
1604
1605#else
1606
1607
1608/*
1609 * return the first IP Address associated with an interface
1610 */
1611int fr_ifpaddr(ifptr, inp)
1612void *ifptr;
1613struct in_addr *inp;
1614{
1615 return 0;
1616}
1617#endif
12#endif
13
14#include <sys/errno.h>
15#include <sys/types.h>
16#include <sys/param.h>
17#include <sys/time.h>
18#include <sys/file.h>
19#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
20 defined(_KERNEL)
21# include "opt_ipfilter_log.h"
22#endif
23#if defined(_KERNEL) && defined(__FreeBSD_version) && \
24 (__FreeBSD_version >= 220000)
25# include <sys/filio.h>
26# include <sys/fcntl.h>
27#else
28# include <sys/ioctl.h>
29#endif
30#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux)
31# include <sys/systm.h>
32#else
33# include <stdio.h>
34# include <string.h>
35# include <stdlib.h>
36#endif
37#include <sys/uio.h>
38#if !defined(__SVR4) && !defined(__svr4__)
39# ifndef linux
40# include <sys/mbuf.h>
41# endif
42#else
43# include <sys/byteorder.h>
44# if SOLARIS2 < 5
45# include <sys/dditypes.h>
46# endif
47# include <sys/stream.h>
48#endif
49#ifndef linux
50# include <sys/protosw.h>
51# include <sys/socket.h>
52#endif
53#include <net/if.h>
54#ifdef sun
55# include <net/af.h>
56#endif
57#include <net/route.h>
58#include <netinet/in.h>
59#include <netinet/in_systm.h>
60#include <netinet/ip.h>
61#ifndef linux
62# include <netinet/ip_var.h>
63#endif
64#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
65# include <sys/hashing.h>
66# include <netinet/in_var.h>
67#endif
68#include <netinet/tcp.h>
69#include <netinet/udp.h>
70#include <netinet/ip_icmp.h>
71#include "netinet/ip_compat.h"
72#include <netinet/tcpip.h>
73#include "netinet/ip_fil.h"
74#include "netinet/ip_proxy.h"
75#include "netinet/ip_nat.h"
76#include "netinet/ip_frag.h"
77#include "netinet/ip_state.h"
78#include "netinet/ip_auth.h"
79# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
80# include <sys/malloc.h>
81# if defined(_KERNEL) && !defined(IPFILTER_LKM)
82# include "opt_ipfilter.h"
83# endif
84# endif
85#ifndef MIN
86# define MIN(a,b) (((a)<(b))?(a):(b))
87#endif
88#include "netinet/ipl.h"
89
90#ifndef _KERNEL
91# include "ipf.h"
92# include "ipt.h"
93extern int opts;
94
95# define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \
96 second; }
97# define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \
98 second; }
99# define FR_VERBOSE(verb_pr) verbose verb_pr
100# define FR_DEBUG(verb_pr) debug verb_pr
101# define SEND_RESET(ip, qif, if, m, fin) send_reset(ip, if)
102# define IPLLOG(a, c, d, e) ipllog()
103# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
104#else /* #ifndef _KERNEL */
105# define FR_IFVERBOSE(ex,second,verb_pr) ;
106# define FR_IFDEBUG(ex,second,verb_pr) ;
107# define FR_VERBOSE(verb_pr)
108# define FR_DEBUG(verb_pr)
109# define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
110# if SOLARIS || defined(__sgi)
111extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat;
112extern kmutex_t ipf_rw;
113# endif
114# if SOLARIS
115# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \
116 ip, qif)
117# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip, qif)
118# define ICMP_ERROR(b, ip, t, c, if, dst) \
119 icmp_error(ip, t, c, if, dst)
120# else /* SOLARIS */
121# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip)
122# ifdef linux
123# define SEND_RESET(ip, qif, if, fin) send_reset(ip, ifp)
124# define ICMP_ERROR(b, ip, t, c, if, dst) icmp_send(b,t,c,0,if)
125# else
126# define SEND_RESET(ip, qif, if, fin) send_reset(fin, ip)
127# define ICMP_ERROR(b, ip, t, c, if, dst) \
128 send_icmp_err(ip, t, c, if, dst)
129# endif /* linux */
130# endif /* SOLARIS || __sgi */
131#endif /* _KERNEL */
132
133
134struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
135struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
136 *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
137struct frgroup *ipfgroups[3][2];
138int fr_flags = IPF_LOGGING, fr_active = 0;
139#if defined(IPFILTER_DEFAULT_BLOCK)
140int fr_pass = FR_NOMATCH|FR_BLOCK;
141#else
142int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH);
143#endif
144char ipfilter_version[] = IPL_VERSION;
145
146fr_info_t frcache[2];
147
148static int fr_tcpudpchk __P((frentry_t *, fr_info_t *));
149static int frflushlist __P((int, minor_t, int *, frentry_t **));
150#ifdef _KERNEL
151static void frsynclist __P((frentry_t *));
152#endif
153
154
155/*
156 * bit values for identifying presence of individual IP options
157 */
158struct optlist ipopts[20] = {
159 { IPOPT_NOP, 0x000001 },
160 { IPOPT_RR, 0x000002 },
161 { IPOPT_ZSU, 0x000004 },
162 { IPOPT_MTUP, 0x000008 },
163 { IPOPT_MTUR, 0x000010 },
164 { IPOPT_ENCODE, 0x000020 },
165 { IPOPT_TS, 0x000040 },
166 { IPOPT_TR, 0x000080 },
167 { IPOPT_SECURITY, 0x000100 },
168 { IPOPT_LSRR, 0x000200 },
169 { IPOPT_E_SEC, 0x000400 },
170 { IPOPT_CIPSO, 0x000800 },
171 { IPOPT_SATID, 0x001000 },
172 { IPOPT_SSRR, 0x002000 },
173 { IPOPT_ADDEXT, 0x004000 },
174 { IPOPT_VISA, 0x008000 },
175 { IPOPT_IMITD, 0x010000 },
176 { IPOPT_EIP, 0x020000 },
177 { IPOPT_FINN, 0x040000 },
178 { 0, 0x000000 }
179};
180
181/*
182 * bit values for identifying presence of individual IP security options
183 */
184struct optlist secopt[8] = {
185 { IPSO_CLASS_RES4, 0x01 },
186 { IPSO_CLASS_TOPS, 0x02 },
187 { IPSO_CLASS_SECR, 0x04 },
188 { IPSO_CLASS_RES3, 0x08 },
189 { IPSO_CLASS_CONF, 0x10 },
190 { IPSO_CLASS_UNCL, 0x20 },
191 { IPSO_CLASS_RES2, 0x40 },
192 { IPSO_CLASS_RES1, 0x80 }
193};
194
195
196/*
197 * compact the IP header into a structure which contains just the info.
198 * which is useful for comparing IP headers with.
199 */
200void fr_makefrip(hlen, ip, fin)
201int hlen;
202ip_t *ip;
203fr_info_t *fin;
204{
205 struct optlist *op;
206 tcphdr_t *tcp;
207 fr_ip_t *fi = &fin->fin_fi;
208 u_short optmsk = 0, secmsk = 0, auth = 0;
209 int i, mv, ol, off;
210 u_char *s, opt;
211
212 fin->fin_rev = 0;
213 fin->fin_fr = NULL;
214 fin->fin_tcpf = 0;
215 fin->fin_data[0] = 0;
216 fin->fin_data[1] = 0;
217 fin->fin_rule = -1;
218 fin->fin_group = -1;
219 fin->fin_id = ip->ip_id;
220#ifdef _KERNEL
221 fin->fin_icode = ipl_unreach;
222#endif
223 fi->fi_v = ip->ip_v;
224 fi->fi_tos = ip->ip_tos;
225 fin->fin_hlen = hlen;
226 fin->fin_dlen = ip->ip_len - hlen;
227 tcp = (tcphdr_t *)((char *)ip + hlen);
228 fin->fin_dp = (void *)tcp;
229 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
230 fi->fi_src.s_addr = ip->ip_src.s_addr;
231 fi->fi_dst.s_addr = ip->ip_dst.s_addr;
232
233 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
234 off = (ip->ip_off & IP_OFFMASK) << 3;
235 if (ip->ip_off & 0x3fff)
236 fi->fi_fl |= FI_FRAG;
237 switch (ip->ip_p)
238 {
239 case IPPROTO_ICMP :
240 {
241 int minicmpsz = sizeof(struct icmp);
242 icmphdr_t *icmp;
243
244 icmp = (icmphdr_t *)tcp;
245
246 if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
247 icmp->icmp_type == ICMP_ECHO))
248 minicmpsz = ICMP_MINLEN;
249 if (!off && (icmp->icmp_type == ICMP_TSTAMP ||
250 icmp->icmp_type == ICMP_TSTAMPREPLY))
251 minicmpsz = 20; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + 3*timestamp(3*4) */
252 if (!off && (icmp->icmp_type == ICMP_MASKREQ ||
253 icmp->icmp_type == ICMP_MASKREPLY))
254 minicmpsz = 12; /* type(1) + code(1) + cksum(2) + id(2) + seq(2) + mask(4) */
255 if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
256 (off && off < sizeof(struct icmp)))
257 fi->fi_fl |= FI_SHORT;
258 if (fin->fin_dlen > 1)
259 fin->fin_data[0] = *(u_short *)tcp;
260 break;
261 }
262 case IPPROTO_TCP :
263 fi->fi_fl |= FI_TCPUDP;
264 if ((!IPMINLEN(ip, tcphdr) && !off) ||
265 (off && off < sizeof(struct tcphdr)))
266 fi->fi_fl |= FI_SHORT;
267 if (!(fi->fi_fl & FI_SHORT) && !off)
268 fin->fin_tcpf = tcp->th_flags;
269 goto getports;
270 case IPPROTO_UDP :
271 fi->fi_fl |= FI_TCPUDP;
272 if ((!IPMINLEN(ip, udphdr) && !off) ||
273 (off && off < sizeof(struct udphdr)))
274 fi->fi_fl |= FI_SHORT;
275getports:
276 if (!off && (fin->fin_dlen > 3)) {
277 fin->fin_data[0] = ntohs(tcp->th_sport);
278 fin->fin_data[1] = ntohs(tcp->th_dport);
279 }
280 break;
281 default :
282 break;
283 }
284
285
286 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen; ) {
287 opt = *s;
288 if (opt == '\0')
289 break;
290 ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
291 if (opt > 1 && (ol < 2 || ol > hlen))
292 break;
293 for (i = 9, mv = 4; mv >= 0; ) {
294 op = ipopts + i;
295 if (opt == (u_char)op->ol_val) {
296 optmsk |= op->ol_bit;
297 if (opt == IPOPT_SECURITY) {
298 struct optlist *sp;
299 u_char sec;
300 int j, m;
301
302 sec = *(s + 2); /* classification */
303 for (j = 3, m = 2; m >= 0; ) {
304 sp = secopt + j;
305 if (sec == sp->ol_val) {
306 secmsk |= sp->ol_bit;
307 auth = *(s + 3);
308 auth *= 256;
309 auth += *(s + 4);
310 break;
311 }
312 if (sec < sp->ol_val)
313 j -= m--;
314 else
315 j += m--;
316 }
317 }
318 break;
319 }
320 if (opt < op->ol_val)
321 i -= mv--;
322 else
323 i += mv--;
324 }
325 hlen -= ol;
326 s += ol;
327 }
328 if (auth && !(auth & 0x0100))
329 auth &= 0xff00;
330 fi->fi_optmsk = optmsk;
331 fi->fi_secmsk = secmsk;
332 fi->fi_auth = auth;
333}
334
335
336/*
337 * check an IP packet for TCP/UDP characteristics such as ports and flags.
338 */
339static int fr_tcpudpchk(fr, fin)
340frentry_t *fr;
341fr_info_t *fin;
342{
343 register u_short po, tup;
344 register char i;
345 register int err = 1;
346
347 /*
348 * Both ports should *always* be in the first fragment.
349 * So far, I cannot find any cases where they can not be.
350 *
351 * compare destination ports
352 */
353 if ((i = (int)fr->fr_dcmp)) {
354 po = fr->fr_dport;
355 tup = fin->fin_data[1];
356 /*
357 * Do opposite test to that required and
358 * continue if that succeeds.
359 */
360 if (!--i && tup != po) /* EQUAL */
361 err = 0;
362 else if (!--i && tup == po) /* NOTEQUAL */
363 err = 0;
364 else if (!--i && tup >= po) /* LESSTHAN */
365 err = 0;
366 else if (!--i && tup <= po) /* GREATERTHAN */
367 err = 0;
368 else if (!--i && tup > po) /* LT or EQ */
369 err = 0;
370 else if (!--i && tup < po) /* GT or EQ */
371 err = 0;
372 else if (!--i && /* Out of range */
373 (tup >= po && tup <= fr->fr_dtop))
374 err = 0;
375 else if (!--i && /* In range */
376 (tup <= po || tup >= fr->fr_dtop))
377 err = 0;
378 }
379 /*
380 * compare source ports
381 */
382 if (err && (i = (int)fr->fr_scmp)) {
383 po = fr->fr_sport;
384 tup = fin->fin_data[0];
385 if (!--i && tup != po)
386 err = 0;
387 else if (!--i && tup == po)
388 err = 0;
389 else if (!--i && tup >= po)
390 err = 0;
391 else if (!--i && tup <= po)
392 err = 0;
393 else if (!--i && tup > po)
394 err = 0;
395 else if (!--i && tup < po)
396 err = 0;
397 else if (!--i && /* Out of range */
398 (tup >= po && tup <= fr->fr_stop))
399 err = 0;
400 else if (!--i && /* In range */
401 (tup <= po || tup >= fr->fr_stop))
402 err = 0;
403 }
404
405 /*
406 * If we don't have all the TCP/UDP header, then how can we
407 * expect to do any sort of match on it ? If we were looking for
408 * TCP flags, then NO match. If not, then match (which should
409 * satisfy the "short" class too).
410 */
411 if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
412 if (fin->fin_fi.fi_fl & FI_SHORT)
413 return !(fr->fr_tcpf | fr->fr_tcpfm);
414 /*
415 * Match the flags ? If not, abort this match.
416 */
417 if (fr->fr_tcpfm &&
418 fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
419 FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
420 fr->fr_tcpfm, fr->fr_tcpf));
421 err = 0;
422 }
423 }
424 return err;
425}
426
427/*
428 * Check the input/output list of rules for a match and result.
429 * Could be per interface, but this gets real nasty when you don't have
430 * kernel sauce.
431 */
432int fr_scanlist(pass, ip, fin, m)
433u_32_t pass;
434ip_t *ip;
435register fr_info_t *fin;
436void *m;
437{
438 register struct frentry *fr;
439 register fr_ip_t *fi = &fin->fin_fi;
440 int rulen, portcmp = 0, off, skip = 0, logged = 0;
441 u_32_t passt;
442
443 fr = fin->fin_fr;
444 fin->fin_fr = NULL;
445 fin->fin_rule = 0;
446 fin->fin_group = 0;
447 off = ip->ip_off & IP_OFFMASK;
448 pass |= (fi->fi_fl << 24);
449
450 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
451 portcmp = 1;
452
453 for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
454 if (skip) {
455 skip--;
456 continue;
457 }
458 /*
459 * In all checks below, a null (zero) value in the
460 * filter struture is taken to mean a wildcard.
461 *
462 * check that we are working for the right interface
463 */
464#ifdef _KERNEL
465# if BSD >= 199306
466 if (fin->fin_out != 0) {
467 if ((fr->fr_oifa &&
468 fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) ||
469 (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp))
470 continue;
471 } else
472# endif
473 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
474 continue;
475#else
476 if (opts & (OPT_VERBOSE|OPT_DEBUG))
477 printf("\n");
478 FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' :
479 (pass & FR_AUTH) ? 'a' : 'b'));
480 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
481 continue;
482 FR_VERBOSE((":i"));
483#endif
484 {
485 register u_32_t *ld, *lm, *lip;
486 register int i;
487
488 lip = (u_32_t *)fi;
489 lm = (u_32_t *)&fr->fr_mip;
490 ld = (u_32_t *)&fr->fr_ip;
491 i = ((lip[0] & lm[0]) != ld[0]);
492 FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
493 lip[0], lm[0], ld[0]));
494 i |= ((lip[1] & lm[1]) != ld[1]) << 19;
495 i ^= (fr->fr_flags & FR_NOTSRCIP);
496 FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
497 lip[1], lm[1], ld[1]));
498 i |= ((lip[2] & lm[2]) != ld[2]) << 20;
499 i ^= (fr->fr_flags & FR_NOTDSTIP);
500 FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
501 lip[2], lm[2], ld[2]));
502 i |= ((lip[3] & lm[3]) != ld[3]);
503 FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
504 lip[3], lm[3], ld[3]));
505 i |= ((lip[4] & lm[4]) != ld[4]);
506 FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
507 lip[4], lm[4], ld[4]));
508 if (i)
509 continue;
510 }
511
512 /*
513 * If a fragment, then only the first has what we're looking
514 * for here...
515 */
516 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
517 fr->fr_tcpfm))
518 continue;
519 if (fi->fi_fl & FI_TCPUDP) {
520 if (!fr_tcpudpchk(fr, fin))
521 continue;
522 } else if (fr->fr_icmpm || fr->fr_icmp) {
523 if ((fi->fi_p != IPPROTO_ICMP) || off ||
524 (fin->fin_dlen < 2))
525 continue;
526 if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) {
527 FR_DEBUG(("i. %#x & %#x != %#x\n",
528 fin->fin_data[0], fr->fr_icmpm,
529 fr->fr_icmp));
530 continue;
531 }
532 }
533 FR_VERBOSE(("*"));
534 /*
535 * Just log this packet...
536 */
537 passt = fr->fr_flags;
538 if ((passt & FR_CALLNOW) && fr->fr_func)
539 passt = (*fr->fr_func)(passt, ip, fin);
540 fin->fin_fr = fr;
541#ifdef IPFILTER_LOG
542 if ((passt & FR_LOGMASK) == FR_LOG) {
543 if (!IPLLOG(passt, ip, fin, m)) {
544 ATOMIC_INC(frstats[fin->fin_out].fr_skip);
545 }
546 ATOMIC_INC(frstats[fin->fin_out].fr_pkl);
547 logged = 1;
548 }
549#endif /* IPFILTER_LOG */
550 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG)
551 pass = passt;
552 FR_DEBUG(("pass %#x\n", pass));
553 ATOMIC_INC(fr->fr_hits);
554 if (pass & FR_ACCOUNT)
555 fr->fr_bytes += (U_QUAD_T)ip->ip_len;
556 else
557 fin->fin_icode = fr->fr_icode;
558 fin->fin_rule = rulen;
559 fin->fin_group = fr->fr_group;
560 if (fr->fr_grp) {
561 fin->fin_fr = fr->fr_grp;
562 pass = fr_scanlist(pass, ip, fin, m);
563 if (fin->fin_fr == NULL) {
564 fin->fin_rule = rulen;
565 fin->fin_group = fr->fr_group;
566 fin->fin_fr = fr;
567 }
568 if (pass & FR_DONTCACHE)
569 logged = 1;
570 }
571 if (pass & FR_QUICK)
572 break;
573 }
574 if (logged)
575 pass |= FR_DONTCACHE;
576 return pass;
577}
578
579
580/*
581 * frcheck - filter check
582 * check using source and destination addresses/ports in a packet whether
583 * or not to pass it on or not.
584 */
585int fr_check(ip, hlen, ifp, out
586#if defined(_KERNEL) && SOLARIS
587, qif, mp)
588qif_t *qif;
589#else
590, mp)
591#endif
592mb_t **mp;
593ip_t *ip;
594int hlen;
595void *ifp;
596int out;
597{
598 /*
599 * The above really sucks, but short of writing a diff
600 */
601 fr_info_t frinfo, *fc;
602 register fr_info_t *fin = &frinfo;
603 frentry_t *fr = NULL;
604 int changed, error = EHOSTUNREACH;
605 u_32_t pass, apass;
606#if !SOLARIS || !defined(_KERNEL)
607 register mb_t *m = *mp;
608#endif
609
610#ifdef _KERNEL
611 mb_t *mc = NULL;
612# if !defined(__SVR4) && !defined(__svr4__)
613# ifdef __sgi
614 char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8];
615# endif
616 int up;
617
618# ifdef M_CANFASTFWD
619 /*
620 * XXX For now, IP Filter and fast-forwarding of cached flows
621 * XXX are mutually exclusive. Eventually, IP Filter should
622 * XXX get a "can-fast-forward" filter rule.
623 */
624 m->m_flags &= ~M_CANFASTFWD;
625# endif /* M_CANFASTFWD */
626
627 if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
628 ip->ip_p == IPPROTO_ICMP)) {
629 int plen = 0;
630
631 if ((ip->ip_off & IP_OFFMASK) == 0)
632 switch(ip->ip_p)
633 {
634 case IPPROTO_TCP:
635 plen = sizeof(tcphdr_t);
636 break;
637 case IPPROTO_UDP:
638 plen = sizeof(udphdr_t);
639 break;
640 /* 96 - enough for complete ICMP error IP header */
641 case IPPROTO_ICMP:
642 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t);
643 break;
644 }
645 up = MIN(hlen + plen, ip->ip_len);
646
647 if (up > m->m_len) {
648# ifdef __sgi
649 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */
650 if ((up > sizeof(hbuf)) || (m_length(m) < up)) {
651 ATOMIC_INC(frstats[out].fr_pull[1]);
652 return -1;
653 }
654 m_copydata(m, 0, up, hbuf);
655 ATOMIC_INC(frstats[out].fr_pull[0]);
656 ip = (ip_t *)hbuf;
657# else /* __ sgi */
658# ifndef linux
659 if ((*mp = m_pullup(m, up)) == 0) {
660 ATOMIC_INC(frstats[out].fr_pull[1]);
661 return -1;
662 } else {
663 ATOMIC_INC(frstats[out].fr_pull[0]);
664 m = *mp;
665 ip = mtod(m, ip_t *);
666 }
667# endif /* !linux */
668# endif /* __sgi */
669 } else
670 up = 0;
671 } else
672 up = 0;
673# endif /* !defined(__SVR4) && !defined(__svr4__) */
674# if SOLARIS
675 mb_t *m = qif->qf_m;
676
677 if ((u_int)ip & 0x3)
678 return 2;
679 fin->fin_qfm = m;
680 fin->fin_qif = qif;
681# endif
682#endif /* _KERNEL */
683
684 /*
685 * Be careful here: ip_id is in network byte order when called
686 * from ip_output()
687 */
688 if (out)
689 ip->ip_id = ntohs(ip->ip_id);
690 fr_makefrip(hlen, ip, fin);
691 fin->fin_ifp = ifp;
692 fin->fin_out = out;
693 fin->fin_mp = mp;
694 pass = fr_pass;
695
696 READ_ENTER(&ipf_mutex);
697
698 if (fin->fin_fi.fi_fl & FI_SHORT)
699 ATOMIC_INC(frstats[out].fr_short);
700
701 /*
702 * Check auth now. This, combined with the check below to see if apass
703 * is 0 is to ensure that we don't count the packet twice, which can
704 * otherwise occur when we reprocess it. As it is, we only count it
705 * after it has no auth. table matchup. This also stops NAT from
706 * occuring until after the packet has been auth'd.
707 */
708 apass = fr_checkauth(ip, fin);
709
710 if (!out) {
711 changed = ip_natin(ip, fin);
712 if (!apass && (fin->fin_fr = ipacct[0][fr_active]) &&
713 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
714 ATOMIC_INC(frstats[0].fr_acct);
715 }
716 }
717
718 if (apass || (!(fr = ipfr_knownfrag(ip, fin)) &&
719 !(fr = fr_checkstate(ip, fin)))) {
720 /*
721 * If a packet is found in the auth table, then skip checking
722 * the access lists for permission but we do need to consider
723 * the result as if it were from the ACL's.
724 */
725 if (!apass) {
726 fc = frcache + out;
727 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
728 /*
729 * copy cached data so we can unlock the mutex
730 * earlier.
731 */
732 bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
733 ATOMIC_INC(frstats[out].fr_chit);
734 if ((fr = fin->fin_fr)) {
735 ATOMIC_INC(fr->fr_hits);
736 pass = fr->fr_flags;
737 }
738 } else {
739 if ((fin->fin_fr = ipfilter[out][fr_active]))
740 pass = fr_scanlist(fr_pass, ip, fin, m);
741 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE)))
742 bcopy((char *)fin, (char *)fc,
743 FI_COPYSIZE);
744 if (pass & FR_NOMATCH) {
745 ATOMIC_INC(frstats[out].fr_nom);
746 }
747 }
748 fr = fin->fin_fr;
749 } else
750 pass = apass;
751
752 /*
753 * If we fail to add a packet to the authorization queue,
754 * then we drop the packet later. However, if it was added
755 * then pretend we've dropped it already.
756 */
757 if ((pass & FR_AUTH))
758 if (FR_NEWAUTH(m, fin, ip, qif) != 0)
759#ifdef _KERNEL
760 m = *mp = NULL;
761#else
762 ;
763#endif
764
765 if (pass & FR_PREAUTH) {
766 READ_ENTER(&ipf_auth);
767 if ((fin->fin_fr = ipauth) &&
768 (pass = fr_scanlist(0, ip, fin, m))) {
769 ATOMIC_INC(fr_authstats.fas_hits);
770 } else {
771 ATOMIC_INC(fr_authstats.fas_miss);
772 }
773 RWLOCK_EXIT(&ipf_auth);
774 }
775
776 fin->fin_fr = fr;
777 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) {
778 if (fin->fin_fi.fi_fl & FI_FRAG) {
779 if (ipfr_newfrag(ip, fin, pass) == -1) {
780 ATOMIC_INC(frstats[out].fr_bnfr);
781 } else {
782 ATOMIC_INC(frstats[out].fr_nfr);
783 }
784 } else {
785 ATOMIC_INC(frstats[out].fr_cfr);
786 }
787 }
788 if (pass & FR_KEEPSTATE) {
789 if (fr_addstate(ip, fin, 0) == NULL) {
790 ATOMIC_INC(frstats[out].fr_bads);
791 } else {
792 ATOMIC_INC(frstats[out].fr_ads);
793 }
794 }
795 } else if (fr != NULL) {
796 pass = fr->fr_flags;
797 if (pass & FR_LOGFIRST)
798 pass &= ~(FR_LOGFIRST|FR_LOG);
799 }
800
801 if (fr && fr->fr_func && !(pass & FR_CALLNOW))
802 pass = (*fr->fr_func)(pass, ip, fin);
803
804 /*
805 * Only count/translate packets which will be passed on, out the
806 * interface.
807 */
808 if (out && (pass & FR_PASS)) {
809 if ((fin->fin_fr = ipacct[1][fr_active]) &&
810 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
811 ATOMIC_INC(frstats[1].fr_acct);
812 }
813 fin->fin_fr = fr;
814 changed = ip_natout(ip, fin);
815 } else
816 fin->fin_fr = fr;
817 RWLOCK_EXIT(&ipf_mutex);
818
819#ifdef IPFILTER_LOG
820 if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
821 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
822 pass |= FF_LOGNOMATCH;
823 ATOMIC_INC(frstats[out].fr_npkl);
824 goto logit;
825 } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
826 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
827 if ((pass & FR_LOGMASK) != FR_LOGP)
828 pass |= FF_LOGPASS;
829 ATOMIC_INC(frstats[out].fr_ppkl);
830 goto logit;
831 } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
832 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
833 if ((pass & FR_LOGMASK) != FR_LOGB)
834 pass |= FF_LOGBLOCK;
835 ATOMIC_INC(frstats[out].fr_bpkl);
836logit:
837 if (!IPLLOG(pass, ip, fin, m)) {
838 ATOMIC_INC(frstats[out].fr_skip);
839 if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
840 (FR_PASS|FR_LOGORBLOCK))
841 pass ^= FR_PASS|FR_BLOCK;
842 }
843 }
844 }
845#endif /* IPFILTER_LOG */
846
847 if (out)
848 ip->ip_id = htons(ip->ip_id);
849
850#ifdef _KERNEL
851 /*
852 * Only allow FR_DUP to work if a rule matched - it makes no sense to
853 * set FR_DUP as a "default" as there are no instructions about where
854 * to send the packet.
855 */
856 if (fr && (pass & FR_DUP))
857# if SOLARIS
858 mc = dupmsg(m);
859# else
860# ifndef linux
861 mc = m_copy(m, 0, M_COPYALL);
862# else
863 ;
864# endif
865# endif
866#endif
867 if (pass & FR_PASS) {
868 ATOMIC_INC(frstats[out].fr_pass);
869 } else if (pass & FR_BLOCK) {
870 ATOMIC_INC(frstats[out].fr_block);
871 /*
872 * Should we return an ICMP packet to indicate error
873 * status passing through the packet filter ?
874 * WARNING: ICMP error packets AND TCP RST packets should
875 * ONLY be sent in repsonse to incoming packets. Sending them
876 * in response to outbound packets can result in a panic on
877 * some operating systems.
878 */
879 if (!out) {
880#ifdef _KERNEL
881 if (pass & FR_RETICMP) {
882 struct in_addr dst;
883
884 if ((pass & FR_RETMASK) == FR_FAKEICMP)
885 dst = ip->ip_dst;
886 else
887 dst.s_addr = 0;
888# if SOLARIS
889 ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
890 qif, dst);
891# else
892 ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
893 ifp, dst);
894# endif
895 ATOMIC_INC(frstats[0].fr_ret);
896 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
897 !(fin->fin_fi.fi_fl & FI_SHORT)) {
898 if (SEND_RESET(ip, qif, ifp, fin) == 0) {
899 ATOMIC_INC(frstats[1].fr_ret);
900 }
901 }
902#else
903 if ((pass & FR_RETMASK) == FR_RETICMP) {
904 verbose("- ICMP unreachable sent\n");
905 ATOMIC_INC(frstats[0].fr_ret);
906 } else if ((pass & FR_RETMASK) == FR_FAKEICMP) {
907 verbose("- forged ICMP unreachable sent\n");
908 ATOMIC_INC(frstats[0].fr_ret);
909 } else if (((pass & FR_RETMASK) == FR_RETRST) &&
910 !(fin->fin_fi.fi_fl & FI_SHORT)) {
911 verbose("- TCP RST sent\n");
912 ATOMIC_INC(frstats[1].fr_ret);
913 }
914#endif
915 } else {
916 if (pass & FR_RETRST)
917 error = ECONNRESET;
918 }
919 }
920
921 /*
922 * If we didn't drop off the bottom of the list of rules (and thus
923 * the 'current' rule fr is not NULL), then we may have some extra
924 * instructions about what to do with a packet.
925 * Once we're finished return to our caller, freeing the packet if
926 * we are dropping it (* BSD ONLY *).
927 */
928#if defined(_KERNEL)
929# if !SOLARIS
930# if !defined(linux)
931 if (fr) {
932 frdest_t *fdp = &fr->fr_tif;
933
934 if (((pass & FR_FASTROUTE) && !out) ||
935 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
936 if (ipfr_fastroute(m, fin, fdp) == 0)
937 m = *mp = NULL;
938 }
939 if (mc)
940 ipfr_fastroute(mc, fin, &fr->fr_dif);
941 }
942 if (!(pass & FR_PASS) && m)
943 m_freem(m);
944# ifdef __sgi
945 else if (changed && up && m)
946 m_copyback(m, 0, up, hbuf);
947# endif
948# endif /* !linux */
949# else /* !SOLARIS */
950 if (fr) {
951 frdest_t *fdp = &fr->fr_tif;
952
953 if (((pass & FR_FASTROUTE) && !out) ||
954 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
955 if (ipfr_fastroute(qif, ip, m, mp, fin, fdp) == 0)
956 m = *mp = NULL;
957 }
958 if (mc)
959 ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
960 }
961# endif /* !SOLARIS */
962 return (pass & FR_PASS) ? 0 : error;
963#else /* _KERNEL */
964 if (pass & FR_NOMATCH)
965 return 1;
966 if (pass & FR_PASS)
967 return 0;
968 if (pass & FR_AUTH)
969 return -2;
970 return -1;
971#endif /* _KERNEL */
972}
973
974
975/*
976 * ipf_cksum
977 * addr should be 16bit aligned and len is in bytes.
978 * length is in bytes
979 */
980u_short ipf_cksum(addr, len)
981register u_short *addr;
982register int len;
983{
984 register u_32_t sum = 0;
985
986 for (sum = 0; len > 1; len -= 2)
987 sum += *addr++;
988
989 /* mop up an odd byte, if necessary */
990 if (len == 1)
991 sum += *(u_char *)addr;
992
993 /*
994 * add back carry outs from top 16 bits to low 16 bits
995 */
996 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
997 sum += (sum >> 16); /* add carry */
998 return (u_short)(~sum);
999}
1000
1001
1002/*
1003 * NB: This function assumes we've pullup'd enough for all of the IP header
1004 * and the TCP header. We also assume that data blocks aren't allocated in
1005 * odd sizes.
1006 */
1007u_short fr_tcpsum(m, ip, tcp)
1008mb_t *m;
1009ip_t *ip;
1010tcphdr_t *tcp;
1011{
1012 u_short *sp, slen, ts;
1013 u_int sum, sum2;
1014 int hlen;
1015
1016 /*
1017 * Add up IP Header portion
1018 */
1019 hlen = ip->ip_hl << 2;
1020 slen = ip->ip_len - hlen;
1021 sum = htons((u_short)ip->ip_p);
1022 sum += htons(slen);
1023 sp = (u_short *)&ip->ip_src;
1024 sum += *sp++; /* ip_src */
1025 sum += *sp++;
1026 sum += *sp++; /* ip_dst */
1027 sum += *sp++;
1028 ts = tcp->th_sum;
1029 tcp->th_sum = 0;
1030#ifdef KERNEL
1031# if SOLARIS
1032 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */
1033 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1034 sum2 = ~sum2 & 0xffff;
1035# else /* SOLARIS */
1036# if defined(BSD) || defined(sun)
1037# if BSD >= 199306
1038 m->m_data += hlen;
1039# else
1040 m->m_off += hlen;
1041# endif
1042 m->m_len -= hlen;
1043 sum2 = in_cksum(m, slen);
1044 m->m_len += hlen;
1045# if BSD >= 199306
1046 m->m_data -= hlen;
1047# else
1048 m->m_off -= hlen;
1049# endif
1050 /*
1051 * Both sum and sum2 are partial sums, so combine them together.
1052 */
1053 sum = (sum & 0xffff) + (sum >> 16);
1054 sum = ~sum & 0xffff;
1055 sum2 += sum;
1056 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
1057# else /* defined(BSD) || defined(sun) */
1058{
1059 union {
1060 u_char c[2];
1061 u_short s;
1062 } bytes;
1063 u_short len = ip->ip_len;
1064# if defined(__sgi)
1065 int add;
1066# endif
1067
1068 /*
1069 * Add up IP Header portion
1070 */
1071 sp = (u_short *)&ip->ip_src;
1072 len -= (ip->ip_hl << 2);
1073 sum = ntohs(IPPROTO_TCP);
1074 sum += htons(len);
1075 sum += *sp++; /* ip_src */
1076 sum += *sp++;
1077 sum += *sp++; /* ip_dst */
1078 sum += *sp++;
1079 if (sp != (u_short *)tcp)
1080 sp = (u_short *)tcp;
1081 sum += *sp++; /* sport */
1082 sum += *sp++; /* dport */
1083 sum += *sp++; /* seq */
1084 sum += *sp++;
1085 sum += *sp++; /* ack */
1086 sum += *sp++;
1087 sum += *sp++; /* off */
1088 sum += *sp++; /* win */
1089 sum += *sp++; /* Skip over checksum */
1090 sum += *sp++; /* urp */
1091
1092# ifdef __sgi
1093 /*
1094 * In case we had to copy the IP & TCP header out of mbufs,
1095 * skip over the mbuf bits which are the header
1096 */
1097 if ((caddr_t)ip != mtod(m, caddr_t)) {
1098 hlen = (caddr_t)sp - (caddr_t)ip;
1099 while (hlen) {
1100 add = MIN(hlen, m->m_len);
1101 sp = (u_short *)(mtod(m, caddr_t) + add);
1102 hlen -= add;
1103 if (add == m->m_len) {
1104 m = m->m_next;
1105 if (!hlen) {
1106 if (!m)
1107 break;
1108 sp = mtod(m, u_short *);
1109 }
1110 PANIC((!m),("fr_tcpsum(1): not enough data"));
1111 }
1112 }
1113 }
1114# endif
1115
1116 if (!(len -= sizeof(*tcp)))
1117 goto nodata;
1118 while (len > 1) {
1119 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
1120 m = m->m_next;
1121 PANIC((!m),("fr_tcpsum(2): not enough data"));
1122 sp = mtod(m, u_short *);
1123 }
1124 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
1125 bytes.c[0] = *(u_char *)sp;
1126 m = m->m_next;
1127 PANIC((!m),("fr_tcpsum(3): not enough data"));
1128 sp = mtod(m, u_short *);
1129 bytes.c[1] = *(u_char *)sp;
1130 sum += bytes.s;
1131 sp = (u_short *)((u_char *)sp + 1);
1132 }
1133 if ((u_long)sp & 1) {
1134 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
1135 sum += bytes.s;
1136 } else
1137 sum += *sp++;
1138 len -= 2;
1139 }
1140 if (len)
1141 sum += ntohs(*(u_char *)sp << 8);
1142nodata:
1143 while (sum > 0xffff)
1144 sum = (sum & 0xffff) + (sum >> 16);
1145 sum2 = (u_short)(~sum & 0xffff);
1146}
1147# endif /* defined(BSD) || defined(sun) */
1148# endif /* SOLARIS */
1149#else /* KERNEL */
1150 sum2 = 0;
1151#endif /* KERNEL */
1152 tcp->th_sum = ts;
1153 return sum2;
1154}
1155
1156
1157#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) )
1158/*
1159 * Copyright (c) 1982, 1986, 1988, 1991, 1993
1160 * The Regents of the University of California. All rights reserved.
1161 *
1162 * Redistribution and use in source and binary forms, with or without
1163 * modification, are permitted provided that the following conditions
1164 * are met:
1165 * 1. Redistributions of source code must retain the above copyright
1166 * notice, this list of conditions and the following disclaimer.
1167 * 2. Redistributions in binary form must reproduce the above copyright
1168 * notice, this list of conditions and the following disclaimer in the
1169 * documentation and/or other materials provided with the distribution.
1170 * 3. All advertising materials mentioning features or use of this software
1171 * must display the following acknowledgement:
1172 * This product includes software developed by the University of
1173 * California, Berkeley and its contributors.
1174 * 4. Neither the name of the University nor the names of its contributors
1175 * may be used to endorse or promote products derived from this software
1176 * without specific prior written permission.
1177 *
1178 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1179 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1180 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1181 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1182 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1183 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1184 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1185 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1186 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1187 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1188 * SUCH DAMAGE.
1189 *
1190 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
1191 * $Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $
1192 */
1193/*
1194 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1195 * continuing for "len" bytes, into the indicated buffer.
1196 */
1197void
1198m_copydata(m, off, len, cp)
1199 register mb_t *m;
1200 register int off;
1201 register int len;
1202 caddr_t cp;
1203{
1204 register unsigned count;
1205
1206 if (off < 0 || len < 0)
1207 panic("m_copydata");
1208 while (off > 0) {
1209 if (m == 0)
1210 panic("m_copydata");
1211 if (off < m->m_len)
1212 break;
1213 off -= m->m_len;
1214 m = m->m_next;
1215 }
1216 while (len > 0) {
1217 if (m == 0)
1218 panic("m_copydata");
1219 count = MIN(m->m_len - off, len);
1220 bcopy(mtod(m, caddr_t) + off, cp, count);
1221 len -= count;
1222 cp += count;
1223 off = 0;
1224 m = m->m_next;
1225 }
1226}
1227
1228
1229# ifndef linux
1230/*
1231 * Copy data from a buffer back into the indicated mbuf chain,
1232 * starting "off" bytes from the beginning, extending the mbuf
1233 * chain if necessary.
1234 */
1235void
1236m_copyback(m0, off, len, cp)
1237 struct mbuf *m0;
1238 register int off;
1239 register int len;
1240 caddr_t cp;
1241{
1242 register int mlen;
1243 register struct mbuf *m = m0, *n;
1244 int totlen = 0;
1245
1246 if (m0 == 0)
1247 return;
1248 while (off > (mlen = m->m_len)) {
1249 off -= mlen;
1250 totlen += mlen;
1251 if (m->m_next == 0) {
1252 n = m_getclr(M_DONTWAIT, m->m_type);
1253 if (n == 0)
1254 goto out;
1255 n->m_len = min(MLEN, len + off);
1256 m->m_next = n;
1257 }
1258 m = m->m_next;
1259 }
1260 while (len > 0) {
1261 mlen = min (m->m_len - off, len);
1262 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1263 cp += mlen;
1264 len -= mlen;
1265 mlen += off;
1266 off = 0;
1267 totlen += mlen;
1268 if (len == 0)
1269 break;
1270 if (m->m_next == 0) {
1271 n = m_get(M_DONTWAIT, m->m_type);
1272 if (n == 0)
1273 break;
1274 n->m_len = min(MLEN, len);
1275 m->m_next = n;
1276 }
1277 m = m->m_next;
1278 }
1279out:
1280#if 0
1281 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1282 m->m_pkthdr.len = totlen;
1283#endif
1284 return;
1285}
1286# endif /* linux */
1287#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */
1288
1289
1290frgroup_t *fr_findgroup(num, flags, which, set, fgpp)
1291u_int num;
1292u_32_t flags;
1293minor_t which;
1294int set;
1295frgroup_t ***fgpp;
1296{
1297 frgroup_t *fg, **fgp;
1298
1299 if (which == IPL_LOGAUTH)
1300 fgp = &ipfgroups[2][set];
1301 else if (flags & FR_ACCOUNT)
1302 fgp = &ipfgroups[1][set];
1303 else if (flags & (FR_OUTQUE|FR_INQUE))
1304 fgp = &ipfgroups[0][set];
1305 else
1306 return NULL;
1307 num &= 0xffff;
1308
1309 while ((fg = *fgp))
1310 if (fg->fg_num == num)
1311 break;
1312 else
1313 fgp = &fg->fg_next;
1314 if (fgpp)
1315 *fgpp = fgp;
1316 return fg;
1317}
1318
1319
1320frgroup_t *fr_addgroup(num, fp, which, set)
1321u_int num;
1322frentry_t *fp;
1323minor_t which;
1324int set;
1325{
1326 frgroup_t *fg, **fgp;
1327
1328 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp)))
1329 return fg;
1330
1331 KMALLOC(fg, frgroup_t *);
1332 if (fg) {
1333 fg->fg_num = num & 0xffff;
1334 fg->fg_next = *fgp;
1335 fg->fg_head = fp;
1336 fg->fg_start = &fp->fr_grp;
1337 *fgp = fg;
1338 }
1339 return fg;
1340}
1341
1342
1343void fr_delgroup(num, flags, which, set)
1344u_int num;
1345u_32_t flags;
1346minor_t which;
1347int set;
1348{
1349 frgroup_t *fg, **fgp;
1350
1351 if (!(fg = fr_findgroup(num, flags, which, set, &fgp)))
1352 return;
1353
1354 *fgp = fg->fg_next;
1355 KFREE(fg);
1356}
1357
1358
1359
1360/*
1361 * recursively flush rules from the list, descending groups as they are
1362 * encountered. if a rule is the head of a group and it has lost all its
1363 * group members, then also delete the group reference.
1364 */
1365static int frflushlist(set, unit, nfreedp, listp)
1366int set;
1367minor_t unit;
1368int *nfreedp;
1369frentry_t **listp;
1370{
1371 register int freed = 0, i;
1372 register frentry_t *fp;
1373
1374 while ((fp = *listp)) {
1375 *listp = fp->fr_next;
1376 if (fp->fr_grp) {
1377 i = frflushlist(set, unit, nfreedp, &fp->fr_grp);
1378 MUTEX_ENTER(&ipf_rw);
1379 fp->fr_ref -= i;
1380 MUTEX_EXIT(&ipf_rw);
1381 }
1382
1383 ATOMIC_DEC(fp->fr_ref);
1384 if (fp->fr_grhead) {
1385 fr_delgroup((u_int)fp->fr_grhead, fp->fr_flags,
1386 unit, set);
1387 fp->fr_grhead = NULL;
1388 }
1389 if (fp->fr_ref == 0) {
1390 KFREE(fp);
1391 freed++;
1392 } else
1393 fp->fr_next = NULL;
1394 }
1395 *nfreedp += freed;
1396 return freed;
1397}
1398
1399
1400int frflush(unit, flags)
1401minor_t unit;
1402int flags;
1403{
1404 int flushed = 0, set;
1405
1406 if (unit != IPL_LOGIPF)
1407 return 0;
1408 WRITE_ENTER(&ipf_mutex);
1409 bzero((char *)frcache, sizeof(frcache[0]) * 2);
1410
1411 set = fr_active;
1412 if (flags & FR_INACTIVE)
1413 set = 1 - set;
1414
1415 if (flags & FR_OUTQUE) {
1416 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]);
1417 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]);
1418 }
1419 if (flags & FR_INQUE) {
1420 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]);
1421 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]);
1422 }
1423 RWLOCK_EXIT(&ipf_mutex);
1424 return flushed;
1425}
1426
1427
1428char *memstr(src, dst, slen, dlen)
1429char *src, *dst;
1430int slen, dlen;
1431{
1432 char *s = NULL;
1433
1434 while (dlen >= slen) {
1435 if (bcmp(src, dst, slen) == 0) {
1436 s = dst;
1437 break;
1438 }
1439 dst++;
1440 dlen--;
1441 }
1442 return s;
1443}
1444
1445
1446void fixskip(listp, rp, addremove)
1447frentry_t **listp, *rp;
1448int addremove;
1449{
1450 frentry_t *fp;
1451 int rules = 0, rn = 0;
1452
1453 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++)
1454 ;
1455
1456 if (!fp)
1457 return;
1458
1459 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++)
1460 if (fp->fr_skip && (rn + fp->fr_skip >= rules))
1461 fp->fr_skip += addremove;
1462}
1463
1464
1465#ifdef _KERNEL
1466/*
1467 * count consecutive 1's in bit mask. If the mask generated by counting
1468 * consecutive 1's is different to that passed, return -1, else return #
1469 * of bits.
1470 */
1471int countbits(ip)
1472u_32_t ip;
1473{
1474 u_32_t ipn;
1475 int cnt = 0, i, j;
1476
1477 ip = ipn = ntohl(ip);
1478 for (i = 32; i; i--, ipn *= 2)
1479 if (ipn & 0x80000000)
1480 cnt++;
1481 else
1482 break;
1483 ipn = 0;
1484 for (i = 32, j = cnt; i; i--, j--) {
1485 ipn *= 2;
1486 if (j > 0)
1487 ipn++;
1488 }
1489 if (ipn == ip)
1490 return cnt;
1491 return -1;
1492}
1493
1494
1495/*
1496 * return the first IP Address associated with an interface
1497 */
1498int fr_ifpaddr(ifptr, inp)
1499void *ifptr;
1500struct in_addr *inp;
1501{
1502# if SOLARIS
1503 ill_t *ill = ifptr;
1504# else
1505 struct ifnet *ifp = ifptr;
1506# endif
1507 struct in_addr in;
1508
1509# if SOLARIS
1510 in.s_addr = ill->ill_ipif->ipif_local_addr;
1511# else /* SOLARIS */
1512# if linux
1513 ;
1514# else /* linux */
1515 struct ifaddr *ifa;
1516 struct sockaddr_in *sin;
1517
1518# if (__FreeBSD_version >= 300000)
1519 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1520# else
1521# if defined(__NetBSD__) || defined(__OpenBSD__)
1522 ifa = ifp->if_addrlist.tqh_first;
1523# else
1524# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */
1525 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa;
1526# else
1527 ifa = ifp->if_addrlist;
1528# endif
1529# endif /* __NetBSD__ || __OpenBSD__ */
1530# endif /* __FreeBSD_version >= 300000 */
1531# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK))
1532 sin = (struct sockaddr_in *)&ifa->ifa_addr;
1533# else
1534 sin = (struct sockaddr_in *)ifa->ifa_addr;
1535 while (sin && ifa &&
1536 sin->sin_family != AF_INET) {
1537# if (__FreeBSD_version >= 300000)
1538 ifa = TAILQ_NEXT(ifa, ifa_link);
1539# else
1540# if defined(__NetBSD__) || defined(__OpenBSD__)
1541 ifa = ifa->ifa_list.tqe_next;
1542# else
1543 ifa = ifa->ifa_next;
1544# endif
1545# endif /* __FreeBSD_version >= 300000 */
1546 if (ifa)
1547 sin = (struct sockaddr_in *)ifa->ifa_addr;
1548 }
1549 if (ifa == NULL)
1550 sin = NULL;
1551 if (sin == NULL)
1552 return -1;
1553# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */
1554 in = sin->sin_addr;
1555# endif /* linux */
1556# endif /* SOLARIS */
1557 *inp = in;
1558 return 0;
1559}
1560
1561
1562static void frsynclist(fr)
1563register frentry_t *fr;
1564{
1565 for (; fr; fr = fr->fr_next) {
1566 if (fr->fr_ifa != NULL) {
1567 fr->fr_ifa = GETUNIT(fr->fr_ifname);
1568 if (fr->fr_ifa == NULL)
1569 fr->fr_ifa = (void *)-1;
1570 }
1571 if (fr->fr_grp)
1572 frsynclist(fr->fr_grp);
1573 }
1574}
1575
1576
1577void frsync()
1578{
1579 register struct ifnet *ifp;
1580
1581# if !SOLARIS
1582# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
1583 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
1584# if (NetBSD >= 199905) || defined(__OpenBSD__)
1585 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
1586# else
1587 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
1588# endif
1589# else
1590 for (ifp = ifnet; ifp; ifp = ifp->if_next)
1591# endif
1592 {
1593 ip_natsync(ifp);
1594 ip_statesync(ifp);
1595 }
1596# endif
1597
1598 WRITE_ENTER(&ipf_mutex);
1599 frsynclist(ipacct[0][fr_active]);
1600 frsynclist(ipacct[1][fr_active]);
1601 frsynclist(ipfilter[0][fr_active]);
1602 frsynclist(ipfilter[1][fr_active]);
1603 RWLOCK_EXIT(&ipf_mutex);
1604}
1605
1606#else
1607
1608
1609/*
1610 * return the first IP Address associated with an interface
1611 */
1612int fr_ifpaddr(ifptr, inp)
1613void *ifptr;
1614struct in_addr *inp;
1615{
1616 return 0;
1617}
1618#endif