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)); }
void VTCP_name(const struct suckaddr *addr, char *abuf, unsigned alen, char *pbuf, unsigned plen) { const struct sockaddr *sa; socklen_t sl; sa = VSA_Get_Sockaddr(addr, &sl); vtcp_sa_to_ascii(sa, sl, abuf, alen, pbuf, plen); }
static void vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s) { const struct sockaddr_in *sin4; const struct sockaddr_in6 *sin6; socklen_t sl; if (proto == PF_INET6) { sin6 = VSA_Get_Sockaddr(s, &sl); //lint !e826 AN(sin6); assert(sl >= sizeof(*sin6)); VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr)); } else { sin4 = VSA_Get_Sockaddr(s, &sl); //lint !e826 AN(sin4); assert(sl >= sizeof(*sin4)); VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr)); } }
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); }
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); }
vmod_geoip2_lookup(VRT_CTX, struct vmod_geoip2_geoip2 *vp, VCL_STRING path, VCL_IP addr) { MMDB_lookup_result_s res; MMDB_entry_data_s data; const struct sockaddr *sa; socklen_t addrlen; const char **ap, *arrpath[COMPONENT_MAX]; char buf[LOOKUP_PATH_MAX]; char *p, *last; uint32_t i; int error; CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); AN(addr); if (!vp) { VSLb(ctx->vsl, SLT_Error, "geoip2.lookup: Database not open"); return (NULL); } if (!path || !*path || strlen(path) >= sizeof(buf)) { VSLb(ctx->vsl, SLT_Error, "geoip2.lookup: Invalid or missing path (%s)", path ? path : "NULL"); return (NULL); } sa = VSA_Get_Sockaddr(addr, &addrlen); AN(sa); res = MMDB_lookup_sockaddr(&vp->mmdb, sa, &error); if (error != MMDB_SUCCESS) { VSLb(ctx->vsl, SLT_Error, "geoip2.lookup: MMDB_lookup_sockaddr: %s", MMDB_strerror(error)); return (NULL); } if (!res.found_entry) { VSLb(ctx->vsl, SLT_Debug, "geoip2.lookup: No entry for this IP address (%s)", VRT_IP_string(ctx, addr)); return (NULL); } strncpy(buf, path, sizeof(buf)); last = NULL; for (p = buf, ap = arrpath; ap < &arrpath[COMPONENT_MAX - 1] && (*ap = strtok_r(p, "/", &last)) != NULL; p = NULL) { if (**ap != '\0') ap++; } *ap = NULL; error = MMDB_aget_value(&res.entry, &data, arrpath); if (error != MMDB_SUCCESS && error != MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR) { VSLb(ctx->vsl, SLT_Error, "geoip2.lookup: MMDB_aget_value: %s", MMDB_strerror(error)); return (NULL); } if (!data.has_data) { VSLb(ctx->vsl, SLT_Debug, "geoip2.lookup: No data for this path (%s)", path); return (NULL); } switch (data.type) { case MMDB_DATA_TYPE_BOOLEAN: p = WS_Printf(ctx->ws, "%s", data.boolean ? "true" : "false"); break; case MMDB_DATA_TYPE_BYTES: p = WS_Alloc(ctx->ws, data.data_size * 2 + 1); if (p) for (i = 0; i < data.data_size; i++) sprintf(&p[i * 2], "%02X", data.bytes[i]); break; case MMDB_DATA_TYPE_DOUBLE: p = WS_Printf(ctx->ws, "%f", data.double_value); break; case MMDB_DATA_TYPE_FLOAT: p = WS_Printf(ctx->ws, "%f", data.float_value); break; case MMDB_DATA_TYPE_INT32: p = WS_Printf(ctx->ws, "%i", data.int32); break; case MMDB_DATA_TYPE_UINT16: p = WS_Printf(ctx->ws, "%u", data.uint16); break; case MMDB_DATA_TYPE_UINT32: p = WS_Printf(ctx->ws, "%u", data.uint32); break; case MMDB_DATA_TYPE_UINT64: p = WS_Printf(ctx->ws, "%ju", (uintmax_t)data.uint64); break; case MMDB_DATA_TYPE_UTF8_STRING: p = WS_Alloc(ctx->ws, data.data_size + 1); if (p) { memcpy(p, data.utf8_string, data.data_size); p[data.data_size] = '\0'; } break; default: VSLb(ctx->vsl, SLT_Error, "geoip2.lookup: Unsupported data type (%d)", data.type); return (NULL); } if (!p) VSLb(ctx->vsl, SLT_Error, "geoip2.lookup: Out of workspace"); return (p); }