xref: /illumos-gate/usr/src/cmd/ipf/tools/ip_fil.c (revision ab25eeb5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 1993-2001, 2003 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate  *
6*ab25eeb5Syz  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate #if !defined(lint)
13*ab25eeb5Syz static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
14*ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp $";
157c478bd9Sstevel@tonic-gate #endif
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #ifndef	SOLARIS
187c478bd9Sstevel@tonic-gate #define	SOLARIS	(defined(sun) && (defined(__svr4__) || defined(__SVR4)))
197c478bd9Sstevel@tonic-gate #endif
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate #include <sys/param.h>
227c478bd9Sstevel@tonic-gate #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
237c478bd9Sstevel@tonic-gate # if defined(IPFILTER_LKM)
247c478bd9Sstevel@tonic-gate #  ifndef __FreeBSD_cc_version
257c478bd9Sstevel@tonic-gate #   include <osreldate.h>
267c478bd9Sstevel@tonic-gate #  else
277c478bd9Sstevel@tonic-gate #   if __FreeBSD_cc_version < 430000
287c478bd9Sstevel@tonic-gate #    include <osreldate.h>
297c478bd9Sstevel@tonic-gate #   endif
307c478bd9Sstevel@tonic-gate #  endif
317c478bd9Sstevel@tonic-gate # endif
327c478bd9Sstevel@tonic-gate #endif
337c478bd9Sstevel@tonic-gate #include <sys/errno.h>
34*ab25eeb5Syz #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
35*ab25eeb5Syz # include <sys/kern_svcs.h>
36*ab25eeb5Syz #endif
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*ab25eeb5Syz #define _KERNEL
39*ab25eeb5Syz #define KERNEL
40*ab25eeb5Syz #ifdef __OpenBSD__
417c478bd9Sstevel@tonic-gate struct file;
427c478bd9Sstevel@tonic-gate #endif
43*ab25eeb5Syz #include <sys/uio.h>
44*ab25eeb5Syz #undef _KERNEL
45*ab25eeb5Syz #undef KERNEL
467c478bd9Sstevel@tonic-gate #include <sys/file.h>
477c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
487c478bd9Sstevel@tonic-gate #ifdef __sgi
497c478bd9Sstevel@tonic-gate # include <sys/ptimers.h>
507c478bd9Sstevel@tonic-gate #endif
517c478bd9Sstevel@tonic-gate #include <sys/time.h>
527c478bd9Sstevel@tonic-gate #if !SOLARIS
537c478bd9Sstevel@tonic-gate # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
547c478bd9Sstevel@tonic-gate #  include <sys/dirent.h>
557c478bd9Sstevel@tonic-gate # else
567c478bd9Sstevel@tonic-gate #  include <sys/dir.h>
577c478bd9Sstevel@tonic-gate # endif
587c478bd9Sstevel@tonic-gate #else
597c478bd9Sstevel@tonic-gate # include <sys/filio.h>
607c478bd9Sstevel@tonic-gate #endif
61*ab25eeb5Syz #ifndef linux
62*ab25eeb5Syz # include <sys/protosw.h>
63*ab25eeb5Syz #endif
647c478bd9Sstevel@tonic-gate #include <sys/socket.h>
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #include <stdio.h>
677c478bd9Sstevel@tonic-gate #include <string.h>
687c478bd9Sstevel@tonic-gate #include <stdlib.h>
697c478bd9Sstevel@tonic-gate #include <ctype.h>
707c478bd9Sstevel@tonic-gate #include <fcntl.h>
71*ab25eeb5Syz #include <arpa/inet.h>
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #ifdef __hpux
747c478bd9Sstevel@tonic-gate # define _NET_ROUTE_INCLUDED
757c478bd9Sstevel@tonic-gate #endif
767c478bd9Sstevel@tonic-gate #include <net/if.h>
777c478bd9Sstevel@tonic-gate #ifdef sun
787c478bd9Sstevel@tonic-gate # include <net/af.h>
797c478bd9Sstevel@tonic-gate #endif
807c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 300000
817c478bd9Sstevel@tonic-gate # include <net/if_var.h>
827c478bd9Sstevel@tonic-gate #endif
837c478bd9Sstevel@tonic-gate #ifdef __sgi
847c478bd9Sstevel@tonic-gate #include <sys/debug.h>
857c478bd9Sstevel@tonic-gate # ifdef IFF_DRVRLOCK /* IRIX6 */
867c478bd9Sstevel@tonic-gate #include <sys/hashing.h>
877c478bd9Sstevel@tonic-gate # endif
887c478bd9Sstevel@tonic-gate #endif
89*ab25eeb5Syz #if defined(__FreeBSD__)
90*ab25eeb5Syz # include "radix_ipf.h"
91*ab25eeb5Syz #endif
927c478bd9Sstevel@tonic-gate #include <net/route.h>
937c478bd9Sstevel@tonic-gate #include <netinet/in.h>
947c478bd9Sstevel@tonic-gate #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
95*ab25eeb5Syz     !defined(__hpux) && !defined(linux)
967c478bd9Sstevel@tonic-gate # include <netinet/in_var.h>
977c478bd9Sstevel@tonic-gate #endif
987c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
997c478bd9Sstevel@tonic-gate #include <netinet/ip.h>
100*ab25eeb5Syz #if !defined(linux)
101*ab25eeb5Syz # include <netinet/ip_var.h>
102*ab25eeb5Syz #endif
1037c478bd9Sstevel@tonic-gate #include <netinet/tcp.h>
1047c478bd9Sstevel@tonic-gate #if defined(__osf__)
1057c478bd9Sstevel@tonic-gate # include <netinet/tcp_timer.h>
1067c478bd9Sstevel@tonic-gate #endif
107*ab25eeb5Syz #if defined(__osf__) || defined(__hpux) || defined(__sgi)
108*ab25eeb5Syz # include "radix_ipf_local.h"
109*ab25eeb5Syz # define _RADIX_H_
110*ab25eeb5Syz #endif
1117c478bd9Sstevel@tonic-gate #include <netinet/udp.h>
1127c478bd9Sstevel@tonic-gate #include <netinet/tcpip.h>
1137c478bd9Sstevel@tonic-gate #include <netinet/ip_icmp.h>
1147c478bd9Sstevel@tonic-gate #include <unistd.h>
1157c478bd9Sstevel@tonic-gate #include <syslog.h>
1167c478bd9Sstevel@tonic-gate #ifdef __hpux
1177c478bd9Sstevel@tonic-gate # undef _NET_ROUTE_INCLUDED
1187c478bd9Sstevel@tonic-gate #endif
1197c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
1207c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
1217c478bd9Sstevel@tonic-gate #include "netinet/ip_nat.h"
1227c478bd9Sstevel@tonic-gate #include "netinet/ip_frag.h"
1237c478bd9Sstevel@tonic-gate #include "netinet/ip_state.h"
1247c478bd9Sstevel@tonic-gate #include "netinet/ip_proxy.h"
1257c478bd9Sstevel@tonic-gate #include "netinet/ip_auth.h"
1267c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_SYNC
1277c478bd9Sstevel@tonic-gate #include "netinet/ip_sync.h"
1287c478bd9Sstevel@tonic-gate #endif
1297c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_SCAN
1307c478bd9Sstevel@tonic-gate #include "netinet/ip_scan.h"
1317c478bd9Sstevel@tonic-gate #endif
1327c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h"
1337c478bd9Sstevel@tonic-gate #ifdef IPFILTER_COMPILED
1347c478bd9Sstevel@tonic-gate # include "netinet/ip_rules.h"
1357c478bd9Sstevel@tonic-gate #endif
1367c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
1377c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
1387c478bd9Sstevel@tonic-gate #endif
1397c478bd9Sstevel@tonic-gate #ifdef __hpux
1407c478bd9Sstevel@tonic-gate struct rtentry;
1417c478bd9Sstevel@tonic-gate #endif
142*ab25eeb5Syz #include "md5.h"
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate #if !defined(__osf__)
1467c478bd9Sstevel@tonic-gate extern	struct	protosw	inetsw[];
1477c478bd9Sstevel@tonic-gate #endif
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate #include "ipt.h"
1507c478bd9Sstevel@tonic-gate static	struct	ifnet **ifneta = NULL;
1517c478bd9Sstevel@tonic-gate static	int	nifs = 0;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate static	int	frzerostats __P((caddr_t));
154*ab25eeb5Syz static	void	fr_setifpaddr __P((struct ifnet *, char *));
1557c478bd9Sstevel@tonic-gate void	init_ifp __P((void));
156*ab25eeb5Syz #if defined(__sgi) && (IRIX < 60500)
1577c478bd9Sstevel@tonic-gate static int 	no_output __P((struct ifnet *, struct mbuf *,
1587c478bd9Sstevel@tonic-gate 			       struct sockaddr *));
1597c478bd9Sstevel@tonic-gate static int	write_output __P((struct ifnet *, struct mbuf *,
1607c478bd9Sstevel@tonic-gate 				  struct sockaddr *));
1617c478bd9Sstevel@tonic-gate #else
1627c478bd9Sstevel@tonic-gate # if TRU64 >= 1885
1637c478bd9Sstevel@tonic-gate static int 	no_output __P((struct ifnet *, struct mbuf *,
1647c478bd9Sstevel@tonic-gate 			       struct sockaddr *, struct rtentry *, char *));
1657c478bd9Sstevel@tonic-gate static int	write_output __P((struct ifnet *, struct mbuf *,
1667c478bd9Sstevel@tonic-gate 				  struct sockaddr *, struct rtentry *, char *));
1677c478bd9Sstevel@tonic-gate # else
1687c478bd9Sstevel@tonic-gate static int 	no_output __P((struct ifnet *, struct mbuf *,
1697c478bd9Sstevel@tonic-gate 			       struct sockaddr *, struct rtentry *));
1707c478bd9Sstevel@tonic-gate static int	write_output __P((struct ifnet *, struct mbuf *,
1717c478bd9Sstevel@tonic-gate 				  struct sockaddr *, struct rtentry *));
1727c478bd9Sstevel@tonic-gate # endif
1737c478bd9Sstevel@tonic-gate #endif
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate int iplattach()
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate 	fr_running = 1;
1797c478bd9Sstevel@tonic-gate 	return 0;
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate int ipldetach()
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	fr_running = -1;
1867c478bd9Sstevel@tonic-gate 	return 0;
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate static	int	frzerostats(data)
1917c478bd9Sstevel@tonic-gate caddr_t	data;
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	friostat_t fio;
1947c478bd9Sstevel@tonic-gate 	int error;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	fr_getstat(&fio);
1977c478bd9Sstevel@tonic-gate 	error = copyoutptr(&fio, data, sizeof(fio));
1987c478bd9Sstevel@tonic-gate 	if (error)
1997c478bd9Sstevel@tonic-gate 		return EFAULT;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	bzero((char *)frstats, sizeof(*frstats) * 2);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	return 0;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * Filter ioctl interface.
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate int iplioctl(dev, cmd, data, mode)
2117c478bd9Sstevel@tonic-gate int dev;
212*ab25eeb5Syz ioctlcmd_t cmd;
2137c478bd9Sstevel@tonic-gate caddr_t data;
2147c478bd9Sstevel@tonic-gate int mode;
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	int error = 0, unit = 0, tmp;
2177c478bd9Sstevel@tonic-gate 	friostat_t fio;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	unit = dev;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	SPL_NET(s);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	if (unit == IPL_LOGNAT) {
2247c478bd9Sstevel@tonic-gate 		if (fr_running > 0)
2257c478bd9Sstevel@tonic-gate 			error = fr_nat_ioctl(data, cmd, mode);
2267c478bd9Sstevel@tonic-gate 		else
2277c478bd9Sstevel@tonic-gate 			error = EIO;
2287c478bd9Sstevel@tonic-gate 		SPL_X(s);
2297c478bd9Sstevel@tonic-gate 		return error;
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 	if (unit == IPL_LOGSTATE) {
2327c478bd9Sstevel@tonic-gate 		if (fr_running > 0)
2337c478bd9Sstevel@tonic-gate 			error = fr_state_ioctl(data, cmd, mode);
2347c478bd9Sstevel@tonic-gate 		else
2357c478bd9Sstevel@tonic-gate 			error = EIO;
2367c478bd9Sstevel@tonic-gate 		SPL_X(s);
2377c478bd9Sstevel@tonic-gate 		return error;
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 	if (unit == IPL_LOGAUTH) {
2407c478bd9Sstevel@tonic-gate 		if (fr_running > 0) {
241*ab25eeb5Syz 			if ((cmd == (ioctlcmd_t)SIOCADAFR) ||
242*ab25eeb5Syz 			    (cmd == (ioctlcmd_t)SIOCRMAFR)) {
2437c478bd9Sstevel@tonic-gate 				if (!(mode & FWRITE)) {
2447c478bd9Sstevel@tonic-gate 					error = EPERM;
2457c478bd9Sstevel@tonic-gate 				} else {
2467c478bd9Sstevel@tonic-gate 					error = frrequest(unit, cmd, data,
2477c478bd9Sstevel@tonic-gate 							  fr_active, 1);
2487c478bd9Sstevel@tonic-gate 				}
2497c478bd9Sstevel@tonic-gate 			} else {
2507c478bd9Sstevel@tonic-gate 				error = fr_auth_ioctl(data, mode, cmd);
2517c478bd9Sstevel@tonic-gate 			}
2527c478bd9Sstevel@tonic-gate 		} else
2537c478bd9Sstevel@tonic-gate 			error = EIO;
2547c478bd9Sstevel@tonic-gate 		SPL_X(s);
2557c478bd9Sstevel@tonic-gate 		return error;
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 	if (unit == IPL_LOGSYNC) {
2587c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_SYNC
2597c478bd9Sstevel@tonic-gate 		if (fr_running > 0)
2607c478bd9Sstevel@tonic-gate 			error = fr_sync_ioctl(data, cmd, mode);
2617c478bd9Sstevel@tonic-gate 		else
2627c478bd9Sstevel@tonic-gate #endif
2637c478bd9Sstevel@tonic-gate 			error = EIO;
2647c478bd9Sstevel@tonic-gate 		SPL_X(s);
2657c478bd9Sstevel@tonic-gate 		return error;
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 	if (unit == IPL_LOGSCAN) {
2687c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_SCAN
2697c478bd9Sstevel@tonic-gate 		if (fr_running > 0)
2707c478bd9Sstevel@tonic-gate 			error = fr_scan_ioctl(data, cmd, mode);
2717c478bd9Sstevel@tonic-gate 		else
2727c478bd9Sstevel@tonic-gate #endif
2737c478bd9Sstevel@tonic-gate 			error = EIO;
2747c478bd9Sstevel@tonic-gate 		SPL_X(s);
2757c478bd9Sstevel@tonic-gate 		return error;
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 	if (unit == IPL_LOGLOOKUP) {
2787c478bd9Sstevel@tonic-gate 		if (fr_running > 0)
2797c478bd9Sstevel@tonic-gate 			error = ip_lookup_ioctl(data, cmd, mode);
2807c478bd9Sstevel@tonic-gate 		else
2817c478bd9Sstevel@tonic-gate 			error = EIO;
2827c478bd9Sstevel@tonic-gate 		SPL_X(s);
2837c478bd9Sstevel@tonic-gate 		return error;
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	switch (cmd)
2877c478bd9Sstevel@tonic-gate 	{
2887c478bd9Sstevel@tonic-gate 	case FIONREAD :
2897c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOG
2907c478bd9Sstevel@tonic-gate 		error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
2917c478bd9Sstevel@tonic-gate 			       sizeof(iplused[IPL_LOGIPF]));
2927c478bd9Sstevel@tonic-gate #endif
2937c478bd9Sstevel@tonic-gate 		break;
2947c478bd9Sstevel@tonic-gate 	case SIOCFRENB :
2957c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
2967c478bd9Sstevel@tonic-gate 			error = EPERM;
2977c478bd9Sstevel@tonic-gate 		else {
2987c478bd9Sstevel@tonic-gate 			error = COPYIN(data, &tmp, sizeof(tmp));
2997c478bd9Sstevel@tonic-gate 			if (error)
3007c478bd9Sstevel@tonic-gate 				break;
3017c478bd9Sstevel@tonic-gate 			if (tmp)
3027c478bd9Sstevel@tonic-gate 				error = iplattach();
3037c478bd9Sstevel@tonic-gate 			else
3047c478bd9Sstevel@tonic-gate 				error = ipldetach();
3057c478bd9Sstevel@tonic-gate 		}
3067c478bd9Sstevel@tonic-gate 		break;
307*ab25eeb5Syz 	case SIOCIPFSET :
308*ab25eeb5Syz 		if (!(mode & FWRITE)) {
309*ab25eeb5Syz 			error = EPERM;
310*ab25eeb5Syz 			break;
311*ab25eeb5Syz 		}
312*ab25eeb5Syz 	case SIOCIPFGETNEXT :
313*ab25eeb5Syz 	case SIOCIPFGET :
314*ab25eeb5Syz 		error = fr_ipftune(cmd, (void *)data);
315*ab25eeb5Syz 		break;
3167c478bd9Sstevel@tonic-gate 	case SIOCSETFF :
3177c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
3187c478bd9Sstevel@tonic-gate 			error = EPERM;
3197c478bd9Sstevel@tonic-gate 		else
3207c478bd9Sstevel@tonic-gate 			error = COPYIN(data, &fr_flags, sizeof(fr_flags));
3217c478bd9Sstevel@tonic-gate 		break;
3227c478bd9Sstevel@tonic-gate 	case SIOCGETFF :
3237c478bd9Sstevel@tonic-gate 		error = COPYOUT(&fr_flags, data, sizeof(fr_flags));
3247c478bd9Sstevel@tonic-gate 		break;
3257c478bd9Sstevel@tonic-gate 	case SIOCFUNCL :
3267c478bd9Sstevel@tonic-gate 		error = fr_resolvefunc(data);
3277c478bd9Sstevel@tonic-gate 		break;
3287c478bd9Sstevel@tonic-gate 	case SIOCINAFR :
3297c478bd9Sstevel@tonic-gate 	case SIOCRMAFR :
3307c478bd9Sstevel@tonic-gate 	case SIOCADAFR :
3317c478bd9Sstevel@tonic-gate 	case SIOCZRLST :
3327c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
3337c478bd9Sstevel@tonic-gate 			error = EPERM;
3347c478bd9Sstevel@tonic-gate 		else
3357c478bd9Sstevel@tonic-gate 			error = frrequest(unit, cmd, data, fr_active, 1);
3367c478bd9Sstevel@tonic-gate 		break;
3377c478bd9Sstevel@tonic-gate 	case SIOCINIFR :
3387c478bd9Sstevel@tonic-gate 	case SIOCRMIFR :
3397c478bd9Sstevel@tonic-gate 	case SIOCADIFR :
3407c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
3417c478bd9Sstevel@tonic-gate 			error = EPERM;
3427c478bd9Sstevel@tonic-gate 		else
3437c478bd9Sstevel@tonic-gate 			error = frrequest(unit, cmd, data, 1 - fr_active, 1);
3447c478bd9Sstevel@tonic-gate 		break;
3457c478bd9Sstevel@tonic-gate 	case SIOCSWAPA :
3467c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
3477c478bd9Sstevel@tonic-gate 			error = EPERM;
3487c478bd9Sstevel@tonic-gate 		else {
3497c478bd9Sstevel@tonic-gate 			bzero((char *)frcache, sizeof(frcache[0]) * 2);
3507c478bd9Sstevel@tonic-gate 			*(u_int *)data = fr_active;
3517c478bd9Sstevel@tonic-gate 			fr_active = 1 - fr_active;
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 		break;
3547c478bd9Sstevel@tonic-gate 	case SIOCGETFS :
3557c478bd9Sstevel@tonic-gate 		fr_getstat(&fio);
3567c478bd9Sstevel@tonic-gate 		error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
3577c478bd9Sstevel@tonic-gate 		break;
3587c478bd9Sstevel@tonic-gate 	case	SIOCFRZST :
3597c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
3607c478bd9Sstevel@tonic-gate 			error = EPERM;
3617c478bd9Sstevel@tonic-gate 		else
3627c478bd9Sstevel@tonic-gate 			error = frzerostats(data);
3637c478bd9Sstevel@tonic-gate 		break;
3647c478bd9Sstevel@tonic-gate 	case	SIOCIPFFL :
3657c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
3667c478bd9Sstevel@tonic-gate 			error = EPERM;
3677c478bd9Sstevel@tonic-gate 		else {
3687c478bd9Sstevel@tonic-gate 			error = COPYIN(data, &tmp, sizeof(tmp));
3697c478bd9Sstevel@tonic-gate 			if (!error) {
3707663b816Sml 				tmp = frflush(unit, 4, tmp);
3717c478bd9Sstevel@tonic-gate 				error = COPYOUT(&tmp, data, sizeof(tmp));
3727c478bd9Sstevel@tonic-gate 			}
3737c478bd9Sstevel@tonic-gate 		}
3747c478bd9Sstevel@tonic-gate 		break;
3757663b816Sml #ifdef	USE_INET6
3767663b816Sml 	case	SIOCIPFL6 :
3777663b816Sml 		if (!(mode & FWRITE))
3787663b816Sml 			error = EPERM;
3797663b816Sml 		else {
3807663b816Sml 			error = COPYIN(data, &tmp, sizeof(tmp));
3817663b816Sml 			if (!error) {
3827663b816Sml 				tmp = frflush(unit, 6, tmp);
3837663b816Sml 				error = COPYOUT(&tmp, data, sizeof(tmp));
3847663b816Sml 			}
3857663b816Sml 		}
3867663b816Sml 		break;
3877663b816Sml #endif
3887c478bd9Sstevel@tonic-gate 	case SIOCSTLCK :
3897c478bd9Sstevel@tonic-gate 		error = COPYIN(data, &tmp, sizeof(tmp));
3907c478bd9Sstevel@tonic-gate 		if (error == 0) {
3917c478bd9Sstevel@tonic-gate 			fr_state_lock = tmp;
3927c478bd9Sstevel@tonic-gate 			fr_nat_lock = tmp;
3937c478bd9Sstevel@tonic-gate 			fr_frag_lock = tmp;
3947c478bd9Sstevel@tonic-gate 			fr_auth_lock = tmp;
3957c478bd9Sstevel@tonic-gate 		} else
3967c478bd9Sstevel@tonic-gate 			error = EFAULT;
3977c478bd9Sstevel@tonic-gate 		break;
3987c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_LOG
3997c478bd9Sstevel@tonic-gate 	case	SIOCIPFFB :
4007c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
4017c478bd9Sstevel@tonic-gate 			error = EPERM;
4027c478bd9Sstevel@tonic-gate 		else
4037c478bd9Sstevel@tonic-gate 			*(int *)data = ipflog_clear(unit);
4047c478bd9Sstevel@tonic-gate 		break;
4057c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOG */
4067c478bd9Sstevel@tonic-gate 	case SIOCGFRST :
4077c478bd9Sstevel@tonic-gate 		error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
4087c478bd9Sstevel@tonic-gate 		break;
4097c478bd9Sstevel@tonic-gate 	case SIOCFRSYN :
4107c478bd9Sstevel@tonic-gate 		if (!(mode & FWRITE))
4117c478bd9Sstevel@tonic-gate 			error = EPERM;
4127c478bd9Sstevel@tonic-gate 		else {
413*ab25eeb5Syz 			frsync(NULL);
4147c478bd9Sstevel@tonic-gate 		}
4157c478bd9Sstevel@tonic-gate 		break;
4167c478bd9Sstevel@tonic-gate 	default :
4177c478bd9Sstevel@tonic-gate 		error = EINVAL;
4187c478bd9Sstevel@tonic-gate 		break;
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 	SPL_X(s);
4217c478bd9Sstevel@tonic-gate 	return error;
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate void fr_forgetifp(ifp)
4267c478bd9Sstevel@tonic-gate void *ifp;
4277c478bd9Sstevel@tonic-gate {
4287c478bd9Sstevel@tonic-gate 	register frentry_t *f;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	WRITE_ENTER(&ipf_mutex);
4317c478bd9Sstevel@tonic-gate 	for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
4327c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4337c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4347c478bd9Sstevel@tonic-gate 	for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
4357c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4367c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4377c478bd9Sstevel@tonic-gate 	for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
4387c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4397c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4407c478bd9Sstevel@tonic-gate 	for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
4417c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4427c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4437c478bd9Sstevel@tonic-gate #ifdef	USE_INET6
4447c478bd9Sstevel@tonic-gate 	for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
4457c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4467c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4477c478bd9Sstevel@tonic-gate 	for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
4487c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4497c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4507c478bd9Sstevel@tonic-gate 	for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
4517c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4527c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4537c478bd9Sstevel@tonic-gate 	for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
4547c478bd9Sstevel@tonic-gate 		if (f->fr_ifa == ifp)
4557c478bd9Sstevel@tonic-gate 			f->fr_ifa = (void *)-1;
4567c478bd9Sstevel@tonic-gate #endif
4577c478bd9Sstevel@tonic-gate 	RWLOCK_EXIT(&ipf_mutex);
4587c478bd9Sstevel@tonic-gate 	fr_natsync(ifp);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 
462*ab25eeb5Syz void fr_resolvedest(fdp, v)
4637c478bd9Sstevel@tonic-gate frdest_t *fdp;
4647c478bd9Sstevel@tonic-gate int v;
4657c478bd9Sstevel@tonic-gate {
4667c478bd9Sstevel@tonic-gate 	fdp->fd_ifp = NULL;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	if (*fdp->fd_ifname) {
4697c478bd9Sstevel@tonic-gate 		fdp->fd_ifp = GETIFP(fdp->fd_ifname, v);
4707c478bd9Sstevel@tonic-gate 		if (!fdp->fd_ifp)
4717c478bd9Sstevel@tonic-gate 			fdp->fd_ifp = (struct ifnet *)-1;
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 
476*ab25eeb5Syz #if defined(__sgi) && (IRIX < 60500)
4777c478bd9Sstevel@tonic-gate static int no_output(ifp, m, s)
4787c478bd9Sstevel@tonic-gate #else
4797c478bd9Sstevel@tonic-gate # if TRU64 >= 1885
4807c478bd9Sstevel@tonic-gate static int no_output (ifp, m, s, rt, cp)
4817c478bd9Sstevel@tonic-gate char *cp;
4827c478bd9Sstevel@tonic-gate # else
4837c478bd9Sstevel@tonic-gate static int no_output(ifp, m, s, rt)
4847c478bd9Sstevel@tonic-gate # endif
4857c478bd9Sstevel@tonic-gate struct rtentry *rt;
4867c478bd9Sstevel@tonic-gate #endif
4877c478bd9Sstevel@tonic-gate struct ifnet *ifp;
4887c478bd9Sstevel@tonic-gate struct mbuf *m;
4897c478bd9Sstevel@tonic-gate struct sockaddr *s;
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate 	return 0;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 
495*ab25eeb5Syz #if defined(__sgi) && (IRIX < 60500)
4967c478bd9Sstevel@tonic-gate static int write_output(ifp, m, s)
4977c478bd9Sstevel@tonic-gate #else
4987c478bd9Sstevel@tonic-gate # if TRU64 >= 1885
4997c478bd9Sstevel@tonic-gate static int write_output (ifp, m, s, rt, cp)
5007c478bd9Sstevel@tonic-gate char *cp;
5017c478bd9Sstevel@tonic-gate # else
5027c478bd9Sstevel@tonic-gate static int write_output(ifp, m, s, rt)
5037c478bd9Sstevel@tonic-gate # endif
5047c478bd9Sstevel@tonic-gate struct rtentry *rt;
5057c478bd9Sstevel@tonic-gate #endif
5067c478bd9Sstevel@tonic-gate struct ifnet *ifp;
5077c478bd9Sstevel@tonic-gate struct mbuf *m;
5087c478bd9Sstevel@tonic-gate struct sockaddr *s;
5097c478bd9Sstevel@tonic-gate {
5107c478bd9Sstevel@tonic-gate 	char fname[32];
5117c478bd9Sstevel@tonic-gate 	mb_t *mb;
5127c478bd9Sstevel@tonic-gate 	ip_t *ip;
5137c478bd9Sstevel@tonic-gate 	int fd;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	mb = (mb_t *)m;
5167c478bd9Sstevel@tonic-gate 	ip = MTOD(mb, ip_t *);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
519*ab25eeb5Syz     (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
520*ab25eeb5Syz     (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
5217c478bd9Sstevel@tonic-gate 	sprintf(fname, "/tmp/%s", ifp->if_xname);
5227c478bd9Sstevel@tonic-gate #else
5237c478bd9Sstevel@tonic-gate 	sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
5247c478bd9Sstevel@tonic-gate #endif
5257c478bd9Sstevel@tonic-gate 	fd = open(fname, O_WRONLY|O_APPEND);
5267c478bd9Sstevel@tonic-gate 	if (fd == -1) {
5277c478bd9Sstevel@tonic-gate 		perror("open");
5287c478bd9Sstevel@tonic-gate 		return -1;
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate 	write(fd, (char *)ip, ntohs(ip->ip_len));
5317c478bd9Sstevel@tonic-gate 	close(fd);
5327c478bd9Sstevel@tonic-gate 	return 0;
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 
536*ab25eeb5Syz static void fr_setifpaddr(ifp, addr)
537*ab25eeb5Syz struct ifnet *ifp;
538*ab25eeb5Syz char *addr;
539*ab25eeb5Syz {
540*ab25eeb5Syz #ifdef __sgi
541*ab25eeb5Syz 	struct in_ifaddr *ifa;
542*ab25eeb5Syz #else
543*ab25eeb5Syz 	struct ifaddr *ifa;
544*ab25eeb5Syz #endif
545*ab25eeb5Syz 
546*ab25eeb5Syz #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
547*ab25eeb5Syz 	if (ifp->if_addrlist.tqh_first != NULL)
548*ab25eeb5Syz #else
549*ab25eeb5Syz # ifdef __sgi
550*ab25eeb5Syz 	if (ifp->in_ifaddr != NULL)
551*ab25eeb5Syz # else
552*ab25eeb5Syz 	if (ifp->if_addrlist != NULL)
553*ab25eeb5Syz # endif
554*ab25eeb5Syz #endif
555*ab25eeb5Syz 		return;
556*ab25eeb5Syz 
557*ab25eeb5Syz 	ifa = (struct ifaddr *)malloc(sizeof(*ifa));
558*ab25eeb5Syz #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
559*ab25eeb5Syz 	ifp->if_addrlist.tqh_first = ifa;
560*ab25eeb5Syz #else
561*ab25eeb5Syz # ifdef __sgi
562*ab25eeb5Syz 	ifp->in_ifaddr = ifa;
563*ab25eeb5Syz # else
564*ab25eeb5Syz 	ifp->if_addrlist = ifa;
565*ab25eeb5Syz # endif
566*ab25eeb5Syz #endif
567*ab25eeb5Syz 
568*ab25eeb5Syz 	if (ifa != NULL) {
569*ab25eeb5Syz 		struct sockaddr_in *sin;
570*ab25eeb5Syz 
571*ab25eeb5Syz #ifdef __sgi
572*ab25eeb5Syz 		sin = (struct sockaddr_in *)&ifa->ia_addr;
573*ab25eeb5Syz #else
574*ab25eeb5Syz 		sin = (struct sockaddr_in *)&ifa->ifa_addr;
575*ab25eeb5Syz #endif
576*ab25eeb5Syz 		sin->sin_addr.s_addr = inet_addr(addr);
577*ab25eeb5Syz 		if (sin->sin_addr.s_addr == 0)
578*ab25eeb5Syz 			abort();
579*ab25eeb5Syz 	}
580*ab25eeb5Syz }
581*ab25eeb5Syz 
5827c478bd9Sstevel@tonic-gate struct ifnet *get_unit(name, v)
5837c478bd9Sstevel@tonic-gate char *name;
5847c478bd9Sstevel@tonic-gate int v;
5857c478bd9Sstevel@tonic-gate {
586*ab25eeb5Syz 	struct ifnet *ifp, **ifpp, **old_ifneta;
587*ab25eeb5Syz 	char *addr;
5887c478bd9Sstevel@tonic-gate #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
589*ab25eeb5Syz     (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
590*ab25eeb5Syz     (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	if (name == NULL)
5937c478bd9Sstevel@tonic-gate 		name = "anon0";
5947c478bd9Sstevel@tonic-gate 
595*ab25eeb5Syz 	addr = strchr(name, '=');
596*ab25eeb5Syz 	if (addr != NULL)
597*ab25eeb5Syz 		*addr++ = '\0';
598*ab25eeb5Syz 
599*ab25eeb5Syz 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
600*ab25eeb5Syz 		if (!strcmp(name, ifp->if_xname)) {
601*ab25eeb5Syz 			if (addr != NULL)
602*ab25eeb5Syz 				fr_setifpaddr(ifp, addr);
6037c478bd9Sstevel@tonic-gate 			return ifp;
604*ab25eeb5Syz 		}
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate #else
6077c478bd9Sstevel@tonic-gate 	char *s, ifname[LIFNAMSIZ+1];
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	if (name == NULL)
6107c478bd9Sstevel@tonic-gate 		name = "anon0";
6117c478bd9Sstevel@tonic-gate 
612*ab25eeb5Syz 	addr = strchr(name, '=');
613*ab25eeb5Syz 	if (addr != NULL)
614*ab25eeb5Syz 		*addr++ = '\0';
615*ab25eeb5Syz 
616*ab25eeb5Syz 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
6177c478bd9Sstevel@tonic-gate 		COPYIFNAME(ifp, ifname);
618*ab25eeb5Syz 		if (!strcmp(name, ifname)) {
619*ab25eeb5Syz 			if (addr != NULL)
620*ab25eeb5Syz 				fr_setifpaddr(ifp, addr);
6217c478bd9Sstevel@tonic-gate 			return ifp;
622*ab25eeb5Syz 		}
6237c478bd9Sstevel@tonic-gate 	}
6247c478bd9Sstevel@tonic-gate #endif
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	if (!ifneta) {
6277c478bd9Sstevel@tonic-gate 		ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
6287c478bd9Sstevel@tonic-gate 		if (!ifneta)
6297c478bd9Sstevel@tonic-gate 			return NULL;
6307c478bd9Sstevel@tonic-gate 		ifneta[1] = NULL;
6317c478bd9Sstevel@tonic-gate 		ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
6327c478bd9Sstevel@tonic-gate 		if (!ifneta[0]) {
6337c478bd9Sstevel@tonic-gate 			free(ifneta);
6347c478bd9Sstevel@tonic-gate 			return NULL;
6357c478bd9Sstevel@tonic-gate 		}
6367c478bd9Sstevel@tonic-gate 		nifs = 1;
6377c478bd9Sstevel@tonic-gate 	} else {
6387c478bd9Sstevel@tonic-gate 		old_ifneta = ifneta;
6397c478bd9Sstevel@tonic-gate 		nifs++;
6407c478bd9Sstevel@tonic-gate 		ifneta = (struct ifnet **)realloc(ifneta,
641*ab25eeb5Syz 						  (nifs + 1) * sizeof(ifp));
6427c478bd9Sstevel@tonic-gate 		if (!ifneta) {
6437c478bd9Sstevel@tonic-gate 			free(old_ifneta);
6447c478bd9Sstevel@tonic-gate 			nifs = 0;
6457c478bd9Sstevel@tonic-gate 			return NULL;
6467c478bd9Sstevel@tonic-gate 		}
6477c478bd9Sstevel@tonic-gate 		ifneta[nifs] = NULL;
6487c478bd9Sstevel@tonic-gate 		ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
6497c478bd9Sstevel@tonic-gate 		if (!ifneta[nifs - 1]) {
6507c478bd9Sstevel@tonic-gate 			nifs--;
6517c478bd9Sstevel@tonic-gate 			return NULL;
6527c478bd9Sstevel@tonic-gate 		}
6537c478bd9Sstevel@tonic-gate 	}
6547c478bd9Sstevel@tonic-gate 	ifp = ifneta[nifs - 1];
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
657*ab25eeb5Syz     (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
658*ab25eeb5Syz     (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
659*ab25eeb5Syz 	(void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
6607c478bd9Sstevel@tonic-gate #else
661*ab25eeb5Syz 	for (s = name; *s && !ISDIGIT(*s); s++)
6627c478bd9Sstevel@tonic-gate 		;
663*ab25eeb5Syz 	if (*s && ISDIGIT(*s)) {
6647c478bd9Sstevel@tonic-gate 		ifp->if_unit = atoi(s);
6657c478bd9Sstevel@tonic-gate 		ifp->if_name = (char *)malloc(s - name + 1);
6665e985db5Sschuster 		if (ifp->if_name == NULL) {
6675e985db5Sschuster 			/*
6685e985db5Sschuster 			 * XXX do it more elegantly: free up mem,
6695e985db5Sschuster 			 * return NULL
6705e985db5Sschuster 			 */
6715e985db5Sschuster 			perror("malloc");
6725e985db5Sschuster 			exit(1);
6735e985db5Sschuster 		}
674*ab25eeb5Syz 		(void) strncpy(ifp->if_name, name, s - name);
6757c478bd9Sstevel@tonic-gate 		ifp->if_name[s - name] = '\0';
6767c478bd9Sstevel@tonic-gate 	} else {
6777c478bd9Sstevel@tonic-gate 		ifp->if_name = strdup(name);
6787c478bd9Sstevel@tonic-gate 		ifp->if_unit = -1;
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate #endif
6817c478bd9Sstevel@tonic-gate 	ifp->if_output = no_output;
682*ab25eeb5Syz 
683*ab25eeb5Syz 	if (addr != NULL) {
684*ab25eeb5Syz 		fr_setifpaddr(ifp, addr);
685*ab25eeb5Syz 	}
686*ab25eeb5Syz 
6877c478bd9Sstevel@tonic-gate 	return ifp;
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate char *get_ifname(ifp)
6927c478bd9Sstevel@tonic-gate struct ifnet *ifp;
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate 	static char ifname[LIFNAMSIZ];
6957c478bd9Sstevel@tonic-gate 
696*ab25eeb5Syz #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
697*ab25eeb5Syz     (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
6987c478bd9Sstevel@tonic-gate 	sprintf(ifname, "%s", ifp->if_xname);
6997c478bd9Sstevel@tonic-gate #else
7007c478bd9Sstevel@tonic-gate 	sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
7017c478bd9Sstevel@tonic-gate #endif
7027c478bd9Sstevel@tonic-gate 	return ifname;
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate void init_ifp()
7087c478bd9Sstevel@tonic-gate {
709*ab25eeb5Syz 	struct ifnet *ifp, **ifpp;
7107c478bd9Sstevel@tonic-gate 	char fname[32];
7117c478bd9Sstevel@tonic-gate 	int fd;
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
714*ab25eeb5Syz     (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
715*ab25eeb5Syz     (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
716*ab25eeb5Syz 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
7177c478bd9Sstevel@tonic-gate 		ifp->if_output = write_output;
7187c478bd9Sstevel@tonic-gate 		sprintf(fname, "/tmp/%s", ifp->if_xname);
7197c478bd9Sstevel@tonic-gate 		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
7207c478bd9Sstevel@tonic-gate 		if (fd == -1)
7217c478bd9Sstevel@tonic-gate 			perror("open");
7227c478bd9Sstevel@tonic-gate 		else
7237c478bd9Sstevel@tonic-gate 			close(fd);
7247c478bd9Sstevel@tonic-gate 	}
7257c478bd9Sstevel@tonic-gate #else
7267c478bd9Sstevel@tonic-gate 
727*ab25eeb5Syz 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
7287c478bd9Sstevel@tonic-gate 		ifp->if_output = write_output;
7297c478bd9Sstevel@tonic-gate 		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
7307c478bd9Sstevel@tonic-gate 		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
7317c478bd9Sstevel@tonic-gate 		if (fd == -1)
7327c478bd9Sstevel@tonic-gate 			perror("open");
7337c478bd9Sstevel@tonic-gate 		else
7347c478bd9Sstevel@tonic-gate 			close(fd);
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate #endif
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate int fr_fastroute(m, mpp, fin, fdp)
7417c478bd9Sstevel@tonic-gate mb_t *m, **mpp;
7427c478bd9Sstevel@tonic-gate fr_info_t *fin;
7437c478bd9Sstevel@tonic-gate frdest_t *fdp;
7447c478bd9Sstevel@tonic-gate {
7457c478bd9Sstevel@tonic-gate 	struct ifnet *ifp = fdp->fd_ifp;
7467c478bd9Sstevel@tonic-gate 	ip_t *ip = fin->fin_ip;
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	if (!ifp)
7497c478bd9Sstevel@tonic-gate 		return 0;	/* no routing table out here */
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	ip->ip_len = htons((u_short)ip->ip_len);
7527c478bd9Sstevel@tonic-gate 	ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
7537c478bd9Sstevel@tonic-gate 	ip->ip_sum = 0;
754*ab25eeb5Syz #if defined(__sgi) && (IRIX < 60500)
7557c478bd9Sstevel@tonic-gate 	(*ifp->if_output)(ifp, (void *)ip, NULL);
7567c478bd9Sstevel@tonic-gate # if TRU64 >= 1885
7577c478bd9Sstevel@tonic-gate 	(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
7587c478bd9Sstevel@tonic-gate # else
7597c478bd9Sstevel@tonic-gate 	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
7607c478bd9Sstevel@tonic-gate # endif
7617c478bd9Sstevel@tonic-gate #endif
7627c478bd9Sstevel@tonic-gate 	return 0;
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate int fr_send_reset(fin)
7677c478bd9Sstevel@tonic-gate fr_info_t *fin;
7687c478bd9Sstevel@tonic-gate {
7697c478bd9Sstevel@tonic-gate 	verbose("- TCP RST sent\n");
7707c478bd9Sstevel@tonic-gate 	return 0;
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate int fr_send_icmp_err(type, fin, dst)
7757c478bd9Sstevel@tonic-gate int type;
7767c478bd9Sstevel@tonic-gate fr_info_t *fin;
7777c478bd9Sstevel@tonic-gate int dst;
7787c478bd9Sstevel@tonic-gate {
779*ab25eeb5Syz 	verbose("- ICMP unreachable sent\n");
7807c478bd9Sstevel@tonic-gate 	return 0;
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 
784*ab25eeb5Syz void frsync(ifp)
785*ab25eeb5Syz void *ifp;
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate 	return;
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate void m_freem(m)
7927c478bd9Sstevel@tonic-gate mb_t *m;
7937c478bd9Sstevel@tonic-gate {
7947c478bd9Sstevel@tonic-gate 	return;
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate void m_copydata(m, off, len, cp)
7997c478bd9Sstevel@tonic-gate mb_t *m;
8007c478bd9Sstevel@tonic-gate int off, len;
8017c478bd9Sstevel@tonic-gate caddr_t cp;
8027c478bd9Sstevel@tonic-gate {
8037c478bd9Sstevel@tonic-gate 	bcopy((char *)m + off, cp, len);
8047c478bd9Sstevel@tonic-gate }
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate int ipfuiomove(buf, len, rwflag, uio)
8087c478bd9Sstevel@tonic-gate caddr_t buf;
8097c478bd9Sstevel@tonic-gate int len, rwflag;
8107c478bd9Sstevel@tonic-gate struct uio *uio;
8117c478bd9Sstevel@tonic-gate {
8127c478bd9Sstevel@tonic-gate 	int left, ioc, num, offset;
8137c478bd9Sstevel@tonic-gate 	struct iovec *io;
8147c478bd9Sstevel@tonic-gate 	char *start;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	if (rwflag == UIO_READ) {
8177c478bd9Sstevel@tonic-gate 		left = len;
8187c478bd9Sstevel@tonic-gate 		ioc = 0;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 		offset = uio->uio_offset;
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
8237c478bd9Sstevel@tonic-gate 			io = uio->uio_iov + ioc;
8247c478bd9Sstevel@tonic-gate 			num = io->iov_len;
8257c478bd9Sstevel@tonic-gate 			if (num > left)
8267c478bd9Sstevel@tonic-gate 				num = left;
8277c478bd9Sstevel@tonic-gate 			start = (char *)io->iov_base + offset;
8287c478bd9Sstevel@tonic-gate 			if (start > (char *)io->iov_base + io->iov_len) {
8297c478bd9Sstevel@tonic-gate 				offset -= io->iov_len;
8307c478bd9Sstevel@tonic-gate 				ioc++;
8317c478bd9Sstevel@tonic-gate 				continue;
8327c478bd9Sstevel@tonic-gate 			}
8337c478bd9Sstevel@tonic-gate 			bcopy(buf, start, num);
8347c478bd9Sstevel@tonic-gate 			uio->uio_resid -= num;
8357c478bd9Sstevel@tonic-gate 			uio->uio_offset += num;
8367c478bd9Sstevel@tonic-gate 			left -= num;
8377c478bd9Sstevel@tonic-gate 			if (left > 0)
8387c478bd9Sstevel@tonic-gate 				ioc++;
8397c478bd9Sstevel@tonic-gate 		}
8407c478bd9Sstevel@tonic-gate 		if (left > 0)
8417c478bd9Sstevel@tonic-gate 			return EFAULT;
8427c478bd9Sstevel@tonic-gate 	}
8437c478bd9Sstevel@tonic-gate 	return 0;
8447c478bd9Sstevel@tonic-gate }
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate u_32_t fr_newisn(fin)
8487c478bd9Sstevel@tonic-gate fr_info_t *fin;
8497c478bd9Sstevel@tonic-gate {
8507c478bd9Sstevel@tonic-gate 	static int iss_seq_off = 0;
8517c478bd9Sstevel@tonic-gate 	u_char hash[16];
8527c478bd9Sstevel@tonic-gate 	u_32_t newiss;
8537c478bd9Sstevel@tonic-gate 	MD5_CTX ctx;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	/*
8567c478bd9Sstevel@tonic-gate 	 * Compute the base value of the ISS.  It is a hash
8577c478bd9Sstevel@tonic-gate 	 * of (saddr, sport, daddr, dport, secret).
8587c478bd9Sstevel@tonic-gate 	 */
8597c478bd9Sstevel@tonic-gate 	MD5Init(&ctx);
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
8627c478bd9Sstevel@tonic-gate 		  sizeof(fin->fin_fi.fi_src));
8637c478bd9Sstevel@tonic-gate 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
8647c478bd9Sstevel@tonic-gate 		  sizeof(fin->fin_fi.fi_dst));
8657c478bd9Sstevel@tonic-gate 	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	MD5Final(hash, &ctx);
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	memcpy(&newiss, hash, sizeof(newiss));
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 	/*
8747c478bd9Sstevel@tonic-gate 	 * Now increment our "timer", and add it in to
8757c478bd9Sstevel@tonic-gate 	 * the computed value.
8767c478bd9Sstevel@tonic-gate 	 *
8777c478bd9Sstevel@tonic-gate 	 * XXX Use `addin'?
8787c478bd9Sstevel@tonic-gate 	 * XXX TCP_ISSINCR too large to use?
8797c478bd9Sstevel@tonic-gate 	 */
8807c478bd9Sstevel@tonic-gate 	iss_seq_off += 0x00010000;
8817c478bd9Sstevel@tonic-gate 	newiss += iss_seq_off;
8827c478bd9Sstevel@tonic-gate 	return newiss;
8837c478bd9Sstevel@tonic-gate }
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
8877c478bd9Sstevel@tonic-gate /* Function:    fr_nextipid                                                 */
8887c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
8897c478bd9Sstevel@tonic-gate /* Parameters:  fin(I) - pointer to packet information                      */
8907c478bd9Sstevel@tonic-gate /*                                                                          */
8917c478bd9Sstevel@tonic-gate /* Returns the next IPv4 ID to use for this packet.                         */
8927c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
8937c478bd9Sstevel@tonic-gate INLINE u_short fr_nextipid(fin)
8947c478bd9Sstevel@tonic-gate fr_info_t *fin;
8957c478bd9Sstevel@tonic-gate {
8967c478bd9Sstevel@tonic-gate 	static u_short ipid = 0;
8977c478bd9Sstevel@tonic-gate 	u_short id;
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	MUTEX_ENTER(&ipf_rw);
9007c478bd9Sstevel@tonic-gate 	id = ipid++;
9017c478bd9Sstevel@tonic-gate 	MUTEX_EXIT(&ipf_rw);
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	return id;
9047c478bd9Sstevel@tonic-gate }
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate INLINE void fr_checkv4sum(fin)
9087c478bd9Sstevel@tonic-gate fr_info_t *fin;
9097c478bd9Sstevel@tonic-gate {
9107c478bd9Sstevel@tonic-gate 	if (fr_checkl4sum(fin) == -1)
9117c478bd9Sstevel@tonic-gate 		fin->fin_flx |= FI_BAD;
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate #ifdef	USE_INET6
9167c478bd9Sstevel@tonic-gate INLINE void fr_checkv6sum(fin)
9177c478bd9Sstevel@tonic-gate fr_info_t *fin;
9187c478bd9Sstevel@tonic-gate {
9197c478bd9Sstevel@tonic-gate 	if (fr_checkl4sum(fin) == -1)
9207c478bd9Sstevel@tonic-gate 		fin->fin_flx |= FI_BAD;
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate #endif
923*ab25eeb5Syz 
924*ab25eeb5Syz 
925*ab25eeb5Syz /*
926*ab25eeb5Syz  * See above for description, except that all addressing is in user space.
927*ab25eeb5Syz  */
928*ab25eeb5Syz int copyoutptr(src, dst, size)
929*ab25eeb5Syz void *src, *dst;
930*ab25eeb5Syz size_t size;
931*ab25eeb5Syz {
932*ab25eeb5Syz 	caddr_t ca;
933*ab25eeb5Syz 
934*ab25eeb5Syz 	bcopy(dst, (char *)&ca, sizeof(ca));
935*ab25eeb5Syz 	bcopy(src, ca, size);
936*ab25eeb5Syz 	return 0;
937*ab25eeb5Syz }
938*ab25eeb5Syz 
939*ab25eeb5Syz 
940*ab25eeb5Syz /*
941*ab25eeb5Syz  * See above for description, except that all addressing is in user space.
942*ab25eeb5Syz  */
943*ab25eeb5Syz int copyinptr(src, dst, size)
944*ab25eeb5Syz void *src, *dst;
945*ab25eeb5Syz size_t size;
946*ab25eeb5Syz {
947*ab25eeb5Syz 	caddr_t ca;
948*ab25eeb5Syz 
949*ab25eeb5Syz 	bcopy(src, (char *)&ca, sizeof(ca));
950*ab25eeb5Syz 	bcopy(ca, dst, size);
951*ab25eeb5Syz 	return 0;
952*ab25eeb5Syz }
953*ab25eeb5Syz 
954*ab25eeb5Syz 
955*ab25eeb5Syz /*
956*ab25eeb5Syz  * return the first IP Address associated with an interface
957*ab25eeb5Syz  */
958*ab25eeb5Syz int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
959*ab25eeb5Syz int v, atype;
960*ab25eeb5Syz void *ifptr;
961*ab25eeb5Syz struct in_addr *inp, *inpmask;
962*ab25eeb5Syz {
963*ab25eeb5Syz 	struct ifnet *ifp = ifptr;
964*ab25eeb5Syz #ifdef __sgi
965*ab25eeb5Syz 	struct in_ifaddr *ifa;
966*ab25eeb5Syz #else
967*ab25eeb5Syz 	struct ifaddr *ifa;
968*ab25eeb5Syz #endif
969*ab25eeb5Syz 
970*ab25eeb5Syz #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
971*ab25eeb5Syz 	ifa = ifp->if_addrlist.tqh_first;
972*ab25eeb5Syz #else
973*ab25eeb5Syz # ifdef __sgi
974*ab25eeb5Syz 	ifa = (struct in_ifaddr *)ifp->in_ifaddr;
975*ab25eeb5Syz # else
976*ab25eeb5Syz 	ifa = ifp->if_addrlist;
977*ab25eeb5Syz # endif
978*ab25eeb5Syz #endif
979*ab25eeb5Syz 	if (ifa != NULL) {
980*ab25eeb5Syz 		struct sockaddr_in *sin, mask;
981*ab25eeb5Syz 
982*ab25eeb5Syz 		mask.sin_addr.s_addr = 0xffffffff;
983*ab25eeb5Syz 
984*ab25eeb5Syz #ifdef __sgi
985*ab25eeb5Syz 		sin = (struct sockaddr_in *)&ifa->ia_addr;
986*ab25eeb5Syz #else
987*ab25eeb5Syz 		sin = (struct sockaddr_in *)&ifa->ifa_addr;
988*ab25eeb5Syz #endif
989*ab25eeb5Syz 
990*ab25eeb5Syz 		return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
991*ab25eeb5Syz 	}
992*ab25eeb5Syz 	return 0;
993*ab25eeb5Syz }
994