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