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