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