int dhcp_l3_socket(int port, const char *interface, int family)
{
	int fd, opt = 1, len;
	struct sockaddr_in addr4;
	struct sockaddr_in6 addr6;
	struct sockaddr *addr;

	fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
	if (fd < 0)
		return -errno;

	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
		int err = errno;
		close(fd);
		return -err;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
				interface, strlen(interface) + 1) < 0) {
		int err = errno;
		close(fd);
		return -err;
	}

	if (family == AF_INET) {
		memset(&addr4, 0, sizeof(addr4));
		addr4.sin_family = family;
		addr4.sin_port = htons(port);
		addr = (struct sockaddr *)&addr4;
		len = sizeof(addr4);
	} else if (family == AF_INET6) {
		memset(&addr6, 0, sizeof(addr6));
		addr6.sin6_family = family;
		addr6.sin6_port = htons(port);
		addr = (struct sockaddr *)&addr6;
		len = sizeof(addr6);
	} else {
		close(fd);
		return -EINVAL;
	}

	if (bind(fd, addr, len) != 0) {
		close(fd);
		return -1;
	}

	return fd;
}
int dhcp_l3_socket(int port, const char *interface, int family)
{
	int fd, opt = 1, len;
	struct sockaddr_in addr4;
	struct sockaddr_in6 addr6;
	struct sockaddr *addr;

	fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
	if (fd < 0)
		return -errno;

	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
		int err = errno;
		close(fd);
		return -err;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
				interface, strlen(interface) + 1) < 0) {
		int err = errno;
		close(fd);
		return -err;
	}

	if (family == AF_INET) {
		memset(&addr4, 0, sizeof(addr4));
		addr4.sin_family = family;
		addr4.sin_port = htons(port);
		addr = (struct sockaddr *)&addr4;
		len = sizeof(addr4);
	} else if (family == AF_INET6) {
		memset(&addr6, 0, sizeof(addr6));
		addr6.sin6_family = family;
		addr6.sin6_port = htons(port);
		addr = (struct sockaddr *)&addr6;
		len = sizeof(addr6);
	} else {
		close(fd);
		return -EINVAL;
	}

	if (bind(fd, addr, len) != 0) {
		close(fd);
		return -1;
	}

	return fd;
}