95ad452
#define _GNU_SOURCE
95ad452
#include <sys/socket.h>
95ad452
#include <dlfcn.h>
95ad452
#include <errno.h>
95ad452
#include <stdlib.h>
4c8469c
#include <string.h>
95ad452
#include <netinet/in.h>
95ad452
4c8469c
static int
4c8469c
port_is_okay(unsigned short port)
4c8469c
{
4c8469c
	char *p, *q;
4c8469c
	long l;
4c8469c
4c8469c
	p = getenv("NOPORT");
4c8469c
	while ((p != NULL) && (*p != '\0')) {
4c8469c
		l = strtol(p, &q, 10);
4c8469c
		if ((q == NULL) || (q == p)) {
4c8469c
			break;
4c8469c
		}
4c8469c
		if ((*q == '\0') || (*q == ',')) {
4c8469c
			if (port == l) {
4c8469c
				errno = ECONNREFUSED;
4c8469c
				return -1;
4c8469c
			}
4c8469c
		}
4c8469c
		p = q;
4c8469c
		p += strspn(p, ",");
4c8469c
	}
4c8469c
	return 0;
4c8469c
}
4c8469c
95ad452
int
95ad452
connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
95ad452
{
95ad452
	unsigned short port;
95ad452
	static int (*next_connect)(int, const struct sockaddr *, socklen_t);
95ad452
95ad452
	if (next_connect == NULL) {
95ad452
		next_connect = dlsym(RTLD_NEXT, "connect");
95ad452
		if (next_connect == NULL) {
95ad452
			errno = ENOSYS;
95ad452
			return -1;
95ad452
		}
95ad452
	}
95ad452
4c8469c
	if (getenv("NOPORT") == NULL) {
95ad452
		return next_connect(sockfd, addr, addrlen);
95ad452
	}
95ad452
95ad452
	switch (addr->sa_family) {
95ad452
	case AF_INET:
95ad452
		port = ntohs(((struct sockaddr_in *)addr)->sin_port);
4c8469c
		if (port_is_okay(port) != 0) {
95ad452
			return -1;
95ad452
		}
95ad452
		break;
95ad452
	case AF_INET6:
95ad452
		port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
4c8469c
		if (port_is_okay(port) != 0) {
95ad452
			return -1;
95ad452
		}
95ad452
		break;
95ad452
	default:
95ad452
		break;
95ad452
	}
95ad452
	return next_connect(sockfd, addr, addrlen);
95ad452
}
95ad452
95ad452
ssize_t
95ad452
sendto(int sockfd, const void *buf, size_t len, int flags,
95ad452
       const struct sockaddr *dest_addr, socklen_t addrlen)
95ad452
{
95ad452
	unsigned short port;
95ad452
	static int (*next_sendto)(int, const void *, size_t, int,
95ad452
				  const struct sockaddr *, socklen_t);
95ad452
95ad452
	if (next_sendto == NULL) {
95ad452
		next_sendto = dlsym(RTLD_NEXT, "sendto");
95ad452
		if (next_sendto == NULL) {
95ad452
			errno = ENOSYS;
95ad452
			return -1;
95ad452
		}
95ad452
	}
95ad452
4c8469c
	if (getenv("NOPORT") == NULL) {
95ad452
		return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
95ad452
	}
95ad452
Nalin Dahyabhai 45d93c6
	if (dest_addr != NULL) {
Nalin Dahyabhai 45d93c6
		switch (dest_addr->sa_family) {
Nalin Dahyabhai 45d93c6
		case AF_INET:
Nalin Dahyabhai 45d93c6
			port = ((struct sockaddr_in *)dest_addr)->sin_port;
Nalin Dahyabhai 45d93c6
			port = ntohs(port);
Nalin Dahyabhai 45d93c6
			if (port_is_okay(port) != 0) {
Nalin Dahyabhai 45d93c6
				return -1;
Nalin Dahyabhai 45d93c6
			}
Nalin Dahyabhai 45d93c6
			break;
Nalin Dahyabhai 45d93c6
		case AF_INET6:
Nalin Dahyabhai 45d93c6
			port = ((struct sockaddr_in6 *)dest_addr)->sin6_port;
Nalin Dahyabhai 45d93c6
			port = ntohs(port);
Nalin Dahyabhai 45d93c6
			if (port_is_okay(port) != 0) {
Nalin Dahyabhai 45d93c6
				return -1;
Nalin Dahyabhai 45d93c6
			}
Nalin Dahyabhai 45d93c6
			break;
Nalin Dahyabhai 45d93c6
		default:
Nalin Dahyabhai 45d93c6
			break;
95ad452
		}
95ad452
	}
95ad452
	return next_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
95ad452
}