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