Index: network_io/unix/sockaddr.c =================================================================== --- network_io/unix/sockaddr.c (revision 1165670) +++ network_io/unix/sockaddr.c (working copy) @@ -560,6 +560,114 @@ #endif /* end of !HAVE_GETADDRINFO code */ +static apr_status_t fillin_literal(apr_sockaddr_t *sa, apr_port_t port, + int af, const char *begin, const char *end) +{ + char buf[80]; + int rc; + + if (end - begin + 1 >= sizeof buf) { + return APR_EINVAL; + } + + memcpy(buf, begin, end - begin + 1); + buf[end - begin + 1] = '\0'; + + apr_sockaddr_vars_set(sa, af, port); + + rc = apr_inet_pton(af, buf, sa->ipaddr_ptr); + if (rc != 1) { + return APR_EINVAL; + } + + return APR_SUCCESS; +} + +static apr_status_t from_envvar(apr_sockaddr_t **in_sa, + const char *hostname, + apr_int32_t family, apr_port_t port, + const char *in_def, + apr_pool_t *p) +{ + const char *def; + const char *end; + apr_sockaddr_t *sa, *prev = NULL; + apr_status_t rv; + + *in_sa = NULL; + + /* family is not checked against configured IP addresses! + * This only makes sense if family is AF_UNSPEC or if only + * IP addrs of the correct family are configured. + */ + + end = strchr(in_def, ';'); + if (end) { + apr_size_t len = end - in_def; + + def = apr_pmemdup(p, in_def, len + 1); + *((char *)def + len) = '\0'; + } + else { + def = in_def; + } + + while (*def) { + sa = apr_pcalloc(p, sizeof *sa); + if (prev) { + prev->next = sa; + } + prev = sa; + + sa->pool = p; + sa->hostname = apr_pstrdup(p, hostname); + sa->port = port; + sa->servname = apr_psprintf(p, "%hu", port); + + if (!*in_sa) { + *in_sa = sa; + } + + if (*def == '[') { /* IPv6 literal */ + end = strchr(def, ']'); + if (!end) { + return APR_EINVAL; + } + + rv = fillin_literal(sa, port, AF_INET6, def + 1, end - 1); + if (rv != APR_SUCCESS) { + return rv; + } + + if (*(end + 1)) { + if (*(end + 1) != ',') { + return APR_EINVAL; + } + def = end + 2; + } + else { + def = end + 1; + } + } + else { /* IPv4 literal */ + end = strchr(def, ','); + if (end) { + rv = fillin_literal(sa, port, AF_INET, def, end - 1); + def = end + 1; + } + else { + rv = fillin_literal(sa, port, AF_INET, def, def + strlen(def) - 1); + def += strlen(def); + } + if (rv != APR_SUCCESS) { + return rv; + } + } + } + + return APR_SUCCESS; +} + APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa, const char *hostname, apr_int32_t family, apr_port_t port, @@ -567,7 +675,29 @@ { apr_int32_t masked; *sa = NULL; + const char *env; + env = getenv("APR_S_I_G"); + if (env && hostname) { + const char *search = apr_pstrcat(p, ";", hostname, "=", NULL); + const char *found = NULL; + + if (!memcmp(env, search + 1, strlen(search) - 1)) { + found = env + strlen(search) - 1; + } + else { + found = strstr(env, search); + if (found) { + found += strlen(search); + } + } + + if (found) { + return from_envvar(sa, hostname, family, port, + found, p); + } + } + if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) { if (!hostname || family != APR_UNSPEC ||