Example #1
0
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));
}
Example #2
0
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);
}
Example #3
0
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));
	}
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
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);
}