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