1 /* 2 * natd - Network Address Translation Daemon for FreeBSD. 3 * 4 * This software is provided free of charge, with no 5 * warranty of any kind, either expressed or implied. 6 * Use at your own risk. 7 * 8 * You may copy, modify and distribute this software (natd.c) freely. 9 * 10 * Ari Suutari <suutari@iki.fi> 11 * 12 * $FreeBSD: src/sbin/natd/natd.c,v 1.25.2.5 2002/02/01 09:18:32 ru Exp $ 13 */ 14 15 #define SYSLOG_NAMES 16 17 #include <sys/param.h> 18 #include <sys/socket.h> 19 #include <sys/sysctl.h> 20 #include <sys/time.h> 21 22 #include <netinet/in.h> 23 #include <netinet/in_systm.h> 24 #include <netinet/ip.h> 25 #include <netinet/tcp.h> 26 #include <netinet/udp.h> 27 #include <netinet/ip_icmp.h> 28 #include <net/if.h> 29 #include <net/if_dl.h> 30 #include <net/route.h> 31 #include <arpa/inet.h> 32 33 #include <alias.h> 34 #include <ctype.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <netdb.h> 38 #include <signal.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <syslog.h> 43 #include <unistd.h> 44 45 #include "natd.h" 46 47 /* 48 * Default values for input and output 49 * divert socket ports. 50 */ 51 52 #define DEFAULT_SERVICE "natd" 53 54 /* 55 * Definition of a port range, and macros to deal with values. 56 * FORMAT: HI 16-bits == first port in range, 0 == all ports. 57 * LO 16-bits == number of ports in range 58 * NOTES: - Port values are not stored in network byte order. 59 */ 60 61 typedef u_long port_range; 62 63 #define GETLOPORT(x) ((x) >> 0x10) 64 #define GETNUMPORTS(x) ((x) & 0x0000ffff) 65 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x))) 66 67 /* Set y to be the low-port value in port_range variable x. */ 68 #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10)) 69 70 /* Set y to be the number of ports in port_range variable x. */ 71 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y)) 72 73 /* 74 * Function prototypes. 75 */ 76 77 static void DoAliasing(int, int); 78 static void DaemonMode(void); 79 static void HandleRoutingInfo(int); 80 static void Usage(void); 81 static char* FormatPacket(struct ip *); 82 static void PrintPacket(struct ip *); 83 static void SyslogPacket(struct ip *, int, const char *); 84 static void SetAliasAddressFromIfName(const char *); 85 static void InitiateShutdown(int); 86 static void Shutdown(int); 87 static void RefreshAddr(int); 88 static void ParseOption(const char *, const char *); 89 static void ReadConfigFile(const char *); 90 static void SetupPortRedirect(const char *); 91 static void SetupProtoRedirect(const char *); 92 static void SetupAddressRedirect(const char *); 93 static void StrToAddr(const char *, struct in_addr *); 94 static u_short StrToPort(const char *, const char *); 95 static int StrToPortRange(const char *, const char *, port_range *); 96 static int StrToProto(const char *); 97 static int StrToAddrAndPortRange(const char *, struct in_addr *, char *, port_range *); 98 static void ParseArgs(int, char **); 99 static void SetupPunchFW(const char *); 100 101 /* 102 * Globals. 103 */ 104 105 static int verbose; 106 static int background; 107 static volatile sig_atomic_t running; 108 static volatile sig_atomic_t assignAliasAddr; 109 static char* ifName; 110 static int ifIndex; 111 static u_short inPort; 112 static u_short outPort; 113 static u_short inOutPort; 114 static struct in_addr aliasAddr; 115 static int dynamicMode; 116 static int ifMTU; 117 static int aliasOverhead; 118 static int icmpSock; 119 static int dropIgnoredIncoming; 120 static int logDropped; 121 static int logFacility; 122 static int logIpfwDenied; 123 static int exitDelay; 124 125 int 126 main(int argc, char **argv) 127 { 128 int divertIn; 129 int divertOut; 130 int divertInOut; 131 int routeSock; 132 struct sockaddr_in addr; 133 fd_set readMask; 134 int fdMax; 135 struct sigaction sa; 136 /* 137 * Initialize packet aliasing software. 138 * Done already here to be able to alter option bits 139 * during command line and configuration file processing. 140 */ 141 PacketAliasInit(); 142 /* 143 * Parse options. 144 */ 145 inPort = 0; 146 outPort = 0; 147 verbose = 0; 148 inOutPort = 0; 149 ifName = NULL; 150 ifMTU = -1; 151 background = 0; 152 running = 1; 153 assignAliasAddr = 0; 154 aliasAddr.s_addr = INADDR_NONE; 155 aliasOverhead = 12; 156 dynamicMode = 0; 157 logDropped = 0; 158 logFacility = LOG_DAEMON; 159 logIpfwDenied = -1; 160 exitDelay = EXIT_DELAY; 161 162 ParseArgs(argc, argv); 163 /* 164 * Log ipfw(8) denied packets by default in verbose mode. 165 */ 166 if (logIpfwDenied == -1) 167 logIpfwDenied = verbose; 168 /* 169 * Open syslog channel. 170 */ 171 openlog("natd", LOG_CONS | LOG_PID | (verbose ? LOG_PERROR : 0), 172 logFacility); 173 /* 174 * Check that valid aliasing address has been given. 175 */ 176 if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL) 177 errx(1, "aliasing address not given"); 178 179 if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL) 180 errx(1, "both alias address and interface " 181 "name are not allowed"); 182 /* 183 * Check that valid port number is known. 184 */ 185 if (inPort != 0 || outPort != 0) 186 if (inPort == 0 || outPort == 0) 187 errx(1, "both input and output ports are required"); 188 189 if (inPort == 0 && outPort == 0 && inOutPort == 0) 190 ParseOption("port", DEFAULT_SERVICE); 191 192 /* 193 * Check if ignored packets should be dropped. 194 */ 195 dropIgnoredIncoming = PacketAliasSetMode(0, 0); 196 dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING; 197 /* 198 * Create divert sockets. Use only one socket if -p was specified 199 * on command line. Otherwise, create separate sockets for 200 * outgoing and incoming connnections. 201 */ 202 if (inOutPort) { 203 divertInOut = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT); 204 if (divertInOut == -1) 205 Quit("Unable to create divert socket."); 206 207 divertIn = -1; 208 divertOut = -1; 209 /* 210 * Bind socket. 211 */ 212 213 addr.sin_family = AF_INET; 214 addr.sin_addr.s_addr = INADDR_ANY; 215 addr.sin_port = inOutPort; 216 217 if (bind(divertInOut, 218 (struct sockaddr *)&addr, 219 sizeof addr) == -1) 220 Quit("Unable to bind divert socket."); 221 } else { 222 divertIn = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT); 223 if (divertIn == -1) 224 Quit("Unable to create incoming divert socket."); 225 226 divertOut = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT); 227 if (divertOut == -1) 228 Quit("Unable to create outgoing divert socket."); 229 230 divertInOut = -1; 231 232 /* 233 * Bind divert sockets. 234 */ 235 236 addr.sin_family = AF_INET; 237 addr.sin_addr.s_addr = INADDR_ANY; 238 addr.sin_port = inPort; 239 240 if (bind(divertIn, 241 (struct sockaddr *)&addr, 242 sizeof addr) == -1) 243 Quit("Unable to bind incoming divert socket."); 244 245 addr.sin_family = AF_INET; 246 addr.sin_addr.s_addr = INADDR_ANY; 247 addr.sin_port = outPort; 248 249 if (bind(divertOut, 250 (struct sockaddr *)&addr, 251 sizeof addr) == -1) 252 Quit("Unable to bind outgoing divert socket."); 253 } 254 /* 255 * Create routing socket if interface name specified and in dynamic mode. 256 */ 257 routeSock = -1; 258 if (ifName) { 259 if (dynamicMode) { 260 routeSock = socket(PF_ROUTE, SOCK_RAW, 0); 261 if (routeSock == -1) 262 Quit("Unable to create routing info socket."); 263 264 assignAliasAddr = 1; 265 } else 266 SetAliasAddressFromIfName(ifName); 267 } 268 /* 269 * Create socket for sending ICMP messages. 270 */ 271 icmpSock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 272 if (icmpSock == -1) 273 Quit("Unable to create ICMP socket."); 274 275 /* 276 * And disable reads for the socket, otherwise it slowly fills 277 * up with received icmps which we do not use. 278 */ 279 shutdown(icmpSock, SHUT_RD); 280 281 /* 282 * Become a daemon unless verbose mode was requested. 283 */ 284 if (!verbose) 285 DaemonMode(); 286 /* 287 * Catch signals to manage shutdown and 288 * refresh of interface address. 289 */ 290 sa.sa_flags = 0; 291 sigemptyset(&sa.sa_mask); 292 if (exitDelay) 293 sa.sa_handler = InitiateShutdown; 294 else 295 sa.sa_handler = Shutdown; 296 sigaction(SIGTERM, &sa, NULL); 297 sa.sa_handler = RefreshAddr; 298 sigaction(SIGHUP, &sa, NULL); 299 /* 300 * Set alias address if it has been given. 301 */ 302 if (aliasAddr.s_addr != INADDR_NONE) 303 PacketAliasSetAddress(aliasAddr); 304 /* 305 * We need largest descriptor number for select. 306 */ 307 308 fdMax = -1; 309 310 if (divertIn > fdMax) 311 fdMax = divertIn; 312 313 if (divertOut > fdMax) 314 fdMax = divertOut; 315 316 if (divertInOut > fdMax) 317 fdMax = divertInOut; 318 319 if (routeSock > fdMax) 320 fdMax = routeSock; 321 322 while (running) { 323 if (divertInOut != -1 && !ifName) { 324 /* 325 * When using only one socket, just call 326 * DoAliasing repeatedly to process packets. 327 */ 328 DoAliasing(divertInOut, DONT_KNOW); 329 continue; 330 } 331 /* 332 * Build read mask from socket descriptors to select. 333 */ 334 FD_ZERO(&readMask); 335 /* 336 * Check if new packets are available. 337 */ 338 if (divertIn != -1) 339 FD_SET(divertIn, &readMask); 340 341 if (divertOut != -1) 342 FD_SET(divertOut, &readMask); 343 344 if (divertInOut != -1) 345 FD_SET(divertInOut, &readMask); 346 /* 347 * Routing info is processed always. 348 */ 349 if (routeSock != -1) 350 FD_SET(routeSock, &readMask); 351 352 if (select(fdMax + 1, 353 &readMask, 354 NULL, 355 NULL, 356 NULL) == -1) { 357 if (errno == EINTR) 358 continue; 359 360 Quit("Select failed."); 361 } 362 363 if (divertIn != -1) 364 if (FD_ISSET(divertIn, &readMask)) 365 DoAliasing(divertIn, INPUT); 366 367 if (divertOut != -1) 368 if (FD_ISSET(divertOut, &readMask)) 369 DoAliasing(divertOut, OUTPUT); 370 371 if (divertInOut != -1) 372 if (FD_ISSET(divertInOut, &readMask)) 373 DoAliasing(divertInOut, DONT_KNOW); 374 375 if (routeSock != -1) 376 if (FD_ISSET(routeSock, &readMask)) 377 HandleRoutingInfo(routeSock); 378 } 379 380 if (background) 381 unlink(PIDFILE); 382 383 return 0; 384 } 385 386 static void 387 DaemonMode(void) 388 { 389 FILE* pidFile; 390 391 daemon(0, 0); 392 background = 1; 393 394 pidFile = fopen(PIDFILE, "w"); 395 if (pidFile) { 396 fprintf(pidFile, "%d\n", getpid()); 397 fclose(pidFile); 398 } 399 } 400 401 static void 402 ParseArgs(int argc, char **argv) 403 { 404 int arg; 405 char* opt; 406 char parmBuf[256]; 407 int len; /* bounds checking */ 408 409 for (arg = 1; arg < argc; arg++) { 410 opt = argv[arg]; 411 if (*opt != '-') { 412 warnx("invalid option %s", opt); 413 Usage(); 414 } 415 416 parmBuf[0] = '\0'; 417 len = 0; 418 419 while (arg < argc - 1) { 420 if (argv[arg + 1][0] == '-') 421 break; 422 423 if (len) { 424 strncat(parmBuf, " ", sizeof(parmBuf) - (len + 1)); 425 len += strlen(parmBuf + len); 426 } 427 428 ++arg; 429 strncat(parmBuf, argv[arg], sizeof(parmBuf) - (len + 1)); 430 len += strlen(parmBuf + len); 431 432 } 433 434 ParseOption(opt + 1, (len ? parmBuf : NULL)); 435 436 } 437 } 438 439 static void 440 DoAliasing(int fd, int direction) 441 { 442 int bytes; 443 int origBytes; 444 char buf[IP_MAXPACKET]; 445 struct sockaddr_in addr; 446 int wrote; 447 int status; 448 int addrSize; 449 struct ip* ip; 450 char msgBuf[80]; 451 452 if (assignAliasAddr) { 453 SetAliasAddressFromIfName(ifName); 454 assignAliasAddr = 0; 455 } 456 /* 457 * Get packet from socket. 458 */ 459 addrSize = sizeof addr; 460 origBytes = recvfrom(fd, 461 buf, 462 sizeof buf, 463 0, 464 (struct sockaddr *)&addr, 465 &addrSize); 466 467 if (origBytes == -1) { 468 if (errno != EINTR) 469 Warn("read from divert socket failed"); 470 471 return; 472 } 473 /* 474 * This is a IP packet. 475 */ 476 ip = (struct ip *)buf; 477 if (direction == DONT_KNOW) { 478 if (addr.sin_addr.s_addr == INADDR_ANY) 479 direction = OUTPUT; 480 else 481 direction = INPUT; 482 } 483 484 if (verbose) { 485 /* 486 * Print packet direction and protocol type. 487 */ 488 printf(direction == OUTPUT ? "Out " : "In "); 489 490 switch (ip->ip_p) { 491 case IPPROTO_TCP: 492 printf("[TCP] "); 493 break; 494 495 case IPPROTO_UDP: 496 printf("[UDP] "); 497 break; 498 499 case IPPROTO_ICMP: 500 printf("[ICMP] "); 501 break; 502 503 default: 504 printf("[%d] ", ip->ip_p); 505 break; 506 } 507 /* 508 * Print addresses. 509 */ 510 PrintPacket(ip); 511 } 512 513 if (direction == OUTPUT) { 514 /* 515 * Outgoing packets. Do aliasing. 516 */ 517 PacketAliasOut(buf, IP_MAXPACKET); 518 } else { 519 /* 520 * Do aliasing. 521 */ 522 status = PacketAliasIn(buf, IP_MAXPACKET); 523 if (status == PKT_ALIAS_IGNORED && 524 dropIgnoredIncoming) { 525 if (verbose) 526 printf(" dropped.\n"); 527 528 if (logDropped) 529 SyslogPacket(ip, LOG_WARNING, "denied"); 530 531 return; 532 } 533 } 534 /* 535 * Length might have changed during aliasing. 536 */ 537 bytes = ntohs(ip->ip_len); 538 /* 539 * Update alias overhead size for outgoing packets. 540 */ 541 if (direction == OUTPUT && 542 bytes - origBytes > aliasOverhead) 543 aliasOverhead = bytes - origBytes; 544 545 if (verbose) { 546 /* 547 * Print addresses after aliasing. 548 */ 549 printf(" aliased to\n"); 550 printf(" "); 551 PrintPacket(ip); 552 printf("\n"); 553 } 554 555 /* 556 * Put packet back for processing. 557 */ 558 wrote = sendto(fd, 559 buf, 560 bytes, 561 0, 562 (struct sockaddr *)&addr, 563 sizeof addr); 564 565 if (wrote != bytes) { 566 if (errno == EMSGSIZE) { 567 if (direction == OUTPUT && 568 ifMTU != -1) 569 SendNeedFragIcmp(icmpSock, 570 (struct ip *)buf, 571 ifMTU - aliasOverhead); 572 } else if (errno == EACCES && logIpfwDenied) { 573 sprintf(msgBuf, "failed to write packet back"); 574 Warn(msgBuf); 575 } 576 } 577 } 578 579 static void 580 HandleRoutingInfo(int fd) 581 { 582 int bytes; 583 struct if_msghdr ifMsg; 584 /* 585 * Get packet from socket. 586 */ 587 bytes = read(fd, &ifMsg, sizeof ifMsg); 588 if (bytes == -1) { 589 Warn("read from routing socket failed"); 590 return; 591 } 592 593 if (ifMsg.ifm_version != RTM_VERSION) { 594 Warn("unexpected packet read from routing socket"); 595 return; 596 } 597 598 if (verbose) 599 printf("Routing message %#x received.\n", ifMsg.ifm_type); 600 601 if ((ifMsg.ifm_type == RTM_NEWADDR || ifMsg.ifm_type == RTM_IFINFO) && 602 ifMsg.ifm_index == ifIndex) { 603 if (verbose) 604 printf("Interface address/MTU has probably changed.\n"); 605 assignAliasAddr = 1; 606 } 607 } 608 609 static void 610 PrintPacket(struct ip *ip) 611 { 612 printf("%s", FormatPacket(ip)); 613 } 614 615 static void 616 SyslogPacket(struct ip *ip, int priority, const char *label) 617 { 618 syslog(priority, "%s %s", label, FormatPacket(ip)); 619 } 620 621 static char* 622 FormatPacket(struct ip *ip) 623 { 624 static char buf[256]; 625 struct tcphdr* tcphdr; 626 struct udphdr* udphdr; 627 struct icmp* icmphdr; 628 char src[20]; 629 char dst[20]; 630 631 strcpy(src, inet_ntoa(ip->ip_src)); 632 strcpy(dst, inet_ntoa(ip->ip_dst)); 633 634 switch (ip->ip_p) { 635 case IPPROTO_TCP: 636 tcphdr = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2)); 637 sprintf(buf, "[TCP] %s:%d -> %s:%d", 638 src, 639 ntohs(tcphdr->th_sport), 640 dst, 641 ntohs(tcphdr->th_dport)); 642 break; 643 644 case IPPROTO_UDP: 645 udphdr = (struct udphdr *)((char *)ip + (ip->ip_hl << 2)); 646 sprintf(buf, "[UDP] %s:%d -> %s:%d", 647 src, 648 ntohs(udphdr->uh_sport), 649 dst, 650 ntohs(udphdr->uh_dport)); 651 break; 652 653 case IPPROTO_ICMP: 654 icmphdr = (struct icmp *)((char *)ip + (ip->ip_hl << 2)); 655 sprintf(buf, "[ICMP] %s -> %s %u(%u)", 656 src, 657 dst, 658 icmphdr->icmp_type, 659 icmphdr->icmp_code); 660 break; 661 662 default: 663 sprintf(buf, "[%d] %s -> %s ", ip->ip_p, src, dst); 664 break; 665 } 666 667 return buf; 668 } 669 670 static void 671 SetAliasAddressFromIfName(const char *ifn) 672 { 673 size_t needed; 674 int mib[6]; 675 char *buf, *lim, *next; 676 struct if_msghdr *ifm; 677 struct ifa_msghdr *ifam; 678 struct sockaddr_dl *s_dl; 679 struct sockaddr_in *s_in; 680 681 mib[0] = CTL_NET; 682 mib[1] = PF_ROUTE; 683 mib[2] = 0; 684 mib[3] = AF_INET; /* Only IP addresses please */ 685 mib[4] = NET_RT_IFLIST; 686 mib[5] = 0; /* ifIndex??? */ 687 /* 688 * Get interface data. 689 */ 690 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 691 err(1, "iflist-sysctl-estimate"); 692 if ((buf = malloc(needed)) == NULL) 693 errx(1, "malloc failed"); 694 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 695 err(1, "iflist-sysctl-get"); 696 lim = buf + needed; 697 /* 698 * Loop through interfaces until one with 699 * given name is found. This is done to 700 * find correct interface index for routing 701 * message processing. 702 */ 703 ifIndex = 0; 704 next = buf; 705 while (next < lim) { 706 ifm = (struct if_msghdr *)next; 707 next += ifm->ifm_msglen; 708 if (ifm->ifm_version != RTM_VERSION) { 709 if (verbose) 710 warnx("routing message version %d " 711 "not understood", ifm->ifm_version); 712 continue; 713 } 714 if (ifm->ifm_type == RTM_IFINFO) { 715 s_dl = (struct sockaddr_dl *)(ifm + 1); 716 if (strlen(ifn) == s_dl->sdl_nlen && 717 strncmp(ifn, s_dl->sdl_data, s_dl->sdl_nlen) == 0) { 718 ifIndex = ifm->ifm_index; 719 ifMTU = ifm->ifm_data.ifi_mtu; 720 break; 721 } 722 } 723 } 724 if (!ifIndex) 725 errx(1, "unknown interface name %s", ifn); 726 /* 727 * Get interface address. 728 */ 729 s_in = NULL; 730 while (next < lim) { 731 ifam = (struct ifa_msghdr *)next; 732 next += ifam->ifam_msglen; 733 if (ifam->ifam_version != RTM_VERSION) { 734 if (verbose) 735 warnx("routing message version %d " 736 "not understood", ifam->ifam_version); 737 continue; 738 } 739 if (ifam->ifam_type != RTM_NEWADDR) 740 break; 741 if (ifam->ifam_addrs & RTA_IFA) { 742 int i; 743 char *cp = (char *)(ifam + 1); 744 745 #define ROUNDUP(a) \ 746 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 747 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 748 749 for (i = 1; i < RTA_IFA; i <<= 1) 750 if (ifam->ifam_addrs & i) 751 ADVANCE(cp, (struct sockaddr *)cp); 752 if (((struct sockaddr *)cp)->sa_family == AF_INET) { 753 s_in = (struct sockaddr_in *)cp; 754 break; 755 } 756 } 757 } 758 if (s_in == NULL) 759 errx(1, "%s: cannot get interface address", ifn); 760 761 PacketAliasSetAddress(s_in->sin_addr); 762 syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes", 763 inet_ntoa(s_in->sin_addr), ifMTU); 764 765 free(buf); 766 } 767 768 void 769 Quit(const char *msg) 770 { 771 Warn(msg); 772 exit(1); 773 } 774 775 void 776 Warn(const char *msg) 777 { 778 if (background) 779 syslog(LOG_ALERT, "%s (%m)", msg); 780 else 781 warn("%s", msg); 782 } 783 784 static void 785 RefreshAddr(int sig __unused) 786 { 787 if (ifName) 788 assignAliasAddr = 1; 789 } 790 791 static void 792 InitiateShutdown(int sig __unused) 793 { 794 struct sigaction sa; 795 /* 796 * Start timer to allow kernel gracefully 797 * shutdown existing connections when system 798 * is shut down. 799 */ 800 sa.sa_handler = Shutdown; 801 sa.sa_flags = 0; 802 sigemptyset(&sa.sa_mask); 803 sigaction(SIGALRM, &sa, NULL); 804 ualarm(exitDelay*1000, 1000); 805 } 806 807 static void 808 Shutdown(int sig __unused) 809 { 810 running = 0; 811 } 812 813 /* 814 * Different options recognized by this program. 815 */ 816 817 enum Option { 818 PacketAliasOption, 819 Verbose, 820 InPort, 821 OutPort, 822 Port, 823 AliasAddress, 824 TargetAddress, 825 InterfaceName, 826 RedirectPort, 827 RedirectProto, 828 RedirectAddress, 829 ConfigFile, 830 DynamicMode, 831 ProxyRule, 832 LogDenied, 833 LogFacility, 834 PunchFW, 835 LogIpfwDenied, 836 ExitDelay 837 }; 838 839 enum Param { 840 YesNo, 841 Numeric, 842 String, 843 None, 844 Address, 845 Service 846 }; 847 848 /* 849 * Option information structure (used by ParseOption). 850 */ 851 852 struct OptionInfo { 853 enum Option type; 854 int packetAliasOpt; 855 enum Param parm; 856 const char* parmDescription; 857 const char* description; 858 const char* name; 859 const char* shortName; 860 }; 861 862 /* 863 * Table of known options. 864 */ 865 866 static struct OptionInfo optionTable[] = { 867 { PacketAliasOption, 868 PKT_ALIAS_UNREGISTERED_ONLY, 869 YesNo, 870 "[yes|no]", 871 "alias only unregistered addresses", 872 "unregistered_only", 873 "u" }, 874 875 { PacketAliasOption, 876 PKT_ALIAS_LOG, 877 YesNo, 878 "[yes|no]", 879 "enable logging", 880 "log", 881 "l" }, 882 883 { PacketAliasOption, 884 PKT_ALIAS_PROXY_ONLY, 885 YesNo, 886 "[yes|no]", 887 "proxy only", 888 "proxy_only", 889 NULL }, 890 891 { PacketAliasOption, 892 PKT_ALIAS_REVERSE, 893 YesNo, 894 "[yes|no]", 895 "operate in reverse mode", 896 "reverse", 897 NULL }, 898 899 { PacketAliasOption, 900 PKT_ALIAS_DENY_INCOMING, 901 YesNo, 902 "[yes|no]", 903 "allow incoming connections", 904 "deny_incoming", 905 "d" }, 906 907 { PacketAliasOption, 908 PKT_ALIAS_USE_SOCKETS, 909 YesNo, 910 "[yes|no]", 911 "use sockets to inhibit port conflict", 912 "use_sockets", 913 "s" }, 914 915 { PacketAliasOption, 916 PKT_ALIAS_SAME_PORTS, 917 YesNo, 918 "[yes|no]", 919 "try to keep original port numbers for connections", 920 "same_ports", 921 "m" }, 922 923 { Verbose, 924 0, 925 YesNo, 926 "[yes|no]", 927 "verbose mode, dump packet information", 928 "verbose", 929 "v" }, 930 931 { DynamicMode, 932 0, 933 YesNo, 934 "[yes|no]", 935 "dynamic mode, automatically detect interface address changes", 936 "dynamic", 937 NULL }, 938 939 { InPort, 940 0, 941 Service, 942 "number|service_name", 943 "set port for incoming packets", 944 "in_port", 945 "i" }, 946 947 { OutPort, 948 0, 949 Service, 950 "number|service_name", 951 "set port for outgoing packets", 952 "out_port", 953 "o" }, 954 955 { Port, 956 0, 957 Service, 958 "number|service_name", 959 "set port (defaults to natd/divert)", 960 "port", 961 "p" }, 962 963 { AliasAddress, 964 0, 965 Address, 966 "x.x.x.x", 967 "address to use for aliasing", 968 "alias_address", 969 "a" }, 970 971 { TargetAddress, 972 0, 973 Address, 974 "x.x.x.x", 975 "address to use for incoming sessions", 976 "target_address", 977 "t" }, 978 979 { InterfaceName, 980 0, 981 String, 982 "network_if_name", 983 "take aliasing address from interface", 984 "interface", 985 "n" }, 986 987 { ProxyRule, 988 0, 989 String, 990 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " 991 "a.b.c.d:yyyy", 992 "add transparent proxying / destination NAT", 993 "proxy_rule", 994 NULL }, 995 996 { RedirectPort, 997 0, 998 String, 999 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range" 1000 " [remote_addr[:remote_port_range]]", 1001 "redirect a port (or ports) for incoming traffic", 1002 "redirect_port", 1003 NULL }, 1004 1005 { RedirectProto, 1006 0, 1007 String, 1008 "proto local_addr [public_addr] [remote_addr]", 1009 "redirect packets of a given proto", 1010 "redirect_proto", 1011 NULL }, 1012 1013 { RedirectAddress, 1014 0, 1015 String, 1016 "local_addr[,...] public_addr", 1017 "define mapping between local and public addresses", 1018 "redirect_address", 1019 NULL }, 1020 1021 { ConfigFile, 1022 0, 1023 String, 1024 "file_name", 1025 "read options from configuration file", 1026 "config", 1027 "f" }, 1028 1029 { LogDenied, 1030 0, 1031 YesNo, 1032 "[yes|no]", 1033 "enable logging of denied incoming packets", 1034 "log_denied", 1035 NULL }, 1036 1037 { LogFacility, 1038 0, 1039 String, 1040 "facility", 1041 "name of syslog facility to use for logging", 1042 "log_facility", 1043 NULL }, 1044 1045 { PunchFW, 1046 0, 1047 String, 1048 "basenumber:count", 1049 "punch holes in the firewall for incoming FTP/IRC DCC connections", 1050 "punch_fw", 1051 NULL }, 1052 1053 { LogIpfwDenied, 1054 0, 1055 YesNo, 1056 "[yes|no]", 1057 "log packets converted by natd, but denied by ipfw", 1058 "log_ipfw_denied", 1059 NULL }, 1060 { ExitDelay, 1061 0, 1062 Numeric, 1063 "ms", 1064 "delay in ms before daemon exit after signal", 1065 "exit_delay", 1066 NULL }, 1067 }; 1068 1069 static void 1070 ParseOption(const char *option, const char *parms) 1071 { 1072 int i; 1073 struct OptionInfo* info; 1074 int yesNoValue; 1075 int aliasValue; 1076 int numValue; 1077 u_short uNumValue; 1078 const char* strValue; 1079 struct in_addr addrValue; 1080 int max; 1081 char* end; 1082 CODE* fac_record = NULL; 1083 /* 1084 * Find option from table. 1085 */ 1086 max = sizeof(optionTable) / sizeof(struct OptionInfo); 1087 for (i = 0, info = optionTable; i < max; i++, info++) { 1088 if (!strcmp(info->name, option)) 1089 break; 1090 1091 if (info->shortName) 1092 if (!strcmp(info->shortName, option)) 1093 break; 1094 } 1095 1096 if (i >= max) { 1097 warnx("unknown option %s", option); 1098 Usage(); 1099 } 1100 1101 uNumValue = 0; 1102 yesNoValue = 0; 1103 numValue = 0; 1104 strValue = NULL; 1105 /* 1106 * Check parameters. 1107 */ 1108 switch (info->parm) { 1109 case YesNo: 1110 if (!parms) 1111 parms = "yes"; 1112 1113 if (!strcmp(parms, "yes")) 1114 yesNoValue = 1; 1115 else 1116 if (!strcmp(parms, "no")) 1117 yesNoValue = 0; 1118 else 1119 errx(1, "%s needs yes/no parameter", option); 1120 break; 1121 1122 case Service: 1123 if (!parms) 1124 errx(1, "%s needs service name or " 1125 "port number parameter", 1126 option); 1127 1128 uNumValue = StrToPort(parms, "divert"); 1129 break; 1130 1131 case Numeric: 1132 if (parms) 1133 numValue = strtol(parms, &end, 10); 1134 else 1135 end = NULL; 1136 1137 if (end == parms) 1138 errx(1, "%s needs numeric parameter", option); 1139 break; 1140 1141 case String: 1142 strValue = parms; 1143 if (!strValue) 1144 errx(1, "%s needs parameter", option); 1145 break; 1146 1147 case None: 1148 if (parms) 1149 errx(1, "%s does not take parameters", option); 1150 break; 1151 1152 case Address: 1153 if (!parms) 1154 errx(1, "%s needs address/host parameter", option); 1155 1156 StrToAddr(parms, &addrValue); 1157 break; 1158 } 1159 1160 switch (info->type) { 1161 case PacketAliasOption: 1162 1163 aliasValue = yesNoValue ? info->packetAliasOpt : 0; 1164 PacketAliasSetMode(aliasValue, info->packetAliasOpt); 1165 break; 1166 1167 case Verbose: 1168 verbose = yesNoValue; 1169 break; 1170 1171 case DynamicMode: 1172 dynamicMode = yesNoValue; 1173 break; 1174 1175 case InPort: 1176 inPort = uNumValue; 1177 break; 1178 1179 case OutPort: 1180 outPort = uNumValue; 1181 break; 1182 1183 case Port: 1184 inOutPort = uNumValue; 1185 break; 1186 1187 case AliasAddress: 1188 memcpy(&aliasAddr, &addrValue, sizeof(struct in_addr)); 1189 break; 1190 1191 case TargetAddress: 1192 PacketAliasSetTarget(addrValue); 1193 break; 1194 1195 case RedirectPort: 1196 SetupPortRedirect(strValue); 1197 break; 1198 1199 case RedirectProto: 1200 SetupProtoRedirect(strValue); 1201 break; 1202 1203 case RedirectAddress: 1204 SetupAddressRedirect(strValue); 1205 break; 1206 1207 case ProxyRule: 1208 PacketAliasProxyRule(strValue); 1209 break; 1210 1211 case InterfaceName: 1212 if (ifName) 1213 free(ifName); 1214 1215 ifName = strdup(strValue); 1216 break; 1217 1218 case ConfigFile: 1219 ReadConfigFile(strValue); 1220 break; 1221 1222 case LogDenied: 1223 logDropped = yesNoValue; 1224 break; 1225 1226 case LogFacility: 1227 1228 fac_record = facilitynames; 1229 while (fac_record->c_name != NULL) { 1230 if (!strcmp(fac_record->c_name, strValue)) { 1231 logFacility = fac_record->c_val; 1232 break; 1233 1234 } else 1235 fac_record++; 1236 } 1237 1238 if(fac_record->c_name == NULL) 1239 errx(1, "Unknown log facility name: %s", strValue); 1240 1241 break; 1242 1243 case PunchFW: 1244 SetupPunchFW(strValue); 1245 break; 1246 1247 case LogIpfwDenied: 1248 logIpfwDenied = yesNoValue; 1249 break; 1250 case ExitDelay: 1251 if (numValue < 0 || numValue > MAX_EXIT_DELAY) 1252 errx(1, "Incorrect exit delay: %d", numValue); 1253 exitDelay = numValue; 1254 break; 1255 } 1256 } 1257 1258 void 1259 ReadConfigFile(const char *fileName) 1260 { 1261 FILE* file; 1262 char *buf; 1263 size_t len; 1264 char *ptr, *p; 1265 char* option; 1266 1267 file = fopen(fileName, "r"); 1268 if (!file) 1269 err(1, "cannot open config file %s", fileName); 1270 1271 while ((buf = fgetln(file, &len)) != NULL) { 1272 if (buf[len - 1] == '\n') 1273 buf[len - 1] = '\0'; 1274 else 1275 errx(1, "config file format error: " 1276 "last line should end with newline"); 1277 1278 /* 1279 * Check for comments, strip off trailing spaces. 1280 */ 1281 if ((ptr = strchr(buf, '#'))) 1282 *ptr = '\0'; 1283 for (ptr = buf; isspace(*ptr); ++ptr) 1284 continue; 1285 if (*ptr == '\0') 1286 continue; 1287 for (p = strchr(buf, '\0'); isspace(*--p);) 1288 continue; 1289 *++p = '\0'; 1290 1291 /* 1292 * Extract option name. 1293 */ 1294 option = ptr; 1295 while (*ptr && !isspace(*ptr)) 1296 ++ptr; 1297 1298 if (*ptr != '\0') { 1299 *ptr = '\0'; 1300 ++ptr; 1301 } 1302 /* 1303 * Skip white space between name and parms. 1304 */ 1305 while (*ptr && isspace(*ptr)) 1306 ++ptr; 1307 1308 ParseOption(option, *ptr ? ptr : NULL); 1309 } 1310 1311 fclose(file); 1312 } 1313 1314 static void 1315 Usage(void) 1316 { 1317 int i; 1318 int max; 1319 struct OptionInfo* info; 1320 1321 fprintf(stderr, "Recognized options:\n\n"); 1322 1323 max = sizeof(optionTable) / sizeof(struct OptionInfo); 1324 for (i = 0, info = optionTable; i < max; i++, info++) { 1325 fprintf(stderr, "-%-20s %s\n", info->name, 1326 info->parmDescription); 1327 1328 if (info->shortName) 1329 fprintf(stderr, "-%-20s %s\n", info->shortName, 1330 info->parmDescription); 1331 1332 fprintf(stderr, " %s\n\n", info->description); 1333 } 1334 1335 exit(1); 1336 } 1337 1338 void 1339 SetupPortRedirect(const char *parms) 1340 { 1341 char buf[128]; 1342 char* ptr; 1343 char* serverPool; 1344 struct in_addr localAddr; 1345 struct in_addr publicAddr; 1346 struct in_addr remoteAddr; 1347 port_range portRange; 1348 u_short localPort = 0; 1349 u_short publicPort = 0; 1350 u_short remotePort = 0; 1351 u_short numLocalPorts = 0; 1352 u_short numPublicPorts = 0; 1353 u_short numRemotePorts = 0; 1354 int proto; 1355 char* protoName; 1356 char* separator; 1357 int i; 1358 struct alias_link *alink = NULL; 1359 1360 strcpy(buf, parms); 1361 /* 1362 * Extract protocol. 1363 */ 1364 protoName = strtok(buf, " \t"); 1365 if (!protoName) 1366 errx(1, "redirect_port: missing protocol"); 1367 1368 proto = StrToProto(protoName); 1369 /* 1370 * Extract local address. 1371 */ 1372 ptr = strtok(NULL, " \t"); 1373 if (!ptr) 1374 errx(1, "redirect_port: missing local address"); 1375 1376 separator = strchr(ptr, ','); 1377 if (separator) { /* LSNAT redirection syntax. */ 1378 localAddr.s_addr = INADDR_NONE; 1379 localPort = ~0; 1380 numLocalPorts = 1; 1381 serverPool = ptr; 1382 } else { 1383 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0 ) 1384 errx(1, "redirect_port: invalid local port range"); 1385 1386 localPort = GETLOPORT(portRange); 1387 numLocalPorts = GETNUMPORTS(portRange); 1388 serverPool = NULL; 1389 } 1390 1391 /* 1392 * Extract public port and optionally address. 1393 */ 1394 ptr = strtok(NULL, " \t"); 1395 if (!ptr) 1396 errx(1, "redirect_port: missing public port"); 1397 1398 separator = strchr(ptr, ':'); 1399 if (separator) { 1400 if (StrToAddrAndPortRange(ptr, &publicAddr, protoName, &portRange) != 0 ) 1401 errx(1, "redirect_port: invalid public port range"); 1402 } else { 1403 publicAddr.s_addr = INADDR_ANY; 1404 if (StrToPortRange(ptr, protoName, &portRange) != 0) 1405 errx(1, "redirect_port: invalid public port range"); 1406 } 1407 1408 publicPort = GETLOPORT(portRange); 1409 numPublicPorts = GETNUMPORTS(portRange); 1410 1411 /* 1412 * Extract remote address and optionally port. 1413 */ 1414 ptr = strtok(NULL, " \t"); 1415 if (ptr) { 1416 separator = strchr(ptr, ':'); 1417 if (separator) { 1418 if (StrToAddrAndPortRange(ptr, &remoteAddr, protoName, &portRange) != 0) 1419 errx(1, "redirect_port: invalid remote port range"); 1420 } else { 1421 SETLOPORT(portRange, 0); 1422 SETNUMPORTS(portRange, 1); 1423 StrToAddr(ptr, &remoteAddr); 1424 } 1425 } else { 1426 SETLOPORT(portRange, 0); 1427 SETNUMPORTS(portRange, 1); 1428 remoteAddr.s_addr = INADDR_ANY; 1429 } 1430 1431 remotePort = GETLOPORT(portRange); 1432 numRemotePorts = GETNUMPORTS(portRange); 1433 1434 /* 1435 * Make sure port ranges match up, then add the redirect ports. 1436 */ 1437 if (numLocalPorts != numPublicPorts) 1438 errx(1, "redirect_port: port ranges must be equal in size"); 1439 1440 /* Remote port range is allowed to be '0' which means all ports. */ 1441 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0)) 1442 errx(1, "redirect_port: remote port must be 0 or equal to local port range in size"); 1443 1444 for (i = 0 ; i < numPublicPorts ; ++i) { 1445 /* If remotePort is all ports, set it to 0. */ 1446 u_short remotePortCopy = remotePort + i; 1447 if (numRemotePorts == 1 && remotePort == 0) 1448 remotePortCopy = 0; 1449 1450 alink = PacketAliasRedirectPort(localAddr, 1451 htons(localPort + i), 1452 remoteAddr, 1453 htons(remotePortCopy), 1454 publicAddr, 1455 htons(publicPort + i), 1456 proto); 1457 } 1458 1459 /* 1460 * Setup LSNAT server pool. 1461 */ 1462 if (serverPool != NULL && alink != NULL) { 1463 ptr = strtok(serverPool, ","); 1464 while (ptr != NULL) { 1465 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0) 1466 errx(1, "redirect_port: invalid local port range"); 1467 1468 localPort = GETLOPORT(portRange); 1469 if (GETNUMPORTS(portRange) != 1) 1470 errx(1, "redirect_port: local port must be single in this context"); 1471 PacketAliasAddServer(alink, localAddr, htons(localPort)); 1472 ptr = strtok(NULL, ","); 1473 } 1474 } 1475 } 1476 1477 void 1478 SetupProtoRedirect(const char *parms) 1479 { 1480 char buf[128]; 1481 char* ptr; 1482 struct in_addr localAddr; 1483 struct in_addr publicAddr; 1484 struct in_addr remoteAddr; 1485 int proto; 1486 char* protoName; 1487 struct protoent *protoent; 1488 1489 strcpy(buf, parms); 1490 /* 1491 * Extract protocol. 1492 */ 1493 protoName = strtok(buf, " \t"); 1494 if (!protoName) 1495 errx(1, "redirect_proto: missing protocol"); 1496 1497 protoent = getprotobyname(protoName); 1498 if (protoent == NULL) 1499 errx(1, "redirect_proto: unknown protocol %s", protoName); 1500 else 1501 proto = protoent->p_proto; 1502 /* 1503 * Extract local address. 1504 */ 1505 ptr = strtok(NULL, " \t"); 1506 if (!ptr) 1507 errx(1, "redirect_proto: missing local address"); 1508 else 1509 StrToAddr(ptr, &localAddr); 1510 /* 1511 * Extract optional public address. 1512 */ 1513 ptr = strtok(NULL, " \t"); 1514 if (ptr) 1515 StrToAddr(ptr, &publicAddr); 1516 else 1517 publicAddr.s_addr = INADDR_ANY; 1518 /* 1519 * Extract optional remote address. 1520 */ 1521 ptr = strtok(NULL, " \t"); 1522 if (ptr) 1523 StrToAddr(ptr, &remoteAddr); 1524 else 1525 remoteAddr.s_addr = INADDR_ANY; 1526 /* 1527 * Create aliasing link. 1528 */ 1529 PacketAliasRedirectProto(localAddr, remoteAddr, publicAddr, proto); 1530 } 1531 1532 void 1533 SetupAddressRedirect(const char *parms) 1534 { 1535 char buf[128]; 1536 char* ptr; 1537 char* separator; 1538 struct in_addr localAddr; 1539 struct in_addr publicAddr; 1540 char* serverPool; 1541 struct alias_link *alink; 1542 1543 strcpy(buf, parms); 1544 /* 1545 * Extract local address. 1546 */ 1547 ptr = strtok(buf, " \t"); 1548 if (!ptr) 1549 errx(1, "redirect_address: missing local address"); 1550 1551 separator = strchr(ptr, ','); 1552 if (separator) { /* LSNAT redirection syntax. */ 1553 localAddr.s_addr = INADDR_NONE; 1554 serverPool = ptr; 1555 } else { 1556 StrToAddr(ptr, &localAddr); 1557 serverPool = NULL; 1558 } 1559 /* 1560 * Extract public address. 1561 */ 1562 ptr = strtok(NULL, " \t"); 1563 if (!ptr) 1564 errx(1, "redirect_address: missing public address"); 1565 1566 StrToAddr(ptr, &publicAddr); 1567 alink = PacketAliasRedirectAddr(localAddr, publicAddr); 1568 1569 /* 1570 * Setup LSNAT server pool. 1571 */ 1572 if (serverPool != NULL && alink != NULL) { 1573 ptr = strtok(serverPool, ","); 1574 while (ptr != NULL) { 1575 StrToAddr(ptr, &localAddr); 1576 PacketAliasAddServer(alink, localAddr, htons(~0)); 1577 ptr = strtok(NULL, ","); 1578 } 1579 } 1580 } 1581 1582 void 1583 StrToAddr(const char *str, struct in_addr *addr) 1584 { 1585 struct hostent *hp; 1586 1587 if (inet_aton(str, addr)) 1588 return; 1589 1590 hp = gethostbyname(str); 1591 if (!hp) 1592 errx(1, "unknown host %s", str); 1593 1594 memcpy(addr, hp->h_addr, sizeof(struct in_addr)); 1595 } 1596 1597 u_short 1598 StrToPort(const char *str, const char *proto) 1599 { 1600 u_short port; 1601 struct servent* sp; 1602 char* end; 1603 1604 port = strtol(str, &end, 10); 1605 if (end != str) 1606 return htons(port); 1607 1608 sp = getservbyname(str, proto); 1609 if (!sp) 1610 errx(1, "unknown service %s/%s", str, proto); 1611 1612 return sp->s_port; 1613 } 1614 1615 int 1616 StrToPortRange(const char *str, const char *proto, port_range *portRange) 1617 { 1618 char* sep; 1619 struct servent* sp; 1620 char* end; 1621 u_short loPort; 1622 u_short hiPort; 1623 1624 /* First see if this is a service, return corresponding port if so. */ 1625 sp = getservbyname(str,proto); 1626 if (sp) { 1627 SETLOPORT(*portRange, ntohs(sp->s_port)); 1628 SETNUMPORTS(*portRange, 1); 1629 return 0; 1630 } 1631 1632 /* Not a service, see if it's a single port or port range. */ 1633 sep = strchr(str, '-'); 1634 if (sep == NULL) { 1635 SETLOPORT(*portRange, strtol(str, &end, 10)); 1636 if (end != str) { 1637 /* Single port. */ 1638 SETNUMPORTS(*portRange, 1); 1639 return 0; 1640 } 1641 1642 /* Error in port range field. */ 1643 errx(1, "unknown service %s/%s", str, proto); 1644 } 1645 1646 /* Port range, get the values and sanity check. */ 1647 sscanf(str, "%hu-%hu", &loPort, &hiPort); 1648 SETLOPORT(*portRange, loPort); 1649 SETNUMPORTS(*portRange, 0); /* Error by default */ 1650 if (loPort <= hiPort) 1651 SETNUMPORTS(*portRange, hiPort - loPort + 1); 1652 1653 if (GETNUMPORTS(*portRange) == 0) 1654 errx(1, "invalid port range %s", str); 1655 1656 return 0; 1657 } 1658 1659 1660 int 1661 StrToProto(const char *str) 1662 { 1663 if (!strcmp(str, "tcp")) 1664 return IPPROTO_TCP; 1665 1666 if (!strcmp(str, "udp")) 1667 return IPPROTO_UDP; 1668 1669 errx(1, "unknown protocol %s. Expected tcp or udp", str); 1670 } 1671 1672 int 1673 StrToAddrAndPortRange(const char *str, struct in_addr *addr, char *proto, port_range *portRange) 1674 { 1675 char* ptr; 1676 1677 ptr = strchr(str, ':'); 1678 if (!ptr) 1679 errx(1, "%s is missing port number", str); 1680 1681 *ptr = '\0'; 1682 ++ptr; 1683 1684 StrToAddr(str, addr); 1685 return StrToPortRange(ptr, proto, portRange); 1686 } 1687 1688 static void 1689 SetupPunchFW(const char *strValue) 1690 { 1691 unsigned int base, num; 1692 1693 if (sscanf(strValue, "%u:%u", &base, &num) != 2) 1694 errx(1, "punch_fw: basenumber:count parameter required"); 1695 1696 PacketAliasSetFWBase(base, num); 1697 PacketAliasSetMode(PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW); 1698 } 1699