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