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