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