]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/tools/ipfs.c
This commit was generated by cvs2svn to compensate for changes in r154178,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / tools / ipfs.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 1999-2001, 2003 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 const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56: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
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  */
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 (rw == 1) {
137                         if (lseek(fd, pos, SEEK_SET) != pos) {
138                                 perror("lseek");
139                                 exit(1);
140                         }
141                         if (write(fd, &ips, sizeof(ips)) != sizeof(ips)) {
142                                 perror("write");
143                                 exit(1);
144                         }
145                 }
146                 pos = lseek(fd, 0, SEEK_CUR);
147         }
148         close(fd);
149
150         return 0;
151 }
152
153
154 /*
155  * Change interface names in NAT information saved out to disk.
156  */
157 int changenatif(ifs, fname)
158 char *ifs, *fname;
159 {
160         int fd, olen, nlen, rw;
161         nat_save_t ipn;
162         nat_t *nat;
163         off_t pos;
164         char *s;
165
166         s = strchr(ifs, ',');
167         if (!s)
168                 usage();
169         *s++ = '\0';
170         nlen = strlen(s);
171         olen = strlen(ifs);
172         nat = &ipn.ipn_nat;
173         if (nlen >= sizeof(nat->nat_ifnames[0]) ||
174             olen >= sizeof(nat->nat_ifnames[0]))
175                 usage();
176
177         fd = open(fname, O_RDWR);
178         if (fd == -1) {
179                 perror("open");
180                 exit(1);
181         }
182
183         for (pos = 0; read(fd, &ipn, sizeof(ipn)) == sizeof(ipn); ) {
184                 rw = 0;
185                 if (!strncmp(nat->nat_ifnames[0], ifs, olen + 1)) {
186                         strcpy(nat->nat_ifnames[0], s);
187                         rw = 1;
188                 }
189                 if (!strncmp(nat->nat_ifnames[1], ifs, olen + 1)) {
190                         strcpy(nat->nat_ifnames[1], s);
191                         rw = 1;
192                 }
193                 if (rw == 1) {
194                         if (lseek(fd, pos, SEEK_SET) != pos) {
195                                 perror("lseek");
196                                 exit(1);
197                         }
198                         if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) {
199                                 perror("write");
200                                 exit(1);
201                         }
202                 }
203                 pos = lseek(fd, 0, SEEK_CUR);
204         }
205         close(fd);
206
207         return 0;
208 }
209
210
211 int main(argc,argv)
212 int argc;
213 char *argv[];
214 {
215         int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0;
216         char *dirname = NULL, *filename = NULL, *ifs = NULL;
217
218         progname = argv[0];
219         while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1)
220                 switch (c)
221                 {
222                 case 'd' :
223                         if ((set == 0) && !dirname && !filename)
224                                 dirname = optarg;
225                         else
226                                 usage();
227                         break;
228                 case 'f' :
229                         if ((set != 0) && !dirname && !filename)
230                                 filename = optarg;
231                         else
232                                 usage();
233                         break;
234                 case 'i' :
235                         ifs = optarg;
236                         set = 1;
237                         break;
238                 case 'l' :
239                         if (filename || dirname || set)
240                                 usage();
241                         lock = 1;
242                         set = 1;
243                         break;
244                 case 'n' :
245                         opts |= OPT_DONOTHING;
246                         break;
247                 case 'N' :
248                         if ((ns >= 0) || dirname || (rw != -1) || set)
249                                 usage();
250                         ns = 0;
251                         set = 1;
252                         break;
253                 case 'r' :
254                         if (dirname || (rw != -1) || (ns == -1))
255                                 usage();
256                         rw = 0;
257                         set = 1;
258                         break;
259                 case 'R' :
260                         rw = 2;
261                         set = 1;
262                         break;
263                 case 'S' :
264                         if ((ns >= 0) || dirname || (rw != -1) || set)
265                                 usage();
266                         ns = 1;
267                         set = 1;
268                         break;
269                 case 'u' :
270                         if (filename || dirname || set)
271                                 usage();
272                         lock = 0;
273                         set = 1;
274                         break;
275                 case 'v' :
276                         opts |= OPT_VERBOSE;
277                         break;
278                 case 'w' :
279                         if (dirname || (rw != -1) || (ns == -1))
280                                 usage();
281                         rw = 1;
282                         set = 1;
283                         break;
284                 case 'W' :
285                         rw = 3;
286                         set = 1;
287                         break;
288                 case '?' :
289                 default :
290                         usage();
291                 }
292
293         if (ifs) {
294                 if (!filename || ns < 0)
295                         usage();
296                 if (ns == 0)
297                         return changenatif(ifs, filename);
298                 else
299                         return changestateif(ifs, filename);
300         }
301
302         if ((ns >= 0) || (lock >= 0)) {
303                 if (lock >= 0)
304                         devfd = opendevice(NULL);
305                 else if (ns >= 0) {
306                         if (ns == 1)
307                                 devfd = opendevice(IPSTATE_NAME);
308                         else if (ns == 0)
309                                 devfd = opendevice(IPNAT_NAME);
310                 }
311                 if (devfd == -1)
312                         exit(1);
313         }
314
315         if (lock >= 0)
316                 err = setlock(devfd, lock);
317         else if (rw >= 0) {
318                 if (rw & 1) {   /* WRITE */
319                         if (rw & 2)
320                                 err = writeall(dirname);
321                         else {
322                                 if (ns == 0)
323                                         err = writenat(devfd, filename);
324                                 else if (ns == 1)
325                                         err = writestate(devfd, filename);
326                         }
327                 } else {
328                         if (rw & 2)
329                                 err = readall(dirname);
330                         else {
331                                 if (ns == 0)
332                                         err = readnat(devfd, filename);
333                                 else if (ns == 1)
334                                         err = readstate(devfd, filename);
335                         }
336                 }
337         }
338         return err;
339 }
340
341
342 int opendevice(ipfdev)
343 char *ipfdev;
344 {
345         int fd = -1;
346
347         if (opts & OPT_DONOTHING)
348                 return -2;
349
350         if (!ipfdev)
351                 ipfdev = IPL_NAME;
352
353         if ((fd = open(ipfdev, O_RDWR)) == -1)
354                 if ((fd = open(ipfdev, O_RDONLY)) == -1)
355                         perror("open device");
356         return fd;
357 }
358
359
360 void closedevice(fd)
361 int fd;
362 {
363         close(fd);
364 }
365
366
367 int setlock(fd, lock)
368 int fd, lock;
369 {
370         if (opts & OPT_VERBOSE)
371                 printf("Turn lock %s\n", lock ? "on" : "off");
372         if (!(opts & OPT_DONOTHING)) {
373                 if (ioctl(fd, SIOCSTLCK, &lock) == -1) {
374                         perror("SIOCSTLCK");
375                         return 1;
376                 }
377                 if (opts & OPT_VERBOSE)
378                         printf("Lock now %s\n", lock ? "on" : "off");
379         }
380         return 0;
381 }
382
383
384 int writestate(fd, file)
385 int fd;
386 char *file;
387 {
388         ipstate_save_t ips, *ipsp;
389         ipfobj_t obj;
390         int wfd = -1;
391
392         if (!file)
393                 file = IPF_STATEFILE;
394
395         wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
396         if (wfd == -1) {
397                 fprintf(stderr, "%s ", file);
398                 perror("state:open");
399                 return 1;
400         }
401
402         ipsp = &ips;
403         bzero((char *)&obj, sizeof(obj));
404         bzero((char *)ipsp, sizeof(ips));
405
406         obj.ipfo_rev = IPFILTER_VERSION;
407         obj.ipfo_size = sizeof(*ipsp);
408         obj.ipfo_type = IPFOBJ_STATESAVE;
409         obj.ipfo_ptr = ipsp;
410
411         do {
412
413                 if (opts & OPT_VERBOSE)
414                         printf("Getting state from addr %p\n", ips.ips_next);
415                 if (ioctl(fd, SIOCSTGET, &obj)) {
416                         if (errno == ENOENT)
417                                 break;
418                         perror("state:SIOCSTGET");
419                         close(wfd);
420                         return 1;
421                 }
422                 if (opts & OPT_VERBOSE)
423                         printf("Got state next %p\n", ips.ips_next);
424                 if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) {
425                         perror("state:write");
426                         close(wfd);
427                         return 1;
428                 }
429         } while (ips.ips_next != NULL);
430         close(wfd);
431
432         return 0;
433 }
434
435
436 int readstate(fd, file)
437 int fd;
438 char *file;
439 {
440         ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL;
441         int sfd = -1, i;
442         ipfobj_t obj;
443
444         if (!file)
445                 file = IPF_STATEFILE;
446
447         sfd = open(file, O_RDONLY, 0600);
448         if (sfd == -1) {
449                 fprintf(stderr, "%s ", file);
450                 perror("open");
451                 return 1;
452         }
453
454         bzero((char *)&ips, sizeof(ips));
455
456         /*
457          * 1. Read all state information in.
458          */
459         do {
460                 i = read(sfd, &ips, sizeof(ips));
461                 if (i == -1) {
462                         perror("read");
463                         close(sfd);
464                         return 1;
465                 }
466                 if (i == 0)
467                         break;
468                 if (i != sizeof(ips)) {
469                         fprintf(stderr, "state:incomplete read: %d != %d\n",
470                                 i, (int)sizeof(ips));
471                         close(sfd);
472                         return 1;
473                 }
474                 is = (ipstate_save_t *)malloc(sizeof(*is));
475                 if(!is) {
476                         fprintf(stderr, "malloc failed\n");
477                         return 1;
478                 }
479
480                 bcopy((char *)&ips, (char *)is, sizeof(ips));
481
482                 /*
483                  * Check to see if this is the first state entry that will
484                  * reference a particular rule and if so, flag it as such
485                  * else just adjust the rule pointer to become a pointer to
486                  * the other.  We do this so we have a means later for tracking
487                  * who is referencing us when we get back the real pointer
488                  * in is_rule after doing the ioctl.
489                  */
490                 for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next)
491                         if (is1->ips_rule == is->ips_rule)
492                                 break;
493                 if (is1 == NULL)
494                         is->ips_is.is_flags |= SI_NEWFR;
495                 else
496                         is->ips_rule = (void *)&is1->ips_rule;
497
498                 /*
499                  * Use a tail-queue type list (add things to the end)..
500                  */
501                 is->ips_next = NULL;
502                 if (!ipshead)
503                         ipshead = is;
504                 if (ipstail)
505                         ipstail->ips_next = is;
506                 ipstail = is;
507         } while (1);
508
509         close(sfd);
510
511         obj.ipfo_rev = IPFILTER_VERSION;
512         obj.ipfo_size = sizeof(*is);
513         obj.ipfo_type = IPFOBJ_STATESAVE;
514
515         for (is = ipshead; is; is = is->ips_next) {
516                 if (opts & OPT_VERBOSE)
517                         printf("Loading new state table entry\n");
518                 if (is->ips_is.is_flags & SI_NEWFR) {
519                         if (opts & OPT_VERBOSE)
520                                 printf("Loading new filter rule\n");
521                 }
522
523                 obj.ipfo_ptr = is;
524                 if (!(opts & OPT_DONOTHING))
525                         if (ioctl(fd, SIOCSTPUT, &obj)) {
526                                 perror("SIOCSTPUT");
527                                 return 1;
528                         }
529
530                 if (is->ips_is.is_flags & SI_NEWFR) {
531                         if (opts & OPT_VERBOSE)
532                                 printf("Real rule addr %p\n", is->ips_rule);
533                         for (is1 = is->ips_next; is1; is1 = is1->ips_next)
534                                 if (is1->ips_rule == (frentry_t *)&is->ips_rule)
535                                         is1->ips_rule = is->ips_rule;
536                 }
537         }
538
539         return 0;
540 }
541
542
543 int readnat(fd, file)
544 int fd;
545 char *file;
546 {
547         nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL;
548         ipfobj_t obj;
549         int nfd, i;
550         nat_t *nat;
551         char *s;
552         int n;
553
554         nfd = -1;
555         in = NULL;
556         ipnhead = NULL;
557         ipntail = NULL;
558
559         if (!file)
560                 file = IPF_NATFILE;
561
562         nfd = open(file, O_RDONLY);
563         if (nfd == -1) {
564                 fprintf(stderr, "%s ", file);
565                 perror("nat:open");
566                 return 1;
567         }
568
569         bzero((char *)&ipn, sizeof(ipn));
570
571         /*
572          * 1. Read all state information in.
573          */
574         do {
575                 i = read(nfd, &ipn, sizeof(ipn));
576                 if (i == -1) {
577                         perror("read");
578                         close(nfd);
579                         return 1;
580                 }
581                 if (i == 0)
582                         break;
583                 if (i != sizeof(ipn)) {
584                         fprintf(stderr, "nat:incomplete read: %d != %d\n",
585                                 i, (int)sizeof(ipn));
586                         close(nfd);
587                         return 1;
588                 }
589
590                 in = (nat_save_t *)malloc(ipn.ipn_dsize);
591                 if (!in)
592                         break;
593
594                 if (ipn.ipn_dsize > sizeof(ipn)) {
595                         n = ipn.ipn_dsize - sizeof(ipn);
596                         if (n > 0) {
597                                 s = in->ipn_data + sizeof(in->ipn_data);
598                                 i = read(nfd, s, n);
599                                 if (i == 0)
600                                         break;
601                                 if (i != n) {
602                                         fprintf(stderr,
603                                             "nat:incomplete read: %d != %d\n",
604                                             i, n);
605                                         close(nfd);
606                                         return 1;
607                                 }
608                         }
609                 }
610                 bcopy((char *)&ipn, (char *)in, sizeof(ipn));
611
612                 /*
613                  * Check to see if this is the first NAT entry that will
614                  * reference a particular rule and if so, flag it as such
615                  * else just adjust the rule pointer to become a pointer to
616                  * the other.  We do this so we have a means later for tracking
617                  * who is referencing us when we get back the real pointer
618                  * in is_rule after doing the ioctl.
619                  */
620                 nat = &in->ipn_nat;
621                 if (nat->nat_fr != NULL) {
622                         for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next)
623                                 if (in1->ipn_rule == nat->nat_fr)
624                                         break;
625                         if (in1 == NULL)
626                                 nat->nat_flags |= SI_NEWFR;
627                         else
628                                 nat->nat_fr = &in1->ipn_fr;
629                 }
630
631                 /*
632                  * Use a tail-queue type list (add things to the end)..
633                  */
634                 in->ipn_next = NULL;
635                 if (!ipnhead)
636                         ipnhead = in;
637                 if (ipntail)
638                         ipntail->ipn_next = in;
639                 ipntail = in;
640         } while (1);
641
642         close(nfd);
643         nfd = -1;
644
645         obj.ipfo_rev = IPFILTER_VERSION;
646         obj.ipfo_type = IPFOBJ_NATSAVE;
647
648         for (in = ipnhead; in; in = in->ipn_next) {
649                 if (opts & OPT_VERBOSE)
650                         printf("Loading new NAT table entry\n");
651                 nat = &in->ipn_nat;
652                 if (nat->nat_flags & SI_NEWFR) {
653                         if (opts & OPT_VERBOSE)
654                                 printf("Loading new filter rule\n");
655                 }
656
657                 obj.ipfo_ptr = in;
658                 obj.ipfo_size = in->ipn_dsize;
659                 if (!(opts & OPT_DONOTHING))
660                         if (ioctl(fd, SIOCSTPUT, &obj)) {
661                                 fprintf(stderr, "in=%p:", in);
662                                 perror("SIOCSTPUT");
663                                 return 1;
664                         }
665
666                 if (nat->nat_flags & SI_NEWFR) {
667                         if (opts & OPT_VERBOSE)
668                                 printf("Real rule addr %p\n", nat->nat_fr);
669                         for (in1 = in->ipn_next; in1; in1 = in1->ipn_next)
670                                 if (in1->ipn_rule == &in->ipn_fr)
671                                         in1->ipn_rule = nat->nat_fr;
672                 }
673         }
674
675         return 0;
676 }
677
678
679 int writenat(fd, file)
680 int fd;
681 char *file;
682 {
683         nat_save_t *ipnp = NULL, *next = NULL;
684         ipfobj_t obj;
685         int nfd = -1;
686         natget_t ng;
687
688         if (!file)
689                 file = IPF_NATFILE;
690
691         nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
692         if (nfd == -1) {
693                 fprintf(stderr, "%s ", file);
694                 perror("nat:open");
695                 return 1;
696         }
697
698         obj.ipfo_rev = IPFILTER_VERSION;
699         obj.ipfo_type = IPFOBJ_NATSAVE;
700
701         do {
702                 if (opts & OPT_VERBOSE)
703                         printf("Getting nat from addr %p\n", ipnp);
704                 ng.ng_ptr = next;
705                 ng.ng_sz = 0;
706                 if (ioctl(fd, SIOCSTGSZ, &ng)) {
707                         perror("nat:SIOCSTGSZ");
708                         close(nfd);
709                         if (ipnp != NULL)
710                                 free(ipnp);
711                         return 1;
712                 }
713
714                 if (opts & OPT_VERBOSE)
715                         printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr);
716
717                 if (ng.ng_sz == 0)
718                         break;
719
720                 if (!ipnp)
721                         ipnp = malloc(ng.ng_sz);
722                 else
723                         ipnp = realloc((char *)ipnp, ng.ng_sz);
724                 if (!ipnp) {
725                         fprintf(stderr,
726                                 "malloc for %d bytes failed\n", ng.ng_sz);
727                         break;
728                 }
729
730                 bzero((char *)ipnp, ng.ng_sz);
731                 obj.ipfo_size = ng.ng_sz;
732                 obj.ipfo_ptr = ipnp;
733                 ipnp->ipn_dsize = ng.ng_sz;
734                 ipnp->ipn_next = next;
735                 if (ioctl(fd, SIOCSTGET, &obj)) {
736                         if (errno == ENOENT)
737                                 break;
738                         perror("nat:SIOCSTGET");
739                         close(nfd);
740                         free(ipnp);
741                         return 1;
742                 }
743
744                 if (opts & OPT_VERBOSE)
745                         printf("Got nat next %p ipn_dsize %d ng_sz %d\n",
746                                 ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz);
747                 if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) {
748                         perror("nat:write");
749                         close(nfd);
750                         free(ipnp);
751                         return 1;
752                 }
753                 next = ipnp->ipn_next;
754         } while (ipnp && next);
755         if (ipnp != NULL)
756                 free(ipnp);
757         close(nfd);
758
759         return 0;
760 }
761
762
763 int writeall(dirname)
764 char *dirname;
765 {
766         int fd, devfd;
767
768         if (!dirname)
769                 dirname = IPF_SAVEDIR;
770
771         if (chdir(dirname)) {
772                 fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname);
773                 perror("chdir(IPF_SAVEDIR)");
774                 return 1;
775         }
776
777         fd = opendevice(NULL);
778         if (fd == -1)
779                 return 1;
780         if (setlock(fd, 1)) {
781                 close(fd);
782                 return 1;
783         }
784
785         devfd = opendevice(IPSTATE_NAME);
786         if (devfd == -1)
787                 goto bad;
788         if (writestate(devfd, NULL))
789                 goto bad;
790         close(devfd);
791
792         devfd = opendevice(IPNAT_NAME);
793         if (devfd == -1)
794                 goto bad;
795         if (writenat(devfd, NULL))
796                 goto bad;
797         close(devfd);
798
799         if (setlock(fd, 0)) {
800                 close(fd);
801                 return 1;
802         }
803
804         close(fd);
805         return 0;
806
807 bad:
808         setlock(fd, 0);
809         close(fd);
810         return 1;
811 }
812
813
814 int readall(dirname)
815 char *dirname;
816 {
817         int fd, devfd;
818
819         if (!dirname)
820                 dirname = IPF_SAVEDIR;
821
822         if (chdir(dirname)) {
823                 perror("chdir(IPF_SAVEDIR)");
824                 return 1;
825         }
826
827         fd = opendevice(NULL);
828         if (fd == -1)
829                 return 1;
830         if (setlock(fd, 1)) {
831                 close(fd);
832                 return 1;
833         }
834
835         devfd = opendevice(IPSTATE_NAME);
836         if (devfd == -1)
837                 return 1;
838         if (readstate(devfd, NULL))
839                 return 1;
840         close(devfd);
841
842         devfd = opendevice(IPNAT_NAME);
843         if (devfd == -1)
844                 return 1;
845         if (readnat(devfd, NULL))
846                 return 1;
847         close(devfd);
848
849         if (setlock(fd, 0)) {
850                 close(fd);
851                 return 1;
852         }
853
854         return 0;
855 }