proxy_util.c
来自「apache服务器源代码(版本号:2.2.2)」· C语言 代码 · 共 2,057 行 · 第 1/5 页
C
2,057 行
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(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url){ struct proxy_alias *ent; int i, l1, l2; char *u; /* * XXX FIXME: Make sure this handled the ambiguous case of the :<PORT> * after the hostname */ l1 = strlen(url); ent = (struct proxy_alias *)conf->raliases->elts; for (i = 0; i < conf->raliases->nelts; i++) { l2 = strlen(ent[i].real); if (l1 >= l2 && strncasecmp(ent[i].real, url, l2) == 0) { u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL); return ap_construct_url(r->pool, u, r); } } return url;}/* * Cookies are a bit trickier to match: we've got two substrings to worry * about, and we can't just find them with strstr 'cos of case. Regexp * matching would be an easy fix, but for better consistency with all the * other matches we'll refrain and use apr_strmatch to find path=/domain= * and stick to plain strings for the config values. */PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str){ struct proxy_alias *ent; size_t len = strlen(str); const char *newpath = NULL; const char *newdomain = NULL; const char *pathp; const char *domainp; const char *pathe = NULL; const char *domaine = NULL; size_t l1, l2, poffs = 0, doffs = 0; int i; int ddiff = 0; int pdiff = 0; char *ret; /* * Find the match and replacement, but save replacing until we've done * both path and domain so we know the new strlen */ if ((pathp = apr_strmatch(conf->cookie_path_str, str, len)) != NULL) { pathp += 5; poffs = pathp - str; pathe = ap_strchr_c(pathp, ';'); l1 = pathe ? (pathe - pathp) : strlen(pathp); pathe = pathp + l1 ; ent = (struct proxy_alias *)conf->cookie_paths->elts; for (i = 0; i < conf->cookie_paths->nelts; i++) { l2 = strlen(ent[i].fake); if (l1 >= l2 && strncmp(ent[i].fake, pathp, l2) == 0) { newpath = ent[i].real; pdiff = strlen(newpath) - l1; break; } } } if ((domainp = apr_strmatch(conf->cookie_domain_str, str, len)) != NULL) { domainp += 7; doffs = domainp - str; domaine = ap_strchr_c(domainp, ';'); l1 = domaine ? (domaine - domainp) : strlen(domainp); domaine = domainp + l1; ent = (struct proxy_alias *)conf->cookie_domains->elts; for (i = 0; i < conf->cookie_domains->nelts; i++) { l2 = strlen(ent[i].fake); if (l1 >= l2 && strncasecmp(ent[i].fake, domainp, l2) == 0) { newdomain = ent[i].real; ddiff = strlen(newdomain) - l1; break; } } } if (newpath) { ret = apr_palloc(r->pool, len + pdiff + ddiff + 1); l1 = strlen(newpath); if (newdomain) { l2 = strlen(newdomain); if (doffs > poffs) { memcpy(ret, str, poffs); memcpy(ret + poffs, newpath, l1); memcpy(ret + poffs + l1, pathe, domainp - pathe); memcpy(ret + doffs + pdiff, newdomain, l2); strcpy(ret + doffs + pdiff + l2, domaine); } else { memcpy(ret, str, doffs) ; memcpy(ret + doffs, newdomain, l2); memcpy(ret + doffs + l2, domaine, pathp - domaine); memcpy(ret + poffs + ddiff, newpath, l1); strcpy(ret + poffs + ddiff + l1, pathe); } } else { memcpy(ret, str, poffs); memcpy(ret + poffs, newpath, l1); strcpy(ret + poffs + l1, pathe); } } else { if (newdomain) { ret = apr_palloc(r->pool, len + pdiff + ddiff + 1); l2 = strlen(newdomain); memcpy(ret, str, doffs); memcpy(ret + doffs, newdomain, l2); strcpy(ret + doffs+l2, domaine); } else { ret = (char *)str; /* no change */ } } return ret;}PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, proxy_server_conf *conf, const char *url){ proxy_balancer *balancer; char *c, *uri = apr_pstrdup(p, url); int i; c = strchr(uri, ':'); if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') return NULL; /* remove path from uri */ if ((c = strchr(c + 3, '/'))) *c = '\0'; balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { if (strcasecmp(balancer->name, uri) == 0) return balancer; balancer++; } return NULL;}PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer, apr_pool_t *p, proxy_server_conf *conf, const char *url){ char *c, *q, *uri = apr_pstrdup(p, url); proxy_balancer_method *lbmethod; c = strchr(uri, ':'); if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') return "Bad syntax for a balancer name"; /* remove path from uri */ if ((q = strchr(c + 3, '/'))) *q = '\0'; ap_str_tolower(uri); *balancer = apr_array_push(conf->balancers); memset(*balancer, 0, sizeof(proxy_balancer)); /* * NOTE: The default method is byrequests, which we assume * exists! */ lbmethod = ap_lookup_provider(PROXY_LBMETHOD, "byrequests", "0"); if (!lbmethod) { return "Can't find 'byrequests' lb method"; } (*balancer)->name = uri; (*balancer)->lbmethod = lbmethod; (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker)); /* XXX Is this a right place to create mutex */#if APR_HAS_THREADS if (apr_thread_mutex_create(&((*balancer)->mutex), APR_THREAD_MUTEX_DEFAULT, p) != APR_SUCCESS) { /* XXX: Do we need to log something here */ return "can not create thread mutex"; }#endif return NULL;}PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, proxy_server_conf *conf, const char *url){ proxy_worker *worker; proxy_worker *max_worker = NULL; int max_match = 0; int url_length; int worker_name_length; const char *c; char *url_copy; int i; c = ap_strchr_c(url, ':'); if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') return NULL; url_copy = apr_pstrdup(p, url); url_length = strlen(url); /* * We need to find the start of the path and * therefore we know the length of the scheme://hostname/ * part to we can force-lowercase everything up to * the start of the path. */ c = ap_strchr_c(c+3, '/');
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?