xref: /onnv-gate/usr/src/cmd/ipf/tools/ipfs.c (revision 2393:76e0289ce525)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Copyright (C) 1999-2001, 2003 by Darren Reed.
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
50Sstevel@tonic-gate  *
6*2393Syz155240  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
70Sstevel@tonic-gate  * Use is subject to license terms.
80Sstevel@tonic-gate  */
90Sstevel@tonic-gate 
100Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
110Sstevel@tonic-gate 
120Sstevel@tonic-gate #ifdef	__FreeBSD__
130Sstevel@tonic-gate # ifndef __FreeBSD_cc_version
140Sstevel@tonic-gate #  include <osreldate.h>
150Sstevel@tonic-gate # else
160Sstevel@tonic-gate #  if __FreeBSD_cc_version < 430000
170Sstevel@tonic-gate #   include <osreldate.h>
180Sstevel@tonic-gate #  endif
190Sstevel@tonic-gate # endif
200Sstevel@tonic-gate #endif
210Sstevel@tonic-gate #include <stdio.h>
220Sstevel@tonic-gate #include <unistd.h>
230Sstevel@tonic-gate #include <string.h>
240Sstevel@tonic-gate #include <fcntl.h>
250Sstevel@tonic-gate #include <errno.h>
260Sstevel@tonic-gate #if !defined(__SVR4) && !defined(__GNUC__)
270Sstevel@tonic-gate #include <strings.h>
280Sstevel@tonic-gate #endif
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/param.h>
310Sstevel@tonic-gate #include <sys/file.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <stddef.h>
340Sstevel@tonic-gate #include <sys/socket.h>
350Sstevel@tonic-gate #include <sys/ioctl.h>
360Sstevel@tonic-gate #include <netinet/in.h>
370Sstevel@tonic-gate #include <netinet/in_systm.h>
380Sstevel@tonic-gate #include <sys/time.h>
390Sstevel@tonic-gate #include <net/if.h>
400Sstevel@tonic-gate #if __FreeBSD_version >= 300000
410Sstevel@tonic-gate # include <net/if_var.h>
420Sstevel@tonic-gate #endif
430Sstevel@tonic-gate #include <netinet/ip.h>
440Sstevel@tonic-gate #include <netdb.h>
450Sstevel@tonic-gate #include <arpa/nameser.h>
460Sstevel@tonic-gate #include <resolv.h>
470Sstevel@tonic-gate #include "ipf.h"
48*2393Syz155240 #include "netinet/ipl.h"
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #if !defined(lint)
51*2393Syz155240 static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp";
520Sstevel@tonic-gate #endif
530Sstevel@tonic-gate 
540Sstevel@tonic-gate #ifndef	IPF_SAVEDIR
550Sstevel@tonic-gate # define	IPF_SAVEDIR	"/var/db/ipf"
560Sstevel@tonic-gate #endif
570Sstevel@tonic-gate #ifndef IPF_NATFILE
580Sstevel@tonic-gate # define	IPF_NATFILE	"ipnat.ipf"
590Sstevel@tonic-gate #endif
600Sstevel@tonic-gate #ifndef IPF_STATEFILE
610Sstevel@tonic-gate # define	IPF_STATEFILE	"ipstate.ipf"
620Sstevel@tonic-gate #endif
630Sstevel@tonic-gate 
640Sstevel@tonic-gate #if !defined(__SVR4) && defined(__GNUC__)
650Sstevel@tonic-gate extern	char	*index __P((const char *, int));
660Sstevel@tonic-gate #endif
670Sstevel@tonic-gate 
680Sstevel@tonic-gate extern	char	*optarg;
690Sstevel@tonic-gate extern	int	optind;
700Sstevel@tonic-gate 
710Sstevel@tonic-gate int	main __P((int, char *[]));
720Sstevel@tonic-gate void	usage __P((void));
730Sstevel@tonic-gate int	changestateif __P((char *, char *));
740Sstevel@tonic-gate int	changenatif __P((char *, char *));
750Sstevel@tonic-gate int	readstate __P((int, char *));
760Sstevel@tonic-gate int	readnat __P((int, char *));
770Sstevel@tonic-gate int	writestate __P((int, char *));
780Sstevel@tonic-gate int	opendevice __P((char *));
790Sstevel@tonic-gate void	closedevice __P((int));
800Sstevel@tonic-gate int	setlock __P((int, int));
810Sstevel@tonic-gate int	writeall __P((char *));
820Sstevel@tonic-gate int	readall __P((char *));
830Sstevel@tonic-gate int	writenat __P((int, char *));
840Sstevel@tonic-gate 
850Sstevel@tonic-gate int	opts = 0;
860Sstevel@tonic-gate char	*progname;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 
890Sstevel@tonic-gate void usage()
900Sstevel@tonic-gate {
910Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nv] -l\n", progname);
920Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nv] -u\n", progname);
930Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nv] [-d <dir>] -R\n", progname);
940Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nv] [-d <dir>] -W\n", progname);
950Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nNSv] [-f <file>] -r\n", progname);
960Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nNSv] [-f <file>] -w\n", progname);
970Sstevel@tonic-gate 	fprintf(stderr, "usage: %s [-nNSv] -f <filename> -i <if1>,<if2>\n",
980Sstevel@tonic-gate 		progname);
990Sstevel@tonic-gate 	exit(1);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate /*
1040Sstevel@tonic-gate  * Change interface names in state information saved out to disk.
1050Sstevel@tonic-gate  */
1060Sstevel@tonic-gate int changestateif(ifs, fname)
1070Sstevel@tonic-gate char *ifs, *fname;
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate 	int fd, olen, nlen, rw;
1100Sstevel@tonic-gate 	ipstate_save_t ips;
1110Sstevel@tonic-gate 	off_t pos;
1120Sstevel@tonic-gate 	char *s;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	s = strchr(ifs, ',');
1150Sstevel@tonic-gate 	if (!s)
1160Sstevel@tonic-gate 		usage();
1170Sstevel@tonic-gate 	*s++ = '\0';
1180Sstevel@tonic-gate 	nlen = strlen(s);
1190Sstevel@tonic-gate 	olen = strlen(ifs);
1200Sstevel@tonic-gate 	if (nlen >= sizeof(ips.ips_is.is_ifname) ||
1210Sstevel@tonic-gate 	    olen >= sizeof(ips.ips_is.is_ifname))
1220Sstevel@tonic-gate 		usage();
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	fd = open(fname, O_RDWR);
1250Sstevel@tonic-gate 	if (fd == -1) {
1260Sstevel@tonic-gate 		perror("open");
1270Sstevel@tonic-gate 		exit(1);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	for (pos = 0; read(fd, &ips, sizeof(ips)) == sizeof(ips); ) {
1310Sstevel@tonic-gate 		rw = 0;
1320Sstevel@tonic-gate 		if (!strncmp(ips.ips_is.is_ifname[0], ifs, olen + 1)) {
1330Sstevel@tonic-gate 			strcpy(ips.ips_is.is_ifname[0], s);
1340Sstevel@tonic-gate 			rw = 1;
1350Sstevel@tonic-gate 		}
1360Sstevel@tonic-gate 		if (!strncmp(ips.ips_is.is_ifname[1], ifs, olen + 1)) {
1370Sstevel@tonic-gate 			strcpy(ips.ips_is.is_ifname[1], s);
1380Sstevel@tonic-gate 			rw = 1;
1390Sstevel@tonic-gate 		}
1400Sstevel@tonic-gate 		if (rw == 1) {
1410Sstevel@tonic-gate 			if (lseek(fd, pos, SEEK_SET) != pos) {
1420Sstevel@tonic-gate 				perror("lseek");
1430Sstevel@tonic-gate 				exit(1);
1440Sstevel@tonic-gate 			}
1450Sstevel@tonic-gate 			if (write(fd, &ips, sizeof(ips)) != sizeof(ips)) {
1460Sstevel@tonic-gate 				perror("write");
1470Sstevel@tonic-gate 				exit(1);
1480Sstevel@tonic-gate 			}
1490Sstevel@tonic-gate 		}
1500Sstevel@tonic-gate 		pos = lseek(fd, 0, SEEK_CUR);
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 	close(fd);
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	return 0;
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate /*
1590Sstevel@tonic-gate  * Change interface names in NAT information saved out to disk.
1600Sstevel@tonic-gate  */
1610Sstevel@tonic-gate int changenatif(ifs, fname)
1620Sstevel@tonic-gate char *ifs, *fname;
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate 	int fd, olen, nlen, rw;
1650Sstevel@tonic-gate 	nat_save_t ipn;
1660Sstevel@tonic-gate 	nat_t *nat;
1670Sstevel@tonic-gate 	off_t pos;
1680Sstevel@tonic-gate 	char *s;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	s = strchr(ifs, ',');
1710Sstevel@tonic-gate 	if (!s)
1720Sstevel@tonic-gate 		usage();
1730Sstevel@tonic-gate 	*s++ = '\0';
1740Sstevel@tonic-gate 	nlen = strlen(s);
1750Sstevel@tonic-gate 	olen = strlen(ifs);
1760Sstevel@tonic-gate 	nat = &ipn.ipn_nat;
1770Sstevel@tonic-gate 	if (nlen >= sizeof(nat->nat_ifnames[0]) ||
1780Sstevel@tonic-gate 	    olen >= sizeof(nat->nat_ifnames[0]))
1790Sstevel@tonic-gate 		usage();
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	fd = open(fname, O_RDWR);
1820Sstevel@tonic-gate 	if (fd == -1) {
1830Sstevel@tonic-gate 		perror("open");
1840Sstevel@tonic-gate 		exit(1);
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	for (pos = 0; read(fd, &ipn, sizeof(ipn)) == sizeof(ipn); ) {
1880Sstevel@tonic-gate 		rw = 0;
1890Sstevel@tonic-gate 		if (!strncmp(nat->nat_ifnames[0], ifs, olen + 1)) {
1900Sstevel@tonic-gate 			strcpy(nat->nat_ifnames[0], s);
1910Sstevel@tonic-gate 			rw = 1;
1920Sstevel@tonic-gate 		}
1930Sstevel@tonic-gate 		if (!strncmp(nat->nat_ifnames[1], ifs, olen + 1)) {
1940Sstevel@tonic-gate 			strcpy(nat->nat_ifnames[1], s);
1950Sstevel@tonic-gate 			rw = 1;
1960Sstevel@tonic-gate 		}
1970Sstevel@tonic-gate 		if (rw == 1) {
1980Sstevel@tonic-gate 			if (lseek(fd, pos, SEEK_SET) != pos) {
1990Sstevel@tonic-gate 				perror("lseek");
2000Sstevel@tonic-gate 				exit(1);
2010Sstevel@tonic-gate 			}
2020Sstevel@tonic-gate 			if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) {
2030Sstevel@tonic-gate 				perror("write");
2040Sstevel@tonic-gate 				exit(1);
2050Sstevel@tonic-gate 			}
2060Sstevel@tonic-gate 		}
2070Sstevel@tonic-gate 		pos = lseek(fd, 0, SEEK_CUR);
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 	close(fd);
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	return 0;
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate int main(argc,argv)
2160Sstevel@tonic-gate int argc;
2170Sstevel@tonic-gate char *argv[];
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0;
2200Sstevel@tonic-gate 	char *dirname = NULL, *filename = NULL, *ifs = NULL;
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	progname = argv[0];
2230Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1)
2240Sstevel@tonic-gate 		switch (c)
2250Sstevel@tonic-gate 		{
2260Sstevel@tonic-gate 		case 'd' :
2270Sstevel@tonic-gate 			if ((set == 0) && !dirname && !filename)
2280Sstevel@tonic-gate 				dirname = optarg;
2290Sstevel@tonic-gate 			else
2300Sstevel@tonic-gate 				usage();
2310Sstevel@tonic-gate 			break;
2320Sstevel@tonic-gate 		case 'f' :
2330Sstevel@tonic-gate 			if ((set == 0) && !dirname && !filename)
2340Sstevel@tonic-gate 				filename = optarg;
2350Sstevel@tonic-gate 			else
2360Sstevel@tonic-gate 				usage();
2370Sstevel@tonic-gate 			break;
2380Sstevel@tonic-gate 		case 'i' :
2390Sstevel@tonic-gate 			ifs = optarg;
2400Sstevel@tonic-gate 			set = 1;
2410Sstevel@tonic-gate 			break;
2420Sstevel@tonic-gate 		case 'l' :
2430Sstevel@tonic-gate 			if (filename || dirname || set)
2440Sstevel@tonic-gate 				usage();
2450Sstevel@tonic-gate 			lock = 1;
2460Sstevel@tonic-gate 			set = 1;
2470Sstevel@tonic-gate 			break;
2480Sstevel@tonic-gate 		case 'n' :
2490Sstevel@tonic-gate 			opts |= OPT_DONOTHING;
2500Sstevel@tonic-gate 			break;
2510Sstevel@tonic-gate 		case 'N' :
2520Sstevel@tonic-gate 			if ((ns >= 0) || dirname || (rw != -1) || set)
2530Sstevel@tonic-gate 				usage();
2540Sstevel@tonic-gate 			ns = 0;
2550Sstevel@tonic-gate 			set = 1;
2560Sstevel@tonic-gate 			break;
2570Sstevel@tonic-gate 		case 'r' :
258*2393Syz155240 			if (dirname || (rw != -1) || (ns == -1))
2590Sstevel@tonic-gate 				usage();
2600Sstevel@tonic-gate 			rw = 0;
2610Sstevel@tonic-gate 			set = 1;
2620Sstevel@tonic-gate 			break;
2630Sstevel@tonic-gate 		case 'R' :
2640Sstevel@tonic-gate 			rw = 2;
2650Sstevel@tonic-gate 			set = 1;
2660Sstevel@tonic-gate 			break;
2670Sstevel@tonic-gate 		case 'S' :
2680Sstevel@tonic-gate 			if ((ns >= 0) || dirname || (rw != -1) || set)
2690Sstevel@tonic-gate 				usage();
2700Sstevel@tonic-gate 			ns = 1;
2710Sstevel@tonic-gate 			set = 1;
2720Sstevel@tonic-gate 			break;
2730Sstevel@tonic-gate 		case 'u' :
2740Sstevel@tonic-gate 			if (filename || dirname || set)
2750Sstevel@tonic-gate 				usage();
2760Sstevel@tonic-gate 			lock = 0;
2770Sstevel@tonic-gate 			set = 1;
2780Sstevel@tonic-gate 			break;
2790Sstevel@tonic-gate 		case 'v' :
2800Sstevel@tonic-gate 			opts |= OPT_VERBOSE;
2810Sstevel@tonic-gate 			break;
2820Sstevel@tonic-gate 		case 'w' :
2830Sstevel@tonic-gate 			if (dirname || (rw != -1) || (ns == -1))
2840Sstevel@tonic-gate 				usage();
2850Sstevel@tonic-gate 			rw = 1;
2860Sstevel@tonic-gate 			set = 1;
2870Sstevel@tonic-gate 			break;
2880Sstevel@tonic-gate 		case 'W' :
2890Sstevel@tonic-gate 			rw = 3;
2900Sstevel@tonic-gate 			set = 1;
2910Sstevel@tonic-gate 			break;
2920Sstevel@tonic-gate 		case '?' :
2930Sstevel@tonic-gate 		default :
2940Sstevel@tonic-gate 			usage();
2950Sstevel@tonic-gate 		}
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	if (ifs) {
2980Sstevel@tonic-gate 		if (!filename || ns < 0)
2990Sstevel@tonic-gate 			usage();
3000Sstevel@tonic-gate 		if (ns == 0)
3010Sstevel@tonic-gate 			return changenatif(ifs, filename);
3020Sstevel@tonic-gate 		else
3030Sstevel@tonic-gate 			return changestateif(ifs, filename);
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	if ((ns >= 0) || (lock >= 0)) {
3070Sstevel@tonic-gate 		if (lock >= 0)
3080Sstevel@tonic-gate 			devfd = opendevice(NULL);
3090Sstevel@tonic-gate 		else if (ns >= 0) {
3100Sstevel@tonic-gate 			if (ns == 1)
3110Sstevel@tonic-gate 				devfd = opendevice(IPSTATE_NAME);
3120Sstevel@tonic-gate 			else if (ns == 0)
3130Sstevel@tonic-gate 				devfd = opendevice(IPNAT_NAME);
3140Sstevel@tonic-gate 		}
3150Sstevel@tonic-gate 		if (devfd == -1)
3160Sstevel@tonic-gate 			exit(1);
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	if (lock >= 0)
3200Sstevel@tonic-gate 		err = setlock(devfd, lock);
3210Sstevel@tonic-gate 	else if (rw >= 0) {
3220Sstevel@tonic-gate 		if (rw & 1) {	/* WRITE */
3230Sstevel@tonic-gate 			if (rw & 2)
3240Sstevel@tonic-gate 				err = writeall(dirname);
3250Sstevel@tonic-gate 			else {
3260Sstevel@tonic-gate 				if (ns == 0)
3270Sstevel@tonic-gate 					err = writenat(devfd, filename);
3280Sstevel@tonic-gate 				else if (ns == 1)
3290Sstevel@tonic-gate 					err = writestate(devfd, filename);
3300Sstevel@tonic-gate 			}
3310Sstevel@tonic-gate 		} else {
3320Sstevel@tonic-gate 			if (rw & 2)
3330Sstevel@tonic-gate 				err = readall(dirname);
3340Sstevel@tonic-gate 			else {
3350Sstevel@tonic-gate 				if (ns == 0)
3360Sstevel@tonic-gate 					err = readnat(devfd, filename);
3370Sstevel@tonic-gate 				else if (ns == 1)
3380Sstevel@tonic-gate 					err = readstate(devfd, filename);
3390Sstevel@tonic-gate 			}
3400Sstevel@tonic-gate 		}
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 	return err;
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate int opendevice(ipfdev)
3470Sstevel@tonic-gate char *ipfdev;
3480Sstevel@tonic-gate {
3490Sstevel@tonic-gate 	int fd = -1;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	if (opts & OPT_DONOTHING)
3520Sstevel@tonic-gate 		return -2;
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	if (!ipfdev)
3550Sstevel@tonic-gate 		ipfdev = IPL_NAME;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	if ((fd = open(ipfdev, O_RDWR)) == -1)
3580Sstevel@tonic-gate 		if ((fd = open(ipfdev, O_RDONLY)) == -1)
3590Sstevel@tonic-gate 			perror("open device");
3600Sstevel@tonic-gate 	return fd;
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate void closedevice(fd)
3650Sstevel@tonic-gate int fd;
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate 	close(fd);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate int setlock(fd, lock)
3720Sstevel@tonic-gate int fd, lock;
3730Sstevel@tonic-gate {
3740Sstevel@tonic-gate 	if (opts & OPT_VERBOSE)
3750Sstevel@tonic-gate 		printf("Turn lock %s\n", lock ? "on" : "off");
3760Sstevel@tonic-gate 	if (!(opts & OPT_DONOTHING)) {
3770Sstevel@tonic-gate 		if (ioctl(fd, SIOCSTLCK, &lock) == -1) {
3780Sstevel@tonic-gate 			perror("SIOCSTLCK");
3790Sstevel@tonic-gate 			return 1;
3800Sstevel@tonic-gate 		}
3810Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
3820Sstevel@tonic-gate 			printf("Lock now %s\n", lock ? "on" : "off");
3830Sstevel@tonic-gate 	}
3840Sstevel@tonic-gate 	return 0;
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate int writestate(fd, file)
3890Sstevel@tonic-gate int fd;
3900Sstevel@tonic-gate char *file;
3910Sstevel@tonic-gate {
3920Sstevel@tonic-gate 	ipstate_save_t ips, *ipsp;
393*2393Syz155240 	ipfobj_t obj;
3940Sstevel@tonic-gate 	int wfd = -1;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	if (!file)
3970Sstevel@tonic-gate 		file = IPF_STATEFILE;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
4000Sstevel@tonic-gate 	if (wfd == -1) {
4010Sstevel@tonic-gate 		fprintf(stderr, "%s ", file);
4020Sstevel@tonic-gate 		perror("state:open");
4030Sstevel@tonic-gate 		return 1;
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	ipsp = &ips;
407*2393Syz155240 	bzero((char *)&obj, sizeof(obj));
4080Sstevel@tonic-gate 	bzero((char *)ipsp, sizeof(ips));
4090Sstevel@tonic-gate 
410*2393Syz155240 	obj.ipfo_rev = IPFILTER_VERSION;
411*2393Syz155240 	obj.ipfo_size = sizeof(*ipsp);
412*2393Syz155240 	obj.ipfo_type = IPFOBJ_STATESAVE;
413*2393Syz155240 	obj.ipfo_ptr = ipsp;
414*2393Syz155240 
4150Sstevel@tonic-gate 	do {
416*2393Syz155240 
4170Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
4180Sstevel@tonic-gate 			printf("Getting state from addr %p\n", ips.ips_next);
419*2393Syz155240 		if (ioctl(fd, SIOCSTGET, &obj)) {
4200Sstevel@tonic-gate 			if (errno == ENOENT)
4210Sstevel@tonic-gate 				break;
4220Sstevel@tonic-gate 			perror("state:SIOCSTGET");
4230Sstevel@tonic-gate 			close(wfd);
4240Sstevel@tonic-gate 			return 1;
4250Sstevel@tonic-gate 		}
4260Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
4270Sstevel@tonic-gate 			printf("Got state next %p\n", ips.ips_next);
4280Sstevel@tonic-gate 		if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) {
4290Sstevel@tonic-gate 			perror("state:write");
4300Sstevel@tonic-gate 			close(wfd);
4310Sstevel@tonic-gate 			return 1;
4320Sstevel@tonic-gate 		}
4330Sstevel@tonic-gate 	} while (ips.ips_next != NULL);
4340Sstevel@tonic-gate 	close(wfd);
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	return 0;
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate int readstate(fd, file)
4410Sstevel@tonic-gate int fd;
4420Sstevel@tonic-gate char *file;
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate 	ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL;
4450Sstevel@tonic-gate 	int sfd = -1, i;
446*2393Syz155240 	ipfobj_t obj;
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	if (!file)
4490Sstevel@tonic-gate 		file = IPF_STATEFILE;
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	sfd = open(file, O_RDONLY, 0600);
4520Sstevel@tonic-gate 	if (sfd == -1) {
4530Sstevel@tonic-gate 		fprintf(stderr, "%s ", file);
4540Sstevel@tonic-gate 		perror("open");
4550Sstevel@tonic-gate 		return 1;
4560Sstevel@tonic-gate 	}
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	bzero((char *)&ips, sizeof(ips));
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	/*
4610Sstevel@tonic-gate 	 * 1. Read all state information in.
4620Sstevel@tonic-gate 	 */
4630Sstevel@tonic-gate 	do {
4640Sstevel@tonic-gate 		i = read(sfd, &ips, sizeof(ips));
4650Sstevel@tonic-gate 		if (i == -1) {
4660Sstevel@tonic-gate 			perror("read");
4670Sstevel@tonic-gate 			close(sfd);
4680Sstevel@tonic-gate 			return 1;
4690Sstevel@tonic-gate 		}
4700Sstevel@tonic-gate 		if (i == 0)
4710Sstevel@tonic-gate 			break;
4720Sstevel@tonic-gate 		if (i != sizeof(ips)) {
473*2393Syz155240 			fprintf(stderr, "state:incomplete read: %d != %d\n",
474*2393Syz155240 				i, (int)sizeof(ips));
4750Sstevel@tonic-gate 			close(sfd);
4760Sstevel@tonic-gate 			return 1;
4770Sstevel@tonic-gate 		}
4780Sstevel@tonic-gate 		is = (ipstate_save_t *)malloc(sizeof(*is));
4790Sstevel@tonic-gate 		if(!is) {
4800Sstevel@tonic-gate 			fprintf(stderr, "malloc failed\n");
4810Sstevel@tonic-gate 			return 1;
4820Sstevel@tonic-gate 		}
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 		bcopy((char *)&ips, (char *)is, sizeof(ips));
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 		/*
4870Sstevel@tonic-gate 		 * Check to see if this is the first state entry that will
4880Sstevel@tonic-gate 		 * reference a particular rule and if so, flag it as such
4890Sstevel@tonic-gate 		 * else just adjust the rule pointer to become a pointer to
4900Sstevel@tonic-gate 		 * the other.  We do this so we have a means later for tracking
4910Sstevel@tonic-gate 		 * who is referencing us when we get back the real pointer
4920Sstevel@tonic-gate 		 * in is_rule after doing the ioctl.
4930Sstevel@tonic-gate 		 */
4940Sstevel@tonic-gate 		for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next)
4950Sstevel@tonic-gate 			if (is1->ips_rule == is->ips_rule)
4960Sstevel@tonic-gate 				break;
4970Sstevel@tonic-gate 		if (is1 == NULL)
4980Sstevel@tonic-gate 			is->ips_is.is_flags |= SI_NEWFR;
4990Sstevel@tonic-gate 		else
5000Sstevel@tonic-gate 			is->ips_rule = (void *)&is1->ips_rule;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 		/*
5030Sstevel@tonic-gate 		 * Use a tail-queue type list (add things to the end)..
5040Sstevel@tonic-gate 		 */
5050Sstevel@tonic-gate 		is->ips_next = NULL;
5060Sstevel@tonic-gate 		if (!ipshead)
5070Sstevel@tonic-gate 			ipshead = is;
5080Sstevel@tonic-gate 		if (ipstail)
5090Sstevel@tonic-gate 			ipstail->ips_next = is;
5100Sstevel@tonic-gate 		ipstail = is;
5110Sstevel@tonic-gate 	} while (1);
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	close(sfd);
5140Sstevel@tonic-gate 
515*2393Syz155240 	obj.ipfo_rev = IPFILTER_VERSION;
516*2393Syz155240 	obj.ipfo_size = sizeof(*is);
517*2393Syz155240 	obj.ipfo_type = IPFOBJ_STATESAVE;
518*2393Syz155240 
5190Sstevel@tonic-gate 	for (is = ipshead; is; is = is->ips_next) {
5200Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
5210Sstevel@tonic-gate 			printf("Loading new state table entry\n");
5220Sstevel@tonic-gate 		if (is->ips_is.is_flags & SI_NEWFR) {
5230Sstevel@tonic-gate 			if (opts & OPT_VERBOSE)
5240Sstevel@tonic-gate 				printf("Loading new filter rule\n");
5250Sstevel@tonic-gate 		}
526*2393Syz155240 
527*2393Syz155240 		obj.ipfo_ptr = is;
5280Sstevel@tonic-gate 		if (!(opts & OPT_DONOTHING))
529*2393Syz155240 			if (ioctl(fd, SIOCSTPUT, &obj)) {
5300Sstevel@tonic-gate 				perror("SIOCSTPUT");
5310Sstevel@tonic-gate 				return 1;
5320Sstevel@tonic-gate 			}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 		if (is->ips_is.is_flags & SI_NEWFR) {
5350Sstevel@tonic-gate 			if (opts & OPT_VERBOSE)
5360Sstevel@tonic-gate 				printf("Real rule addr %p\n", is->ips_rule);
5370Sstevel@tonic-gate 			for (is1 = is->ips_next; is1; is1 = is1->ips_next)
5380Sstevel@tonic-gate 				if (is1->ips_rule == (frentry_t *)&is->ips_rule)
5390Sstevel@tonic-gate 					is1->ips_rule = is->ips_rule;
5400Sstevel@tonic-gate 		}
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	return 0;
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate int readnat(fd, file)
5480Sstevel@tonic-gate int fd;
5490Sstevel@tonic-gate char *file;
5500Sstevel@tonic-gate {
551*2393Syz155240 	nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL;
552*2393Syz155240 	ipfobj_t obj;
5530Sstevel@tonic-gate 	int nfd, i;
5540Sstevel@tonic-gate 	nat_t *nat;
555*2393Syz155240 	char *s;
556*2393Syz155240 	int n;
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	nfd = -1;
5590Sstevel@tonic-gate 	in = NULL;
5600Sstevel@tonic-gate 	ipnhead = NULL;
5610Sstevel@tonic-gate 	ipntail = NULL;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	if (!file)
5640Sstevel@tonic-gate 		file = IPF_NATFILE;
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	nfd = open(file, O_RDONLY);
5670Sstevel@tonic-gate 	if (nfd == -1) {
5680Sstevel@tonic-gate 		fprintf(stderr, "%s ", file);
5690Sstevel@tonic-gate 		perror("nat:open");
5700Sstevel@tonic-gate 		return 1;
5710Sstevel@tonic-gate 	}
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	bzero((char *)&ipn, sizeof(ipn));
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	/*
5760Sstevel@tonic-gate 	 * 1. Read all state information in.
5770Sstevel@tonic-gate 	 */
5780Sstevel@tonic-gate 	do {
5790Sstevel@tonic-gate 		i = read(nfd, &ipn, sizeof(ipn));
5800Sstevel@tonic-gate 		if (i == -1) {
5810Sstevel@tonic-gate 			perror("read");
5820Sstevel@tonic-gate 			close(nfd);
5830Sstevel@tonic-gate 			return 1;
5840Sstevel@tonic-gate 		}
5850Sstevel@tonic-gate 		if (i == 0)
5860Sstevel@tonic-gate 			break;
5870Sstevel@tonic-gate 		if (i != sizeof(ipn)) {
588*2393Syz155240 			fprintf(stderr, "nat:incomplete read: %d != %d\n",
589*2393Syz155240 				i, (int)sizeof(ipn));
5900Sstevel@tonic-gate 			close(nfd);
5910Sstevel@tonic-gate 			return 1;
5920Sstevel@tonic-gate 		}
5930Sstevel@tonic-gate 
594*2393Syz155240 		in = (nat_save_t *)malloc(ipn.ipn_dsize);
595*2393Syz155240 		if (!in)
596*2393Syz155240 			break;
5970Sstevel@tonic-gate 
598*2393Syz155240 		if (ipn.ipn_dsize > sizeof(ipn)) {
599*2393Syz155240 			n = ipn.ipn_dsize - sizeof(ipn);
600*2393Syz155240 			if (n > 0) {
601*2393Syz155240 				s = in->ipn_data + sizeof(in->ipn_data);
602*2393Syz155240  				i = read(nfd, s, n);
603*2393Syz155240 				if (i == 0)
604*2393Syz155240 					break;
605*2393Syz155240 				if (i != n) {
606*2393Syz155240 					fprintf(stderr,
607*2393Syz155240 					    "nat:incomplete read: %d != %d\n",
608*2393Syz155240 					    i, n);
609*2393Syz155240 					close(nfd);
610*2393Syz155240 					return 1;
611*2393Syz155240 				}
6120Sstevel@tonic-gate 			}
6130Sstevel@tonic-gate 		}
614*2393Syz155240 		bcopy((char *)&ipn, (char *)in, sizeof(ipn));
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 		/*
617*2393Syz155240 		 * Check to see if this is the first NAT entry that will
6180Sstevel@tonic-gate 		 * reference a particular rule and if so, flag it as such
6190Sstevel@tonic-gate 		 * else just adjust the rule pointer to become a pointer to
6200Sstevel@tonic-gate 		 * the other.  We do this so we have a means later for tracking
6210Sstevel@tonic-gate 		 * who is referencing us when we get back the real pointer
6220Sstevel@tonic-gate 		 * in is_rule after doing the ioctl.
6230Sstevel@tonic-gate 		 */
6240Sstevel@tonic-gate 		nat = &in->ipn_nat;
6250Sstevel@tonic-gate 		if (nat->nat_fr != NULL) {
6260Sstevel@tonic-gate 			for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next)
6270Sstevel@tonic-gate 				if (in1->ipn_rule == nat->nat_fr)
6280Sstevel@tonic-gate 					break;
6290Sstevel@tonic-gate 			if (in1 == NULL)
6300Sstevel@tonic-gate 				nat->nat_flags |= SI_NEWFR;
6310Sstevel@tonic-gate 			else
6320Sstevel@tonic-gate 				nat->nat_fr = &in1->ipn_fr;
6330Sstevel@tonic-gate 		}
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 		/*
6360Sstevel@tonic-gate 		 * Use a tail-queue type list (add things to the end)..
6370Sstevel@tonic-gate 		 */
6380Sstevel@tonic-gate 		in->ipn_next = NULL;
6390Sstevel@tonic-gate 		if (!ipnhead)
6400Sstevel@tonic-gate 			ipnhead = in;
6410Sstevel@tonic-gate 		if (ipntail)
6420Sstevel@tonic-gate 			ipntail->ipn_next = in;
6430Sstevel@tonic-gate 		ipntail = in;
6440Sstevel@tonic-gate 	} while (1);
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	close(nfd);
647*2393Syz155240 	nfd = -1;
648*2393Syz155240 
649*2393Syz155240 	obj.ipfo_rev = IPFILTER_VERSION;
650*2393Syz155240 	obj.ipfo_type = IPFOBJ_NATSAVE;
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	for (in = ipnhead; in; in = in->ipn_next) {
6530Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
6540Sstevel@tonic-gate 			printf("Loading new NAT table entry\n");
6550Sstevel@tonic-gate 		nat = &in->ipn_nat;
6560Sstevel@tonic-gate 		if (nat->nat_flags & SI_NEWFR) {
6570Sstevel@tonic-gate 			if (opts & OPT_VERBOSE)
6580Sstevel@tonic-gate 				printf("Loading new filter rule\n");
6590Sstevel@tonic-gate 		}
660*2393Syz155240 
661*2393Syz155240 		obj.ipfo_ptr = in;
662*2393Syz155240 		obj.ipfo_size = in->ipn_dsize;
6630Sstevel@tonic-gate 		if (!(opts & OPT_DONOTHING))
664*2393Syz155240 			if (ioctl(fd, SIOCSTPUT, &obj)) {
665*2393Syz155240 				fprintf(stderr, "in=%p:", in);
6660Sstevel@tonic-gate 				perror("SIOCSTPUT");
6670Sstevel@tonic-gate 				return 1;
6680Sstevel@tonic-gate 			}
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 		if (nat->nat_flags & SI_NEWFR) {
6710Sstevel@tonic-gate 			if (opts & OPT_VERBOSE)
6720Sstevel@tonic-gate 				printf("Real rule addr %p\n", nat->nat_fr);
6730Sstevel@tonic-gate 			for (in1 = in->ipn_next; in1; in1 = in1->ipn_next)
6740Sstevel@tonic-gate 				if (in1->ipn_rule == &in->ipn_fr)
6750Sstevel@tonic-gate 					in1->ipn_rule = nat->nat_fr;
6760Sstevel@tonic-gate 		}
6770Sstevel@tonic-gate 	}
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	return 0;
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate int writenat(fd, file)
6840Sstevel@tonic-gate int fd;
6850Sstevel@tonic-gate char *file;
6860Sstevel@tonic-gate {
6870Sstevel@tonic-gate 	nat_save_t *ipnp = NULL, *next = NULL;
688*2393Syz155240 	ipfobj_t obj;
6890Sstevel@tonic-gate 	int nfd = -1;
6900Sstevel@tonic-gate 	natget_t ng;
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	if (!file)
6930Sstevel@tonic-gate 		file = IPF_NATFILE;
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
6960Sstevel@tonic-gate 	if (nfd == -1) {
6970Sstevel@tonic-gate 		fprintf(stderr, "%s ", file);
6980Sstevel@tonic-gate 		perror("nat:open");
6990Sstevel@tonic-gate 		return 1;
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate 
702*2393Syz155240 	obj.ipfo_rev = IPFILTER_VERSION;
703*2393Syz155240 	obj.ipfo_type = IPFOBJ_NATSAVE;
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	do {
7060Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
7070Sstevel@tonic-gate 			printf("Getting nat from addr %p\n", ipnp);
7080Sstevel@tonic-gate 		ng.ng_ptr = next;
7090Sstevel@tonic-gate 		ng.ng_sz = 0;
7100Sstevel@tonic-gate 		if (ioctl(fd, SIOCSTGSZ, &ng)) {
7110Sstevel@tonic-gate 			perror("nat:SIOCSTGSZ");
7120Sstevel@tonic-gate 			close(nfd);
7130Sstevel@tonic-gate 			if (ipnp != NULL)
7140Sstevel@tonic-gate 				free(ipnp);
7150Sstevel@tonic-gate 			return 1;
7160Sstevel@tonic-gate 		}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
7190Sstevel@tonic-gate 			printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr);
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 		if (ng.ng_sz == 0)
7220Sstevel@tonic-gate 			break;
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 		if (!ipnp)
7250Sstevel@tonic-gate 			ipnp = malloc(ng.ng_sz);
7260Sstevel@tonic-gate 		else
7270Sstevel@tonic-gate 			ipnp = realloc((char *)ipnp, ng.ng_sz);
7280Sstevel@tonic-gate 		if (!ipnp) {
7290Sstevel@tonic-gate 			fprintf(stderr,
7300Sstevel@tonic-gate 				"malloc for %d bytes failed\n", ng.ng_sz);
7310Sstevel@tonic-gate 			break;
7320Sstevel@tonic-gate 		}
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 		bzero((char *)ipnp, ng.ng_sz);
735*2393Syz155240 		obj.ipfo_size = ng.ng_sz;
736*2393Syz155240 		obj.ipfo_ptr = ipnp;
737*2393Syz155240 		ipnp->ipn_dsize = ng.ng_sz;
7380Sstevel@tonic-gate 		ipnp->ipn_next = next;
739*2393Syz155240 		if (ioctl(fd, SIOCSTGET, &obj)) {
7400Sstevel@tonic-gate 			if (errno == ENOENT)
7410Sstevel@tonic-gate 				break;
7420Sstevel@tonic-gate 			perror("nat:SIOCSTGET");
7430Sstevel@tonic-gate 			close(nfd);
7440Sstevel@tonic-gate 			free(ipnp);
7450Sstevel@tonic-gate 			return 1;
7460Sstevel@tonic-gate 		}
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 		if (opts & OPT_VERBOSE)
749*2393Syz155240 			printf("Got nat next %p ipn_dsize %d ng_sz %d\n",
750*2393Syz155240 				ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz);
751*2393Syz155240 		if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) {
7520Sstevel@tonic-gate 			perror("nat:write");
7530Sstevel@tonic-gate 			close(nfd);
7540Sstevel@tonic-gate 			free(ipnp);
7550Sstevel@tonic-gate 			return 1;
7560Sstevel@tonic-gate 		}
7570Sstevel@tonic-gate 		next = ipnp->ipn_next;
7580Sstevel@tonic-gate 	} while (ipnp && next);
7590Sstevel@tonic-gate 	if (ipnp != NULL)
7600Sstevel@tonic-gate 		free(ipnp);
7610Sstevel@tonic-gate 	close(nfd);
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	return 0;
7640Sstevel@tonic-gate }
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate int writeall(dirname)
7680Sstevel@tonic-gate char *dirname;
7690Sstevel@tonic-gate {
7700Sstevel@tonic-gate 	int fd, devfd;
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	if (!dirname)
7730Sstevel@tonic-gate 		dirname = IPF_SAVEDIR;
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	if (chdir(dirname)) {
776*2393Syz155240 		fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname);
7770Sstevel@tonic-gate 		perror("chdir(IPF_SAVEDIR)");
7780Sstevel@tonic-gate 		return 1;
7790Sstevel@tonic-gate 	}
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 	fd = opendevice(NULL);
7820Sstevel@tonic-gate 	if (fd == -1)
7830Sstevel@tonic-gate 		return 1;
7840Sstevel@tonic-gate 	if (setlock(fd, 1)) {
7850Sstevel@tonic-gate 		close(fd);
7860Sstevel@tonic-gate 		return 1;
7870Sstevel@tonic-gate 	}
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	devfd = opendevice(IPSTATE_NAME);
7900Sstevel@tonic-gate 	if (devfd == -1)
7910Sstevel@tonic-gate 		goto bad;
7920Sstevel@tonic-gate 	if (writestate(devfd, NULL))
7930Sstevel@tonic-gate 		goto bad;
7940Sstevel@tonic-gate 	close(devfd);
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	devfd = opendevice(IPNAT_NAME);
7970Sstevel@tonic-gate 	if (devfd == -1)
7980Sstevel@tonic-gate 		goto bad;
7990Sstevel@tonic-gate 	if (writenat(devfd, NULL))
8000Sstevel@tonic-gate 		goto bad;
8010Sstevel@tonic-gate 	close(devfd);
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if (setlock(fd, 0)) {
8040Sstevel@tonic-gate 		close(fd);
8050Sstevel@tonic-gate 		return 1;
8060Sstevel@tonic-gate 	}
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	close(fd);
8090Sstevel@tonic-gate 	return 0;
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate bad:
8120Sstevel@tonic-gate 	setlock(fd, 0);
8130Sstevel@tonic-gate 	close(fd);
8140Sstevel@tonic-gate 	return 1;
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate int readall(dirname)
8190Sstevel@tonic-gate char *dirname;
8200Sstevel@tonic-gate {
8210Sstevel@tonic-gate 	int fd, devfd;
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	if (!dirname)
8240Sstevel@tonic-gate 		dirname = IPF_SAVEDIR;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	if (chdir(dirname)) {
8270Sstevel@tonic-gate 		perror("chdir(IPF_SAVEDIR)");
8280Sstevel@tonic-gate 		return 1;
8290Sstevel@tonic-gate 	}
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	fd = opendevice(NULL);
8320Sstevel@tonic-gate 	if (fd == -1)
8330Sstevel@tonic-gate 		return 1;
8340Sstevel@tonic-gate 	if (setlock(fd, 1)) {
8350Sstevel@tonic-gate 		close(fd);
8360Sstevel@tonic-gate 		return 1;
8370Sstevel@tonic-gate 	}
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	devfd = opendevice(IPSTATE_NAME);
8400Sstevel@tonic-gate 	if (devfd == -1)
8410Sstevel@tonic-gate 		return 1;
8420Sstevel@tonic-gate 	if (readstate(devfd, NULL))
8430Sstevel@tonic-gate 		return 1;
8440Sstevel@tonic-gate 	close(devfd);
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	devfd = opendevice(IPNAT_NAME);
8470Sstevel@tonic-gate 	if (devfd == -1)
8480Sstevel@tonic-gate 		return 1;
8490Sstevel@tonic-gate 	if (readnat(devfd, NULL))
8500Sstevel@tonic-gate 		return 1;
8510Sstevel@tonic-gate 	close(devfd);
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 	if (setlock(fd, 0)) {
8540Sstevel@tonic-gate 		close(fd);
8550Sstevel@tonic-gate 		return 1;
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	return 0;
8590Sstevel@tonic-gate }
860