1 /*
2 * Copyright (C) 1999-2001, 2003 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 *
6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
8 *
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
10 */
11
12 #ifdef __FreeBSD__
13 # ifndef __FreeBSD_cc_version
14 # include <osreldate.h>
15 # else
16 # if __FreeBSD_cc_version < 430000
17 # include <osreldate.h>
18 # endif
19 # endif
20 #endif
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #if !defined(__SVR4) && !defined(__GNUC__)
27 #include <strings.h>
28 #endif
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/file.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <sys/socket.h>
35 #include <sys/ioctl.h>
36 #include <netinet/in.h>
37 #include <netinet/in_systm.h>
38 #include <sys/time.h>
39 #include <net/if.h>
40 #if __FreeBSD_version >= 300000
41 # include <net/if_var.h>
42 #endif
43 #include <netinet/ip.h>
44 #include <netdb.h>
45 #include <arpa/nameser.h>
46 #include <resolv.h>
47 #include "ipf.h"
48 #include "netinet/ipl.h"
49 #include "ipfzone.h"
50
51 #if !defined(lint)
52 static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp";
53 #endif
54
55 #ifndef IPF_SAVEDIR
56 # define IPF_SAVEDIR "/var/db/ipf"
57 #endif
58 #ifndef IPF_NATFILE
59 # define IPF_NATFILE "ipnat.ipf"
60 #endif
61 #ifndef IPF_STATEFILE
62 # define IPF_STATEFILE "ipstate.ipf"
63 #endif
64
65 #if !defined(__SVR4) && defined(__GNUC__)
66 extern char *index __P((const char *, int));
67 #endif
68
69 extern char *optarg;
70 extern int optind;
71
72 int main __P((int, char *[]));
73 void usage __P((void));
74 int changestateif __P((char *, char *));
75 int changenatif __P((char *, char *));
76 int readstate __P((int, char *));
77 int readnat __P((int, char *));
78 int writestate __P((int, char *));
79 int opendevice __P((char *));
80 void closedevice __P((int));
81 int setlock __P((int, int));
82 int writeall __P((char *));
83 int readall __P((char *));
84 int writenat __P((int, char *));
85
86 int opts = 0;
87 char *progname;
88
89
usage()90 void usage()
91 {
92 const char *zoneopt = "[-G|-z zonename] ";
93 fprintf(stderr, "usage: %s %s[-nv] -l\n", progname, zoneopt);
94 fprintf(stderr, "usage: %s %s[-nv] -u\n", progname, zoneopt);
95 fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -R\n", progname, zoneopt);
96 fprintf(stderr, "usage: %s %s[-nv] [-d <dir>] -W\n", progname, zoneopt);
97 fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -r\n", progname,
98 zoneopt);
99 fprintf(stderr, "usage: %s %s[-nv] [-N|-S] [-f <file>] -w\n", progname,
100 zoneopt);
101 fprintf(stderr, "usage: %s %s[-nv] [-N|-S] -f <file> -i <if1>,<if2>\n",
102 progname, zoneopt);
103 exit(1);
104 }
105
106
107 /*
108 * Change interface names in state information saved out to disk.
109 */
changestateif(ifs,fname)110 int changestateif(ifs, fname)
111 char *ifs, *fname;
112 {
113 int fd, olen, nlen, rw;
114 ipstate_save_t ips;
115 off_t pos;
116 char *s;
117
118 s = strchr(ifs, ',');
119 if (!s)
120 usage();
121 *s++ = '\0';
122 nlen = strlen(s);
123 olen = strlen(ifs);
124 if (nlen >= sizeof(ips.ips_is.is_ifname) ||
125 olen >= sizeof(ips.ips_is.is_ifname))
126 usage();
127
128 fd = open(fname, O_RDWR);
129 if (fd == -1) {
130 perror("open");
131 exit(1);
132 }
133
134 for (pos = 0; read(fd, &ips, sizeof(ips)) == sizeof(ips); ) {
135 rw = 0;
136 if (!strncmp(ips.ips_is.is_ifname[0], ifs, olen + 1)) {
137 strcpy(ips.ips_is.is_ifname[0], s);
138 rw = 1;
139 }
140 if (!strncmp(ips.ips_is.is_ifname[1], ifs, olen + 1)) {
141 strcpy(ips.ips_is.is_ifname[1], s);
142 rw = 1;
143 }
144 if (rw == 1) {
145 if (lseek(fd, pos, SEEK_SET) != pos) {
146 perror("lseek");
147 exit(1);
148 }
149 if (write(fd, &ips, sizeof(ips)) != sizeof(ips)) {
150 perror("write");
151 exit(1);
152 }
153 }
154 pos = lseek(fd, 0, SEEK_CUR);
155 }
156 close(fd);
157
158 return 0;
159 }
160
161
162 /*
163 * Change interface names in NAT information saved out to disk.
164 */
changenatif(ifs,fname)165 int changenatif(ifs, fname)
166 char *ifs, *fname;
167 {
168 int fd, olen, nlen, rw;
169 nat_save_t ipn;
170 nat_t *nat;
171 off_t pos;
172 char *s;
173
174 s = strchr(ifs, ',');
175 if (!s)
176 usage();
177 *s++ = '\0';
178 nlen = strlen(s);
179 olen = strlen(ifs);
180 nat = &ipn.ipn_nat;
181 if (nlen >= sizeof(nat->nat_ifnames[0]) ||
182 olen >= sizeof(nat->nat_ifnames[0]))
183 usage();
184
185 fd = open(fname, O_RDWR);
186 if (fd == -1) {
187 perror("open");
188 exit(1);
189 }
190
191 for (pos = 0; read(fd, &ipn, sizeof(ipn)) == sizeof(ipn); ) {
192 rw = 0;
193 if (!strncmp(nat->nat_ifnames[0], ifs, olen + 1)) {
194 strcpy(nat->nat_ifnames[0], s);
195 rw = 1;
196 }
197 if (!strncmp(nat->nat_ifnames[1], ifs, olen + 1)) {
198 strcpy(nat->nat_ifnames[1], s);
199 rw = 1;
200 }
201 if (rw == 1) {
202 if (lseek(fd, pos, SEEK_SET) != pos) {
203 perror("lseek");
204 exit(1);
205 }
206 if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) {
207 perror("write");
208 exit(1);
209 }
210 }
211 pos = lseek(fd, 0, SEEK_CUR);
212 }
213 close(fd);
214
215 return 0;
216 }
217
218
main(argc,argv)219 int main(argc,argv)
220 int argc;
221 char *argv[];
222 {
223 int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0;
224 char *dirname = NULL, *filename = NULL, *ifs = NULL;
225
226 progname = argv[0];
227 while ((c = getopt(argc, argv, "d:f:G:lNnSRruvWwz:")) != -1)
228 switch (c)
229 {
230 case 'd' :
231 if ((set == 0) && !dirname && !filename)
232 dirname = optarg;
233 else
234 usage();
235 break;
236 case 'f' :
237 if ((set == 0) && !dirname && !filename)
238 filename = optarg;
239 else
240 usage();
241 break;
242 case 'G' :
243 setzonename_global(optarg);
244 break;
245 case 'i' :
246 ifs = optarg;
247 set = 1;
248 break;
249 case 'l' :
250 if (filename || dirname || set)
251 usage();
252 lock = 1;
253 set = 1;
254 break;
255 case 'n' :
256 opts |= OPT_DONOTHING;
257 break;
258 case 'N' :
259 if ((ns >= 0) || dirname || (rw != -1) || set)
260 usage();
261 ns = 0;
262 set = 1;
263 break;
264 case 'r' :
265 if (dirname || (rw != -1) || (ns == -1))
266 usage();
267 rw = 0;
268 set = 1;
269 break;
270 case 'R' :
271 rw = 2;
272 set = 1;
273 break;
274 case 'S' :
275 if ((ns >= 0) || dirname || (rw != -1) || set)
276 usage();
277 ns = 1;
278 set = 1;
279 break;
280 case 'u' :
281 if (filename || dirname || set)
282 usage();
283 lock = 0;
284 set = 1;
285 break;
286 case 'v' :
287 opts |= OPT_VERBOSE;
288 break;
289 case 'w' :
290 if (dirname || (rw != -1) || (ns == -1))
291 usage();
292 rw = 1;
293 set = 1;
294 break;
295 case 'W' :
296 rw = 3;
297 set = 1;
298 break;
299 case 'z' :
300 setzonename(optarg);
301 break;
302 case '?' :
303 default :
304 usage();
305 }
306
307 if (ifs) {
308 if (!filename || ns < 0)
309 usage();
310 if (ns == 0)
311 return changenatif(ifs, filename);
312 else
313 return changestateif(ifs, filename);
314 }
315
316 if ((ns >= 0) || (lock >= 0)) {
317 if (lock >= 0)
318 devfd = opendevice(NULL);
319 else if (ns >= 0) {
320 if (ns == 1)
321 devfd = opendevice(IPSTATE_NAME);
322 else if (ns == 0)
323 devfd = opendevice(IPNAT_NAME);
324 }
325 if (devfd == -1)
326 exit(1);
327 }
328
329 if (lock >= 0)
330 err = setlock(devfd, lock);
331 else if (rw >= 0) {
332 if (rw & 1) { /* WRITE */
333 if (rw & 2)
334 err = writeall(dirname);
335 else {
336 if (ns == 0)
337 err = writenat(devfd, filename);
338 else if (ns == 1)
339 err = writestate(devfd, filename);
340 }
341 } else {
342 if (rw & 2)
343 err = readall(dirname);
344 else {
345 if (ns == 0)
346 err = readnat(devfd, filename);
347 else if (ns == 1)
348 err = readstate(devfd, filename);
349 }
350 }
351 }
352 return err;
353 }
354
355
opendevice(ipfdev)356 int opendevice(ipfdev)
357 char *ipfdev;
358 {
359 int fd = -1;
360
361 if (opts & OPT_DONOTHING)
362 return -2;
363
364 if (!ipfdev)
365 ipfdev = IPL_NAME;
366
367 if ((fd = open(ipfdev, O_RDWR)) == -1)
368 if ((fd = open(ipfdev, O_RDONLY)) == -1)
369 perror("open device");
370
371 if (setzone(fd) != 0) {
372 close(fd);
373 fd = -1;
374 }
375
376 return fd;
377 }
378
379
closedevice(fd)380 void closedevice(fd)
381 int fd;
382 {
383 close(fd);
384 }
385
386
setlock(fd,lock)387 int setlock(fd, lock)
388 int fd, lock;
389 {
390 if (opts & OPT_VERBOSE)
391 printf("Turn lock %s\n", lock ? "on" : "off");
392 if (!(opts & OPT_DONOTHING)) {
393 if (ioctl(fd, SIOCSTLCK, &lock) == -1) {
394 perror("SIOCSTLCK");
395 return 1;
396 }
397 if (opts & OPT_VERBOSE)
398 printf("Lock now %s\n", lock ? "on" : "off");
399 }
400 return 0;
401 }
402
403
writestate(fd,file)404 int writestate(fd, file)
405 int fd;
406 char *file;
407 {
408 ipstate_save_t ips, *ipsp;
409 ipfobj_t obj;
410 int wfd = -1;
411
412 if (!file)
413 file = IPF_STATEFILE;
414
415 wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
416 if (wfd == -1) {
417 fprintf(stderr, "%s ", file);
418 perror("state:open");
419 return 1;
420 }
421
422 ipsp = &ips;
423 bzero((char *)&obj, sizeof(obj));
424 bzero((char *)ipsp, sizeof(ips));
425
426 obj.ipfo_rev = IPFILTER_VERSION;
427 obj.ipfo_size = sizeof(*ipsp);
428 obj.ipfo_type = IPFOBJ_STATESAVE;
429 obj.ipfo_ptr = ipsp;
430
431 do {
432
433 if (opts & OPT_VERBOSE)
434 printf("Getting state from addr %p\n", ips.ips_next);
435 if (ioctl(fd, SIOCSTGET, &obj)) {
436 if (errno == ENOENT)
437 break;
438 perror("state:SIOCSTGET");
439 close(wfd);
440 return 1;
441 }
442 if (opts & OPT_VERBOSE)
443 printf("Got state next %p\n", ips.ips_next);
444 if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) {
445 perror("state:write");
446 close(wfd);
447 return 1;
448 }
449 } while (ips.ips_next != NULL);
450 close(wfd);
451
452 return 0;
453 }
454
455
readstate(fd,file)456 int readstate(fd, file)
457 int fd;
458 char *file;
459 {
460 ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL;
461 int sfd = -1, i;
462 ipfobj_t obj;
463
464 if (!file)
465 file = IPF_STATEFILE;
466
467 sfd = open(file, O_RDONLY, 0600);
468 if (sfd == -1) {
469 fprintf(stderr, "%s ", file);
470 perror("open");
471 return 1;
472 }
473
474 bzero((char *)&ips, sizeof(ips));
475
476 /*
477 * 1. Read all state information in.
478 */
479 do {
480 i = read(sfd, &ips, sizeof(ips));
481 if (i == -1) {
482 perror("read");
483 close(sfd);
484 return 1;
485 }
486 if (i == 0)
487 break;
488 if (i != sizeof(ips)) {
489 fprintf(stderr, "state:incomplete read: %d != %d\n",
490 i, (int)sizeof(ips));
491 close(sfd);
492 return 1;
493 }
494 is = (ipstate_save_t *)malloc(sizeof(*is));
495 if(!is) {
496 fprintf(stderr, "malloc failed\n");
497 return 1;
498 }
499
500 bcopy((char *)&ips, (char *)is, sizeof(ips));
501
502 /*
503 * Check to see if this is the first state entry that will
504 * reference a particular rule and if so, flag it as such
505 * else just adjust the rule pointer to become a pointer to
506 * the other. We do this so we have a means later for tracking
507 * who is referencing us when we get back the real pointer
508 * in is_rule after doing the ioctl.
509 */
510 for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next)
511 if (is1->ips_rule == is->ips_rule)
512 break;
513 if (is1 == NULL)
514 is->ips_is.is_flags |= SI_NEWFR;
515 else
516 is->ips_rule = (void *)&is1->ips_rule;
517
518 /*
519 * Use a tail-queue type list (add things to the end)..
520 */
521 is->ips_next = NULL;
522 if (!ipshead)
523 ipshead = is;
524 if (ipstail)
525 ipstail->ips_next = is;
526 ipstail = is;
527 } while (1);
528
529 close(sfd);
530
531 obj.ipfo_rev = IPFILTER_VERSION;
532 obj.ipfo_size = sizeof(*is);
533 obj.ipfo_type = IPFOBJ_STATESAVE;
534
535 for (is = ipshead; is; is = is->ips_next) {
536 if (opts & OPT_VERBOSE)
537 printf("Loading new state table entry\n");
538 if (is->ips_is.is_flags & SI_NEWFR) {
539 if (opts & OPT_VERBOSE)
540 printf("Loading new filter rule\n");
541 }
542
543 obj.ipfo_ptr = is;
544 if (!(opts & OPT_DONOTHING))
545 if (ioctl(fd, SIOCSTPUT, &obj)) {
546 perror("SIOCSTPUT");
547 return 1;
548 }
549
550 if (is->ips_is.is_flags & SI_NEWFR) {
551 if (opts & OPT_VERBOSE)
552 printf("Real rule addr %p\n", is->ips_rule);
553 for (is1 = is->ips_next; is1; is1 = is1->ips_next)
554 if (is1->ips_rule == (frentry_t *)&is->ips_rule)
555 is1->ips_rule = is->ips_rule;
556 }
557 }
558
559 return 0;
560 }
561
562
readnat(fd,file)563 int readnat(fd, file)
564 int fd;
565 char *file;
566 {
567 nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL;
568 ipfobj_t obj;
569 int nfd, i;
570 nat_t *nat;
571 char *s;
572 int n;
573
574 nfd = -1;
575 in = NULL;
576 ipnhead = NULL;
577 ipntail = NULL;
578
579 if (!file)
580 file = IPF_NATFILE;
581
582 nfd = open(file, O_RDONLY);
583 if (nfd == -1) {
584 fprintf(stderr, "%s ", file);
585 perror("nat:open");
586 return 1;
587 }
588
589 bzero((char *)&ipn, sizeof(ipn));
590
591 /*
592 * 1. Read all state information in.
593 */
594 do {
595 i = read(nfd, &ipn, sizeof(ipn));
596 if (i == -1) {
597 perror("read");
598 close(nfd);
599 return 1;
600 }
601 if (i == 0)
602 break;
603 if (i != sizeof(ipn)) {
604 fprintf(stderr, "nat:incomplete read: %d != %d\n",
605 i, (int)sizeof(ipn));
606 close(nfd);
607 return 1;
608 }
609
610 in = (nat_save_t *)malloc(ipn.ipn_dsize);
611 if (!in)
612 break;
613
614 if (ipn.ipn_dsize > sizeof(ipn)) {
615 n = ipn.ipn_dsize - sizeof(ipn);
616 if (n > 0) {
617 s = in->ipn_data + sizeof(in->ipn_data);
618 i = read(nfd, s, n);
619 if (i == 0)
620 break;
621 if (i != n) {
622 fprintf(stderr,
623 "nat:incomplete read: %d != %d\n",
624 i, n);
625 close(nfd);
626 return 1;
627 }
628 }
629 }
630 bcopy((char *)&ipn, (char *)in, sizeof(ipn));
631
632 /*
633 * Check to see if this is the first NAT entry that will
634 * reference a particular rule and if so, flag it as such
635 * else just adjust the rule pointer to become a pointer to
636 * the other. We do this so we have a means later for tracking
637 * who is referencing us when we get back the real pointer
638 * in is_rule after doing the ioctl.
639 */
640 nat = &in->ipn_nat;
641 if (nat->nat_fr != NULL) {
642 for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next)
643 if (in1->ipn_rule == nat->nat_fr)
644 break;
645 if (in1 == NULL)
646 nat->nat_flags |= SI_NEWFR;
647 else
648 nat->nat_fr = &in1->ipn_fr;
649 }
650
651 /*
652 * Use a tail-queue type list (add things to the end)..
653 */
654 in->ipn_next = NULL;
655 if (!ipnhead)
656 ipnhead = in;
657 if (ipntail)
658 ipntail->ipn_next = in;
659 ipntail = in;
660 } while (1);
661
662 close(nfd);
663 nfd = -1;
664
665 obj.ipfo_rev = IPFILTER_VERSION;
666 obj.ipfo_type = IPFOBJ_NATSAVE;
667
668 for (in = ipnhead; in; in = in->ipn_next) {
669 if (opts & OPT_VERBOSE)
670 printf("Loading new NAT table entry\n");
671 nat = &in->ipn_nat;
672 if (nat->nat_flags & SI_NEWFR) {
673 if (opts & OPT_VERBOSE)
674 printf("Loading new filter rule\n");
675 }
676
677 obj.ipfo_ptr = in;
678 obj.ipfo_size = in->ipn_dsize;
679 if (!(opts & OPT_DONOTHING))
680 if (ioctl(fd, SIOCSTPUT, &obj)) {
681 fprintf(stderr, "in=%p:", in);
682 perror("SIOCSTPUT");
683 return 1;
684 }
685
686 if (nat->nat_flags & SI_NEWFR) {
687 if (opts & OPT_VERBOSE)
688 printf("Real rule addr %p\n", nat->nat_fr);
689 for (in1 = in->ipn_next; in1; in1 = in1->ipn_next)
690 if (in1->ipn_rule == &in->ipn_fr)
691 in1->ipn_rule = nat->nat_fr;
692 }
693 }
694
695 return 0;
696 }
697
698
writenat(fd,file)699 int writenat(fd, file)
700 int fd;
701 char *file;
702 {
703 nat_save_t *ipnp = NULL, *next = NULL;
704 ipfobj_t obj;
705 int nfd = -1;
706 natget_t ng;
707
708 if (!file)
709 file = IPF_NATFILE;
710
711 nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
712 if (nfd == -1) {
713 fprintf(stderr, "%s ", file);
714 perror("nat:open");
715 return 1;
716 }
717
718 obj.ipfo_rev = IPFILTER_VERSION;
719 obj.ipfo_type = IPFOBJ_NATSAVE;
720
721 do {
722 if (opts & OPT_VERBOSE)
723 printf("Getting nat from addr %p\n", ipnp);
724 ng.ng_ptr = next;
725 ng.ng_sz = 0;
726 if (ioctl(fd, SIOCSTGSZ, &ng)) {
727 perror("nat:SIOCSTGSZ");
728 close(nfd);
729 if (ipnp != NULL)
730 free(ipnp);
731 return 1;
732 }
733
734 if (opts & OPT_VERBOSE)
735 printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr);
736
737 if (ng.ng_sz == 0)
738 break;
739
740 if (!ipnp)
741 ipnp = malloc(ng.ng_sz);
742 else
743 ipnp = realloc((char *)ipnp, ng.ng_sz);
744 if (!ipnp) {
745 fprintf(stderr,
746 "malloc for %d bytes failed\n", ng.ng_sz);
747 break;
748 }
749
750 bzero((char *)ipnp, ng.ng_sz);
751 obj.ipfo_size = ng.ng_sz;
752 obj.ipfo_ptr = ipnp;
753 ipnp->ipn_dsize = ng.ng_sz;
754 ipnp->ipn_next = next;
755 if (ioctl(fd, SIOCSTGET, &obj)) {
756 if (errno == ENOENT)
757 break;
758 perror("nat:SIOCSTGET");
759 close(nfd);
760 free(ipnp);
761 return 1;
762 }
763
764 if (opts & OPT_VERBOSE)
765 printf("Got nat next %p ipn_dsize %d ng_sz %d\n",
766 ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz);
767 if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) {
768 perror("nat:write");
769 close(nfd);
770 free(ipnp);
771 return 1;
772 }
773 next = ipnp->ipn_next;
774 } while (ipnp && next);
775 if (ipnp != NULL)
776 free(ipnp);
777 close(nfd);
778
779 return 0;
780 }
781
782
writeall(dirname)783 int writeall(dirname)
784 char *dirname;
785 {
786 int fd, devfd;
787
788 if (!dirname)
789 dirname = IPF_SAVEDIR;
790
791 if (chdir(dirname)) {
792 fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname);
793 perror("chdir(IPF_SAVEDIR)");
794 return 1;
795 }
796
797 fd = opendevice(NULL);
798 if (fd == -1)
799 return 1;
800 if (setlock(fd, 1)) {
801 close(fd);
802 return 1;
803 }
804
805 devfd = opendevice(IPSTATE_NAME);
806 if (devfd == -1)
807 goto bad;
808 if (writestate(devfd, NULL))
809 goto bad;
810 close(devfd);
811
812 devfd = opendevice(IPNAT_NAME);
813 if (devfd == -1)
814 goto bad;
815 if (writenat(devfd, NULL))
816 goto bad;
817 close(devfd);
818
819 if (setlock(fd, 0)) {
820 close(fd);
821 return 1;
822 }
823
824 close(fd);
825 return 0;
826
827 bad:
828 setlock(fd, 0);
829 close(fd);
830 return 1;
831 }
832
833
readall(dirname)834 int readall(dirname)
835 char *dirname;
836 {
837 int fd, devfd;
838
839 if (!dirname)
840 dirname = IPF_SAVEDIR;
841
842 if (chdir(dirname)) {
843 perror("chdir(IPF_SAVEDIR)");
844 return 1;
845 }
846
847 fd = opendevice(NULL);
848 if (fd == -1)
849 return 1;
850 if (setlock(fd, 1)) {
851 close(fd);
852 return 1;
853 }
854
855 devfd = opendevice(IPSTATE_NAME);
856 if (devfd == -1)
857 return 1;
858 if (readstate(devfd, NULL))
859 return 1;
860 close(devfd);
861
862 devfd = opendevice(IPNAT_NAME);
863 if (devfd == -1)
864 return 1;
865 if (readnat(devfd, NULL))
866 return 1;
867 close(devfd);
868
869 if (setlock(fd, 0)) {
870 close(fd);
871 return 1;
872 }
873
874 return 0;
875 }
876