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