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 || ifMsg.ifm_type == RTM_IFINFO) && 646 ifMsg.ifm_index == ifIndex) { 647 if (verbose) 648 printf("Interface address/MTU has probably changed.\n"); 649 assignAliasAddr = 1; 650 } 651 } 652 653 static void PrintPacket (struct ip* ip) 654 { 655 printf ("%s", FormatPacket (ip)); 656 } 657 658 static void SyslogPacket (struct ip* ip, int priority, const char *label) 659 { 660 syslog (priority, "%s %s", label, FormatPacket (ip)); 661 } 662 663 static char* FormatPacket (struct ip* ip) 664 { 665 static char buf[256]; 666 struct tcphdr* tcphdr; 667 struct udphdr* udphdr; 668 struct icmp* icmphdr; 669 char src[20]; 670 char dst[20]; 671 672 strcpy (src, inet_ntoa (ip->ip_src)); 673 strcpy (dst, inet_ntoa (ip->ip_dst)); 674 675 switch (ip->ip_p) { 676 case IPPROTO_TCP: 677 tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); 678 sprintf (buf, "[TCP] %s:%d -> %s:%d", 679 src, 680 ntohs (tcphdr->th_sport), 681 dst, 682 ntohs (tcphdr->th_dport)); 683 break; 684 685 case IPPROTO_UDP: 686 udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2)); 687 sprintf (buf, "[UDP] %s:%d -> %s:%d", 688 src, 689 ntohs (udphdr->uh_sport), 690 dst, 691 ntohs (udphdr->uh_dport)); 692 break; 693 694 case IPPROTO_ICMP: 695 icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2)); 696 sprintf (buf, "[ICMP] %s -> %s %u(%u)", 697 src, 698 dst, 699 icmphdr->icmp_type, 700 icmphdr->icmp_code); 701 break; 702 703 default: 704 sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst); 705 break; 706 } 707 708 return buf; 709 } 710 711 static void 712 SetAliasAddressFromIfName(const char *ifn) 713 { 714 size_t needed; 715 int mib[6]; 716 char *buf, *lim, *next; 717 struct if_msghdr *ifm; 718 struct ifa_msghdr *ifam; 719 struct sockaddr_dl *sdl; 720 struct sockaddr_in *sin; 721 722 mib[0] = CTL_NET; 723 mib[1] = PF_ROUTE; 724 mib[2] = 0; 725 mib[3] = AF_INET; /* Only IP addresses please */ 726 mib[4] = NET_RT_IFLIST; 727 mib[5] = 0; /* ifIndex??? */ 728 /* 729 * Get interface data. 730 */ 731 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 732 err(1, "iflist-sysctl-estimate"); 733 if ((buf = malloc(needed)) == NULL) 734 errx(1, "malloc failed"); 735 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 736 err(1, "iflist-sysctl-get"); 737 lim = buf + needed; 738 /* 739 * Loop through interfaces until one with 740 * given name is found. This is done to 741 * find correct interface index for routing 742 * message processing. 743 */ 744 ifIndex = 0; 745 next = buf; 746 while (next < lim) { 747 ifm = (struct if_msghdr *)next; 748 next += ifm->ifm_msglen; 749 if (ifm->ifm_version != RTM_VERSION) { 750 if (verbose) 751 warnx("routing message version %d " 752 "not understood", ifm->ifm_version); 753 continue; 754 } 755 if (ifm->ifm_type == RTM_IFINFO) { 756 sdl = (struct sockaddr_dl *)(ifm + 1); 757 if (strlen(ifn) == sdl->sdl_nlen && 758 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) { 759 ifIndex = ifm->ifm_index; 760 ifMTU = ifm->ifm_data.ifi_mtu; 761 break; 762 } 763 } 764 } 765 if (!ifIndex) 766 errx(1, "unknown interface name %s", ifn); 767 /* 768 * Get interface address. 769 */ 770 sin = NULL; 771 while (next < lim) { 772 ifam = (struct ifa_msghdr *)next; 773 next += ifam->ifam_msglen; 774 if (ifam->ifam_version != RTM_VERSION) { 775 if (verbose) 776 warnx("routing message version %d " 777 "not understood", ifam->ifam_version); 778 continue; 779 } 780 if (ifam->ifam_type != RTM_NEWADDR) 781 break; 782 if (ifam->ifam_addrs & RTA_IFA) { 783 int i; 784 char *cp = (char *)(ifam + 1); 785 786 #define ROUNDUP(a) \ 787 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 788 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 789 790 for (i = 1; i < RTA_IFA; i <<= 1) 791 if (ifam->ifam_addrs & i) 792 ADVANCE(cp, (struct sockaddr *)cp); 793 if (((struct sockaddr *)cp)->sa_family == AF_INET) { 794 sin = (struct sockaddr_in *)cp; 795 break; 796 } 797 } 798 } 799 if (sin == NULL) 800 errx(1, "%s: cannot get interface address", ifn); 801 802 PacketAliasSetAddress(sin->sin_addr); 803 syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes", 804 inet_ntoa(sin->sin_addr), ifMTU); 805 806 free(buf); 807 } 808 809 void Quit (const char* msg) 810 { 811 Warn (msg); 812 exit (1); 813 } 814 815 void Warn (const char* msg) 816 { 817 if (background) 818 syslog (LOG_ALERT, "%s (%m)", msg); 819 else 820 warn (msg); 821 } 822 823 static void RefreshAddr (int sig) 824 { 825 if (ifName) 826 assignAliasAddr = 1; 827 } 828 829 static void InitiateShutdown (int sig) 830 { 831 /* 832 * Start timer to allow kernel gracefully 833 * shutdown existing connections when system 834 * is shut down. 835 */ 836 siginterrupt(SIGALRM, 1); 837 signal (SIGALRM, Shutdown); 838 alarm (10); 839 } 840 841 static void Shutdown (int sig) 842 { 843 running = 0; 844 } 845 846 /* 847 * Different options recognized by this program. 848 */ 849 850 enum Option { 851 852 PacketAliasOption, 853 Verbose, 854 InPort, 855 OutPort, 856 Port, 857 AliasAddress, 858 InterfaceName, 859 RedirectPort, 860 RedirectAddress, 861 ConfigFile, 862 DynamicMode, 863 PptpAlias, 864 ProxyRule, 865 LogDenied, 866 LogFacility 867 }; 868 869 enum Param { 870 871 YesNo, 872 Numeric, 873 String, 874 None, 875 Address, 876 Service 877 }; 878 879 /* 880 * Option information structure (used by ParseOption). 881 */ 882 883 struct OptionInfo { 884 885 enum Option type; 886 int packetAliasOpt; 887 enum Param parm; 888 const char* parmDescription; 889 const char* description; 890 const char* name; 891 const char* shortName; 892 }; 893 894 /* 895 * Table of known options. 896 */ 897 898 static struct OptionInfo optionTable[] = { 899 900 { PacketAliasOption, 901 PKT_ALIAS_UNREGISTERED_ONLY, 902 YesNo, 903 "[yes|no]", 904 "alias only unregistered addresses", 905 "unregistered_only", 906 "u" }, 907 908 { PacketAliasOption, 909 PKT_ALIAS_LOG, 910 YesNo, 911 "[yes|no]", 912 "enable logging", 913 "log", 914 "l" }, 915 916 { PacketAliasOption, 917 PKT_ALIAS_PROXY_ONLY, 918 YesNo, 919 "[yes|no]", 920 "proxy only", 921 "proxy_only", 922 NULL }, 923 924 { PacketAliasOption, 925 PKT_ALIAS_REVERSE, 926 YesNo, 927 "[yes|no]", 928 "operate in reverse mode", 929 "reverse", 930 NULL }, 931 932 { PacketAliasOption, 933 PKT_ALIAS_DENY_INCOMING, 934 YesNo, 935 "[yes|no]", 936 "allow incoming connections", 937 "deny_incoming", 938 "d" }, 939 940 { PacketAliasOption, 941 PKT_ALIAS_USE_SOCKETS, 942 YesNo, 943 "[yes|no]", 944 "use sockets to inhibit port conflict", 945 "use_sockets", 946 "s" }, 947 948 { PacketAliasOption, 949 PKT_ALIAS_SAME_PORTS, 950 YesNo, 951 "[yes|no]", 952 "try to keep original port numbers for connections", 953 "same_ports", 954 "m" }, 955 956 { Verbose, 957 0, 958 YesNo, 959 "[yes|no]", 960 "verbose mode, dump packet information", 961 "verbose", 962 "v" }, 963 964 { DynamicMode, 965 0, 966 YesNo, 967 "[yes|no]", 968 "dynamic mode, automatically detect interface address changes", 969 "dynamic", 970 NULL }, 971 972 { InPort, 973 0, 974 Service, 975 "number|service_name", 976 "set port for incoming packets", 977 "in_port", 978 "i" }, 979 980 { OutPort, 981 0, 982 Service, 983 "number|service_name", 984 "set port for outgoing packets", 985 "out_port", 986 "o" }, 987 988 { Port, 989 0, 990 Service, 991 "number|service_name", 992 "set port (defaults to natd/divert)", 993 "port", 994 "p" }, 995 996 { AliasAddress, 997 0, 998 Address, 999 "x.x.x.x", 1000 "address to use for aliasing", 1001 "alias_address", 1002 "a" }, 1003 1004 { InterfaceName, 1005 0, 1006 String, 1007 "network_if_name", 1008 "take aliasing address from interface", 1009 "interface", 1010 "n" }, 1011 1012 { ProxyRule, 1013 0, 1014 String, 1015 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " 1016 "a.b.c.d:yyyy", 1017 "add transparent proxying / destination NAT", 1018 "proxy_rule", 1019 NULL }, 1020 1021 { RedirectPort, 1022 0, 1023 String, 1024 "tcp|udp local_addr:local_port_range [public_addr:]public_port_range" 1025 " [remote_addr[:remote_port_range]]", 1026 "redirect a port (or ports) for incoming traffic", 1027 "redirect_port", 1028 NULL }, 1029 1030 { RedirectAddress, 1031 0, 1032 String, 1033 "local_addr public_addr", 1034 "define mapping between local and public addresses", 1035 "redirect_address", 1036 NULL }, 1037 1038 { PptpAlias, 1039 0, 1040 String, 1041 "src", 1042 "define inside machine for PPTP traffic", 1043 "pptpalias", 1044 NULL }, 1045 1046 { ConfigFile, 1047 0, 1048 String, 1049 "file_name", 1050 "read options from configuration file", 1051 "config", 1052 "f" }, 1053 1054 { LogDenied, 1055 0, 1056 YesNo, 1057 "[yes|no]", 1058 "enable logging of denied incoming packets", 1059 "log_denied", 1060 NULL }, 1061 1062 { LogFacility, 1063 0, 1064 String, 1065 "facility", 1066 "name of syslog facility to use for logging", 1067 "log_facility", 1068 NULL } 1069 1070 }; 1071 1072 static void ParseOption (const char* option, const char* parms, int cmdLine) 1073 { 1074 int i; 1075 struct OptionInfo* info; 1076 int yesNoValue; 1077 int aliasValue; 1078 int numValue; 1079 u_short uNumValue; 1080 const char* strValue; 1081 struct in_addr addrValue; 1082 int max; 1083 char* end; 1084 CODE* fac_record = NULL; 1085 /* 1086 * Find option from table. 1087 */ 1088 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1089 for (i = 0, info = optionTable; i < max; i++, info++) { 1090 1091 if (!strcmp (info->name, option)) 1092 break; 1093 1094 if (info->shortName) 1095 if (!strcmp (info->shortName, option)) 1096 break; 1097 } 1098 1099 if (i >= max) { 1100 1101 warnx ("unknown option %s", option); 1102 Usage (); 1103 } 1104 1105 uNumValue = 0; 1106 yesNoValue = 0; 1107 numValue = 0; 1108 strValue = NULL; 1109 /* 1110 * Check parameters. 1111 */ 1112 switch (info->parm) { 1113 case YesNo: 1114 if (!parms) 1115 parms = "yes"; 1116 1117 if (!strcmp (parms, "yes")) 1118 yesNoValue = 1; 1119 else 1120 if (!strcmp (parms, "no")) 1121 yesNoValue = 0; 1122 else 1123 errx (1, "%s needs yes/no parameter", option); 1124 break; 1125 1126 case Service: 1127 if (!parms) 1128 errx (1, "%s needs service name or " 1129 "port number parameter", 1130 option); 1131 1132 uNumValue = StrToPort (parms, "divert"); 1133 break; 1134 1135 case Numeric: 1136 if (parms) 1137 numValue = strtol (parms, &end, 10); 1138 else 1139 end = NULL; 1140 1141 if (end == parms) 1142 errx (1, "%s needs numeric parameter", option); 1143 break; 1144 1145 case String: 1146 strValue = parms; 1147 if (!strValue) 1148 errx (1, "%s needs parameter", option); 1149 break; 1150 1151 case None: 1152 if (parms) 1153 errx (1, "%s does not take parameters", option); 1154 break; 1155 1156 case Address: 1157 if (!parms) 1158 errx (1, "%s needs address/host parameter", option); 1159 1160 StrToAddr (parms, &addrValue); 1161 break; 1162 } 1163 1164 switch (info->type) { 1165 case PacketAliasOption: 1166 1167 aliasValue = yesNoValue ? info->packetAliasOpt : 0; 1168 PacketAliasSetMode (aliasValue, info->packetAliasOpt); 1169 break; 1170 1171 case Verbose: 1172 verbose = yesNoValue; 1173 break; 1174 1175 case DynamicMode: 1176 dynamicMode = yesNoValue; 1177 break; 1178 1179 case InPort: 1180 inPort = uNumValue; 1181 break; 1182 1183 case OutPort: 1184 outPort = uNumValue; 1185 break; 1186 1187 case Port: 1188 inOutPort = uNumValue; 1189 break; 1190 1191 case AliasAddress: 1192 memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); 1193 break; 1194 1195 case RedirectPort: 1196 SetupPortRedirect (strValue); 1197 break; 1198 1199 case RedirectAddress: 1200 SetupAddressRedirect (strValue); 1201 break; 1202 1203 case PptpAlias: 1204 SetupPptpAlias (strValue); 1205 break; 1206 1207 case ProxyRule: 1208 PacketAliasProxyRule (strValue); 1209 break; 1210 1211 case InterfaceName: 1212 if (ifName) 1213 free (ifName); 1214 1215 ifName = strdup (strValue); 1216 break; 1217 1218 case ConfigFile: 1219 ReadConfigFile (strValue); 1220 break; 1221 1222 case LogDenied: 1223 logDropped = 1; 1224 break; 1225 1226 case LogFacility: 1227 1228 fac_record = facilitynames; 1229 while (fac_record->c_name != NULL) { 1230 1231 if (!strcmp (fac_record->c_name, strValue)) { 1232 1233 logFacility = fac_record->c_val; 1234 break; 1235 1236 } 1237 else 1238 fac_record++; 1239 } 1240 1241 if(fac_record->c_name == NULL) 1242 errx(1, "Unknown log facility name: %s", strValue); 1243 1244 break; 1245 } 1246 } 1247 1248 void ReadConfigFile (const char* fileName) 1249 { 1250 FILE* file; 1251 char *buf; 1252 size_t len; 1253 char *ptr, *p; 1254 char* option; 1255 1256 file = fopen (fileName, "r"); 1257 if (!file) 1258 err(1, "cannot open config file %s", fileName); 1259 1260 while ((buf = fgetln(file, &len)) != NULL) { 1261 if (buf[len - 1] == '\n') 1262 buf[len - 1] = '\0'; 1263 else 1264 errx(1, "config file format error: " 1265 "last line should end with newline"); 1266 1267 /* 1268 * Check for comments, strip off trailing spaces. 1269 */ 1270 if ((ptr = strchr(buf, '#'))) 1271 *ptr = '\0'; 1272 for (ptr = buf; isspace(*ptr); ++ptr) 1273 continue; 1274 if (*ptr == '\0') 1275 continue; 1276 for (p = strchr(buf, '\0'); isspace(*--p);) 1277 continue; 1278 *++p = '\0'; 1279 1280 /* 1281 * Extract option name. 1282 */ 1283 option = ptr; 1284 while (*ptr && !isspace (*ptr)) 1285 ++ptr; 1286 1287 if (*ptr != '\0') { 1288 1289 *ptr = '\0'; 1290 ++ptr; 1291 } 1292 /* 1293 * Skip white space between name and parms. 1294 */ 1295 while (*ptr && isspace (*ptr)) 1296 ++ptr; 1297 1298 ParseOption (option, *ptr ? ptr : NULL, 0); 1299 } 1300 1301 fclose (file); 1302 } 1303 1304 static void Usage () 1305 { 1306 int i; 1307 int max; 1308 struct OptionInfo* info; 1309 1310 fprintf (stderr, "Recognized options:\n\n"); 1311 1312 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1313 for (i = 0, info = optionTable; i < max; i++, info++) { 1314 1315 fprintf (stderr, "-%-20s %s\n", info->name, 1316 info->parmDescription); 1317 1318 if (info->shortName) 1319 fprintf (stderr, "-%-20s %s\n", info->shortName, 1320 info->parmDescription); 1321 1322 fprintf (stderr, " %s\n\n", info->description); 1323 } 1324 1325 exit (1); 1326 } 1327 1328 void SetupPptpAlias (const char* parms) 1329 { 1330 char buf[128]; 1331 char* ptr; 1332 struct in_addr srcAddr; 1333 1334 strcpy (buf, parms); 1335 1336 /* 1337 * Extract source address. 1338 */ 1339 ptr = strtok (buf, " \t"); 1340 if (!ptr) 1341 errx(1, "pptpalias: missing src address"); 1342 1343 StrToAddr (ptr, &srcAddr); 1344 PacketAliasPptp (srcAddr); 1345 } 1346 1347 void SetupPortRedirect (const char* parms) 1348 { 1349 char buf[128]; 1350 char* ptr; 1351 struct in_addr localAddr; 1352 struct in_addr publicAddr; 1353 struct in_addr remoteAddr; 1354 port_range portRange; 1355 u_short localPort = 0; 1356 u_short publicPort = 0; 1357 u_short remotePort = 0; 1358 u_short numLocalPorts = 0; 1359 u_short numPublicPorts = 0; 1360 u_short numRemotePorts = 0; 1361 int proto; 1362 char* protoName; 1363 char* separator; 1364 int i; 1365 1366 strcpy (buf, parms); 1367 /* 1368 * Extract protocol. 1369 */ 1370 protoName = strtok (buf, " \t"); 1371 if (!protoName) 1372 errx (1, "redirect_port: missing protocol"); 1373 1374 proto = StrToProto (protoName); 1375 /* 1376 * Extract local address. 1377 */ 1378 ptr = strtok (NULL, " \t"); 1379 if (!ptr) 1380 errx (1, "redirect_port: missing local address"); 1381 1382 if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 ) 1383 errx (1, "redirect_port: invalid local port range"); 1384 1385 localPort = GETLOPORT(portRange); 1386 numLocalPorts = GETNUMPORTS(portRange); 1387 1388 /* 1389 * Extract public port and optionally address. 1390 */ 1391 ptr = strtok (NULL, " \t"); 1392 if (!ptr) 1393 errx (1, "redirect_port: missing public port"); 1394 1395 separator = strchr (ptr, ':'); 1396 if (separator) { 1397 if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 ) 1398 errx (1, "redirect_port: invalid public port range"); 1399 } 1400 else { 1401 publicAddr.s_addr = INADDR_ANY; 1402 if (StrToPortRange (ptr, protoName, &portRange) != 0) 1403 errx (1, "redirect_port: invalid public port range"); 1404 } 1405 1406 publicPort = GETLOPORT(portRange); 1407 numPublicPorts = GETNUMPORTS(portRange); 1408 1409 /* 1410 * Extract remote address and optionally port. 1411 */ 1412 ptr = strtok (NULL, " \t"); 1413 if (ptr) { 1414 separator = strchr (ptr, ':'); 1415 if (separator) { 1416 if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0) 1417 errx (1, "redirect_port: invalid remote port range"); 1418 } else { 1419 SETLOPORT(portRange, 0); 1420 SETNUMPORTS(portRange, 1); 1421 StrToAddr (ptr, &remoteAddr); 1422 } 1423 } 1424 else { 1425 SETLOPORT(portRange, 0); 1426 SETNUMPORTS(portRange, 1); 1427 remoteAddr.s_addr = INADDR_ANY; 1428 } 1429 1430 remotePort = GETLOPORT(portRange); 1431 numRemotePorts = GETNUMPORTS(portRange); 1432 1433 /* 1434 * Make sure port ranges match up, then add the redirect ports. 1435 */ 1436 if (numLocalPorts != numPublicPorts) 1437 errx (1, "redirect_port: port ranges must be equal in size"); 1438 1439 /* Remote port range is allowed to be '0' which means all ports. */ 1440 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0)) 1441 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size"); 1442 1443 for (i = 0 ; i < numPublicPorts ; ++i) { 1444 /* If remotePort is all ports, set it to 0. */ 1445 u_short remotePortCopy = remotePort + i; 1446 if (numRemotePorts == 1 && remotePort == 0) 1447 remotePortCopy = 0; 1448 1449 PacketAliasRedirectPort (localAddr, 1450 htons(localPort + i), 1451 remoteAddr, 1452 htons(remotePortCopy), 1453 publicAddr, 1454 htons(publicPort + i), 1455 proto); 1456 } 1457 } 1458 1459 void SetupAddressRedirect (const char* parms) 1460 { 1461 char buf[128]; 1462 char* ptr; 1463 struct in_addr localAddr; 1464 struct in_addr publicAddr; 1465 1466 strcpy (buf, parms); 1467 /* 1468 * Extract local address. 1469 */ 1470 ptr = strtok (buf, " \t"); 1471 if (!ptr) 1472 errx (1, "redirect_address: missing local address"); 1473 1474 StrToAddr (ptr, &localAddr); 1475 /* 1476 * Extract public address. 1477 */ 1478 ptr = strtok (NULL, " \t"); 1479 if (!ptr) 1480 errx (1, "redirect_address: missing public address"); 1481 1482 StrToAddr (ptr, &publicAddr); 1483 PacketAliasRedirectAddr (localAddr, publicAddr); 1484 } 1485 1486 void StrToAddr (const char* str, struct in_addr* addr) 1487 { 1488 struct hostent* hp; 1489 1490 if (inet_aton (str, addr)) 1491 return; 1492 1493 hp = gethostbyname (str); 1494 if (!hp) 1495 errx (1, "unknown host %s", str); 1496 1497 memcpy (addr, hp->h_addr, sizeof (struct in_addr)); 1498 } 1499 1500 u_short StrToPort (const char* str, const char* proto) 1501 { 1502 u_short port; 1503 struct servent* sp; 1504 char* end; 1505 1506 port = strtol (str, &end, 10); 1507 if (end != str) 1508 return htons (port); 1509 1510 sp = getservbyname (str, proto); 1511 if (!sp) 1512 errx (1, "unknown service %s/%s", str, proto); 1513 1514 return sp->s_port; 1515 } 1516 1517 int StrToPortRange (const char* str, const char* proto, port_range *portRange) 1518 { 1519 char* sep; 1520 struct servent* sp; 1521 char* end; 1522 u_short loPort; 1523 u_short hiPort; 1524 1525 /* First see if this is a service, return corresponding port if so. */ 1526 sp = getservbyname (str,proto); 1527 if (sp) { 1528 SETLOPORT(*portRange, ntohs(sp->s_port)); 1529 SETNUMPORTS(*portRange, 1); 1530 return 0; 1531 } 1532 1533 /* Not a service, see if it's a single port or port range. */ 1534 sep = strchr (str, '-'); 1535 if (sep == NULL) { 1536 SETLOPORT(*portRange, strtol(str, &end, 10)); 1537 if (end != str) { 1538 /* Single port. */ 1539 SETNUMPORTS(*portRange, 1); 1540 return 0; 1541 } 1542 1543 /* Error in port range field. */ 1544 errx (1, "unknown service %s/%s", str, proto); 1545 } 1546 1547 /* Port range, get the values and sanity check. */ 1548 sscanf (str, "%hu-%hu", &loPort, &hiPort); 1549 SETLOPORT(*portRange, loPort); 1550 SETNUMPORTS(*portRange, 0); /* Error by default */ 1551 if (loPort <= hiPort) 1552 SETNUMPORTS(*portRange, hiPort - loPort + 1); 1553 1554 if (GETNUMPORTS(*portRange) == 0) 1555 errx (1, "invalid port range %s", str); 1556 1557 return 0; 1558 } 1559 1560 1561 int StrToProto (const char* str) 1562 { 1563 if (!strcmp (str, "tcp")) 1564 return IPPROTO_TCP; 1565 1566 if (!strcmp (str, "udp")) 1567 return IPPROTO_UDP; 1568 1569 errx (1, "unknown protocol %s. Expected tcp or udp", str); 1570 } 1571 1572 int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange) 1573 { 1574 char* ptr; 1575 1576 ptr = strchr (str, ':'); 1577 if (!ptr) 1578 errx (1, "%s is missing port number", str); 1579 1580 *ptr = '\0'; 1581 ++ptr; 1582 1583 StrToAddr (str, addr); 1584 return StrToPortRange (ptr, proto, portRange); 1585 } 1586