xref: /titanic_44/usr/src/cmd/ipf/tools/ipftest.c (revision 1ae0874509b6811fdde1dfd46f0d93fd09867a3f)
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 (ifp == NULL) {
211 			fprintf(stderr, "out of memory\n");
212 			exit(1);
213 		}
214 		if (!use_inet6) {
215 			ip->ip_off = ntohs(ip->ip_off);
216 			ip->ip_len = ntohs(ip->ip_len);
217 			if (r->r_flags & R_DO_CKSUM)
218 				fixv4sums(m, ip);
219 			hlen = IP_HL(ip) << 2;
220 		}
221 #ifdef	USE_INET6
222 		else
223 			hlen = sizeof(ip6_t);
224 #endif
225 		/* ipfr_slowtimer(); */
226 		m = &mb;
227 		m->mb_len = i;
228 		i = fr_check(ip, hlen, ifp, dir, &m);
229 		if ((opts & OPT_NAT) == 0)
230 			switch (i)
231 			{
232 			case -4 :
233 				(void)printf("preauth");
234 				break;
235 			case -3 :
236 				(void)printf("account");
237 				break;
238 			case -2 :
239 				(void)printf("auth");
240 				break;
241 			case -1 :
242 				(void)printf("block");
243 				break;
244 			case 0 :
245 				(void)printf("pass");
246 				break;
247 			case 1 :
248 				(void)printf("nomatch");
249 				break;
250 			case 3 :
251 				(void)printf("block return-rst");
252 				break;
253 			case 4 :
254 				(void)printf("block return-icmp");
255 				break;
256 			case 5 :
257 				(void)printf("block return-icmp-as-dest");
258 				break;
259 			default :
260 				(void)printf("recognised return %#x\n", i);
261 				break;
262 			}
263 		if (!use_inet6) {
264 			ip->ip_off = htons(ip->ip_off);
265 			ip->ip_len = htons(ip->ip_len);
266 		}
267 
268 		if (!(opts & OPT_BRIEF)) {
269 			putchar(' ');
270 			printpacket(ip);
271 			printf("--------------");
272 		} else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF))
273 			printpacket(ip);
274 		if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL))
275 #if  defined(__sgi) && (IRIX < 605)
276 			(*ifp->if_output)(ifp, (void *)m, NULL);
277 #else
278 # if TRU64 >= 1885
279 			(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
280 # else
281 			(*ifp->if_output)(ifp, (void *)m, NULL, 0);
282 # endif
283 #endif
284 		if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF))
285 			putchar('\n');
286 		dir = 0;
287 		if (iface != ifname) {
288 			free(iface);
289 			iface = ifname;
290 		}
291 		m = &mb;
292 	}
293 	(*r->r_close)();
294 
295 	if (logout != NULL) {
296 		drain_log(logout);
297 	}
298 
299 	if (dump == 1)  {
300 		dumpnat();
301 		dumpstate();
302 		dumplookups();
303 		dumpgroups();
304 	}
305 
306 	for (i = IPL_LOGMAX; i >= 0; i--)
307 		(void) ipflog_clear(i);
308 
309 	fr_fragunload();
310 	fr_authunload();
311 	fr_stateunload();
312 	fr_natunload();
313 	appr_unload();
314 
315 	i = frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
316 	i += frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE);
317 
318 	ip_lookup_unload();
319 
320 	return 0;
321 }
322 
323 
324 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
325 	(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
326 	defined(__osf__)
327 int ipftestioctl(int dev, ioctlcmd_t cmd, ...)
328 {
329 	caddr_t data;
330 	va_list ap;
331 	int i;
332 
333 	va_start(ap, cmd);
334 	data = va_arg(ap, caddr_t);
335 	va_end(ap);
336 
337 	i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
338 	if (opts & OPT_DEBUG)
339 		fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n",
340 			(u_int)cmd, data, i);
341 	return i;
342 }
343 
344 
345 int ipnattestioctl(int dev, ioctlcmd_t cmd, ...)
346 {
347 	caddr_t data;
348 	va_list ap;
349 	int i;
350 
351 	va_start(ap, cmd);
352 	data = va_arg(ap, caddr_t);
353 	va_end(ap);
354 
355 	i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
356 	if (opts & OPT_DEBUG)
357 		fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n",
358 			(u_int)cmd, data, i);
359 	return i;
360 }
361 
362 
363 int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...)
364 {
365 	caddr_t data;
366 	va_list ap;
367 	int i;
368 
369 	va_start(ap, cmd);
370 	data = va_arg(ap, caddr_t);
371 	va_end(ap);
372 
373 	i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
374 	if ((opts & OPT_DEBUG) || (i != 0))
375 		fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n",
376 			(u_int)cmd, data, i);
377 	return i;
378 }
379 
380 
381 int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...)
382 {
383 	caddr_t data;
384 	va_list ap;
385 	int i;
386 
387 	va_start(ap, cmd);
388 	data = va_arg(ap, caddr_t);
389 	va_end(ap);
390 
391 	i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
392 	if ((opts & OPT_DEBUG) || (i != 0))
393 		fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n",
394 			(u_int)cmd, data, i);
395 	return i;
396 }
397 
398 
399 int ipscantestioctl(int dev, ioctlcmd_t cmd, ...)
400 {
401 	caddr_t data;
402 	va_list ap;
403 	int i;
404 
405 	va_start(ap, cmd);
406 	data = va_arg(ap, caddr_t);
407 	va_end(ap);
408 
409 	i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
410 	if ((opts & OPT_DEBUG) || (i != 0))
411 		fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n",
412 			(u_int)cmd, data, i);
413 	return i;
414 }
415 
416 
417 int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...)
418 {
419 	caddr_t data;
420 	va_list ap;
421 	int i;
422 
423 	va_start(ap, cmd);
424 	data = va_arg(ap, caddr_t);
425 	va_end(ap);
426 
427 	i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
428 	if ((opts & OPT_DEBUG) || (i != 0))
429 		fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n",
430 			(u_int)cmd, data, i);
431 	return i;
432 }
433 
434 
435 int ipooltestioctl(int dev, ioctlcmd_t cmd, ...)
436 {
437 	caddr_t data;
438 	va_list ap;
439 	int i;
440 
441 	va_start(ap, cmd);
442 	data = va_arg(ap, caddr_t);
443 	va_end(ap);
444 
445 	i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
446 	if ((opts & OPT_DEBUG) || (i != 0))
447 		fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n",
448 			(u_int)cmd, data, i);
449 	return i;
450 }
451 #else
452 int ipftestioctl(dev, cmd, data)
453 dev_t dev;
454 ioctlcmd_t cmd;
455 void *data;
456 {
457 	int i;
458 
459 	i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
460 	if ((opts & OPT_DEBUG) || (i != 0))
461 		fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i);
462 	return i;
463 }
464 
465 
466 int ipnattestioctl(dev, cmd, data)
467 dev_t dev;
468 ioctlcmd_t cmd;
469 void *data;
470 {
471 	int i;
472 
473 	i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
474 	if ((opts & OPT_DEBUG) || (i != 0))
475 		fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i);
476 	return i;
477 }
478 
479 
480 int ipstatetestioctl(dev, cmd, data)
481 dev_t dev;
482 ioctlcmd_t cmd;
483 void *data;
484 {
485 	int i;
486 
487 	i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
488 	if ((opts & OPT_DEBUG) || (i != 0))
489 		fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i);
490 	return i;
491 }
492 
493 
494 int ipauthtestioctl(dev, cmd, data)
495 dev_t dev;
496 ioctlcmd_t cmd;
497 void *data;
498 {
499 	int i;
500 
501 	i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
502 	if ((opts & OPT_DEBUG) || (i != 0))
503 		fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i);
504 	return i;
505 }
506 
507 
508 int ipsynctestioctl(dev, cmd, data)
509 dev_t dev;
510 ioctlcmd_t cmd;
511 void *data;
512 {
513 	int i;
514 
515 	i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
516 	if ((opts & OPT_DEBUG) || (i != 0))
517 		fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i);
518 	return i;
519 }
520 
521 
522 int ipscantestioctl(dev, cmd, data)
523 dev_t dev;
524 ioctlcmd_t cmd;
525 void *data;
526 {
527 	int i;
528 
529 	i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
530 	if ((opts & OPT_DEBUG) || (i != 0))
531 		fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i);
532 	return i;
533 }
534 
535 
536 int ipooltestioctl(dev, cmd, data)
537 dev_t dev;
538 ioctlcmd_t cmd;
539 void *data;
540 {
541 	int i;
542 
543 	i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
544 	if (opts & OPT_DEBUG)
545 		fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i);
546 	return i;
547 }
548 #endif
549 
550 
551 int kmemcpy(addr, offset, size)
552 char *addr;
553 long offset;
554 int size;
555 {
556 	bcopy((char *)offset, addr, size);
557 	return 0;
558 }
559 
560 
561 int kstrncpy(buf, pos, n)
562 char *buf;
563 long pos;
564 int n;
565 {
566 	char *ptr;
567 
568 	ptr = (char *)pos;
569 
570 	while ((n-- > 0) && (*buf++ = *ptr++))
571 		;
572 	return 0;
573 }
574 
575 
576 /*
577  * Display the built up NAT table rules and mapping entries.
578  */
579 void dumpnat()
580 {
581 	ipnat_t	*ipn;
582 	nat_t	*nat;
583 
584 	printf("List of active MAP/Redirect filters:\n");
585 	for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next)
586 		printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
587 	printf("\nList of active sessions:\n");
588 	for (nat = nat_instances; nat; nat = nat->nat_next)
589 		printactivenat(nat, opts);
590 }
591 
592 
593 /*
594  * Display the built up state table rules and mapping entries.
595  */
596 void dumpstate()
597 {
598 	ipstate_t *ips;
599 
600 	printf("List of active state sessions:\n");
601 	for (ips = ips_list; ips != NULL; )
602 		ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE));
603 }
604 
605 
606 void dumplookups()
607 {
608 	iphtable_t *iph;
609 	ip_pool_t *ipl;
610 	int i;
611 
612 	printf("List of configured pools\n");
613 	for (i = 0; i < IPL_LOGSIZE; i++)
614 		for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next)
615 			printpool(ipl, bcopywrap, opts);
616 
617 	printf("List of configured hash tables\n");
618 	for (i = 0; i < IPL_LOGSIZE; i++)
619 		for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next)
620 			printhash(iph, bcopywrap, opts);
621 }
622 
623 
624 void dumpgroups()
625 {
626 	frgroup_t *fg;
627 	frentry_t *fr;
628 	int i;
629 
630 	printf("List of groups configured (set 0)\n");
631 	for (i = 0; i < IPL_LOGSIZE; i++)
632 		for (fg =  ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) {
633 			printf("Dev.%d. Group %s Ref %d Flags %#x\n",
634 				i, fg->fg_name, fg->fg_ref, fg->fg_flags);
635 			for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
636 #ifdef	USE_QUAD_T
637 				printf("%qu ",(unsigned long long)fr->fr_hits);
638 #else
639 				printf("%ld ", fr->fr_hits);
640 #endif
641 				printfr(fr, ipftestioctl);
642 			}
643 		}
644 
645 	printf("List of groups configured (set 1)\n");
646 	for (i = 0; i < IPL_LOGSIZE; i++)
647 		for (fg =  ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) {
648 			printf("Dev.%d. Group %s Ref %d Flags %#x\n",
649 				i, fg->fg_name, fg->fg_ref, fg->fg_flags);
650 			for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
651 #ifdef	USE_QUAD_T
652 				printf("%qu ",(unsigned long long)fr->fr_hits);
653 #else
654 				printf("%ld ", fr->fr_hits);
655 #endif
656 				printfr(fr, ipftestioctl);
657 			}
658 		}
659 }
660 
661 
662 void drain_log(filename)
663 char *filename;
664 {
665 	char buffer[DEFAULT_IPFLOGSIZE];
666 	struct iovec iov;
667 	struct uio uio;
668 	size_t resid;
669 	int fd;
670 
671 	fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
672 	if (fd == -1) {
673 		perror("drain_log:open");
674 		return;
675 	}
676 
677 	while (1) {
678 		bzero((char *)&iov, sizeof(iov));
679 		iov.iov_base = buffer;
680 		iov.iov_len = sizeof(buffer);
681 
682 		bzero((char *)&uio, sizeof(uio));
683 		uio.uio_iov = &iov;
684 		uio.uio_iovcnt = 1;
685 		uio.uio_resid = iov.iov_len;
686 		resid = uio.uio_resid;
687 
688 		if (ipflog_read(0, &uio) == 0) {
689 			/*
690 			 * If nothing was read then break out.
691 			 */
692 			if (uio.uio_resid == resid)
693 				break;
694 			write(fd, buffer, resid - uio.uio_resid);
695 		} else
696 			break;
697 	}
698 
699 	close(fd);
700 }
701 
702 
703 void fixv4sums(m, ip)
704 mb_t *m;
705 ip_t *ip;
706 {
707 	u_char *csump, *hdr;
708 
709 	ip->ip_sum = 0;
710 	ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2);
711 
712 	csump = (u_char *)ip;
713 	csump += IP_HL(ip) << 2;
714 
715 	switch (ip->ip_p)
716 	{
717 	case IPPROTO_TCP :
718 		hdr = csump;
719 		csump += offsetof(tcphdr_t, th_sum);
720 		break;
721 	case IPPROTO_UDP :
722 		hdr = csump;
723 		csump += offsetof(udphdr_t, uh_sum);
724 		break;
725 	default :
726 		csump = NULL;
727 		hdr = NULL;
728 		break;
729 	}
730 	if (hdr != NULL) {
731 		*csump = 0;
732 		*(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr);
733 	}
734 }
735