static void dyn_dir_init(VRT_CTX, struct xyzzy_debug_dyn *dyn, VCL_STRING addr, VCL_STRING port, VCL_PROBE probe) { struct addrinfo hints, *res = NULL; struct suckaddr *sa; VCL_BACKEND dir, dir2; struct vrt_backend vrt; CHECK_OBJ_NOTNULL(dyn, VMOD_DEBUG_DYN_MAGIC); XXXAN(addr); XXXAN(port); INIT_OBJ(&vrt, VRT_BACKEND_MAGIC); vrt.port = port; vrt.vcl_name = dyn->vcl_name; vrt.hosthdr = addr; vrt.probe = probe; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; AZ(getaddrinfo(addr, port, &hints, &res)); XXXAZ(res->ai_next); sa = VSA_Malloc(res->ai_addr, res->ai_addrlen); AN(sa); if (VSA_Get_Proto(sa) == AF_INET) { vrt.ipv4_addr = addr; vrt.ipv4_suckaddr = sa; } else if (VSA_Get_Proto(sa) == AF_INET6) { vrt.ipv6_addr = addr; vrt.ipv6_suckaddr = sa; } else WRONG("Wrong proto family"); freeaddrinfo(res); dir = VRT_new_backend(ctx, &vrt); AN(dir); /* * NB: A real dynamic backend should not replace the previous * instance if the new one is identical. We do it here because * the d* tests requires a replacement. */ AZ(pthread_mutex_lock(&dyn->mtx)); dir2 = dyn->dir; dyn->dir = dir; AZ(pthread_mutex_unlock(&dyn->mtx)); if (dir2 != NULL) VRT_delete_backend(ctx, &dir2); free(sa); }
int vtc_send_proxy(int fd, int version, const struct suckaddr *sac, const struct suckaddr *sas) { struct vsb *vsb; char hc[VTCP_ADDRBUFSIZE]; char pc[VTCP_PORTBUFSIZE]; char hs[VTCP_ADDRBUFSIZE]; char ps[VTCP_PORTBUFSIZE]; int i, len; int proto; AN(sac); AN(sas); assert(version == 1 || version == 2); vsb = VSB_new_auto(); AN(vsb); proto = VSA_Get_Proto(sas); assert(proto == PF_INET6 || proto == PF_INET); if (version == 1) { VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig)); if (proto == PF_INET6) VSB_printf(vsb, " TCP6 "); else if (proto == PF_INET) VSB_printf(vsb, " TCP4 "); VTCP_name(sac, hc, sizeof(hc), pc, sizeof(pc)); VTCP_name(sas, hs, sizeof(hs), ps, sizeof(ps)); VSB_printf(vsb, "%s %s %s %s\r\n", hc, hs, pc, ps); } else if (version == 2) { VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig)); VSB_putc(vsb, 0x21); if (proto == PF_INET6) { VSB_putc(vsb, 0x21); VSB_putc(vsb, 0x00); VSB_putc(vsb, 0x24); } else if (proto == PF_INET) { VSB_putc(vsb, 0x11); VSB_putc(vsb, 0x00); VSB_putc(vsb, 0x0c); } vpx_enc_addr(vsb, proto, sac); vpx_enc_addr(vsb, proto, sas); vpx_enc_port(vsb, sac); vpx_enc_port(vsb, sas); } else WRONG("Wrong proxy version"); AZ(VSB_finish(vsb)); len = VSB_len(vsb); i = write(fd, VSB_data(vsb), len); VSB_delete(vsb); return (i != len); }
int VTCP_bind(const struct suckaddr *sa, const char **errp) { int sd, val, e; socklen_t sl; const struct sockaddr *so; int proto; if (errp != NULL) *errp = NULL; proto = VSA_Get_Proto(sa); sd = socket(proto, SOCK_STREAM, 0); if (sd < 0) { if (errp != NULL) *errp = "socket(2)"; return (-1); } val = 1; if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val) != 0) { if (errp != NULL) *errp = "setsockopt(SO_REUSEADDR, 1)"; e = errno; AZ(close(sd)); errno = e; return (-1); } #ifdef IPV6_V6ONLY /* forcibly use separate sockets for IPv4 and IPv6 */ val = 1; if (proto == AF_INET6 && setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof val) != 0) { if (errp != NULL) *errp = "setsockopt(IPV6_V6ONLY, 1)"; e = errno; AZ(close(sd)); errno = e; return (-1); } #endif so = VSA_Get_Sockaddr(sa, &sl); if (bind(sd, so, sl) != 0) { if (errp != NULL) *errp = "bind(2)"; e = errno; AZ(close(sd)); errno = e; return (-1); } return (sd); }
static void vbp_poke(struct vbp_target *vt) { int s, tmo, i, proxy_header, err; vtim_real t_start, t_now, t_end; unsigned rlen, resp; char buf[8192], *p; struct pollfd pfda[1], *pfd = pfda; const struct suckaddr *sa; t_start = t_now = VTIM_real(); t_end = t_start + vt->timeout; s = VTP_Open(vt->tcp_pool, t_end - t_now, (const void **)&sa, &err); if (s < 0) { bprintf(vt->resp_buf, "Open error %d (%s)", err, strerror(err)); Lck_Lock(&vbp_mtx); if (vt->backend) VBE_Connect_Error(vt->backend->vsc, err); Lck_Unlock(&vbp_mtx); return; } i = VSA_Get_Proto(sa); if (VSA_Compare(sa, bogo_ip) == 0) vt->good_unix |= 1; else if (i == AF_INET) vt->good_ipv4 |= 1; else if (i == AF_INET6) vt->good_ipv6 |= 1; else WRONG("Wrong probe protocol family"); t_now = VTIM_real(); tmo = (int)round((t_end - t_now) * 1e3); if (tmo <= 0) { bprintf(vt->resp_buf, "Open timeout %.3fs exceeded by %.3fs", vt->timeout, t_now - t_end); VTCP_close(&s); return; } Lck_Lock(&vbp_mtx); if (vt->backend != NULL) proxy_header = vt->backend->proxy_header; else proxy_header = -1; Lck_Unlock(&vbp_mtx); if (proxy_header < 0) { bprintf(vt->resp_buf, "%s", "No backend"); VTCP_close(&s); return; } /* Send the PROXY header */ assert(proxy_header <= 2); if (proxy_header == 1) { if (vbp_write_proxy_v1(vt, &s) != 0) return; } else if (proxy_header == 2 && vbp_write(vt, &s, vbp_proxy_local, sizeof vbp_proxy_local) != 0) return; /* Send the request */ if (vbp_write(vt, &s, vt->req, vt->req_len) != 0) return; vt->good_xmit |= 1; pfd->fd = s; rlen = 0; while (1) { pfd->events = POLLIN; pfd->revents = 0; tmo = (int)round((t_end - t_now) * 1e3); if (tmo > 0) i = poll(pfd, 1, tmo); if (i == 0) { vt->err_recv |= 1; bprintf(vt->resp_buf, "Poll error %d (%s)", errno, strerror(errno)); VTCP_close(&s); return; } if (tmo <= 0) { bprintf(vt->resp_buf, "Poll (read) timeout %.3fs exceeded by %.3fs", vt->timeout, t_now - t_end); VTCP_close(&s); return; } if (rlen < sizeof vt->resp_buf) i = read(s, vt->resp_buf + rlen, sizeof vt->resp_buf - rlen); else i = read(s, buf, sizeof buf); if (i <= 0) { if (i < 0) bprintf(vt->resp_buf, "Read error %d (%s)", errno, strerror(errno)); break; } rlen += i; } VTCP_close(&s); if (i < 0) { /* errno reported above */ vt->err_recv |= 1; return; } if (rlen == 0) { bprintf(vt->resp_buf, "%s", "Empty response"); return; } /* So we have a good receive ... */ t_now = VTIM_real(); vt->last = t_now - t_start; vt->good_recv |= 1; /* Now find out if we like the response */ vt->resp_buf[sizeof vt->resp_buf - 1] = '\0'; p = strchr(vt->resp_buf, '\r'); if (p != NULL) *p = '\0'; p = strchr(vt->resp_buf, '\n'); if (p != NULL) *p = '\0'; i = sscanf(vt->resp_buf, "HTTP/%*f %u ", &resp); if (i == 1 && resp == vt->exp_status) vt->happy |= 1; }
static void vbp_poke(struct vbp_target *vt) { int s, tmo, i; double t_start, t_now, t_end; unsigned rlen, resp; char buf[8192], *p; struct pollfd pfda[1], *pfd = pfda; const struct suckaddr *sa; t_start = t_now = VTIM_real(); t_end = t_start + vt->timeout; s = VBT_Open(vt->tcp_pool, t_end - t_now, &sa); if (s < 0) { /* Got no connection: failed */ return; } i = VSA_Get_Proto(sa); if (i == AF_INET) vt->good_ipv4 |= 1; else if(i == AF_INET6) vt->good_ipv6 |= 1; else WRONG("Wrong probe protocol family"); t_now = VTIM_real(); tmo = (int)round((t_end - t_now) * 1e3); if (tmo <= 0) { /* Spent too long time getting it */ VTCP_close(&s); return; } /* Send the request */ i = write(s, vt->req, vt->req_len); if (i != vt->req_len) { if (i < 0) vt->err_xmit |= 1; VTCP_close(&s); return; } vt->good_xmit |= 1; pfd->fd = s; rlen = 0; do { pfd->events = POLLIN; pfd->revents = 0; tmo = (int)round((t_end - t_now) * 1e3); if (tmo > 0) i = poll(pfd, 1, tmo); if (i == 0 || tmo <= 0) { if (i == 0) vt->err_recv |= 1; VTCP_close(&s); return; } if (rlen < sizeof vt->resp_buf) i = read(s, vt->resp_buf + rlen, sizeof vt->resp_buf - rlen); else i = read(s, buf, sizeof buf); rlen += i; } while (i > 0); VTCP_close(&s); if (i < 0) { vt->err_recv |= 1; return; } if (rlen == 0) return; /* So we have a good receive ... */ t_now = VTIM_real(); vt->last = t_now - t_start; vt->good_recv |= 1; /* Now find out if we like the response */ vt->resp_buf[sizeof vt->resp_buf - 1] = '\0'; p = strchr(vt->resp_buf, '\r'); if (p != NULL) *p = '\0'; p = strchr(vt->resp_buf, '\n'); if (p != NULL) *p = '\0'; i = sscanf(vt->resp_buf, "HTTP/%*f %u %s", &resp, buf); if ((i == 1 || i == 2) && resp == vt->exp_status) vt->happy |= 1; }