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 for (i = 1; i < RTA_IFA; i <<= 1) 746 if (ifam->ifam_addrs & i) 747 RT_ADVANCE(cp, (struct sockaddr *)cp); 748 if (((struct sockaddr *)cp)->sa_family == AF_INET) { 749 s_in = (struct sockaddr_in *)cp; 750 break; 751 } 752 } 753 } 754 if (s_in == NULL) 755 errx(1, "%s: cannot get interface address", ifn); 756 757 PacketAliasSetAddress(s_in->sin_addr); 758 syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes", 759 inet_ntoa(s_in->sin_addr), ifMTU); 760 761 free(buf); 762 } 763 764 void 765 Quit(const char *msg) 766 { 767 Warn(msg); 768 exit(1); 769 } 770 771 void 772 Warn(const char *msg) 773 { 774 if (background) 775 syslog(LOG_ALERT, "%s (%m)", msg); 776 else 777 warn("%s", msg); 778 } 779 780 static void 781 RefreshAddr(int sig __unused) 782 { 783 if (ifName) 784 assignAliasAddr = 1; 785 } 786 787 static void 788 InitiateShutdown(int sig __unused) 789 { 790 struct sigaction sa; 791 /* 792 * Start timer to allow kernel gracefully 793 * shutdown existing connections when system 794 * is shut down. 795 */ 796 sa.sa_handler = Shutdown; 797 sa.sa_flags = 0; 798 sigemptyset(&sa.sa_mask); 799 sigaction(SIGALRM, &sa, NULL); 800 ualarm(exitDelay*1000, 1000); 801 } 802 803 static void 804 Shutdown(int sig __unused) 805 { 806 running = 0; 807 } 808 809 /* 810 * Different options recognized by this program. 811 */ 812 813 enum Option { 814 PacketAliasOption, 815 Verbose, 816 InPort, 817 OutPort, 818 Port, 819 AliasAddress, 820 TargetAddress, 821 InterfaceName, 822 RedirectPort, 823 RedirectProto, 824 RedirectAddress, 825 ConfigFile, 826 DynamicMode, 827 ProxyRule, 828 LogDenied, 829 LogFacility, 830 PunchFW, 831 LogIpfwDenied, 832 ExitDelay 833 }; 834 835 enum Param { 836 YesNo, 837 Numeric, 838 String, 839 None, 840 Address, 841 Service 842 }; 843 844 /* 845 * Option information structure (used by ParseOption). 846 */ 847 848 struct OptionInfo { 849 enum Option type; 850 int packetAliasOpt; 851 enum Param parm; 852 const char* parmDescription; 853 const char* description; 854 const char* name; 855 const char* shortName; 856 }; 857 858 /* 859 * Table of known options. 860 */ 861 862 static struct OptionInfo optionTable[] = { 863 { PacketAliasOption, 864 PKT_ALIAS_UNREGISTERED_ONLY, 865 YesNo, 866 "[yes|no]", 867 "alias only unregistered addresses", 868 "unregistered_only", 869 "u" }, 870 871 { PacketAliasOption, 872 PKT_ALIAS_LOG, 873 YesNo, 874 "[yes|no]", 875 "enable logging", 876 "log", 877 "l" }, 878 879 { PacketAliasOption, 880 PKT_ALIAS_PROXY_ONLY, 881 YesNo, 882 "[yes|no]", 883 "proxy only", 884 "proxy_only", 885 NULL }, 886 887 { PacketAliasOption, 888 PKT_ALIAS_REVERSE, 889 YesNo, 890 "[yes|no]", 891 "operate in reverse mode", 892 "reverse", 893 NULL }, 894 895 { PacketAliasOption, 896 PKT_ALIAS_DENY_INCOMING, 897 YesNo, 898 "[yes|no]", 899 "allow incoming connections", 900 "deny_incoming", 901 "d" }, 902 903 { PacketAliasOption, 904 PKT_ALIAS_USE_SOCKETS, 905 YesNo, 906 "[yes|no]", 907 "use sockets to inhibit port conflict", 908 "use_sockets", 909 "s" }, 910 911 { PacketAliasOption, 912 PKT_ALIAS_SAME_PORTS, 913 YesNo, 914 "[yes|no]", 915 "try to keep original port numbers for connections", 916 "same_ports", 917 "m" }, 918 919 { Verbose, 920 0, 921 YesNo, 922 "[yes|no]", 923 "verbose mode, dump packet information", 924 "verbose", 925 "v" }, 926 927 { DynamicMode, 928 0, 929 YesNo, 930 "[yes|no]", 931 "dynamic mode, automatically detect interface address changes", 932 "dynamic", 933 NULL }, 934 935 { InPort, 936 0, 937 Service, 938 "number|service_name", 939 "set port for incoming packets", 940 "in_port", 941 "i" }, 942 943 { OutPort, 944 0, 945 Service, 946 "number|service_name", 947 "set port for outgoing packets", 948 "out_port", 949 "o" }, 950 951 { Port, 952 0, 953 Service, 954 "number|service_name", 955 "set port (defaults to natd/divert)", 956 "port", 957 "p" }, 958 959 { AliasAddress, 960 0, 961 Address, 962 "x.x.x.x", 963 "address to use for aliasing", 964 "alias_address", 965 "a" }, 966 967 { TargetAddress, 968 0, 969 Address, 970 "x.x.x.x", 971 "address to use for incoming sessions", 972 "target_address", 973 "t" }, 974 975 { InterfaceName, 976 0, 977 String, 978 "network_if_name", 979 "take aliasing address from interface", 980 "interface", 981 "n" }, 982 983 { ProxyRule, 984 0, 985 String, 986 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " 987 "a.b.c.d:yyyy", 988 "add transparent proxying / destination NAT", 989 "proxy_rule", 990 NULL }, 991 992 { RedirectPort, 993 0, 994 String, 995 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range" 996 " [remote_addr[:remote_port_range]]", 997 "redirect a port (or ports) for incoming traffic", 998 "redirect_port", 999 NULL }, 1000 1001 { RedirectProto, 1002 0, 1003 String, 1004 "proto local_addr [public_addr] [remote_addr]", 1005 "redirect packets of a given proto", 1006 "redirect_proto", 1007 NULL }, 1008 1009 { RedirectAddress, 1010 0, 1011 String, 1012 "local_addr[,...] public_addr", 1013 "define mapping between local and public addresses", 1014 "redirect_address", 1015 NULL }, 1016 1017 { ConfigFile, 1018 0, 1019 String, 1020 "file_name", 1021 "read options from configuration file", 1022 "config", 1023 "f" }, 1024 1025 { LogDenied, 1026 0, 1027 YesNo, 1028 "[yes|no]", 1029 "enable logging of denied incoming packets", 1030 "log_denied", 1031 NULL }, 1032 1033 { LogFacility, 1034 0, 1035 String, 1036 "facility", 1037 "name of syslog facility to use for logging", 1038 "log_facility", 1039 NULL }, 1040 1041 { PunchFW, 1042 0, 1043 String, 1044 "basenumber:count", 1045 "punch holes in the firewall for incoming FTP/IRC DCC connections", 1046 "punch_fw", 1047 NULL }, 1048 1049 { LogIpfwDenied, 1050 0, 1051 YesNo, 1052 "[yes|no]", 1053 "log packets converted by natd, but denied by ipfw", 1054 "log_ipfw_denied", 1055 NULL }, 1056 { ExitDelay, 1057 0, 1058 Numeric, 1059 "ms", 1060 "delay in ms before daemon exit after signal", 1061 "exit_delay", 1062 NULL }, 1063 }; 1064 1065 static void 1066 ParseOption(const char *option, const char *parms) 1067 { 1068 int i; 1069 struct OptionInfo* info; 1070 int yesNoValue; 1071 int aliasValue; 1072 int numValue; 1073 u_short uNumValue; 1074 const char* strValue; 1075 struct in_addr addrValue; 1076 int max; 1077 char* end; 1078 CODE* fac_record = NULL; 1079 /* 1080 * Find option from table. 1081 */ 1082 max = NELEM(optionTable); 1083 for (i = 0, info = optionTable; i < max; i++, info++) { 1084 if (!strcmp(info->name, option)) 1085 break; 1086 1087 if (info->shortName) 1088 if (!strcmp(info->shortName, option)) 1089 break; 1090 } 1091 1092 if (i >= max) { 1093 warnx("unknown option %s", option); 1094 Usage(); 1095 } 1096 1097 uNumValue = 0; 1098 yesNoValue = 0; 1099 numValue = 0; 1100 strValue = NULL; 1101 /* 1102 * Check parameters. 1103 */ 1104 switch (info->parm) { 1105 case YesNo: 1106 if (!parms) 1107 parms = "yes"; 1108 1109 if (!strcmp(parms, "yes")) 1110 yesNoValue = 1; 1111 else 1112 if (!strcmp(parms, "no")) 1113 yesNoValue = 0; 1114 else 1115 errx(1, "%s needs yes/no parameter", option); 1116 break; 1117 1118 case Service: 1119 if (!parms) 1120 errx(1, "%s needs service name or " 1121 "port number parameter", 1122 option); 1123 1124 uNumValue = StrToPort(parms, "divert"); 1125 break; 1126 1127 case Numeric: 1128 if (parms) 1129 numValue = strtol(parms, &end, 10); 1130 else 1131 end = NULL; 1132 1133 if (end == parms) 1134 errx(1, "%s needs numeric parameter", option); 1135 break; 1136 1137 case String: 1138 strValue = parms; 1139 if (!strValue) 1140 errx(1, "%s needs parameter", option); 1141 break; 1142 1143 case None: 1144 if (parms) 1145 errx(1, "%s does not take parameters", option); 1146 break; 1147 1148 case Address: 1149 if (!parms) 1150 errx(1, "%s needs address/host parameter", option); 1151 1152 StrToAddr(parms, &addrValue); 1153 break; 1154 } 1155 1156 switch (info->type) { 1157 case PacketAliasOption: 1158 1159 aliasValue = yesNoValue ? info->packetAliasOpt : 0; 1160 PacketAliasSetMode(aliasValue, info->packetAliasOpt); 1161 break; 1162 1163 case Verbose: 1164 verbose = yesNoValue; 1165 break; 1166 1167 case DynamicMode: 1168 dynamicMode = yesNoValue; 1169 break; 1170 1171 case InPort: 1172 inPort = uNumValue; 1173 break; 1174 1175 case OutPort: 1176 outPort = uNumValue; 1177 break; 1178 1179 case Port: 1180 inOutPort = uNumValue; 1181 break; 1182 1183 case AliasAddress: 1184 memcpy(&aliasAddr, &addrValue, sizeof(struct in_addr)); 1185 break; 1186 1187 case TargetAddress: 1188 PacketAliasSetTarget(addrValue); 1189 break; 1190 1191 case RedirectPort: 1192 SetupPortRedirect(strValue); 1193 break; 1194 1195 case RedirectProto: 1196 SetupProtoRedirect(strValue); 1197 break; 1198 1199 case RedirectAddress: 1200 SetupAddressRedirect(strValue); 1201 break; 1202 1203 case ProxyRule: 1204 PacketAliasProxyRule(strValue); 1205 break; 1206 1207 case InterfaceName: 1208 if (ifName) 1209 free(ifName); 1210 1211 ifName = strdup(strValue); 1212 break; 1213 1214 case ConfigFile: 1215 ReadConfigFile(strValue); 1216 break; 1217 1218 case LogDenied: 1219 logDropped = yesNoValue; 1220 break; 1221 1222 case LogFacility: 1223 1224 fac_record = facilitynames; 1225 while (fac_record->c_name != NULL) { 1226 if (!strcmp(fac_record->c_name, strValue)) { 1227 logFacility = fac_record->c_val; 1228 break; 1229 1230 } else 1231 fac_record++; 1232 } 1233 1234 if(fac_record->c_name == NULL) 1235 errx(1, "Unknown log facility name: %s", strValue); 1236 1237 break; 1238 1239 case PunchFW: 1240 SetupPunchFW(strValue); 1241 break; 1242 1243 case LogIpfwDenied: 1244 logIpfwDenied = yesNoValue; 1245 break; 1246 case ExitDelay: 1247 if (numValue < 0 || numValue > MAX_EXIT_DELAY) 1248 errx(1, "Incorrect exit delay: %d", numValue); 1249 exitDelay = numValue; 1250 break; 1251 } 1252 } 1253 1254 void 1255 ReadConfigFile(const char *fileName) 1256 { 1257 FILE* file; 1258 char *buf; 1259 size_t len; 1260 char *ptr, *p; 1261 char* option; 1262 1263 file = fopen(fileName, "r"); 1264 if (!file) 1265 err(1, "cannot open config file %s", fileName); 1266 1267 while ((buf = fgetln(file, &len)) != NULL) { 1268 if (buf[len - 1] == '\n') 1269 buf[len - 1] = '\0'; 1270 else 1271 errx(1, "config file format error: " 1272 "last line should end with newline"); 1273 1274 /* 1275 * Check for comments, strip off trailing spaces. 1276 */ 1277 if ((ptr = strchr(buf, '#'))) 1278 *ptr = '\0'; 1279 for (ptr = buf; isspace(*ptr); ++ptr) 1280 continue; 1281 if (*ptr == '\0') 1282 continue; 1283 for (p = strchr(buf, '\0'); isspace(*--p);) 1284 continue; 1285 *++p = '\0'; 1286 1287 /* 1288 * Extract option name. 1289 */ 1290 option = ptr; 1291 while (*ptr && !isspace(*ptr)) 1292 ++ptr; 1293 1294 if (*ptr != '\0') { 1295 *ptr = '\0'; 1296 ++ptr; 1297 } 1298 /* 1299 * Skip white space between name and parms. 1300 */ 1301 while (*ptr && isspace(*ptr)) 1302 ++ptr; 1303 1304 ParseOption(option, *ptr ? ptr : NULL); 1305 } 1306 1307 fclose(file); 1308 } 1309 1310 static void 1311 Usage(void) 1312 { 1313 int i; 1314 int max; 1315 struct OptionInfo* info; 1316 1317 fprintf(stderr, "Recognized options:\n\n"); 1318 1319 max = NELEM(optionTable); 1320 for (i = 0, info = optionTable; i < max; i++, info++) { 1321 fprintf(stderr, "-%-20s %s\n", info->name, 1322 info->parmDescription); 1323 1324 if (info->shortName) 1325 fprintf(stderr, "-%-20s %s\n", info->shortName, 1326 info->parmDescription); 1327 1328 fprintf(stderr, " %s\n\n", info->description); 1329 } 1330 1331 exit(1); 1332 } 1333 1334 void 1335 SetupPortRedirect(const char *parms) 1336 { 1337 char buf[128]; 1338 char* ptr; 1339 char* serverPool; 1340 struct in_addr localAddr; 1341 struct in_addr publicAddr; 1342 struct in_addr remoteAddr; 1343 port_range portRange; 1344 u_short localPort = 0; 1345 u_short publicPort = 0; 1346 u_short remotePort = 0; 1347 u_short numLocalPorts = 0; 1348 u_short numPublicPorts = 0; 1349 u_short numRemotePorts = 0; 1350 int proto; 1351 char* protoName; 1352 char* separator; 1353 int i; 1354 struct alias_link *alink = NULL; 1355 1356 strcpy(buf, parms); 1357 /* 1358 * Extract protocol. 1359 */ 1360 protoName = strtok(buf, " \t"); 1361 if (!protoName) 1362 errx(1, "redirect_port: missing protocol"); 1363 1364 proto = StrToProto(protoName); 1365 /* 1366 * Extract local address. 1367 */ 1368 ptr = strtok(NULL, " \t"); 1369 if (!ptr) 1370 errx(1, "redirect_port: missing local address"); 1371 1372 separator = strchr(ptr, ','); 1373 if (separator) { /* LSNAT redirection syntax. */ 1374 localAddr.s_addr = INADDR_NONE; 1375 localPort = ~0; 1376 numLocalPorts = 1; 1377 serverPool = ptr; 1378 } else { 1379 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0 ) 1380 errx(1, "redirect_port: invalid local port range"); 1381 1382 localPort = GETLOPORT(portRange); 1383 numLocalPorts = GETNUMPORTS(portRange); 1384 serverPool = NULL; 1385 } 1386 1387 /* 1388 * Extract public port and optionally address. 1389 */ 1390 ptr = strtok(NULL, " \t"); 1391 if (!ptr) 1392 errx(1, "redirect_port: missing public port"); 1393 1394 separator = strchr(ptr, ':'); 1395 if (separator) { 1396 if (StrToAddrAndPortRange(ptr, &publicAddr, protoName, &portRange) != 0 ) 1397 errx(1, "redirect_port: invalid public port range"); 1398 } else { 1399 publicAddr.s_addr = INADDR_ANY; 1400 if (StrToPortRange(ptr, protoName, &portRange) != 0) 1401 errx(1, "redirect_port: invalid public port range"); 1402 } 1403 1404 publicPort = GETLOPORT(portRange); 1405 numPublicPorts = GETNUMPORTS(portRange); 1406 1407 /* 1408 * Extract remote address and optionally port. 1409 */ 1410 ptr = strtok(NULL, " \t"); 1411 if (ptr) { 1412 separator = strchr(ptr, ':'); 1413 if (separator) { 1414 if (StrToAddrAndPortRange(ptr, &remoteAddr, protoName, &portRange) != 0) 1415 errx(1, "redirect_port: invalid remote port range"); 1416 } else { 1417 SETLOPORT(portRange, 0); 1418 SETNUMPORTS(portRange, 1); 1419 StrToAddr(ptr, &remoteAddr); 1420 } 1421 } else { 1422 SETLOPORT(portRange, 0); 1423 SETNUMPORTS(portRange, 1); 1424 remoteAddr.s_addr = INADDR_ANY; 1425 } 1426 1427 remotePort = GETLOPORT(portRange); 1428 numRemotePorts = GETNUMPORTS(portRange); 1429 1430 /* 1431 * Make sure port ranges match up, then add the redirect ports. 1432 */ 1433 if (numLocalPorts != numPublicPorts) 1434 errx(1, "redirect_port: port ranges must be equal in size"); 1435 1436 /* Remote port range is allowed to be '0' which means all ports. */ 1437 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0)) 1438 errx(1, "redirect_port: remote port must be 0 or equal to local port range in size"); 1439 1440 for (i = 0 ; i < numPublicPorts ; ++i) { 1441 /* If remotePort is all ports, set it to 0. */ 1442 u_short remotePortCopy = remotePort + i; 1443 if (numRemotePorts == 1 && remotePort == 0) 1444 remotePortCopy = 0; 1445 1446 alink = PacketAliasRedirectPort(localAddr, 1447 htons(localPort + i), 1448 remoteAddr, 1449 htons(remotePortCopy), 1450 publicAddr, 1451 htons(publicPort + i), 1452 proto); 1453 } 1454 1455 /* 1456 * Setup LSNAT server pool. 1457 */ 1458 if (serverPool != NULL && alink != NULL) { 1459 ptr = strtok(serverPool, ","); 1460 while (ptr != NULL) { 1461 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0) 1462 errx(1, "redirect_port: invalid local port range"); 1463 1464 localPort = GETLOPORT(portRange); 1465 if (GETNUMPORTS(portRange) != 1) 1466 errx(1, "redirect_port: local port must be single in this context"); 1467 PacketAliasAddServer(alink, localAddr, htons(localPort)); 1468 ptr = strtok(NULL, ","); 1469 } 1470 } 1471 } 1472 1473 void 1474 SetupProtoRedirect(const char *parms) 1475 { 1476 char buf[128]; 1477 char* ptr; 1478 struct in_addr localAddr; 1479 struct in_addr publicAddr; 1480 struct in_addr remoteAddr; 1481 int proto; 1482 char* protoName; 1483 struct protoent *protoent; 1484 1485 strcpy(buf, parms); 1486 /* 1487 * Extract protocol. 1488 */ 1489 protoName = strtok(buf, " \t"); 1490 if (!protoName) 1491 errx(1, "redirect_proto: missing protocol"); 1492 1493 protoent = getprotobyname(protoName); 1494 if (protoent == NULL) 1495 errx(1, "redirect_proto: unknown protocol %s", protoName); 1496 else 1497 proto = protoent->p_proto; 1498 /* 1499 * Extract local address. 1500 */ 1501 ptr = strtok(NULL, " \t"); 1502 if (!ptr) 1503 errx(1, "redirect_proto: missing local address"); 1504 else 1505 StrToAddr(ptr, &localAddr); 1506 /* 1507 * Extract optional public address. 1508 */ 1509 ptr = strtok(NULL, " \t"); 1510 if (ptr) 1511 StrToAddr(ptr, &publicAddr); 1512 else 1513 publicAddr.s_addr = INADDR_ANY; 1514 /* 1515 * Extract optional remote address. 1516 */ 1517 ptr = strtok(NULL, " \t"); 1518 if (ptr) 1519 StrToAddr(ptr, &remoteAddr); 1520 else 1521 remoteAddr.s_addr = INADDR_ANY; 1522 /* 1523 * Create aliasing link. 1524 */ 1525 PacketAliasRedirectProto(localAddr, remoteAddr, publicAddr, proto); 1526 } 1527 1528 void 1529 SetupAddressRedirect(const char *parms) 1530 { 1531 char buf[128]; 1532 char* ptr; 1533 char* separator; 1534 struct in_addr localAddr; 1535 struct in_addr publicAddr; 1536 char* serverPool; 1537 struct alias_link *alink; 1538 1539 strcpy(buf, parms); 1540 /* 1541 * Extract local address. 1542 */ 1543 ptr = strtok(buf, " \t"); 1544 if (!ptr) 1545 errx(1, "redirect_address: missing local address"); 1546 1547 separator = strchr(ptr, ','); 1548 if (separator) { /* LSNAT redirection syntax. */ 1549 localAddr.s_addr = INADDR_NONE; 1550 serverPool = ptr; 1551 } else { 1552 StrToAddr(ptr, &localAddr); 1553 serverPool = NULL; 1554 } 1555 /* 1556 * Extract public address. 1557 */ 1558 ptr = strtok(NULL, " \t"); 1559 if (!ptr) 1560 errx(1, "redirect_address: missing public address"); 1561 1562 StrToAddr(ptr, &publicAddr); 1563 alink = PacketAliasRedirectAddr(localAddr, publicAddr); 1564 1565 /* 1566 * Setup LSNAT server pool. 1567 */ 1568 if (serverPool != NULL && alink != NULL) { 1569 ptr = strtok(serverPool, ","); 1570 while (ptr != NULL) { 1571 StrToAddr(ptr, &localAddr); 1572 PacketAliasAddServer(alink, localAddr, htons(~0)); 1573 ptr = strtok(NULL, ","); 1574 } 1575 } 1576 } 1577 1578 void 1579 StrToAddr(const char *str, struct in_addr *addr) 1580 { 1581 struct hostent *hp; 1582 1583 if (inet_aton(str, addr)) 1584 return; 1585 1586 hp = gethostbyname(str); 1587 if (!hp) 1588 errx(1, "unknown host %s", str); 1589 1590 memcpy(addr, hp->h_addr, sizeof(struct in_addr)); 1591 } 1592 1593 u_short 1594 StrToPort(const char *str, const char *proto) 1595 { 1596 u_short port; 1597 struct servent* sp; 1598 char* end; 1599 1600 port = strtol(str, &end, 10); 1601 if (end != str) 1602 return htons(port); 1603 1604 sp = getservbyname(str, proto); 1605 if (!sp) 1606 errx(1, "unknown service %s/%s", str, proto); 1607 1608 return sp->s_port; 1609 } 1610 1611 int 1612 StrToPortRange(const char *str, const char *proto, port_range *portRange) 1613 { 1614 char* sep; 1615 struct servent* sp; 1616 char* end; 1617 u_short loPort; 1618 u_short hiPort; 1619 1620 /* First see if this is a service, return corresponding port if so. */ 1621 sp = getservbyname(str,proto); 1622 if (sp) { 1623 SETLOPORT(*portRange, ntohs(sp->s_port)); 1624 SETNUMPORTS(*portRange, 1); 1625 return 0; 1626 } 1627 1628 /* Not a service, see if it's a single port or port range. */ 1629 sep = strchr(str, '-'); 1630 if (sep == NULL) { 1631 SETLOPORT(*portRange, strtol(str, &end, 10)); 1632 if (end != str) { 1633 /* Single port. */ 1634 SETNUMPORTS(*portRange, 1); 1635 return 0; 1636 } 1637 1638 /* Error in port range field. */ 1639 errx(1, "unknown service %s/%s", str, proto); 1640 } 1641 1642 /* Port range, get the values and sanity check. */ 1643 sscanf(str, "%hu-%hu", &loPort, &hiPort); 1644 SETLOPORT(*portRange, loPort); 1645 SETNUMPORTS(*portRange, 0); /* Error by default */ 1646 if (loPort <= hiPort) 1647 SETNUMPORTS(*portRange, hiPort - loPort + 1); 1648 1649 if (GETNUMPORTS(*portRange) == 0) 1650 errx(1, "invalid port range %s", str); 1651 1652 return 0; 1653 } 1654 1655 1656 int 1657 StrToProto(const char *str) 1658 { 1659 if (!strcmp(str, "tcp")) 1660 return IPPROTO_TCP; 1661 1662 if (!strcmp(str, "udp")) 1663 return IPPROTO_UDP; 1664 1665 errx(1, "unknown protocol %s. Expected tcp or udp", str); 1666 } 1667 1668 int 1669 StrToAddrAndPortRange(const char *str, struct in_addr *addr, char *proto, port_range *portRange) 1670 { 1671 char* ptr; 1672 1673 ptr = strchr(str, ':'); 1674 if (!ptr) 1675 errx(1, "%s is missing port number", str); 1676 1677 *ptr = '\0'; 1678 ++ptr; 1679 1680 StrToAddr(str, addr); 1681 return StrToPortRange(ptr, proto, portRange); 1682 } 1683 1684 static void 1685 SetupPunchFW(const char *strValue) 1686 { 1687 unsigned int base, num; 1688 1689 if (sscanf(strValue, "%u:%u", &base, &num) != 2) 1690 errx(1, "punch_fw: basenumber:count parameter required"); 1691 1692 PacketAliasSetFWBase(base, num); 1693 PacketAliasSetMode(PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW); 1694 } 1695