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