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