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 { Verbose, 1142 0, 1143 YesNo, 1144 "[yes|no]", 1145 "verbose mode, dump packet information", 1146 "verbose", 1147 "v" }, 1148 1149 { DynamicMode, 1150 0, 1151 YesNo, 1152 "[yes|no]", 1153 "dynamic mode, automatically detect interface address changes", 1154 "dynamic", 1155 NULL }, 1156 1157 { InPort, 1158 0, 1159 Service, 1160 "number|service_name", 1161 "set port for incoming packets", 1162 "in_port", 1163 "i" }, 1164 1165 { OutPort, 1166 0, 1167 Service, 1168 "number|service_name", 1169 "set port for outgoing packets", 1170 "out_port", 1171 "o" }, 1172 1173 { Port, 1174 0, 1175 Service, 1176 "number|service_name", 1177 "set port (defaults to natd/divert)", 1178 "port", 1179 "p" }, 1180 1181 { GlobalPort, 1182 0, 1183 Service, 1184 "number|service_name", 1185 "set globalport", 1186 "globalport", 1187 NULL }, 1188 1189 { AliasAddress, 1190 0, 1191 Address, 1192 "x.x.x.x", 1193 "address to use for aliasing", 1194 "alias_address", 1195 "a" }, 1196 1197 { TargetAddress, 1198 0, 1199 Address, 1200 "x.x.x.x", 1201 "address to use for incoming sessions", 1202 "target_address", 1203 "t" }, 1204 1205 { InterfaceName, 1206 0, 1207 String, 1208 "network_if_name", 1209 "take aliasing address from interface", 1210 "interface", 1211 "n" }, 1212 1213 { ProxyRule, 1214 0, 1215 String, 1216 "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " 1217 "a.b.c.d:yyyy", 1218 "add transparent proxying / destination NAT", 1219 "proxy_rule", 1220 NULL }, 1221 1222 { RedirectPort, 1223 0, 1224 String, 1225 "tcp|udp local_addr:local_port_range[,...] [public_addr:]public_port_range" 1226 " [remote_addr[:remote_port_range]]", 1227 "redirect a port (or ports) for incoming traffic", 1228 "redirect_port", 1229 NULL }, 1230 1231 { RedirectProto, 1232 0, 1233 String, 1234 "proto local_addr [public_addr] [remote_addr]", 1235 "redirect packets of a given proto", 1236 "redirect_proto", 1237 NULL }, 1238 1239 { RedirectAddress, 1240 0, 1241 String, 1242 "local_addr[,...] public_addr", 1243 "define mapping between local and public addresses", 1244 "redirect_address", 1245 NULL }, 1246 1247 { ConfigFile, 1248 0, 1249 String, 1250 "file_name", 1251 "read options from configuration file", 1252 "config", 1253 "f" }, 1254 1255 { LogDenied, 1256 0, 1257 YesNo, 1258 "[yes|no]", 1259 "enable logging of denied incoming packets", 1260 "log_denied", 1261 NULL }, 1262 1263 { LogFacility, 1264 0, 1265 String, 1266 "facility", 1267 "name of syslog facility to use for logging", 1268 "log_facility", 1269 NULL }, 1270 1271 { PunchFW, 1272 0, 1273 String, 1274 "basenumber:count", 1275 "punch holes in the firewall for incoming FTP/IRC DCC connections", 1276 "punch_fw", 1277 NULL }, 1278 1279 { SkinnyPort, 1280 0, 1281 String, 1282 "port", 1283 "set the TCP port for use with the Skinny Station protocol", 1284 "skinny_port", 1285 NULL }, 1286 1287 { LogIpfwDenied, 1288 0, 1289 YesNo, 1290 "[yes|no]", 1291 "log packets converted by natd, but denied by ipfw", 1292 "log_ipfw_denied", 1293 NULL }, 1294 1295 { PidFile, 1296 0, 1297 String, 1298 "file_name", 1299 "store PID in an alternate file", 1300 "pid_file", 1301 "P" }, 1302 { Instance, 1303 0, 1304 String, 1305 "instance name", 1306 "name of aliasing engine instance", 1307 "instance", 1308 NULL }, 1309 { ExitDelay, 1310 0, 1311 Numeric, 1312 "ms", 1313 "delay in ms before daemon exit after signal", 1314 "exit_delay", 1315 NULL }, 1316 }; 1317 1318 static void ParseOption (const char* option, const char* parms) 1319 { 1320 int i; 1321 struct OptionInfo* info; 1322 int yesNoValue; 1323 int aliasValue; 1324 int numValue; 1325 u_short uNumValue; 1326 const char* strValue; 1327 struct in_addr addrValue; 1328 int max; 1329 char* end; 1330 const CODE* fac_record = NULL; 1331 /* 1332 * Find option from table. 1333 */ 1334 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1335 for (i = 0, info = optionTable; i < max; i++, info++) { 1336 1337 if (!strcmp (info->name, option)) 1338 break; 1339 1340 if (info->shortName) 1341 if (!strcmp (info->shortName, option)) 1342 break; 1343 } 1344 1345 if (i >= max) { 1346 1347 warnx ("unknown option %s", option); 1348 Usage (); 1349 } 1350 1351 uNumValue = 0; 1352 yesNoValue = 0; 1353 numValue = 0; 1354 strValue = NULL; 1355 /* 1356 * Check parameters. 1357 */ 1358 switch (info->parm) { 1359 case YesNo: 1360 if (!parms) 1361 parms = "yes"; 1362 1363 if (!strcmp (parms, "yes")) 1364 yesNoValue = 1; 1365 else 1366 if (!strcmp (parms, "no")) 1367 yesNoValue = 0; 1368 else 1369 errx (1, "%s needs yes/no parameter", option); 1370 break; 1371 1372 case Service: 1373 if (!parms) 1374 errx (1, "%s needs service name or " 1375 "port number parameter", 1376 option); 1377 1378 uNumValue = StrToPort (parms, "divert"); 1379 break; 1380 1381 case Numeric: 1382 if (parms) 1383 numValue = strtol (parms, &end, 10); 1384 else 1385 end = NULL; 1386 1387 if (end == parms) 1388 errx (1, "%s needs numeric parameter", option); 1389 break; 1390 1391 case String: 1392 strValue = parms; 1393 if (!strValue) 1394 errx (1, "%s needs parameter", option); 1395 break; 1396 1397 case None: 1398 if (parms) 1399 errx (1, "%s does not take parameters", option); 1400 break; 1401 1402 case Address: 1403 if (!parms) 1404 errx (1, "%s needs address/host parameter", option); 1405 1406 StrToAddr (parms, &addrValue); 1407 break; 1408 } 1409 1410 switch (info->type) { 1411 case LibAliasOption: 1412 1413 aliasValue = yesNoValue ? info->packetAliasOpt : 0; 1414 LibAliasSetMode (mla, aliasValue, info->packetAliasOpt); 1415 break; 1416 1417 case Verbose: 1418 verbose = yesNoValue; 1419 break; 1420 1421 case DynamicMode: 1422 dynamicMode = yesNoValue; 1423 break; 1424 1425 case InPort: 1426 mip->inPort = uNumValue; 1427 break; 1428 1429 case OutPort: 1430 mip->outPort = uNumValue; 1431 break; 1432 1433 case Port: 1434 mip->inOutPort = uNumValue; 1435 break; 1436 1437 case GlobalPort: 1438 globalPort = uNumValue; 1439 break; 1440 1441 case AliasAddress: 1442 memcpy (&mip->aliasAddr, &addrValue, sizeof (struct in_addr)); 1443 break; 1444 1445 case TargetAddress: 1446 LibAliasSetTarget(mla, addrValue); 1447 break; 1448 1449 case RedirectPort: 1450 SetupPortRedirect (strValue); 1451 break; 1452 1453 case RedirectProto: 1454 SetupProtoRedirect(strValue); 1455 break; 1456 1457 case RedirectAddress: 1458 SetupAddressRedirect (strValue); 1459 break; 1460 1461 case ProxyRule: 1462 LibAliasProxyRule (mla, strValue); 1463 break; 1464 1465 case InterfaceName: 1466 if (mip->ifName) 1467 free (mip->ifName); 1468 1469 mip->ifName = strdup (strValue); 1470 break; 1471 1472 case ConfigFile: 1473 ReadConfigFile (strValue); 1474 break; 1475 1476 case LogDenied: 1477 mip->logDropped = yesNoValue; 1478 break; 1479 1480 case LogFacility: 1481 1482 fac_record = facilitynames; 1483 while (fac_record->c_name != NULL) { 1484 1485 if (!strcmp (fac_record->c_name, strValue)) { 1486 1487 logFacility = fac_record->c_val; 1488 break; 1489 1490 } 1491 else 1492 fac_record++; 1493 } 1494 1495 if(fac_record->c_name == NULL) 1496 errx(1, "Unknown log facility name: %s", strValue); 1497 1498 break; 1499 1500 case PunchFW: 1501 SetupPunchFW(strValue); 1502 break; 1503 1504 case SkinnyPort: 1505 SetupSkinnyPort(strValue); 1506 break; 1507 1508 case LogIpfwDenied: 1509 logIpfwDenied = yesNoValue; 1510 break; 1511 1512 case PidFile: 1513 pidName = strdup (strValue); 1514 break; 1515 case Instance: 1516 NewInstance(strValue); 1517 break; 1518 case ExitDelay: 1519 if (numValue < 0 || numValue > MAX_EXIT_DELAY) 1520 errx(1, "Incorrect exit delay: %d", numValue); 1521 exitDelay = numValue; 1522 break; 1523 } 1524 } 1525 1526 void ReadConfigFile (const char* fileName) 1527 { 1528 FILE* file; 1529 char *buf; 1530 size_t len; 1531 char *ptr, *p; 1532 char* option; 1533 1534 file = fopen (fileName, "r"); 1535 if (!file) 1536 err(1, "cannot open config file %s", fileName); 1537 1538 while ((buf = fgetln(file, &len)) != NULL) { 1539 if (buf[len - 1] == '\n') 1540 buf[len - 1] = '\0'; 1541 else 1542 errx(1, "config file format error: " 1543 "last line should end with newline"); 1544 1545 /* 1546 * Check for comments, strip off trailing spaces. 1547 */ 1548 if ((ptr = strchr(buf, '#'))) 1549 *ptr = '\0'; 1550 for (ptr = buf; isspace(*ptr); ++ptr) 1551 continue; 1552 if (*ptr == '\0') 1553 continue; 1554 for (p = strchr(buf, '\0'); isspace(*--p);) 1555 continue; 1556 *++p = '\0'; 1557 1558 /* 1559 * Extract option name. 1560 */ 1561 option = ptr; 1562 while (*ptr && !isspace (*ptr)) 1563 ++ptr; 1564 1565 if (*ptr != '\0') { 1566 1567 *ptr = '\0'; 1568 ++ptr; 1569 } 1570 /* 1571 * Skip white space between name and parms. 1572 */ 1573 while (*ptr && isspace (*ptr)) 1574 ++ptr; 1575 1576 ParseOption (option, *ptr ? ptr : NULL); 1577 } 1578 1579 fclose (file); 1580 } 1581 1582 static void Usage(void) 1583 { 1584 int i; 1585 int max; 1586 struct OptionInfo* info; 1587 1588 fprintf (stderr, "Recognized options:\n\n"); 1589 1590 max = sizeof (optionTable) / sizeof (struct OptionInfo); 1591 for (i = 0, info = optionTable; i < max; i++, info++) { 1592 1593 fprintf (stderr, "-%-20s %s\n", info->name, 1594 info->parmDescription); 1595 1596 if (info->shortName) 1597 fprintf (stderr, "-%-20s %s\n", info->shortName, 1598 info->parmDescription); 1599 1600 fprintf (stderr, " %s\n\n", info->description); 1601 } 1602 1603 exit (1); 1604 } 1605 1606 void SetupPortRedirect (const char* parms) 1607 { 1608 char *buf; 1609 char* ptr; 1610 char* serverPool; 1611 struct in_addr localAddr; 1612 struct in_addr publicAddr; 1613 struct in_addr remoteAddr; 1614 port_range portRange; 1615 u_short localPort = 0; 1616 u_short publicPort = 0; 1617 u_short remotePort = 0; 1618 u_short numLocalPorts = 0; 1619 u_short numPublicPorts = 0; 1620 u_short numRemotePorts = 0; 1621 int proto; 1622 char* protoName; 1623 char* separator; 1624 int i; 1625 struct alias_link *aliaslink = NULL; 1626 1627 buf = strdup (parms); 1628 if (!buf) 1629 errx (1, "redirect_port: strdup() failed"); 1630 /* 1631 * Extract protocol. 1632 */ 1633 protoName = strtok (buf, " \t"); 1634 if (!protoName) 1635 errx (1, "redirect_port: missing protocol"); 1636 1637 proto = StrToProto (protoName); 1638 /* 1639 * Extract local address. 1640 */ 1641 ptr = strtok (NULL, " \t"); 1642 if (!ptr) 1643 errx (1, "redirect_port: missing local address"); 1644 1645 separator = strchr(ptr, ','); 1646 if (separator) { /* LSNAT redirection syntax. */ 1647 localAddr.s_addr = INADDR_NONE; 1648 localPort = ~0; 1649 numLocalPorts = 1; 1650 serverPool = ptr; 1651 } else { 1652 if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 ) 1653 errx (1, "redirect_port: invalid local port range"); 1654 1655 localPort = GETLOPORT(portRange); 1656 numLocalPorts = GETNUMPORTS(portRange); 1657 serverPool = NULL; 1658 } 1659 1660 /* 1661 * Extract public port and optionally address. 1662 */ 1663 ptr = strtok (NULL, " \t"); 1664 if (!ptr) 1665 errx (1, "redirect_port: missing public port"); 1666 1667 separator = strchr (ptr, ':'); 1668 if (separator) { 1669 if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 ) 1670 errx (1, "redirect_port: invalid public port range"); 1671 } 1672 else { 1673 publicAddr.s_addr = INADDR_ANY; 1674 if (StrToPortRange (ptr, protoName, &portRange) != 0) 1675 errx (1, "redirect_port: invalid public port range"); 1676 } 1677 1678 publicPort = GETLOPORT(portRange); 1679 numPublicPorts = GETNUMPORTS(portRange); 1680 1681 /* 1682 * Extract remote address and optionally port. 1683 */ 1684 ptr = strtok (NULL, " \t"); 1685 if (ptr) { 1686 separator = strchr (ptr, ':'); 1687 if (separator) { 1688 if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0) 1689 errx (1, "redirect_port: invalid remote port range"); 1690 } else { 1691 SETLOPORT(portRange, 0); 1692 SETNUMPORTS(portRange, 1); 1693 StrToAddr (ptr, &remoteAddr); 1694 } 1695 } 1696 else { 1697 SETLOPORT(portRange, 0); 1698 SETNUMPORTS(portRange, 1); 1699 remoteAddr.s_addr = INADDR_ANY; 1700 } 1701 1702 remotePort = GETLOPORT(portRange); 1703 numRemotePorts = GETNUMPORTS(portRange); 1704 1705 /* 1706 * Make sure port ranges match up, then add the redirect ports. 1707 */ 1708 if (numLocalPorts != numPublicPorts) 1709 errx (1, "redirect_port: port ranges must be equal in size"); 1710 1711 /* Remote port range is allowed to be '0' which means all ports. */ 1712 if (numRemotePorts != numLocalPorts && (numRemotePorts != 1 || remotePort != 0)) 1713 errx (1, "redirect_port: remote port must be 0 or equal to local port range in size"); 1714 1715 for (i = 0 ; i < numPublicPorts ; ++i) { 1716 /* If remotePort is all ports, set it to 0. */ 1717 u_short remotePortCopy = remotePort + i; 1718 if (numRemotePorts == 1 && remotePort == 0) 1719 remotePortCopy = 0; 1720 1721 aliaslink = LibAliasRedirectPort (mla, localAddr, 1722 htons(localPort + i), 1723 remoteAddr, 1724 htons(remotePortCopy), 1725 publicAddr, 1726 htons(publicPort + i), 1727 proto); 1728 } 1729 1730 /* 1731 * Setup LSNAT server pool. 1732 */ 1733 if (serverPool != NULL && aliaslink != NULL) { 1734 ptr = strtok(serverPool, ","); 1735 while (ptr != NULL) { 1736 if (StrToAddrAndPortRange(ptr, &localAddr, protoName, &portRange) != 0) 1737 errx(1, "redirect_port: invalid local port range"); 1738 1739 localPort = GETLOPORT(portRange); 1740 if (GETNUMPORTS(portRange) != 1) 1741 errx(1, "redirect_port: local port must be single in this context"); 1742 LibAliasAddServer(mla, aliaslink, localAddr, htons(localPort)); 1743 ptr = strtok(NULL, ","); 1744 } 1745 } 1746 1747 free (buf); 1748 } 1749 1750 void 1751 SetupProtoRedirect(const char* parms) 1752 { 1753 char *buf; 1754 char* ptr; 1755 struct in_addr localAddr; 1756 struct in_addr publicAddr; 1757 struct in_addr remoteAddr; 1758 int proto; 1759 char* protoName; 1760 struct protoent *protoent; 1761 1762 buf = strdup (parms); 1763 if (!buf) 1764 errx (1, "redirect_port: strdup() failed"); 1765 /* 1766 * Extract protocol. 1767 */ 1768 protoName = strtok(buf, " \t"); 1769 if (!protoName) 1770 errx(1, "redirect_proto: missing protocol"); 1771 1772 protoent = getprotobyname(protoName); 1773 if (protoent == NULL) 1774 errx(1, "redirect_proto: unknown protocol %s", protoName); 1775 else 1776 proto = protoent->p_proto; 1777 /* 1778 * Extract local address. 1779 */ 1780 ptr = strtok(NULL, " \t"); 1781 if (!ptr) 1782 errx(1, "redirect_proto: missing local address"); 1783 else 1784 StrToAddr(ptr, &localAddr); 1785 /* 1786 * Extract optional public address. 1787 */ 1788 ptr = strtok(NULL, " \t"); 1789 if (ptr) 1790 StrToAddr(ptr, &publicAddr); 1791 else 1792 publicAddr.s_addr = INADDR_ANY; 1793 /* 1794 * Extract optional remote address. 1795 */ 1796 ptr = strtok(NULL, " \t"); 1797 if (ptr) 1798 StrToAddr(ptr, &remoteAddr); 1799 else 1800 remoteAddr.s_addr = INADDR_ANY; 1801 /* 1802 * Create aliasing link. 1803 */ 1804 (void)LibAliasRedirectProto(mla, localAddr, remoteAddr, publicAddr, 1805 proto); 1806 1807 free (buf); 1808 } 1809 1810 void SetupAddressRedirect (const char* parms) 1811 { 1812 char *buf; 1813 char* ptr; 1814 char* separator; 1815 struct in_addr localAddr; 1816 struct in_addr publicAddr; 1817 char* serverPool; 1818 struct alias_link *aliaslink; 1819 1820 buf = strdup (parms); 1821 if (!buf) 1822 errx (1, "redirect_port: strdup() failed"); 1823 /* 1824 * Extract local address. 1825 */ 1826 ptr = strtok (buf, " \t"); 1827 if (!ptr) 1828 errx (1, "redirect_address: missing local address"); 1829 1830 separator = strchr(ptr, ','); 1831 if (separator) { /* LSNAT redirection syntax. */ 1832 localAddr.s_addr = INADDR_NONE; 1833 serverPool = ptr; 1834 } else { 1835 StrToAddr (ptr, &localAddr); 1836 serverPool = NULL; 1837 } 1838 /* 1839 * Extract public address. 1840 */ 1841 ptr = strtok (NULL, " \t"); 1842 if (!ptr) 1843 errx (1, "redirect_address: missing public address"); 1844 1845 StrToAddr (ptr, &publicAddr); 1846 aliaslink = LibAliasRedirectAddr(mla, localAddr, publicAddr); 1847 1848 /* 1849 * Setup LSNAT server pool. 1850 */ 1851 if (serverPool != NULL && aliaslink != NULL) { 1852 ptr = strtok(serverPool, ","); 1853 while (ptr != NULL) { 1854 StrToAddr(ptr, &localAddr); 1855 LibAliasAddServer(mla, aliaslink, localAddr, htons(~0)); 1856 ptr = strtok(NULL, ","); 1857 } 1858 } 1859 1860 free (buf); 1861 } 1862 1863 void StrToAddr (const char* str, struct in_addr* addr) 1864 { 1865 struct hostent* hp; 1866 1867 if (inet_aton (str, addr)) 1868 return; 1869 1870 hp = gethostbyname (str); 1871 if (!hp) 1872 errx (1, "unknown host %s", str); 1873 1874 memcpy (addr, hp->h_addr, sizeof (struct in_addr)); 1875 } 1876 1877 u_short StrToPort (const char* str, const char* proto) 1878 { 1879 u_short port; 1880 struct servent* sp; 1881 char* end; 1882 1883 port = strtol (str, &end, 10); 1884 if (end != str) 1885 return htons (port); 1886 1887 sp = getservbyname (str, proto); 1888 if (!sp) 1889 errx (1, "%s/%s: unknown service", str, proto); 1890 1891 return sp->s_port; 1892 } 1893 1894 int StrToPortRange (const char* str, const char* proto, port_range *portRange) 1895 { 1896 const char* sep; 1897 struct servent* sp; 1898 char* end; 1899 u_short loPort; 1900 u_short hiPort; 1901 1902 /* First see if this is a service, return corresponding port if so. */ 1903 sp = getservbyname (str,proto); 1904 if (sp) { 1905 SETLOPORT(*portRange, ntohs(sp->s_port)); 1906 SETNUMPORTS(*portRange, 1); 1907 return 0; 1908 } 1909 1910 /* Not a service, see if it's a single port or port range. */ 1911 sep = strchr (str, '-'); 1912 if (sep == NULL) { 1913 SETLOPORT(*portRange, strtol(str, &end, 10)); 1914 if (end != str) { 1915 /* Single port. */ 1916 SETNUMPORTS(*portRange, 1); 1917 return 0; 1918 } 1919 1920 /* Error in port range field. */ 1921 errx (1, "%s/%s: unknown service", str, proto); 1922 } 1923 1924 /* Port range, get the values and sanity check. */ 1925 sscanf (str, "%hu-%hu", &loPort, &hiPort); 1926 SETLOPORT(*portRange, loPort); 1927 SETNUMPORTS(*portRange, 0); /* Error by default */ 1928 if (loPort <= hiPort) 1929 SETNUMPORTS(*portRange, hiPort - loPort + 1); 1930 1931 if (GETNUMPORTS(*portRange) == 0) 1932 errx (1, "invalid port range %s", str); 1933 1934 return 0; 1935 } 1936 1937 1938 static int 1939 StrToProto (const char* str) 1940 { 1941 if (!strcmp (str, "tcp")) 1942 return IPPROTO_TCP; 1943 1944 if (!strcmp (str, "udp")) 1945 return IPPROTO_UDP; 1946 1947 errx (1, "unknown protocol %s. Expected tcp or udp", str); 1948 } 1949 1950 static int 1951 StrToAddrAndPortRange (char* str, struct in_addr* addr, char* proto, port_range *portRange) 1952 { 1953 char* ptr; 1954 1955 ptr = strchr (str, ':'); 1956 if (!ptr) 1957 errx (1, "%s is missing port number", str); 1958 1959 *ptr = '\0'; 1960 ++ptr; 1961 1962 StrToAddr (str, addr); 1963 return StrToPortRange (ptr, proto, portRange); 1964 } 1965 1966 static void 1967 SetupPunchFW(const char *strValue) 1968 { 1969 unsigned int base, num; 1970 1971 if (sscanf(strValue, "%u:%u", &base, &num) != 2) 1972 errx(1, "punch_fw: basenumber:count parameter required"); 1973 1974 if (CheckIpfwRulenum(base + num - 1) == -1) 1975 errx(1, "punch_fw: basenumber:count parameter should fit " 1976 "the maximum allowed rule numbers"); 1977 1978 LibAliasSetFWBase(mla, base, num); 1979 (void)LibAliasSetMode(mla, PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW); 1980 } 1981 1982 static void 1983 SetupSkinnyPort(const char *strValue) 1984 { 1985 unsigned int port; 1986 1987 if (sscanf(strValue, "%u", &port) != 1) 1988 errx(1, "skinny_port: port parameter required"); 1989 1990 LibAliasSetSkinnyPort(mla, port); 1991 } 1992 1993 static void 1994 NewInstance(const char *name) 1995 { 1996 struct instance *ip; 1997 1998 LIST_FOREACH(ip, &root, list) { 1999 if (!strcmp(ip->name, name)) { 2000 mla = ip->la; 2001 mip = ip; 2002 return; 2003 } 2004 } 2005 ninstance++; 2006 ip = calloc(1, sizeof(*ip)); 2007 ip->name = strdup(name); 2008 ip->la = LibAliasInit (ip->la); 2009 ip->assignAliasAddr = 0; 2010 ip->ifName = NULL; 2011 ip->logDropped = 0; 2012 ip->inPort = 0; 2013 ip->outPort = 0; 2014 ip->inOutPort = 0; 2015 ip->aliasAddr.s_addr = INADDR_NONE; 2016 ip->ifMTU = -1; 2017 ip->aliasOverhead = 12; 2018 LIST_INSERT_HEAD(&root, ip, list); 2019 mla = ip->la; 2020 mip = ip; 2021 } 2022 2023 static int 2024 CheckIpfwRulenum(unsigned int rnum) 2025 { 2026 unsigned int default_rule; 2027 size_t len = sizeof(default_rule); 2028 2029 if (sysctlbyname("net.inet.ip.fw.default_rule", &default_rule, &len, 2030 NULL, 0) == -1) { 2031 warn("Failed to get the default ipfw rule number, using " 2032 "default historical value 65535. The reason was"); 2033 default_rule = 65535; 2034 } 2035 if (rnum >= default_rule) { 2036 return -1; 2037 } 2038 2039 return 0; 2040 } 2041