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, int cmdLine); 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 SetupPptpAlias (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 FlushPacketBuffer (int fd); 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, 0); 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), 1); 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 (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 InterfaceName, 864 RedirectPort, 865 RedirectProto, 866 RedirectAddress, 867 ConfigFile, 868 DynamicMode, 869 PptpAlias, 870 ProxyRule, 871 LogDenied, 872 LogFacility 873 }; 874 875 enum Param { 876 877 YesNo, 878 Numeric, 879 String, 880 None, 881 Address, 882 Service 883 }; 884 885 /* 886 * Option information structure (used by ParseOption). 887 */ 888 889 struct OptionInfo { 890 891 enum Option type; 892 int packetAliasOpt; 893 enum Param parm; 894 const char* parmDescription; 895 const char* description; 896 const char* name; 897 const char* shortName; 898 }; 899 900 /* 901 * Table of known options. 902 */ 903 904 static struct OptionInfo optionTable[] = { 905 906 { PacketAliasOption, 907 PKT_ALIAS_UNREGISTERED_ONLY, 908 YesNo, 909 "[yes|no]", 910 "alias only unregistered addresses", 911 "unregistered_only", 912 "u" }, 913 914 { PacketAliasOption, 915 PKT_ALIAS_LOG, 916 YesNo, 917 "[yes|no]", 918 "enable logging", 919 "log", 920 "l" }, 921 922 { PacketAliasOption, 923 PKT_ALIAS_PROXY_ONLY, 924 YesNo, 925 "[yes|no]", 926 "proxy only", 927 "proxy_only", 928 NULL }, 929 930 { PacketAliasOption, 931 PKT_ALIAS_REVERSE, 932 YesNo, 933 "[yes|no]", 934 "operate in reverse mode", 935 "reverse", 936 NULL }, 937 938 { PacketAliasOption, 939 PKT_ALIAS_DENY_INCOMING, 940 YesNo, 941 "[yes|no]", 942 "allow incoming connections", 943 "deny_incoming", 944 "d" }, 945 946 { PacketAliasOption, 947 PKT_ALIAS_USE_SOCKETS, 948 YesNo, 949 "[yes|no]", 950 "use sockets to inhibit port conflict", 951 "use_sockets", 952 "s" }, 953 954 { PacketAliasOption, 955 PKT_ALIAS_SAME_PORTS, 956 YesNo, 957 "[yes|no]", 958 "try to keep original port numbers for connections", 959 "same_ports", 960 "m" }, 961 962 { Verbose, 963 0, 964 YesNo, 965 "[yes|no]", 966 "verbose mode, dump packet information", 967 "verbose", 968 "v" }, 969 970 { DynamicMode, 971 0, 972 YesNo, 973 "[yes|no]", 974 "dynamic mode, automatically detect interface address changes", 975 "dynamic", 976 NULL }, 977 978 { InPort, 979 0, 980 Service, 981 "number|service_name", 982 "set port for incoming packets", 983 "in_port", 984 "i" }, 985 986 { OutPort, 987 0, 988 Service, 989 "number|service_name", 990 "set port for outgoing packets", 991 "out_port", 992 "o" }, 993 994 { Port, 995 0, 996 Service, 997 "number|service_name", 998 "set port (defaults to natd/divert)", 999 "port", 1000 "p" }, 1001 1002 { AliasAddress, 1003 0, 1004 Address, 1005 "x.x.x.x", 1006 "address to use for aliasing", 1007 "alias_address", 1008 "a" }, 1009 1010 { InterfaceName, 1011 0, 1012 String, 1013 "network_if_name", 1014 "take aliasing address from interface", 1015 "interface", 1016 "n" }, 1017 1018 { ProxyRule, 1019 0, 1020 String, 1021 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " 1022 "a.b.c.d:yyyy", 1023 "add transparent proxying / destination NAT", 1024 "proxy_rule", 1025 NULL }, 1026 1027 { RedirectPort, 1028 0, 1029 String, 1030 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range" 1031 " [remote_addr[:remote_port_range]]", 1032 "redirect a port (or ports) for incoming traffic", 1033 "redirect_port", 1034 NULL }, 1035 1036 { RedirectProto, 1037 0, 1038 String, 1039 "proto local_addr [public_addr] [remote_addr]", 1040 "redirect packets of a given proto", 1041 "redirect_proto", 1042 NULL }, 1043 1044 { RedirectAddress, 1045 0, 1046 String, 1047 "local_addr[,...] public_addr", 1048 "define mapping between local and public addresses", 1049 "redirect_address", 1050 NULL }, 1051 1052 { PptpAlias, 1053 0, 1054 String, 1055 "src", 1056 "define inside machine for PPTP traffic", 1057 "pptpalias", 1058 NULL }, 1059 1060 { ConfigFile, 1061 0, 1062 String, 1063 "file_name", 1064 "read options from configuration file", 1065 "config", 1066 "f" }, 1067 1068 { LogDenied, 1069 0, 1070 YesNo, 1071 "[yes|no]", 1072 "enable logging of denied incoming packets", 1073 "log_denied", 1074 NULL }, 1075 1076 { LogFacility, 1077 0, 1078 String, 1079 "facility", 1080 "name of syslog facility to use for logging", 1081 "log_facility", 1082 NULL } 1083 1084 }; 1085 1086 static void ParseOption (const char* option, const char* parms, int cmdLine) 1087 { 1088 int i; 1089 struct OptionInfo* info; 1090 int yesNoValue; 1091 int aliasValue; 1092 int numValue; 1093 u_short uNumValue; 1094 const char* strValue; 1095 struct in_addr addrValue; 1096 int max; 1097 char* end; 1098 CODE* fac_record = NULL; 1099 /* 1100 * Find option from table. 1101 */ 1102 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1103 for (i = 0, info = optionTable; i < max; i++, info++) { 1104 1105 if (!strcmp (info->name, option)) 1106 break; 1107 1108 if (info->shortName) 1109 if (!strcmp (info->shortName, option)) 1110 break; 1111 } 1112 1113 if (i >= max) { 1114 1115 warnx ("unknown option %s", option); 1116 Usage (); 1117 } 1118 1119 uNumValue = 0; 1120 yesNoValue = 0; 1121 numValue = 0; 1122 strValue = NULL; 1123 /* 1124 * Check parameters. 1125 */ 1126 switch (info->parm) { 1127 case YesNo: 1128 if (!parms) 1129 parms = "yes"; 1130 1131 if (!strcmp (parms, "yes")) 1132 yesNoValue = 1; 1133 else 1134 if (!strcmp (parms, "no")) 1135 yesNoValue = 0; 1136 else 1137 errx (1, "%s needs yes/no parameter", option); 1138 break; 1139 1140 case Service: 1141 if (!parms) 1142 errx (1, "%s needs service name or " 1143 "port number parameter", 1144 option); 1145 1146 uNumValue = StrToPort (parms, "divert"); 1147 break; 1148 1149 case Numeric: 1150 if (parms) 1151 numValue = strtol (parms, &end, 10); 1152 else 1153 end = NULL; 1154 1155 if (end == parms) 1156 errx (1, "%s needs numeric parameter", option); 1157 break; 1158 1159 case String: 1160 strValue = parms; 1161 if (!strValue) 1162 errx (1, "%s needs parameter", option); 1163 break; 1164 1165 case None: 1166 if (parms) 1167 errx (1, "%s does not take parameters", option); 1168 break; 1169 1170 case Address: 1171 if (!parms) 1172 errx (1, "%s needs address/host parameter", option); 1173 1174 StrToAddr (parms, &addrValue); 1175 break; 1176 } 1177 1178 switch (info->type) { 1179 case PacketAliasOption: 1180 1181 aliasValue = yesNoValue ? info->packetAliasOpt : 0; 1182 PacketAliasSetMode (aliasValue, info->packetAliasOpt); 1183 break; 1184 1185 case Verbose: 1186 verbose = yesNoValue; 1187 break; 1188 1189 case DynamicMode: 1190 dynamicMode = yesNoValue; 1191 break; 1192 1193 case InPort: 1194 inPort = uNumValue; 1195 break; 1196 1197 case OutPort: 1198 outPort = uNumValue; 1199 break; 1200 1201 case Port: 1202 inOutPort = uNumValue; 1203 break; 1204 1205 case AliasAddress: 1206 memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); 1207 break; 1208 1209 case RedirectPort: 1210 SetupPortRedirect (strValue); 1211 break; 1212 1213 case RedirectProto: 1214 SetupProtoRedirect(strValue); 1215 break; 1216 1217 case RedirectAddress: 1218 SetupAddressRedirect (strValue); 1219 break; 1220 1221 case PptpAlias: 1222 SetupPptpAlias (strValue); 1223 break; 1224 1225 case ProxyRule: 1226 PacketAliasProxyRule (strValue); 1227 break; 1228 1229 case InterfaceName: 1230 if (ifName) 1231 free (ifName); 1232 1233 ifName = strdup (strValue); 1234 break; 1235 1236 case ConfigFile: 1237 ReadConfigFile (strValue); 1238 break; 1239 1240 case LogDenied: 1241 logDropped = 1; 1242 break; 1243 1244 case LogFacility: 1245 1246 fac_record = facilitynames; 1247 while (fac_record->c_name != NULL) { 1248 1249 if (!strcmp (fac_record->c_name, strValue)) { 1250 1251 logFacility = fac_record->c_val; 1252 break; 1253 1254 } 1255 else 1256 fac_record++; 1257 } 1258 1259 if(fac_record->c_name == NULL) 1260 errx(1, "Unknown log facility name: %s", strValue); 1261 1262 break; 1263 } 1264 } 1265 1266 void ReadConfigFile (const char* fileName) 1267 { 1268 FILE* file; 1269 char *buf; 1270 size_t len; 1271 char *ptr, *p; 1272 char* option; 1273 1274 file = fopen (fileName, "r"); 1275 if (!file) 1276 err(1, "cannot open config file %s", fileName); 1277 1278 while ((buf = fgetln(file, &len)) != NULL) { 1279 if (buf[len - 1] == '\n') 1280 buf[len - 1] = '\0'; 1281 else 1282 errx(1, "config file format error: " 1283 "last line should end with newline"); 1284 1285 /* 1286 * Check for comments, strip off trailing spaces. 1287 */ 1288 if ((ptr = strchr(buf, '#'))) 1289 *ptr = '\0'; 1290 for (ptr = buf; isspace(*ptr); ++ptr) 1291 continue; 1292 if (*ptr == '\0') 1293 continue; 1294 for (p = strchr(buf, '\0'); isspace(*--p);) 1295 continue; 1296 *++p = '\0'; 1297 1298 /* 1299 * Extract option name. 1300 */ 1301 option = ptr; 1302 while (*ptr && !isspace (*ptr)) 1303 ++ptr; 1304 1305 if (*ptr != '\0') { 1306 1307 *ptr = '\0'; 1308 ++ptr; 1309 } 1310 /* 1311 * Skip white space between name and parms. 1312 */ 1313 while (*ptr && isspace (*ptr)) 1314 ++ptr; 1315 1316 ParseOption (option, *ptr ? ptr : NULL, 0); 1317 } 1318 1319 fclose (file); 1320 } 1321 1322 static void Usage () 1323 { 1324 int i; 1325 int max; 1326 struct OptionInfo* info; 1327 1328 fprintf (stderr, "Recognized options:\n\n"); 1329 1330 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1331 for (i = 0, info = optionTable; i < max; i++, info++) { 1332 1333 fprintf (stderr, "-%-20s %s\n", info->name, 1334 info->parmDescription); 1335 1336 if (info->shortName) 1337 fprintf (stderr, "-%-20s %s\n", info->shortName, 1338 info->parmDescription); 1339 1340 fprintf (stderr, " %s\n\n", info->description); 1341 } 1342 1343 exit (1); 1344 } 1345 1346 void SetupPptpAlias (const char* parms) 1347 { 1348 char buf[128]; 1349 char* ptr; 1350 struct in_addr srcAddr; 1351 1352 strcpy (buf, parms); 1353 1354 /* 1355 * Extract source address. 1356 */ 1357 ptr = strtok (buf, " \t"); 1358 if (!ptr) 1359 errx(1, "pptpalias: missing src address"); 1360 1361 StrToAddr (ptr, &srcAddr); 1362 PacketAliasPptp (srcAddr); 1363 } 1364 1365 void SetupPortRedirect (const char* parms) 1366 { 1367 char buf[128]; 1368 char* ptr; 1369 char* serverPool; 1370 struct in_addr localAddr; 1371 struct in_addr publicAddr; 1372 struct in_addr remoteAddr; 1373 port_range portRange; 1374 u_short localPort = 0; 1375 u_short publicPort = 0; 1376 u_short remotePort = 0; 1377 u_short numLocalPorts = 0; 1378 u_short numPublicPorts = 0; 1379 u_short numRemotePorts = 0; 1380 int proto; 1381 char* protoName; 1382 char* separator; 1383 int i; 1384 struct alias_link *link = NULL; 1385 1386 strcpy (buf, parms); 1387 /* 1388 * Extract protocol. 1389 */ 1390 protoName = strtok (buf, " \t"); 1391 if (!protoName) 1392 errx (1, "redirect_port: missing protocol"); 1393 1394 proto = StrToProto (protoName); 1395 /* 1396 * Extract local address. 1397 */ 1398 ptr = strtok (NULL, " \t"); 1399 if (!ptr) 1400 errx (1, "redirect_port: missing local address"); 1401 1402 separator = strchr(ptr, ','); 1403 if (separator) { /* LSNAT redirection syntax. */ 1404 localAddr.s_addr = INADDR_NONE; 1405 localPort = ~0; 1406 numLocalPorts = 1; 1407 serverPool = ptr; 1408 } else { 1409 if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 ) 1410 errx (1, "redirect_port: invalid local port range"); 1411 1412 localPort = GETLOPORT(portRange); 1413 numLocalPorts = GETNUMPORTS(portRange); 1414 serverPool = NULL; 1415 } 1416 1417 /* 1418 * Extract public port and optionally address. 1419 */ 1420 ptr = strtok (NULL, " \t"); 1421 if (!ptr) 1422 errx (1, "redirect_port: missing public port"); 1423 1424 separator = strchr (ptr, ':'); 1425 if (separator) { 1426 if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 ) 1427 errx (1, "redirect_port: invalid public port range"); 1428 } 1429 else { 1430 publicAddr.s_addr = INADDR_ANY; 1431 if (StrToPortRange (ptr, protoName, &portRange) != 0) 1432 errx (1, "redirect_port: invalid public port range"); 1433 } 1434 1435 publicPort = GETLOPORT(portRange); 1436 numPublicPorts = GETNUMPORTS(portRange); 1437 1438 /* 1439 * Extract remote address and optionally port. 1440 */ 1441 ptr = strtok (NULL, " \t"); 1442 if (ptr) { 1443 separator = strchr (ptr, ':'); 1444 if (separator) { 1445 if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0) 1446 errx (1, "redirect_port: invalid remote port range"); 1447 } else { 1448 SETLOPORT(portRange, 0); 1449 SETNUMPORTS(portRange, 1); 1450 StrToAddr (ptr, &remoteAddr); 1451 } 1452 } 1453 else { 1454 SETLOPORT(portRange, 0); 1455 SETNUMPORTS(portRange, 1); 1456 remoteAddr.s_addr = INADDR_ANY; 1457 } 1458 1459 remotePort = GETLOPORT(portRange); 1460 numRemotePorts = GETNUMPORTS(portRange); 1461 1462 /* 1463 * Make sure port ranges match up, then add the redirect ports. 1464 */ 1465 if (numLocalPorts != numPublicPorts) 1466 errx (1, "redirect_port: port ranges must be equal in size"); 1467 1468 /* Remote port range is allowed to be '0' which means all ports. */ 1469 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0)) 1470 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size"); 1471 1472 for (i = 0 ; i < numPublicPorts ; ++i) { 1473 /* If remotePort is all ports, set it to 0. */ 1474 u_short remotePortCopy = remotePort + i; 1475 if (numRemotePorts == 1 && remotePort == 0) 1476 remotePortCopy = 0; 1477 1478 link = PacketAliasRedirectPort (localAddr, 1479 htons(localPort + i), 1480 remoteAddr, 1481 htons(remotePortCopy), 1482 publicAddr, 1483 htons(publicPort + i), 1484 proto); 1485 } 1486 1487 /* 1488 * Setup LSNAT server pool. 1489 */ 1490 if (serverPool != NULL && link != NULL) { 1491 ptr = strtok(serverPool, ","); 1492 while (ptr != NULL) { 1493 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0) 1494 errx(1, "redirect_port: invalid local port range"); 1495 1496 localPort = GETLOPORT(portRange); 1497 if (GETNUMPORTS(portRange) != 1) 1498 errx(1, "redirect_port: local port must be single in this context"); 1499 PacketAliasAddServer(link, localAddr, htons(localPort)); 1500 ptr = strtok(NULL, ","); 1501 } 1502 } 1503 } 1504 1505 void 1506 SetupProtoRedirect(const char* parms) 1507 { 1508 char buf[128]; 1509 char* ptr; 1510 struct in_addr localAddr; 1511 struct in_addr publicAddr; 1512 struct in_addr remoteAddr; 1513 int proto; 1514 char* protoName; 1515 struct protoent *protoent; 1516 1517 strcpy (buf, parms); 1518 /* 1519 * Extract protocol. 1520 */ 1521 protoName = strtok(buf, " \t"); 1522 if (!protoName) 1523 errx(1, "redirect_proto: missing protocol"); 1524 1525 protoent = getprotobyname(protoName); 1526 if (protoent == NULL) 1527 errx(1, "redirect_proto: unknown protocol %s", protoName); 1528 else 1529 proto = protoent->p_proto; 1530 /* 1531 * Extract local address. 1532 */ 1533 ptr = strtok(NULL, " \t"); 1534 if (!ptr) 1535 errx(1, "redirect_proto: missing local address"); 1536 else 1537 StrToAddr(ptr, &localAddr); 1538 /* 1539 * Extract optional public address. 1540 */ 1541 ptr = strtok(NULL, " \t"); 1542 if (ptr) 1543 StrToAddr(ptr, &publicAddr); 1544 else 1545 publicAddr.s_addr = INADDR_ANY; 1546 /* 1547 * Extract optional remote address. 1548 */ 1549 ptr = strtok(NULL, " \t"); 1550 if (ptr) 1551 StrToAddr(ptr, &remoteAddr); 1552 else 1553 remoteAddr.s_addr = INADDR_ANY; 1554 /* 1555 * Create aliasing link. 1556 */ 1557 (void)PacketAliasRedirectProto(localAddr, remoteAddr, publicAddr, 1558 proto); 1559 } 1560 1561 void SetupAddressRedirect (const char* parms) 1562 { 1563 char buf[128]; 1564 char* ptr; 1565 char* separator; 1566 struct in_addr localAddr; 1567 struct in_addr publicAddr; 1568 char* serverPool; 1569 struct alias_link *link; 1570 1571 strcpy (buf, parms); 1572 /* 1573 * Extract local address. 1574 */ 1575 ptr = strtok (buf, " \t"); 1576 if (!ptr) 1577 errx (1, "redirect_address: missing local address"); 1578 1579 separator = strchr(ptr, ','); 1580 if (separator) { /* LSNAT redirection syntax. */ 1581 localAddr.s_addr = INADDR_NONE; 1582 serverPool = ptr; 1583 } else { 1584 StrToAddr (ptr, &localAddr); 1585 serverPool = NULL; 1586 } 1587 /* 1588 * Extract public address. 1589 */ 1590 ptr = strtok (NULL, " \t"); 1591 if (!ptr) 1592 errx (1, "redirect_address: missing public address"); 1593 1594 StrToAddr (ptr, &publicAddr); 1595 link = PacketAliasRedirectAddr(localAddr, publicAddr); 1596 1597 /* 1598 * Setup LSNAT server pool. 1599 */ 1600 if (serverPool != NULL && link != NULL) { 1601 ptr = strtok(serverPool, ","); 1602 while (ptr != NULL) { 1603 StrToAddr(ptr, &localAddr); 1604 PacketAliasAddServer(link, localAddr, htons(~0)); 1605 ptr = strtok(NULL, ","); 1606 } 1607 } 1608 } 1609 1610 void StrToAddr (const char* str, struct in_addr* addr) 1611 { 1612 struct hostent* hp; 1613 1614 if (inet_aton (str, addr)) 1615 return; 1616 1617 hp = gethostbyname (str); 1618 if (!hp) 1619 errx (1, "unknown host %s", str); 1620 1621 memcpy (addr, hp->h_addr, sizeof (struct in_addr)); 1622 } 1623 1624 u_short StrToPort (const char* str, const char* proto) 1625 { 1626 u_short port; 1627 struct servent* sp; 1628 char* end; 1629 1630 port = strtol (str, &end, 10); 1631 if (end != str) 1632 return htons (port); 1633 1634 sp = getservbyname (str, proto); 1635 if (!sp) 1636 errx (1, "unknown service %s/%s", str, proto); 1637 1638 return sp->s_port; 1639 } 1640 1641 int StrToPortRange (const char* str, const char* proto, port_range *portRange) 1642 { 1643 char* sep; 1644 struct servent* sp; 1645 char* end; 1646 u_short loPort; 1647 u_short hiPort; 1648 1649 /* First see if this is a service, return corresponding port if so. */ 1650 sp = getservbyname (str,proto); 1651 if (sp) { 1652 SETLOPORT(*portRange, ntohs(sp->s_port)); 1653 SETNUMPORTS(*portRange, 1); 1654 return 0; 1655 } 1656 1657 /* Not a service, see if it's a single port or port range. */ 1658 sep = strchr (str, '-'); 1659 if (sep == NULL) { 1660 SETLOPORT(*portRange, strtol(str, &end, 10)); 1661 if (end != str) { 1662 /* Single port. */ 1663 SETNUMPORTS(*portRange, 1); 1664 return 0; 1665 } 1666 1667 /* Error in port range field. */ 1668 errx (1, "unknown service %s/%s", str, proto); 1669 } 1670 1671 /* Port range, get the values and sanity check. */ 1672 sscanf (str, "%hu-%hu", &loPort, &hiPort); 1673 SETLOPORT(*portRange, loPort); 1674 SETNUMPORTS(*portRange, 0); /* Error by default */ 1675 if (loPort <= hiPort) 1676 SETNUMPORTS(*portRange, hiPort - loPort + 1); 1677 1678 if (GETNUMPORTS(*portRange) == 0) 1679 errx (1, "invalid port range %s", str); 1680 1681 return 0; 1682 } 1683 1684 1685 int StrToProto (const char* str) 1686 { 1687 if (!strcmp (str, "tcp")) 1688 return IPPROTO_TCP; 1689 1690 if (!strcmp (str, "udp")) 1691 return IPPROTO_UDP; 1692 1693 errx (1, "unknown protocol %s. Expected tcp or udp", str); 1694 } 1695 1696 int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange) 1697 { 1698 char* ptr; 1699 1700 ptr = strchr (str, ':'); 1701 if (!ptr) 1702 errx (1, "%s is missing port number", str); 1703 1704 *ptr = '\0'; 1705 ++ptr; 1706 1707 StrToAddr (str, addr); 1708 return StrToPortRange (ptr, proto, portRange); 1709 } 1710