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