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