xref: /illumos-gate/usr/src/cmd/ipf/tools/ip_fil.c (revision 7c478bd9)
1 /*
2  * Copyright (C) 1993-2001, 2003 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * Copyright 2003 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 #if !defined(lint)
13 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.121 2003/06/28 17:01:55 darrenr Exp $";
14 #endif
15 
16 #ifndef	SOLARIS
17 #define	SOLARIS	(defined(sun) && (defined(__svr4__) || defined(__SVR4)))
18 #endif
19 
20 #if defined(KERNEL) || defined(_KERNEL)
21 # undef KERNEL
22 # undef _KERNEL
23 # define        KERNEL	1
24 # define        _KERNEL	1
25 #endif
26 #include <sys/param.h>
27 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
28 # if defined(IPFILTER_LKM)
29 #  ifndef __FreeBSD_cc_version
30 #   include <osreldate.h>
31 #  else
32 #   if __FreeBSD_cc_version < 430000
33 #    include <osreldate.h>
34 #   endif
35 #  endif
36 # endif
37 #endif
38 #include <sys/errno.h>
39 #include <sys/types.h>
40 
41 #ifdef _KERNEL
42 #  include <sys/systm.h>
43 #  include <sys/fcntl.h>
44 #else
45 #  define _KERNEL
46 #  ifdef __OpenBSD__
47 struct file;
48 #  endif
49 
50 #  include <sys/uio.h>
51 #  undef _KERNEL
52 #endif
53 
54 #include <sys/file.h>
55 #include <sys/ioctl.h>
56 
57 #include <stdio.h>
58 #include <string.h>
59 #include <stdlib.h>
60 #include <ctype.h>
61 #include <fcntl.h>
62 
63 #ifdef __sgi
64 # include <sys/ptimers.h>
65 #endif
66 #include <sys/time.h>
67 #if !SOLARIS
68 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
69 #  include <sys/dirent.h>
70 # else
71 #  include <sys/dir.h>
72 # endif
73 #else
74 # include <sys/filio.h>
75 #endif
76 #include <sys/protosw.h>
77 #include <sys/socket.h>
78 
79 #include <stdio.h>
80 #include <string.h>
81 #include <stdlib.h>
82 #include <ctype.h>
83 #include <fcntl.h>
84 
85 #ifdef __hpux
86 # define _NET_ROUTE_INCLUDED
87 #endif
88 #include <net/if.h>
89 #ifdef sun
90 # include <net/af.h>
91 #endif
92 #if __FreeBSD_version >= 300000
93 # include <net/if_var.h>
94 #endif
95 #ifdef __sgi
96 #include <sys/debug.h>
97 # ifdef IFF_DRVRLOCK /* IRIX6 */
98 #include <sys/hashing.h>
99 # endif
100 #endif
101 #include <net/route.h>
102 #include <netinet/in.h>
103 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
104     !defined(__hpux)
105 # include <netinet/in_var.h>
106 #endif
107 #include <netinet/in_systm.h>
108 #include <netinet/ip.h>
109 #include <netinet/ip_var.h>
110 #include <netinet/tcp.h>
111 #if defined(__osf__)
112 # include <netinet/tcp_timer.h>
113 #endif
114 #include <netinet/udp.h>
115 #include <netinet/tcpip.h>
116 #include <netinet/ip_icmp.h>
117 #include <unistd.h>
118 #include <syslog.h>
119 #ifdef __hpux
120 # undef _NET_ROUTE_INCLUDED
121 #endif
122 #if SOLARIS2 >= 10
123 #include "ip_compat.h"
124 #include "ip_fil.h"
125 #include "ip_nat.h"
126 #include "ip_frag.h"
127 #include "ip_state.h"
128 #include "ip_proxy.h"
129 #include "ip_auth.h"
130 #else
131 #include "netinet/ip_compat.h"
132 #include "netinet/ip_fil.h"
133 #include "netinet/ip_nat.h"
134 #include "netinet/ip_frag.h"
135 #include "netinet/ip_state.h"
136 #include "netinet/ip_proxy.h"
137 #include "netinet/ip_auth.h"
138 #endif
139 #ifdef	IPFILTER_SYNC
140 #include "netinet/ip_sync.h"
141 #endif
142 #ifdef	IPFILTER_SCAN
143 #include "netinet/ip_scan.h"
144 #endif
145 #if SOLARIS2 >= 10
146 #include "ip_pool.h"
147 #else
148 #include "netinet/ip_pool.h"
149 #endif
150 #ifdef IPFILTER_COMPILED
151 # include "netinet/ip_rules.h"
152 #endif
153 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
154 # include <sys/malloc.h>
155 #endif
156 #ifdef __hpux
157 struct rtentry;
158 #endif
159 
160 #include <sys/md5.h>
161 
162 #if !defined(__osf__)
163 extern	struct	protosw	inetsw[];
164 #endif
165 
166 #include "ipt.h"
167 static	struct	ifnet **ifneta = NULL;
168 static	int	nifs = 0;
169 
170 static	int	frzerostats __P((caddr_t));
171 void	init_ifp __P((void));
172 #if defined(__sgi) && (IRIX < 605)
173 static int 	no_output __P((struct ifnet *, struct mbuf *,
174 			       struct sockaddr *));
175 static int	write_output __P((struct ifnet *, struct mbuf *,
176 				  struct sockaddr *));
177 #else
178 # if TRU64 >= 1885
179 static int 	no_output __P((struct ifnet *, struct mbuf *,
180 			       struct sockaddr *, struct rtentry *, char *));
181 static int	write_output __P((struct ifnet *, struct mbuf *,
182 				  struct sockaddr *, struct rtentry *, char *));
183 # else
184 static int 	no_output __P((struct ifnet *, struct mbuf *,
185 			       struct sockaddr *, struct rtentry *));
186 static int	write_output __P((struct ifnet *, struct mbuf *,
187 				  struct sockaddr *, struct rtentry *));
188 # endif
189 #endif
190 
191 
192 int iplattach()
193 {
194 	fr_running = 1;
195 	return 0;
196 }
197 
198 
199 int ipldetach()
200 {
201 	fr_running = -1;
202 	return 0;
203 }
204 
205 
206 static	int	frzerostats(data)
207 caddr_t	data;
208 {
209 	friostat_t fio;
210 	int error;
211 
212 	fr_getstat(&fio);
213 	error = copyoutptr(&fio, data, sizeof(fio));
214 	if (error)
215 		return EFAULT;
216 
217 	bzero((char *)frstats, sizeof(*frstats) * 2);
218 
219 	return 0;
220 }
221 
222 
223 
224 /*
225  * Filter ioctl interface.
226  */
227 int iplioctl(dev, cmd, data, mode)
228 int dev;
229 #if defined(__NetBSD__) || defined(__OpenBSD__) || \
230 	(_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
231 u_long cmd;
232 #else
233 int cmd;
234 #endif
235 caddr_t data;
236 int mode;
237 {
238 	int error = 0, unit = 0, tmp;
239 	friostat_t fio;
240 
241 	unit = dev;
242 
243 	SPL_NET(s);
244 
245 	if (unit == IPL_LOGNAT) {
246 		if (fr_running > 0)
247 			error = fr_nat_ioctl(data, cmd, mode);
248 		else
249 			error = EIO;
250 		SPL_X(s);
251 		return error;
252 	}
253 	if (unit == IPL_LOGSTATE) {
254 		if (fr_running > 0)
255 			error = fr_state_ioctl(data, cmd, mode);
256 		else
257 			error = EIO;
258 		SPL_X(s);
259 		return error;
260 	}
261 	if (unit == IPL_LOGAUTH) {
262 		if (fr_running > 0) {
263 			if ((cmd == SIOCADAFR) || (cmd == SIOCRMAFR)) {
264 				if (!(mode & FWRITE)) {
265 					error = EPERM;
266 				} else {
267 					error = frrequest(unit, cmd, data,
268 							  fr_active, 1);
269 				}
270 			} else {
271 				error = fr_auth_ioctl(data, mode, cmd);
272 			}
273 		} else
274 			error = EIO;
275 		SPL_X(s);
276 		return error;
277 	}
278 	if (unit == IPL_LOGSYNC) {
279 #ifdef	IPFILTER_SYNC
280 		if (fr_running > 0)
281 			error = fr_sync_ioctl(data, cmd, mode);
282 		else
283 #endif
284 			error = EIO;
285 		SPL_X(s);
286 		return error;
287 	}
288 	if (unit == IPL_LOGSCAN) {
289 #ifdef	IPFILTER_SCAN
290 		if (fr_running > 0)
291 			error = fr_scan_ioctl(data, cmd, mode);
292 		else
293 #endif
294 			error = EIO;
295 		SPL_X(s);
296 		return error;
297 	}
298 	if (unit == IPL_LOGLOOKUP) {
299 		if (fr_running > 0)
300 			error = ip_lookup_ioctl(data, cmd, mode);
301 		else
302 			error = EIO;
303 		SPL_X(s);
304 		return error;
305 	}
306 
307 	switch (cmd)
308 	{
309 	case FIONREAD :
310 #ifdef IPFILTER_LOG
311 		error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
312 			       sizeof(iplused[IPL_LOGIPF]));
313 #endif
314 		break;
315 	case SIOCFRENB :
316 		if (!(mode & FWRITE))
317 			error = EPERM;
318 		else {
319 			error = COPYIN(data, &tmp, sizeof(tmp));
320 			if (error)
321 				break;
322 			if (tmp)
323 				error = iplattach();
324 			else
325 				error = ipldetach();
326 		}
327 		break;
328 	case SIOCSETFF :
329 		if (!(mode & FWRITE))
330 			error = EPERM;
331 		else
332 			error = COPYIN(data, &fr_flags, sizeof(fr_flags));
333 		break;
334 	case SIOCGETFF :
335 		error = COPYOUT(&fr_flags, data, sizeof(fr_flags));
336 		break;
337 	case SIOCFUNCL :
338 		error = fr_resolvefunc(data);
339 		break;
340 	case SIOCINAFR :
341 	case SIOCRMAFR :
342 	case SIOCADAFR :
343 	case SIOCZRLST :
344 		if (!(mode & FWRITE))
345 			error = EPERM;
346 		else
347 			error = frrequest(unit, cmd, data, fr_active, 1);
348 		break;
349 	case SIOCINIFR :
350 	case SIOCRMIFR :
351 	case SIOCADIFR :
352 		if (!(mode & FWRITE))
353 			error = EPERM;
354 		else
355 			error = frrequest(unit, cmd, data, 1 - fr_active, 1);
356 		break;
357 	case SIOCSWAPA :
358 		if (!(mode & FWRITE))
359 			error = EPERM;
360 		else {
361 			bzero((char *)frcache, sizeof(frcache[0]) * 2);
362 			*(u_int *)data = fr_active;
363 			fr_active = 1 - fr_active;
364 		}
365 		break;
366 	case SIOCGETFS :
367 		fr_getstat(&fio);
368 		error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
369 		break;
370 	case	SIOCFRZST :
371 		if (!(mode & FWRITE))
372 			error = EPERM;
373 		else
374 			error = frzerostats(data);
375 		break;
376 	case	SIOCIPFFL :
377 		if (!(mode & FWRITE))
378 			error = EPERM;
379 		else {
380 			error = COPYIN(data, &tmp, sizeof(tmp));
381 			if (!error) {
382 				tmp = frflush(unit, tmp);
383 				error = COPYOUT(&tmp, data, sizeof(tmp));
384 			}
385 		}
386 		break;
387 	case SIOCSTLCK :
388 		error = COPYIN(data, &tmp, sizeof(tmp));
389 		if (error == 0) {
390 			fr_state_lock = tmp;
391 			fr_nat_lock = tmp;
392 			fr_frag_lock = tmp;
393 			fr_auth_lock = tmp;
394 		} else
395 			error = EFAULT;
396 		break;
397 #ifdef	IPFILTER_LOG
398 	case	SIOCIPFFB :
399 		if (!(mode & FWRITE))
400 			error = EPERM;
401 		else
402 			*(int *)data = ipflog_clear(unit);
403 		break;
404 #endif /* IPFILTER_LOG */
405 	case SIOCGFRST :
406 		error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
407 		break;
408 	case SIOCFRSYN :
409 		if (!(mode & FWRITE))
410 			error = EPERM;
411 		else {
412 			frsync();
413 		}
414 		break;
415 	default :
416 		error = EINVAL;
417 		break;
418 	}
419 	SPL_X(s);
420 	return error;
421 }
422 
423 
424 void fr_forgetifp(ifp)
425 void *ifp;
426 {
427 	register frentry_t *f;
428 
429 	WRITE_ENTER(&ipf_mutex);
430 	for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
431 		if (f->fr_ifa == ifp)
432 			f->fr_ifa = (void *)-1;
433 	for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
434 		if (f->fr_ifa == ifp)
435 			f->fr_ifa = (void *)-1;
436 	for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
437 		if (f->fr_ifa == ifp)
438 			f->fr_ifa = (void *)-1;
439 	for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
440 		if (f->fr_ifa == ifp)
441 			f->fr_ifa = (void *)-1;
442 #ifdef	USE_INET6
443 	for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
444 		if (f->fr_ifa == ifp)
445 			f->fr_ifa = (void *)-1;
446 	for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
447 		if (f->fr_ifa == ifp)
448 			f->fr_ifa = (void *)-1;
449 	for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
450 		if (f->fr_ifa == ifp)
451 			f->fr_ifa = (void *)-1;
452 	for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
453 		if (f->fr_ifa == ifp)
454 			f->fr_ifa = (void *)-1;
455 #endif
456 	RWLOCK_EXIT(&ipf_mutex);
457 	fr_natsync(ifp);
458 }
459 
460 
461 void fr_resolvdest(fdp, v)
462 frdest_t *fdp;
463 int v;
464 {
465 	fdp->fd_ifp = NULL;
466 
467 	if (*fdp->fd_ifname) {
468 		fdp->fd_ifp = GETIFP(fdp->fd_ifname, v);
469 		if (!fdp->fd_ifp)
470 			fdp->fd_ifp = (struct ifnet *)-1;
471 	}
472 }
473 
474 
475 #if defined(__sgi) && (IRIX < 605)
476 static int no_output(ifp, m, s)
477 #else
478 # if TRU64 >= 1885
479 static int no_output (ifp, m, s, rt, cp)
480 char *cp;
481 # else
482 static int no_output(ifp, m, s, rt)
483 # endif
484 struct rtentry *rt;
485 #endif
486 struct ifnet *ifp;
487 struct mbuf *m;
488 struct sockaddr *s;
489 {
490 	return 0;
491 }
492 
493 
494 #if defined(__sgi) && (IRIX < 605)
495 static int write_output(ifp, m, s)
496 #else
497 # if TRU64 >= 1885
498 static int write_output (ifp, m, s, rt, cp)
499 char *cp;
500 # else
501 static int write_output(ifp, m, s, rt)
502 # endif
503 struct rtentry *rt;
504 #endif
505 struct ifnet *ifp;
506 struct mbuf *m;
507 struct sockaddr *s;
508 {
509 	char fname[32];
510 	mb_t *mb;
511 	ip_t *ip;
512 	int fd;
513 
514 	mb = (mb_t *)m;
515 	ip = MTOD(mb, ip_t *);
516 
517 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
518 	(defined(OpenBSD) && (OpenBSD >= 199603))
519 	sprintf(fname, "/tmp/%s", ifp->if_xname);
520 #else
521 	sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
522 #endif
523 	fd = open(fname, O_WRONLY|O_APPEND);
524 	if (fd == -1) {
525 		perror("open");
526 		return -1;
527 	}
528 	write(fd, (char *)ip, ntohs(ip->ip_len));
529 	close(fd);
530 	return 0;
531 }
532 
533 
534 struct ifnet *get_unit(name, v)
535 char *name;
536 int v;
537 {
538 	struct ifnet *ifp, **ifa, **old_ifneta;
539 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
540 	(defined(OpenBSD) && (OpenBSD >= 199603))
541 
542 	if (name == NULL)
543 		name = "anon0";
544 
545 	for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
546 		if (!strcmp(name, ifp->if_xname))
547 			return ifp;
548 	}
549 #else
550 	char *s, ifname[LIFNAMSIZ+1];
551 
552 	if (name == NULL)
553 		name = "anon0";
554 
555 	for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
556 		COPYIFNAME(ifp, ifname);
557 		if (!strcmp(name, ifname))
558 			return ifp;
559 	}
560 #endif
561 
562 	if (!ifneta) {
563 		ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
564 		if (!ifneta)
565 			return NULL;
566 		ifneta[1] = NULL;
567 		ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
568 		if (!ifneta[0]) {
569 			free(ifneta);
570 			return NULL;
571 		}
572 		nifs = 1;
573 	} else {
574 		old_ifneta = ifneta;
575 		nifs++;
576 		ifneta = (struct ifnet **)realloc(ifneta,
577 						  (nifs + 1) * sizeof(*ifa));
578 		if (!ifneta) {
579 			free(old_ifneta);
580 			nifs = 0;
581 			return NULL;
582 		}
583 		ifneta[nifs] = NULL;
584 		ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
585 		if (!ifneta[nifs - 1]) {
586 			nifs--;
587 			return NULL;
588 		}
589 	}
590 	ifp = ifneta[nifs - 1];
591 
592 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
593 	(defined(OpenBSD) && (OpenBSD >= 199603))
594 	strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
595 #else
596 	for (s = name; *s && !isdigit(*s); s++)
597 		;
598 	if (*s && isdigit(*s)) {
599 		ifp->if_unit = atoi(s);
600 		ifp->if_name = (char *)malloc(s - name + 1);
601 		strncpy(ifp->if_name, name, s - name);
602 		ifp->if_name[s - name] = '\0';
603 	} else {
604 		ifp->if_name = strdup(name);
605 		ifp->if_unit = -1;
606 	}
607 #endif
608 	ifp->if_output = no_output;
609 	return ifp;
610 }
611 
612 
613 char *get_ifname(ifp)
614 struct ifnet *ifp;
615 {
616 	static char ifname[LIFNAMSIZ];
617 
618 #if defined(__OpenBSD__) || defined(__NetBSD__)
619 	sprintf(ifname, "%s", ifp->if_xname);
620 #else
621 	sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
622 #endif
623 	return ifname;
624 }
625 
626 
627 
628 void init_ifp()
629 {
630 	struct ifnet *ifp, **ifa;
631 	char fname[32];
632 	int fd;
633 
634 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
635 	(defined(OpenBSD) && (OpenBSD >= 199603))
636 	for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
637 		ifp->if_output = write_output;
638 		sprintf(fname, "/tmp/%s", ifp->if_xname);
639 		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
640 		if (fd == -1)
641 			perror("open");
642 		else
643 			close(fd);
644 	}
645 #else
646 
647 	for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
648 		ifp->if_output = write_output;
649 		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
650 		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
651 		if (fd == -1)
652 			perror("open");
653 		else
654 			close(fd);
655 	}
656 #endif
657 }
658 
659 
660 int fr_fastroute(m, mpp, fin, fdp)
661 mb_t *m, **mpp;
662 fr_info_t *fin;
663 frdest_t *fdp;
664 {
665 	struct ifnet *ifp = fdp->fd_ifp;
666 	ip_t *ip = fin->fin_ip;
667 
668 	if (!ifp)
669 		return 0;	/* no routing table out here */
670 
671 	ip->ip_len = htons((u_short)ip->ip_len);
672 	ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
673 	ip->ip_sum = 0;
674 #if defined(__sgi) && (IRIX < 605)
675 	(*ifp->if_output)(ifp, (void *)ip, NULL);
676 # if TRU64 >= 1885
677 	(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
678 # else
679 	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
680 # endif
681 #endif
682 	return 0;
683 }
684 
685 
686 int fr_send_reset(fin)
687 fr_info_t *fin;
688 {
689 	verbose("- TCP RST sent\n");
690 	return 0;
691 }
692 
693 
694 int fr_send_icmp_err(type, fin, dst)
695 int type;
696 fr_info_t *fin;
697 int dst;
698 {
699 	verbose("- TCP RST sent\n");
700 	return 0;
701 }
702 
703 
704 void frsync()
705 {
706 	return;
707 }
708 
709 
710 void m_freem(m)
711 mb_t *m;
712 {
713 	return;
714 }
715 
716 
717 void m_copydata(m, off, len, cp)
718 mb_t *m;
719 int off, len;
720 caddr_t cp;
721 {
722 	bcopy((char *)m + off, cp, len);
723 }
724 
725 
726 int ipfuiomove(buf, len, rwflag, uio)
727 caddr_t buf;
728 int len, rwflag;
729 struct uio *uio;
730 {
731 	int left, ioc, num, offset;
732 	struct iovec *io;
733 	char *start;
734 
735 	if (rwflag == UIO_READ) {
736 		left = len;
737 		ioc = 0;
738 
739 		offset = uio->uio_offset;
740 
741 		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
742 			io = uio->uio_iov + ioc;
743 			num = io->iov_len;
744 			if (num > left)
745 				num = left;
746 			start = (char *)io->iov_base + offset;
747 			if (start > (char *)io->iov_base + io->iov_len) {
748 				offset -= io->iov_len;
749 				ioc++;
750 				continue;
751 			}
752 			bcopy(buf, start, num);
753 			uio->uio_resid -= num;
754 			uio->uio_offset += num;
755 			left -= num;
756 			if (left > 0)
757 				ioc++;
758 		}
759 		if (left > 0)
760 			return EFAULT;
761 	}
762 	return 0;
763 }
764 
765 
766 u_32_t fr_newisn(fin)
767 fr_info_t *fin;
768 {
769 	static int iss_seq_off = 0;
770 	u_char hash[16];
771 	u_32_t newiss;
772 	MD5_CTX ctx;
773 
774 	/*
775 	 * Compute the base value of the ISS.  It is a hash
776 	 * of (saddr, sport, daddr, dport, secret).
777 	 */
778 	MD5Init(&ctx);
779 
780 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
781 		  sizeof(fin->fin_fi.fi_src));
782 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
783 		  sizeof(fin->fin_fi.fi_dst));
784 	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
785 
786 	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
787 
788 	MD5Final(hash, &ctx);
789 
790 	memcpy(&newiss, hash, sizeof(newiss));
791 
792 	/*
793 	 * Now increment our "timer", and add it in to
794 	 * the computed value.
795 	 *
796 	 * XXX Use `addin'?
797 	 * XXX TCP_ISSINCR too large to use?
798 	 */
799 	iss_seq_off += 0x00010000;
800 	newiss += iss_seq_off;
801 	return newiss;
802 }
803 
804 
805 /* ------------------------------------------------------------------------ */
806 /* Function:    fr_nextipid                                                 */
807 /* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
808 /* Parameters:  fin(I) - pointer to packet information                      */
809 /*                                                                          */
810 /* Returns the next IPv4 ID to use for this packet.                         */
811 /* ------------------------------------------------------------------------ */
812 INLINE u_short fr_nextipid(fin)
813 fr_info_t *fin;
814 {
815 	static u_short ipid = 0;
816 	u_short id;
817 
818 	MUTEX_ENTER(&ipf_rw);
819 	id = ipid++;
820 	MUTEX_EXIT(&ipf_rw);
821 
822 	return id;
823 }
824 
825 
826 INLINE void fr_checkv4sum(fin)
827 fr_info_t *fin;
828 {
829 	if (fr_checkl4sum(fin) == -1)
830 		fin->fin_flx |= FI_BAD;
831 }
832 
833 
834 #ifdef	USE_INET6
835 INLINE void fr_checkv6sum(fin)
836 fr_info_t *fin;
837 {
838 	if (fr_checkl4sum(fin) == -1)
839 		fin->fin_flx |= FI_BAD;
840 }
841 #endif
842