static const char *proxies_set(cmd_parms *cmd, void *cfg, const char *arg) { remoteip_config_t *config = ap_get_module_config(cmd->server->module_config, &remoteip_module); remoteip_proxymatch_t *match; apr_status_t rv; char *ip = apr_pstrdup(cmd->temp_pool, arg); char *s = ap_strchr(ip, '/'); if (s) { *s++ = '\0'; } if (!config->proxymatch_ip) { config->proxymatch_ip = apr_array_make(cmd->pool, 1, sizeof(*match)); } match = (remoteip_proxymatch_t *) apr_array_push(config->proxymatch_ip); match->internal = cmd->info; if (looks_like_ip(ip)) { /* Note s may be null, that's fine (explicit host) */ rv = apr_ipsubnet_create(&match->ip, ip, s, cmd->pool); } else { apr_sockaddr_t *temp_sa; if (s) { return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg, " the subnet /", s, " is invalid for ", cmd->cmd->name, NULL); } rv = apr_sockaddr_info_get(&temp_sa, ip, APR_UNSPEC, 0, APR_IPV4_ADDR_OK, cmd->temp_pool); while (rv == APR_SUCCESS) { apr_sockaddr_ip_get(&ip, temp_sa); rv = apr_ipsubnet_create(&match->ip, ip, NULL, cmd->pool); if (!(temp_sa = temp_sa->next)) { break; } match = (remoteip_proxymatch_t *) apr_array_push(config->proxymatch_ip); match->internal = cmd->info; } } if (rv != APR_SUCCESS) { char msgbuf[128]; apr_strerror(rv, msgbuf, sizeof(msgbuf)); return apr_pstrcat(cmd->pool, "RemoteIP: Error parsing IP ", arg, " (", msgbuf, " error) for ", cmd->cmd->name, NULL); } return NULL; }
/* be sure not to store any IPv4 address as a v4-mapped IPv6 address */ APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, const char *ipstr, const char *mask_or_numbits, apr_pool_t *p) { apr_status_t rv; char *endptr; long bits, maxbits = 32; /* filter out stuff which doesn't look remotely like an IP address; this helps * callers like mod_access which have a syntax allowing hostname or IP address; * APR_EINVAL tells the caller that it was probably not intended to be an IP * address */ if (!looks_like_ip(ipstr)) { return APR_EINVAL; } *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t)); /* assume ipstr is an individual IP address, not a subnet */ memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask); rv = parse_ip(*ipsub, ipstr, mask_or_numbits == NULL); if (rv != APR_SUCCESS) { return rv; } if (mask_or_numbits) { #if APR_HAVE_IPV6 if ((*ipsub)->family == AF_INET6) { maxbits = 128; } #endif bits = strtol(mask_or_numbits, &endptr, 10); if (*endptr == '\0' && bits > 0 && bits <= maxbits) { /* valid num-bits string; fill in mask appropriately */ int cur_entry = 0; apr_int32_t cur_bit_value; memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask); while (bits > 32) { (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */ bits -= 32; ++cur_entry; } cur_bit_value = 0x80000000; while (bits) { (*ipsub)->mask[cur_entry] |= cur_bit_value; --bits; cur_bit_value /= 2; } (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]); } else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 && (*ipsub)->family == AF_INET) { /* valid IPv4 netmask */ } else { return APR_EBADMASK; } } fix_subnet(*ipsub); return APR_SUCCESS; }