diff options
Diffstat (limited to 'usr.sbin/natd/natd.c')
-rw-r--r-- | usr.sbin/natd/natd.c | 1477 |
1 files changed, 0 insertions, 1477 deletions
diff --git a/usr.sbin/natd/natd.c b/usr.sbin/natd/natd.c deleted file mode 100644 index 5dab03e..0000000 --- a/usr.sbin/natd/natd.c +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * natd - Network Address Translation Daemon for FreeBSD. - * - * This software is provided free of charge, with no - * warranty of any kind, either expressed or implied. - * Use at your own risk. - * - * You may copy, modify and distribute this software (natd.c) freely. - * - * Ari Suutari <suutari@iki.fi> - * - * $Id: natd.c,v 1.10 1999/03/07 18:23:56 brian Exp $ - */ - -#define SYSLOG_NAMES - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <machine/in_cksum.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <net/route.h> -#include <arpa/inet.h> - -#include <alias.h> -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <netdb.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> - -#include "natd.h" - -/* - * Default values for input and output - * divert socket ports. - */ - -#define DEFAULT_SERVICE "natd" - -/* - * Function prototypes. - */ - -static void DoAliasing (int fd, int direction); -static void DaemonMode (); -static void HandleRoutingInfo (int fd); -static void Usage (); -static char* FormatPacket (struct ip*); -static void PrintPacket (struct ip*); -static void SyslogPacket (struct ip*, int priority, char *label); -static void SetAliasAddressFromIfName (char* ifName); -static void InitiateShutdown (); -static void Shutdown (); -static void RefreshAddr (); -static void ParseOption (char* option, char* parms, int cmdLine); -static void ReadConfigFile (char* fileName); -static void SetupPortRedirect (char* parms); -static void SetupAddressRedirect (char* parms); -static void SetupPptpAlias (char* parms); -static void StrToAddr (char* str, struct in_addr* addr); -static u_short StrToPort (char* str, char* proto); -static int StrToProto (char* str); -static u_short StrToAddrAndPort (char* str, struct in_addr* addr, char* proto); -static void ParseArgs (int argc, char** argv); -static void FlushPacketBuffer (int fd); - -/* - * Globals. - */ - -static int verbose; -static int background; -static int running; -static int assignAliasAddr; -static char* ifName; -static int ifIndex; -static u_short inPort; -static u_short outPort; -static u_short inOutPort; -static struct in_addr aliasAddr; -static int dynamicMode; -static int ifMTU; -static int aliasOverhead; -static int icmpSock; -static char packetBuf[IP_MAXPACKET]; -static int packetLen; -static struct sockaddr_in packetAddr; -static int packetSock; -static int packetDirection; -static int dropIgnoredIncoming; -static int logDropped; -static int logFacility; - -int main (int argc, char** argv) -{ - int divertIn; - int divertOut; - int divertInOut; - int routeSock; - struct sockaddr_in addr; - fd_set readMask; - fd_set writeMask; - int fdMax; -/* - * Initialize packet aliasing software. - * Done already here to be able to alter option bits - * during command line and configuration file processing. - */ - PacketAliasInit (); -/* - * Parse options. - */ - inPort = 0; - outPort = 0; - verbose = 0; - inOutPort = 0; - ifName = NULL; - ifMTU = -1; - background = 0; - running = 1; - assignAliasAddr = 0; - aliasAddr.s_addr = INADDR_NONE; - aliasOverhead = 12; - dynamicMode = 0; - logDropped = 0; - logFacility = LOG_DAEMON; -/* - * Mark packet buffer empty. - */ - packetSock = -1; - packetDirection = DONT_KNOW; - - ParseArgs (argc, argv); -/* - * Open syslog channel. - */ - openlog ("natd", LOG_CONS | LOG_PID, logFacility); -/* - * Check that valid aliasing address has been given. - */ - if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL) - errx (1, "aliasing address not given"); - - if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL) - errx (1, "both alias address and interface " - "name are not allowed"); -/* - * Check that valid port number is known. - */ - if (inPort != 0 || outPort != 0) - if (inPort == 0 || outPort == 0) - errx (1, "both input and output ports are required"); - - if (inPort == 0 && outPort == 0 && inOutPort == 0) - ParseOption ("port", DEFAULT_SERVICE, 0); - -/* - * Check if ignored packets should be dropped. - */ - dropIgnoredIncoming = PacketAliasSetMode (0, 0); - dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING; -/* - * Create divert sockets. Use only one socket if -p was specified - * on command line. Otherwise, create separate sockets for - * outgoing and incoming connnections. - */ - if (inOutPort) { - - divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); - if (divertInOut == -1) - Quit ("Unable to create divert socket."); - - divertIn = -1; - divertOut = -1; -/* - * Bind socket. - */ - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = inOutPort; - - if (bind (divertInOut, - (struct sockaddr*) &addr, - sizeof addr) == -1) - Quit ("Unable to bind divert socket."); - } - else { - - divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); - if (divertIn == -1) - Quit ("Unable to create incoming divert socket."); - - divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); - if (divertOut == -1) - Quit ("Unable to create outgoing divert socket."); - - divertInOut = -1; - -/* - * Bind divert sockets. - */ - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = inPort; - - if (bind (divertIn, - (struct sockaddr*) &addr, - sizeof addr) == -1) - Quit ("Unable to bind incoming divert socket."); - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = outPort; - - if (bind (divertOut, - (struct sockaddr*) &addr, - sizeof addr) == -1) - Quit ("Unable to bind outgoing divert socket."); - } -/* - * Create routing socket if interface name specified. - */ - if (ifName && dynamicMode) { - - routeSock = socket (PF_ROUTE, SOCK_RAW, 0); - if (routeSock == -1) - Quit ("Unable to create routing info socket."); - } - else - routeSock = -1; -/* - * Create socket for sending ICMP messages. - */ - icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); - if (icmpSock == -1) - Quit ("Unable to create ICMP socket."); -/* - * Become a daemon unless verbose mode was requested. - */ - if (!verbose) - DaemonMode (); -/* - * Catch signals to manage shutdown and - * refresh of interface address. - */ - signal (SIGTERM, InitiateShutdown); - signal (SIGHUP, RefreshAddr); -/* - * Set alias address if it has been given. - */ - if (aliasAddr.s_addr != INADDR_NONE) - PacketAliasSetAddress (aliasAddr); -/* - * We need largest descriptor number for select. - */ - - fdMax = -1; - - if (divertIn > fdMax) - fdMax = divertIn; - - if (divertOut > fdMax) - fdMax = divertOut; - - if (divertInOut > fdMax) - fdMax = divertInOut; - - if (routeSock > fdMax) - fdMax = routeSock; - - while (running) { - - if (divertInOut != -1 && !ifName && packetSock == -1) { -/* - * When using only one socket, just call - * DoAliasing repeatedly to process packets. - */ - DoAliasing (divertInOut, DONT_KNOW); - continue; - } -/* - * Build read mask from socket descriptors to select. - */ - FD_ZERO (&readMask); - FD_ZERO (&writeMask); - -/* - * If there is unsent packet in buffer, use select - * to check when socket comes writable again. - */ - if (packetSock != -1) { - - FD_SET (packetSock, &writeMask); - } - else { -/* - * No unsent packet exists - safe to check if - * new ones are available. - */ - if (divertIn != -1) - FD_SET (divertIn, &readMask); - - if (divertOut != -1) - FD_SET (divertOut, &readMask); - - if (divertInOut != -1) - FD_SET (divertInOut, &readMask); - } -/* - * Routing info is processed always. - */ - if (routeSock != -1) - FD_SET (routeSock, &readMask); - - if (select (fdMax + 1, - &readMask, - &writeMask, - NULL, - NULL) == -1) { - - if (errno == EINTR) - continue; - - Quit ("Select failed."); - } - - if (packetSock != -1) - if (FD_ISSET (packetSock, &writeMask)) - FlushPacketBuffer (packetSock); - - if (divertIn != -1) - if (FD_ISSET (divertIn, &readMask)) - DoAliasing (divertIn, INPUT); - - if (divertOut != -1) - if (FD_ISSET (divertOut, &readMask)) - DoAliasing (divertOut, OUTPUT); - - if (divertInOut != -1) - if (FD_ISSET (divertInOut, &readMask)) - DoAliasing (divertInOut, DONT_KNOW); - - if (routeSock != -1) - if (FD_ISSET (routeSock, &readMask)) - HandleRoutingInfo (routeSock); - } - - if (background) - unlink (PIDFILE); - - return 0; -} - -static void DaemonMode () -{ - FILE* pidFile; - - daemon (0, 0); - background = 1; - - pidFile = fopen (PIDFILE, "w"); - if (pidFile) { - - fprintf (pidFile, "%d\n", getpid ()); - fclose (pidFile); - } -} - -static void ParseArgs (int argc, char** argv) -{ - int arg; - char* parm; - char* opt; - char parmBuf[256]; - - for (arg = 1; arg < argc; arg++) { - - opt = argv[arg]; - if (*opt != '-') { - - warnx ("invalid option %s", opt); - Usage (); - } - - parm = NULL; - parmBuf[0] = '\0'; - - while (arg < argc - 1) { - - if (argv[arg + 1][0] == '-') - break; - - if (parm) - strcat (parmBuf, " "); - - ++arg; - parm = parmBuf; - strcat (parmBuf, argv[arg]); - } - - ParseOption (opt + 1, parm, 1); - } -} - -static void DoAliasing (int fd, int direction) -{ - int bytes; - int origBytes; - int status; - int addrSize; - struct ip* ip; - - if (assignAliasAddr) { - - SetAliasAddressFromIfName (ifName); - assignAliasAddr = 0; - } -/* - * Get packet from socket. - */ - addrSize = sizeof packetAddr; - origBytes = recvfrom (fd, - packetBuf, - sizeof packetBuf, - 0, - (struct sockaddr*) &packetAddr, - &addrSize); - - if (origBytes == -1) { - - if (errno != EINTR) - Warn ("read from divert socket failed"); - - return; - } -/* - * This is a IP packet. - */ - ip = (struct ip*) packetBuf; - if (direction == DONT_KNOW) - if (packetAddr.sin_addr.s_addr == INADDR_ANY) - direction = OUTPUT; - else - direction = INPUT; - - if (verbose) { - -/* - * Print packet direction and protocol type. - */ - printf (direction == OUTPUT ? "Out " : "In "); - - switch (ip->ip_p) { - case IPPROTO_TCP: - printf ("[TCP] "); - break; - - case IPPROTO_UDP: - printf ("[UDP] "); - break; - - case IPPROTO_ICMP: - printf ("[ICMP] "); - break; - - default: - printf ("[%d] ", ip->ip_p); - break; - } -/* - * Print addresses. - */ - PrintPacket (ip); - } - - if (direction == OUTPUT) { -/* - * Outgoing packets. Do aliasing. - */ - PacketAliasOut (packetBuf, IP_MAXPACKET); - } - else { - -/* - * Do aliasing. - */ - status = PacketAliasIn (packetBuf, IP_MAXPACKET); - if (status == PKT_ALIAS_IGNORED && - dropIgnoredIncoming) { - - if (verbose) - printf (" dropped.\n"); - - if (logDropped) - SyslogPacket (ip, LOG_WARNING, "denied"); - - return; - } - } -/* - * Length might have changed during aliasing. - */ - bytes = ntohs (ip->ip_len); -/* - * Update alias overhead size for outgoing packets. - */ - if (direction == OUTPUT && - bytes - origBytes > aliasOverhead) - aliasOverhead = bytes - origBytes; - - if (verbose) { - -/* - * Print addresses after aliasing. - */ - printf (" aliased to\n"); - printf (" "); - PrintPacket (ip); - printf ("\n"); - } - - packetLen = bytes; - packetSock = fd; - packetDirection = direction; - - FlushPacketBuffer (fd); -} - -static void FlushPacketBuffer (int fd) -{ - int wrote; - char msgBuf[80]; -/* - * Put packet back for processing. - */ - wrote = sendto (fd, - packetBuf, - packetLen, - 0, - (struct sockaddr*) &packetAddr, - sizeof packetAddr); - - if (wrote != packetLen) { -/* - * If buffer space is not available, - * just return. Main loop will take care of - * retrying send when space becomes available. - */ - if (errno == ENOBUFS) - return; - - if (errno == EMSGSIZE) { - - if (packetDirection == OUTPUT && - ifMTU != -1) - SendNeedFragIcmp (icmpSock, - (struct ip*) packetBuf, - ifMTU - aliasOverhead); - } - else { - - sprintf (msgBuf, "failed to write packet back"); - Warn (msgBuf); - } - } - - packetSock = -1; -} - -static void HandleRoutingInfo (int fd) -{ - int bytes; - struct if_msghdr ifMsg; -/* - * Get packet from socket. - */ - bytes = read (fd, &ifMsg, sizeof ifMsg); - if (bytes == -1) { - - Warn ("read from routing socket failed"); - return; - } - - if (ifMsg.ifm_version != RTM_VERSION) { - - Warn ("unexpected packet read from routing socket"); - return; - } - - if (verbose) - printf ("Routing message %X received.\n", ifMsg.ifm_type); - - if (ifMsg.ifm_type != RTM_NEWADDR) - return; - - if (verbose && ifMsg.ifm_index == ifIndex) - printf ("Interface address has changed.\n"); - - if (ifMsg.ifm_index == ifIndex) - assignAliasAddr = 1; -} - -static void PrintPacket (struct ip* ip) -{ - printf ("%s", FormatPacket (ip)); -} - -static void SyslogPacket (struct ip* ip, int priority, char *label) -{ - syslog (priority, "%s %s", label, FormatPacket (ip)); -} - -static char* FormatPacket (struct ip* ip) -{ - static char buf[256]; - struct tcphdr* tcphdr; - struct udphdr* udphdr; - struct icmp* icmphdr; - char src[20]; - char dst[20]; - - strcpy (src, inet_ntoa (ip->ip_src)); - strcpy (dst, inet_ntoa (ip->ip_dst)); - - switch (ip->ip_p) { - case IPPROTO_TCP: - tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); - sprintf (buf, "[TCP] %s:%d -> %s:%d", - src, - ntohs (tcphdr->th_sport), - dst, - ntohs (tcphdr->th_dport)); - break; - - case IPPROTO_UDP: - udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2)); - sprintf (buf, "[UDP] %s:%d -> %s:%d", - src, - ntohs (udphdr->uh_sport), - dst, - ntohs (udphdr->uh_dport)); - break; - - case IPPROTO_ICMP: - icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2)); - sprintf (buf, "[ICMP] %s -> %s %u(%u)", - src, - dst, - icmphdr->icmp_type, - icmphdr->icmp_code); - break; - - default: - sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst); - break; - } - - return buf; -} - -static void SetAliasAddressFromIfName (char* ifName) -{ - struct ifconf cf; - struct ifreq buf[32]; - char msg[80]; - struct ifreq* ifPtr; - int extra; - int helperSock; - int bytes; - struct sockaddr_in* addr; - int found; - struct ifreq req; - char last[10]; -/* - * Create a dummy socket to access interface information. - */ - helperSock = socket (AF_INET, SOCK_DGRAM, 0); - if (helperSock == -1) { - - Quit ("Failed to create helper socket."); - exit (1); - } - - cf.ifc_len = sizeof (buf); - cf.ifc_req = buf; -/* - * Get interface data. - */ - if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) { - - Quit ("Ioctl SIOCGIFCONF failed."); - exit (1); - } - - ifIndex = 0; - ifPtr = buf; - bytes = cf.ifc_len; - found = 0; - last[0] = '\0'; -/* - * Loop through interfaces until one with - * given name is found. This is done to - * find correct interface index for routing - * message processing. - */ - while (bytes) { - - if (ifPtr->ifr_addr.sa_family == AF_INET && - !strcmp (ifPtr->ifr_name, ifName)) { - - found = 1; - break; - } - - if (strcmp (last, ifPtr->ifr_name)) { - - strcpy (last, ifPtr->ifr_name); - ++ifIndex; - } - - extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr); - - ifPtr++; - ifPtr = (struct ifreq*) ((char*) ifPtr + extra); - bytes -= sizeof (struct ifreq) + extra; - } - - if (!found) { - - close (helperSock); - sprintf (msg, "Unknown interface name %s.\n", ifName); - Quit (msg); - } -/* - * Get MTU size. - */ - strcpy (req.ifr_name, ifName); - - if (ioctl (helperSock, SIOCGIFMTU, &req) == -1) - Quit ("Cannot get interface mtu size."); - - ifMTU = req.ifr_mtu; -/* - * Get interface address. - */ - if (ioctl (helperSock, SIOCGIFADDR, &req) == -1) - Quit ("Cannot get interface address."); - - addr = (struct sockaddr_in*) &req.ifr_addr; - PacketAliasSetAddress (addr->sin_addr); - syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes", - inet_ntoa (addr->sin_addr), - ifMTU); - - close (helperSock); -} - -void Quit (char* msg) -{ - Warn (msg); - exit (1); -} - -void Warn (char* msg) -{ - if (background) - syslog (LOG_ALERT, "%s (%m)", msg); - else - warn (msg); -} - -static void RefreshAddr () -{ - signal (SIGHUP, RefreshAddr); - if (ifName) - assignAliasAddr = 1; -} - -static void InitiateShutdown () -{ -/* - * Start timer to allow kernel gracefully - * shutdown existing connections when system - * is shut down. - */ - signal (SIGALRM, Shutdown); - alarm (10); -} - -static void Shutdown () -{ - running = 0; -} - -/* - * Different options recognized by this program. - */ - -enum Option { - - PacketAliasOption, - Verbose, - InPort, - OutPort, - Port, - AliasAddress, - InterfaceName, - RedirectPort, - RedirectAddress, - ConfigFile, - DynamicMode, - PptpAlias, - ProxyRule, - LogDenied, - LogFacility -}; - -enum Param { - - YesNo, - Numeric, - String, - None, - Address, - Service -}; - -/* - * Option information structure (used by ParseOption). - */ - -struct OptionInfo { - - enum Option type; - int packetAliasOpt; - enum Param parm; - char* parmDescription; - char* description; - char* name; - char* shortName; -}; - -/* - * Table of known options. - */ - -static struct OptionInfo optionTable[] = { - - { PacketAliasOption, - PKT_ALIAS_UNREGISTERED_ONLY, - YesNo, - "[yes|no]", - "alias only unregistered addresses", - "unregistered_only", - "u" }, - - { PacketAliasOption, - PKT_ALIAS_LOG, - YesNo, - "[yes|no]", - "enable logging", - "log", - "l" }, - - { PacketAliasOption, - PKT_ALIAS_PROXY_ONLY, - YesNo, - "[yes|no]", - "proxy only", - "proxy_only", - NULL }, - - { PacketAliasOption, - PKT_ALIAS_REVERSE, - YesNo, - "[yes|no]", - "operate in reverse mode", - "reverse", - NULL }, - - { PacketAliasOption, - PKT_ALIAS_DENY_INCOMING, - YesNo, - "[yes|no]", - "allow incoming connections", - "deny_incoming", - "d" }, - - { PacketAliasOption, - PKT_ALIAS_USE_SOCKETS, - YesNo, - "[yes|no]", - "use sockets to inhibit port conflict", - "use_sockets", - "s" }, - - { PacketAliasOption, - PKT_ALIAS_SAME_PORTS, - YesNo, - "[yes|no]", - "try to keep original port numbers for connections", - "same_ports", - "m" }, - - { Verbose, - 0, - YesNo, - "[yes|no]", - "verbose mode, dump packet information", - "verbose", - "v" }, - - { DynamicMode, - 0, - YesNo, - "[yes|no]", - "dynamic mode, automatically detect interface address changes", - "dynamic", - NULL }, - - { InPort, - 0, - Service, - "number|service_name", - "set port for incoming packets", - "in_port", - "i" }, - - { OutPort, - 0, - Service, - "number|service_name", - "set port for outgoing packets", - "out_port", - "o" }, - - { Port, - 0, - Service, - "number|service_name", - "set port (defaults to natd/divert)", - "port", - "p" }, - - { AliasAddress, - 0, - Address, - "x.x.x.x", - "address to use for aliasing", - "alias_address", - "a" }, - - { InterfaceName, - 0, - String, - "network_if_name", - "take aliasing address from interface", - "interface", - "n" }, - - { ProxyRule, - 0, - String, - "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " - "a.b.c.d:yyyy", - "add transparent proxying / destination NAT", - "proxy_rule", - NULL }, - - { RedirectPort, - 0, - String, - "tcp|udp local_addr:local_port [public_addr:]public_port" - " [remote_addr[:remote_port]]", - "redirect a port for incoming traffic", - "redirect_port", - NULL }, - - { RedirectAddress, - 0, - String, - "local_addr public_addr", - "define mapping between local and public addresses", - "redirect_address", - NULL }, - - { PptpAlias, - 0, - String, - "src", - "define inside machine for PPTP traffic", - "pptpalias", - NULL }, - - { ConfigFile, - 0, - String, - "file_name", - "read options from configuration file", - "config", - "f" }, - - { LogDenied, - 0, - YesNo, - "[yes|no]", - "enable logging of denied incoming packets", - "log_denied", - NULL }, - - { LogFacility, - 0, - String, - "facility", - "name of syslog facility to use for logging", - "log_facility", - NULL } - -}; - -static void ParseOption (char* option, char* parms, int cmdLine) -{ - int i; - struct OptionInfo* info; - int yesNoValue; - int aliasValue; - int numValue; - u_short uNumValue; - char* strValue; - struct in_addr addrValue; - int max; - char* end; - CODE* fac_record = NULL; -/* - * Find option from table. - */ - max = sizeof (optionTable) / sizeof (struct OptionInfo); - for (i = 0, info = optionTable; i < max; i++, info++) { - - if (!strcmp (info->name, option)) - break; - - if (info->shortName) - if (!strcmp (info->shortName, option)) - break; - } - - if (i >= max) { - - warnx ("unknown option %s", option); - Usage (); - } - - uNumValue = 0; - yesNoValue = 0; - numValue = 0; - strValue = NULL; -/* - * Check parameters. - */ - switch (info->parm) { - case YesNo: - if (!parms) - parms = "yes"; - - if (!strcmp (parms, "yes")) - yesNoValue = 1; - else - if (!strcmp (parms, "no")) - yesNoValue = 0; - else - errx (1, "%s needs yes/no parameter", option); - break; - - case Service: - if (!parms) - errx (1, "%s needs service name or " - "port number parameter", - option); - - uNumValue = StrToPort (parms, "divert"); - break; - - case Numeric: - if (parms) - numValue = strtol (parms, &end, 10); - else - end = parms; - - if (end == parms) - errx (1, "%s needs numeric parameter", option); - break; - - case String: - strValue = parms; - if (!strValue) - errx (1, "%s needs parameter", option); - break; - - case None: - if (parms) - errx (1, "%s does not take parameters", option); - break; - - case Address: - if (!parms) - errx (1, "%s needs address/host parameter", option); - - StrToAddr (parms, &addrValue); - break; - } - - switch (info->type) { - case PacketAliasOption: - - aliasValue = yesNoValue ? info->packetAliasOpt : 0; - PacketAliasSetMode (aliasValue, info->packetAliasOpt); - break; - - case Verbose: - verbose = yesNoValue; - break; - - case DynamicMode: - dynamicMode = yesNoValue; - break; - - case InPort: - inPort = uNumValue; - break; - - case OutPort: - outPort = uNumValue; - break; - - case Port: - inOutPort = uNumValue; - break; - - case AliasAddress: - memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); - break; - - case RedirectPort: - SetupPortRedirect (strValue); - break; - - case RedirectAddress: - SetupAddressRedirect (strValue); - break; - - case PptpAlias: - SetupPptpAlias (strValue); - break; - - case ProxyRule: - PacketAliasProxyRule (strValue); - break; - - case InterfaceName: - if (ifName) - free (ifName); - - ifName = strdup (strValue); - assignAliasAddr = 1; - break; - - case ConfigFile: - ReadConfigFile (strValue); - break; - - case LogDenied: - logDropped = 1; - break; - - case LogFacility: - - fac_record = facilitynames; - while (fac_record->c_name != NULL) { - - if (!strcmp (fac_record->c_name, strValue)) { - - logFacility = fac_record->c_val; - break; - - } - else - fac_record++; - } - - if(fac_record->c_name == NULL) - errx(1, "Unknown log facility name: %s", strValue); - - break; - } -} - -void ReadConfigFile (char* fileName) -{ - FILE* file; - char buf[128]; - char* ptr; - char* option; - - file = fopen (fileName, "r"); - if (!file) { - - sprintf (buf, "Cannot open config file %s.\n", fileName); - Quit (buf); - } - - while (fgets (buf, sizeof (buf), file)) { - - ptr = strchr (buf, '\n'); - if (!ptr) - errx (1, "config line too long: %s", buf); - - *ptr = '\0'; - if (buf[0] == '#') - continue; - - ptr = buf; -/* - * Skip white space at beginning of line. - */ - while (*ptr && isspace (*ptr)) - ++ptr; - - if (*ptr == '\0') - continue; -/* - * Extract option name. - */ - option = ptr; - while (*ptr && !isspace (*ptr)) - ++ptr; - - if (*ptr != '\0') { - - *ptr = '\0'; - ++ptr; - } -/* - * Skip white space between name and parms. - */ - while (*ptr && isspace (*ptr)) - ++ptr; - - ParseOption (option, *ptr ? ptr : NULL, 0); - } - - fclose (file); -} - -static void Usage () -{ - int i; - int max; - struct OptionInfo* info; - - fprintf (stderr, "Recognized options:\n\n"); - - max = sizeof (optionTable) / sizeof (struct OptionInfo); - for (i = 0, info = optionTable; i < max; i++, info++) { - - fprintf (stderr, "-%-20s %s\n", info->name, - info->parmDescription); - - if (info->shortName) - fprintf (stderr, "-%-20s %s\n", info->shortName, - info->parmDescription); - - fprintf (stderr, " %s\n\n", info->description); - } - - exit (1); -} - -void SetupPptpAlias (char* parms) -{ - char buf[128]; - char* ptr; - struct in_addr srcAddr; - - strcpy (buf, parms); - -/* - * Extract source address. - */ - ptr = strtok (buf, " \t"); - if (!ptr) - errx(1, "pptpalias: missing src address"); - - StrToAddr (ptr, &srcAddr); - PacketAliasPptp (srcAddr); -} - -void SetupPortRedirect (char* parms) -{ - char buf[128]; - char* ptr; - struct in_addr localAddr; - struct in_addr publicAddr; - struct in_addr remoteAddr; - u_short localPort; - u_short publicPort; - u_short remotePort; - int proto; - char* protoName; - char* separator; - - strcpy (buf, parms); -/* - * Extract protocol. - */ - protoName = strtok (buf, " \t"); - if (!protoName) - errx (1, "redirect_port: missing protocol"); - - proto = StrToProto (protoName); -/* - * Extract local address. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "redirect_port: missing local address"); - - localPort = StrToAddrAndPort (ptr, &localAddr, protoName); -/* - * Extract public port and optinally address. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "redirect_port: missing public port"); - - separator = strchr (ptr, ':'); - if (separator) - publicPort = StrToAddrAndPort (ptr, &publicAddr, protoName); - else { - - publicAddr.s_addr = INADDR_ANY; - publicPort = StrToPort (ptr, protoName); - } - -/* - * Extract remote address and optionally port. - */ - ptr = strtok (NULL, " \t"); - if (ptr) { - - - separator = strchr (ptr, ':'); - if (separator) - remotePort = StrToAddrAndPort (ptr, - &remoteAddr, - protoName); - else { - - remotePort = 0; - StrToAddr (ptr, &remoteAddr); - } - } - else { - - remotePort = 0; - remoteAddr.s_addr = INADDR_ANY; - } - - PacketAliasRedirectPort (localAddr, - localPort, - remoteAddr, - remotePort, - publicAddr, - publicPort, - proto); -} - -void SetupAddressRedirect (char* parms) -{ - char buf[128]; - char* ptr; - struct in_addr localAddr; - struct in_addr publicAddr; - - strcpy (buf, parms); -/* - * Extract local address. - */ - ptr = strtok (buf, " \t"); - if (!ptr) - errx (1, "redirect_address: missing local address"); - - StrToAddr (ptr, &localAddr); -/* - * Extract public address. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "redirect_address: missing public address"); - - StrToAddr (ptr, &publicAddr); - PacketAliasRedirectAddr (localAddr, publicAddr); -} - -void StrToAddr (char* str, struct in_addr* addr) -{ - struct hostent* hp; - - if (inet_aton (str, addr)) - return; - - hp = gethostbyname (str); - if (!hp) - errx (1, "unknown host %s", str); - - memcpy (addr, hp->h_addr, sizeof (struct in_addr)); -} - -u_short StrToPort (char* str, char* proto) -{ - u_short port; - struct servent* sp; - char* end; - - port = strtol (str, &end, 10); - if (end != str) - return htons (port); - - sp = getservbyname (str, proto); - if (!sp) - errx (1, "unknown service %s/%s", str, proto); - - return sp->s_port; -} - -int StrToProto (char* str) -{ - if (!strcmp (str, "tcp")) - return IPPROTO_TCP; - - if (!strcmp (str, "udp")) - return IPPROTO_UDP; - - errx (1, "unknown protocol %s. Expected tcp or udp", str); -} - -u_short StrToAddrAndPort (char* str, struct in_addr* addr, char* proto) -{ - char* ptr; - - ptr = strchr (str, ':'); - if (!ptr) - errx (1, "%s is missing port number", str); - - *ptr = '\0'; - ++ptr; - - StrToAddr (str, addr); - return StrToPort (ptr, proto); -} - |