Exemple #1
0
void dump_VSL_split(struct req *req, char *p, unsigned mlen, const void *ptr, size_t l, char * suf){
	
	char *p2       = p + VMOD_DUMP_KEY_LEN;
	unsigned mlen2 = mlen - VMOD_DUMP_KEY_LEN;
	size_t length  = l;
	void *c_ptr    = (void*)ptr;
	txt t;
	t.b = p;
	unsigned slen = strlen(suf);
	assert(slen <= 2);
	do{
		if(mlen2 > length){
			memcpy(p2, c_ptr, length);
			t.e = t.b + length + VMOD_DUMP_KEY_LEN;
			if(slen > 0) {
				memcpy(p2 + length, suf, slen);
				t.e += slen;
			}
			VSLbt(req->vsl, SLT_Debug,t);
			break;
		}
		memcpy(p2, c_ptr, mlen2);
		t.e = t.b + mlen2 + VMOD_DUMP_KEY_LEN;
		if(slen > 0) {
			memcpy(p2 + mlen2, suf, slen);
			t.e += slen;
		}
		VSLbt(req->vsl, SLT_Debug,t);
		c_ptr  += mlen2;
		length -= mlen2;
		
	}while(1);
}
Exemple #2
0
void
http_CopyHome(const struct http *hp)
{
	unsigned u, l;
	char *p;

	for (u = 0; u < hp->nhd; u++) {
		if (hp->hd[u].b == NULL)
			continue;
		if (hp->hd[u].b >= hp->ws->s && hp->hd[u].e <= hp->ws->e) {
			http_VSLH(hp, u);
			continue;
		}
		l = Tlen(hp->hd[u]);
		p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
		if (p != NULL) {
			http_VSLH(hp, u);
			hp->hd[u].b = p;
			hp->hd[u].e = p + l;
		} else {
			/* XXX This leaves a slot empty */
			VSC_C_main->losthdr++;
			VSLbt(hp->vsl, SLT_LostHeader, hp->hd[u]);
			hp->hd[u].b = NULL;
			hp->hd[u].e = NULL;
		}
	}
}
Exemple #3
0
static void
http_filterfields(struct http *to, const struct http *fm, unsigned how)
{
	unsigned u;

	CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
	to->nhd = HTTP_HDR_FIRST;
	to->status = fm->status;
	for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
		if (fm->hd[u].b == NULL)
			continue;
		if (fm->hdf[u] & HDF_FILTER)
			continue;
#define HTTPH(a, b, c) \
		if (((c) & how) && http_IsHdr(&fm->hd[u], (b))) \
			continue;
#include "tbl/http_headers.h"
#undef HTTPH
		Tcheck(fm->hd[u]);
		if (to->nhd < to->shd) {
			to->hd[to->nhd] = fm->hd[u];
			to->hdf[to->nhd] = 0;
			to->nhd++;
		} else  {
			VSC_C_main->losthdr++;
			VSLbt(to->vsl, SLT_LostHeader, fm->hd[u]);
		}
	}
}
Exemple #4
0
void
http_VSLH(const struct http *hp, unsigned hdr)
{

	AN(hp->vsl);
	AN(hp->vsl->wid & (VSL_CLIENTMARKER|VSL_BACKENDMARKER));
	VSLbt(hp->vsl, http2shmlog(hp, hdr), hp->hd[hdr]);
}
uint16_t
http_DissectResponse(struct http *hp, const struct http_conn *htc)
{
	int j;
	uint16_t retval = 0;
	char *p;


	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
	hp->logtag = HTTP_Rx;

	if (http_splitline(hp, htc,
	    HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_RESPONSE))
		retval = 503;

	if (retval == 0 && memcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.", 7))
		retval = 503;

	if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
		retval = 503;

	if (retval == 0) {
		hp->status = 0;
		p = hp->hd[HTTP_HDR_STATUS].b;
		for (j = 100; j != 0; j /= 10) {
			if (!vct_isdigit(*p)) {
				retval = 503;
				break;
			}
			hp->status += (uint16_t)(j * (*p - '0'));
			p++;
		}
		if (*p != '\0')
			retval = 503;
	}

	if (retval != 0) {
		VSLbt(hp->vsl, SLT_HttpGarbage, htc->rxbuf);
		assert(retval >= 100 && retval <= 999);
		hp->status = retval;
	} else {
		http_ProtoVer(hp);
	}

	if (hp->hd[HTTP_HDR_RESPONSE].b == NULL ||
	    !Tlen(hp->hd[HTTP_HDR_RESPONSE])) {
		/* Backend didn't send a response string, use the standard */
		hp->hd[HTTP_HDR_RESPONSE].b =
		    TRUST_ME(http_StatusMessage(hp->status));
		hp->hd[HTTP_HDR_RESPONSE].e =
		    strchr(hp->hd[HTTP_HDR_RESPONSE].b, '\0');
	}
	return (retval);
}
static void
http_VSLH_del(const struct http *hp, unsigned hdr)
{
	int i;

	if (hp->vsl != NULL) {
		/* We don't support unsetting stuff in the first line */
		assert (hdr >= HTTP_HDR_FIRST);
		AN(hp->vsl->wid & (VSL_CLIENTMARKER|VSL_BACKENDMARKER));
		i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
		i += hp->logtag;
		VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
	}
}
static void
http_VSLH(const struct http *hp, unsigned hdr)
{
	int i;

	if (hp->vsl != NULL) {
		AN(hp->vsl->wid & (VSL_CLIENTMARKER|VSL_BACKENDMARKER));
		i = hdr;
		if (i > HTTP_HDR_FIRST)
			i = HTTP_HDR_FIRST;
		i += hp->logtag;
		VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
	}
}
uint16_t
HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
{
	uint16_t retval = 0;
	char *p;


	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

	if (htc_splitline(hp, htc, 0))
		retval = 503;

	if (retval == 0 && memcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.", 7))
		retval = 503;

	if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
		retval = 503;

	if (retval == 0) {
		p = hp->hd[HTTP_HDR_STATUS].b;

		if (p[0] >= '1' && p[0] <= '9' &&
		    p[1] >= '0' && p[1] <= '9' &&
		    p[2] >= '0' && p[2] <= '9')
			hp->status =
			    100 * (p[0] - '0') + 10 * (p[1] - '0') + p[2] - '0';
		else
			retval = 503;
	}

	if (retval != 0) {
		VSLbt(hp->vsl, SLT_HttpGarbage, htc->rxbuf);
		assert(retval >= 100 && retval <= 999);
		hp->status = retval;
	} else
		htc_proto_ver(hp);

	if (hp->hd[HTTP_HDR_RESPONSE].b == NULL ||
	    !Tlen(hp->hd[HTTP_HDR_RESPONSE])) {
		/* Backend didn't send a response string, use the standard */
		hp->hd[HTTP_HDR_RESPONSE].b =
		    TRUST_ME(http_StatusMessage(hp->status));
		hp->hd[HTTP_HDR_RESPONSE].e =
		    strchr(hp->hd[HTTP_HDR_RESPONSE].b, '\0');
	}
	return (retval);
}
vmod_log(const struct vrt_ctx *ctx, const char *fmt, ...)
{
	unsigned u;
	va_list ap;
	txt t;

	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
	u = WS_Reserve(ctx->ws, 0);
	t.b = ctx->ws->f;
	va_start(ap, fmt);
	t.e = VRT_StringList(t.b, u, fmt, ap);
	va_end(ap);
	if (t.e != NULL) {
		assert(t.e > t.b);
		t.e--;
		VSLbt(ctx->vsl, SLT_VCL_Log, t);
	}
	WS_Release(ctx->ws, 0);
}
uint16_t
HTTP1_DissectRequest(struct req *req)
{
	struct http_conn *htc;
	struct http *hp;
	uint16_t retval;
	char *b, *e;

	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	htc = req->htc;
	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	hp = req->http;
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

	retval = htc_splitline(hp, htc, 1);
	if (retval != 0) {
		VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
		return (retval);
	}
	htc_proto_ver(hp);

	retval = htc_request_check_host_hdr(hp);
	if (retval != 0) {
		return (retval);
	}

	/* RFC2616, section 5.2, point 1 */
	if (!strncasecmp(hp->hd[HTTP_HDR_URL].b, "http://", 7)) {
		b = e = hp->hd[HTTP_HDR_URL].b + 7;
		while (*e != '/' && *e != '\0')
			e++;
		if (*e == '/') {
			http_Unset(hp, H_Host);
			http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b);
			hp->hd[HTTP_HDR_URL].b = e;
		}
	}

	return (retval);
}
Exemple #11
0
uint16_t
http_DissectRequest(const struct sess *sp)
{
	struct http_conn *htc;
	struct http *hp;
	uint16_t retval;

	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
	htc = sp->req->htc;
	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	hp = sp->req->http;
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

	hp->logtag = HTTP_Rx;

	retval = http_splitline(hp, htc,
	    HTTP_HDR_REQ, HTTP_HDR_URL, HTTP_HDR_PROTO);
	if (retval != 0) {
		VSLbt(sp->req->vsl, SLT_HttpGarbage, htc->rxbuf);
		return (retval);
	}
	http_ProtoVer(hp);
	return (retval);
}
static enum req_fsm_nxt
http1_dissect(struct worker *wrk, struct req *req)
{
	const char *r_100 = "HTTP/1.1 100 Continue\r\n\r\n";
	const char *r_400 = "HTTP/1.1 400 Bad Request\r\n\r\n";
	const char *r_417 = "HTTP/1.1 417 Expectation Failed\r\n\r\n";
	char *p;
	ssize_t r;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);

	/* Allocate a new vxid now that we know we'll need it. */
	AZ(req->vsl->wid);
	req->vsl->wid = VXID_Get(wrk, VSL_CLIENTMARKER);

	VSLb(req->vsl, SLT_Begin, "req %u rxreq", VXID(req->sp->vxid));
	VSL(SLT_Link, req->sp->vxid, "req %u rxreq", VXID(req->vsl->wid));
	AZ(isnan(req->t_first)); /* First byte timestamp set by http1_wait */
	AZ(isnan(req->t_req));	 /* Complete req rcvd set by http1_wait */
	req->t_prev = req->t_first;
	VSLb_ts_req(req, "Start", req->t_first);
	VSLb_ts_req(req, "Req", req->t_req);

	/* Borrow VCL reference from worker thread */
	VCL_Refresh(&wrk->vcl);
	req->vcl = wrk->vcl;
	wrk->vcl = NULL;

	HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
	req->err_code = HTTP1_DissectRequest(req->htc, req->http);

	/* If we could not even parse the request, just close */
	if (req->err_code != 0) {
		VSLbt(req->vsl, SLT_HttpGarbage, req->htc->rxbuf);
		wrk->stats->client_req_400++;
		r = write(req->sp->fd, r_400, strlen(r_400));
		if (r > 0)
			req->acct.resp_hdrbytes += r;
		SES_Close(req->sp, SC_RX_JUNK);
		return (REQ_FSM_DONE);
	}

	assert (req->req_body_status == REQ_BODY_INIT);

	if (req->htc->body_status == BS_CHUNKED) {
		req->req_body_status = REQ_BODY_WITHOUT_LEN;
	} else if (req->htc->body_status == BS_LENGTH) {
		req->req_body_status = REQ_BODY_WITH_LEN;
	} else if (req->htc->body_status == BS_NONE) {
		req->req_body_status = REQ_BODY_NONE;
	} else if (req->htc->body_status == BS_EOF) {
		req->req_body_status = REQ_BODY_WITHOUT_LEN;
	} else {
		WRONG("Unknown req.body_length situation");
	}

	if (http_GetHdr(req->http, H_Expect, &p)) {
		if (strcasecmp(p, "100-continue")) {
			wrk->stats->client_req_417++;
			req->err_code = 417;
			r = write(req->sp->fd, r_417, strlen(r_417));
			if (r > 0)
				req->resp_hdrbytes += r;
			SES_Close(req->sp, SC_RX_JUNK);
			return (REQ_FSM_DONE);
		}
		r = write(req->sp->fd, r_100, strlen(r_100));
		if (r > 0)
			req->acct.resp_hdrbytes += r;
		if (r != strlen(r_100)) {
			SES_Close(req->sp, SC_REM_CLOSE);
			return (REQ_FSM_DONE);
		}
		http_Unset(req->http, H_Expect);
	}

	wrk->stats->client_req++;
	wrk->stats->s_req++;

	AZ(req->err_code);
	req->ws_req = WS_Snapshot(req->ws);

	assert(req->req_body_status != REQ_BODY_INIT);

	HTTP_Copy(req->http0, req->http);	// For ESI & restart

	return (REQ_FSM_MORE);
}