Exemplo n.º 1
0
int socket_listen(SocketAddress *addr, Error **errp)
{
    int fd;

    switch (addr->type) {
    case SOCKET_ADDRESS_TYPE_INET:
        fd = inet_listen_saddr(&addr->u.inet, 0, errp);
        break;

    case SOCKET_ADDRESS_TYPE_UNIX:
        fd = unix_listen_saddr(&addr->u.q_unix, errp);
        break;

    case SOCKET_ADDRESS_TYPE_FD:
        fd = socket_get_fd(addr->u.fd.str, errp);
        break;

    case SOCKET_ADDRESS_TYPE_VSOCK:
        fd = vsock_listen_saddr(&addr->u.vsock, errp);
        break;

    default:
        abort();
    }
    return fd;
}
Exemplo n.º 2
0
static void named_pipe_accept(struct stream_connection *conn)
{
	struct tstream_context *plain_tstream;
	int fd;
	struct tevent_req *subreq;
	int ret;

	/* Let tstream take over fd operations */

	fd = socket_get_fd(conn->socket);
	socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);
	TALLOC_FREE(conn->event.fde);
	TALLOC_FREE(conn->socket);

	ret = tstream_bsd_existing_socket(conn, fd, &plain_tstream);
	if (ret != 0) {
		stream_terminate_connection(conn,
				"named_pipe_accept: out of memory");
		return;
	}

	subreq = tstream_npa_accept_existing_send(conn, conn->event.ctx,
						  plain_tstream,
						  FILE_TYPE_MESSAGE_MODE_PIPE,
						  0xff | 0x0400 | 0x0100,
						  4096);
	if (subreq == NULL) {
		stream_terminate_connection(conn,
			"named_pipe_accept: "
			"no memory for tstream_npa_accept_existing_send");
		return;
	}
	tevent_req_set_callback(subreq, named_pipe_accept_done, conn);
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
void sigint_handler(int signum)
{
    // do cleanups here and free all existing variables and stuff
    log_out("Closing client on: %d...\n", socket_get_fd(s));
    socket_close(s);
    exit(signum);
}
Exemplo n.º 5
0
Arquivo: kdc.c Projeto: Arkhont/samba
/*
  called when we get a new connection
*/
static void kdc_tcp_accept(struct stream_connection *conn)
{
	struct kdc_socket *kdc_socket;
	struct kdc_tcp_connection *kdc_conn;
	struct tevent_req *subreq;
	int rc;

	kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
	if (kdc_conn == NULL) {
		stream_terminate_connection(conn,
				"kdc_tcp_accept: out of memory");
		return;
	}

	kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
	if (kdc_conn->send_queue == NULL) {
		stream_terminate_connection(conn,
				"kdc_tcp_accept: out of memory");
		return;
	}

	kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);

	TALLOC_FREE(conn->event.fde);

	rc = tstream_bsd_existing_socket(kdc_conn,
			socket_get_fd(conn->socket),
			&kdc_conn->tstream);
	if (rc < 0) {
		stream_terminate_connection(conn,
				"kdc_tcp_accept: out of memory");
		return;
	}

	kdc_conn->conn = conn;
	kdc_conn->kdc_socket = kdc_socket;
	conn->private_data = kdc_conn;

	/*
	 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
	 * packet_full_request_u32 provides the pdu length then.
	 */
	subreq = tstream_read_pdu_blob_send(kdc_conn,
					    kdc_conn->conn->event.ctx,
					    kdc_conn->tstream,
					    4, /* initial_read_size */
					    packet_full_request_u32,
					    kdc_conn);
	if (subreq == NULL) {
		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
}
Exemplo n.º 6
0
/*
  create a transport structure based on an established socket
*/
struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
					       TALLOC_CTX *parent_ctx, 
					       bool primary, 
					       struct smbcli_options *options)
{
	struct smbcli_transport *transport;

	transport = talloc_zero(parent_ctx, struct smbcli_transport);
	if (!transport) return NULL;

	if (primary) {
		transport->socket = talloc_steal(transport, sock);
	} else {
		transport->socket = talloc_reference(transport, sock);
	}
	transport->negotiate.protocol = PROTOCOL_NT1;
	transport->options = *options;
	transport->negotiate.max_xmit = transport->options.max_xmit;

	/* setup the stream -> packet parser */
	transport->packet = packet_init(transport);
	if (transport->packet == NULL) {
		talloc_free(transport);
		return NULL;
	}
	packet_set_private(transport->packet, transport);
	packet_set_socket(transport->packet, transport->socket->sock);
	packet_set_callback(transport->packet, smbcli_transport_finish_recv);
	packet_set_full_request(transport->packet, packet_full_request_nbt);
	packet_set_error_handler(transport->packet, smbcli_transport_error);
	packet_set_event_context(transport->packet, transport->socket->event.ctx);
	packet_set_nofree(transport->packet);
	packet_set_initial_read(transport->packet, 4);

	smbcli_init_signing(transport);

	ZERO_STRUCT(transport->called);

	/* take over event handling from the socket layer - it only
	   handles events up until we are connected */
	talloc_free(transport->socket->event.fde);
	transport->socket->event.fde = event_add_fd(transport->socket->event.ctx,
						    transport->socket->sock,
						    socket_get_fd(transport->socket->sock),
						    EVENT_FD_READ,
						    smbcli_transport_event_handler,
						    transport);

	packet_set_fde(transport->packet, transport->socket->event.fde);
	packet_set_serialise(transport->packet);
	talloc_set_destructor(transport, transport_destructor);

	return transport;
}
Exemplo n.º 7
0
static void wbsrv_accept(struct stream_connection *conn)
{
	struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data,
								   struct wbsrv_listen_socket);
	struct wbsrv_connection *wbsrv_conn;
	struct tevent_req *subreq;
	int rc;

	wbsrv_conn = talloc_zero(conn, struct wbsrv_connection);
	if (wbsrv_conn == NULL) {
		stream_terminate_connection(conn, "wbsrv_accept: out of memory");
		return;
	}

	wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept");
	if (wbsrv_conn->send_queue == NULL) {
		stream_terminate_connection(conn,
				"wbsrv_accept: out of memory");
		return;
	}

	TALLOC_FREE(conn->event.fde);

	rc = tstream_bsd_existing_socket(wbsrv_conn,
			socket_get_fd(conn->socket),
			&wbsrv_conn->tstream);
	if (rc < 0) {
		stream_terminate_connection(conn,
				"wbsrv_accept: out of memory");
		return;
	}

	wbsrv_conn->conn = conn;
	wbsrv_conn->listen_socket = wbsrv_socket;
	wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx;
	conn->private_data = wbsrv_conn;

	/*
	 * The winbind pdu's has the length as 4 byte (initial_read_size),
	 * wbsrv_samba3_packet_full_request provides the pdu length then.
	 */
	subreq = tstream_read_pdu_blob_send(wbsrv_conn,
					    wbsrv_conn->conn->event.ctx,
					    wbsrv_conn->tstream,
					    4, /* initial_read_size */
					    wbsrv_samba3_packet_full_request,
					    wbsrv_conn);
	if (subreq == NULL) {
		wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
}
Exemplo n.º 8
0
/**
 requires valid_vector(sockets);

 */
pollsocket_t* pollsocket_create(vector* sockets){

    if (sockets == NULL){
        return NULL;
    }

    size_t num_sockets = vector_count(sockets);

    // Validate all sockets before adding
    unsigned int valid_count = 0;
    size_t valid_indices[num_sockets];

    for (size_t i = 0; i < num_sockets; ++i){
        socket_t* s = vector_get(sockets, i);
        sstatus_t socket_status = socket_get_status(s);

        if (socket_status == SOCKET_OPEN)
        {
            valid_indices[valid_count] = i;
            ++valid_count;
        }
    }

    // Create a pollsocket_t* with valid descriptors
    pollsocket_t* ps = calloc(1, sizeof(pollsocket_t));
    if (ps == NULL){
        log_error("%s, %d: Could not malloc for pollsocket_t\n", __func__, __LINE__);
        return NULL;
    }


    // Track the count and sockets vector
    ps->size = valid_count;
    ps->sockets = sockets;

    // Malloc valid_count number of pollfds
    ps->pfds = calloc(valid_count, sizeof(struct pollfd));

    for (unsigned int i = 0; i < valid_count; ++i){
        unsigned int idx = valid_indices[i];

        // Match corresponding socket
        socket_t* s = vector_get(sockets, idx);
        (ps->pfds[i]).fd = socket_get_fd(s);
        (ps->pfds[i]).revents = 0;
    }

    return ps;
}
Exemplo n.º 9
0
_PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
					 struct socket_context **new_sock, 
					 enum socket_type type, uint32_t flags)
{
	NTSTATUS status;

	(*new_sock) = talloc(mem_ctx, struct socket_context);
	if (!(*new_sock)) {
		return NT_STATUS_NO_MEMORY;
	}

	(*new_sock)->type = type;
	(*new_sock)->state = SOCKET_STATE_UNDEFINED;
	(*new_sock)->flags = flags;

	(*new_sock)->fd = -1;

	(*new_sock)->private_data = NULL;
	(*new_sock)->ops = ops;
	(*new_sock)->backend_name = NULL;

	status = (*new_sock)->ops->fn_init((*new_sock));
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(*new_sock);
		return status;
	}

	/* by enabling "testnonblock" mode, all socket receive and
	   send calls on non-blocking sockets will randomly recv/send
	   less data than requested */

	if (!(flags & SOCKET_FLAG_BLOCK) &&
	    type == SOCKET_TYPE_STREAM &&
		getenv("SOCKET_TESTNONBLOCK") != NULL) {
		(*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK;
	}

	/* we don't do a connect() on dgram sockets, so need to set
	   non-blocking at socket create time */
	if (!(flags & SOCKET_FLAG_BLOCK) && type == SOCKET_TYPE_DGRAM) {
		set_blocking(socket_get_fd(*new_sock), false);
	}

	talloc_set_destructor(*new_sock, socket_destructor);

	return NT_STATUS_OK;
}
Exemplo n.º 10
0
/*
  initialise a wrepl_socket from an already existing connection
*/
struct wrepl_socket *wrepl_socket_merge(TALLOC_CTX *mem_ctx,
                                        struct tevent_context *event_ctx,
                                        struct socket_context *sock,
                                        struct packet_context *pack)
{
    struct wrepl_socket *wrepl_socket;

    wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket);
    if (wrepl_socket == NULL) goto failed;

    wrepl_socket->event.ctx = talloc_reference(wrepl_socket, event_ctx);
    if (wrepl_socket->event.ctx == NULL) goto failed;

    wrepl_socket->sock = sock;
    talloc_steal(wrepl_socket, wrepl_socket->sock);


    wrepl_socket->request_timeout	= WREPL_SOCKET_REQUEST_TIMEOUT;

    wrepl_socket->event.fde = event_add_fd(wrepl_socket->event.ctx, wrepl_socket,
                                           socket_get_fd(wrepl_socket->sock),
                                           EVENT_FD_READ,
                                           wrepl_handler, wrepl_socket);
    if (wrepl_socket->event.fde == NULL) {
        goto failed;
    }

    wrepl_socket->packet = pack;
    talloc_steal(wrepl_socket, wrepl_socket->packet);
    packet_set_private(wrepl_socket->packet, wrepl_socket);
    packet_set_socket(wrepl_socket->packet, wrepl_socket->sock);
    packet_set_callback(wrepl_socket->packet, wrepl_finish_recv);
    packet_set_full_request(wrepl_socket->packet, packet_full_request_u32);
    packet_set_error_handler(wrepl_socket->packet, wrepl_error);
    packet_set_event_context(wrepl_socket->packet, wrepl_socket->event.ctx);
    packet_set_fde(wrepl_socket->packet, wrepl_socket->event.fde);
    packet_set_serialise(wrepl_socket->packet);

    talloc_set_destructor(wrepl_socket, wrepl_socket_destructor);

    return wrepl_socket;

failed:
    talloc_free(wrepl_socket);
    return NULL;
}
Exemplo n.º 11
0
/*
  initialise a server_context from a open socket and register a event handler
  for reading from that socket
*/
static void samba3_smb_accept(struct stream_connection *conn)
{
	int i;
	int fd = socket_get_fd(conn->socket);
	const char *prog;
	char *argv[2];
	char *reason;

	close(0);
	close(1);
	dup2(fd, 0);
	dup2(fd, 1);
	dup2(fd, 2);
	for (i=3;i<256;i++) {
		close(i);
	}

	prog = lpcfg_parm_string(conn->lp_ctx, NULL, "samba3", "smbd");

	if (prog == NULL) {
		argv[0] = talloc_asprintf(conn, "%s/%s", dyn_BINDIR, "smbd3");
	}
	else {
		argv[0] = talloc_strdup(conn, prog);
	}

	if (argv[0] == NULL) {
		stream_terminate_connection(conn, "out of memory");
		return;
	}
	argv[1] = NULL;

	execv(argv[0], argv);

	/*
	 * Should never get here
	 */
	reason = talloc_asprintf(conn, "Could not execute %s", argv[0]);
	if (reason == NULL) {
		stream_terminate_connection(conn, "out of memory");
		return;
	}
	stream_terminate_connection(conn, reason);
	talloc_free(reason);
}
Exemplo n.º 12
0
/*
  called when a listening socket becomes readable. 
*/
static void single_accept_connection(struct tevent_context *ev, 
				     struct loadparm_context *lp_ctx,
				     struct socket_context *listen_socket,
				     void (*new_conn)(struct tevent_context *, 
						      struct loadparm_context *,
						      struct socket_context *, 
						      struct server_id , void *), 
				     void *private_data)
{
	NTSTATUS status;
	struct socket_context *connected_socket;
	pid_t pid = getpid();

	/* accept an incoming connection. */
	status = socket_accept(listen_socket, &connected_socket);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("single_accept_connection: accept: %s\n", nt_errstr(status)));
		/* this looks strange, but is correct. 

		   We can only be here if woken up from select, due to
		   an incoming connection.

		   We need to throttle things until the system clears
		   enough resources to handle this new socket. 

		   If we don't then we will spin filling the log and
		   causing more problems. We don't panic as this is
		   probably a temporary resource constraint */
		sleep(1);
		return;
	}

	talloc_steal(private_data, connected_socket);

	/*
	 * We use the PID so we cannot collide in with cluster ids
	 * generated in other single mode tasks, and, and won't
	 * collide with PIDs from process model standard because a the
	 * combination of pid/fd should be unique system-wide
	 */
	new_conn(ev, lp_ctx, connected_socket,
		 cluster_id(pid, socket_get_fd(connected_socket)), private_data);
}
Exemplo n.º 13
0
/*
  called when a listening socket becomes readable.
*/
static void prefork_accept_connection(
	struct tevent_context *ev,
	struct loadparm_context *lp_ctx,
	struct socket_context *listen_socket,
	void (*new_conn)(struct tevent_context *,
			struct loadparm_context *,
			struct socket_context *,
			struct server_id,
			void *,
			void *),
	void *private_data,
	void *process_context)
{
	NTSTATUS status;
	struct socket_context *connected_socket;
	pid_t pid = getpid();

	/* accept an incoming connection. */
	status = socket_accept(listen_socket, &connected_socket);
	if (!NT_STATUS_IS_OK(status)) {
		/*
		 * For prefork we can ignore STATUS_MORE_ENTRIES, as  once a
		 * connection becomes available all waiting processes are
		 * woken, but only one gets work to  process.
		 * AKA the thundering herd.
		 * In the short term this should not be an issue as the number
		 * of workers should be a small multiple of the number of cpus
		 * In the longer term socket_accept needs to implement a
		 * mutex/semaphore (like apache does) to serialise the accepts
		 */
		if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
			DBG_ERR("Worker process (%d), error in accept [%s]\n",
				getpid(), nt_errstr(status));
		}
		return;
	}

	talloc_steal(private_data, connected_socket);

	new_conn(ev, lp_ctx, connected_socket,
		 cluster_id(pid, socket_get_fd(connected_socket)),
		 private_data, process_context);
}
Exemplo n.º 14
0
/*
  called when a listening socket becomes readable.
*/
static void onefork_accept_connection(struct tevent_context *ev,
				      struct loadparm_context *lp_ctx,
				      struct socket_context *listen_socket,
				       void (*new_conn)(struct tevent_context *,
							struct loadparm_context *, struct socket_context *,
							struct server_id , void *),
				       void *private_data)
{
	NTSTATUS status;
	struct socket_context *connected_socket;
	pid_t pid = getpid();

	/* accept an incoming connection. */
	status = socket_accept(listen_socket, &connected_socket);
	if (!NT_STATUS_IS_OK(status)) {
		return;
	}

	talloc_steal(private_data, connected_socket);

	new_conn(ev, lp_ctx, connected_socket, cluster_id(pid, socket_get_fd(connected_socket)), private_data);
}
Exemplo n.º 15
0
static NTSTATUS gensec_socket_set_option(struct socket_context *sock, const char *option, const char *val)
{
	set_socket_options(socket_get_fd(sock), option);
	return NT_STATUS_OK;
}
krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
					    void *data,
					    krb5_krbhst_info *hi,
					    time_t timeout,
					    const krb5_data *send_buf,
					    krb5_data *recv_buf)
{
	krb5_error_code ret;
	NTSTATUS status;
	const char *name;
	struct addrinfo *ai, *a;
	struct smb_krb5_socket *smb_krb5;

	DATA_BLOB send_blob;

	struct tevent_context *ev;
	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		return ENOMEM;
	}

	if (!data) {
		/* If no event context was available, then create one for this loop */
		ev = samba_tevent_context_init(tmp_ctx);
		if (!ev) {
			talloc_free(tmp_ctx);
			return ENOMEM;
		}
	} else {
		ev = talloc_get_type_abort(data, struct tevent_context);
	}

	send_blob = data_blob_const(send_buf->data, send_buf->length);

	ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
	if (ret) {
		talloc_free(tmp_ctx);
		return ret;
	}

	for (a = ai; a; a = a->ai_next) {
		struct socket_address *remote_addr;
		smb_krb5 = talloc(tmp_ctx, struct smb_krb5_socket);
		if (!smb_krb5) {
			talloc_free(tmp_ctx);
			return ENOMEM;
		}
		smb_krb5->hi = hi;

		switch (a->ai_family) {
		case PF_INET:
			name = "ipv4";
			break;
#ifdef HAVE_IPV6
		case PF_INET6:
			name = "ipv6";
			break;
#endif
		default:
			talloc_free(tmp_ctx);
			return EINVAL;
		}

		status = NT_STATUS_INVALID_PARAMETER;
		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_TCP:
			status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		talloc_steal(smb_krb5, smb_krb5->sock);

		remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
		if (!remote_addr) {
			talloc_free(smb_krb5);
			continue;
		}

		status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		/* Setup the FDE, start listening for read events
		 * from the start (otherwise we may miss a socket
		 * drop) and mark as AUTOCLOSE along with the fde */

		/* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
		smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock,
					      socket_get_fd(smb_krb5->sock),
					      TEVENT_FD_READ,
					      smb_krb5_socket_handler, smb_krb5);
		/* its now the job of the event layer to close the socket */
		tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn);
		socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE);

		tevent_add_timer(ev, smb_krb5,
				 timeval_current_ofs(timeout, 0),
				 smb_krb5_request_timeout, smb_krb5);

		smb_krb5->status = NT_STATUS_OK;
		smb_krb5->reply = data_blob(NULL, 0);

		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			TEVENT_FD_WRITEABLE(smb_krb5->fde);
			smb_krb5->request = send_blob;
			break;
		case KRB5_KRBHST_TCP:

			smb_krb5->packet = packet_init(smb_krb5);
			if (smb_krb5->packet == NULL) {
				talloc_free(smb_krb5);
				return ENOMEM;
			}
			packet_set_private(smb_krb5->packet, smb_krb5);
			packet_set_socket(smb_krb5->packet, smb_krb5->sock);
			packet_set_callback(smb_krb5->packet, smb_krb5_full_packet);
			packet_set_full_request(smb_krb5->packet, packet_full_request_u32);
			packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler);
			packet_set_event_context(smb_krb5->packet, ev);
			packet_set_fde(smb_krb5->packet, smb_krb5->fde);

			smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4);
			RSIVAL(smb_krb5->request.data, 0, send_blob.length);
			memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length);
			packet_send(smb_krb5->packet, smb_krb5->request);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
			if (tevent_loop_once(ev) != 0) {
				talloc_free(tmp_ctx);
				return EINVAL;
			}

			/* After each and every event loop, reset the
			 * send_to_kdc pointers to what they were when
			 * we entered this loop.  That way, if a
			 * nested event has invalidated them, we put
			 * it back before we return to the heimdal
			 * code */
			ret = krb5_set_send_to_kdc_func(context,
							smb_krb5_send_and_recv_func,
							data);
			if (ret != 0) {
				talloc_free(tmp_ctx);
				return ret;
			}
		}
		if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) {
			talloc_free(smb_krb5);
			continue;
		}

		if (!NT_STATUS_IS_OK(smb_krb5->status)) {
			struct tsocket_address *addr = socket_address_to_tsocket_address(smb_krb5, remote_addr);
			const char *addr_string = NULL;
			if (addr) {
				addr_string = tsocket_address_inet_addr_string(addr, smb_krb5);
			} else {
				addr_string = NULL;
			}
			DEBUG(2,("Error reading smb_krb5 reply packet: %s from %s\n", nt_errstr(smb_krb5->status),
				 addr_string));
			talloc_free(smb_krb5);
			continue;
		}

		ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
		if (ret) {
			talloc_free(tmp_ctx);
			return ret;
		}
		talloc_free(smb_krb5);

		break;
	}
	talloc_free(tmp_ctx);
	if (a) {
		return 0;
	}
	return KRB5_KDC_UNREACH;
}
Exemplo n.º 17
0
/*@
 requires \valid(ps);
 requires valid_vector(ps->sockets);
 requires \valid(ps->pfds);
*/
pollsocket_t* pollsocket_validate(pollsocket_t* ps){
    // Safety checks together
    if (!ps || !(ps->sockets) || !(ps->pfds)){
        return NULL;
    }

    // validate all the sockets (that they're valid)
    vector* sockets = ps->sockets;
    long num_sockets = vector_count(sockets);

    // Validate all sockets before adding
    unsigned int invalid_count = 0;
    long invalid_indices[num_sockets];

    for (long i = 0; i < num_sockets; ++i){
        socket_t* s = vector_get(sockets, i);
        sstatus_t socket_status = socket_get_status(s);

        if (socket_status != SOCKET_OPEN) {
            invalid_indices[invalid_count] = i;
            ++invalid_count;
        }
    }

    // Remove all the invalid indices, going from high->low
    for (unsigned int i = 0; i < invalid_count; ++i)
    {
        unsigned int idx = invalid_indices[invalid_count - i - 1];
        printf("[D]: %d\n", socket_get_fd(vector_get(sockets, idx)));
        vector_delete(sockets, idx);
    }

    unsigned int valid_count = num_sockets - invalid_count;
    // If the size is different from the previous size, we want
    // to malloc to resize the number of pfds
    if (ps->size != valid_count) {
        free(ps->pfds);
        ps->pfds = calloc(valid_count, sizeof(struct pollfd));
        ps->size = valid_count;
    }

    for (unsigned int i = 0; i < valid_count; ++i){
        unsigned int idx = i;

        // Match corresponding socket
        socket_t* s = vector_get(sockets, idx);
        (ps->pfds[i]).fd = socket_get_fd(s);
        (ps->pfds[i]).revents = 0;

        // First one is ALWAYS the listener (since its the accepter) ,
        // else everyone else is both listener and reader
        if (i == 0){
            (ps->pfds[i]).events = POLLIN;
        } else {
            (ps->pfds[i]).events = POLLIN;
        }
    }

    return ps;

}
Exemplo n.º 18
0
/*
  initialise a server_context from a open socket and register a event handler
  for reading from that socket
*/
static void ldapsrv_accept(struct stream_connection *c,
			   struct auth_session_info *session_info,
			   bool is_privileged)
{
	struct ldapsrv_service *ldapsrv_service = 
		talloc_get_type(c->private_data, struct ldapsrv_service);
	struct ldapsrv_connection *conn;
	struct cli_credentials *server_credentials;
	struct socket_address *socket_address;
	NTSTATUS status;
	int port;
	int ret;
	struct tevent_req *subreq;
	struct timeval endtime;

	conn = talloc_zero(c, struct ldapsrv_connection);
	if (!conn) {
		stream_terminate_connection(c, "ldapsrv_accept: out of memory");
		return;
	}
	conn->is_privileged = is_privileged;

	conn->sockets.send_queue = tevent_queue_create(conn, "ldapsev send queue");
	if (conn->sockets.send_queue == NULL) {
		stream_terminate_connection(c,
					    "ldapsrv_accept: tevent_queue_create failed");
		return;
	}

	TALLOC_FREE(c->event.fde);

	ret = tstream_bsd_existing_socket(conn,
					  socket_get_fd(c->socket),
					  &conn->sockets.raw);
	if (ret == -1) {
		stream_terminate_connection(c,
					    "ldapsrv_accept: out of memory");
		return;
	}
	socket_set_flags(c->socket, SOCKET_FLAG_NOCLOSE);

	conn->connection  = c;
	conn->service     = ldapsrv_service;
	conn->lp_ctx      = ldapsrv_service->task->lp_ctx;

	c->private_data   = conn;

	socket_address = socket_get_my_addr(c->socket, conn);
	if (!socket_address) {
		ldapsrv_terminate_connection(conn, "ldapsrv_accept: failed to obtain local socket address!");
		return;
	}
	port = socket_address->port;
	talloc_free(socket_address);
	if (port == 3268 || port == 3269) /* Global catalog */ {
		conn->global_catalog = true;
	}

	server_credentials = cli_credentials_init(conn);
	if (!server_credentials) {
		stream_terminate_connection(c, "Failed to init server credentials\n");
		return;
	}

	cli_credentials_set_conf(server_credentials, conn->lp_ctx);
	status = cli_credentials_set_machine_account(server_credentials, conn->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		stream_terminate_connection(c, talloc_asprintf(conn, "Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
		return;
	}
	conn->server_credentials = server_credentials;

	conn->session_info = session_info;

	if (!NT_STATUS_IS_OK(ldapsrv_backend_Init(conn))) {
		ldapsrv_terminate_connection(conn, "backend Init failed");
		return;
	}

	/* load limits from the conf partition */
	ldapsrv_load_limits(conn); /* should we fail on error ? */

	/* register the server */	
	irpc_add_name(c->msg_ctx, "ldap_server");

	conn->sockets.active = conn->sockets.raw;

	if (port != 636 && port != 3269) {
		ldapsrv_call_read_next(conn);
		return;
	}

	endtime = timeval_current_ofs(conn->limits.conn_idle_time, 0);

	subreq = tstream_tls_accept_send(conn,
					 conn->connection->event.ctx,
					 conn->sockets.raw,
					 conn->service->tls_params);
	if (subreq == NULL) {
		ldapsrv_terminate_connection(conn, "ldapsrv_accept: "
				"no memory for tstream_tls_accept_send");
		return;
	}
	tevent_req_set_endtime(subreq,
			       conn->connection->event.ctx,
			       endtime);
	tevent_req_set_callback(subreq, ldapsrv_accept_tls_done, conn);
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
0
/*
  called when a new socket connection has been established. This is called in the process
  context of the new process (if appropriate)
*/
static void stream_new_connection(struct tevent_context *ev,
				  struct loadparm_context *lp_ctx,
				  struct socket_context *sock, 
				  struct server_id server_id, void *private_data)
{
	struct stream_socket *stream_socket = talloc_get_type(private_data, struct stream_socket);
	struct stream_connection *srv_conn;

	srv_conn = talloc_zero(ev, struct stream_connection);
	if (!srv_conn) {
		DEBUG(0,("talloc(mem_ctx, struct stream_connection) failed\n"));
		return;
	}

	talloc_steal(srv_conn, sock);

	srv_conn->private_data	= stream_socket->private_data;
	srv_conn->model_ops     = stream_socket->model_ops;
	srv_conn->socket	= sock;
	srv_conn->server_id	= server_id;
	srv_conn->ops           = stream_socket->ops;
	srv_conn->event.ctx	= ev;
	srv_conn->lp_ctx	= lp_ctx;

	if (!socket_check_access(sock, "smbd", lpcfg_hostsallow(NULL, lpcfg_default_service(lp_ctx)), lpcfg_hostsdeny(NULL, lpcfg_default_service(lp_ctx)))) {
		stream_terminate_connection(srv_conn, "denied by access rules");
		return;
	}

	srv_conn->event.fde	= tevent_add_fd(ev, srv_conn, socket_get_fd(sock),
						0, stream_io_handler_fde, srv_conn);
	if (!srv_conn->event.fde) {
		stream_terminate_connection(srv_conn, "tevent_add_fd() failed");
		return;
	}

	/* setup to receive internal messages on this connection */
	srv_conn->msg_ctx = imessaging_init(srv_conn,
					    lpcfg_imessaging_path(srv_conn, lp_ctx),
					    srv_conn->server_id, ev, false);
	if (!srv_conn->msg_ctx) {
		stream_terminate_connection(srv_conn, "imessaging_init() failed");
		return;
	}

	srv_conn->remote_address = socket_get_remote_addr(srv_conn->socket, srv_conn);
	if (!srv_conn->remote_address) {
		stream_terminate_connection(srv_conn, "socket_get_remote_addr() failed");
		return;
	}

	srv_conn->local_address = socket_get_local_addr(srv_conn->socket, srv_conn);
	if (!srv_conn->local_address) {
		stream_terminate_connection(srv_conn, "socket_get_local_addr() failed");
		return;
	}

	{
		TALLOC_CTX *tmp_ctx;
		const char *title;

		tmp_ctx = talloc_new(srv_conn);

		title = talloc_asprintf(tmp_ctx, "conn[%s] c[%s] s[%s] server_id[%s]",
					stream_socket->ops->name, 
					tsocket_address_string(srv_conn->remote_address, tmp_ctx),
					tsocket_address_string(srv_conn->local_address, tmp_ctx),
					server_id_str(tmp_ctx, &server_id));
		if (title) {
			stream_connection_set_title(srv_conn, title);
		}
		talloc_free(tmp_ctx);
	}

	/* we're now ready to start receiving events on this stream */
	TEVENT_FD_READABLE(srv_conn->event.fde);

	/* call the server specific accept code */
	stream_socket->ops->accept_connection(srv_conn);
}
Exemplo n.º 21
0
krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
					    void *data,
					    krb5_krbhst_info *hi,
					    time_t timeout,
					    const krb5_data *send_buf,
					    krb5_data *recv_buf)
{
	krb5_error_code ret;
	NTSTATUS status;
	struct socket_address *remote_addr;
	const char *name;
	struct addrinfo *ai, *a;
	struct smb_krb5_socket *smb_krb5;

	struct tevent_context *ev = talloc_get_type(data, struct tevent_context);

	DATA_BLOB send_blob = data_blob_const(send_buf->data, send_buf->length);

	ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
	if (ret) {
		return ret;
	}

	for (a = ai; a; a = ai->ai_next) {
		smb_krb5 = talloc(NULL, struct smb_krb5_socket);
		if (!smb_krb5) {
			return ENOMEM;
		}
		smb_krb5->hi = hi;

		switch (a->ai_family) {
		case PF_INET:
			name = "ipv4";
			break;
#ifdef HAVE_IPV6
		case PF_INET6:
			name = "ipv6";
			break;
#endif
		default:
			talloc_free(smb_krb5);
			return EINVAL;
		}

		status = NT_STATUS_INVALID_PARAMETER;
		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_TCP:
			status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(smb_krb5);
			return EINVAL;
		}
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}

		talloc_steal(smb_krb5, smb_krb5->sock);

		remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
		if (!remote_addr) {
			talloc_free(smb_krb5);
			continue;
		}

		status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(smb_krb5);
			continue;
		}
		talloc_free(remote_addr);

		/* Setup the FDE, start listening for read events
		 * from the start (otherwise we may miss a socket
		 * drop) and mark as AUTOCLOSE along with the fde */

		/* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
		smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock,
					      socket_get_fd(smb_krb5->sock),
					      TEVENT_FD_READ,
					      smb_krb5_socket_handler, smb_krb5);
		/* its now the job of the event layer to close the socket */
		tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn);
		socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE);

		tevent_add_timer(ev, smb_krb5,
				 timeval_current_ofs(timeout, 0),
				 smb_krb5_request_timeout, smb_krb5);

		smb_krb5->status = NT_STATUS_OK;
		smb_krb5->reply = data_blob(NULL, 0);

		switch (hi->proto) {
		case KRB5_KRBHST_UDP:
			TEVENT_FD_WRITEABLE(smb_krb5->fde);
			smb_krb5->request = send_blob;
			break;
		case KRB5_KRBHST_TCP:

			smb_krb5->packet = packet_init(smb_krb5);
			if (smb_krb5->packet == NULL) {
				talloc_free(smb_krb5);
				return ENOMEM;
			}
			packet_set_private(smb_krb5->packet, smb_krb5);
			packet_set_socket(smb_krb5->packet, smb_krb5->sock);
			packet_set_callback(smb_krb5->packet, smb_krb5_full_packet);
			packet_set_full_request(smb_krb5->packet, packet_full_request_u32);
			packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler);
			packet_set_event_context(smb_krb5->packet, ev);
			packet_set_fde(smb_krb5->packet, smb_krb5->fde);

			smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4);
			RSIVAL(smb_krb5->request.data, 0, send_blob.length);
			memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length);
			packet_send(smb_krb5->packet, smb_krb5->request);
			break;
		case KRB5_KRBHST_HTTP:
			talloc_free(smb_krb5);
			return EINVAL;
		}
		while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
			if (tevent_loop_once(ev) != 0) {
				talloc_free(smb_krb5);
				return EINVAL;
			}
		}
		if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) {
			talloc_free(smb_krb5);
			continue;
		}

		if (!NT_STATUS_IS_OK(smb_krb5->status)) {
			DEBUG(2,("Error reading smb_krb5 reply packet: %s\n", nt_errstr(smb_krb5->status)));
			talloc_free(smb_krb5);
			continue;
		}

		ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
		if (ret) {
			talloc_free(smb_krb5);
			return ret;
		}
		talloc_free(smb_krb5);

		break;
	}
	if (a) {
		return 0;
	}
	return KRB5_KDC_UNREACH;
}
Exemplo n.º 22
0
static int gensec_socket_get_fd(struct socket_context *sock)
{
	struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
	return socket_get_fd(gensec->socket);
}
Exemplo n.º 23
0
/*
  called when we get a new connection
*/
static void wreplsrv_accept(struct stream_connection *conn)
{
	struct wreplsrv_service *service = talloc_get_type(conn->private_data, struct wreplsrv_service);
	struct wreplsrv_in_connection *wrepl_conn;
	struct tsocket_address *peer_addr;
	char *peer_ip;
	struct tevent_req *subreq;
	int rc;

	wrepl_conn = talloc_zero(conn, struct wreplsrv_in_connection);
	if (wrepl_conn == NULL) {
		stream_terminate_connection(conn,
					    "wreplsrv_accept: out of memory");
		return;
	}

	wrepl_conn->send_queue = tevent_queue_create(conn, "wrepl_accept");
	if (wrepl_conn->send_queue == NULL) {
		stream_terminate_connection(conn,
					    "wrepl_accept: out of memory");
		return;
	}

	TALLOC_FREE(conn->event.fde);

	rc = tstream_bsd_existing_socket(wrepl_conn,
					 socket_get_fd(conn->socket),
					 &wrepl_conn->tstream);
	if (rc < 0) {
		stream_terminate_connection(conn,
					    "wrepl_accept: out of memory");
		return;
	}
	socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);

	wrepl_conn->conn = conn;
	wrepl_conn->service = service;

	peer_addr = conn->remote_address;

	if (!tsocket_address_is_inet(peer_addr, "ipv4")) {
		DEBUG(0,("wreplsrv_accept: non ipv4 peer addr '%s'\n",
			tsocket_address_string(peer_addr, wrepl_conn)));
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: "
				"invalid peer IP");
		return;
	}

	peer_ip = tsocket_address_inet_addr_string(peer_addr, wrepl_conn);
	if (peer_ip == NULL) {
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: "
				"could not convert peer IP into a string");
		return;
	}

	wrepl_conn->partner = wreplsrv_find_partner(service, peer_ip);
	irpc_add_name(conn->msg_ctx, "wreplsrv_connection");

	/*
	 * The wrepl pdu's has the length as 4 byte (initial_read_size),
	 * packet_full_request_u32 provides the pdu length then.
	 */
	subreq = tstream_read_pdu_blob_send(wrepl_conn,
					    wrepl_conn->conn->event.ctx,
					    wrepl_conn->tstream,
					    4, /* initial_read_size */
					    packet_full_request_u32,
					    wrepl_conn);
	if (subreq == NULL) {
		wreplsrv_terminate_in_connection(wrepl_conn, "wrepl_accept: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn);
}
Exemplo n.º 24
0
/*
 * -----------------------------------------------------------------------------
 *				RRC simulator main process
 * -----------------------------------------------------------------------------
 */
int main (int argc, const char* argv[])
{
    /*
     * Get the command line options
     */
    if ( as_simulator_parser_get_options(argc, argv) != RETURNok )
    {
	as_simulator_parser_print_usage();
	exit(EXIT_FAILURE);
    }
    const char* uhost = as_simulator_parser_get_uhost();
    const char* uport = as_simulator_parser_get_uport();
    const char* mhost = as_simulator_parser_get_mhost();
    const char* mport = as_simulator_parser_get_mport();

    nas_log_init(0x2f);

    /*
     * Initialize the communication channel to the UE NAS process
     */
    _as_simulator_ue_sid = socket_udp_open(SOCKET_SERVER, uhost, uport);
    if (_as_simulator_ue_sid == NULL) {
	const char* error = ( (errno < 0) ?
			      gai_strerror(errno) : strerror(errno) );
	printf("ERROR\t: socket_udp_open() failed: %s\n", error);
	exit(EXIT_FAILURE);
    }
    printf("INFO\t: %s - The RRC Simulator is now connected to %s/%s (%d)\n",
	   __FUNCTION__, uhost, uport, socket_get_fd(_as_simulator_ue_sid));

    /*
     * Initialize the communication channel to the MME NAS process
     */
    _as_simulator_mme_sid = socket_udp_open(SOCKET_CLIENT, mhost, mport);
    if (_as_simulator_mme_sid == NULL) {
	const char* error = ( (errno < 0) ?
			      gai_strerror(errno) : strerror(errno) );
	printf("ERROR\t: socket_udp_open() failed: %s\n", error);
	socket_close(_as_simulator_ue_sid);
	exit(EXIT_FAILURE);
    }
    printf("INFO\t: %s - The RRC Simulator is now connected to %s/%s (%d)\n",
	   __FUNCTION__, mhost, mport, socket_get_fd(_as_simulator_mme_sid));

    MSCGEN("[MSC_NEW][%s][AS=%s]\n", getTime(), _as_id);

    /*
     * Set up signal handler
     */
   (void) _set_signal_handler(SIGINT, _signal_handler);
   (void) _set_signal_handler(SIGTERM, _signal_handler);

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    /*
     * Start thread use to manage the connection endpoint with the
     * UE NAS process
     */
    pthread_t ue_mngr;
    if ( pthread_create (&ue_mngr, &attr, _as_simulator_ue_mngr, NULL) != 0 )
    {
        perror("ERROR\t: Failed to create the UE management thread\n");
	socket_close(_as_simulator_ue_sid);
	socket_close(_as_simulator_mme_sid);
	exit(EXIT_FAILURE);	
    }

    /*
     * Start thread use to manage the connection endpoint with the
     * MME NAS process
     */
    pthread_t mme_mngr;
    if ( pthread_create (&mme_mngr, &attr, _as_simulator_mme_mngr, NULL) != 0 )
    {
        perror("ERROR\t: Failed to create the MME management thread\n");
	socket_close(_as_simulator_ue_sid);
	socket_close(_as_simulator_mme_sid);
	exit(EXIT_FAILURE);	
    }
    pthread_attr_destroy(&attr);

    /*
     * Suspend execution of the main process until connection
     * managers are running
     */
    poll(NULL, 0, SLEEP_TIMEOUT);
    while (_as_simulator_ue_is_running && _as_simulator_mme_is_running)
    {
	poll(NULL, 0, SLEEP_TIMEOUT);
    }

    /*
     * Termination cleanup
     */
    printf("INFO\t: %s - Closing UE's connection endpoint %d\n",
	   __FUNCTION__, socket_get_fd(_as_simulator_ue_sid));
    socket_close(_as_simulator_ue_sid);
    printf("INFO\t: %s - Closing MME's connection endpoint %d\n",
	   __FUNCTION__, socket_get_fd(_as_simulator_mme_sid));
    socket_close(_as_simulator_mme_sid);

    printf("INFO\t: %s - RRC simulator exited\n", __FUNCTION__);
    exit(EXIT_SUCCESS);
}