📄 proxy_util.c
字号:
!= 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){ char *host = This->name; const char *host2 = proxy_get_host_of_request(r); int h2_len; int h1_len; if (host == NULL || host2 == NULL) return 0; /* oops! */ h2_len = strlen(host2); h1_len = strlen(host);#if 0 struct apr_sockaddr_t *addr = *This->hostaddr; /* Try to deal with multiple IP addr's for a host */ while (addr) { if (addr->ipaddr_ptr == ? ? ? ? ? ? ? ? ? ? ? ? ?) return 1; addr = addr->next; }#endif /* Ignore trailing dots in host2 comparison: */ while (h2_len > 0 && host2[h2_len - 1] == '.') --h2_len; while (h1_len > 0 && host[h1_len - 1] == '.') --h1_len; return h1_len == h2_len && strncasecmp(host, host2, h1_len) == 0;}/* Return TRUE if addr is to be matched as a word */PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p){ This->matcher = proxy_match_word; return 1;}/* Return TRUE if string "str2" occurs literally in "str1" */static int proxy_match_word(struct dirconn_entry *This, request_rec *r){ const char *host = proxy_get_host_of_request(r); return host != NULL && ap_strstr_c(host, This->name) != NULL;}/* checks whether a host in uri_addr matches proxyblock */PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr){ int j; apr_sockaddr_t * src_uri_addr = uri_addr; /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */ for (j = 0; j < conf->noproxies->nelts; j++) { struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct apr_sockaddr_t *conf_addr = npent[j].addr; uri_addr = src_uri_addr; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: checking remote machine [%s] against [%s]", uri_addr->hostname, npent[j].name); if ((npent[j].name && ap_strstr_c(uri_addr->hostname, npent[j].name)) || npent[j].name[0] == '*') { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, "proxy: connect to remote machine %s blocked: name %s matched", uri_addr->hostname, npent[j].name); return HTTP_FORBIDDEN; } while (conf_addr) { while (uri_addr) { char *conf_ip; char *uri_ip; apr_sockaddr_ip_get(&conf_ip, conf_addr); apr_sockaddr_ip_get(&uri_ip, uri_addr); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: ProxyBlock comparing %s and %s", conf_ip, uri_ip); if (!apr_strnatcasecmp(conf_ip, uri_ip)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server, "proxy: connect to remote machine %s blocked: IP %s matched", uri_addr->hostname, conf_ip); return HTTP_FORBIDDEN; } uri_addr = uri_addr->next; } conf_addr = conf_addr->next; } } return OK;}/* set up the minimal filter set */PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r){ ap_add_input_filter("HTTP_IN", NULL, r, c); return OK;}/* converts a series of buckets into a string * XXX: BillS says this function performs essentially the same function as * ap_rgetline() in protocol.c. Deprecate this function and use ap_rgetline() * instead? I think ap_proxy_string_read() will not work properly on non ASCII * (EBCDIC) machines either. */PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, apr_size_t bufflen, int *eos){ apr_bucket *e; apr_status_t rv; char *pos = buff; char *response; int found = 0; apr_size_t len; /* start with an empty string */ buff[0] = 0; *eos = 0; /* loop through each brigade */ while (!found) { /* get brigade from network one line at a time */ if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb, AP_MODE_GETLINE, APR_BLOCK_READ, 0))) { return rv; } /* loop through each bucket */ while (!found) { if (*eos || APR_BRIGADE_EMPTY(bb)) { /* The connection aborted or timed out */ return APR_ECONNABORTED; } e = APR_BRIGADE_FIRST(bb); if (APR_BUCKET_IS_EOS(e)) { *eos = 1; } else { if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) { return rv; } /* is string LF terminated? * XXX: This check can be made more efficient by simply checking * if the last character in the 'response' buffer is an ASCII_LF. * See ap_rgetline() for an example. */ if (memchr(response, APR_ASCII_LF, len)) { found = 1; } /* concat strings until buff is full - then throw the data away */ if (len > ((bufflen-1)-(pos-buff))) { len = (bufflen-1)-(pos-buff); } if (len > 0) { pos = apr_cpystrn(pos, response, len); } } APR_BUCKET_REMOVE(e); apr_bucket_destroy(e); } } return APR_SUCCESS;}/* unmerge an element in the table */PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key){ apr_off_t offset = 0; apr_off_t count = 0; char *value = NULL; /* get the value to unmerge */ const char *initial = apr_table_get(t, key); if (!initial) { return; } value = apr_pstrdup(p, initial); /* remove the value from the headers */ apr_table_unset(t, key); /* find each comma */ while (value[count]) { if (value[count] == ',') { value[count] = 0; apr_table_add(t, key, value + offset); offset = count + 1; } count++; } apr_table_add(t, key, value + offset);}PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **newsock, const char *proxy_function, apr_sockaddr_t *backend_addr, const char *backend_name, proxy_server_conf *conf, server_rec *s, apr_pool_t *p){ apr_status_t rv; int connected = 0; int loglevel; while (backend_addr && !connected) { if ((rv = apr_socket_create(newsock, backend_addr->family, SOCK_STREAM, p)) != APR_SUCCESS) { loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; ap_log_error(APLOG_MARK, loglevel, rv, s, "proxy: %s: error creating fam %d socket for target %s", proxy_function, backend_addr->family, backend_name); /* this could be an IPv6 address from the DNS but the * local machine won't give us an IPv6 socket; hopefully the * DNS returned an additional address to try */ backend_addr = backend_addr->next; continue; }#if !defined(TPF) && !defined(BEOS) if (conf->recv_buffer_size > 0 && (rv = apr_socket_opt_set(*newsock, APR_SO_RCVBUF, conf->recv_buffer_size))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "apr_socket_opt_set(SO_RCVBUF): Failed to set " "ProxyReceiveBufferSize, using default"); }#endif /* Set a timeout on the socket */ if (conf->timeout_set == 1) { apr_socket_timeout_set(*newsock, conf->timeout); } else { apr_socket_timeout_set(*newsock, s->timeout); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "proxy: %s: fam %d socket created to connect to %s", proxy_function, backend_addr->family, backend_name); /* make the connection out of the socket */ rv = apr_connect(*newsock, backend_addr); /* if an error occurred, loop round and try again */ if (rv != APR_SUCCESS) { apr_socket_close(*newsock); loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR; ap_log_error(APLOG_MARK, loglevel, rv, s, "proxy: %s: attempt to connect to %pI (%s) failed", proxy_function, backend_addr, backend_name); backend_addr = backend_addr->next; continue; } connected = 1; } return connected ? 0 : 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -