static enum VCLI_status_e varnish_ask_cli(const struct varnish *v, const char *cmd, char **repl) { int i; unsigned retval; char *r; if (cmd != NULL) { vtc_dump(v->vl, 4, "CLI TX", cmd, -1); i = write(v->cli_fd, cmd, strlen(cmd)); assert(i == strlen(cmd)); i = write(v->cli_fd, "\n", 1); assert(i == 1); } i = VCLI_ReadResult(v->cli_fd, &retval, &r, 20.0); if (i != 0) { vtc_log(v->vl, 0, "CLI failed (%s) = %d %u %s", cmd, i, retval, r); return ((enum VCLI_status_e)retval); } assert(i == 0); vtc_log(v->vl, 3, "CLI RX %u", retval); vtc_dump(v->vl, 4, "CLI RX", r, -1); if (repl != NULL) *repl = r; else free(r); return ((enum VCLI_status_e)retval); }
static void http_swallow_body(struct http *hp, char * const *hh, int body) { char *p, *q; int i, l, ll; ll = 0; p = http_find_header(hh, "content-length"); if (p != NULL) { l = strtoul(p, NULL, 0); hp->body = hp->rxbuf + hp->prxbuf; http_rxchar(hp, l); vtc_dump(hp->vl, 4, "body", hp->body); sprintf(hp->bodylen, "%d", l); return; } p = http_find_header(hh, "transfer-encoding"); if (p != NULL && !strcmp(p, "chunked")) { hp->body = hp->rxbuf + hp->prxbuf; while (1) { l = hp->prxbuf; do http_rxchar(hp, 1); while (hp->rxbuf[hp->prxbuf - 1] != '\n'); vtc_dump(hp->vl, 4, "len", hp->rxbuf + l); i = strtoul(hp->rxbuf + l, &q, 16); assert(q != hp->rxbuf + l); assert(*q == '\0' || vct_islws(*q)); hp->prxbuf = l; if (i > 0) { ll += i; http_rxchar(hp, i); vtc_dump(hp->vl, 4, "chunk", hp->rxbuf + l); } l = hp->prxbuf; http_rxchar(hp, 2); assert(vct_iscrlf(hp->rxbuf[l])); assert(vct_iscrlf(hp->rxbuf[l + 1])); hp->prxbuf = l; hp->rxbuf[l] = '\0'; if (i == 0) break; } vtc_dump(hp->vl, 4, "body", hp->body); sprintf(hp->bodylen, "%d", ll); return; } if (body) { hp->body = hp->rxbuf + hp->prxbuf; do { i = http_rxchar_eof(hp, 1); ll += i; } while (i > 0); vtc_dump(hp->vl, 4, "rxeof", hp->body); } sprintf(hp->bodylen, "%d", ll); }
static void * varnish_thread(void *priv) { struct varnish *v; char buf[BUFSIZ]; struct pollfd *fds, fd; int i; CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC); (void)VTCP_nonblocking(v->fds[0]); while (1) { fds = &fd; memset(fds, 0, sizeof *fds); fds->fd = v->fds[0]; fds->events = POLLIN; i = poll(fds, 1, 1000); if (i == 0) continue; if (fds->revents & (POLLERR|POLLHUP)) break; i = read(v->fds[0], buf, sizeof buf - 1); if (i <= 0) break; buf[i] = '\0'; vtc_dump(v->vl, 3, "debug", buf, -2); } return (NULL); }
static void http_rxhdr(struct http *hp) { int i; char *p; CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); hp->prxbuf = 0; hp->body = NULL; while (1) { (void)http_rxchar(hp, 1, 0); p = hp->rxbuf + hp->prxbuf - 1; for (i = 0; p > hp->rxbuf; p--) { if (*p != '\n') break; if (p - 1 > hp->rxbuf && p[-1] == '\r') p--; if (++i == 2) break; } if (i == 2) break; } vtc_dump(hp->vl, 4, "rxhdr", hp->rxbuf, -1); }
void * vtc_record(struct vtclog *vl, int fd, struct vsb *vsb) { char buf[65536]; struct pollfd fds[1]; int i; (void)VTCP_nonblocking(fd); while (1) { memset(fds, 0, sizeof fds); fds->fd = fd; fds->events = POLLIN; i = poll(fds, 1, 10000); if (i == 0) continue; if (fds->revents & POLLIN) { i = read(fd, buf, sizeof buf - 1); if (i > 0) { if (vsb != NULL) VSB_bcat(vsb, buf, i); buf[i] = '\0'; vtc_dump(vl, 3, "debug", buf, -2); } } if (fds->revents & (POLLERR|POLLHUP)) { vtc_log(vl, 4, "STDOUT poll 0x%x", fds->revents); break; } } return (NULL); }
static void cmd_err_shell(CMD_ARGS) { (void)priv; (void)cmd; struct vsb *vsb; FILE *fp; int r, c; if (av == NULL) return; AN(av[1]); AN(av[2]); AZ(av[3]); vsb = VSB_new_auto(); AN(vsb); vtc_dump(vl, 4, "cmd", av[2], -1); fp = popen(av[2], "r"); if (fp == NULL) vtc_log(vl, 0, "popen fails: %s", strerror(errno)); do { c = getc(fp); if (c != EOF) VSB_putc(vsb, c); } while (c != EOF); r = pclose(fp); vtc_log(vl, 4, "Status = %d", WEXITSTATUS(r)); if (WIFSIGNALED(r)) vtc_log(vl, 4, "Signal = %d", WTERMSIG(r)); if (WEXITSTATUS(r) == 0) { vtc_log(vl, 0, "expected error from shell"); } AZ(VSB_finish(vsb)); vtc_dump(vl, 4, "stdout", VSB_data(vsb), VSB_len(vsb)); if (strstr(VSB_data(vsb), av[1]) == NULL) vtc_log(vl, 0, "Did not find expected string: (\"%s\")", av[1]); else vtc_log(vl, 4, "Found expected string: (\"%s\")", av[1]); VSB_delete(vsb); }
static void cmd_http_gunzip_body(CMD_ARGS) { int i; z_stream vz; struct http *hp; char *p; unsigned l; (void)av; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); memset(&vz, 0, sizeof vz); AN(hp->body); if (hp->body[0] != (char)0x1f || hp->body[1] != (char)0x8b) vtc_log(hp->vl, hp->fatal, "Gunzip error: Body lacks gzip magics"); vz.next_in = TRUST_ME(hp->body); vz.avail_in = hp->bodyl; l = hp->bodyl * 10; p = calloc(l, 1); AN(p); vz.next_out = TRUST_ME(p); vz.avail_out = l; assert(Z_OK == inflateInit2(&vz, 31)); i = inflate(&vz, Z_FINISH); assert(vz.total_out < l); hp->bodyl = vz.total_out; memcpy(hp->body, p, hp->bodyl); free(p); vtc_log(hp->vl, 3, "new bodylen %u", hp->bodyl); vtc_dump(hp->vl, 4, "body", hp->body, hp->bodyl); bprintf(hp->bodylen, "%u", hp->bodyl); vtc_log(hp->vl, 4, "startbit = %ju %ju/%ju", (uintmax_t)vz.start_bit, (uintmax_t)vz.start_bit >> 3, (uintmax_t)vz.start_bit & 7); vtc_log(hp->vl, 4, "lastbit = %ju %ju/%ju", (uintmax_t)vz.last_bit, (uintmax_t)vz.last_bit >> 3, (uintmax_t)vz.last_bit & 7); vtc_log(hp->vl, 4, "stopbit = %ju %ju/%ju", (uintmax_t)vz.stop_bit, (uintmax_t)vz.stop_bit >> 3, (uintmax_t)vz.stop_bit & 7); if (i != Z_STREAM_END) vtc_log(hp->vl, hp->fatal, "Gunzip error = %d (%s) in:%jd out:%jd", i, vz.msg, (intmax_t)vz.total_in, (intmax_t)vz.total_out); assert(Z_OK == inflateEnd(&vz)); hp->body[hp->bodyl] = '\0'; }
static void http_write(const struct http *hp, int lvl, const char *pfx) { int l; AZ(VSB_finish(hp->vsb)); vtc_dump(hp->vl, lvl, pfx, VSB_data(hp->vsb), VSB_len(hp->vsb)); l = write(hp->fd, VSB_data(hp->vsb), VSB_len(hp->vsb)); if (l != VSB_len(hp->vsb)) vtc_log(hp->vl, hp->fatal, "Write failed: (%d vs %d) %s", l, VSB_len(hp->vsb), strerror(errno)); }
static void http_write(const struct http *hp, int lvl, const char *pfx) { int l; vsb_finish(hp->vsb); AZ(vsb_overflowed(hp->vsb)); vtc_dump(hp->vl, lvl, pfx, vsb_data(hp->vsb)); l = write(hp->fd, vsb_data(hp->vsb), vsb_len(hp->vsb)); if (l != vsb_len(hp->vsb)) vtc_log(hp->vl, 0, "Write failed: %s", strerror(errno)); }
static int http_rxchunk(struct http *hp) { char *q; int l, i; l = hp->prxbuf; do (void)http_rxchar(hp, 1, 0); while (hp->rxbuf[hp->prxbuf - 1] != '\n'); vtc_dump(hp->vl, 4, "len", hp->rxbuf + l, -1); i = strtoul(hp->rxbuf + l, &q, 16); bprintf(hp->chunklen, "%d", i); if ((q == hp->rxbuf + l) || (*q != '\0' && !vct_islws(*q))) { vtc_log(hp->vl, hp->fatal, "chunked fail %02x @ %d", *q, q - (hp->rxbuf + l)); } assert(q != hp->rxbuf + l); assert(*q == '\0' || vct_islws(*q)); hp->prxbuf = l; if (i > 0) { (void)http_rxchar(hp, i, 0); vtc_dump(hp->vl, 4, "chunk", hp->rxbuf + l, i); } l = hp->prxbuf; (void)http_rxchar(hp, 2, 0); if(!vct_iscrlf(hp->rxbuf[l])) vtc_log(hp->vl, hp->fatal, "Wrong chunk tail[0] = %02x", hp->rxbuf[l] & 0xff); if(!vct_iscrlf(hp->rxbuf[l + 1])) vtc_log(hp->vl, hp->fatal, "Wrong chunk tail[1] = %02x", hp->rxbuf[l + 1] & 0xff); hp->prxbuf = l; hp->rxbuf[l] = '\0'; return (i); }
static void http_swallow_body(struct http *hp, char * const *hh, int body) { char *p; int i, l, ll; ll = 0; p = http_find_header(hh, "content-length"); if (p != NULL) { hp->body = hp->rxbuf + hp->prxbuf; l = strtoul(p, NULL, 0); (void)http_rxchar(hp, l, 0); vtc_dump(hp->vl, 4, "body", hp->body, l); hp->bodyl = l; sprintf(hp->bodylen, "%d", l); return; } p = http_find_header(hh, "transfer-encoding"); if (p != NULL && !strcmp(p, "chunked")) { while (http_rxchunk(hp) != 0) continue; vtc_dump(hp->vl, 4, "body", hp->body, ll); ll = hp->rxbuf + hp->prxbuf - hp->body; hp->bodyl = ll; sprintf(hp->bodylen, "%d", ll); return; } if (body) { hp->body = hp->rxbuf + hp->prxbuf; do { i = http_rxchar(hp, 1, 1); ll += i; } while (i > 0); vtc_dump(hp->vl, 4, "rxeof", hp->body, ll); } hp->bodyl = ll; sprintf(hp->bodylen, "%d", ll); }
static void cmd_shell(CMD_ARGS) { (void)priv; (void)cmd; int r; if (av == NULL) return; AN(av[1]); AZ(av[2]); vtc_dump(vl, 4, "shell", av[1], -1); r = system(av[1]); AZ(WEXITSTATUS(r)); }
static void cmd_http_send(CMD_ARGS) { struct http *hp; int i; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AZ(av[2]); vtc_dump(hp->vl, 4, "send", av[1]); i = write(hp->fd, av[1], strlen(av[1])); assert(i == strlen(av[1])); }
static void cmd_http_send(CMD_ARGS) { struct http *hp; int i; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AZ(av[2]); vtc_dump(hp->vl, 4, "send", av[1], -1); i = write(hp->fd, av[1], strlen(av[1])); if (i != strlen(av[1])) vtc_log(hp->vl, hp->fatal, "Write error in http_send(): %s", strerror(errno)); }
static void cmd_http_recv(CMD_ARGS) { struct http *hp; int i, n; char u[32]; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AZ(av[2]); n = strtoul(av[1], NULL, 0); while (n > 0) { i = read(hp->fd, u, n > 32 ? 32 : n); if (i > 0) vtc_dump(hp->vl, 4, "recv", u, i); else vtc_log(hp->vl, hp->fatal, "recv() got %d (%s)", i, strerror(errno)); n -= i; } }
static void cmd_http_send_n(CMD_ARGS) { struct http *hp; int i, n, l; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AN(av[2]); AZ(av[3]); n = strtoul(av[1], NULL, 0); vtc_dump(hp->vl, 4, "send_n", av[2], -1); l = strlen(av[2]); while (n--) { i = write(hp->fd, av[2], l); if (i != l) vtc_log(hp->vl, hp->fatal, "Write error in http_send(): %s", strerror(errno)); } }
static void http_splitheader(struct http *hp, int req) { char *p, *q, **hh; int n; char buf[20]; CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); if (req) { memset(hp->req, 0, sizeof hp->req); hh = hp->req; } else { memset(hp->resp, 0, sizeof hp->resp); hh = hp->resp; } n = 0; p = hp->rxbuf; /* REQ/PROTO */ while (vct_islws(*p)) p++; hh[n++] = p; while (!vct_islws(*p)) p++; assert(!vct_iscrlf(*p)); *p++ = '\0'; /* URL/STATUS */ while (vct_issp(*p)) /* XXX: H space only */ p++; assert(!vct_iscrlf(*p)); hh[n++] = p; while (!vct_islws(*p)) p++; if (vct_iscrlf(*p)) { hh[n++] = NULL; q = p; p += vct_skipcrlf(p); *q = '\0'; } else { *p++ = '\0'; /* PROTO/MSG */ while (vct_issp(*p)) /* XXX: H space only */ p++; hh[n++] = p; while (!vct_iscrlf(*p)) p++; q = p; p += vct_skipcrlf(p); *q = '\0'; } assert(n == 3); while (*p != '\0') { assert(n < MAX_HDR); if (vct_iscrlf(*p)) break; hh[n++] = p++; while (*p != '\0' && !vct_iscrlf(*p)) p++; q = p; p += vct_skipcrlf(p); *q = '\0'; } p += vct_skipcrlf(p); assert(*p == '\0'); for (n = 0; n < 3 || hh[n] != NULL; n++) { sprintf(buf, "http[%2d] ", n); vtc_dump(hp->vl, 4, buf, hh[n], -1); } }