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