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