1/* $NetBSD: ipfs.c,v 1.9 2007/05/01 19:08:04 martti Exp $ */ 2 3/* 4 * Copyright (C) 2001-2006 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 const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56: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) 103char *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) 166char *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 (!strncmp(nat->nat_ifnames[2], ifs, olen + 1)) { 202 strcpy(nat->nat_ifnames[2], s); 203 rw = 1; 204 } 205 if (!strncmp(nat->nat_ifnames[3], ifs, olen + 1)) { 206 strcpy(nat->nat_ifnames[3], s); 207 rw = 1; 208 } 209 if (rw == 1) { 210 if (lseek(fd, pos, SEEK_SET) != pos) { 211 perror("lseek"); 212 exit(1); 213 } 214 if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) { 215 perror("write"); 216 exit(1); 217 } 218 } 219 pos = lseek(fd, 0, SEEK_CUR); 220 } 221 close(fd); 222 223 return 0; 224} 225 226 227int main(argc,argv) 228int argc; 229char *argv[]; 230{ 231 int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0; 232 char *dirname = NULL, *filename = NULL, *ifs = NULL; 233 234 progname = argv[0]; 235 while ((c = getopt(argc, argv, "d:f:i:lNnSRruvWw")) != -1) 236 switch (c) 237 { 238 case 'd' : 239 if ((set == 0) && !dirname && !filename) 240 dirname = optarg; 241 else 242 usage(); 243 break; 244 case 'f' : 245 if ((set != 0) && !dirname && !filename) 246 filename = optarg; 247 else 248 usage(); 249 break; 250 case 'i' : 251 ifs = optarg; 252 set = 1; 253 break; 254 case 'l' : 255 if (filename || dirname || set) 256 usage(); 257 lock = 1; 258 set = 1; 259 break; 260 case 'n' : 261 opts |= OPT_DONOTHING; 262 break; 263 case 'N' : 264 if ((ns >= 0) || dirname || (rw != -1) || set) 265 usage(); 266 ns = 0; 267 set = 1; 268 break; 269 case 'r' : 270 if (dirname || (rw != -1) || (ns == -1)) 271 usage(); 272 rw = 0; 273 set = 1; 274 break; 275 case 'R' : 276 rw = 2; 277 set = 1; 278 break; 279 case 'S' : 280 if ((ns >= 0) || dirname || (rw != -1) || set) 281 usage(); 282 ns = 1; 283 set = 1; 284 break; 285 case 'u' : 286 if (filename || dirname || set) 287 usage(); 288 lock = 0; 289 set = 1; 290 break; 291 case 'v' : 292 opts |= OPT_VERBOSE; 293 break; 294 case 'w' : 295 if (dirname || (rw != -1) || (ns == -1)) 296 usage(); 297 rw = 1; 298 set = 1; 299 break; 300 case 'W' : 301 rw = 3; 302 set = 1; 303 break; 304 case '?' : 305 default : 306 usage(); 307 } 308 309 if (ifs) { 310 if (!filename || ns < 0) 311 usage(); 312 if (ns == 0) 313 return changenatif(ifs, filename); 314 else 315 return changestateif(ifs, filename); 316 } 317 318 if ((ns >= 0) || (lock >= 0)) { 319 if (lock >= 0) 320 devfd = opendevice(NULL); 321 else if (ns >= 0) { 322 if (ns == 1) 323 devfd = opendevice(IPSTATE_NAME); 324 else if (ns == 0) 325 devfd = opendevice(IPNAT_NAME); 326 } 327 if (devfd == -1) 328 exit(1); 329 } 330 331 if (lock >= 0) 332 err = setlock(devfd, lock); 333 else if (rw >= 0) { 334 if (rw & 1) { /* WRITE */ 335 if (rw & 2) 336 err = writeall(dirname); 337 else { 338 if (ns == 0) 339 err = writenat(devfd, filename); 340 else if (ns == 1) 341 err = writestate(devfd, filename); 342 } 343 } else { 344 if (rw & 2) 345 err = readall(dirname); 346 else { 347 if (ns == 0) 348 err = readnat(devfd, filename); 349 else if (ns == 1) 350 err = readstate(devfd, filename); 351 } 352 } 353 } 354 return err; 355} 356 357 358int opendevice(ipfdev) 359char *ipfdev; 360{ 361 int fd = -1; 362 363 if (opts & OPT_DONOTHING) 364 return -2; 365 366 if (!ipfdev) 367 ipfdev = IPL_NAME; 368 369 if ((fd = open(ipfdev, O_RDWR)) == -1) 370 if ((fd = open(ipfdev, O_RDONLY)) == -1) 371 perror("open device"); 372 return fd; 373} 374 375 376void closedevice(fd) 377int fd; 378{ 379 close(fd); 380} 381 382 383int setlock(fd, lock) 384int fd, lock; 385{ 386 if (opts & OPT_VERBOSE) 387 printf("Turn lock %s\n", lock ? "on" : "off"); 388 if (!(opts & OPT_DONOTHING)) { 389 if (ioctl(fd, SIOCSTLCK, &lock) == -1) { 390 perror("SIOCSTLCK"); 391 return 1; 392 } 393 if (opts & OPT_VERBOSE) 394 printf("Lock now %s\n", lock ? "on" : "off"); 395 } 396 return 0; 397} 398 399 400int writestate(fd, file) 401int fd; 402char *file; 403{ 404 ipstate_save_t ips, *ipsp; 405 ipfobj_t obj; 406 int wfd = -1; 407 408 if (!file) 409 file = IPF_STATEFILE; 410 411 wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); 412 if (wfd == -1) { 413 fprintf(stderr, "%s ", file); 414 perror("state:open"); 415 return 1; 416 } 417 418 ipsp = &ips; 419 bzero((char *)&obj, sizeof(obj)); 420 bzero((char *)ipsp, sizeof(ips)); 421 422 obj.ipfo_rev = IPFILTER_VERSION; 423 obj.ipfo_size = sizeof(*ipsp); 424 obj.ipfo_type = IPFOBJ_STATESAVE; 425 obj.ipfo_ptr = ipsp; 426 427 do { 428 429 if (opts & OPT_VERBOSE) 430 printf("Getting state from addr %p\n", ips.ips_next); 431 if (ioctl(fd, SIOCSTGET, &obj)) { 432 if (errno == ENOENT) 433 break; 434 perror("state:SIOCSTGET"); 435 close(wfd); 436 return 1; 437 } 438 if (opts & OPT_VERBOSE) 439 printf("Got state next %p\n", ips.ips_next); 440 if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) { 441 perror("state:write"); 442 close(wfd); 443 return 1; 444 } 445 } while (ips.ips_next != NULL); 446 close(wfd); 447 448 return 0; 449} 450 451 452int readstate(fd, file) 453int fd; 454char *file; 455{ 456 ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL; 457 int sfd = -1, i; 458 ipfobj_t obj; 459 460 if (!file) 461 file = IPF_STATEFILE; 462 463 sfd = open(file, O_RDONLY, 0600); 464 if (sfd == -1) { 465 fprintf(stderr, "%s ", file); 466 perror("open"); 467 return 1; 468 } 469 470 bzero((char *)&ips, sizeof(ips)); 471 472 /* 473 * 1. Read all state information in. 474 */ 475 do { 476 i = read(sfd, &ips, sizeof(ips)); 477 if (i == -1) { 478 perror("read"); 479 goto freeipshead; 480 } 481 if (i == 0) 482 break; 483 if (i != sizeof(ips)) { 484 fprintf(stderr, "state:incomplete read: %d != %d\n", 485 i, (int)sizeof(ips)); 486 goto freeipshead; 487 } 488 is = (ipstate_save_t *)malloc(sizeof(*is)); 489 if (is == NULL) { 490 fprintf(stderr, "malloc failed\n"); 491 goto freeipshead; 492 } 493 494 bcopy((char *)&ips, (char *)is, sizeof(ips)); 495 496 /* 497 * Check to see if this is the first state entry that will 498 * reference a particular rule and if so, flag it as such 499 * else just adjust the rule pointer to become a pointer to 500 * the other. We do this so we have a means later for tracking 501 * who is referencing us when we get back the real pointer 502 * in is_rule after doing the ioctl. 503 */ 504 for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next) 505 if (is1->ips_rule == is->ips_rule) 506 break; 507 if (is1 == NULL) 508 is->ips_is.is_flags |= SI_NEWFR; 509 else 510 is->ips_rule = (void *)&is1->ips_rule; 511 512 /* 513 * Use a tail-queue type list (add things to the end).. 514 */ 515 is->ips_next = NULL; 516 if (!ipshead) 517 ipshead = is; 518 if (ipstail) 519 ipstail->ips_next = is; 520 ipstail = is; 521 } while (1); 522 523 close(sfd); 524 525 obj.ipfo_rev = IPFILTER_VERSION; 526 obj.ipfo_size = sizeof(*is); 527 obj.ipfo_type = IPFOBJ_STATESAVE; 528 529 while ((is = ipshead) != NULL) { 530 if (opts & OPT_VERBOSE) 531 printf("Loading new state table entry\n"); 532 if (is->ips_is.is_flags & SI_NEWFR) { 533 if (opts & OPT_VERBOSE) 534 printf("Loading new filter rule\n"); 535 } 536 537 obj.ipfo_ptr = is; 538 if (!(opts & OPT_DONOTHING)) 539 if (ioctl(fd, SIOCSTPUT, &obj)) { 540 perror("SIOCSTPUT"); 541 goto freeipshead; 542 } 543 544 if (is->ips_is.is_flags & SI_NEWFR) { 545 if (opts & OPT_VERBOSE) 546 printf("Real rule addr %p\n", is->ips_rule); 547 for (is1 = is->ips_next; is1; is1 = is1->ips_next) 548 if (is1->ips_rule == (frentry_t *)&is->ips_rule) 549 is1->ips_rule = is->ips_rule; 550 } 551 552 ipshead = is->ips_next; 553 free(is); 554 } 555 556 return 0; 557 558freeipshead: 559 while ((is = ipshead) != NULL) { 560 ipshead = is->ips_next; 561 free(is); 562 } 563 if (sfd != -1) 564 close(sfd); 565 return 1; 566} 567 568 569int readnat(fd, file) 570int fd; 571char *file; 572{ 573 nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL; 574 ipfobj_t obj; 575 int nfd, i; 576 nat_t *nat; 577 char *s; 578 int n; 579 580 nfd = -1; 581 in = NULL; 582 ipnhead = NULL; 583 ipntail = NULL; 584 585 if (!file) 586 file = IPF_NATFILE; 587 588 nfd = open(file, O_RDONLY); 589 if (nfd == -1) { 590 fprintf(stderr, "%s ", file); 591 perror("nat:open"); 592 return 1; 593 } 594 595 bzero((char *)&ipn, sizeof(ipn)); 596 597 /* 598 * 1. Read all state information in. 599 */ 600 do { 601 i = read(nfd, &ipn, sizeof(ipn)); 602 if (i == -1) { 603 perror("read"); 604 goto freenathead; 605 } 606 if (i == 0) 607 break; 608 if (i != sizeof(ipn)) { 609 fprintf(stderr, "nat:incomplete read: %d != %d\n", 610 i, (int)sizeof(ipn)); 611 goto freenathead; 612 } 613 614 in = (nat_save_t *)malloc(ipn.ipn_dsize); 615 if (in == NULL) { 616 fprintf(stderr, "nat:cannot malloc nat save atruct\n"); 617 goto freenathead; 618 } 619 620 if (ipn.ipn_dsize > sizeof(ipn)) { 621 n = ipn.ipn_dsize - sizeof(ipn); 622 if (n > 0) { 623 s = in->ipn_data + sizeof(in->ipn_data); 624 i = read(nfd, s, n); 625 if (i == 0) 626 break; 627 if (i != n) { 628 fprintf(stderr, 629 "nat:incomplete read: %d != %d\n", 630 i, n); 631 goto freenathead; 632 } 633 } 634 } 635 bcopy((char *)&ipn, (char *)in, sizeof(ipn)); 636 637 /* 638 * Check to see if this is the first NAT entry that will 639 * reference a particular rule and if so, flag it as such 640 * else just adjust the rule pointer to become a pointer to 641 * the other. We do this so we have a means later for tracking 642 * who is referencing us when we get back the real pointer 643 * in is_rule after doing the ioctl. 644 */ 645 nat = &in->ipn_nat; 646 if (nat->nat_fr != NULL) { 647 for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next) 648 if (in1->ipn_rule == nat->nat_fr) 649 break; 650 if (in1 == NULL) 651 nat->nat_flags |= SI_NEWFR; 652 else 653 nat->nat_fr = &in1->ipn_fr; 654 } 655 656 /* 657 * Use a tail-queue type list (add things to the end).. 658 */ 659 in->ipn_next = NULL; 660 if (!ipnhead) 661 ipnhead = in; 662 if (ipntail) 663 ipntail->ipn_next = in; 664 ipntail = in; 665 } while (1); 666 667 close(nfd); 668 nfd = -1; 669 670 obj.ipfo_rev = IPFILTER_VERSION; 671 obj.ipfo_type = IPFOBJ_NATSAVE; 672 673 while ((in = ipnhead) != NULL) { 674 if (opts & OPT_VERBOSE) 675 printf("Loading new NAT table entry\n"); 676 nat = &in->ipn_nat; 677 if (nat->nat_flags & SI_NEWFR) { 678 if (opts & OPT_VERBOSE) 679 printf("Loading new filter rule\n"); 680 } 681 682 obj.ipfo_ptr = in; 683 obj.ipfo_size = in->ipn_dsize; 684 if (!(opts & OPT_DONOTHING)) 685 if (ioctl(fd, SIOCSTPUT, &obj)) { 686 fprintf(stderr, "in=%p:", in); 687 perror("SIOCSTPUT"); 688 return 1; 689 } 690 691 if (nat->nat_flags & SI_NEWFR) { 692 if (opts & OPT_VERBOSE) 693 printf("Real rule addr %p\n", nat->nat_fr); 694 for (in1 = in->ipn_next; in1; in1 = in1->ipn_next) 695 if (in1->ipn_rule == &in->ipn_fr) 696 in1->ipn_rule = nat->nat_fr; 697 } 698 699 ipnhead = in->ipn_next; 700 free(in); 701 } 702 703 return 0; 704 705freenathead: 706 while ((in = ipnhead) != NULL) { 707 ipnhead = in->ipn_next; 708 free(in); 709 } 710 if (nfd != -1) 711 close(nfd); 712 return 1; 713} 714 715 716int writenat(fd, file) 717int fd; 718char *file; 719{ 720 nat_save_t *ipnp = NULL, *next = NULL; 721 ipfobj_t obj; 722 int nfd = -1; 723 natget_t ng; 724 725 if (!file) 726 file = IPF_NATFILE; 727 728 nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); 729 if (nfd == -1) { 730 fprintf(stderr, "%s ", file); 731 perror("nat:open"); 732 return 1; 733 } 734 735 obj.ipfo_rev = IPFILTER_VERSION; 736 obj.ipfo_type = IPFOBJ_NATSAVE; 737 738 do { 739 if (opts & OPT_VERBOSE) 740 printf("Getting nat from addr %p\n", ipnp); 741 ng.ng_ptr = next; 742 ng.ng_sz = 0; 743 if (ioctl(fd, SIOCSTGSZ, &ng)) { 744 perror("nat:SIOCSTGSZ"); 745 close(nfd); 746 if (ipnp != NULL) 747 free(ipnp); 748 return 1; 749 } 750 751 if (opts & OPT_VERBOSE) 752 printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr); 753 754 if (ng.ng_sz == 0) 755 break; 756 757 if (!ipnp) 758 ipnp = malloc(ng.ng_sz); 759 else 760 ipnp = realloc((char *)ipnp, ng.ng_sz); 761 if (!ipnp) { 762 fprintf(stderr, 763 "malloc for %d bytes failed\n", ng.ng_sz); 764 break; 765 } 766 767 bzero((char *)ipnp, ng.ng_sz); 768 obj.ipfo_size = ng.ng_sz; 769 obj.ipfo_ptr = ipnp; 770 ipnp->ipn_dsize = ng.ng_sz; 771 ipnp->ipn_next = next; 772 if (ioctl(fd, SIOCSTGET, &obj)) { 773 if (errno == ENOENT) 774 break; 775 perror("nat:SIOCSTGET"); 776 close(nfd); 777 free(ipnp); 778 return 1; 779 } 780 781 if (opts & OPT_VERBOSE) 782 printf("Got nat next %p ipn_dsize %d ng_sz %d\n", 783 ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz); 784 if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) { 785 perror("nat:write"); 786 close(nfd); 787 free(ipnp); 788 return 1; 789 } 790 next = ipnp->ipn_next; 791 } while (ipnp && next); 792 if (ipnp != NULL) 793 free(ipnp); 794 close(nfd); 795 796 return 0; 797} 798 799 800int writeall(dirname) 801char *dirname; 802{ 803 int fd, devfd; 804 805 if (!dirname) 806 dirname = IPF_SAVEDIR; 807 808 if (chdir(dirname)) { 809 fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname); 810 perror("chdir(IPF_SAVEDIR)"); 811 return 1; 812 } 813 814 fd = opendevice(NULL); 815 if (fd == -1) 816 return 1; 817 if (setlock(fd, 1)) { 818 close(fd); 819 return 1; 820 } 821 822 devfd = opendevice(IPSTATE_NAME); 823 if (devfd == -1) 824 goto bad; 825 if (writestate(devfd, NULL)) 826 goto bad; 827 close(devfd); 828 829 devfd = opendevice(IPNAT_NAME); 830 if (devfd == -1) 831 goto bad; 832 if (writenat(devfd, NULL)) 833 goto bad; 834 close(devfd); 835 836 if (setlock(fd, 0)) { 837 close(fd); 838 return 1; 839 } 840 841 close(fd); 842 return 0; 843 844bad: 845 setlock(fd, 0); 846 close(fd); 847 return 1; 848} 849 850 851int readall(dirname) 852char *dirname; 853{ 854 int fd, devfd; 855 856 if (!dirname) 857 dirname = IPF_SAVEDIR; 858 859 if (chdir(dirname)) { 860 perror("chdir(IPF_SAVEDIR)"); 861 return 1; 862 } 863 864 fd = opendevice(NULL); 865 if (fd == -1) 866 return 1; 867 if (setlock(fd, 1)) { 868 close(fd); 869 return 1; 870 } 871 872 devfd = opendevice(IPSTATE_NAME); 873 if (devfd == -1) 874 return 1; 875 if (readstate(devfd, NULL)) 876 return 1; 877 close(devfd); 878 879 devfd = opendevice(IPNAT_NAME); 880 if (devfd == -1) 881 return 1; 882 if (readnat(devfd, NULL)) 883 return 1; 884 close(devfd); 885 886 if (setlock(fd, 0)) { 887 close(fd); 888 return 1; 889 } 890 891 return 0; 892} 893