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