proxy_util.c
来自「apache服务器源代码(版本号:2.2.2)」· C语言 代码 · 共 2,057 行 · 第 1/5 页
C
2,057 行
* optional whitespace around the tokens. * if val appears on the list of tokens, it is removed from the list, * and the new list is returned. */PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val){ int len, i; const char *p; char *new = NULL; len = strlen(val); while (list != NULL) { p = ap_strchr_c(list, ','); if (p != NULL) { i = p - list; do p++; while (apr_isspace(*p)); } else i = strlen(list); while (i > 0 && apr_isspace(list[i - 1])) i--; if (i == len && strncasecmp(list, val, len) == 0) { /* do nothing */ } else { if (new) new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL); else new = apr_pstrndup(pool, list, i); } list = p; } return new;}/* * Converts 8 hex digits to a time integer */PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x){ int i, ch; unsigned int j; for (i = 0, j = 0; i < 8; i++) { ch = x[i]; j <<= 4; if (apr_isdigit(ch)) j |= ch - '0'; else if (apr_isupper(ch)) j |= ch - ('A' - 10); else j |= ch - ('a' - 10); } if (j == 0xffffffff) return -1; /* so that it works with 8-byte ints */ else return j;}/* * Converts a time integer to 8 hex digits */PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y){ int i, ch; unsigned int j = t; for (i = 7; i >= 0; i--) { ch = j & 0xF; j >>= 4; if (ch >= 10) y[i] = ch + ('A' - 10); else y[i] = ch + '0'; } y[8] = '\0';}PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message){ apr_table_setn(r->notes, "error-notes", apr_pstrcat(r->pool, "The proxy server could not handle the request " "<em><a href=\"", ap_escape_uri(r->pool, r->uri), "\">", ap_escape_html(r->pool, r->method), " ", ap_escape_html(r->pool, r->uri), "</a></em>.<p>\n" "Reason: <strong>", ap_escape_html(r->pool, message), "</strong></p>", NULL)); /* Allow "error-notes" string to be printed by ap_send_error_response() */ apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*")); r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: %s returned by %s", message, r->uri); return statuscode;}static const char * proxy_get_host_of_request(request_rec *r){ char *url, *user = NULL, *password = NULL, *err, *host; apr_port_t port; if (r->hostname != NULL) return r->hostname; /* Set url to the first char after "scheme://" */ if ((url = strchr(r->uri, ':')) == NULL || url[1] != '/' || url[2] != '/') return NULL; url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */ err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port); if (err != NULL) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", err); r->hostname = host; return host; /* ought to return the port, too */}/* Return TRUE if addr represents an IP address (or an IP network address) */PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p){ const char *addr = This->name; long ip_addr[4]; int i, quads; long bits; /* * if the address is given with an explicit netmask, use that * Due to a deficiency in apr_inet_addr(), it is impossible to parse * "partial" addresses (with less than 4 quads) correctly, i.e. * 192.168.123 is parsed as 192.168.0.123, which is not what I want. * I therefore have to parse the IP address manually: * if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) * addr and mask were set by proxy_readmask() * return 1; */ /* * Parse IP addr manually, optionally allowing * abbreviated net addresses like 192.168. */ /* Iterate over up to 4 (dotted) quads. */ for (quads = 0; quads < 4 && *addr != '\0'; ++quads) { char *tmp; if (*addr == '/' && quads > 0) /* netmask starts here. */ break; if (!apr_isdigit(*addr)) return 0; /* no digit at start of quad */ ip_addr[quads] = strtol(addr, &tmp, 0); if (tmp == addr) /* expected a digit, found something else */ return 0; if (ip_addr[quads] < 0 || ip_addr[quads] > 255) { /* invalid octet */ return 0; } addr = tmp; if (*addr == '.' && quads != 3) ++addr; /* after the 4th quad, a dot would be illegal */ } for (This->addr.s_addr = 0, i = 0; i < quads; ++i) This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i)); if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */ char *tmp; ++addr; bits = strtol(addr, &tmp, 0); if (tmp == addr) /* expected a digit, found something else */ return 0; addr = tmp; if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */ return 0; } else { /* * Determine (i.e., "guess") netmask by counting the * number of trailing .0's; reduce #quads appropriately * (so that 192.168.0.0 is equivalent to 192.168.) */ while (quads > 0 && ip_addr[quads - 1] == 0) --quads; /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */ if (quads < 1) return 0; /* every zero-byte counts as 8 zero-bits */ bits = 8 * quads; if (bits != 32) /* no warning for fully qualified IP address */ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld", inet_ntoa(This->addr), bits); } This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits)); if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Warning: NetMask and IP-Addr disagree in %s/%ld", inet_ntoa(This->addr), bits); This->addr.s_addr &= This->mask.s_addr; ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " Set to %s/%ld", inet_ntoa(This->addr), bits); } if (*addr == '\0') { This->matcher = proxy_match_ipaddr; return 1; } else return (*addr == '\0'); /* okay iff we've parsed the whole string */}/* Return TRUE if addr represents an IP address (or an IP network address) */static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r){ int i, ip_addr[4]; struct in_addr addr, *ip; const char *host = proxy_get_host_of_request(r); if (host == NULL) /* oops! */ return 0; memset(&addr, '\0', sizeof addr); memset(ip_addr, '\0', sizeof ip_addr); if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) { for (addr.s_addr = 0, i = 0; i < 4; ++i) addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i)); if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {#if DEBUGGING ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s/", inet_ntoa(This->addr)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s", inet_ntoa(This->mask));#endif return 1; }#if DEBUGGING else { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s/", inet_ntoa(This->addr)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s", inet_ntoa(This->mask)); }#endif } else { struct apr_sockaddr_t *reqaddr; if (apr_sockaddr_info_get(&reqaddr, host, APR_UNSPEC, 0, 0, r->pool) != APR_SUCCESS) {#if DEBUGGING ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "2)IP-NoMatch: hostname=%s msg=Host not found", host);#endif return 0; } /* Try to deal with multiple IP addr's for a host */ /* FIXME: This needs to be able to deal with IPv6 */ while (reqaddr) { ip = (struct in_addr *) reqaddr->ipaddr_ptr; if (This->addr.s_addr == (ip->s_addr & This->mask.s_addr)) {#if DEBUGGING ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "3)IP-Match: %s[%s] <-> ", host, inet_ntoa(*ip)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s/", inet_ntoa(This->addr)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s", inet_ntoa(This->mask));#endif return 1; }#if DEBUGGING else { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "3)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(*ip)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s/", inet_ntoa(This->addr)); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "%s", inet_ntoa(This->mask)); }#endif reqaddr = reqaddr->next; } } return 0;}/* Return TRUE if addr represents a domain name */PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p){ char *addr = This->name; int i; /* Domain name must start with a '.' */ if (addr[0] != '.') return 0; /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */ for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i) continue;#if 0 if (addr[i] == ':') { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "@@@@ handle optional port in proxy_is_domainname()"); /* @@@@ handle optional port */ }#endif if (addr[i] != '\0') return 0; /* Strip trailing dots */ for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) addr[i] = '\0'; This->matcher = proxy_match_domainname; return 1;}/* Return TRUE if host "host" is in domain "domain" */static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r){ const char *host = proxy_get_host_of_request(r); int d_len = strlen(This->name), h_len; if (host == NULL) /* some error was logged already */ return 0; h_len = strlen(host); /* @@@ do this within the setup? */ /* Ignore trailing dots in domain comparison: */ while (d_len > 0 && This->name[d_len - 1] == '.') --d_len; while (h_len > 0 && host[h_len - 1] == '.') --h_len; return h_len > d_len && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;}/* Return TRUE if host represents a host name */PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p){ struct apr_sockaddr_t *addr; char *host = This->name; int i; /* Host names must not start with a '.' */ if (host[0] == '.') return 0; /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */ for (i = 0; apr_isalnum(host[i]) || host[i] == '-' || host[i] == '.'; ++i); if (host[i] != '\0' || apr_sockaddr_info_get(&addr, host, APR_UNSPEC, 0, 0, p) != APR_SUCCESS) return 0; This->hostaddr = addr; /* Strip trailing dots */ for (i = strlen(host) - 1; i > 0 && host[i] == '.'; --i) host[i] = '\0'; This->matcher = proxy_match_hostname; return 1;}/* Return TRUE if host "host" is equal to host2 "host2" */static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?