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