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