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