Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Jan 2009 12:01:30 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r187770 - head/sbin/ipfw
Message-ID:  <200901271201.n0RC1Us3085751@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Tue Jan 27 12:01:30 2009
New Revision: 187770
URL: http://svn.freebsd.org/changeset/base/187770

Log:
  Put nat and ipv6 support in their own files.
  
  Usual moving of code with no changes from ipfw2.c to the
  newly created files, and addition of prototypes to ipfw2.h
  
  I have added forward declarations for ipfw_insn_* in ipfw2.h
  to avoid a global dependency on ip_fw.h

Added:
  head/sbin/ipfw/ipv6.c   (contents, props changed)
  head/sbin/ipfw/nat.c   (contents, props changed)
Modified:
  head/sbin/ipfw/Makefile
  head/sbin/ipfw/ipfw2.c
  head/sbin/ipfw/ipfw2.h

Modified: head/sbin/ipfw/Makefile
==============================================================================
--- head/sbin/ipfw/Makefile	Tue Jan 27 11:06:59 2009	(r187769)
+++ head/sbin/ipfw/Makefile	Tue Jan 27 12:01:30 2009	(r187770)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PROG=	ipfw
-SRCS=	ipfw2.c dummynet.c main.c
+SRCS=	ipfw2.c dummynet.c ipv6.c main.c nat.c
 WARNS?=	0
 MAN=	ipfw.8
 

Modified: head/sbin/ipfw/ipfw2.c
==============================================================================
--- head/sbin/ipfw/ipfw2.c	Tue Jan 27 11:06:59 2009	(r187769)
+++ head/sbin/ipfw/ipfw2.c	Tue Jan 27 12:01:30 2009	(r187770)
@@ -52,11 +52,9 @@
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
-#include <netinet/icmp6.h>
 #include <netinet/ip_fw.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
-#include <alias.h>
 
 struct cmdline_opts co;	/* global options */
 
@@ -192,22 +190,6 @@ static struct _s_x ether_types[] = {
 };
 
 
-static struct _s_x nat_params[] = {
-	{ "ip",	                TOK_IP },
-	{ "if",	                TOK_IF },
- 	{ "log",                TOK_ALOG },
- 	{ "deny_in",	        TOK_DENY_INC },
- 	{ "same_ports",	        TOK_SAME_PORTS },
- 	{ "unreg_only",	        TOK_UNREG_ONLY },
- 	{ "reset",	        TOK_RESET_ADDR },
- 	{ "reverse",	        TOK_ALIAS_REV },	
- 	{ "proxy_only",	        TOK_PROXY_ONLY },
-	{ "redirect_addr",	TOK_REDIR_ADDR },
-	{ "redirect_port",	TOK_REDIR_PORT },
-	{ "redirect_proto",	TOK_REDIR_PROTO },
- 	{ NULL, 0 }	/* terminator */
-};
-
 static struct _s_x rule_actions[] = {
 	{ "accept",		TOK_ACCEPT },
 	{ "pass",		TOK_ACCEPT },
@@ -401,7 +383,7 @@ match_token(struct _s_x *table, char *st
  * match_value takes a table and a value, returns the string associated
  * with the value (NULL in case of failure).
  */
-static char const *
+char const *
 match_value(struct _s_x *p, int value)
 {
 	for (; p->s != NULL; p++)
@@ -786,40 +768,6 @@ print_reject_code(uint16_t code)
 		printf("unreach %u", code);
 }
 
-static struct _s_x icmp6codes[] = {
-      { "no-route",		ICMP6_DST_UNREACH_NOROUTE },
-      { "admin-prohib",		ICMP6_DST_UNREACH_ADMIN },
-      { "address",		ICMP6_DST_UNREACH_ADDR },
-      { "port",			ICMP6_DST_UNREACH_NOPORT },
-      { NULL, 0 }
-};
-
-static void
-fill_unreach6_code(u_short *codep, char *str)
-{
-	int val;
-	char *s;
-
-	val = strtoul(str, &s, 0);
-	if (s == str || *s != '\0' || val >= 0x100)
-		val = match_token(icmp6codes, str);
-	if (val < 0)
-		errx(EX_DATAERR, "unknown ICMPv6 unreachable code ``%s''", str);
-	*codep = val;
-	return;
-}
-
-static void
-print_unreach6_code(uint16_t code)
-{
-	char const *s = match_value(icmp6codes, code);
-
-	if (s != NULL)
-		printf("unreach6 %s", s);
-	else
-		printf("unreach6 %u", code);
-}
-
 /*
  * Returns the number of bits set (from left) in a contiguous bitmask,
  * or -1 if the mask is not contiguous.
@@ -831,7 +779,7 @@ print_unreach6_code(uint16_t code)
  * the first bit on the wire is bit 0 of the first byte.
  * len is the max length in bits.
  */
-static int
+int
 contigmask(uint8_t *p, int len)
 {
 	int i, n;
@@ -1022,226 +970,6 @@ print_icmptypes(ipfw_insn_u32 *cmd)
 	}
 }
 
-/* 
- * Print the ip address contained in a command.
- */
-static void
-print_ip6(ipfw_insn_ip6 *cmd, char const *s)
-{
-       struct hostent *he = NULL;
-       int len = F_LEN((ipfw_insn *) cmd) - 1;
-       struct in6_addr *a = &(cmd->addr6);
-       char trad[255];
-
-       printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s);
-
-       if (cmd->o.opcode == O_IP6_SRC_ME || cmd->o.opcode == O_IP6_DST_ME) {
-               printf("me6");
-               return;
-       }
-       if (cmd->o.opcode == O_IP6) {
-               printf(" ip6");
-               return;
-       }
-
-       /*
-        * len == 4 indicates a single IP, whereas lists of 1 or more
-        * addr/mask pairs have len = (2n+1). We convert len to n so we
-        * use that to count the number of entries.
-        */
-
-       for (len = len / 4; len > 0; len -= 2, a += 2) {
-           int mb =        /* mask length */
-               (cmd->o.opcode == O_IP6_SRC || cmd->o.opcode == O_IP6_DST) ?
-               128 : contigmask((uint8_t *)&(a[1]), 128);
-
-           if (mb == 128 && co.do_resolv)
-               he = gethostbyaddr((char *)a, sizeof(*a), AF_INET6);
-           if (he != NULL)             /* resolved to name */
-               printf("%s", he->h_name);
-           else if (mb == 0)           /* any */
-               printf("any");
-           else {          /* numeric IP followed by some kind of mask */
-               if (inet_ntop(AF_INET6,  a, trad, sizeof( trad ) ) == NULL)
-                   printf("Error ntop in print_ip6\n");
-               printf("%s",  trad );
-               if (mb < 0)     /* XXX not really legal... */
-                   printf(":%s",
-                       inet_ntop(AF_INET6, &a[1], trad, sizeof(trad)));
-               else if (mb < 128)
-                   printf("/%d", mb);
-           }
-           if (len > 2)
-               printf(",");
-       }
-}
-
-static void
-fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av)
-{
-       uint8_t type;
-
-       bzero(cmd, sizeof(*cmd));
-       while (*av) {
-           if (*av == ',')
-               av++;
-           type = strtoul(av, &av, 0);
-           if (*av != ',' && *av != '\0')
-               errx(EX_DATAERR, "invalid ICMP6 type");
-	   /*
-	    * XXX: shouldn't this be 0xFF?  I can't see any reason why
-	    * we shouldn't be able to filter all possiable values
-	    * regardless of the ability of the rest of the kernel to do
-	    * anything useful with them.
-	    */
-           if (type > ICMP6_MAXTYPE)
-               errx(EX_DATAERR, "ICMP6 type out of range");
-           cmd->d[type / 32] |= ( 1 << (type % 32));
-       }
-       cmd->o.opcode = O_ICMP6TYPE;
-       cmd->o.len |= F_INSN_SIZE(ipfw_insn_icmp6);
-}
-
-
-static void
-print_icmp6types(ipfw_insn_u32 *cmd)
-{
-       int i, j;
-       char sep= ' ';
-
-       printf(" ip6 icmp6types");
-       for (i = 0; i < 7; i++)
-               for (j=0; j < 32; ++j) {
-                       if ( (cmd->d[i] & (1 << (j))) == 0)
-                               continue;
-                       printf("%c%d", sep, (i*32 + j));
-                       sep = ',';
-               }
-}
-
-static void
-print_flow6id( ipfw_insn_u32 *cmd)
-{
-       uint16_t i, limit = cmd->o.arg1;
-       char sep = ',';
-
-       printf(" flow-id ");
-       for( i=0; i < limit; ++i) {
-               if (i == limit - 1)
-                       sep = ' ';
-               printf("%d%c", cmd->d[i], sep);
-       }
-}
-
-/* structure and define for the extension header in ipv6 */
-static struct _s_x ext6hdrcodes[] = {
-       { "frag",       EXT_FRAGMENT },
-       { "hopopt",     EXT_HOPOPTS },
-       { "route",      EXT_ROUTING },
-       { "dstopt",     EXT_DSTOPTS },
-       { "ah",         EXT_AH },
-       { "esp",        EXT_ESP },
-       { "rthdr0",     EXT_RTHDR0 },
-       { "rthdr2",     EXT_RTHDR2 },
-       { NULL,         0 }
-};
-
-/* fills command for the extension header filtering */
-static int
-fill_ext6hdr( ipfw_insn *cmd, char *av)
-{
-       int tok;
-       char *s = av;
-
-       cmd->arg1 = 0;
-
-       while(s) {
-           av = strsep( &s, ",") ;
-           tok = match_token(ext6hdrcodes, av);
-           switch (tok) {
-           case EXT_FRAGMENT:
-               cmd->arg1 |= EXT_FRAGMENT;
-               break;
-
-           case EXT_HOPOPTS:
-               cmd->arg1 |= EXT_HOPOPTS;
-               break;
-
-           case EXT_ROUTING:
-               cmd->arg1 |= EXT_ROUTING;
-               break;
-
-           case EXT_DSTOPTS:
-               cmd->arg1 |= EXT_DSTOPTS;
-               break;
-
-           case EXT_AH:
-               cmd->arg1 |= EXT_AH;
-               break;
-
-           case EXT_ESP:
-               cmd->arg1 |= EXT_ESP;
-               break;
-
-           case EXT_RTHDR0:
-               cmd->arg1 |= EXT_RTHDR0;
-               break;
-
-           case EXT_RTHDR2:
-               cmd->arg1 |= EXT_RTHDR2;
-               break;
-
-           default:
-               errx( EX_DATAERR, "invalid option for ipv6 exten header" );
-               break;
-           }
-       }
-       if (cmd->arg1 == 0 )
-           return 0;
-       cmd->opcode = O_EXT_HDR;
-       cmd->len |= F_INSN_SIZE( ipfw_insn );
-       return 1;
-}
-
-static void
-print_ext6hdr( ipfw_insn *cmd )
-{
-       char sep = ' ';
-
-       printf(" extension header:");
-       if (cmd->arg1 & EXT_FRAGMENT ) {
-           printf("%cfragmentation", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_HOPOPTS ) {
-           printf("%chop options", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_ROUTING ) {
-           printf("%crouting options", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_RTHDR0 ) {
-           printf("%crthdr0", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_RTHDR2 ) {
-           printf("%crthdr2", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_DSTOPTS ) {
-           printf("%cdestination options", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_AH ) {
-           printf("%cauthentication header", sep);
-           sep = ',';
-       }
-       if (cmd->arg1 & EXT_ESP ) {
-           printf("%cencapsulated security payload", sep);
-       }
-}
-
 /*
  * show_ipfw() prints the body of an ipfw rule.
  * Because the standard rule has at least proto src_ip dst_ip, we use
@@ -2490,21 +2218,6 @@ fill_ip(ipfw_insn_ip *cmd, char *av)
 }
 
 
-/* Try to find ipv6 address by hostname */
-static int
-lookup_host6 (char *host, struct in6_addr *ip6addr)
-{
-	struct hostent *he;
-
-	if (!inet_pton(AF_INET6, host, ip6addr)) {
-		if ((he = gethostbyname2(host, AF_INET6)) == NULL)
-			return(-1);
-		memcpy(ip6addr, he->h_addr_list[0], sizeof( struct in6_addr));
-	}
-	return(0);
-}
-
-
 /* n2mask sets n bits of the mask */
 void
 n2mask(struct in6_addr *mask, int n)
@@ -2526,196 +2239,6 @@ n2mask(struct in6_addr *mask, int n)
  
 
 /*
- * fill the addr and mask fields in the instruction as appropriate from av.
- * Update length as appropriate.
- * The following formats are allowed:
- *     any     matches any IP6. Actually returns an empty instruction.
- *     me      returns O_IP6_*_ME
- *
- *     03f1::234:123:0342                single IP6 addres
- *     03f1::234:123:0342/24            address/mask
- *     03f1::234:123:0342/24,03f1::234:123:0343/               List of address
- *
- * Set of address (as in ipv6) not supported because ipv6 address
- * are typically random past the initial prefix.
- * Return 1 on success, 0 on failure.
- */
-static int
-fill_ip6(ipfw_insn_ip6 *cmd, char *av)
-{
-	int len = 0;
-	struct in6_addr *d = &(cmd->addr6);
-	/*
-	 * Needed for multiple address.
-	 * Note d[1] points to struct in6_add r mask6 of cmd
-	 */
-
-       cmd->o.len &= ~F_LEN_MASK;	/* zero len */
-
-       if (strcmp(av, "any") == 0)
-	       return (1);
-
-
-       if (strcmp(av, "me") == 0) {	/* Set the data for "me" opt*/
-	       cmd->o.len |= F_INSN_SIZE(ipfw_insn);
-	       return (1);
-       }
-
-       if (strcmp(av, "me6") == 0) {	/* Set the data for "me" opt*/
-	       cmd->o.len |= F_INSN_SIZE(ipfw_insn);
-	       return (1);
-       }
-
-       av = strdup(av);
-       while (av) {
-		/*
-		 * After the address we can have '/' indicating a mask,
-		 * or ',' indicating another address follows.
-		 */
-
-		char *p;
-		int masklen;
-		char md = '\0';
-
-		if ((p = strpbrk(av, "/,")) ) {
-			md = *p;	/* save the separator */
-			*p = '\0';	/* terminate address string */
-			p++;		/* and skip past it */
-		}
-		/* now p points to NULL, mask or next entry */
-
-		/* lookup stores address in *d as a side effect */
-		if (lookup_host6(av, d) != 0) {
-			/* XXX: failed. Free memory and go */
-			errx(EX_DATAERR, "bad address \"%s\"", av);
-		}
-		/* next, look at the mask, if any */
-		masklen = (md == '/') ? atoi(p) : 128;
-		if (masklen > 128 || masklen < 0)
-			errx(EX_DATAERR, "bad width \"%s\''", p);
-		else
-			n2mask(&d[1], masklen);
-
-		APPLY_MASK(d, &d[1])   /* mask base address with mask */
-
-		/* find next separator */
-
-		if (md == '/') {	/* find separator past the mask */
-			p = strpbrk(p, ",");
-			if (p != NULL)
-				p++;
-		}
-		av = p;
-
-		/* Check this entry */
-		if (masklen == 0) {
-			/*
-			 * 'any' turns the entire list into a NOP.
-			 * 'not any' never matches, so it is removed from the
-			 * list unless it is the only item, in which case we
-			 * report an error.
-			 */
-			if (cmd->o.len & F_NOT && av == NULL && len == 0)
-				errx(EX_DATAERR, "not any never matches");
-			continue;
-		}
-
-		/*
-		 * A single IP can be stored alone
-		 */
-		if (masklen == 128 && av == NULL && len == 0) {
-			len = F_INSN_SIZE(struct in6_addr);
-			break;
-		}
-
-		/* Update length and pointer to arguments */
-		len += F_INSN_SIZE(struct in6_addr)*2;
-		d += 2;
-	} /* end while */
-
-	/*
-	 * Total length of the command, remember that 1 is the size of
-	 * the base command.
-	 */
-	if (len + 1 > F_LEN_MASK)
-		errx(EX_DATAERR, "address list too long");
-	cmd->o.len |= len+1;
-	free(av);
-	return (1);
-}
-
-/*
- * fills command for ipv6 flow-id filtering
- * note that the 20 bit flow number is stored in a array of u_int32_t
- * it's supported lists of flow-id, so in the o.arg1 we store how many
- * additional flow-id we want to filter, the basic is 1
- */
-static void
-fill_flow6( ipfw_insn_u32 *cmd, char *av )
-{
-	u_int32_t type;	 /* Current flow number */
-	u_int16_t nflow = 0;    /* Current flow index */
-	char *s = av;
-	cmd->d[0] = 0;	  /* Initializing the base number*/
-
-	while (s) {
-		av = strsep( &s, ",") ;
-		type = strtoul(av, &av, 0);
-		if (*av != ',' && *av != '\0')
-			errx(EX_DATAERR, "invalid ipv6 flow number %s", av);
-		if (type > 0xfffff)
-			errx(EX_DATAERR, "flow number out of range %s", av);
-		cmd->d[nflow] |= type;
-		nflow++;
-	}
-	if( nflow > 0 ) {
-		cmd->o.opcode = O_FLOW6ID;
-		cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + nflow;
-		cmd->o.arg1 = nflow;
-	}
-	else {
-		errx(EX_DATAERR, "invalid ipv6 flow number %s", av);
-	}
-}
-
-static ipfw_insn *
-add_srcip6(ipfw_insn *cmd, char *av)
-{
-
-	fill_ip6((ipfw_insn_ip6 *)cmd, av);
-	if (F_LEN(cmd) == 0) {				/* any */
-	} else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) {	/* "me" */
-		cmd->opcode = O_IP6_SRC_ME;
-	} else if (F_LEN(cmd) ==
-	    (F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn))) {
-		/* single IP, no mask*/
-		cmd->opcode = O_IP6_SRC;
-	} else {					/* addr/mask opt */
-		cmd->opcode = O_IP6_SRC_MASK;
-	}
-	return cmd;
-}
-
-static ipfw_insn *
-add_dstip6(ipfw_insn *cmd, char *av)
-{
-
-	fill_ip6((ipfw_insn_ip6 *)cmd, av);
-	if (F_LEN(cmd) == 0) {				/* any */
-	} else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn)) {	/* "me" */
-		cmd->opcode = O_IP6_DST_ME;
-	} else if (F_LEN(cmd) ==
-	    (F_INSN_SIZE(struct in6_addr) + F_INSN_SIZE(ipfw_insn))) {
-		/* single IP, no mask*/
-		cmd->opcode = O_IP6_DST;
-	} else {					/* addr/mask opt */
-		cmd->opcode = O_IP6_DST_MASK;
-	}
-	return cmd;
-}
-
-
-/*
  * helper function to process a set of flags and set bits in the
  * appropriate masks.
  */
@@ -2824,769 +2347,6 @@ fill_iface(ipfw_insn_if *cmd, char *arg)
 		errx(EX_DATAERR, "bad ip address ``%s''", arg);
 }
 
-/* 
- * Search for interface with name "ifn", and fill n accordingly:
- *
- * n->ip        ip address of interface "ifn"
- * n->if_name   copy of interface name "ifn"
- */
-static void
-set_addr_dynamic(const char *ifn, struct cfg_nat *n)
-{
-	size_t needed;
-	int mib[6];
-	char *buf, *lim, *next;
-	struct if_msghdr *ifm;
-	struct ifa_msghdr *ifam;
-	struct sockaddr_dl *sdl;
-	struct sockaddr_in *sin;
-	int ifIndex, ifMTU;
-
-	mib[0] = CTL_NET;
-	mib[1] = PF_ROUTE;
-	mib[2] = 0;
-	mib[3] = AF_INET;	
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = 0;		
-/*
- * Get interface data.
- */
-	if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
-		err(1, "iflist-sysctl-estimate");
-	buf = safe_calloc(1, needed);
-	if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
-		err(1, "iflist-sysctl-get");
-	lim = buf + needed;
-/*
- * Loop through interfaces until one with
- * given name is found. This is done to
- * find correct interface index for routing
- * message processing.
- */
-	ifIndex	= 0;
-	next = buf;
-	while (next < lim) {
-		ifm = (struct if_msghdr *)next;
-		next += ifm->ifm_msglen;
-		if (ifm->ifm_version != RTM_VERSION) {
-			if (co.verbose)
-				warnx("routing message version %d "
-				    "not understood", ifm->ifm_version);
-			continue;
-		}
-		if (ifm->ifm_type == RTM_IFINFO) {
-			sdl = (struct sockaddr_dl *)(ifm + 1);
-			if (strlen(ifn) == sdl->sdl_nlen &&
-			    strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
-				ifIndex = ifm->ifm_index;
-				ifMTU = ifm->ifm_data.ifi_mtu;
-				break;
-			}
-		}
-	}
-	if (!ifIndex)
-		errx(1, "unknown interface name %s", ifn);
-/*
- * Get interface address.
- */
-	sin = NULL;
-	while (next < lim) {
-		ifam = (struct ifa_msghdr *)next;
-		next += ifam->ifam_msglen;
-		if (ifam->ifam_version != RTM_VERSION) {
-			if (co.verbose)
-				warnx("routing message version %d "
-				    "not understood", ifam->ifam_version);
-			continue;
-		}
-		if (ifam->ifam_type != RTM_NEWADDR)
-			break;
-		if (ifam->ifam_addrs & RTA_IFA) {
-			int i;
-			char *cp = (char *)(ifam + 1);
-
-			for (i = 1; i < RTA_IFA; i <<= 1) {
-				if (ifam->ifam_addrs & i)
-					cp += SA_SIZE((struct sockaddr *)cp);
-			}
-			if (((struct sockaddr *)cp)->sa_family == AF_INET) {
-				sin = (struct sockaddr_in *)cp;
-				break;
-			}
-		}
-	}
-	if (sin == NULL)
-		errx(1, "%s: cannot get interface address", ifn);
-
-	n->ip = sin->sin_addr;
-	strncpy(n->if_name, ifn, IF_NAMESIZE);
-
-	free(buf);
-}
-
-/* 
- * XXX - The following functions, macros and definitions come from natd.c:
- * it would be better to move them outside natd.c, in a file 
- * (redirect_support.[ch]?) shared by ipfw and natd, but for now i can live 
- * with it.
- */
-
-/*
- * Definition of a port range, and macros to deal with values.
- * FORMAT:  HI 16-bits == first port in range, 0 == all ports.
- *          LO 16-bits == number of ports in range
- * NOTES:   - Port values are not stored in network byte order.
- */
-
-#define port_range u_long
-
-#define GETLOPORT(x)     ((x) >> 0x10)
-#define GETNUMPORTS(x)   ((x) & 0x0000ffff)
-#define GETHIPORT(x)     (GETLOPORT((x)) + GETNUMPORTS((x)))
-
-/* Set y to be the low-port value in port_range variable x. */
-#define SETLOPORT(x,y)   ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
-
-/* Set y to be the number of ports in port_range variable x. */
-#define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
-
-static void 
-StrToAddr (const 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));
-}
-
-static int 
-StrToPortRange (const char* str, const char* proto, port_range *portRange)
-{
-	char*           sep;
-	struct servent*	sp;
-	char*		end;
-	u_short         loPort;
-	u_short         hiPort;
-	
-	/* First see if this is a service, return corresponding port if so. */
-	sp = getservbyname (str,proto);
-	if (sp) {
-	        SETLOPORT(*portRange, ntohs(sp->s_port));
-		SETNUMPORTS(*portRange, 1);
-		return 0;
-	}
-	        
-	/* Not a service, see if it's a single port or port range. */
-	sep = strchr (str, '-');
-	if (sep == NULL) {
-	        SETLOPORT(*portRange, strtol(str, &end, 10));
-		if (end != str) {
-		        /* Single port. */
-		        SETNUMPORTS(*portRange, 1);
-			return 0;
-		}
-
-		/* Error in port range field. */
-		errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
-	}
-
-	/* Port range, get the values and sanity check. */
-	sscanf (str, "%hu-%hu", &loPort, &hiPort);
-	SETLOPORT(*portRange, loPort);
-	SETNUMPORTS(*portRange, 0);	/* Error by default */
-	if (loPort <= hiPort)
-	        SETNUMPORTS(*portRange, hiPort - loPort + 1);
-
-	if (GETNUMPORTS(*portRange) == 0)
-	        errx (EX_DATAERR, "invalid port range %s", str);
-
-	return 0;
-}
-
-static int 
-StrToProto (const char* str)
-{
-	if (!strcmp (str, "tcp"))
-		return IPPROTO_TCP;
-
-	if (!strcmp (str, "udp"))
-		return IPPROTO_UDP;
-
-	errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
-}
-
-static int 
-StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, 
-		       port_range *portRange)
-{
-	char*	ptr;
-
-	ptr = strchr (str, ':');
-	if (!ptr)
-		errx (EX_DATAERR, "%s is missing port number", str);
-
-	*ptr = '\0';
-	++ptr;
-
-	StrToAddr (str, addr);
-	return StrToPortRange (ptr, proto, portRange);
-}
-
-/* End of stuff taken from natd.c. */
-
-#define INC_ARGCV() do {        \
-	(*_av)++;               \
-	(*_ac)--;               \
-	av = *_av;              \
-	ac = *_ac;              \
-} while(0)
-
-/* 
- * The next 3 functions add support for the addr, port and proto redirect and 
- * their logic is loosely based on SetupAddressRedirect(), SetupPortRedirect() 
- * and SetupProtoRedirect() from natd.c.
- *
- * Every setup_* function fills at least one redirect entry 
- * (struct cfg_redir) and zero or more server pool entry (struct cfg_spool) 
- * in buf.
- * 
- * The format of data in buf is:
- * 
- *
- *     cfg_nat    cfg_redir    cfg_spool    ......  cfg_spool 
- *
- *    -------------------------------------        ------------
- *   |          | .....X ... |          |         |           |  .....
- *    ------------------------------------- ...... ------------
- *                     ^          
- *                spool_cnt       n=0       ......   n=(X-1)
- *
- * len points to the amount of available space in buf
- * space counts the memory consumed by every function
- *
- * XXX - Every function get all the argv params so it 
- * has to check, in optional parameters, that the next
- * args is a valid option for the redir entry and not 
- * another token. Only redir_port and redir_proto are 
- * affected by this.
- */
-
-static int
-setup_redir_addr(char *spool_buf, int len,
-		 int *_ac, char ***_av) 
-{
-	char **av, *sep; /* Token separator. */
-	/* Temporary buffer used to hold server pool ip's. */
-	char tmp_spool_buf[NAT_BUF_LEN]; 
-	int ac, space, lsnat;
-	struct cfg_redir *r;	
-	struct cfg_spool *tmp;		
-
-	av = *_av;
-	ac = *_ac;
-	space = 0;
-	lsnat = 0;
-	if (len >= SOF_REDIR) {
-		r = (struct cfg_redir *)spool_buf;
-		/* Skip cfg_redir at beginning of buf. */
-		spool_buf = &spool_buf[SOF_REDIR];
-		space = SOF_REDIR;
-		len -= SOF_REDIR;
-	} else 
-		goto nospace; 
-	r->mode = REDIR_ADDR;
-	/* Extract local address. */
-	if (ac == 0) 
-		errx(EX_DATAERR, "redirect_addr: missing local address");
-	sep = strchr(*av, ',');
-	if (sep) {		/* LSNAT redirection syntax. */
-		r->laddr.s_addr = INADDR_NONE;
-		/* Preserve av, copy spool servers to tmp_spool_buf. */
-		strncpy(tmp_spool_buf, *av, strlen(*av)+1);
-		lsnat = 1;
-	} else 
-		StrToAddr(*av, &r->laddr);		
-	INC_ARGCV();
-
-	/* Extract public address. */
-	if (ac == 0) 
-		errx(EX_DATAERR, "redirect_addr: missing public address");
-	StrToAddr(*av, &r->paddr);
-	INC_ARGCV();
-
-	/* Setup LSNAT server pool. */
-	if (sep) {
-		sep = strtok(tmp_spool_buf, ",");		
-		while (sep != NULL) {
-			tmp = (struct cfg_spool *)spool_buf;		
-			if (len < SOF_SPOOL)
-				goto nospace;
-			len -= SOF_SPOOL;
-			space += SOF_SPOOL;			
-			StrToAddr(sep, &tmp->addr);
-			tmp->port = ~0;
-			r->spool_cnt++;
-			/* Point to the next possible cfg_spool. */
-			spool_buf = &spool_buf[SOF_SPOOL];
-			sep = strtok(NULL, ",");
-		}
-	}
-	return(space);
-nospace:
-	errx(EX_DATAERR, "redirect_addr: buf is too small\n");
-}
-
-static int
-setup_redir_port(char *spool_buf, int len,
-		 int *_ac, char ***_av) 
-{
-	char **av, *sep, *protoName;
-	char tmp_spool_buf[NAT_BUF_LEN];
-	int ac, space, lsnat;
-	struct cfg_redir *r;
-	struct cfg_spool *tmp;
-	u_short numLocalPorts;
-	port_range portRange;	
-
-	av = *_av;
-	ac = *_ac;
-	space = 0;
-	lsnat = 0;
-	numLocalPorts = 0;	
-
-	if (len >= SOF_REDIR) {
-		r = (struct cfg_redir *)spool_buf;
-		/* Skip cfg_redir at beginning of buf. */
-		spool_buf = &spool_buf[SOF_REDIR];
-		space = SOF_REDIR;
-		len -= SOF_REDIR;
-	} else 
-		goto nospace; 
-	r->mode = REDIR_PORT;
-	/*
-	 * Extract protocol.
-	 */
-	if (ac == 0)
-		errx (EX_DATAERR, "redirect_port: missing protocol");
-	r->proto = StrToProto(*av);
-	protoName = *av;	
-	INC_ARGCV();
-
-	/*
-	 * Extract local address.
-	 */
-	if (ac == 0)
-		errx (EX_DATAERR, "redirect_port: missing local address");
-
-	sep = strchr(*av, ',');
-	/* LSNAT redirection syntax. */
-	if (sep) {
-		r->laddr.s_addr = INADDR_NONE;
-		r->lport = ~0;
-		numLocalPorts = 1;
-		/* Preserve av, copy spool servers to tmp_spool_buf. */
-		strncpy(tmp_spool_buf, *av, strlen(*av)+1);
-		lsnat = 1;
-	} else {
-		if (StrToAddrAndPortRange (*av, &r->laddr, protoName, 
-		    &portRange) != 0)
-			errx(EX_DATAERR, "redirect_port:"
-			    "invalid local port range");
-
-		r->lport = GETLOPORT(portRange);
-		numLocalPorts = GETNUMPORTS(portRange);
-	}
-	INC_ARGCV();	
-
-	/*
-	 * Extract public port and optionally address.
-	 */
-	if (ac == 0)
-		errx (EX_DATAERR, "redirect_port: missing public port");
-
-	sep = strchr (*av, ':');
-	if (sep) {
-	        if (StrToAddrAndPortRange (*av, &r->paddr, protoName, 
-		    &portRange) != 0)
-		        errx(EX_DATAERR, "redirect_port:" 
-			    "invalid public port range");
-	} else {
-		r->paddr.s_addr = INADDR_ANY;
-		if (StrToPortRange (*av, protoName, &portRange) != 0)
-		        errx(EX_DATAERR, "redirect_port:"
-			    "invalid public port range");
-	}
-
-	r->pport = GETLOPORT(portRange);
-	r->pport_cnt = GETNUMPORTS(portRange);
-	INC_ARGCV();
-
-	/*
-	 * Extract remote address and optionally port.
-	 */	
-	/* 
-	 * NB: isalpha(**av) => we've to check that next parameter is really an
-	 * option for this redirect entry, else stop here processing arg[cv].
-	 */
-	if (ac != 0 && !isalpha(**av)) { 
-		sep = strchr (*av, ':');
-		if (sep) {
-		        if (StrToAddrAndPortRange (*av, &r->raddr, protoName, 
-			    &portRange) != 0)
-				errx(EX_DATAERR, "redirect_port:"
-				    "invalid remote port range");
-		} else {
-		        SETLOPORT(portRange, 0);
-			SETNUMPORTS(portRange, 1);
-			StrToAddr (*av, &r->raddr);
-		}
-		INC_ARGCV();
-	} else {
-		SETLOPORT(portRange, 0);
-		SETNUMPORTS(portRange, 1);
-		r->raddr.s_addr = INADDR_ANY;
-	}
-	r->rport = GETLOPORT(portRange);
-	r->rport_cnt = GETNUMPORTS(portRange);
-
-	/* 
-	 * Make sure port ranges match up, then add the redirect ports.
-	 */
-	if (numLocalPorts != r->pport_cnt)
-	        errx(EX_DATAERR, "redirect_port:"
-		    "port ranges must be equal in size");
-
-	/* Remote port range is allowed to be '0' which means all ports. */
-	if (r->rport_cnt != numLocalPorts && 
-	    (r->rport_cnt != 1 || r->rport != 0))
-	        errx(EX_DATAERR, "redirect_port: remote port must"
-		    "be 0 or equal to local port range in size");

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901271201.n0RC1Us3085751>