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); }
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; } } }
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]); } } }
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); }
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); }