[MEDIUM] rename process_request to http_process_request

Now the function only does HTTP request and nothing else. Also pass
the request buffer to it.
This commit is contained in:
Willy Tarreau 2008-11-30 23:51:27 +01:00
parent d34af78a34
commit 59234e91c2
3 changed files with 698 additions and 717 deletions

View File

@ -62,7 +62,7 @@ void process_session(struct task *t, int *next);
int process_cli(struct session *t); int process_cli(struct session *t);
int process_srv_data(struct session *t); int process_srv_data(struct session *t);
int process_srv_conn(struct session *t); int process_srv_conn(struct session *t);
int process_request(struct session *t); int http_process_request(struct session *t, struct buffer *req);
int http_process_tarpit(struct session *s, struct buffer *req); int http_process_tarpit(struct session *s, struct buffer *req);
int http_process_request_body(struct session *s, struct buffer *req); int http_process_request_body(struct session *s, struct buffer *req);
int process_response(struct session *t); int process_response(struct session *t);

View File

@ -1563,22 +1563,20 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx
* called after XXX bytes have been received (or transfered), and the min of * called after XXX bytes have been received (or transfered), and the min of
* all's wishes will be used to ring back (unless a special condition occurs). * all's wishes will be used to ring back (unless a special condition occurs).
*/ */
int process_request(struct session *t) int http_process_request(struct session *s, struct buffer *req)
{ {
struct buffer *req = t->req;
DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n", DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
now_ms, __FUNCTION__, now_ms, __FUNCTION__,
t, s,
req, req,
req->rex, req->wex, req->rex, req->wex,
req->flags, req->flags,
req->l, req->l,
req->analysers); req->analysers);
if (req->analysers & AN_REQ_HTTP_HDR) {
/* /*
* Now parse the partial (or complete) lines. * We will parse the partial (or complete) lines.
* We will check the request syntax, and also join multi-line * We will check the request syntax, and also join multi-line
* headers. An index of all the lines will be elaborated while * headers. An index of all the lines will be elaborated while
* parsing. * parsing.
@ -1594,7 +1592,7 @@ int process_request(struct session *t)
*/ */
int cur_idx; int cur_idx;
struct http_txn *txn = &t->txn; struct http_txn *txn = &s->txn;
struct http_msg *msg = &txn->req; struct http_msg *msg = &txn->req;
struct proxy *cur_proxy; struct proxy *cur_proxy;
@ -1609,14 +1607,14 @@ int process_request(struct session *t)
sol = req->data + msg->som; sol = req->data + msg->som;
eol = sol + msg->sl.rq.l; eol = sol + msg->sl.rq.l;
debug_hdr("clireq", t, sol, eol); debug_hdr("clireq", s, sol, eol);
sol += hdr_idx_first_pos(&txn->hdr_idx); sol += hdr_idx_first_pos(&txn->hdr_idx);
cur_idx = hdr_idx_first_idx(&txn->hdr_idx); cur_idx = hdr_idx_first_idx(&txn->hdr_idx);
while (cur_idx) { while (cur_idx) {
eol = sol + txn->hdr_idx.v[cur_idx].len; eol = sol + txn->hdr_idx.v[cur_idx].len;
debug_hdr("clihdr", t, sol, eol); debug_hdr("clihdr", s, sol, eol);
sol = eol + txn->hdr_idx.v[cur_idx].cr + 1; sol = eol + txn->hdr_idx.v[cur_idx].cr + 1;
cur_idx = txn->hdr_idx.v[cur_idx].next; cur_idx = txn->hdr_idx.v[cur_idx].next;
} }
@ -1656,11 +1654,11 @@ int process_request(struct session *t)
/* we cannot return any message on error */ /* we cannot return any message on error */
msg->msg_state = HTTP_MSG_ERROR; msg->msg_state = HTTP_MSG_ERROR;
req->analysers = 0; req->analysers = 0;
//t->fe->failed_req++; s->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK)) if (!(s->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLICL; s->flags |= SN_ERR_CLICL;
if (!(t->flags & SN_FINST_MASK)) if (!(s->flags & SN_FINST_MASK))
t->flags |= SN_FINST_R; s->flags |= SN_FINST_R;
return 0; return 0;
} }
@ -1668,36 +1666,36 @@ int process_request(struct session *t)
else if (req->flags & BF_READ_TIMEOUT || tick_is_expired(req->analyse_exp, now_ms)) { else if (req->flags & BF_READ_TIMEOUT || tick_is_expired(req->analyse_exp, now_ms)) {
/* read timeout : give up with an error message. */ /* read timeout : give up with an error message. */
txn->status = 408; txn->status = 408;
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_408)); stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_408));
msg->msg_state = HTTP_MSG_ERROR; msg->msg_state = HTTP_MSG_ERROR;
req->analysers = 0; req->analysers = 0;
t->fe->failed_req++; s->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK)) if (!(s->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLITO; s->flags |= SN_ERR_CLITO;
if (!(t->flags & SN_FINST_MASK)) if (!(s->flags & SN_FINST_MASK))
t->flags |= SN_FINST_R; s->flags |= SN_FINST_R;
return 0; return 0;
} }
/* 4: have we encountered a close ? */ /* 4: have we encountered a close ? */
else if (req->flags & BF_SHUTR) { else if (req->flags & BF_SHUTR) {
txn->status = 400; txn->status = 400;
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_400)); stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
msg->msg_state = HTTP_MSG_ERROR; msg->msg_state = HTTP_MSG_ERROR;
req->analysers = 0; req->analysers = 0;
t->fe->failed_req++; s->fe->failed_req++;
if (!(t->flags & SN_ERR_MASK)) if (!(s->flags & SN_ERR_MASK))
t->flags |= SN_ERR_CLICL; s->flags |= SN_ERR_CLICL;
if (!(t->flags & SN_FINST_MASK)) if (!(s->flags & SN_FINST_MASK))
t->flags |= SN_FINST_R; s->flags |= SN_FINST_R;
return 0; return 0;
} }
buffer_write_dis(req); buffer_write_dis(req);
/* just set the request timeout once at the beginning of the request */ /* just set the request timeout once at the beginning of the request */
if (!tick_isset(req->analyse_exp)) if (!tick_isset(req->analyse_exp))
req->analyse_exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq); req->analyse_exp = tick_add_ifset(now_ms, s->fe->timeout.httpreq);
/* we're not ready yet */ /* we're not ready yet */
return 0; return 0;
@ -1723,29 +1721,29 @@ int process_request(struct session *t)
/* we can make use of server redirect on GET and HEAD */ /* we can make use of server redirect on GET and HEAD */
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD) if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
t->flags |= SN_REDIRECTABLE; s->flags |= SN_REDIRECTABLE;
/* /*
* 2: check if the URI matches the monitor_uri. * 2: check if the URI matches the monitor_uri.
* We have to do this for every request which gets in, because * We have to do this for every request which gets in, because
* the monitor-uri is defined by the frontend. * the monitor-uri is defined by the frontend.
*/ */
if (unlikely((t->fe->monitor_uri_len != 0) && if (unlikely((s->fe->monitor_uri_len != 0) &&
(t->fe->monitor_uri_len == msg->sl.rq.u_l) && (s->fe->monitor_uri_len == msg->sl.rq.u_l) &&
!memcmp(&req->data[msg->sl.rq.u], !memcmp(&req->data[msg->sl.rq.u],
t->fe->monitor_uri, s->fe->monitor_uri,
t->fe->monitor_uri_len))) { s->fe->monitor_uri_len))) {
/* /*
* We have found the monitor URI * We have found the monitor URI
*/ */
struct acl_cond *cond; struct acl_cond *cond;
cur_proxy = t->fe; cur_proxy = s->fe;
t->flags |= SN_MONITOR; s->flags |= SN_MONITOR;
/* Check if we want to fail this monitor request or not */ /* Check if we want to fail this monitor request or not */
list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) { list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) {
int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ); int ret = acl_exec_cond(cond, cur_proxy, s, txn, ACL_DIR_REQ);
ret = acl_pass(ret); ret = acl_pass(ret);
if (cond->pol == ACL_COND_UNLESS) if (cond->pol == ACL_COND_UNLESS)
@ -1754,7 +1752,7 @@ int process_request(struct session *t)
if (ret) { if (ret) {
/* we fail this request, let's return 503 service unavail */ /* we fail this request, let's return 503 service unavail */
txn->status = 503; txn->status = 503;
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_503)); stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_503));
goto return_prx_cond; goto return_prx_cond;
} }
} }
@ -1770,7 +1768,7 @@ int process_request(struct session *t)
* Note: we cannot log anymore if the request has been * Note: we cannot log anymore if the request has been
* classified as invalid. * classified as invalid.
*/ */
if (unlikely(t->logs.logwait & LW_REQ)) { if (unlikely(s->logs.logwait & LW_REQ)) {
/* we have a complete HTTP request that we must log */ /* we have a complete HTTP request that we must log */
if ((txn->uri = pool_alloc2(pool2_requri)) != NULL) { if ((txn->uri = pool_alloc2(pool2_requri)) != NULL) {
int urilen = msg->sl.rq.l; int urilen = msg->sl.rq.l;
@ -1780,14 +1778,13 @@ int process_request(struct session *t)
memcpy(txn->uri, &req->data[msg->som], urilen); memcpy(txn->uri, &req->data[msg->som], urilen);
txn->uri[urilen] = 0; txn->uri[urilen] = 0;
if (!(t->logs.logwait &= ~LW_REQ)) if (!(s->logs.logwait &= ~LW_REQ))
t->do_log(t); s->do_log(s);
} else { } else {
Alert("HTTP logging : out of memory.\n"); Alert("HTTP logging : out of memory.\n");
} }
} }
/* 4. We may have to convert HTTP/0.9 requests to HTTP/1.0 */ /* 4. We may have to convert HTTP/0.9 requests to HTTP/1.0 */
if (unlikely(msg->sl.rq.v_l == 0)) { if (unlikely(msg->sl.rq.v_l == 0)) {
int delta; int delta;
@ -1821,9 +1818,9 @@ int process_request(struct session *t)
/* 5: we may need to capture headers */ /* 5: we may need to capture headers */
if (unlikely((t->logs.logwait & LW_REQHDR) && t->fe->req_cap)) if (unlikely((s->logs.logwait & LW_REQHDR) && s->fe->req_cap))
capture_headers(req->data + msg->som, &txn->hdr_idx, capture_headers(req->data + msg->som, &txn->hdr_idx,
txn->req.cap, t->fe->req_cap); txn->req.cap, s->fe->req_cap);
/* /*
* 6: we will have to evaluate the filters. * 6: we will have to evaluate the filters.
@ -1852,12 +1849,12 @@ int process_request(struct session *t)
do { do {
struct acl_cond *cond; struct acl_cond *cond;
struct redirect_rule *rule; struct redirect_rule *rule;
struct proxy *rule_set = t->be; struct proxy *rule_set = s->be;
cur_proxy = t->be; cur_proxy = s->be;
/* first check whether we have some ACLs set to redirect this request */ /* first check whether we have some ACLs set to redirect this request */
list_for_each_entry(rule, &cur_proxy->redirect_rules, list) { list_for_each_entry(rule, &cur_proxy->redirect_rules, list) {
int ret = acl_exec_cond(rule->cond, cur_proxy, t, txn, ACL_DIR_REQ); int ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ);
ret = acl_pass(ret); ret = acl_pass(ret);
if (rule->cond->pol == ACL_COND_UNLESS) if (rule->cond->pol == ACL_COND_UNLESS)
@ -1931,7 +1928,7 @@ int process_request(struct session *t)
txn->status = rule->code; txn->status = rule->code;
/* let's log the request time */ /* let's log the request time */
t->logs.tv_request = now; s->logs.tv_request = now;
stream_int_retnclose(req->prod, &rdr); stream_int_retnclose(req->prod, &rdr);
goto return_prx_cond; goto return_prx_cond;
} }
@ -1939,7 +1936,7 @@ int process_request(struct session *t)
/* first check whether we have some ACLs set to block this request */ /* first check whether we have some ACLs set to block this request */
list_for_each_entry(cond, &cur_proxy->block_cond, list) { list_for_each_entry(cond, &cur_proxy->block_cond, list) {
int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ); int ret = acl_exec_cond(cond, cur_proxy, s, txn, ACL_DIR_REQ);
ret = acl_pass(ret); ret = acl_pass(ret);
if (cond->pol == ACL_COND_UNLESS) if (cond->pol == ACL_COND_UNLESS)
@ -1948,28 +1945,28 @@ int process_request(struct session *t)
if (ret) { if (ret) {
txn->status = 403; txn->status = 403;
/* let's log the request time */ /* let's log the request time */
t->logs.tv_request = now; s->logs.tv_request = now;
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_403)); stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
goto return_prx_cond; goto return_prx_cond;
} }
} }
/* try headers filters */ /* try headers filters */
if (rule_set->req_exp != NULL) { if (rule_set->req_exp != NULL) {
if (apply_filters_to_request(t, req, rule_set->req_exp) < 0) if (apply_filters_to_request(s, req, rule_set->req_exp) < 0)
goto return_bad_req; goto return_bad_req;
} }
if (!(t->flags & SN_BE_ASSIGNED) && (t->be != cur_proxy)) { if (!(s->flags & SN_BE_ASSIGNED) && (s->be != cur_proxy)) {
/* to ensure correct connection accounting on /* to ensure correct connection accounting on
* the backend, we count the connection for the * the backend, we count the connection for the
* one managing the queue. * one managing the queue.
*/ */
t->be->beconn++; s->be->beconn++;
if (t->be->beconn > t->be->beconn_max) if (s->be->beconn > s->be->beconn_max)
t->be->beconn_max = t->be->beconn; s->be->beconn_max = s->be->beconn;
t->be->cum_beconn++; s->be->cum_beconn++;
t->flags |= SN_BE_ASSIGNED; s->flags |= SN_BE_ASSIGNED;
} }
/* has the request been denied ? */ /* has the request been denied ? */
@ -1977,14 +1974,14 @@ int process_request(struct session *t)
/* no need to go further */ /* no need to go further */
txn->status = 403; txn->status = 403;
/* let's log the request time */ /* let's log the request time */
t->logs.tv_request = now; s->logs.tv_request = now;
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_403)); stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
goto return_prx_cond; goto return_prx_cond;
} }
/* We might have to check for "Connection:" */ /* We might have to check for "Connection:" */
if (((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) && if (((s->fe->options | s->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) &&
!(t->flags & SN_CONN_CLOSED)) { !(s->flags & SN_CONN_CLOSED)) {
char *cur_ptr, *cur_end, *cur_next; char *cur_ptr, *cur_end, *cur_next;
int cur_idx, old_idx, delta, val; int cur_idx, old_idx, delta, val;
struct hdr_idx_elem *cur_hdr; struct hdr_idx_elem *cur_hdr;
@ -2010,7 +2007,7 @@ int process_request(struct session *t)
* and this line indicates non-close. We * and this line indicates non-close. We
* replace it. * replace it.
*/ */
if (t->flags & SN_CONN_CLOSED) { if (s->flags & SN_CONN_CLOSED) {
delta = buffer_replace2(req, cur_ptr, cur_next, NULL, 0); delta = buffer_replace2(req, cur_ptr, cur_next, NULL, 0);
txn->req.eoh += delta; txn->req.eoh += delta;
cur_next += delta; cur_next += delta;
@ -2025,7 +2022,7 @@ int process_request(struct session *t)
cur_hdr->len += delta; cur_hdr->len += delta;
txn->req.eoh += delta; txn->req.eoh += delta;
} }
t->flags |= SN_CONN_CLOSED; s->flags |= SN_CONN_CLOSED;
} }
} }
old_idx = cur_idx; old_idx = cur_idx;
@ -2047,71 +2044,71 @@ int process_request(struct session *t)
* FIXME!!! that one is rather dangerous, we want to * FIXME!!! that one is rather dangerous, we want to
* make it follow standard rules (eg: clear req->analysers). * make it follow standard rules (eg: clear req->analysers).
*/ */
if (stats_check_uri_auth(t, rule_set)) { if (stats_check_uri_auth(s, rule_set)) {
req->analysers = 0; req->analysers = 0;
return 0; return 0;
} }
} }
/* now check whether we have some switching rules for this request */ /* now check whether we have some switching rules for this request */
if (!(t->flags & SN_BE_ASSIGNED)) { if (!(s->flags & SN_BE_ASSIGNED)) {
struct switching_rule *rule; struct switching_rule *rule;
list_for_each_entry(rule, &cur_proxy->switching_rules, list) { list_for_each_entry(rule, &cur_proxy->switching_rules, list) {
int ret; int ret;
ret = acl_exec_cond(rule->cond, cur_proxy, t, txn, ACL_DIR_REQ); ret = acl_exec_cond(rule->cond, cur_proxy, s, txn, ACL_DIR_REQ);
ret = acl_pass(ret); ret = acl_pass(ret);
if (rule->cond->pol == ACL_COND_UNLESS) if (rule->cond->pol == ACL_COND_UNLESS)
ret = !ret; ret = !ret;
if (ret) { if (ret) {
t->be = rule->be.backend; s->be = rule->be.backend;
t->be->beconn++; s->be->beconn++;
if (t->be->beconn > t->be->beconn_max) if (s->be->beconn > s->be->beconn_max)
t->be->beconn_max = t->be->beconn; s->be->beconn_max = s->be->beconn;
t->be->cum_beconn++; s->be->cum_beconn++;
/* assign new parameters to the session from the new backend */ /* assign new parameters to the session from the new backend */
t->rep->rto = t->req->wto = t->be->timeout.server; s->rep->rto = s->req->wto = s->be->timeout.server;
t->req->cto = t->be->timeout.connect; s->req->cto = s->be->timeout.connect;
t->conn_retries = t->be->conn_retries; s->conn_retries = s->be->conn_retries;
t->flags |= SN_BE_ASSIGNED; s->flags |= SN_BE_ASSIGNED;
break; break;
} }
} }
} }
if (!(t->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) { if (!(s->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) {
/* No backend was set, but there was a default /* No backend was set, but there was a default
* backend set in the frontend, so we use it and * backend set in the frontend, so we use it and
* loop again. * loop again.
*/ */
t->be = cur_proxy->defbe.be; s->be = cur_proxy->defbe.be;
t->be->beconn++; s->be->beconn++;
if (t->be->beconn > t->be->beconn_max) if (s->be->beconn > s->be->beconn_max)
t->be->beconn_max = t->be->beconn; s->be->beconn_max = s->be->beconn;
t->be->cum_beconn++; s->be->cum_beconn++;
/* assign new parameters to the session from the new backend */ /* assign new parameters to the session from the new backend */
t->rep->rto = t->req->wto = t->be->timeout.server; s->rep->rto = s->req->wto = s->be->timeout.server;
t->req->cto = t->be->timeout.connect; s->req->cto = s->be->timeout.connect;
t->conn_retries = t->be->conn_retries; s->conn_retries = s->be->conn_retries;
t->flags |= SN_BE_ASSIGNED; s->flags |= SN_BE_ASSIGNED;
} }
} while (t->be != cur_proxy); /* we loop only if t->be has changed */ } while (s->be != cur_proxy); /* we loop only if s->be has changed */
if (!(t->flags & SN_BE_ASSIGNED)) { if (!(s->flags & SN_BE_ASSIGNED)) {
/* To ensure correct connection accounting on /* To ensure correct connection accounting on
* the backend, we count the connection for the * the backend, we count the connection for the
* one managing the queue. * one managing the queue.
*/ */
t->be->beconn++; s->be->beconn++;
if (t->be->beconn > t->be->beconn_max) if (s->be->beconn > s->be->beconn_max)
t->be->beconn_max = t->be->beconn; s->be->beconn_max = s->be->beconn;
t->be->cum_beconn++; s->be->cum_beconn++;
t->flags |= SN_BE_ASSIGNED; s->flags |= SN_BE_ASSIGNED;
} }
/* /*
@ -2125,8 +2122,8 @@ int process_request(struct session *t)
* If HTTP PROXY is set we simply get remote server address * If HTTP PROXY is set we simply get remote server address
* parsing incoming request. * parsing incoming request.
*/ */
if ((t->be->options & PR_O_HTTP_PROXY) && !(t->flags & SN_ADDR_SET)) { if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
url2sa(req->data + msg->sl.rq.u, msg->sl.rq.u_l, &t->srv_addr); url2sa(req->data + msg->sl.rq.u, msg->sl.rq.u_l, &s->srv_addr);
} }
/* /*
@ -2135,52 +2132,50 @@ int process_request(struct session *t)
*/ */
/* It needs to look into the URI */ /* It needs to look into the URI */
if (t->be->appsession_name) { if (s->be->appsession_name) {
get_srv_from_appsession(t, &req->data[msg->som], msg->sl.rq.l); get_srv_from_appsession(s, &req->data[msg->som], msg->sl.rq.l);
} }
/* /*
* 8: Now we can work with the cookies. * 8: Now we can work with the cookies.
* Note that doing so might move headers in the request, but * Note that doing so might move headers in the request, but
* the fields will stay coherent and the URI will not move. * the fields will stay coherent and the URI will not move.
* This should only be performed in the backend. * This should only be performed in the backend.
*/ */
if ((t->be->cookie_name || t->be->appsession_name || t->be->capture_name) if ((s->be->cookie_name || s->be->appsession_name || s->be->capture_name)
&& !(txn->flags & (TX_CLDENY|TX_CLTARPIT))) && !(txn->flags & (TX_CLDENY|TX_CLTARPIT)))
manage_client_side_cookies(t, req); manage_client_side_cookies(s, req);
/* /*
* 9: add X-Forwarded-For if either the frontend or the backend * 9: add X-Forwarded-For if either the frontend or the backend
* asks for it. * asks for it.
*/ */
if ((t->fe->options | t->be->options) & PR_O_FWDFOR) { if ((s->fe->options | s->be->options) & PR_O_FWDFOR) {
if (t->cli_addr.ss_family == AF_INET) { if (s->cli_addr.ss_family == AF_INET) {
/* Add an X-Forwarded-For header unless the source IP is /* Add an X-Forwarded-For header unless the source IP is
* in the 'except' network range. * in the 'except' network range.
*/ */
if ((!t->fe->except_mask.s_addr || if ((!s->fe->except_mask.s_addr ||
(((struct sockaddr_in *)&t->cli_addr)->sin_addr.s_addr & t->fe->except_mask.s_addr) (((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr & s->fe->except_mask.s_addr)
!= t->fe->except_net.s_addr) && != s->fe->except_net.s_addr) &&
(!t->be->except_mask.s_addr || (!s->be->except_mask.s_addr ||
(((struct sockaddr_in *)&t->cli_addr)->sin_addr.s_addr & t->be->except_mask.s_addr) (((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr & s->be->except_mask.s_addr)
!= t->be->except_net.s_addr)) { != s->be->except_net.s_addr)) {
int len; int len;
unsigned char *pn; unsigned char *pn;
pn = (unsigned char *)&((struct sockaddr_in *)&t->cli_addr)->sin_addr; pn = (unsigned char *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for /* Note: we rely on the backend to get the header name to be used for
* x-forwarded-for, because the header is really meant for the backends. * x-forwarded-for, because the header is really meant for the backends.
* However, if the backend did not specify any option, we have to rely * However, if the backend did not specify any option, we have to rely
* on the frontend's header name. * on the frontend's header name.
*/ */
if (t->be->fwdfor_hdr_len) { if (s->be->fwdfor_hdr_len) {
len = t->be->fwdfor_hdr_len; len = s->be->fwdfor_hdr_len;
memcpy(trash, t->be->fwdfor_hdr_name, len); memcpy(trash, s->be->fwdfor_hdr_name, len);
} else { } else {
len = t->fe->fwdfor_hdr_len; len = s->fe->fwdfor_hdr_len;
memcpy(trash, t->fe->fwdfor_hdr_name, len); memcpy(trash, s->fe->fwdfor_hdr_name, len);
} }
len += sprintf(trash + len, ": %d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]); len += sprintf(trash + len, ": %d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]);
@ -2189,14 +2184,14 @@ int process_request(struct session *t)
goto return_bad_req; goto return_bad_req;
} }
} }
else if (t->cli_addr.ss_family == AF_INET6) { else if (s->cli_addr.ss_family == AF_INET6) {
/* FIXME: for the sake of completeness, we should also support /* FIXME: for the sake of completeness, we should also support
* 'except' here, although it is mostly useless in this case. * 'except' here, although it is mostly useless in this case.
*/ */
int len; int len;
char pn[INET6_ADDRSTRLEN]; char pn[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, inet_ntop(AF_INET6,
(const void *)&((struct sockaddr_in6 *)(&t->cli_addr))->sin6_addr, (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
pn, sizeof(pn)); pn, sizeof(pn));
/* Note: we rely on the backend to get the header name to be used for /* Note: we rely on the backend to get the header name to be used for
@ -2204,12 +2199,12 @@ int process_request(struct session *t)
* However, if the backend did not specify any option, we have to rely * However, if the backend did not specify any option, we have to rely
* on the frontend's header name. * on the frontend's header name.
*/ */
if (t->be->fwdfor_hdr_len) { if (s->be->fwdfor_hdr_len) {
len = t->be->fwdfor_hdr_len; len = s->be->fwdfor_hdr_len;
memcpy(trash, t->be->fwdfor_hdr_name, len); memcpy(trash, s->be->fwdfor_hdr_name, len);
} else { } else {
len = t->fe->fwdfor_hdr_len; len = s->fe->fwdfor_hdr_len;
memcpy(trash, t->fe->fwdfor_hdr_name, len); memcpy(trash, s->fe->fwdfor_hdr_name, len);
} }
len += sprintf(trash + len, ": %s", pn); len += sprintf(trash + len, ": %s", pn);
@ -2223,23 +2218,23 @@ int process_request(struct session *t)
* 10: add "Connection: close" if needed and not yet set. * 10: add "Connection: close" if needed and not yet set.
* Note that we do not need to add it in case of HTTP/1.0. * Note that we do not need to add it in case of HTTP/1.0.
*/ */
if (!(t->flags & SN_CONN_CLOSED) && if (!(s->flags & SN_CONN_CLOSED) &&
((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) { ((s->fe->options | s->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) {
if ((unlikely(msg->sl.rq.v_l != 8) || if ((unlikely(msg->sl.rq.v_l != 8) ||
unlikely(req->data[msg->som + msg->sl.rq.v + 7] != '0')) && unlikely(req->data[msg->som + msg->sl.rq.v + 7] != '0')) &&
unlikely(http_header_add_tail2(req, &txn->req, &txn->hdr_idx, unlikely(http_header_add_tail2(req, &txn->req, &txn->hdr_idx,
"Connection: close", 17)) < 0) "Connection: close", 17)) < 0)
goto return_bad_req; goto return_bad_req;
t->flags |= SN_CONN_CLOSED; s->flags |= SN_CONN_CLOSED;
} }
/* Before we switch to data, was assignment set in manage_client_side_cookie? /* Before we switch to data, was assignment set in manage_client_side_cookie?
* If not assigned, perhaps we are balancing on url_param, but this is a * If not assigned, perhaps we are balancing on url_param, but this is a
* POST; and the parameters are in the body, maybe scan there to find our server. * POST; and the parameters are in the body, maybe scan there to find our server.
* (unless headers overflowed the buffer?) * (unless headers overflowed the buffer?)
*/ */
if (!(t->flags & (SN_ASSIGNED|SN_DIRECT)) && if (!(s->flags & (SN_ASSIGNED|SN_DIRECT)) &&
t->txn.meth == HTTP_METH_POST && t->be->url_param_name != NULL && s->txn.meth == HTTP_METH_POST && s->be->url_param_name != NULL &&
t->be->url_param_post_limit != 0 && !(req->flags & BF_FULL) && s->be->url_param_post_limit != 0 && !(req->flags & BF_FULL) &&
memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) { memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) {
/* are there enough bytes here? total == l || r || rlim ? /* are there enough bytes here? total == l || r || rlim ?
* len is unsigned, but eoh is int, * len is unsigned, but eoh is int,
@ -2272,7 +2267,7 @@ int process_request(struct session *t)
goto end_check_maybe_wait_for_body; goto end_check_maybe_wait_for_body;
} }
if (likely(len > t->be->url_param_post_limit)) { if (likely(len > s->be->url_param_post_limit)) {
/* nothing to do, we got enough */ /* nothing to do, we got enough */
} else { } else {
/* limit implies we are supposed to need this many bytes /* limit implies we are supposed to need this many bytes
@ -2302,8 +2297,8 @@ int process_request(struct session *t)
} }
} }
/* but limited to what we care about, maybe we don't expect any entity data (hint == 0) */ /* but limited to what we care about, maybe we don't expect any entity data (hint == 0) */
if (t->be->url_param_post_limit < hint) if (s->be->url_param_post_limit < hint)
hint = t->be->url_param_post_limit; hint = s->be->url_param_post_limit;
/* now do we really need to buffer more data? */ /* now do we really need to buffer more data? */
if (len < hint) { if (len < hint) {
buffer_write_dis(req); buffer_write_dis(req);
@ -2321,7 +2316,7 @@ int process_request(struct session *t)
************************************************************/ ************************************************************/
buffer_set_rlim(req, BUFSIZE); /* no more rewrite needed */ buffer_set_rlim(req, BUFSIZE); /* no more rewrite needed */
t->logs.tv_request = now; s->logs.tv_request = now;
/* When a connection is tarpitted, we use the tarpit timeout, /* When a connection is tarpitted, we use the tarpit timeout,
* which may be the same as the connect timeout if unspecified. * which may be the same as the connect timeout if unspecified.
@ -2329,46 +2324,32 @@ int process_request(struct session *t)
* eventually expire. We build the tarpit as an analyser. * eventually expire. We build the tarpit as an analyser.
*/ */
if (txn->flags & TX_CLTARPIT) { if (txn->flags & TX_CLTARPIT) {
buffer_flush(t->req); buffer_flush(s->req);
/* flush the request so that we can drop the connection early /* flush the request so that we can drop the connection early
* if the client closes first. * if the client closes first.
*/ */
buffer_write_dis(req); buffer_write_dis(req);
req->analysers |= AN_REQ_HTTP_TARPIT; req->analysers |= AN_REQ_HTTP_TARPIT;
req->analyse_exp = tick_add_ifset(now_ms, t->be->timeout.tarpit); req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.tarpit);
if (!req->analyse_exp) if (!req->analyse_exp)
req->analyse_exp = now_ms; req->analyse_exp = now_ms;
} }
/* OK let's go on with the BODY now */ /* OK let's go on with the BODY now */
goto end_of_headers; return 1;
return_bad_req: /* let's centralize all bad requests */ return_bad_req: /* let's centralize all bad requests */
txn->req.msg_state = HTTP_MSG_ERROR; txn->req.msg_state = HTTP_MSG_ERROR;
txn->status = 400; txn->status = 400;
req->analysers = 0; req->analysers = 0;
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_400)); stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
t->fe->failed_req++; s->fe->failed_req++;
return_prx_cond:
if (!(t->flags & SN_ERR_MASK))
t->flags |= SN_ERR_PRXCOND;
if (!(t->flags & SN_FINST_MASK))
t->flags |= SN_FINST_R;
return 0;
end_of_headers:
; // to keep gcc happy
}
/* Note: eventhough nobody should set an unknown flag, clearing them right now will return_prx_cond:
* probably reduce one day's debugging session. if (!(s->flags & SN_ERR_MASK))
*/ s->flags |= SN_ERR_PRXCOND;
#ifdef DEBUG_DEV if (!(s->flags & SN_FINST_MASK))
if (req->analysers & ~(AN_REQ_INSPECT | AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_BODY)) { s->flags |= SN_FINST_R;
fprintf(stderr, "FIXME !!!! unknown analysers flags %s:%d = 0x%08X\n",
__FILE__, __LINE__, req->analysers);
ABORT_NOW();
}
#endif
return 0; return 0;
} }

View File

@ -705,8 +705,8 @@ resync_stream_interface:
if (!tcp_inspect_request(s, s->req)) if (!tcp_inspect_request(s, s->req))
break; break;
if (s->req->analysers) if (s->req->analysers & AN_REQ_HTTP_HDR)
if (!process_request(s)) if (!http_process_request(s, s->req))
break; break;
if (s->req->analysers & AN_REQ_HTTP_TARPIT) if (s->req->analysers & AN_REQ_HTTP_TARPIT)