VCL_IP vmod_ip(const struct vrt_ctx *ctx, VCL_STRING s, VCL_IP d) { struct addrinfo hints, *res0 = NULL; const struct addrinfo *res; int error; char *p; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); AN(d); assert(VSA_Sane(d)); if (s != NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(s, "80", &hints, &res0); if (!error) { for (res = res0; res != NULL; res = res->ai_next) { if (VSA_Sane(res->ai_addr) && res->ai_addrlen >= VSA_Len(res->ai_addr)) { d = res->ai_addr; break; } } } } AN(d); p = WS_Alloc(ctx->ws, VSA_Len(d)); AN(p); memcpy(p, d, VSA_Len(d)); if (res0 != NULL) freeaddrinfo(res0); return (p); }
int VTCP_connect(const struct suckaddr *name, int msec) { int s, i; struct pollfd fds[1]; const struct sockaddr *sa; socklen_t sl; int val; if (name == NULL) return (-1); /* Attempt the connect */ AN(VSA_Sane(name)); sa = VSA_Get_Sockaddr(name, &sl); AN(sa); AN(sl); s = socket(sa->sa_family, SOCK_STREAM, 0); if (s < 0) return (s); /* Set the socket non-blocking */ if (msec != 0) (void)VTCP_nonblocking(s); val = 1; AZ(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val)); i = connect(s, sa, sl); if (i == 0) return (s); if (errno != EINPROGRESS) { AZ(close(s)); return (-1); } if (msec < 0) { /* * Caller is responsible for waiting and * calling VTCP_connected */ return (s); } assert(msec > 0); /* Exercise our patience, polling for write */ fds[0].fd = s; fds[0].events = POLLWRNORM; fds[0].revents = 0; i = poll(fds, 1, msec); if (i == 0) { /* Timeout, close and give up */ AZ(close(s)); errno = ETIMEDOUT; return (-1); } return (VTCP_connected(s)); }
static void ses_vsl_socket(struct sess *sp, const char *lsockname) { struct sockaddr_storage ss; socklen_t sl; char laddr[ADDR_BUFSIZE]; char lport[PORT_BUFSIZE]; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); AN(lsockname); AN(sp->addrs); sl = sizeof ss; AZ(getsockname(sp->fd, (void*)&ss, &sl)); AN(VSA_Build(sess_local_addr(sp), &ss, sl)); assert(VSA_Sane(sess_local_addr(sp))); VTCP_name(sess_remote_addr(sp), laddr, sizeof laddr, lport, sizeof lport); sp->client_addr_str = WS_Copy(sp->ws, laddr, -1); sp->client_port_str = WS_Copy(sp->ws, lport, -1); VTCP_name(sess_local_addr(sp), laddr, sizeof laddr, lport, sizeof lport); VSL(SLT_Begin, sp->vxid, "sess 0 HTTP/1"); VSL(SLT_SessOpen, sp->vxid, "%s %s %s %s %s %.6f %d", sp->client_addr_str, sp->client_port_str, lsockname, laddr, lport, sp->t_open, sp->fd); }
int VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(acl, VRT_ACL_MAGIC); assert(VSA_Sane(ip)); return (acl->match(ctx, ip)); }
VCL_BOOL vmod_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip) { CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_ORNULL(acl, VRT_ACL_MAGIC); assert(VSA_Sane(ip)); return (VRT_acl_match(ctx, acl, ip)); }
struct suckaddr * VSA_Clone(const struct suckaddr *sua) { struct suckaddr *sua2; assert(VSA_Sane(sua)); sua2 = calloc(1, vsa_suckaddr_len); XXXAN(sua2); memcpy(sua2, sua, vsa_suckaddr_len); return (sua2); }
int VSA_Compare_IP(const struct suckaddr *sua1, const struct suckaddr *sua2) { assert(VSA_Sane(sua1)); assert(VSA_Sane(sua2)); if (sua1->sa_family != sua2->sa_family) return (-1); switch (sua1->sa_family) { case PF_INET: return (memcmp(&sua1->sa.sa4.sin_addr, &sua2->sa.sa4.sin_addr, sizeof(struct in_addr))); case PF_INET6: return (memcmp(&sua1->sa.sa6.sin6_addr, &sua2->sa.sa6.sin6_addr, sizeof(struct in6_addr))); case PF_UNIX: return (strcmp(sua1->sa.sau->sun_path, sua2->sa.sau->sun_path)); default: WRONG("Just plain insane"); } NEEDLESS(return(-1)); }
int VTCP_connect(int s, const struct suckaddr *name, int msec) { int i, k; socklen_t l; struct pollfd fds[1]; const struct sockaddr *sa; socklen_t sl; assert(s >= 0); /* Set the socket non-blocking */ if (msec > 0) (void)VTCP_nonblocking(s); /* Attempt the connect */ AN(VSA_Sane(name)); sa = VSA_Get_Sockaddr(name, &sl); i = connect(s, sa, sl); if (i == 0 || errno != EINPROGRESS) return (i); assert(msec > 0); /* Exercise our patience, polling for write */ fds[0].fd = s; fds[0].events = POLLWRNORM; fds[0].revents = 0; i = poll(fds, 1, msec); if (i == 0) { /* Timeout, close and give up */ errno = ETIMEDOUT; return (-1); } /* Find out if we got a connection */ l = sizeof k; AZ(getsockopt(s, SOL_SOCKET, SO_ERROR, &k, &l)); /* An error means no connection established */ errno = k; if (k) return (-1); (void)VTCP_blocking(s); return (0); }
struct suckaddr * VSA_Clone(const struct suckaddr *sua) { struct suckaddr *sua2; struct sockaddr_un *suds; assert(VSA_Sane(sua)); sua2 = calloc(1, vsa_suckaddr_len); XXXAN(sua2); memcpy(sua2, sua, vsa_suckaddr_len); if (sua->sa_family == PF_UNIX && sua->sa.sau != NULL) { suds = calloc(1, sizeof(struct sockaddr_un)); XXXAN(suds); memcpy(suds, sua->sa.sau, sizeof(struct sockaddr_un)); sua2->sa.sau = suds; } return (sua2); }
VCL_IP vmod_ip(VRT_CTX, VCL_STRING s, VCL_IP d) { struct addrinfo hints, *res0 = NULL; const struct addrinfo *res; int error; void *p; struct suckaddr *r; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); AN(d); assert(VSA_Sane(d)); p = WS_Alloc(ctx->ws, vsa_suckaddr_len); if (p == NULL) { VSLb(ctx->vsl, SLT_VCL_Error, "vmod std.ip(): insufficient workspace"); return d; } r = NULL; if (s != NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(s, "80", &hints, &res0); if (!error) { for (res = res0; res != NULL; res = res->ai_next) { r = VSA_Build(p, res->ai_addr, res->ai_addrlen); if (r != NULL) break; } } } if (r == NULL) { r = p; memcpy(r, d, vsa_suckaddr_len); } if (res0 != NULL) freeaddrinfo(res0); return (r); }