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