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