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