fil.c revision 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";
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 $";
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
1619