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