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