Esempio n. 1
0
/*
  initialise a nbt_dgram_socket. The event_ctx is optional, if provided
  then operations will use that event context
*/
struct nbt_dgram_socket *nbt_dgram_socket_init(TALLOC_CTX *mem_ctx, 
					      struct tevent_context *event_ctx)
{
	struct nbt_dgram_socket *dgmsock;
	NTSTATUS status;

	dgmsock = talloc(mem_ctx, struct nbt_dgram_socket);
	if (dgmsock == NULL) goto failed;

	dgmsock->event_ctx = event_ctx;
	if (dgmsock->event_ctx == NULL) goto failed;

	status = socket_create("ip", SOCKET_TYPE_DGRAM, &dgmsock->sock, 0);
	if (!NT_STATUS_IS_OK(status)) goto failed;

	socket_set_option(dgmsock->sock, "SO_BROADCAST", "1");

	talloc_steal(dgmsock, dgmsock->sock);

	dgmsock->fde = tevent_add_fd(dgmsock->event_ctx, dgmsock,
				    socket_get_fd(dgmsock->sock), 0,
				    dgm_socket_handler, dgmsock);

	dgmsock->send_queue = NULL;
	dgmsock->incoming.handler = NULL;
	dgmsock->mailslot_handlers = NULL;
	
	return dgmsock;

failed:
	talloc_free(dgmsock);
	return NULL;
}
Esempio n. 2
0
static NTSTATUS ipv6_listen(struct socket_context *sock,
			    const struct socket_address *my_address,
			    int queue_size, uint32_t flags)
{
	struct sockaddr_in6 my_addr;
	struct in6_addr ip_addr;
	int ret;

	socket_set_option(sock, "SO_REUSEADDR=1", NULL);

	if (my_address->sockaddr) {
		ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen);
	} else {
		int one = 1;
		ip_addr = interpret_addr6(my_address->addr);
		
		ZERO_STRUCT(my_addr);
		my_addr.sin6_addr	= ip_addr;
		my_addr.sin6_port	= htons(my_address->port);
		my_addr.sin6_family	= PF_INET6;
		fix_scope_id(&my_addr, my_address->addr);

		/* when binding on ipv6 we always want to only bind on v6 */
		ret = setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
				 (const void *)&one, sizeof(one));
		if (ret != -1) {
			ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
		}
	}

	if (ret == -1) {
		return map_nt_error_from_unix_common(errno);
	}

	if (sock->type == SOCKET_TYPE_STREAM) {
		ret = listen(sock->fd, queue_size);
		if (ret == -1) {
			return map_nt_error_from_unix_common(errno);
		}
	}

	if (!(flags & SOCKET_FLAG_BLOCK)) {
		ret = set_blocking(sock->fd, false);
		if (ret == -1) {
			return map_nt_error_from_unix_common(errno);
		}
	}

	sock->state= SOCKET_STATE_SERVER_LISTEN;

	return NT_STATUS_OK;
}
Esempio n. 3
0
/*
  note that for simplicity of the API, socket_listen() is also
  use for DGRAM sockets, but in reality only a bind() is done
*/
static NTSTATUS ipv4_listen(struct socket_context *sock,
			    const struct socket_address *my_address, 
			    int queue_size, uint32_t flags)
{
	struct sockaddr_in my_addr;
	struct in_addr ip_addr;
	int ret;

	socket_set_option(sock, "SO_REUSEADDR=1", NULL);

	if (my_address->sockaddr) {
		ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen);
	} else {
		ip_addr = interpret_addr2(my_address->addr);
		
		ZERO_STRUCT(my_addr);
#ifdef HAVE_SOCK_SIN_LEN
		my_addr.sin_len		= sizeof(my_addr);
#endif
		my_addr.sin_addr.s_addr	= ip_addr.s_addr;
		my_addr.sin_port	= htons(my_address->port);
		my_addr.sin_family	= PF_INET;
		
		ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
	}

	if (ret == -1) {
		return map_nt_error_from_unix_common(errno);
	}

	if (sock->type == SOCKET_TYPE_STREAM) {
		ret = listen(sock->fd, queue_size);
		if (ret == -1) {
			return map_nt_error_from_unix_common(errno);
		}
	}

	if (!(flags & SOCKET_FLAG_BLOCK)) {
		ret = set_blocking(sock->fd, false);
		if (ret == -1) {
			return map_nt_error_from_unix_common(errno);
		}
	}

	sock->state= SOCKET_STATE_SERVER_LISTEN;

	return NT_STATUS_OK;
}
Esempio n. 4
0
/*
  setup a listen stream socket
  if you pass *port == 0, then a port > 1024 is used

  FIXME: This function is TCP/IP specific - uses an int rather than 
  	 a string for the port. Should leave allocating a port nr 
         to the socket implementation - JRV20070903
 */
NTSTATUS stream_setup_socket(TALLOC_CTX *mem_ctx,
			     struct tevent_context *event_context,
			     struct loadparm_context *lp_ctx,
			     const struct model_ops *model_ops,
			     const struct stream_server_ops *stream_ops,
			     const char *family,
			     const char *sock_addr,
			     uint16_t *port,
			     const char *socket_options,
			     void *private_data)
{
	NTSTATUS status;
	struct stream_socket *stream_socket;
	struct socket_address *socket_address;
	struct tevent_fd *fde;
	int i;
	struct sockaddr_storage ss;

	stream_socket = talloc_zero(mem_ctx, struct stream_socket);
	NT_STATUS_HAVE_NO_MEMORY(stream_socket);

	if (strcmp(family, "ip") == 0) {
		/* we will get the real family from the address itself */
		if (!interpret_string_addr(&ss, sock_addr, 0)) {
			talloc_free(stream_socket);
			return NT_STATUS_INVALID_ADDRESS;
		}

		socket_address = socket_address_from_sockaddr_storage(stream_socket, &ss, port?*port:0);
		NT_STATUS_HAVE_NO_MEMORY_AND_FREE(socket_address, stream_socket);

		status = socket_create(socket_address->family, SOCKET_TYPE_STREAM, &stream_socket->sock, 0);
		NT_STATUS_NOT_OK_RETURN(status);
	} else {
		status = socket_create(family, SOCKET_TYPE_STREAM, &stream_socket->sock, 0);
		NT_STATUS_NOT_OK_RETURN(status);

		/* this is for non-IP sockets, eg. unix domain sockets */
		socket_address = socket_address_from_strings(stream_socket,
							     stream_socket->sock->backend_name,
							     sock_addr, port?*port:0);
		NT_STATUS_HAVE_NO_MEMORY(socket_address);
	}


	talloc_steal(stream_socket, stream_socket->sock);

	stream_socket->lp_ctx = talloc_reference(stream_socket, lp_ctx);

	/* ready to listen */
	status = socket_set_option(stream_socket->sock, "SO_KEEPALIVE", NULL);
	NT_STATUS_NOT_OK_RETURN(status);

	if (socket_options != NULL) {
		status = socket_set_option(stream_socket->sock, socket_options, NULL);
		NT_STATUS_NOT_OK_RETURN(status);
	}

	/* TODO: set socket ACL's (host allow etc) here when they're
	 * implemented */

	/* Some sockets don't have a port, or are just described from
	 * the string.  We are indicating this by having port == NULL */
	if (!port) {
		status = socket_listen(stream_socket->sock, socket_address, SERVER_LISTEN_BACKLOG, 0);
	} else if (*port == 0) {
		for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
			socket_address->port = i;
			status = socket_listen(stream_socket->sock, socket_address, 
					       SERVER_LISTEN_BACKLOG, 0);
			if (NT_STATUS_IS_OK(status)) {
				*port = i;
				break;
			}
		}
	} else {
		status = socket_listen(stream_socket->sock, socket_address, SERVER_LISTEN_BACKLOG, 0);
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Failed to listen on %s:%u - %s\n",
			 sock_addr, port ? (unsigned int)(*port) : 0,
			 nt_errstr(status)));
		talloc_free(stream_socket);
		return status;
	}

	/* Add the FD from the newly created socket into the event
	 * subsystem.  it will call the accept handler whenever we get
	 * new connections */

	fde = tevent_add_fd(event_context, stream_socket->sock,
			    socket_get_fd(stream_socket->sock),
			    TEVENT_FD_READ,
			    stream_accept_handler, stream_socket);
	if (!fde) {
		DEBUG(0,("Failed to setup fd event\n"));
		talloc_free(stream_socket);
		return NT_STATUS_NO_MEMORY;
	}

	/* we let events system to the close on the socket. This avoids
	 * nasty interactions with waiting for talloc to close the socket. */
	tevent_fd_set_close_fn(fde, socket_tevent_fd_close_fn);
	socket_set_flags(stream_socket->sock, SOCKET_FLAG_NOCLOSE);

	stream_socket->private_data     = talloc_reference(stream_socket, private_data);
	stream_socket->ops              = stream_ops;
	stream_socket->event_ctx	= event_context;
	stream_socket->model_ops        = model_ops;

	return NT_STATUS_OK;
}
Esempio n. 5
0
	void set_option(const OPTION& opt) {
		static_assert(is_option<OPTION>::VALUE, "you must specify a valid option");

		socket_set_option(hdl, OPTION::NAME, reinterpret_cast<const void*>(&opt.value), sizeof(opt.value));
	}