[MEDIUM] add support for binding to source port ranges during connect

Some users are already hitting the 64k source port limit when
connecting to servers. The system usually maintains a list of
unused source ports, regardless of the source IP they're bound
to. So in order to go beyond the 64k concurrent connections, we
have to manage the source ip:port lists ourselves.

The solution consists in assigning a source port range to each
server and use a free port in that range when connecting to that
server, either for a proxied connection or for a health check.
The port must then be put back into the server's range when the
connection is closed.

This mechanism is used only when a port range is specified on
a server. It makes it possible to reach 64k connections per
server, possibly all from the same IP address. Right now it
should be more than enough even for huge deployments.
diff --git a/src/standard.c b/src/standard.c
index de5b664..9dc56af 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -1,7 +1,7 @@
 /*
  * General purpose functions.
  *
- * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -241,6 +241,65 @@
 }
 
 /*
+ * converts <str> to a struct sockaddr_in* which is locally allocated, and a
+ * port range consisting in two integers. The low and high end are always set
+ * even if the port is unspecified, in which case (0,0) is returned. The low
+ * port is set in the sockaddr_in. Thus, it is enough to check the size of the
+ * returned range to know if an array must be allocated or not. The format is
+ * "addr[:port[-port]]", where "addr" can be a dotted IPv4 address, a host
+ * name, or empty or "*" to indicate INADDR_ANY.
+ */
+struct sockaddr_in *str2sa_range(char *str, int *low, int *high)
+{
+	static struct sockaddr_in sa;
+	char *c;
+	int portl, porth;
+
+	memset(&sa, 0, sizeof(sa));
+	str = strdup(str);
+	if (str == NULL)
+		goto out_nofree;
+
+	if ((c = strrchr(str,':')) != NULL) {
+		char *sep;
+		*c++ = '\0';
+		sep = strchr(c, '-');
+		if (sep)
+			*sep++ = '\0';
+		else
+			sep = c;
+		portl = atol(c);
+		porth = atol(sep);
+	}
+	else {
+		portl = 0;
+		porth = 0;
+	}
+
+	if (*str == '*' || *str == '\0') { /* INADDR_ANY */
+		sa.sin_addr.s_addr = INADDR_ANY;
+	}
+	else if (!inet_pton(AF_INET, str, &sa.sin_addr)) {
+		struct hostent *he;
+
+		if ((he = gethostbyname(str)) == NULL) {
+			Alert("Invalid server name: '%s'\n", str);
+		}
+		else
+			sa.sin_addr = *(struct in_addr *) *(he->h_addr_list);
+	}
+	sa.sin_port   = htons(portl);
+	sa.sin_family = AF_INET;
+
+	*low = portl;
+	*high = porth;
+
+	free(str);
+ out_nofree:
+	return &sa;
+}
+
+/*
  * converts <str> to two struct in_addr* which must be pre-allocated.
  * The format is "addr[/mask]", where "addr" cannot be empty, and mask
  * is optionnal and either in the dotted or CIDR notation.