1/*
2 * Copyright (C) 1993-2001 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 *
6 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
7 * Use is subject to license terms.
8 */
9
10#include "ipf.h"
11#include "ipt.h"
12#include <sys/ioctl.h>
13#include <sys/file.h>
14
15extern	char	*optarg;
16extern	struct frentry	*ipfilter[2][2];
17extern	struct ipread	snoop, etherf, tcpd, pcap, iptext, iphex;
18extern	struct ifnet	*get_unit __P((char *, int, ipf_stack_t *));
19extern	void	init_ifp __P((void));
20
21int	opts = OPT_DONOTHING;
22int	use_inet6 = 0;
23int	pfil_delayed_copy = 0;
24int	main __P((int, char *[]));
25int	loadrules __P((char *, int));
26int	kmemcpy __P((char *, long, int));
27int     kstrncpy __P((char *, long, int n));
28void	dumpnat __P((ipf_stack_t *ifs));
29void	dumpstate __P((ipf_stack_t *ifs));
30void	dumplookups __P((ipf_stack_t *ifs));
31void	dumpgroups __P((ipf_stack_t *ifs));
32void	drain_log __P((char *, ipf_stack_t *ifs));
33void	fixv4sums __P((mb_t *, ip_t *));
34ipf_stack_t *get_ifs __P((void));
35ipf_stack_t *create_ifs __P((void));
36
37
38#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(SOLARIS) || \
39	(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
40	defined(__osf__) || defined(linux)
41int ipftestioctl __P((int, ioctlcmd_t, ...));
42int ipnattestioctl __P((int, ioctlcmd_t, ...));
43int ipstatetestioctl __P((int, ioctlcmd_t, ...));
44int ipauthtestioctl __P((int, ioctlcmd_t, ...));
45int ipscantestioctl __P((int, ioctlcmd_t, ...));
46int ipsynctestioctl __P((int, ioctlcmd_t, ...));
47int ipooltestioctl __P((int, ioctlcmd_t, ...));
48#else
49int ipftestioctl __P((dev_t, ioctlcmd_t, void *));
50int ipnattestioctl __P((dev_t, ioctlcmd_t, void *));
51int ipstatetestioctl __P((dev_t, ioctlcmd_t, void *));
52int ipauthtestioctl __P((dev_t, ioctlcmd_t, void *));
53int ipsynctestioctl __P((dev_t, ioctlcmd_t, void *));
54int ipscantestioctl __P((dev_t, ioctlcmd_t, void *));
55int ipooltestioctl __P((dev_t, ioctlcmd_t, void *));
56#endif
57
58static	ioctlfunc_t	iocfunctions[IPL_LOGSIZE] = { ipftestioctl,
59						      ipnattestioctl,
60						      ipstatetestioctl,
61						      ipauthtestioctl,
62						      ipsynctestioctl,
63						      ipscantestioctl,
64						      ipooltestioctl,
65						      NULL };
66
67
68int main(argc,argv)
69int argc;
70char *argv[];
71{
72	char	*datain, *iface, *ifname, *logout;
73	int	fd, i, dir, c, loaded, dump, hlen;
74	struct	ifnet	*ifp;
75	struct	ipread	*r;
76	mb_t	mb, *m;
77	ip_t	*ip;
78	ipf_stack_t *ifs;
79
80	m = &mb;
81	dir = 0;
82	dump = 0;
83	hlen = 0;
84	loaded = 0;
85	r = &iptext;
86	iface = NULL;
87	logout = NULL;
88	ifname = "anon0";
89	datain = NULL;
90
91	initparse();
92	ifs = create_ifs();
93
94#if defined(IPFILTER_DEFAULT_BLOCK)
95        ifs->ifs_fr_pass = FR_BLOCK|FR_NOMATCH;
96#else
97        ifs->ifs_fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH;
98#endif
99	ipftuneable_alloc(ifs);
100
101	MUTEX_INIT(&ifs->ifs_ipf_rw, "ipf rw mutex");
102	MUTEX_INIT(&ifs->ifs_ipf_timeoutlock, "ipf timeout lock");
103	RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex");
104	RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
105	RWLOCK_INIT(&ifs->ifs_ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
106	RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf rule cache rwlock");
107
108	fr_loginit(ifs);
109	fr_authinit(ifs);
110	fr_fraginit(ifs);
111	fr_stateinit(ifs);
112	fr_natinit(ifs);
113	appr_init(ifs);
114	ip_lookup_init(ifs);
115	ifs->ifs_fr_running = 1;
116
117	while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1)
118		switch (c)
119		{
120		case '6' :
121#ifdef	USE_INET6
122			use_inet6 = 1;
123#else
124			fprintf(stderr, "IPv6 not supported\n");
125			exit(1);
126#endif
127			break;
128		case 'b' :
129			opts |= OPT_BRIEF;
130			break;
131		case 'd' :
132			opts |= OPT_DEBUG;
133			break;
134		case 'D' :
135			dump = 1;
136			break;
137		case 'F' :
138			if (strcasecmp(optarg, "pcap") == 0)
139				r = &pcap;
140			else if (strcasecmp(optarg, "etherfind") == 0)
141				r = &etherf;
142			else if (strcasecmp(optarg, "snoop") == 0)
143				r = &snoop;
144			else if (strcasecmp(optarg, "tcpdump") == 0)
145				r = &tcpd;
146			else if (strcasecmp(optarg, "hex") == 0)
147				r = &iphex;
148			else if (strcasecmp(optarg, "text") == 0)
149				r = &iptext;
150			break;
151		case 'i' :
152			datain = optarg;
153			break;
154		case 'I' :
155			ifname = optarg;
156			break;
157		case 'l' :
158			logout = optarg;
159			break;
160		case 'o' :
161			opts |= OPT_SAVEOUT;
162			break;
163		case 'r' :
164			if (ipf_parsefile(-1, ipf_addrule, iocfunctions,
165					  optarg) == -1)
166				return -1;
167			loaded = 1;
168			break;
169		case 'R' :
170			opts |= OPT_NORESOLVE;
171			break;
172		case 'v' :
173			opts |= OPT_VERBOSE;
174			break;
175		case 'N' :
176			if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl,
177					    optarg) == -1)
178				return -1;
179			loaded = 1;
180			opts |= OPT_NAT;
181			break;
182		case 'P' :
183			if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1)
184				return -1;
185			loaded = 1;
186			break;
187		case 'T' :
188			ipf_dotuning(-1, optarg, ipftestioctl);
189			break;
190		case 'x' :
191			opts |= OPT_HEX;
192			break;
193		}
194
195	if (loaded == 0) {
196		(void)fprintf(stderr,"no rules loaded\n");
197		exit(-1);
198	}
199
200	if (opts & OPT_SAVEOUT)
201		init_ifp();
202
203	if (datain)
204		fd = (*r->r_open)(datain);
205	else
206		fd = (*r->r_open)("-");
207
208	if (fd < 0)
209		exit(-1);
210
211	ip = MTOD(m, ip_t *);
212	while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf),
213				    &iface, &dir)) > 0) {
214		if (iface == NULL || *iface == '\0')
215			iface = ifname;
216		ifp = get_unit(iface, IP_V(ip), ifs);
217		if (ifp == NULL) {
218			fprintf(stderr, "out of memory\n");
219			exit(1);
220		}
221		if (!use_inet6) {
222			ip->ip_off = ntohs(ip->ip_off);
223			ip->ip_len = ntohs(ip->ip_len);
224			if (r->r_flags & R_DO_CKSUM)
225				fixv4sums(m, ip);
226			hlen = IP_HL(ip) << 2;
227		}
228#ifdef	USE_INET6
229		else
230			hlen = sizeof(ip6_t);
231#endif
232		/* ipfr_slowtimer(); */
233		m = &mb;
234		m->mb_len = i;
235		i = fr_check(ip, hlen, ifp, dir, &m, ifs);
236		if ((opts & OPT_NAT) == 0)
237			switch (i)
238			{
239			case -4 :
240				(void)printf("preauth");
241				break;
242			case -3 :
243				(void)printf("account");
244				break;
245			case -2 :
246				(void)printf("auth");
247				break;
248			case -1 :
249				(void)printf("block");
250				break;
251			case 0 :
252				(void)printf("pass");
253				break;
254			case 1 :
255				(void)printf("nomatch");
256				break;
257			case 3 :
258				(void)printf("block return-rst");
259				break;
260			case 4 :
261				(void)printf("block return-icmp");
262				break;
263			case 5 :
264				(void)printf("block return-icmp-as-dest");
265				break;
266			default :
267				(void)printf("recognised return %#x\n", i);
268				break;
269			}
270		if (!use_inet6) {
271			ip->ip_off = htons(ip->ip_off);
272			ip->ip_len = htons(ip->ip_len);
273		}
274
275		if (!(opts & OPT_BRIEF)) {
276			putchar(' ');
277			printpacket(ip);
278			printf("--------------");
279		} else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF))
280			printpacket(ip);
281		if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL))
282#if  defined(__sgi) && (IRIX < 60500)
283			(*ifp->if_output)(ifp, (void *)m, NULL);
284#else
285# if TRU64 >= 1885
286			(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
287# else
288			(*ifp->if_output)(ifp, (void *)m, NULL, 0);
289# endif
290#endif
291		if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF))
292			putchar('\n');
293		dir = 0;
294		if (iface != ifname) {
295			free(iface);
296			iface = ifname;
297		}
298		m = &mb;
299	}
300	(*r->r_close)();
301
302	if (logout != NULL) {
303		drain_log(logout, ifs);
304	}
305
306	if (dump == 1)  {
307		dumpnat(ifs);
308		dumpstate(ifs);
309		dumplookups(ifs);
310		dumpgroups(ifs);
311	}
312
313	fr_deinitialise(ifs);
314
315	return 0;
316}
317
318
319#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(SOLARIS) || \
320	(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
321	defined(__osf__) || defined(linux)
322int ipftestioctl(int dev, ioctlcmd_t cmd, ...)
323{
324	caddr_t data;
325	va_list ap;
326	int i;
327
328	va_start(ap, cmd);
329	data = va_arg(ap, caddr_t);
330	va_end(ap);
331
332	i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
333	if (opts & OPT_DEBUG)
334		fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n",
335			(u_int)cmd, data, i);
336	if (i != 0) {
337		errno = i;
338		return -1;
339	}
340	return 0;
341}
342
343
344int ipnattestioctl(int dev, ioctlcmd_t cmd, ...)
345{
346	caddr_t data;
347	va_list ap;
348	int i;
349
350	va_start(ap, cmd);
351	data = va_arg(ap, caddr_t);
352	va_end(ap);
353
354	i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
355	if (opts & OPT_DEBUG)
356		fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n",
357			(u_int)cmd, data, i);
358	if (i != 0) {
359		errno = i;
360		return -1;
361	}
362	return 0;
363}
364
365
366int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...)
367{
368	caddr_t data;
369	va_list ap;
370	int i;
371
372	va_start(ap, cmd);
373	data = va_arg(ap, caddr_t);
374	va_end(ap);
375
376	i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
377	if ((opts & OPT_DEBUG) || (i != 0))
378		fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n",
379			(u_int)cmd, data, i);
380	if (i != 0) {
381		errno = i;
382		return -1;
383	}
384	return 0;
385}
386
387
388int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...)
389{
390	caddr_t data;
391	va_list ap;
392	int i;
393
394	va_start(ap, cmd);
395	data = va_arg(ap, caddr_t);
396	va_end(ap);
397
398	i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
399	if ((opts & OPT_DEBUG) || (i != 0))
400		fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n",
401			(u_int)cmd, data, i);
402	if (i != 0) {
403		errno = i;
404		return -1;
405	}
406	return 0;
407}
408
409
410int ipscantestioctl(int dev, ioctlcmd_t cmd, ...)
411{
412	caddr_t data;
413	va_list ap;
414	int i;
415
416	va_start(ap, cmd);
417	data = va_arg(ap, caddr_t);
418	va_end(ap);
419
420	i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
421	if ((opts & OPT_DEBUG) || (i != 0))
422		fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n",
423			(u_int)cmd, data, i);
424	if (i != 0) {
425		errno = i;
426		return -1;
427	}
428	return 0;
429}
430
431
432int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...)
433{
434	caddr_t data;
435	va_list ap;
436	int i;
437
438	va_start(ap, cmd);
439	data = va_arg(ap, caddr_t);
440	va_end(ap);
441
442	i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
443	if ((opts & OPT_DEBUG) || (i != 0))
444		fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n",
445			(u_int)cmd, data, i);
446	if (i != 0) {
447		errno = i;
448		return -1;
449	}
450	return 0;
451}
452
453
454int ipooltestioctl(int dev, ioctlcmd_t cmd, ...)
455{
456	caddr_t data;
457	va_list ap;
458	int i;
459
460	va_start(ap, cmd);
461	data = va_arg(ap, caddr_t);
462	va_end(ap);
463
464	i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
465	if ((opts & OPT_DEBUG) || (i != 0))
466		fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n",
467			(u_int)cmd, data, i);
468	if (i != 0) {
469		errno = i;
470		return -1;
471	}
472	return 0;
473}
474#else
475int ipftestioctl(dev, cmd, data)
476dev_t dev;
477ioctlcmd_t cmd;
478void *data;
479{
480	int i;
481
482	i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
483	if ((opts & OPT_DEBUG) || (i != 0))
484		fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i);
485	if (i != 0) {
486		errno = i;
487		return -1;
488	}
489	return 0;
490}
491
492
493int ipnattestioctl(dev, cmd, data)
494dev_t dev;
495ioctlcmd_t cmd;
496void *data;
497{
498	int i;
499
500	i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
501	if ((opts & OPT_DEBUG) || (i != 0))
502		fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i);
503	if (i != 0) {
504		errno = i;
505		return -1;
506	}
507	return 0;
508}
509
510
511int ipstatetestioctl(dev, cmd, data)
512dev_t dev;
513ioctlcmd_t cmd;
514void *data;
515{
516	int i;
517
518	i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
519	if ((opts & OPT_DEBUG) || (i != 0))
520		fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i);
521	if (i != 0) {
522		errno = i;
523		return -1;
524	}
525	return 0;
526}
527
528
529int ipauthtestioctl(dev, cmd, data)
530dev_t dev;
531ioctlcmd_t cmd;
532void *data;
533{
534	int i;
535
536	i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
537	if ((opts & OPT_DEBUG) || (i != 0))
538		fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i);
539	if (i != 0) {
540		errno = i;
541		return -1;
542	}
543	return 0;
544}
545
546
547int ipsynctestioctl(dev, cmd, data)
548dev_t dev;
549ioctlcmd_t cmd;
550void *data;
551{
552	int i;
553
554	i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
555	if ((opts & OPT_DEBUG) || (i != 0))
556		fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i);
557	if (i != 0) {
558		errno = i;
559		return -1;
560	}
561	return 0;
562}
563
564
565int ipscantestioctl(dev, cmd, data)
566dev_t dev;
567ioctlcmd_t cmd;
568void *data;
569{
570	int i;
571
572	i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
573	if ((opts & OPT_DEBUG) || (i != 0))
574		fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i);
575	if (i != 0) {
576		errno = i;
577		return -1;
578	}
579	return 0;
580}
581
582
583int ipooltestioctl(dev, cmd, data)
584dev_t dev;
585ioctlcmd_t cmd;
586void *data;
587{
588	int i;
589
590	i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
591	if (opts & OPT_DEBUG)
592		fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i);
593	if (i != 0) {
594		errno = i;
595		return -1;
596	}
597	return 0;
598}
599#endif
600
601
602int kmemcpy(addr, offset, size)
603char *addr;
604long offset;
605int size;
606{
607	bcopy((char *)offset, addr, size);
608	return 0;
609}
610
611
612int kstrncpy(buf, pos, n)
613char *buf;
614long pos;
615int n;
616{
617	char *ptr;
618
619	ptr = (char *)pos;
620
621	while ((n-- > 0) && (*buf++ = *ptr++))
622		;
623	return 0;
624}
625
626
627/*
628 * Display the built up NAT table rules and mapping entries.
629 */
630void dumpnat(ifs)
631	ipf_stack_t *ifs;
632{
633	ipnat_t	*ipn;
634	nat_t	*nat;
635
636	printf("List of active MAP/Redirect filters:\n");
637	for (ipn = ifs->ifs_nat_list; ipn != NULL; ipn = ipn->in_next)
638		printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
639	printf("\nList of active sessions:\n");
640	for (nat = ifs->ifs_nat_instances; nat; nat = nat->nat_next) {
641		printactivenat(nat, opts, 0);
642		if (nat->nat_aps)
643			printaps(nat->nat_aps, opts);
644	}
645}
646
647
648/*
649 * Display the built up state table rules and mapping entries.
650 */
651void dumpstate(ifs)
652	ipf_stack_t *ifs;
653{
654	ipstate_t *ips;
655
656	printf("List of active state sessions:\n");
657	for (ips = ifs->ifs_ips_list; ips != NULL; )
658		ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE),
659				 ifs->ifs_fr_ticks);
660}
661
662
663void dumplookups(ifs)
664	ipf_stack_t *ifs;
665{
666	iphtable_t *iph;
667	ip_pool_t *ipl;
668	int i;
669
670	printf("List of configured pools\n");
671	for (i = 0; i < IPL_LOGSIZE; i++)
672		for (ipl = ifs->ifs_ip_pool_list[i]; ipl != NULL;
673		    ipl = ipl->ipo_next)
674			printpool(ipl, bcopywrap, NULL, opts);
675
676	printf("List of configured hash tables\n");
677	for (i = 0; i < IPL_LOGSIZE; i++)
678		for (iph = ifs->ifs_ipf_htables[i]; iph != NULL;
679		     iph = iph->iph_next)
680			printhash(iph, bcopywrap, NULL, opts);
681}
682
683
684void dumpgroups(ifs)
685	ipf_stack_t *ifs;
686{
687	frgroup_t *fg;
688	frentry_t *fr;
689	int i;
690
691	printf("List of groups configured (set 0)\n");
692	for (i = 0; i < IPL_LOGSIZE; i++)
693		for (fg =  ifs->ifs_ipfgroups[i][0]; fg != NULL;
694		    fg = fg->fg_next) {
695			printf("Dev.%d. Group %s Ref %d Flags %#x\n",
696				i, fg->fg_name, fg->fg_ref, fg->fg_flags);
697			for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
698#ifdef	USE_QUAD_T
699				printf("%qu ",(unsigned long long)fr->fr_hits);
700#else
701				printf("%ld ", fr->fr_hits);
702#endif
703				printfr(fr, ipftestioctl);
704			}
705		}
706
707	printf("List of groups configured (set 1)\n");
708	for (i = 0; i < IPL_LOGSIZE; i++)
709		for (fg =  ifs->ifs_ipfgroups[i][1]; fg != NULL;
710		    fg = fg->fg_next) {
711			printf("Dev.%d. Group %s Ref %d Flags %#x\n",
712				i, fg->fg_name, fg->fg_ref, fg->fg_flags);
713			for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
714#ifdef	USE_QUAD_T
715				printf("%qu ",(unsigned long long)fr->fr_hits);
716#else
717				printf("%ld ", fr->fr_hits);
718#endif
719				printfr(fr, ipftestioctl);
720			}
721		}
722}
723
724
725void drain_log(filename, ifs)
726char *filename;
727ipf_stack_t *ifs;
728{
729	char buffer[DEFAULT_IPFLOGSIZE];
730	struct iovec iov;
731	struct uio uio;
732	size_t resid;
733	int fd, i;
734
735	fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
736	if (fd == -1) {
737		perror("drain_log:open");
738		return;
739	}
740
741	for (i = 0; i <= IPL_LOGMAX; i++)
742		while (1) {
743			bzero((char *)&iov, sizeof(iov));
744			iov.iov_base = buffer;
745			iov.iov_len = sizeof(buffer);
746
747			bzero((char *)&uio, sizeof(uio));
748			uio.uio_iov = &iov;
749			uio.uio_iovcnt = 1;
750			uio.uio_resid = iov.iov_len;
751			resid = uio.uio_resid;
752
753			if (ipflog_read(i, &uio, ifs) == 0) {
754				/*
755				 * If nothing was read then break out.
756				 */
757				if (uio.uio_resid == resid)
758					break;
759				write(fd, buffer, resid - uio.uio_resid);
760			} else
761				break;
762	}
763
764	close(fd);
765}
766
767
768void fixv4sums(m, ip)
769mb_t *m;
770ip_t *ip;
771{
772	u_char *csump, *hdr;
773
774	ip->ip_sum = 0;
775	ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2);
776
777	csump = (u_char *)ip;
778	csump += IP_HL(ip) << 2;
779
780	switch (ip->ip_p)
781	{
782	case IPPROTO_TCP :
783		hdr = csump;
784		csump += offsetof(tcphdr_t, th_sum);
785		break;
786	case IPPROTO_UDP :
787		hdr = csump;
788		csump += offsetof(udphdr_t, uh_sum);
789		break;
790	default :
791		csump = NULL;
792		hdr = NULL;
793		break;
794	}
795	if (hdr != NULL) {
796		*csump = 0;
797		*(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr);
798	}
799}
800
801ipf_stack_t *gifs;
802
803/*
804 * Allocate and keep pointer for get_ifs()
805 */
806ipf_stack_t *
807create_ifs()
808{
809	ipf_stack_t *ifs;
810
811	KMALLOCS(ifs, ipf_stack_t *, sizeof (*ifs));
812	bzero(ifs, sizeof (*ifs));
813	gifs = ifs;
814	return (ifs);
815}
816
817ipf_stack_t *
818get_ifs()
819{
820	return (gifs);
821}
822