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