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