Exemplo n.º 1
0
void service_anvil_global_init(void)
{
	struct service_anvil_global *anvil;

	anvil = i_new(struct service_anvil_global, 1);
	if (pipe(anvil->status_fd) < 0)
		i_fatal("pipe() failed: %m");
	if (pipe(anvil->blocking_fd) < 0)
		i_fatal("pipe() failed: %m");
	if (pipe(anvil->nonblocking_fd) < 0)
		i_fatal("pipe() failed: %m");
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, anvil->log_fdpass_fd) < 0)
		i_fatal("socketpair() failed: %m");
	fd_set_nonblock(anvil->status_fd[0], TRUE);
	fd_set_nonblock(anvil->status_fd[1], TRUE);
	fd_set_nonblock(anvil->nonblocking_fd[1], TRUE);

	fd_close_on_exec(anvil->status_fd[0], TRUE);
	fd_close_on_exec(anvil->status_fd[1], TRUE);
	fd_close_on_exec(anvil->blocking_fd[0], TRUE);
	fd_close_on_exec(anvil->blocking_fd[1], TRUE);
	fd_close_on_exec(anvil->nonblocking_fd[0], TRUE);
	fd_close_on_exec(anvil->nonblocking_fd[1], TRUE);
	fd_close_on_exec(anvil->log_fdpass_fd[0], TRUE);
	fd_close_on_exec(anvil->log_fdpass_fd[1], TRUE);

	anvil->kills =
		service_process_notify_init(anvil->nonblocking_fd[1],
					    service_process_write_anvil_kill);
	service_anvil_global = anvil;
}
Exemplo n.º 2
0
struct tube* tube_create(void)
{
	struct tube* tube = (struct tube*)calloc(1, sizeof(*tube));
	int sv[2];
	if(!tube) {
		int err = errno;
		log_err("tube_create: out of memory");
		errno = err;
		return NULL;
	}
	tube->sr = -1;
	tube->sw = -1;
	if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
		int err = errno;
		log_err("socketpair: %s", strerror(errno));
		free(tube);
		errno = err;
		return NULL;
	}
	tube->sr = sv[0];
	tube->sw = sv[1];
	if(!fd_set_nonblock(tube->sr) || !fd_set_nonblock(tube->sw)) {
		int err = errno;
		log_err("tube: cannot set nonblocking");
		tube_delete(tube);
		errno = err;
		return NULL;
	}
	return tube;
}
Exemplo n.º 3
0
int
pipe_cloexec_nonblock(int fd[2])
{
#ifdef WIN32
    return _pipe(fd, 512, _O_BINARY);
#else
    int ret;

#ifdef HAVE_PIPE2
    ret = pipe2(fd, O_CLOEXEC|O_NONBLOCK);
    if (ret >= 0 || errno != ENOSYS)
        return ret;
#endif

    ret = pipe(fd);
    if (ret >= 0) {
        fd_set_cloexec(fd[0], true);
        fd_set_cloexec(fd[1], true);

        fd_set_nonblock(fd[0]);
        fd_set_nonblock(fd[1]);
    }

    return ret;
#endif
}
Exemplo n.º 4
0
static void test_istream_unix_server(int fd)
{
	struct istream *input;
	const unsigned char *data;
	size_t size;

	input = i_stream_create_unix(fd, 1024);
	/* 1) simple read */
	test_server_read_nofd(input, 1);
	write_one(fd);

	/* 2) fd was sent but we won't get it */
	test_server_read_nofd(input, 2);
	/* we still shouldn't have the fd */
	fd_set_nonblock(fd, TRUE);
	i_stream_unix_set_read_fd(input);
	test_assert(i_stream_read_data(input, &data, &size, 0) == 0);
	test_assert(i_stream_unix_get_read_fd(input) == -1);
	fd_set_nonblock(fd, FALSE);
	write_one(fd);

	/* 3) the previous fd should be lost now */
	test_server_read_nofd(input, 3);
	write_one(fd);

	/* 4) we should get the fd now */
	test_server_read_fd(input, send_fd2, 4);
	write_one(fd);

	/* 5) the previous fd shouldn't be returned anymore */
	i_stream_unix_set_read_fd(input);
	test_server_read_nofd(input, 5);
	write_one(fd);

	/* 6) with i_stream_unix_unset_read_fd() we shouldn't get fd anymore */
	i_stream_unix_unset_read_fd(input);
	test_server_read_nofd(input, 6);
	write_one(fd);

	/* 7-8) two fds were sent, but we'll get only the first one */
	i_stream_unix_set_read_fd(input);
	test_server_read_fd(input, send_fd, 7);
	test_server_read_nofd(input, 8);
	write_one(fd);

	/* 9-10) two fds were sent, and we'll get them both */
	i_stream_unix_set_read_fd(input);
	test_server_read_fd(input, send_fd, 9);
	i_stream_unix_set_read_fd(input);
	test_server_read_fd(input, send_fd2, 10);
	write_one(fd);

	i_stream_destroy(&input);
	i_close_fd(&fd);
}
Exemplo n.º 5
0
int
accept_cloexec_nonblock(int fd, struct sockaddr *address,
            size_t *address_length_r)
{
    int ret;
    socklen_t address_length = *address_length_r;

#ifdef HAVE_ACCEPT4
    ret = accept4(fd, address, &address_length,
              SOCK_CLOEXEC|SOCK_NONBLOCK);
    if (ret >= 0 || errno != ENOSYS) {
        if (ret >= 0)
            *address_length_r = address_length;

        return ret;
    }
#endif

    ret = accept(fd, address, &address_length);
    if (ret >= 0) {
        fd_set_cloexec(ret, true);
        fd_set_nonblock(ret);
        *address_length_r = address_length;
    }

    return ret;
}
Exemplo n.º 6
0
int sock_comm_buffer_init(struct sock_conn *conn)
{
	int optval;
	socklen_t size = SOCK_COMM_BUF_SZ;
	socklen_t optlen = sizeof(socklen_t);

	optval = 1;
	if (setsockopt(conn->sock_fd, IPPROTO_TCP, TCP_NODELAY,
		       &optval, sizeof optval))
		SOCK_LOG_ERROR("setsockopt failed\n");

	fd_set_nonblock(conn->sock_fd);
	rbinit(&conn->inbuf, SOCK_COMM_BUF_SZ);
	rbinit(&conn->outbuf, SOCK_COMM_BUF_SZ);

	if (setsockopt(conn->sock_fd, SOL_SOCKET, SO_RCVBUF, &size, optlen))
		SOCK_LOG_ERROR("setsockopt failed\n");

	if (setsockopt(conn->sock_fd, SOL_SOCKET, SO_SNDBUF, &size, optlen))
		SOCK_LOG_ERROR("setsockopt failed\n");

	if (!getsockopt(conn->sock_fd, SOL_SOCKET, SO_RCVBUF, &size, &optlen))
		SOCK_LOG_INFO("SO_RCVBUF: %d\n", size);
	
	optlen = sizeof(socklen_t);
	if (!getsockopt(conn->sock_fd, SOL_SOCKET, SO_SNDBUF, &size, &optlen))
		SOCK_LOG_INFO("SO_SNDBUF: %d\n", size);
	return 0;
}
Exemplo n.º 7
0
int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, 
        int nonblock)
{
	ssize_t r, d;
	int fd = tube->sw;

	/* test */
	if(nonblock) {
		r = write(fd, &len, sizeof(len));
		if(r == -1) {
			if(errno==EINTR || errno==EAGAIN)
				return -1;
			log_err("tube msg write failed: %s", strerror(errno));
			return -1; /* can still continue, perhaps */
		}
	} else r = 0;
	if(!fd_set_block(fd))
		return 0;
	/* write remainder */
	d = r;
	while(d != (ssize_t)sizeof(len)) {
		if((r=write(fd, ((char*)&len)+d, sizeof(len)-d)) == -1) {
			if(errno == EAGAIN)
				continue; /* temporarily unavail: try again*/
			log_err("tube msg write failed: %s", strerror(errno));
			(void)fd_set_nonblock(fd);
			return 0;
		}
		d += r;
	}
	d = 0;
	while(d != (ssize_t)len) {
		if((r=write(fd, buf+d, len-d)) == -1) {
			if(errno == EAGAIN)
				continue; /* temporarily unavail: try again*/
			log_err("tube msg write failed: %s", strerror(errno));
			(void)fd_set_nonblock(fd);
			return 0;
		}
		d += r;
	}
	if(!fd_set_nonblock(fd))
		return 0;
	return 1;
}
Exemplo n.º 8
0
int
dup_cloexec(int oldfd)
{
	int newfd = dup(oldfd);
	if (newfd >= 0)
		fd_set_nonblock(newfd);

	return newfd;
}
Exemplo n.º 9
0
static struct dsync_ibc *
cmd_dsync_icb_stream_init(struct dsync_cmd_context *ctx,
			  const char *name, const char *temp_prefix)
{
	if (ctx->input == NULL) {
		fd_set_nonblock(ctx->fd_in, TRUE);
		fd_set_nonblock(ctx->fd_out, TRUE);
		ctx->input = i_stream_create_fd(ctx->fd_in, (size_t)-1, FALSE);
		ctx->output = o_stream_create_fd(ctx->fd_out, (size_t)-1, FALSE);
	}
	i_stream_ref(ctx->input);
	o_stream_ref(ctx->output);
	if (ctx->rawlog_path != NULL) {
		iostream_rawlog_create_path(ctx->rawlog_path,
					    &ctx->input, &ctx->output);
	}
	return dsync_ibc_init_stream(ctx->input, ctx->output,
				     name, temp_prefix);
}
Exemplo n.º 10
0
int
create_local_accept_sock(const char *path, int* noproto)
{
#ifdef HAVE_SYS_UN_H
	int s;
	struct sockaddr_un usock;

	verbose(VERB_ALGO, "creating unix socket %s", path);
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
	/* this member exists on BSDs, not Linux */
	usock.sun_len = (socklen_t)sizeof(usock);
#endif
	usock.sun_family = AF_LOCAL;
	/* length is 92-108, 104 on FreeBSD */
	(void)strlcpy(usock.sun_path, path, sizeof(usock.sun_path));

	if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) {
		log_err("Cannot create local socket %s (%s)",
			path, strerror(errno));
		return -1;
	}

	if (unlink(path) && errno != ENOENT) {
		/* The socket already exists and cannot be removed */
		log_err("Cannot remove old local socket %s (%s)",
			path, strerror(errno));
		return -1;
	}

	if (bind(s, (struct sockaddr *)&usock,
		(socklen_t)sizeof(struct sockaddr_un)) == -1) {
		log_err("Cannot bind local socket %s (%s)",
			path, strerror(errno));
		return -1;
	}

	if (!fd_set_nonblock(s)) {
		log_err("Cannot set non-blocking mode");
		return -1;
	}

	if (listen(s, TCP_BACKLOG) == -1) {
		log_err("can't listen: %s", strerror(errno));
		return -1;
	}

	(void)noproto; /*unused*/
	return s;
#else
	(void)path;
	log_err("Local sockets are not supported");
	*noproto = 1;
	return -1;
#endif
}
Exemplo n.º 11
0
void sock_set_sockopts(int sock)
{
	int optval;
	optval = 1;

	sock_set_sockopt_reuseaddr(sock);
	if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)))
		SOCK_LOG_ERROR("setsockopt nodelay failed\n");

	fd_set_nonblock(sock);
}
Exemplo n.º 12
0
void sig_init() {
	int pipe_fd[2];
	struct sigaction act;
	struct signal_spec_s *ss;
	
	// in a last-ditch attempt to recover from fatal errors, we might re-run
	// the initialization.  otherwise, this condition is never true.
	if (sig_wake_rd >= 0) close(sig_wake_rd);
	if (sig_wake_wr >= 0) close(sig_wake_wr);

	if (!sig_main_pid)
		sig_main_pid= getpid();
	
	// initialize with 0
	memset((void*)signals, 0, sizeof(signals));

	// Create pipe and set non-blocking
	if (pipe(pipe_fd) < 0
		|| fcntl(pipe_fd[0], F_SETFD, FD_CLOEXEC) < 0
		|| fcntl(pipe_fd[1], F_SETFD, FD_CLOEXEC) < 0
		|| !fd_set_nonblock(pipe_fd[0])
		|| !fd_set_nonblock(pipe_fd[1])
	) {
		fatal(EXIT_IMPOSSIBLE_SCENARIO, "signal pipe setup: %s", strerror(errno));
	}
	log_trace("pipe => (%d, %d)", pipe_fd[0], pipe_fd[1]);
	sig_wake_rd= pipe_fd[0];
	sig_wake_wr= pipe_fd[1];
	
	// set signal handlers
	memset(&act, 0, sizeof(act));
	for (ss= signal_spec; ss->signum != 0; ss++) {
		act.sa_handler= ss->handler;
		if (sigaction(ss->signum, &act, NULL))
			fatal(EXIT_IMPOSSIBLE_SCENARIO, "signal handler setup: %s", strerror(errno));
	}
	
	// capture our signal mask
	if (!sigprocmask(SIG_SETMASK, NULL, &sig_mask_orig) == 0)
		perror("sigprocmask(all)");
}
Exemplo n.º 13
0
static struct istream *mail_raw_create_stream
(struct mail_user *ruser, int fd, time_t *mtime_r, const char **sender)
{
	struct istream *input, *input2, *input_list[2];
	const unsigned char *data;
	size_t i, size;
	int ret, tz;
	char *env_sender = NULL;

	*mtime_r = (time_t)-1;
	fd_set_nonblock(fd, FALSE);

	input = i_stream_create_fd(fd, 4096, FALSE);
	input->blocking = TRUE;
	/* If input begins with a From-line, drop it */
	ret = i_stream_read_data(input, &data, &size, 5);
	if (ret > 0 && size >= 5 && memcmp(data, "From ", 5) == 0) {
		/* skip until the first LF */
		i_stream_skip(input, 5);
		while ( i_stream_read_data(input, &data, &size, 0) > 0 ) {
			for (i = 0; i < size; i++) {
				if (data[i] == '\n')
					break;
			}
			if (i != size) {
				(void)mbox_from_parse(data, i, mtime_r, &tz, &env_sender);
				i_stream_skip(input, i + 1);
				break;
			}
			i_stream_skip(input, size);
		}
	}

	if (env_sender != NULL && sender != NULL) {
		*sender = t_strdup(env_sender);
	}
	i_free(env_sender);

	if (input->v_offset == 0) {
		input2 = input;
		i_stream_ref(input2);
	} else {
		input2 = i_stream_create_limit(input, (uoff_t)-1);
	}
	i_stream_unref(&input);

	input_list[0] = input2; input_list[1] = NULL;
	input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER,
		seekable_fd_callback, (void*)ruser);
	i_stream_unref(&input2);
	return input;
}
Exemplo n.º 14
0
int
socketpair_cloexec_nonblock(int domain, int type, int protocol, int sv[2])
{
	int ret;

#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
	ret = socketpair(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol,
			 sv);
	if (ret >= 0 || errno != EINVAL)
		return ret;
#endif

	ret = socketpair(domain, type, protocol, sv);
	if (ret >= 0) {
		fd_set_cloexec(sv[0], true);
		fd_set_nonblock(sv[0]);
		fd_set_cloexec(sv[1], true);
		fd_set_nonblock(sv[1]);
	}

	return ret;
}
Exemplo n.º 15
0
static void
run_cmd(struct dsync_cmd_context *ctx, const char *const *args)
{
	int fd_in[2], fd_out[2], fd_err[2];

	if (pipe(fd_in) < 0 || pipe(fd_out) < 0 || pipe(fd_err) < 0)
		i_fatal("pipe() failed: %m");

	ctx->remote_pid = fork();
	switch (ctx->remote_pid) {
	case -1:
		i_fatal("fork() failed: %m");
	case 0:
		/* child, which will execute the proxy server. stdin/stdout
		   goes to pipes which we'll pass to proxy client. */
		if (dup2(fd_in[0], STDIN_FILENO) < 0 ||
		    dup2(fd_out[1], STDOUT_FILENO) < 0 ||
		    dup2(fd_err[1], STDERR_FILENO) < 0)
			i_fatal("dup2() failed: %m");

		i_close_fd(&fd_in[0]);
		i_close_fd(&fd_in[1]);
		i_close_fd(&fd_out[0]);
		i_close_fd(&fd_out[1]);
		i_close_fd(&fd_err[0]);
		i_close_fd(&fd_err[1]);

		execvp_const(args[0], args);
	default:
		/* parent */
		break;
	}

	i_close_fd(&fd_in[0]);
	i_close_fd(&fd_out[1]);
	i_close_fd(&fd_err[1]);
	ctx->fd_in = fd_out[0];
	ctx->fd_out = fd_in[1];
	ctx->fd_err = fd_err[0];

	if (ctx->remote_user_prefix) {
		const char *prefix =
			t_strdup_printf("%s\n", ctx->ctx.cur_username);
		if (write_full(ctx->fd_out, prefix, strlen(prefix)) < 0)
			i_fatal("write(remote out) failed: %m");
	}

	fd_set_nonblock(ctx->fd_err, TRUE);
	ctx->err_stream = i_stream_create_fd(ctx->fd_err, IO_BLOCK_SIZE, FALSE);
	i_stream_set_return_partial_line(ctx->err_stream, TRUE);
}
Exemplo n.º 16
0
/** find or else create proxy for this remote client */
static struct proxy*
find_create_proxy(struct sockaddr_storage* from, socklen_t from_len,
	fd_set* rorig, int* max, struct proxy** proxies, int serv_ip6,
	struct timeval* now, struct timeval* reuse_timeout)
{
	struct proxy* p;
	struct timeval t;
	for(p = *proxies; p; p = p->next) {
		if(sockaddr_cmp(from, from_len, &p->addr, p->addr_len)==0)
			return p;
	}
	/* possibly: reuse lapsed entries */
	for(p = *proxies; p; p = p->next) {
		if(p->numwait > p->numsent || p->numsent > p->numreturn)
			continue;
		t = *now;
		dl_tv_subtract(&t, &p->lastuse);
		if(dl_tv_smaller(&t, reuse_timeout))
			continue;
		/* yes! */
		verbose(1, "reuse existing entry");
		memmove(&p->addr, from, from_len);
		p->addr_len = from_len;
		p->numreuse++;
		return p;
	}
	/* create new */
	p = (struct proxy*)calloc(1, sizeof(*p));
	if(!p) fatal_exit("out of memory");
	p->s = socket(serv_ip6?AF_INET6:AF_INET, SOCK_DGRAM, 0);
	if(p->s == -1) {
#ifndef USE_WINSOCK
		fatal_exit("socket: %s", strerror(errno));
#else
		fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
	fd_set_nonblock(p->s);
	memmove(&p->addr, from, from_len);
	p->addr_len = from_len;
	p->next = *proxies;
	*proxies = p;
	FD_SET(FD_SET_T p->s, rorig);
	if(p->s+1 > *max)
		*max = p->s+1;
	return p;
}
Exemplo n.º 17
0
int
socket_cloexec_nonblock(int domain, int type, int protocol)
{
    int fd;

#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
    fd = socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol);
    if (fd >= 0 || errno != EINVAL)
        return fd;
#endif

    fd = socket(domain, type, protocol);
    if (fd >= 0) {
        fd_set_cloexec(fd, true);
        fd_set_nonblock(fd);
    }

    return fd;
}
Exemplo n.º 18
0
Arquivo: tcp.c Projeto: ftnapps/qico
int tcp_setsockopts(int fd)
{
	struct linger	lopt;
	int		rc = 0;

	rc = fd_set_nonblock( fd, true );

	/* Set SO_LINGER socket option */
	memset( &lopt, 0, sizeof( struct linger ));

	lopt.l_onoff  = 1;
	lopt.l_linger = 200; /* 2 seconds */

	if ( setsockopt( fd, SOL_SOCKET, SO_LINGER,
	    (char*) &lopt, sizeof( struct linger )) == -1 )
	{
		rc--;
		DEBUG(('I',1,"can't set SO_LINGER socket option on stdout: %s", strerror( errno )));
	}

	return ( rc == 0 );
}
Exemplo n.º 19
0
int
create_udp_sock(int family, int socktype, struct sockaddr* addr,
        socklen_t addrlen, int v6only, int* inuse, int* noproto,
	int rcv, int snd)
{
	int s;
#if defined(IPV6_USE_MIN_MTU)
	int on=1;
#endif
#ifdef IPV6_MTU
	int mtu = IPV6_MIN_MTU;
#endif
#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
	(void)rcv;
#endif
#if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
	(void)snd;
#endif
#ifndef IPV6_V6ONLY
	(void)v6only;
#endif
	if((s = socket(family, socktype, 0)) == -1) {
		*inuse = 0;
#ifndef USE_WINSOCK
		if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", strerror(errno));
#else
		if(WSAGetLastError() == WSAEAFNOSUPPORT || 
			WSAGetLastError() == WSAEPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", 
			wsa_strerror(WSAGetLastError()));
#endif
		*noproto = 0;
		return -1;
	}
	if(rcv) {
#ifdef SO_RCVBUF
		int got;
		socklen_t slen = (socklen_t)sizeof(got);
#  ifdef SO_RCVBUFFORCE
		/* Linux specific: try to use root permission to override
		 * system limits on rcvbuf. The limit is stored in 
		 * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
		if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv, 
			(socklen_t)sizeof(rcv)) < 0) {
			if(errno != EPERM) {
#    ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_RCVBUFFORCE, "
					"...) failed: %s", strerror(errno));
				close(s);
#    else
				log_err("setsockopt(..., SO_RCVBUFFORCE, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#    endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
#  endif /* SO_RCVBUFFORCE */
			if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, 
				(socklen_t)sizeof(rcv)) < 0) {
#  ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_RCVBUF, "
					"...) failed: %s", strerror(errno));
				close(s);
#  else
				log_err("setsockopt(..., SO_RCVBUF, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#  endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
			/* check if we got the right thing or if system
			 * reduced to some system max.  Warn if so */
			if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got, 
				&slen) >= 0 && got < rcv/2) {
				log_warn("so-rcvbuf %u was not granted. "
					"Got %u. To fix: start with "
					"root permissions(linux) or sysctl "
					"bigger net.core.rmem_max(linux) or "
					"kern.ipc.maxsockbuf(bsd) values.",
					(unsigned)rcv, (unsigned)got);
			}
#  ifdef SO_RCVBUFFORCE
		}
#  endif
#endif /* SO_RCVBUF */
	}
	/* first do RCVBUF as the receive buffer is more important */
	if(snd) {
#ifdef SO_SNDBUF
		int got;
		socklen_t slen = (socklen_t)sizeof(got);
#  ifdef SO_SNDBUFFORCE
		/* Linux specific: try to use root permission to override
		 * system limits on sndbuf. The limit is stored in 
		 * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
		if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, 
			(socklen_t)sizeof(snd)) < 0) {
			if(errno != EPERM) {
#    ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_SNDBUFFORCE, "
					"...) failed: %s", strerror(errno));
				close(s);
#    else
				log_err("setsockopt(..., SO_SNDBUFFORCE, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#    endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
#  endif /* SO_SNDBUFFORCE */
			if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, 
				(socklen_t)sizeof(snd)) < 0) {
#  ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_SNDBUF, "
					"...) failed: %s", strerror(errno));
				close(s);
#  else
				log_err("setsockopt(..., SO_SNDBUF, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#  endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
			/* check if we got the right thing or if system
			 * reduced to some system max.  Warn if so */
			if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got, 
				&slen) >= 0 && got < snd/2) {
				log_warn("so-sndbuf %u was not granted. "
					"Got %u. To fix: start with "
					"root permissions(linux) or sysctl "
					"bigger net.core.wmem_max(linux) or "
					"kern.ipc.maxsockbuf(bsd) values.",
					(unsigned)snd, (unsigned)got);
			}
#  ifdef SO_SNDBUFFORCE
		}
#  endif
#endif /* SO_SNDBUF */
	}
	if(family == AF_INET6) {
# if defined(IPV6_V6ONLY)
		if(v6only) {
			int val=(v6only==2)?0:1;
			if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
				(void*)&val, (socklen_t)sizeof(val)) < 0) {
#ifndef USE_WINSOCK
				log_err("setsockopt(..., IPV6_V6ONLY"
					", ...) failed: %s", strerror(errno));
				close(s);
#else
				log_err("setsockopt(..., IPV6_V6ONLY"
					", ...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
		}
# endif
# if defined(IPV6_USE_MIN_MTU)
		/*
		 * There is no fragmentation of IPv6 datagrams
		 * during forwarding in the network. Therefore
		 * we do not send UDP datagrams larger than
		 * the minimum IPv6 MTU of 1280 octets. The
		 * EDNS0 message length can be larger if the
		 * network stack supports IPV6_USE_MIN_MTU.
		 */
		if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
			(void*)&on, (socklen_t)sizeof(on)) < 0) {
#  ifndef USE_WINSOCK
			log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
				"...) failed: %s", strerror(errno));
			close(s);
#  else
			log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
				"...) failed: %s", 
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
#  endif
			*noproto = 0;
			*inuse = 0;
			return -1;
		}
# elif defined(IPV6_MTU)
		/*
		 * On Linux, to send no larger than 1280, the PMTUD is
		 * disabled by default for datagrams anyway, so we set
		 * the MTU to use.
		 */
		if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
			(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
#  ifndef USE_WINSOCK
			log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
				strerror(errno));
			close(s);
#  else
			log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
#  endif
			*noproto = 0;
			*inuse = 0;
			return -1;
		}
# endif /* IPv6 MTU */
	} else if(family == AF_INET) {
#  if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
		int action = IP_PMTUDISC_DONT;
		if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, 
			&action, (socklen_t)sizeof(action)) < 0) {
			log_err("setsockopt(..., IP_MTU_DISCOVER, "
				"IP_PMTUDISC_DONT...) failed: %s",
				strerror(errno));
#    ifndef USE_WINSOCK
			close(s);
#    else
			closesocket(s);
#    endif
			return -1;
		}
#  elif defined(IP_DONTFRAG)
		int off = 0;
		if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, 
			&off, (socklen_t)sizeof(off)) < 0) {
			log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
				strerror(errno));
#    ifndef USE_WINSOCK
			close(s);
#    else
			closesocket(s);
#    endif
			return -1;
		}
#  endif /* IPv4 MTU */
	}
	if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
		*noproto = 0;
#ifndef USE_WINSOCK
#ifdef EADDRINUSE
		*inuse = (errno == EADDRINUSE);
		/* detect freebsd jail with no ipv6 permission */
		if(family==AF_INET6 && errno==EINVAL)
			*noproto = 1;
		else if(errno != EADDRINUSE) {
			log_err("can't bind socket: %s", strerror(errno));
			log_addr(0, "failed address",
				(struct sockaddr_storage*)addr, addrlen);
		}
#endif /* EADDRINUSE */
		close(s);
#else /* USE_WINSOCK */
		if(WSAGetLastError() != WSAEADDRINUSE &&
			WSAGetLastError() != WSAEADDRNOTAVAIL) {
			log_err("can't bind socket: %s", 
				wsa_strerror(WSAGetLastError()));
			log_addr(0, "failed address",
				(struct sockaddr_storage*)addr, addrlen);
		}
		closesocket(s);
#endif
		return -1;
	}
	if(!fd_set_nonblock(s)) {
		*noproto = 0;
		*inuse = 0;
#ifndef USE_WINSOCK
		close(s);
#else
		closesocket(s);
#endif
		return -1;
	}
	return s;
}
Exemplo n.º 20
0
/** delayer main service routine */
static void
service(const char* bind_str, int bindport, const char* serv_str, 
	size_t memsize, int delay_msec)
{
	struct sockaddr_storage bind_addr, srv_addr;
	socklen_t bind_len, srv_len;
	struct ringbuf* ring = ring_create(memsize);
	struct timeval delay, reuse;
	sldns_buffer* pkt;
	int i, s, listen_s;
#ifndef S_SPLINT_S
	delay.tv_sec = delay_msec / 1000;
	delay.tv_usec = (delay_msec % 1000)*1000;
#endif
	reuse = delay; /* reuse is max(4*delay, 1 second) */
	dl_tv_add(&reuse, &delay);
	dl_tv_add(&reuse, &delay);
	dl_tv_add(&reuse, &delay);
	if(reuse.tv_sec == 0)
		reuse.tv_sec = 1;
	if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) {
		printf("cannot parse forward address: %s\n", serv_str);
		exit(1);
	}
	pkt = sldns_buffer_new(65535);
	if(!pkt)
		fatal_exit("out of memory");
	if( signal(SIGINT, delayer_sigh) == SIG_ERR ||
#ifdef SIGHUP
		signal(SIGHUP, delayer_sigh) == SIG_ERR ||
#endif
#ifdef SIGQUIT
		signal(SIGQUIT, delayer_sigh) == SIG_ERR ||
#endif
#ifdef SIGBREAK
		signal(SIGBREAK, delayer_sigh) == SIG_ERR ||
#endif
#ifdef SIGALRM
		signal(SIGALRM, delayer_sigh) == SIG_ERR ||
#endif
		signal(SIGTERM, delayer_sigh) == SIG_ERR)
		fatal_exit("could not bind to signal");
	/* bind UDP port */
	if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET,
		SOCK_DGRAM, 0)) == -1) {
#ifndef USE_WINSOCK
		fatal_exit("socket: %s", strerror(errno));
#else
		fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
	i=0;
	if(bindport == 0) {
		bindport = 1024 + random()%64000;
		i = 100;
	}
	while(1) {
		if(!ipstrtoaddr(bind_str, bindport, &bind_addr, &bind_len)) {
			printf("cannot parse listen address: %s\n", bind_str);
			exit(1);
		}
		if(bind(s, (struct sockaddr*)&bind_addr, bind_len) == -1) {
#ifndef USE_WINSOCK
			log_err("bind: %s", strerror(errno));
#else
			log_err("bind: %s", wsa_strerror(WSAGetLastError()));
#endif
			if(i--==0)
				fatal_exit("cannot bind any port");
			bindport = 1024 + random()%64000;
		} else break;
	}
	fd_set_nonblock(s);
	/* and TCP port */
	if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET,
		SOCK_STREAM, 0)) == -1) {
#ifndef USE_WINSOCK
		fatal_exit("tcp socket: %s", strerror(errno));
#else
		fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
#ifdef SO_REUSEADDR
	if(1) {
		int on = 1;
		if(setsockopt(listen_s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
			(socklen_t)sizeof(on)) < 0)
#ifndef USE_WINSOCK
			fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s",
				strerror(errno));
#else
			fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s",
				wsa_strerror(WSAGetLastError()));
#endif
	}
#endif
	if(bind(listen_s, (struct sockaddr*)&bind_addr, bind_len) == -1) {
#ifndef USE_WINSOCK
		fatal_exit("tcp bind: %s", strerror(errno));
#else
		fatal_exit("tcp bind: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
	if(listen(listen_s, 5) == -1) {
#ifndef USE_WINSOCK
		fatal_exit("tcp listen: %s", strerror(errno));
#else
		fatal_exit("tcp listen: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
	fd_set_nonblock(listen_s);
	printf("listening on port: %d\n", bindport);

	/* process loop */
	do_quit = 0;
	service_loop(s, listen_s, ring, &delay, &reuse, &srv_addr, srv_len, 
		pkt);

	/* cleanup */
	verbose(1, "cleanup");
#ifndef USE_WINSOCK
	close(s);
	close(listen_s);
#else
	closesocket(s);
	closesocket(listen_s);
#endif
	sldns_buffer_free(pkt);
	ring_delete(ring);
}
Exemplo n.º 21
0
struct sock_conn *sock_ep_connect(struct sock_ep *ep, fi_addr_t index)
{
	int conn_fd = -1, ret;
	int do_retry = sock_conn_retry;
	struct sock_conn *conn, *new_conn;
	uint16_t idx;
	struct sockaddr_in *addr;
	socklen_t lon;
	int valopt = 0;
	struct pollfd poll_fd;

	if (ep->ep_type == FI_EP_MSG) {
		idx = 0;
		addr = ep->dest_addr;
	} else {
		idx = index & ep->av->mask;
		addr = (struct sockaddr_in *)&ep->av->table[idx].addr;
	}

do_connect:
	fastlock_acquire(&ep->cmap.lock);
	conn = sock_ep_lookup_conn(ep, index, addr);
	fastlock_release(&ep->cmap.lock);

	if (conn != SOCK_CM_CONN_IN_PROGRESS)
		return conn;

	conn_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (conn_fd == -1) {
		SOCK_LOG_ERROR("failed to create conn_fd, errno: %d\n", errno);
		errno = FI_EOTHER;
		return NULL;
	}

	ret = fd_set_nonblock(conn_fd);
	if (ret) {
		SOCK_LOG_ERROR("failed to set conn_fd nonblocking, errno: %d\n", errno);
		errno = FI_EOTHER;
		close(conn_fd);
                return NULL;
	}

	SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr->sin_addr),
			ntohs(addr->sin_port));
	SOCK_LOG_DBG("Connecting using address:%s\n",
			inet_ntoa(ep->src_addr->sin_addr));

	ret = connect(conn_fd, (struct sockaddr *) addr, sizeof *addr);
	if (ret < 0) {
		if (errno == EINPROGRESS) {
			poll_fd.fd = conn_fd;
			poll_fd.events = POLLOUT;

			ret = poll(&poll_fd, 1, 15 * 1000);
			if (ret < 0) {
				SOCK_LOG_DBG("poll failed\n");
				goto retry;
			}

			lon = sizeof(int);
			ret = getsockopt(conn_fd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
			if (ret < 0) {
				SOCK_LOG_DBG("getsockopt failed: %d, %d\n", ret, conn_fd);
				goto retry;
			}

			if (valopt) {
				SOCK_LOG_DBG("Error in connection() %d - %s - %d\n", valopt, strerror(valopt), conn_fd);
				SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr->sin_addr),
						ntohs(addr->sin_port));
				SOCK_LOG_DBG("Connecting using address:%s\n",
				inet_ntoa(ep->src_addr->sin_addr));
				goto retry;
			}
			goto out;
		} else {
			SOCK_LOG_DBG("Timeout or error() - %s: %d\n", strerror(errno), conn_fd);
			SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr->sin_addr),
					ntohs(addr->sin_port));
			SOCK_LOG_DBG("Connecting using address:%s\n",
					inet_ntoa(ep->src_addr->sin_addr));
			goto retry;
		}
	} else {
		goto out;
	}

retry:
	do_retry--;
	sleep(10);
	if (!do_retry)
		goto err;

	if (conn_fd != -1) {
		close(conn_fd);
		conn_fd = -1;
	}

	SOCK_LOG_ERROR("Connect error, retrying - %s - %d\n", strerror(errno), conn_fd);
	SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr->sin_addr),
			ntohs(addr->sin_port));
	SOCK_LOG_DBG("Connecting using address:%s\n",
			inet_ntoa(ep->src_addr->sin_addr));
        goto do_connect;

out:
	fastlock_acquire(&ep->cmap.lock);
	new_conn = sock_conn_map_insert(ep, addr, conn_fd, 0);
	new_conn->av_index = (ep->ep_type == FI_EP_MSG) ? FI_ADDR_NOTAVAIL : (fi_addr_t) idx;
	conn = idm_lookup(&ep->av_idm, index);
	if (conn == SOCK_CM_CONN_IN_PROGRESS) {
		idm_set(&ep->av_idm, index, new_conn);
		conn = new_conn;
	}
	fastlock_release(&ep->cmap.lock);
	return conn;

err:
	close(conn_fd);
	return NULL;
}
Exemplo n.º 22
0
static
void test_iostream_proxy_simple(void)
{
	size_t bytes;

	test_begin("iostream_proxy");
	int sfdl[2];
	int sfdr[2];

	int counter;

	test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sfdl) == 0);
	test_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sfdr) == 0);

	fd_set_nonblock(sfdl[0], TRUE);
	fd_set_nonblock(sfdl[1], TRUE);
	fd_set_nonblock(sfdr[0], TRUE);
	fd_set_nonblock(sfdr[1], TRUE);

	struct ioloop *ioloop = io_loop_create();

	struct istream *left_in = i_stream_create_fd(sfdl[1], IO_BLOCK_SIZE);
	struct ostream *left_out = o_stream_create_fd(sfdl[1], IO_BLOCK_SIZE);

	struct istream *right_in = i_stream_create_fd(sfdr[1], IO_BLOCK_SIZE);
	struct ostream *right_out = o_stream_create_fd(sfdr[1], IO_BLOCK_SIZE);

	struct iostream_proxy *proxy;

	proxy = iostream_proxy_create(left_in, left_out, right_in, right_out);
	i_stream_unref(&left_in);
	o_stream_unref(&left_out);
	i_stream_unref(&right_in);
	o_stream_unref(&right_out);

	iostream_proxy_set_completion_callback(proxy, completed, &counter);
	iostream_proxy_start(proxy);

	left_in = i_stream_create_fd(sfdl[0], IO_BLOCK_SIZE);
	left_out = o_stream_create_fd(sfdl[0], IO_BLOCK_SIZE);

	right_in = i_stream_create_fd(sfdr[0], IO_BLOCK_SIZE);
	right_out = o_stream_create_fd(sfdr[0], IO_BLOCK_SIZE);

	test_assert(proxy != NULL);
	test_assert(o_stream_send_str(left_out, "hello, world") > 0);
	o_stream_flush(left_out);
	o_stream_unref(&left_out);
	test_assert(shutdown(sfdl[0], SHUT_WR) == 0);

	counter = 1;
	io_loop_run(ioloop);

	i_stream_read(right_in);
	test_assert(strcmp((const char*)i_stream_get_data(right_in, &bytes), "hello, world") == 0);
	i_stream_skip(right_in, bytes);

	test_assert(o_stream_send_str(right_out, "hello, world") > 0);
	o_stream_flush(right_out);
	o_stream_unref(&right_out);
	test_assert(shutdown(sfdr[0], SHUT_WR) == 0);

	counter = 1;
	io_loop_run(ioloop);

	i_stream_read(left_in);
	test_assert(strcmp((const char*)i_stream_get_data(left_in, &bytes), "hello, world") == 0);
	i_stream_skip(left_in, bytes);

	iostream_proxy_unref(&proxy);

	io_loop_destroy(&ioloop);

	i_stream_unref(&left_in);
	i_stream_unref(&right_in);

	/* close fd */
	close(sfdl[0]);
	close(sfdl[1]);
	close(sfdr[0]);
	close(sfdr[1]);

	test_end();
}
Exemplo n.º 23
0
static int __backlight_init(struct backlight *b, char *iface, int fd)
{
	b->fd = fd_move_cloexec(fd_set_nonblock(fd));
	b->iface = iface;
	return 1;
}
Exemplo n.º 24
0
struct sock_conn *sock_ep_connect(struct sock_ep_attr *ep_attr, fi_addr_t index)
{
	int conn_fd = -1, ret;
	int do_retry = sock_conn_retry;
	struct sock_conn *conn, *new_conn;
	struct sockaddr_in addr;
	socklen_t lon;
	int valopt = 0;
	struct pollfd poll_fd;

	if (ep_attr->ep_type == FI_EP_MSG) {
		/* Need to check that destination address has been
		   passed to endpoint */
		assert(ep_attr->dest_addr);
		addr = *ep_attr->dest_addr;
		addr.sin_port = htons(ep_attr->msg_dest_port);
	} else {
		addr = *((struct sockaddr_in *)&ep_attr->av->table[index].addr);
	}

do_connect:
	fastlock_acquire(&ep_attr->cmap.lock);
	conn = sock_ep_lookup_conn(ep_attr, index, &addr);
	fastlock_release(&ep_attr->cmap.lock);

	if (conn != SOCK_CM_CONN_IN_PROGRESS)
		return conn;

	conn_fd = ofi_socket(AF_INET, SOCK_STREAM, 0);
	if (conn_fd == -1) {
		SOCK_LOG_ERROR("failed to create conn_fd, errno: %d\n", errno);
		errno = FI_EOTHER;
		return NULL;
	}

	ret = fd_set_nonblock(conn_fd);
	if (ret) {
		SOCK_LOG_ERROR("failed to set conn_fd nonblocking, errno: %d\n", errno);
		errno = FI_EOTHER;
		ofi_close_socket(conn_fd);
		return NULL;
	}

	SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr),
			ntohs(addr.sin_port));
	SOCK_LOG_DBG("Connecting using address:%s\n",
			inet_ntoa(ep_attr->src_addr->sin_addr));

	ret = connect(conn_fd, (struct sockaddr *) &addr, sizeof addr);
	if (ret < 0) {
		if (ofi_sockerr() == EINPROGRESS) {
			poll_fd.fd = conn_fd;
			poll_fd.events = POLLOUT;

			ret = poll(&poll_fd, 1, 15 * 1000);
			if (ret < 0) {
				SOCK_LOG_DBG("poll failed\n");
				goto retry;
			}

			lon = sizeof(int);
			ret = getsockopt(conn_fd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
			if (ret < 0) {
				SOCK_LOG_DBG("getsockopt failed: %d, %d\n", ret, conn_fd);
				goto retry;
			}

			if (valopt) {
				SOCK_LOG_DBG("Error in connection() %d - %s - %d\n", valopt, strerror(valopt), conn_fd);
				SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr),
						ntohs(addr.sin_port));
				SOCK_LOG_DBG("Connecting using address:%s\n",
				inet_ntoa(ep_attr->src_addr->sin_addr));
				goto retry;
			}
			goto out;
		} else {
			SOCK_LOG_DBG("Timeout or error() - %s: %d\n", strerror(errno), conn_fd);
			SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr),
					ntohs(addr.sin_port));
			SOCK_LOG_DBG("Connecting using address:%s\n",
					inet_ntoa(ep_attr->src_addr->sin_addr));
			goto retry;
		}
	} else {
		goto out;
	}

retry:
	do_retry--;
	sleep(10);
	if (!do_retry)
		goto err;

	if (conn_fd != -1) {
		ofi_close_socket(conn_fd);
		conn_fd = -1;
	}

	SOCK_LOG_ERROR("Connect error, retrying - %s - %d\n", strerror(errno), conn_fd);
	SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr),
			ntohs(addr.sin_port));
	SOCK_LOG_DBG("Connecting using address:%s\n",
			inet_ntoa(ep_attr->src_addr->sin_addr));
        goto do_connect;

out:
	fastlock_acquire(&ep_attr->cmap.lock);
	new_conn = sock_conn_map_insert(ep_attr, &addr, conn_fd, 0);
	if (!new_conn) {
		fastlock_release(&ep_attr->cmap.lock);
		goto err;
	}
	new_conn->av_index = (ep_attr->ep_type == FI_EP_MSG) ? FI_ADDR_NOTAVAIL : index;
	conn = ofi_idm_lookup(&ep_attr->av_idm, index);
	if (conn == SOCK_CM_CONN_IN_PROGRESS) {
		if (ofi_idm_set(&ep_attr->av_idm, index, new_conn) < 0)
			SOCK_LOG_ERROR("ofi_idm_set failed\n");
		conn = new_conn;
	}
	fastlock_release(&ep_attr->cmap.lock);
	return conn;

err:
	ofi_close_socket(conn_fd);
	return NULL;
}
Exemplo n.º 25
0
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
	int* reuseport)
{
	int s;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY)
	int on = 1;
#endif /* SO_REUSEADDR || IPV6_V6ONLY */
	verbose_print_addr(addr);
	*noproto = 0;
	if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
#ifndef USE_WINSOCK
		if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", strerror(errno));
#else
		if(WSAGetLastError() == WSAEAFNOSUPPORT ||
			WSAGetLastError() == WSAEPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", 
			wsa_strerror(WSAGetLastError()));
#endif
		return -1;
	}
#ifdef SO_REUSEADDR
	if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
		(socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
		log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
			strerror(errno));
		close(s);
#else
		log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
			wsa_strerror(WSAGetLastError()));
		closesocket(s);
#endif
		return -1;
	}
#endif /* SO_REUSEADDR */
#ifdef SO_REUSEPORT
	/* try to set SO_REUSEPORT so that incoming
	 * connections are distributed evenly among the receiving threads.
	 * Each thread must have its own socket bound to the same port,
	 * with SO_REUSEPORT set on each socket.
	 */
	if (reuseport && *reuseport &&
		setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
		(socklen_t)sizeof(on)) < 0) {
#ifdef ENOPROTOOPT
		if(errno != ENOPROTOOPT || verbosity >= 3)
			log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
				strerror(errno));
#endif
		/* this option is not essential, we can continue */
		*reuseport = 0;
	}
#else
	(void)reuseport;
#endif /* defined(SO_REUSEPORT) */
#if defined(IPV6_V6ONLY)
	if(addr->ai_family == AF_INET6 && v6only) {
		if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
			(void*)&on, (socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
			log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
				strerror(errno));
			close(s);
#else
			log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
#endif
			return -1;
		}
	}
#else
	(void)v6only;
#endif /* IPV6_V6ONLY */
	if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
#ifndef USE_WINSOCK
		/* detect freebsd jail with no ipv6 permission */
		if(addr->ai_family==AF_INET6 && errno==EINVAL)
			*noproto = 1;
		else {
			log_err_addr("can't bind socket", strerror(errno),
				(struct sockaddr_storage*)addr->ai_addr,
				addr->ai_addrlen);
		}
		close(s);
#else
		log_err_addr("can't bind socket", 
			wsa_strerror(WSAGetLastError()),
			(struct sockaddr_storage*)addr->ai_addr,
			addr->ai_addrlen);
		closesocket(s);
#endif
		return -1;
	}
	if(!fd_set_nonblock(s)) {
#ifndef USE_WINSOCK
		close(s);
#else
		closesocket(s);
#endif
		return -1;
	}
	if(listen(s, TCP_BACKLOG) == -1) {
#ifndef USE_WINSOCK
		log_err("can't listen: %s", strerror(errno));
		close(s);
#else
		log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
		closesocket(s);
#endif
		return -1;
	}
	return s;
}
Exemplo n.º 26
0
int sock_conn_listen(struct sock_ep_attr *ep_attr)
{
	struct addrinfo *s_res = NULL, *p;
	struct addrinfo hints = { 0 };
	int listen_fd = 0, ret;
	socklen_t addr_size;
	struct sockaddr_in addr;
	struct sock_conn_listener *listener = &ep_attr->listener;
	char service[NI_MAXSERV] = {0};
	char *port;
	char ipaddr[24];

	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;

	memcpy(&addr, ep_attr->src_addr, sizeof(addr));
	if (getnameinfo((void *)ep_attr->src_addr, sizeof(*ep_attr->src_addr),
			NULL, 0, listener->service,
			sizeof(listener->service), NI_NUMERICSERV)) {
		SOCK_LOG_ERROR("could not resolve src_addr\n");
		return -FI_EINVAL;
	}

	if (ep_attr->ep_type == FI_EP_MSG) {
		memset(listener->service, 0, NI_MAXSERV);
		port = NULL;
		addr.sin_port = 0;
	} else
		port = listener->service;

	inet_ntop(addr.sin_family, &addr.sin_addr, ipaddr, sizeof(ipaddr));
	ret = getaddrinfo(ipaddr, port, &hints, &s_res);
	if (ret) {
		SOCK_LOG_ERROR("no available AF_INET address, service %s, %s\n",
			       listener->service, gai_strerror(ret));
		return -FI_EINVAL;
	}

	SOCK_LOG_DBG("Binding listener thread to port: %s\n", listener->service);
	for (p = s_res; p; p = p->ai_next) {
		listen_fd = ofi_socket(p->ai_family, p->ai_socktype, p->ai_protocol);
		if (listen_fd >= 0) {
			sock_set_sockopts(listen_fd);

			if (!bind(listen_fd, s_res->ai_addr, s_res->ai_addrlen))
				break;
			ofi_close_socket(listen_fd);
			listen_fd = -1;
		}
	}
	freeaddrinfo(s_res);

	if (listen_fd < 0) {
		SOCK_LOG_ERROR("failed to listen to port: %s\n",
			       listener->service);
		goto err;
	}

	if (atoi(listener->service) == 0) {
		addr_size = sizeof(addr);
		if (getsockname(listen_fd, (struct sockaddr *) &addr, &addr_size))
			goto err;
		snprintf(listener->service, sizeof listener->service, "%d",
			 ntohs(addr.sin_port));
		SOCK_LOG_DBG("Bound to port: %s - %d\n", listener->service, getpid());
		ep_attr->msg_src_port = ntohs(addr.sin_port);
	}

	if (ep_attr->src_addr->sin_addr.s_addr == 0) {
		snprintf(service, sizeof service, "%s", listener->service);
		ret = sock_get_src_addr_from_hostname(ep_attr->src_addr, service);
		if (ret)
			goto err;
	}

	if (listen(listen_fd, sock_cm_def_map_sz)) {
		SOCK_LOG_ERROR("failed to listen socket: %s\n", strerror(errno));
		goto err;
	}

	if (((struct sockaddr_in *) (ep_attr->src_addr))->sin_port == 0) {
		((struct sockaddr_in *) (ep_attr->src_addr))->sin_port =
			htons(atoi(listener->service));
	}

	listener->sock = listen_fd;
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, listener->signal_fds) < 0)
		goto err;

	listener->do_listen = 1;

	fd_set_nonblock(listener->signal_fds[1]);
	if (pthread_create(&listener->listener_thread, 0,
			   _sock_conn_listen, ep_attr)) {
		SOCK_LOG_ERROR("failed to create conn listener thread\n");
		goto err;
	} while (!*((volatile int*)&listener->is_ready));
	return 0;
err:
	if (listen_fd >= 0)
		ofi_close_socket(listen_fd);
	return -FI_EINVAL;
}
Exemplo n.º 27
0
int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, 
        int nonblock)
{
	ssize_t r, d;
	int fd = tube->sr;

	/* test */
	*len = 0;
	if(nonblock) {
		r = read(fd, len, sizeof(*len));
		if(r == -1) {
			if(errno==EINTR || errno==EAGAIN)
				return -1;
			log_err("tube msg read failed: %s", strerror(errno));
			return -1; /* we can still continue, perhaps */
		}
		if(r == 0) /* EOF */
			return 0;
	} else r = 0;
	if(!fd_set_block(fd))
		return 0;
	/* read remainder */
	d = r;
	while(d != (ssize_t)sizeof(*len)) {
		if((r=read(fd, ((char*)len)+d, sizeof(*len)-d)) == -1) {
			log_err("tube msg read failed: %s", strerror(errno));
			(void)fd_set_nonblock(fd);
			return 0;
		}
		if(r == 0) /* EOF */ {
			(void)fd_set_nonblock(fd);
			return 0;
		}
		d += r;
	}
	log_assert(*len < 65536*2);
	*buf = (uint8_t*)malloc(*len);
	if(!*buf) {
		log_err("tube read out of memory");
		(void)fd_set_nonblock(fd);
		return 0;
	}
	d = 0;
	while(d < (ssize_t)*len) {
		if((r=read(fd, (*buf)+d, (size_t)((ssize_t)*len)-d)) == -1) {
			log_err("tube msg read failed: %s", strerror(errno));
			(void)fd_set_nonblock(fd);
			free(*buf);
			return 0;
		}
		if(r == 0) { /* EOF */
			(void)fd_set_nonblock(fd);
			free(*buf);
			return 0;
		}
		d += r;
	}
	if(!fd_set_nonblock(fd)) {
		free(*buf);
		return 0;
	}
	return 1;
}
Exemplo n.º 28
0
/** accept new TCP connections, and set them up */
static void
service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies,
	struct sockaddr_storage* srv_addr, socklen_t srv_len, 
	struct timeval* now, struct timeval* tcp_timeout)
{
	int newfd;
	struct sockaddr_storage addr;
	struct tcp_proxy* p;
	socklen_t addr_len;
	newfd = accept(s, (struct sockaddr*)&addr, &addr_len);
	if(newfd == -1) {
#ifndef USE_WINSOCK
		if(errno == EAGAIN || errno == EINTR)
			return;
		fatal_exit("accept: %s", strerror(errno));
#else
		if(WSAGetLastError() == WSAEWOULDBLOCK || 
			WSAGetLastError() == WSAEINPROGRESS ||
			WSAGetLastError() == WSAECONNRESET)
			return;
		fatal_exit("accept: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
	p = (struct tcp_proxy*)calloc(1, sizeof(*p));
	if(!p) fatal_exit("out of memory");
	memmove(&p->addr, &addr, addr_len);
	p->addr_len = addr_len;
	log_addr(1, "new tcp proxy", &p->addr, p->addr_len);
	p->client_s = newfd;
	p->server_s = socket(addr_is_ip6(srv_addr, srv_len)?AF_INET6:AF_INET,
		SOCK_STREAM, 0);
	if(p->server_s == -1) {
#ifndef USE_WINSOCK
		fatal_exit("tcp socket: %s", strerror(errno));
#else
		fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError()));
#endif
	}
	fd_set_nonblock(p->client_s);
	fd_set_nonblock(p->server_s);
	if(connect(p->server_s, (struct sockaddr*)srv_addr, srv_len) == -1) {
#ifndef USE_WINSOCK
		if(errno != EINPROGRESS) {
			log_err("tcp connect: %s", strerror(errno));
			close(p->server_s);
			close(p->client_s);
#else
		if(WSAGetLastError() != WSAEWOULDBLOCK &&
			WSAGetLastError() != WSAEINPROGRESS) {
			log_err("tcp connect: %s", 
				wsa_strerror(WSAGetLastError()));
			closesocket(p->server_s);
			closesocket(p->client_s);
#endif
			free(p);
			return;
		}
	}
	p->timeout = *now;
	dl_tv_add(&p->timeout, tcp_timeout);

	/* listen to client and server */
	FD_SET(FD_SET_T p->client_s, rorig);
	FD_SET(FD_SET_T p->server_s, rorig);
	if(p->client_s+1 > *max)
		*max = p->client_s+1;
	if(p->server_s+1 > *max)
		*max = p->server_s+1;

	/* add into proxy list */
	p->next = *proxies;
	*proxies = p;
}

/** relay TCP, read a part */
static int
tcp_relay_read(int s, struct tcp_send_list** first, 
	struct tcp_send_list** last, struct timeval* now, 
	struct timeval* delay, sldns_buffer* pkt)
{
	struct tcp_send_list* item;
	ssize_t r = recv(s, (void*)sldns_buffer_begin(pkt), 
		sldns_buffer_capacity(pkt), 0);
	if(r == -1) {
#ifndef USE_WINSOCK
		if(errno == EINTR || errno == EAGAIN)
			return 1;
		log_err("tcp read: %s", strerror(errno));
#else
		if(WSAGetLastError() == WSAEINPROGRESS || 
			WSAGetLastError() == WSAEWOULDBLOCK)
			return 1;
		log_err("tcp read: %s", wsa_strerror(WSAGetLastError()));
#endif
		return 0;
	} else if(r == 0) {
		/* connection closed */
		return 0;
	}
	item = (struct tcp_send_list*)malloc(sizeof(*item));
	if(!item) {
		log_err("out of memory");
		return 0;
	}
	verbose(1, "read item len %d", (int)r);
	item->len = (size_t)r;
	item->item = memdup(sldns_buffer_begin(pkt), item->len);
	if(!item->item) {
		free(item);
		log_err("out of memory");
		return 0;
	}
	item->done = 0;
	item->wait = *now;
	dl_tv_add(&item->wait, delay);
	item->next = NULL;
	
	/* link in */
	if(*first) {
		(*last)->next = item;
	} else {
		*first = item;
	}
	*last = item;
	return 1;
}

/** relay TCP, write a part */
static int
tcp_relay_write(int s, struct tcp_send_list** first, 
	struct tcp_send_list** last, struct timeval* now)
{
	ssize_t r;
	struct tcp_send_list* p;
	while(*first) {
		p = *first;
		/* is the item ready? */
		if(!dl_tv_smaller(&p->wait, now))
			return 1;
		/* write it */
		r = send(s, (void*)(p->item + p->done), p->len - p->done, 0);
		if(r == -1) {
#ifndef USE_WINSOCK
			if(errno == EAGAIN || errno == EINTR)
				return 1;
			log_err("tcp write: %s", strerror(errno));
#else
			if(WSAGetLastError() == WSAEWOULDBLOCK || 
				WSAGetLastError() == WSAEINPROGRESS)
				return 1;
			log_err("tcp write: %s", 
				wsa_strerror(WSAGetLastError()));
#endif
			return 0;
		} else if(r == 0) {
			/* closed */
			return 0;
		}
		/* account it */
		p->done += (size_t)r;
		verbose(1, "write item %d of %d", (int)p->done, (int)p->len);
		if(p->done >= p->len) {
			free(p->item);
			*first = p->next;
			if(!*first)
				*last = NULL;
			free(p);
		} else {
			/* partial write */
			return 1;
		}
	}
	return 1;
}
Exemplo n.º 29
0
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
{
	int s;
#if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
	int on = 1;
#endif /* SO_REUSEADDR || IPV6_V6ONLY */
	verbose_print_addr(addr);
	*noproto = 0;
	if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
#ifndef USE_WINSOCK
		if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", strerror(errno));
#else
		if(WSAGetLastError() == WSAEAFNOSUPPORT ||
			WSAGetLastError() == WSAEPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", 
			wsa_strerror(WSAGetLastError()));
#endif
		return -1;
	}
#ifdef SO_REUSEADDR
	if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
		(socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
		log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
			strerror(errno));
		close(s);
#else
		log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
			wsa_strerror(WSAGetLastError()));
		closesocket(s);
#endif
		return -1;
	}
#endif /* SO_REUSEADDR */
#if defined(IPV6_V6ONLY)
	if(addr->ai_family == AF_INET6 && v6only) {
		if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
			(void*)&on, (socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
			log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
				strerror(errno));
			close(s);
#else
			log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
#endif
			return -1;
		}
	}
#else
	(void)v6only;
#endif /* IPV6_V6ONLY */
	if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
#ifndef USE_WINSOCK
		/* detect freebsd jail with no ipv6 permission */
		if(addr->ai_family==AF_INET6 && errno==EINVAL)
			*noproto = 1;
		else {
			log_err("can't bind socket: %s", strerror(errno));
			log_addr(0, "failed address",
				(struct sockaddr_storage*)addr->ai_addr,
				addr->ai_addrlen);
		}
		close(s);
#else
		log_err("can't bind socket: %s", 
			wsa_strerror(WSAGetLastError()));
		log_addr(0, "failed address",
			(struct sockaddr_storage*)addr->ai_addr,
			addr->ai_addrlen);
		closesocket(s);
#endif
		return -1;
	}
	if(!fd_set_nonblock(s)) {
#ifndef USE_WINSOCK
		close(s);
#else
		closesocket(s);
#endif
		return -1;
	}
	if(listen(s, TCP_BACKLOG) == -1) {
#ifndef USE_WINSOCK
		log_err("can't listen: %s", strerror(errno));
		close(s);
#else
		log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
		closesocket(s);
#endif
		return -1;
	}
	return s;
}
Exemplo n.º 30
0
int
create_udp_sock(int family, int socktype, struct sockaddr* addr,
        socklen_t addrlen, int v6only, int* inuse, int* noproto,
	int rcv, int snd, int listen, int* reuseport)
{
	int s;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU)
	int on=1;
#endif
#ifdef IPV6_MTU
	int mtu = IPV6_MIN_MTU;
#endif
#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
	(void)rcv;
#endif
#if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
	(void)snd;
#endif
#ifndef IPV6_V6ONLY
	(void)v6only;
#endif
	if((s = socket(family, socktype, 0)) == -1) {
		*inuse = 0;
#ifndef USE_WINSOCK
		if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", strerror(errno));
#else
		if(WSAGetLastError() == WSAEAFNOSUPPORT || 
			WSAGetLastError() == WSAEPROTONOSUPPORT) {
			*noproto = 1;
			return -1;
		}
		log_err("can't create socket: %s", 
			wsa_strerror(WSAGetLastError()));
#endif
		*noproto = 0;
		return -1;
	}
	if(listen) {
#ifdef SO_REUSEADDR
		if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
			(socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
			log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
				strerror(errno));
			if(errno != ENOSYS) {
				close(s);
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
#else
			log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
			*noproto = 0;
			*inuse = 0;
			return -1;
#endif
		}
#endif /* SO_REUSEADDR */
#ifdef SO_REUSEPORT
		/* try to set SO_REUSEPORT so that incoming
		 * queries are distributed evenly among the receiving threads.
		 * Each thread must have its own socket bound to the same port,
		 * with SO_REUSEPORT set on each socket.
		 */
		if (reuseport && *reuseport &&
		    setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
			(socklen_t)sizeof(on)) < 0) {
#ifdef ENOPROTOOPT
			if(errno != ENOPROTOOPT || verbosity >= 3)
				log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
					strerror(errno));
#endif
			/* this option is not essential, we can continue */
			*reuseport = 0;
		}
#else
		(void)reuseport;
#endif /* defined(SO_REUSEPORT) */
	}
	if(rcv) {
#ifdef SO_RCVBUF
		int got;
		socklen_t slen = (socklen_t)sizeof(got);
#  ifdef SO_RCVBUFFORCE
		/* Linux specific: try to use root permission to override
		 * system limits on rcvbuf. The limit is stored in 
		 * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
		if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv, 
			(socklen_t)sizeof(rcv)) < 0) {
			if(errno != EPERM) {
#    ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_RCVBUFFORCE, "
					"...) failed: %s", strerror(errno));
				close(s);
#    else
				log_err("setsockopt(..., SO_RCVBUFFORCE, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#    endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
#  endif /* SO_RCVBUFFORCE */
			if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, 
				(socklen_t)sizeof(rcv)) < 0) {
#  ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_RCVBUF, "
					"...) failed: %s", strerror(errno));
				close(s);
#  else
				log_err("setsockopt(..., SO_RCVBUF, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#  endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
			/* check if we got the right thing or if system
			 * reduced to some system max.  Warn if so */
			if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got, 
				&slen) >= 0 && got < rcv/2) {
				log_warn("so-rcvbuf %u was not granted. "
					"Got %u. To fix: start with "
					"root permissions(linux) or sysctl "
					"bigger net.core.rmem_max(linux) or "
					"kern.ipc.maxsockbuf(bsd) values.",
					(unsigned)rcv, (unsigned)got);
			}
#  ifdef SO_RCVBUFFORCE
		}
#  endif
#endif /* SO_RCVBUF */
	}
	/* first do RCVBUF as the receive buffer is more important */
	if(snd) {
#ifdef SO_SNDBUF
		int got;
		socklen_t slen = (socklen_t)sizeof(got);
#  ifdef SO_SNDBUFFORCE
		/* Linux specific: try to use root permission to override
		 * system limits on sndbuf. The limit is stored in 
		 * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
		if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, 
			(socklen_t)sizeof(snd)) < 0) {
			if(errno != EPERM) {
#    ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_SNDBUFFORCE, "
					"...) failed: %s", strerror(errno));
				close(s);
#    else
				log_err("setsockopt(..., SO_SNDBUFFORCE, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#    endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
#  endif /* SO_SNDBUFFORCE */
			if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, 
				(socklen_t)sizeof(snd)) < 0) {
#  ifndef USE_WINSOCK
				log_err("setsockopt(..., SO_SNDBUF, "
					"...) failed: %s", strerror(errno));
				close(s);
#  else
				log_err("setsockopt(..., SO_SNDBUF, "
					"...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#  endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
			/* check if we got the right thing or if system
			 * reduced to some system max.  Warn if so */
			if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got, 
				&slen) >= 0 && got < snd/2) {
				log_warn("so-sndbuf %u was not granted. "
					"Got %u. To fix: start with "
					"root permissions(linux) or sysctl "
					"bigger net.core.wmem_max(linux) or "
					"kern.ipc.maxsockbuf(bsd) values.",
					(unsigned)snd, (unsigned)got);
			}
#  ifdef SO_SNDBUFFORCE
		}
#  endif
#endif /* SO_SNDBUF */
	}
	if(family == AF_INET6) {
# if defined(IPV6_V6ONLY)
		if(v6only) {
			int val=(v6only==2)?0:1;
			if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
				(void*)&val, (socklen_t)sizeof(val)) < 0) {
#ifndef USE_WINSOCK
				log_err("setsockopt(..., IPV6_V6ONLY"
					", ...) failed: %s", strerror(errno));
				close(s);
#else
				log_err("setsockopt(..., IPV6_V6ONLY"
					", ...) failed: %s", 
					wsa_strerror(WSAGetLastError()));
				closesocket(s);
#endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
		}
# endif
# if defined(IPV6_USE_MIN_MTU)
		/*
		 * There is no fragmentation of IPv6 datagrams
		 * during forwarding in the network. Therefore
		 * we do not send UDP datagrams larger than
		 * the minimum IPv6 MTU of 1280 octets. The
		 * EDNS0 message length can be larger if the
		 * network stack supports IPV6_USE_MIN_MTU.
		 */
		if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
			(void*)&on, (socklen_t)sizeof(on)) < 0) {
#  ifndef USE_WINSOCK
			log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
				"...) failed: %s", strerror(errno));
			close(s);
#  else
			log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
				"...) failed: %s", 
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
#  endif
			*noproto = 0;
			*inuse = 0;
			return -1;
		}
# elif defined(IPV6_MTU)
		/*
		 * On Linux, to send no larger than 1280, the PMTUD is
		 * disabled by default for datagrams anyway, so we set
		 * the MTU to use.
		 */
		if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
			(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
#  ifndef USE_WINSOCK
			log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
				strerror(errno));
			close(s);
#  else
			log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
				wsa_strerror(WSAGetLastError()));
			closesocket(s);
#  endif
			*noproto = 0;
			*inuse = 0;
			return -1;
		}
# endif /* IPv6 MTU */
	} else if(family == AF_INET) {
#  if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
/* linux 3.15 has IP_PMTUDISC_OMIT, Hannes Frederic Sowa made it so that
 * PMTU information is not accepted, but fragmentation is allowed
 * if and only if the packet size exceeds the outgoing interface MTU
 * (and also uses the interface mtu to determine the size of the packets).
 * So there won't be any EMSGSIZE error.  Against DNS fragmentation attacks.
 * FreeBSD already has same semantics without setting the option. */
		int omit_set = 0;
		int action;
#   if defined(IP_PMTUDISC_OMIT)
		action = IP_PMTUDISC_OMIT;
		if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, 
			&action, (socklen_t)sizeof(action)) < 0) {

			if (errno != EINVAL) {
				log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s",
					strerror(errno));

#    ifndef USE_WINSOCK
				close(s);
#    else
				closesocket(s);
#    endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
		}
		else
		{
		    omit_set = 1;
		}
#   endif
		if (omit_set == 0) {
   			action = IP_PMTUDISC_DONT;
			if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
				&action, (socklen_t)sizeof(action)) < 0) {
				log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s",
					strerror(errno));
#    ifndef USE_WINSOCK
				close(s);
#    else
				closesocket(s);
#    endif
				*noproto = 0;
				*inuse = 0;
				return -1;
			}
		}
#  elif defined(IP_DONTFRAG)
		int off = 0;
		if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, 
			&off, (socklen_t)sizeof(off)) < 0) {
			log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
				strerror(errno));
#    ifndef USE_WINSOCK
			close(s);
#    else
			closesocket(s);
#    endif
			*noproto = 0;
			*inuse = 0;
			return -1;
		}
#  endif /* IPv4 MTU */
	}
	if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
		*noproto = 0;
		*inuse = 0;
#ifndef USE_WINSOCK
#ifdef EADDRINUSE
		*inuse = (errno == EADDRINUSE);
		/* detect freebsd jail with no ipv6 permission */
		if(family==AF_INET6 && errno==EINVAL)
			*noproto = 1;
		else if(errno != EADDRINUSE) {
			log_err_addr("can't bind socket", strerror(errno),
				(struct sockaddr_storage*)addr, addrlen);
		}
#endif /* EADDRINUSE */
		close(s);
#else /* USE_WINSOCK */
		if(WSAGetLastError() != WSAEADDRINUSE &&
			WSAGetLastError() != WSAEADDRNOTAVAIL) {
			log_err_addr("can't bind socket", 
				wsa_strerror(WSAGetLastError()),
				(struct sockaddr_storage*)addr, addrlen);
		}
		closesocket(s);
#endif
		return -1;
	}
	if(!fd_set_nonblock(s)) {
		*noproto = 0;
		*inuse = 0;
#ifndef USE_WINSOCK
		close(s);
#else
		closesocket(s);
#endif
		return -1;
	}
	return s;
}