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 13 #include <sys/cdefs.h> 14 #define SYSLOG_NAMES 15 16 #include <sys/types.h> 17 #include <sys/socket.h> 18 #include <sys/sysctl.h> 19 #include <sys/time.h> 20 #include <sys/queue.h> 21 22 #include <netinet/in.h> 23 #include <netinet/in_systm.h> 24 #include <netinet/ip.h> 25 #include <netinet/tcp.h> 26 #include <netinet/udp.h> 27 #include <netinet/ip_icmp.h> 28 #include <net/if.h> 29 #include <net/if_dl.h> 30 #include <net/route.h> 31 #include <arpa/inet.h> 32 33 #include <alias.h> 34 #include <ctype.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <netdb.h> 38 #include <signal.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <syslog.h> 43 #include <unistd.h> 44 45 #include "natd.h" 46 47 struct instance { 48 const char *name; 49 struct libalias *la; 50 LIST_ENTRY(instance) list; 51 52 int ifIndex; 53 int assignAliasAddr; 54 char* ifName; 55 int logDropped; 56 u_short inPort; 57 u_short outPort; 58 u_short inOutPort; 59 struct in_addr aliasAddr; 60 int ifMTU; 61 int aliasOverhead; 62 int dropIgnoredIncoming; 63 int divertIn; 64 int divertOut; 65 int divertInOut; 66 }; 67 68 static LIST_HEAD(, instance) root = LIST_HEAD_INITIALIZER(root); 69 70 struct libalias *mla; 71 static struct instance *mip; 72 static int ninstance = 1; 73 74 /* 75 * Default values for input and output 76 * divert socket ports. 77 */ 78 79 #define DEFAULT_SERVICE "natd" 80 81 /* 82 * Definition of a port range, and macros to deal with values. 83 * FORMAT: HI 16-bits == first port in range, 0 == all ports. 84 * LO 16-bits == number of ports in range 85 * NOTES: - Port values are not stored in network byte order. 86 */ 87 88 typedef u_long port_range; 89 90 #define GETLOPORT(x) ((x) >> 0x10) 91 #define GETNUMPORTS(x) ((x) & 0x0000ffff) 92 #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x))) 93 94 /* Set y to be the low-port value in port_range variable x. */ 95 #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10)) 96 97 /* Set y to be the number of ports in port_range variable x. */ 98 #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y)) 99 100 /* 101 * Function prototypes. 102 */ 103 104 static void DoAliasing (int fd, int direction); 105 static void DaemonMode (void); 106 static void HandleRoutingInfo (int fd); 107 static void Usage (void); 108 static char* FormatPacket (struct ip*); 109 static void PrintPacket (struct ip*); 110 static void SyslogPacket (struct ip*, int priority, const char *label); 111 static int SetAliasAddressFromIfName (const char *ifName); 112 static void InitiateShutdown (int); 113 static void Shutdown (int); 114 static void RefreshAddr (int); 115 static void ParseOption (const char* option, const char* parms); 116 static void ReadConfigFile (const char* fileName); 117 static void SetupPortRedirect (const char* parms); 118 static void SetupProtoRedirect(const char* parms); 119 static void SetupAddressRedirect (const char* parms); 120 static void StrToAddr (const char* str, struct in_addr* addr); 121 static u_short StrToPort (const char* str, const char* proto); 122 static int StrToPortRange (const char* str, const char* proto, port_range *portRange); 123 static int StrToProto (const char* str); 124 static int StrToAddrAndPortRange (char* str, struct in_addr* addr, char* proto, port_range *portRange); 125 static void ParseArgs (int argc, char** argv); 126 static void SetupPunchFW(const char *strValue); 127 static void SetupSkinnyPort(const char *strValue); 128 static void NewInstance(const char *name); 129 static void DoGlobal (int fd); 130 static int CheckIpfwRulenum(unsigned int rnum); 131 132 /* 133 * Globals. 134 */ 135 136 static int verbose; 137 static int background; 138 static int running; 139 static int logFacility; 140 141 static int dynamicMode; 142 static int icmpSock; 143 static int logIpfwDenied; 144 static const char* pidName; 145 static int routeSock; 146 static int globalPort; 147 static int divertGlobal; 148 static int exitDelay; 149 150 151 int main (int argc, char** argv) 152 { 153 struct sockaddr_in addr; 154 fd_set readMask; 155 int fdMax; 156 int rval; 157 /* 158 * Initialize packet aliasing software. 159 * Done already here to be able to alter option bits 160 * during command line and configuration file processing. 161 */ 162 NewInstance("default"); 163 164 /* 165 * Parse options. 166 */ 167 verbose = 0; 168 background = 0; 169 running = 1; 170 dynamicMode = 0; 171 logFacility = LOG_DAEMON; 172 logIpfwDenied = -1; 173 pidName = PIDFILE; 174 routeSock = -1; 175 icmpSock = -1; 176 fdMax = -1; 177 divertGlobal = -1; 178 exitDelay = EXIT_DELAY; 179 180 ParseArgs (argc, argv); 181 /* 182 * Log ipfw(8) denied packets by default in verbose mode. 183 */ 184 if (logIpfwDenied == -1) 185 logIpfwDenied = verbose; 186 /* 187 * Open syslog channel. 188 */ 189 openlog ("natd", LOG_CONS | LOG_PID | (verbose ? LOG_PERROR : 0), 190 logFacility); 191 192 LIST_FOREACH(mip, &root, list) { 193 mla = mip->la; 194 /* 195 * If not doing the transparent proxying only, 196 * check that valid aliasing address has been given. 197 */ 198 if (mip->aliasAddr.s_addr == INADDR_NONE && mip->ifName == NULL && 199 !(LibAliasSetMode(mla, 0,0) & PKT_ALIAS_PROXY_ONLY)) 200 errx (1, "instance %s: aliasing address not given", mip->name); 201 202 if (mip->aliasAddr.s_addr != INADDR_NONE && mip->ifName != NULL) 203 errx (1, "both alias address and interface " 204 "name are not allowed"); 205 /* 206 * Check that valid port number is known. 207 */ 208 if (mip->inPort != 0 || mip->outPort != 0) 209 if (mip->inPort == 0 || mip->outPort == 0) 210 errx (1, "both input and output ports are required"); 211 212 if (mip->inPort == 0 && mip->outPort == 0 && mip->inOutPort == 0) 213 ParseOption ("port", DEFAULT_SERVICE); 214 215 /* 216 * Check if ignored packets should be dropped. 217 */ 218 mip->dropIgnoredIncoming = LibAliasSetMode (mla, 0, 0); 219 mip->dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING; 220 /* 221 * Create divert sockets. Use only one socket if -p was specified 222 * on command line. Otherwise, create separate sockets for 223 * outgoing and incoming connections. 224 */ 225 if (mip->inOutPort) { 226 227 mip->divertInOut = socket(PF_DIVERT, SOCK_RAW, 0); 228 if (mip->divertInOut == -1) 229 Quit ("Unable to create divert socket."); 230 if (mip->divertInOut > fdMax) 231 fdMax = mip->divertInOut; 232 233 mip->divertIn = -1; 234 mip->divertOut = -1; 235 /* 236 * Bind socket. 237 */ 238 239 addr.sin_family = AF_INET; 240 addr.sin_addr.s_addr = INADDR_ANY; 241 addr.sin_port = mip->inOutPort; 242 243 if (bind (mip->divertInOut, 244 (struct sockaddr*) &addr, 245 sizeof addr) == -1) 246 Quit ("Unable to bind divert socket."); 247 } 248 else { 249 250 mip->divertIn = socket(PF_DIVERT, SOCK_RAW, 0); 251 if (mip->divertIn == -1) 252 Quit ("Unable to create incoming divert socket."); 253 if (mip->divertIn > fdMax) 254 fdMax = mip->divertIn; 255 256 257 mip->divertOut = socket(PF_DIVERT, SOCK_RAW, 0); 258 if (mip->divertOut == -1) 259 Quit ("Unable to create outgoing divert socket."); 260 if (mip->divertOut > fdMax) 261 fdMax = mip->divertOut; 262 263 mip->divertInOut = -1; 264 265 /* 266 * Bind divert sockets. 267 */ 268 269 addr.sin_family = AF_INET; 270 addr.sin_addr.s_addr = INADDR_ANY; 271 addr.sin_port = mip->inPort; 272 273 if (bind (mip->divertIn, 274 (struct sockaddr*) &addr, 275 sizeof addr) == -1) 276 Quit ("Unable to bind incoming divert socket."); 277 278 addr.sin_family = AF_INET; 279 addr.sin_addr.s_addr = INADDR_ANY; 280 addr.sin_port = mip->outPort; 281 282 if (bind (mip->divertOut, 283 (struct sockaddr*) &addr, 284 sizeof addr) == -1) 285 Quit ("Unable to bind outgoing divert socket."); 286 } 287 /* 288 * Create routing socket if interface name specified and in dynamic mode. 289 */ 290 if (mip->ifName) { 291 if (dynamicMode) { 292 293 if (routeSock == -1) 294 routeSock = socket (PF_ROUTE, SOCK_RAW, 0); 295 if (routeSock == -1) 296 Quit ("Unable to create routing info socket."); 297 if (routeSock > fdMax) 298 fdMax = routeSock; 299 300 mip->assignAliasAddr = 1; 301 } 302 else { 303 do { 304 rval = SetAliasAddressFromIfName (mip->ifName); 305 if (background == 0 || dynamicMode == 0) 306 break; 307 if (rval == EAGAIN) 308 sleep(1); 309 } while (rval == EAGAIN); 310 if (rval != 0) 311 exit(1); 312 } 313 } 314 315 } 316 if (globalPort) { 317 318 divertGlobal = socket(PF_DIVERT, SOCK_RAW, 0); 319 if (divertGlobal == -1) 320 Quit ("Unable to create divert socket."); 321 if (divertGlobal > fdMax) 322 fdMax = divertGlobal; 323 324 /* 325 * Bind socket. 326 */ 327 328 addr.sin_family = AF_INET; 329 addr.sin_addr.s_addr = INADDR_ANY; 330 addr.sin_port = globalPort; 331 332 if (bind (divertGlobal, 333 (struct sockaddr*) &addr, 334 sizeof addr) == -1) 335 Quit ("Unable to bind global divert socket."); 336 } 337 /* 338 * Create socket for sending ICMP messages. 339 */ 340 icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); 341 if (icmpSock == -1) 342 Quit ("Unable to create ICMP socket."); 343 344 /* 345 * And disable reads for the socket, otherwise it slowly fills 346 * up with received icmps which we do not use. 347 */ 348 shutdown(icmpSock, SHUT_RD); 349 350 /* 351 * Become a daemon unless verbose mode was requested. 352 */ 353 if (!verbose) 354 DaemonMode (); 355 /* 356 * Catch signals to manage shutdown and 357 * refresh of interface address. 358 */ 359 siginterrupt(SIGTERM, 1); 360 siginterrupt(SIGHUP, 1); 361 if (exitDelay) 362 signal(SIGTERM, InitiateShutdown); 363 else 364 signal(SIGTERM, Shutdown); 365 signal (SIGHUP, RefreshAddr); 366 /* 367 * Set alias address if it has been given. 368 */ 369 mip = LIST_FIRST(&root); /* XXX: simon */ 370 LIST_FOREACH(mip, &root, list) { 371 mla = mip->la; 372 if (mip->aliasAddr.s_addr != INADDR_NONE) 373 LibAliasSetAddress (mla, mip->aliasAddr); 374 } 375 376 while (running) { 377 mip = LIST_FIRST(&root); /* XXX: simon */ 378 379 if (mip->divertInOut != -1 && !mip->ifName && ninstance == 1) { 380 /* 381 * When using only one socket, just call 382 * DoAliasing repeatedly to process packets. 383 */ 384 DoAliasing (mip->divertInOut, DONT_KNOW); 385 continue; 386 } 387 /* 388 * Build read mask from socket descriptors to select. 389 */ 390 FD_ZERO (&readMask); 391 /* 392 * Check if new packets are available. 393 */ 394 LIST_FOREACH(mip, &root, list) { 395 if (mip->divertIn != -1) 396 FD_SET (mip->divertIn, &readMask); 397 398 if (mip->divertOut != -1) 399 FD_SET (mip->divertOut, &readMask); 400 401 if (mip->divertInOut != -1) 402 FD_SET (mip->divertInOut, &readMask); 403 } 404 /* 405 * Routing info is processed always. 406 */ 407 if (routeSock != -1) 408 FD_SET (routeSock, &readMask); 409 410 if (divertGlobal != -1) 411 FD_SET (divertGlobal, &readMask); 412 413 if (select (fdMax + 1, 414 &readMask, 415 NULL, 416 NULL, 417 NULL) == -1) { 418 419 if (errno == EINTR) 420 continue; 421 422 Quit ("Select failed."); 423 } 424 425 if (divertGlobal != -1) 426 if (FD_ISSET (divertGlobal, &readMask)) 427 DoGlobal (divertGlobal); 428 LIST_FOREACH(mip, &root, list) { 429 mla = mip->la; 430 if (mip->divertIn != -1) 431 if (FD_ISSET (mip->divertIn, &readMask)) 432 DoAliasing (mip->divertIn, INPUT); 433 434 if (mip->divertOut != -1) 435 if (FD_ISSET (mip->divertOut, &readMask)) 436 DoAliasing (mip->divertOut, OUTPUT); 437 438 if (mip->divertInOut != -1) 439 if (FD_ISSET (mip->divertInOut, &readMask)) 440 DoAliasing (mip->divertInOut, DONT_KNOW); 441 442 } 443 if (routeSock != -1) 444 if (FD_ISSET (routeSock, &readMask)) 445 HandleRoutingInfo (routeSock); 446 } 447 448 if (background) 449 unlink (pidName); 450 451 return 0; 452 } 453 454 static void DaemonMode(void) 455 { 456 FILE* pidFile; 457 458 daemon (0, 0); 459 background = 1; 460 461 pidFile = fopen (pidName, "w"); 462 if (pidFile) { 463 464 fprintf (pidFile, "%d\n", getpid ()); 465 fclose (pidFile); 466 } 467 } 468 469 static void ParseArgs (int argc, char** argv) 470 { 471 int arg; 472 char* opt; 473 char parmBuf[256]; 474 int len; /* bounds checking */ 475 476 for (arg = 1; arg < argc; arg++) { 477 478 opt = argv[arg]; 479 if (*opt != '-') { 480 481 warnx ("invalid option %s", opt); 482 Usage (); 483 } 484 485 parmBuf[0] = '\0'; 486 len = 0; 487 488 while (arg < argc - 1) { 489 490 if (argv[arg + 1][0] == '-') 491 break; 492 493 if (len) { 494 strncat (parmBuf, " ", sizeof(parmBuf) - (len + 1)); 495 len += strlen(parmBuf + len); 496 } 497 498 ++arg; 499 strncat (parmBuf, argv[arg], sizeof(parmBuf) - (len + 1)); 500 len += strlen(parmBuf + len); 501 502 } 503 504 ParseOption (opt + 1, (len ? parmBuf : NULL)); 505 506 } 507 } 508 509 static void DoGlobal (int fd) 510 { 511 int bytes; 512 int origBytes; 513 char buf[IP_MAXPACKET]; 514 struct sockaddr_in addr; 515 int wrote; 516 socklen_t addrSize; 517 struct ip* ip; 518 char msgBuf[80]; 519 520 /* 521 * Get packet from socket. 522 */ 523 addrSize = sizeof addr; 524 origBytes = recvfrom (fd, 525 buf, 526 sizeof buf, 527 0, 528 (struct sockaddr*) &addr, 529 &addrSize); 530 531 if (origBytes == -1) { 532 533 if (errno != EINTR) 534 Warn ("read from divert socket failed"); 535 536 return; 537 } 538 539 #if 0 540 if (mip->assignAliasAddr) { 541 if (SetAliasAddressFromIfName (mip->ifName) != 0) 542 exit(1); 543 mip->assignAliasAddr = 0; 544 } 545 #endif 546 /* 547 * This is an IP packet. 548 */ 549 ip = (struct ip*) buf; 550 551 if (verbose) { 552 /* 553 * Print packet direction and protocol type. 554 */ 555 printf ("Glb "); 556 557 switch (ip->ip_p) { 558 case IPPROTO_TCP: 559 printf ("[TCP] "); 560 break; 561 562 case IPPROTO_UDP: 563 printf ("[UDP] "); 564 break; 565 566 case IPPROTO_ICMP: 567 printf ("[ICMP] "); 568 break; 569 570 default: 571 printf ("[%d] ", ip->ip_p); 572 break; 573 } 574 /* 575 * Print addresses. 576 */ 577 PrintPacket (ip); 578 } 579 580 LIST_FOREACH(mip, &root, list) { 581 mla = mip->la; 582 if (LibAliasOutTry (mla, buf, IP_MAXPACKET, 0) != PKT_ALIAS_IGNORED) 583 break; 584 } 585 /* 586 * Length might have changed during aliasing. 587 */ 588 bytes = ntohs (ip->ip_len); 589 /* 590 * Update alias overhead size for outgoing packets. 591 */ 592 if (mip != NULL && bytes - origBytes > mip->aliasOverhead) 593 mip->aliasOverhead = bytes - origBytes; 594 595 if (verbose) { 596 597 /* 598 * Print addresses after aliasing. 599 */ 600 printf (" aliased to\n"); 601 printf (" "); 602 PrintPacket (ip); 603 printf ("\n"); 604 } 605 606 /* 607 * Put packet back for processing. 608 */ 609 wrote = sendto (fd, 610 buf, 611 bytes, 612 0, 613 (struct sockaddr*) &addr, 614 sizeof addr); 615 616 if (wrote != bytes) { 617 618 if (errno == EMSGSIZE && mip != NULL) { 619 620 if (mip->ifMTU != -1) 621 SendNeedFragIcmp (icmpSock, 622 (struct ip*) buf, 623 mip->ifMTU - mip->aliasOverhead); 624 } 625 else if (errno == EACCES && logIpfwDenied) { 626 627 sprintf (msgBuf, "failed to write packet back"); 628 Warn (msgBuf); 629 } 630 } 631 } 632 633 634 static void DoAliasing (int fd, int direction) 635 { 636 int bytes; 637 int origBytes; 638 char buf[IP_MAXPACKET]; 639 struct sockaddr_in addr; 640 int wrote; 641 int status; 642 socklen_t addrSize; 643 struct ip* ip; 644 char msgBuf[80]; 645 int rval; 646 647 if (mip->assignAliasAddr) { 648 do { 649 rval = SetAliasAddressFromIfName (mip->ifName); 650 if (background == 0 || dynamicMode == 0) 651 break; 652 if (rval == EAGAIN) 653 sleep(1); 654 } while (rval == EAGAIN); 655 if (rval != 0) 656 exit(1); 657 mip->assignAliasAddr = 0; 658 } 659 /* 660 * Get packet from socket. 661 */ 662 addrSize = sizeof addr; 663 origBytes = recvfrom (fd, 664 buf, 665 sizeof buf, 666 0, 667 (struct sockaddr*) &addr, 668 &addrSize); 669 670 if (origBytes == -1) { 671 672 if (errno != EINTR) 673 Warn ("read from divert socket failed"); 674 675 return; 676 } 677 /* 678 * This is an IP packet. 679 */ 680 ip = (struct ip*) buf; 681 if (direction == DONT_KNOW) { 682 if (addr.sin_addr.s_addr == INADDR_ANY) 683 direction = OUTPUT; 684 else 685 direction = INPUT; 686 } 687 688 if (verbose) { 689 /* 690 * Print packet direction and protocol type. 691 */ 692 printf (direction == OUTPUT ? "Out " : "In "); 693 if (ninstance > 1) 694 printf ("{%s}", mip->name); 695 696 switch (ip->ip_p) { 697 case IPPROTO_TCP: 698 printf ("[TCP] "); 699 break; 700 701 case IPPROTO_UDP: 702 printf ("[UDP] "); 703 break; 704 705 case IPPROTO_ICMP: 706 printf ("[ICMP] "); 707 break; 708 709 default: 710 printf ("[%d] ", ip->ip_p); 711 break; 712 } 713 /* 714 * Print addresses. 715 */ 716 PrintPacket (ip); 717 } 718 719 if (direction == OUTPUT) { 720 /* 721 * Outgoing packets. Do aliasing. 722 */ 723 LibAliasOut (mla, buf, IP_MAXPACKET); 724 } 725 else { 726 727 /* 728 * Do aliasing. 729 */ 730 status = LibAliasIn (mla, buf, IP_MAXPACKET); 731 if (status == PKT_ALIAS_IGNORED && 732 mip->dropIgnoredIncoming) { 733 734 if (verbose) 735 printf (" dropped.\n"); 736 737 if (mip->logDropped) 738 SyslogPacket (ip, LOG_WARNING, "denied"); 739 740 return; 741 } 742 } 743 /* 744 * Length might have changed during aliasing. 745 */ 746 bytes = ntohs (ip->ip_len); 747 /* 748 * Update alias overhead size for outgoing packets. 749 */ 750 if (direction == OUTPUT && 751 bytes - origBytes > mip->aliasOverhead) 752 mip->aliasOverhead = bytes - origBytes; 753 754 if (verbose) { 755 756 /* 757 * Print addresses after aliasing. 758 */ 759 printf (" aliased to\n"); 760 printf (" "); 761 PrintPacket (ip); 762 printf ("\n"); 763 } 764 765 /* 766 * Put packet back for processing. 767 */ 768 wrote = sendto (fd, 769 buf, 770 bytes, 771 0, 772 (struct sockaddr*) &addr, 773 sizeof addr); 774 775 if (wrote != bytes) { 776 777 if (errno == EMSGSIZE) { 778 779 if (direction == OUTPUT && 780 mip->ifMTU != -1) 781 SendNeedFragIcmp (icmpSock, 782 (struct ip*) buf, 783 mip->ifMTU - mip->aliasOverhead); 784 } 785 else if (errno == EACCES && logIpfwDenied) { 786 787 sprintf (msgBuf, "failed to write packet back"); 788 Warn (msgBuf); 789 } 790 } 791 } 792 793 static void HandleRoutingInfo (int fd) 794 { 795 int bytes; 796 struct if_msghdr ifMsg; 797 /* 798 * Get packet from socket. 799 */ 800 bytes = read (fd, &ifMsg, sizeof ifMsg); 801 if (bytes == -1) { 802 803 Warn ("read from routing socket failed"); 804 return; 805 } 806 807 if (ifMsg.ifm_version != RTM_VERSION) { 808 809 Warn ("unexpected packet read from routing socket"); 810 return; 811 } 812 813 if (verbose) 814 printf ("Routing message %#x received.\n", ifMsg.ifm_type); 815 816 if ((ifMsg.ifm_type == RTM_NEWADDR || ifMsg.ifm_type == RTM_IFINFO)) { 817 LIST_FOREACH(mip, &root, list) { 818 mla = mip->la; 819 if (ifMsg.ifm_index == mip->ifIndex) { 820 if (verbose) 821 printf("Interface address/MTU has probably changed.\n"); 822 mip->assignAliasAddr = 1; 823 } 824 } 825 } 826 } 827 828 static void PrintPacket (struct ip* ip) 829 { 830 printf ("%s", FormatPacket (ip)); 831 } 832 833 static void SyslogPacket (struct ip* ip, int priority, const char *label) 834 { 835 syslog (priority, "%s %s", label, FormatPacket (ip)); 836 } 837 838 static char* FormatPacket (struct ip* ip) 839 { 840 static char buf[256]; 841 struct tcphdr* tcphdr; 842 struct udphdr* udphdr; 843 struct icmp* icmphdr; 844 char src[20]; 845 char dst[20]; 846 847 strcpy (src, inet_ntoa (ip->ip_src)); 848 strcpy (dst, inet_ntoa (ip->ip_dst)); 849 850 switch (ip->ip_p) { 851 case IPPROTO_TCP: 852 tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); 853 sprintf (buf, "[TCP] %s:%d -> %s:%d", 854 src, 855 ntohs (tcphdr->th_sport), 856 dst, 857 ntohs (tcphdr->th_dport)); 858 break; 859 860 case IPPROTO_UDP: 861 udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2)); 862 sprintf (buf, "[UDP] %s:%d -> %s:%d", 863 src, 864 ntohs (udphdr->uh_sport), 865 dst, 866 ntohs (udphdr->uh_dport)); 867 break; 868 869 case IPPROTO_ICMP: 870 icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2)); 871 sprintf (buf, "[ICMP] %s -> %s %u(%u)", 872 src, 873 dst, 874 icmphdr->icmp_type, 875 icmphdr->icmp_code); 876 break; 877 878 default: 879 sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst); 880 break; 881 } 882 883 return buf; 884 } 885 886 static int 887 SetAliasAddressFromIfName(const char *ifn) 888 { 889 size_t needed; 890 int mib[6]; 891 char *buf, *lim, *next; 892 struct if_msghdr *ifm; 893 struct ifa_msghdr *ifam; 894 struct sockaddr_dl *sdl; 895 struct sockaddr_in *sin; 896 897 mib[0] = CTL_NET; 898 mib[1] = PF_ROUTE; 899 mib[2] = 0; 900 mib[3] = AF_INET; /* Only IP addresses please */ 901 mib[4] = NET_RT_IFLIST; 902 mib[5] = 0; /* ifIndex??? */ 903 /* 904 * Get interface data. 905 */ 906 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 907 err(1, "iflist-sysctl-estimate"); 908 if ((buf = malloc(needed)) == NULL) 909 errx(1, "malloc failed"); 910 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1 && errno != ENOMEM) 911 err(1, "iflist-sysctl-get"); 912 lim = buf + needed; 913 /* 914 * Loop through interfaces until one with 915 * given name is found. This is done to 916 * find correct interface index for routing 917 * message processing. 918 */ 919 mip->ifIndex = 0; 920 next = buf; 921 while (next < lim) { 922 ifm = (struct if_msghdr *)next; 923 next += ifm->ifm_msglen; 924 if (ifm->ifm_version != RTM_VERSION) { 925 if (verbose) 926 warnx("routing message version %d " 927 "not understood", ifm->ifm_version); 928 continue; 929 } 930 if (ifm->ifm_type == RTM_IFINFO) { 931 sdl = (struct sockaddr_dl *)(ifm + 1); 932 if (strlen(ifn) == sdl->sdl_nlen && 933 strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) { 934 mip->ifIndex = ifm->ifm_index; 935 mip->ifMTU = ifm->ifm_data.ifi_mtu; 936 break; 937 } 938 } 939 } 940 if (!mip->ifIndex) 941 errx(1, "unknown interface name %s", ifn); 942 /* 943 * Get interface address. 944 */ 945 sin = NULL; 946 while (next < lim) { 947 ifam = (struct ifa_msghdr *)next; 948 next += ifam->ifam_msglen; 949 if (ifam->ifam_version != RTM_VERSION) { 950 if (verbose) 951 warnx("routing message version %d " 952 "not understood", ifam->ifam_version); 953 continue; 954 } 955 if (ifam->ifam_type != RTM_NEWADDR) 956 break; 957 if (ifam->ifam_addrs & RTA_IFA) { 958 int i; 959 char *cp = (char *)(ifam + 1); 960 961 for (i = 1; i < RTA_IFA; i <<= 1) 962 if (ifam->ifam_addrs & i) 963 cp += SA_SIZE((struct sockaddr *)cp); 964 if (((struct sockaddr *)cp)->sa_family == AF_INET) { 965 sin = (struct sockaddr_in *)cp; 966 break; 967 } 968 } 969 } 970 if (sin == NULL) { 971 warnx("%s: cannot get interface address", ifn); 972 free(buf); 973 return EAGAIN; 974 } 975 976 LibAliasSetAddress(mla, sin->sin_addr); 977 syslog(LOG_INFO, "Aliasing to %s, mtu %d bytes", 978 inet_ntoa(sin->sin_addr), mip->ifMTU); 979 980 free(buf); 981 982 return 0; 983 } 984 985 void Quit (const char* msg) 986 { 987 Warn (msg); 988 exit (1); 989 } 990 991 void Warn (const char* msg) 992 { 993 if (background) 994 syslog (LOG_ALERT, "%s (%m)", msg); 995 else 996 warn ("%s", msg); 997 } 998 999 static void RefreshAddr (int sig __unused) 1000 { 1001 LibAliasRefreshModules(); 1002 if (mip != NULL && mip->ifName != NULL) 1003 mip->assignAliasAddr = 1; 1004 } 1005 1006 static void InitiateShutdown (int sig __unused) 1007 { 1008 /* 1009 * Start timer to allow kernel gracefully 1010 * shutdown existing connections when system 1011 * is shut down. 1012 */ 1013 siginterrupt(SIGALRM, 1); 1014 signal (SIGALRM, Shutdown); 1015 ualarm(exitDelay*1000, 1000); 1016 } 1017 1018 static void Shutdown (int sig __unused) 1019 { 1020 running = 0; 1021 } 1022 1023 /* 1024 * Different options recognized by this program. 1025 */ 1026 1027 enum Option { 1028 1029 LibAliasOption, 1030 Instance, 1031 Verbose, 1032 InPort, 1033 OutPort, 1034 Port, 1035 GlobalPort, 1036 AliasAddress, 1037 TargetAddress, 1038 InterfaceName, 1039 RedirectPort, 1040 RedirectProto, 1041 RedirectAddress, 1042 ConfigFile, 1043 DynamicMode, 1044 ProxyRule, 1045 LogDenied, 1046 LogFacility, 1047 PunchFW, 1048 SkinnyPort, 1049 LogIpfwDenied, 1050 PidFile, 1051 ExitDelay 1052 }; 1053 1054 enum Param { 1055 1056 YesNo, 1057 Numeric, 1058 String, 1059 None, 1060 Address, 1061 Service 1062 }; 1063 1064 /* 1065 * Option information structure (used by ParseOption). 1066 */ 1067 1068 struct OptionInfo { 1069 1070 enum Option type; 1071 int packetAliasOpt; 1072 enum Param parm; 1073 const char* parmDescription; 1074 const char* description; 1075 const char* name; 1076 const char* shortName; 1077 }; 1078 1079 /* 1080 * Table of known options. 1081 */ 1082 1083 static struct OptionInfo optionTable[] = { 1084 1085 { LibAliasOption, 1086 PKT_ALIAS_UNREGISTERED_ONLY, 1087 YesNo, 1088 "[yes|no]", 1089 "alias only unregistered addresses", 1090 "unregistered_only", 1091 "u" }, 1092 1093 { LibAliasOption, 1094 PKT_ALIAS_LOG, 1095 YesNo, 1096 "[yes|no]", 1097 "enable logging", 1098 "log", 1099 "l" }, 1100 1101 { LibAliasOption, 1102 PKT_ALIAS_PROXY_ONLY, 1103 YesNo, 1104 "[yes|no]", 1105 "proxy only", 1106 "proxy_only", 1107 NULL }, 1108 1109 { LibAliasOption, 1110 PKT_ALIAS_REVERSE, 1111 YesNo, 1112 "[yes|no]", 1113 "operate in reverse mode", 1114 "reverse", 1115 NULL }, 1116 1117 { LibAliasOption, 1118 PKT_ALIAS_DENY_INCOMING, 1119 YesNo, 1120 "[yes|no]", 1121 "allow incoming connections", 1122 "deny_incoming", 1123 "d" }, 1124 1125 { LibAliasOption, 1126 PKT_ALIAS_USE_SOCKETS, 1127 YesNo, 1128 "[yes|no]", 1129 "use sockets to inhibit port conflict", 1130 "use_sockets", 1131 "s" }, 1132 1133 { LibAliasOption, 1134 PKT_ALIAS_SAME_PORTS, 1135 YesNo, 1136 "[yes|no]", 1137 "try to keep original port numbers for connections", 1138 "same_ports", 1139 "m" }, 1140 1141 { LibAliasOption, 1142 PKT_ALIAS_UDP_EIM, 1143 YesNo, 1144 "[yes|no]", 1145 "UDP traffic uses endpoint-independent mapping (\"full cone\" NAT)", 1146 "udp_eim", 1147 NULL }, 1148 1149 { Verbose, 1150 0, 1151 YesNo, 1152 "[yes|no]", 1153 "verbose mode, dump packet information", 1154 "verbose", 1155 "v" }, 1156 1157 { DynamicMode, 1158 0, 1159 YesNo, 1160 "[yes|no]", 1161 "dynamic mode, automatically detect interface address changes", 1162 "dynamic", 1163 NULL }, 1164 1165 { InPort, 1166 0, 1167 Service, 1168 "number|service_name", 1169 "set port for incoming packets", 1170 "in_port", 1171 "i" }, 1172 1173 { OutPort, 1174 0, 1175 Service, 1176 "number|service_name", 1177 "set port for outgoing packets", 1178 "out_port", 1179 "o" }, 1180 1181 { Port, 1182 0, 1183 Service, 1184 "number|service_name", 1185 "set port (defaults to natd/divert)", 1186 "port", 1187 "p" }, 1188 1189 { GlobalPort, 1190 0, 1191 Service, 1192 "number|service_name", 1193 "set globalport", 1194 "globalport", 1195 NULL }, 1196 1197 { AliasAddress, 1198 0, 1199 Address, 1200 "x.x.x.x", 1201 "address to use for aliasing", 1202 "alias_address", 1203 "a" }, 1204 1205 { TargetAddress, 1206 0, 1207 Address, 1208 "x.x.x.x", 1209 "address to use for incoming sessions", 1210 "target_address", 1211 "t" }, 1212 1213 { InterfaceName, 1214 0, 1215 String, 1216 "network_if_name", 1217 "take aliasing address from interface", 1218 "interface", 1219 "n" }, 1220 1221 { ProxyRule, 1222 0, 1223 String, 1224 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " 1225 "a.b.c.d:yyyy", 1226 "add transparent proxying / destination NAT", 1227 "proxy_rule", 1228 NULL }, 1229 1230 { RedirectPort, 1231 0, 1232 String, 1233 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range" 1234 " [remote_addr[:remote_port_range]]", 1235 "redirect a port (or ports) for incoming traffic", 1236 "redirect_port", 1237 NULL }, 1238 1239 { RedirectProto, 1240 0, 1241 String, 1242 "proto local_addr [public_addr] [remote_addr]", 1243 "redirect packets of a given proto", 1244 "redirect_proto", 1245 NULL }, 1246 1247 { RedirectAddress, 1248 0, 1249 String, 1250 "local_addr[,...] public_addr", 1251 "define mapping between local and public addresses", 1252 "redirect_address", 1253 NULL }, 1254 1255 { ConfigFile, 1256 0, 1257 String, 1258 "file_name", 1259 "read options from configuration file", 1260 "config", 1261 "f" }, 1262 1263 { LogDenied, 1264 0, 1265 YesNo, 1266 "[yes|no]", 1267 "enable logging of denied incoming packets", 1268 "log_denied", 1269 NULL }, 1270 1271 { LogFacility, 1272 0, 1273 String, 1274 "facility", 1275 "name of syslog facility to use for logging", 1276 "log_facility", 1277 NULL }, 1278 1279 { PunchFW, 1280 0, 1281 String, 1282 "basenumber:count", 1283 "punch holes in the firewall for incoming FTP/IRC DCC connections", 1284 "punch_fw", 1285 NULL }, 1286 1287 { SkinnyPort, 1288 0, 1289 String, 1290 "port", 1291 "set the TCP port for use with the Skinny Station protocol", 1292 "skinny_port", 1293 NULL }, 1294 1295 { LogIpfwDenied, 1296 0, 1297 YesNo, 1298 "[yes|no]", 1299 "log packets converted by natd, but denied by ipfw", 1300 "log_ipfw_denied", 1301 NULL }, 1302 1303 { PidFile, 1304 0, 1305 String, 1306 "file_name", 1307 "store PID in an alternate file", 1308 "pid_file", 1309 "P" }, 1310 { Instance, 1311 0, 1312 String, 1313 "instance name", 1314 "name of aliasing engine instance", 1315 "instance", 1316 NULL }, 1317 { ExitDelay, 1318 0, 1319 Numeric, 1320 "ms", 1321 "delay in ms before daemon exit after signal", 1322 "exit_delay", 1323 NULL }, 1324 }; 1325 1326 static void ParseOption (const char* option, const char* parms) 1327 { 1328 int i; 1329 struct OptionInfo* info; 1330 int yesNoValue; 1331 int aliasValue; 1332 int numValue; 1333 u_short uNumValue; 1334 const char* strValue; 1335 struct in_addr addrValue; 1336 int max; 1337 char* end; 1338 const CODE* fac_record = NULL; 1339 /* 1340 * Find option from table. 1341 */ 1342 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1343 for (i = 0, info = optionTable; i < max; i++, info++) { 1344 1345 if (!strcmp (info->name, option)) 1346 break; 1347 1348 if (info->shortName) 1349 if (!strcmp (info->shortName, option)) 1350 break; 1351 } 1352 1353 if (i >= max) { 1354 1355 warnx ("unknown option %s", option); 1356 Usage (); 1357 } 1358 1359 uNumValue = 0; 1360 yesNoValue = 0; 1361 numValue = 0; 1362 strValue = NULL; 1363 /* 1364 * Check parameters. 1365 */ 1366 switch (info->parm) { 1367 case YesNo: 1368 if (!parms) 1369 parms = "yes"; 1370 1371 if (!strcmp (parms, "yes")) 1372 yesNoValue = 1; 1373 else 1374 if (!strcmp (parms, "no")) 1375 yesNoValue = 0; 1376 else 1377 errx (1, "%s needs yes/no parameter", option); 1378 break; 1379 1380 case Service: 1381 if (!parms) 1382 errx (1, "%s needs service name or " 1383 "port number parameter", 1384 option); 1385 1386 uNumValue = StrToPort (parms, "divert"); 1387 break; 1388 1389 case Numeric: 1390 if (parms) 1391 numValue = strtol (parms, &end, 10); 1392 else 1393 end = NULL; 1394 1395 if (end == parms) 1396 errx (1, "%s needs numeric parameter", option); 1397 break; 1398 1399 case String: 1400 strValue = parms; 1401 if (!strValue) 1402 errx (1, "%s needs parameter", option); 1403 break; 1404 1405 case None: 1406 if (parms) 1407 errx (1, "%s does not take parameters", option); 1408 break; 1409 1410 case Address: 1411 if (!parms) 1412 errx (1, "%s needs address/host parameter", option); 1413 1414 StrToAddr (parms, &addrValue); 1415 break; 1416 } 1417 1418 switch (info->type) { 1419 case LibAliasOption: 1420 1421 aliasValue = yesNoValue ? info->packetAliasOpt : 0; 1422 LibAliasSetMode (mla, aliasValue, info->packetAliasOpt); 1423 break; 1424 1425 case Verbose: 1426 verbose = yesNoValue; 1427 break; 1428 1429 case DynamicMode: 1430 dynamicMode = yesNoValue; 1431 break; 1432 1433 case InPort: 1434 mip->inPort = uNumValue; 1435 break; 1436 1437 case OutPort: 1438 mip->outPort = uNumValue; 1439 break; 1440 1441 case Port: 1442 mip->inOutPort = uNumValue; 1443 break; 1444 1445 case GlobalPort: 1446 globalPort = uNumValue; 1447 break; 1448 1449 case AliasAddress: 1450 memcpy (&mip->aliasAddr, &addrValue, sizeof (struct in_addr)); 1451 break; 1452 1453 case TargetAddress: 1454 LibAliasSetTarget(mla, addrValue); 1455 break; 1456 1457 case RedirectPort: 1458 SetupPortRedirect (strValue); 1459 break; 1460 1461 case RedirectProto: 1462 SetupProtoRedirect(strValue); 1463 break; 1464 1465 case RedirectAddress: 1466 SetupAddressRedirect (strValue); 1467 break; 1468 1469 case ProxyRule: 1470 LibAliasProxyRule (mla, strValue); 1471 break; 1472 1473 case InterfaceName: 1474 if (mip->ifName) 1475 free (mip->ifName); 1476 1477 mip->ifName = strdup (strValue); 1478 break; 1479 1480 case ConfigFile: 1481 ReadConfigFile (strValue); 1482 break; 1483 1484 case LogDenied: 1485 mip->logDropped = yesNoValue; 1486 break; 1487 1488 case LogFacility: 1489 1490 fac_record = facilitynames; 1491 while (fac_record->c_name != NULL) { 1492 1493 if (!strcmp (fac_record->c_name, strValue)) { 1494 1495 logFacility = fac_record->c_val; 1496 break; 1497 1498 } 1499 else 1500 fac_record++; 1501 } 1502 1503 if(fac_record->c_name == NULL) 1504 errx(1, "Unknown log facility name: %s", strValue); 1505 1506 break; 1507 1508 case PunchFW: 1509 SetupPunchFW(strValue); 1510 break; 1511 1512 case SkinnyPort: 1513 SetupSkinnyPort(strValue); 1514 break; 1515 1516 case LogIpfwDenied: 1517 logIpfwDenied = yesNoValue; 1518 break; 1519 1520 case PidFile: 1521 pidName = strdup (strValue); 1522 break; 1523 case Instance: 1524 NewInstance(strValue); 1525 break; 1526 case ExitDelay: 1527 if (numValue < 0 || numValue > MAX_EXIT_DELAY) 1528 errx(1, "Incorrect exit delay: %d", numValue); 1529 exitDelay = numValue; 1530 break; 1531 } 1532 } 1533 1534 void ReadConfigFile (const char* fileName) 1535 { 1536 FILE* file; 1537 char *buf; 1538 size_t len; 1539 char *ptr, *p; 1540 char* option; 1541 1542 file = fopen (fileName, "r"); 1543 if (!file) 1544 err(1, "cannot open config file %s", fileName); 1545 1546 while ((buf = fgetln(file, &len)) != NULL) { 1547 if (buf[len - 1] == '\n') 1548 buf[len - 1] = '\0'; 1549 else 1550 errx(1, "config file format error: " 1551 "last line should end with newline"); 1552 1553 /* 1554 * Check for comments, strip off trailing spaces. 1555 */ 1556 if ((ptr = strchr(buf, '#'))) 1557 *ptr = '\0'; 1558 for (ptr = buf; isspace(*ptr); ++ptr) 1559 continue; 1560 if (*ptr == '\0') 1561 continue; 1562 for (p = strchr(buf, '\0'); isspace(*--p);) 1563 continue; 1564 *++p = '\0'; 1565 1566 /* 1567 * Extract option name. 1568 */ 1569 option = ptr; 1570 while (*ptr && !isspace (*ptr)) 1571 ++ptr; 1572 1573 if (*ptr != '\0') { 1574 1575 *ptr = '\0'; 1576 ++ptr; 1577 } 1578 /* 1579 * Skip white space between name and parms. 1580 */ 1581 while (*ptr && isspace (*ptr)) 1582 ++ptr; 1583 1584 ParseOption (option, *ptr ? ptr : NULL); 1585 } 1586 1587 fclose (file); 1588 } 1589 1590 static void Usage(void) 1591 { 1592 int i; 1593 int max; 1594 struct OptionInfo* info; 1595 1596 fprintf (stderr, "Recognized options:\n\n"); 1597 1598 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1599 for (i = 0, info = optionTable; i < max; i++, info++) { 1600 1601 fprintf (stderr, "-%-20s %s\n", info->name, 1602 info->parmDescription); 1603 1604 if (info->shortName) 1605 fprintf (stderr, "-%-20s %s\n", info->shortName, 1606 info->parmDescription); 1607 1608 fprintf (stderr, " %s\n\n", info->description); 1609 } 1610 1611 exit (1); 1612 } 1613 1614 void SetupPortRedirect (const char* parms) 1615 { 1616 char *buf; 1617 char* ptr; 1618 char* serverPool; 1619 struct in_addr localAddr; 1620 struct in_addr publicAddr; 1621 struct in_addr remoteAddr; 1622 port_range portRange; 1623 u_short localPort = 0; 1624 u_short publicPort = 0; 1625 u_short remotePort = 0; 1626 u_short numLocalPorts = 0; 1627 u_short numPublicPorts = 0; 1628 u_short numRemotePorts = 0; 1629 int proto; 1630 char* protoName; 1631 char* separator; 1632 int i; 1633 struct alias_link *aliaslink = NULL; 1634 1635 buf = strdup (parms); 1636 if (!buf) 1637 errx (1, "redirect_port: strdup() failed"); 1638 /* 1639 * Extract protocol. 1640 */ 1641 protoName = strtok (buf, " \t"); 1642 if (!protoName) 1643 errx (1, "redirect_port: missing protocol"); 1644 1645 proto = StrToProto (protoName); 1646 /* 1647 * Extract local address. 1648 */ 1649 ptr = strtok (NULL, " \t"); 1650 if (!ptr) 1651 errx (1, "redirect_port: missing local address"); 1652 1653 separator = strchr(ptr, ','); 1654 if (separator) { /* LSNAT redirection syntax. */ 1655 localAddr.s_addr = INADDR_NONE; 1656 localPort = ~0; 1657 numLocalPorts = 1; 1658 serverPool = ptr; 1659 } else { 1660 if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 ) 1661 errx (1, "redirect_port: invalid local port range"); 1662 1663 localPort = GETLOPORT(portRange); 1664 numLocalPorts = GETNUMPORTS(portRange); 1665 serverPool = NULL; 1666 } 1667 1668 /* 1669 * Extract public port and optionally address. 1670 */ 1671 ptr = strtok (NULL, " \t"); 1672 if (!ptr) 1673 errx (1, "redirect_port: missing public port"); 1674 1675 separator = strchr (ptr, ':'); 1676 if (separator) { 1677 if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 ) 1678 errx (1, "redirect_port: invalid public port range"); 1679 } 1680 else { 1681 publicAddr.s_addr = INADDR_ANY; 1682 if (StrToPortRange (ptr, protoName, &portRange) != 0) 1683 errx (1, "redirect_port: invalid public port range"); 1684 } 1685 1686 publicPort = GETLOPORT(portRange); 1687 numPublicPorts = GETNUMPORTS(portRange); 1688 1689 /* 1690 * Extract remote address and optionally port. 1691 */ 1692 ptr = strtok (NULL, " \t"); 1693 if (ptr) { 1694 separator = strchr (ptr, ':'); 1695 if (separator) { 1696 if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0) 1697 errx (1, "redirect_port: invalid remote port range"); 1698 } else { 1699 SETLOPORT(portRange, 0); 1700 SETNUMPORTS(portRange, 1); 1701 StrToAddr (ptr, &remoteAddr); 1702 } 1703 } 1704 else { 1705 SETLOPORT(portRange, 0); 1706 SETNUMPORTS(portRange, 1); 1707 remoteAddr.s_addr = INADDR_ANY; 1708 } 1709 1710 remotePort = GETLOPORT(portRange); 1711 numRemotePorts = GETNUMPORTS(portRange); 1712 1713 /* 1714 * Make sure port ranges match up, then add the redirect ports. 1715 */ 1716 if (numLocalPorts != numPublicPorts) 1717 errx (1, "redirect_port: port ranges must be equal in size"); 1718 1719 /* Remote port range is allowed to be '0' which means all ports. */ 1720 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0)) 1721 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size"); 1722 1723 for (i = 0 ; i < numPublicPorts ; ++i) { 1724 /* If remotePort is all ports, set it to 0. */ 1725 u_short remotePortCopy = remotePort + i; 1726 if (numRemotePorts == 1 && remotePort == 0) 1727 remotePortCopy = 0; 1728 1729 aliaslink = LibAliasRedirectPort (mla, localAddr, 1730 htons(localPort + i), 1731 remoteAddr, 1732 htons(remotePortCopy), 1733 publicAddr, 1734 htons(publicPort + i), 1735 proto); 1736 } 1737 1738 /* 1739 * Setup LSNAT server pool. 1740 */ 1741 if (serverPool != NULL && aliaslink != NULL) { 1742 ptr = strtok(serverPool, ","); 1743 while (ptr != NULL) { 1744 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0) 1745 errx(1, "redirect_port: invalid local port range"); 1746 1747 localPort = GETLOPORT(portRange); 1748 if (GETNUMPORTS(portRange) != 1) 1749 errx(1, "redirect_port: local port must be single in this context"); 1750 LibAliasAddServer(mla, aliaslink, localAddr, htons(localPort)); 1751 ptr = strtok(NULL, ","); 1752 } 1753 } 1754 1755 free (buf); 1756 } 1757 1758 void 1759 SetupProtoRedirect(const char* parms) 1760 { 1761 char *buf; 1762 char* ptr; 1763 struct in_addr localAddr; 1764 struct in_addr publicAddr; 1765 struct in_addr remoteAddr; 1766 int proto; 1767 char* protoName; 1768 struct protoent *protoent; 1769 1770 buf = strdup (parms); 1771 if (!buf) 1772 errx (1, "redirect_port: strdup() failed"); 1773 /* 1774 * Extract protocol. 1775 */ 1776 protoName = strtok(buf, " \t"); 1777 if (!protoName) 1778 errx(1, "redirect_proto: missing protocol"); 1779 1780 protoent = getprotobyname(protoName); 1781 if (protoent == NULL) 1782 errx(1, "redirect_proto: unknown protocol %s", protoName); 1783 else 1784 proto = protoent->p_proto; 1785 /* 1786 * Extract local address. 1787 */ 1788 ptr = strtok(NULL, " \t"); 1789 if (!ptr) 1790 errx(1, "redirect_proto: missing local address"); 1791 else 1792 StrToAddr(ptr, &localAddr); 1793 /* 1794 * Extract optional public address. 1795 */ 1796 ptr = strtok(NULL, " \t"); 1797 if (ptr) 1798 StrToAddr(ptr, &publicAddr); 1799 else 1800 publicAddr.s_addr = INADDR_ANY; 1801 /* 1802 * Extract optional remote address. 1803 */ 1804 ptr = strtok(NULL, " \t"); 1805 if (ptr) 1806 StrToAddr(ptr, &remoteAddr); 1807 else 1808 remoteAddr.s_addr = INADDR_ANY; 1809 /* 1810 * Create aliasing link. 1811 */ 1812 (void)LibAliasRedirectProto(mla, localAddr, remoteAddr, publicAddr, 1813 proto); 1814 1815 free (buf); 1816 } 1817 1818 void SetupAddressRedirect (const char* parms) 1819 { 1820 char *buf; 1821 char* ptr; 1822 char* separator; 1823 struct in_addr localAddr; 1824 struct in_addr publicAddr; 1825 char* serverPool; 1826 struct alias_link *aliaslink; 1827 1828 buf = strdup (parms); 1829 if (!buf) 1830 errx (1, "redirect_port: strdup() failed"); 1831 /* 1832 * Extract local address. 1833 */ 1834 ptr = strtok (buf, " \t"); 1835 if (!ptr) 1836 errx (1, "redirect_address: missing local address"); 1837 1838 separator = strchr(ptr, ','); 1839 if (separator) { /* LSNAT redirection syntax. */ 1840 localAddr.s_addr = INADDR_NONE; 1841 serverPool = ptr; 1842 } else { 1843 StrToAddr (ptr, &localAddr); 1844 serverPool = NULL; 1845 } 1846 /* 1847 * Extract public address. 1848 */ 1849 ptr = strtok (NULL, " \t"); 1850 if (!ptr) 1851 errx (1, "redirect_address: missing public address"); 1852 1853 StrToAddr (ptr, &publicAddr); 1854 aliaslink = LibAliasRedirectAddr(mla, localAddr, publicAddr); 1855 1856 /* 1857 * Setup LSNAT server pool. 1858 */ 1859 if (serverPool != NULL && aliaslink != NULL) { 1860 ptr = strtok(serverPool, ","); 1861 while (ptr != NULL) { 1862 StrToAddr(ptr, &localAddr); 1863 LibAliasAddServer(mla, aliaslink, localAddr, htons(~0)); 1864 ptr = strtok(NULL, ","); 1865 } 1866 } 1867 1868 free (buf); 1869 } 1870 1871 void StrToAddr (const char* str, struct in_addr* addr) 1872 { 1873 struct hostent* hp; 1874 1875 if (inet_aton (str, addr)) 1876 return; 1877 1878 hp = gethostbyname (str); 1879 if (!hp) 1880 errx (1, "unknown host %s", str); 1881 1882 memcpy (addr, hp->h_addr, sizeof (struct in_addr)); 1883 } 1884 1885 u_short StrToPort (const char* str, const char* proto) 1886 { 1887 u_short port; 1888 struct servent* sp; 1889 char* end; 1890 1891 port = strtol (str, &end, 10); 1892 if (end != str) 1893 return htons (port); 1894 1895 sp = getservbyname (str, proto); 1896 if (!sp) 1897 errx (1, "%s/%s: unknown service", str, proto); 1898 1899 return sp->s_port; 1900 } 1901 1902 int StrToPortRange (const char* str, const char* proto, port_range *portRange) 1903 { 1904 const char* sep; 1905 struct servent* sp; 1906 char* end; 1907 u_short loPort; 1908 u_short hiPort; 1909 1910 /* First see if this is a service, return corresponding port if so. */ 1911 sp = getservbyname (str,proto); 1912 if (sp) { 1913 SETLOPORT(*portRange, ntohs(sp->s_port)); 1914 SETNUMPORTS(*portRange, 1); 1915 return 0; 1916 } 1917 1918 /* Not a service, see if it's a single port or port range. */ 1919 sep = strchr (str, '-'); 1920 if (sep == NULL) { 1921 SETLOPORT(*portRange, strtol(str, &end, 10)); 1922 if (end != str) { 1923 /* Single port. */ 1924 SETNUMPORTS(*portRange, 1); 1925 return 0; 1926 } 1927 1928 /* Error in port range field. */ 1929 errx (1, "%s/%s: unknown service", str, proto); 1930 } 1931 1932 /* Port range, get the values and sanity check. */ 1933 sscanf (str, "%hu-%hu", &loPort, &hiPort); 1934 SETLOPORT(*portRange, loPort); 1935 SETNUMPORTS(*portRange, 0); /* Error by default */ 1936 if (loPort <= hiPort) 1937 SETNUMPORTS(*portRange, hiPort - loPort + 1); 1938 1939 if (GETNUMPORTS(*portRange) == 0) 1940 errx (1, "invalid port range %s", str); 1941 1942 return 0; 1943 } 1944 1945 1946 static int 1947 StrToProto (const char* str) 1948 { 1949 if (!strcmp (str, "tcp")) 1950 return IPPROTO_TCP; 1951 1952 if (!strcmp (str, "udp")) 1953 return IPPROTO_UDP; 1954 1955 errx (1, "unknown protocol %s. Expected tcp or udp", str); 1956 } 1957 1958 static int 1959 StrToAddrAndPortRange (char* str, struct in_addr* addr, char* proto, port_range *portRange) 1960 { 1961 char* ptr; 1962 1963 ptr = strchr (str, ':'); 1964 if (!ptr) 1965 errx (1, "%s is missing port number", str); 1966 1967 *ptr = '\0'; 1968 ++ptr; 1969 1970 StrToAddr (str, addr); 1971 return StrToPortRange (ptr, proto, portRange); 1972 } 1973 1974 static void 1975 SetupPunchFW(const char *strValue) 1976 { 1977 unsigned int base, num; 1978 1979 if (sscanf(strValue, "%u:%u", &base, &num) != 2) 1980 errx(1, "punch_fw: basenumber:count parameter required"); 1981 1982 if (CheckIpfwRulenum(base + num - 1) == -1) 1983 errx(1, "punch_fw: basenumber:count parameter should fit " 1984 "the maximum allowed rule numbers"); 1985 1986 LibAliasSetFWBase(mla, base, num); 1987 (void)LibAliasSetMode(mla, PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW); 1988 } 1989 1990 static void 1991 SetupSkinnyPort(const char *strValue) 1992 { 1993 unsigned int port; 1994 1995 if (sscanf(strValue, "%u", &port) != 1) 1996 errx(1, "skinny_port: port parameter required"); 1997 1998 LibAliasSetSkinnyPort(mla, port); 1999 } 2000 2001 static void 2002 NewInstance(const char *name) 2003 { 2004 struct instance *ip; 2005 2006 LIST_FOREACH(ip, &root, list) { 2007 if (!strcmp(ip->name, name)) { 2008 mla = ip->la; 2009 mip = ip; 2010 return; 2011 } 2012 } 2013 ninstance++; 2014 ip = calloc(1, sizeof(*ip)); 2015 ip->name = strdup(name); 2016 ip->la = LibAliasInit (ip->la); 2017 ip->assignAliasAddr = 0; 2018 ip->ifName = NULL; 2019 ip->logDropped = 0; 2020 ip->inPort = 0; 2021 ip->outPort = 0; 2022 ip->inOutPort = 0; 2023 ip->aliasAddr.s_addr = INADDR_NONE; 2024 ip->ifMTU = -1; 2025 ip->aliasOverhead = 12; 2026 LIST_INSERT_HEAD(&root, ip, list); 2027 mla = ip->la; 2028 mip = ip; 2029 } 2030 2031 static int 2032 CheckIpfwRulenum(unsigned int rnum) 2033 { 2034 unsigned int default_rule; 2035 size_t len = sizeof(default_rule); 2036 2037 if (sysctlbyname("net.inet.ip.fw.default_rule", &default_rule, &len, 2038 NULL, 0) == -1) { 2039 warn("Failed to get the default ipfw rule number, using " 2040 "default historical value 65535. The reason was"); 2041 default_rule = 65535; 2042 } 2043 if (rnum >= default_rule) { 2044 return -1; 2045 } 2046 2047 return 0; 2048 } 2049