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