_PUBLIC_ struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct socket_address *a; struct tsocket_address *r; a = socket_get_my_addr(sock, mem_ctx); if (a == NULL) { return NULL; } r = socket_address_to_tsocket_address(mem_ctx, a); talloc_free(a); return r; }
static struct socket_address *gensec_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket); return socket_get_my_addr(gensec->socket, mem_ctx); }
/** basic testing of udp routines */ static bool test_udp(struct torture_context *tctx) { struct socket_context *sock1, *sock2; NTSTATUS status; struct socket_address *srv_addr, *from_addr, *localhost; size_t size = 100 + (random() % 100); DATA_BLOB blob, blob2; size_t sent, nread; TALLOC_CTX *mem_ctx = tctx; struct interface *ifaces; load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces); status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0); torture_assert_ntstatus_ok(tctx, status, "creating DGRAM IP socket 1"); talloc_steal(mem_ctx, sock1); status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock2, 0); torture_assert_ntstatus_ok(tctx, status, "creating DGRAM IP socket 1"); talloc_steal(mem_ctx, sock2); localhost = socket_address_from_strings(sock1, sock1->backend_name, iface_best_ip(ifaces, "127.0.0.1"), 0); torture_assert(tctx, localhost, "Localhost not found"); status = socket_listen(sock1, localhost, 0, 0); torture_assert_ntstatus_ok(tctx, status, "listen on socket 1"); srv_addr = socket_get_my_addr(sock1, mem_ctx); torture_assert(tctx, srv_addr != NULL && strcmp(srv_addr->addr, iface_best_ip(ifaces, "127.0.0.1")) == 0, talloc_asprintf(tctx, "Expected server address of %s but got %s", iface_best_ip(ifaces, "127.0.0.1"), srv_addr ? srv_addr->addr : NULL)); torture_comment(tctx, "server port is %d\n", srv_addr->port); blob = data_blob_talloc(mem_ctx, NULL, size); blob2 = data_blob_talloc(mem_ctx, NULL, size); generate_random_buffer(blob.data, blob.length); sent = size; status = socket_sendto(sock2, &blob, &sent, srv_addr); torture_assert_ntstatus_ok(tctx, status, "sendto() on socket 2"); status = socket_recvfrom(sock1, blob2.data, size, &nread, sock1, &from_addr); torture_assert_ntstatus_ok(tctx, status, "recvfrom() on socket 1"); torture_assert_str_equal(tctx, from_addr->addr, srv_addr->addr, "different address"); torture_assert_int_equal(tctx, nread, size, "Unexpected recvfrom size"); torture_assert_mem_equal(tctx, blob2.data, blob.data, size, "Bad data in recvfrom"); generate_random_buffer(blob.data, blob.length); status = socket_sendto(sock1, &blob, &sent, from_addr); torture_assert_ntstatus_ok(tctx, status, "sendto() on socket 1"); status = socket_recvfrom(sock2, blob2.data, size, &nread, sock2, &from_addr); torture_assert_ntstatus_ok(tctx, status, "recvfrom() on socket 2"); torture_assert_str_equal(tctx, from_addr->addr, srv_addr->addr, "Unexpected recvfrom addr"); torture_assert_int_equal(tctx, nread, size, "Unexpected recvfrom size"); torture_assert_int_equal(tctx, from_addr->port, srv_addr->port, "Unexpected recvfrom port"); torture_assert_mem_equal(tctx, blob2.data, blob.data, size, "Bad data in recvfrom"); talloc_free(sock1); talloc_free(sock2); return true; }
/* basic testing of tcp routines */ static bool test_tcp(struct torture_context *tctx) { struct socket_context *sock1, *sock2, *sock3; NTSTATUS status; struct socket_address *srv_addr, *from_addr, *localhost; size_t size = 100 + (random() % 100); DATA_BLOB blob, blob2; size_t sent, nread; TALLOC_CTX *mem_ctx = tctx; struct tevent_context *ev = tctx->ev; struct interface *ifaces; status = socket_create("ip", SOCKET_TYPE_STREAM, &sock1, 0); torture_assert_ntstatus_ok(tctx, status, "creating IP stream socket 1"); talloc_steal(mem_ctx, sock1); status = socket_create("ip", SOCKET_TYPE_STREAM, &sock2, 0); torture_assert_ntstatus_ok(tctx, status, "creating IP stream socket 1"); talloc_steal(mem_ctx, sock2); load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces); localhost = socket_address_from_strings(sock1, sock1->backend_name, iface_best_ip(ifaces, "127.0.0.1"), 0); torture_assert(tctx, localhost, "Localhost not found"); status = socket_listen(sock1, localhost, 0, 0); torture_assert_ntstatus_ok(tctx, status, "listen on socket 1"); srv_addr = socket_get_my_addr(sock1, mem_ctx); torture_assert(tctx, srv_addr && srv_addr->addr, "Unexpected socket_get_my_addr NULL\n"); torture_assert_str_equal(tctx, srv_addr->addr, iface_best_ip(ifaces, "127.0.0.1"), "Unexpected server address"); torture_comment(tctx, "server port is %d\n", srv_addr->port); status = socket_connect_ev(sock2, NULL, srv_addr, 0, ev); torture_assert_ntstatus_ok(tctx, status, "connect() on socket 2"); status = socket_accept(sock1, &sock3); torture_assert_ntstatus_ok(tctx, status, "accept() on socket 1"); talloc_steal(mem_ctx, sock3); talloc_free(sock1); blob = data_blob_talloc(mem_ctx, NULL, size); blob2 = data_blob_talloc(mem_ctx, NULL, size); generate_random_buffer(blob.data, blob.length); sent = size; status = socket_send(sock2, &blob, &sent); torture_assert_ntstatus_ok(tctx, status, "send() on socket 2"); status = socket_recv(sock3, blob2.data, size, &nread); torture_assert_ntstatus_ok(tctx, status, "recv() on socket 3"); from_addr = socket_get_peer_addr(sock3, mem_ctx); torture_assert(tctx, from_addr && from_addr->addr, "Unexpected recvfrom addr NULL"); torture_assert_str_equal(tctx, from_addr->addr, srv_addr->addr, "Unexpected recvfrom addr"); torture_assert_int_equal(tctx, nread, size, "Unexpected recvfrom size"); torture_assert_mem_equal(tctx, blob2.data, blob.data, size, "Bad data in recv"); return true; }
/* send a mailslot request */ NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock, enum dgram_msg_type msg_type, const char *mailslot_name, struct nbt_name *dest_name, struct socket_address *dest, struct nbt_name *src_name, DATA_BLOB *request) { TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); struct nbt_dgram_packet packet; struct dgram_message *msg; struct dgram_smb_packet *smb; struct smb_trans_body *trans; struct socket_address *src; NTSTATUS status; if (dest->port == 0) { return NT_STATUS_INVALID_PARAMETER; } ZERO_STRUCT(packet); packet.msg_type = msg_type; packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD; packet.dgram_id = generate_random() % UINT16_MAX; src = socket_get_my_addr(dgmsock->sock, tmp_ctx); if (!src) { return NT_STATUS_NO_MEMORY; } packet.src_addr = src->addr; packet.src_port = src->port; msg = &packet.data.msg; /* this length calculation is very crude - it should be based on gensize calls */ msg->length = 138 + strlen(mailslot_name) + request->length; msg->offset = 0; msg->source_name = *src_name; msg->dest_name = *dest_name; msg->dgram_body_type = DGRAM_SMB; smb = &msg->body.smb; smb->smb_command = SMB_TRANSACTION; trans = &smb->body.trans; trans->total_data_count = request->length; trans->timeout = 1000; trans->data_count = request->length; trans->data_offset = 70 + strlen(mailslot_name); trans->opcode = 1; /* write mail slot */ trans->priority = 1; trans->_class = 2; trans->mailslot_name = mailslot_name; trans->data = *request; status = nbt_dgram_send(dgmsock, &packet, dest); talloc_free(tmp_ctx); return status; }
/* called when a listening socket becomes readable. */ static void standard_accept_connection(struct tevent_context *ev, struct loadparm_context *lp_ctx, struct socket_context *sock, void (*new_conn)(struct tevent_context *, struct loadparm_context *, struct socket_context *, struct server_id , void *), void *private_data) { NTSTATUS status; struct socket_context *sock2; pid_t pid; struct socket_address *c, *s; struct standard_child_state *state; struct tevent_fd *fde = NULL; struct tevent_signal *se = NULL; state = setup_standard_child_pipe(ev, NULL); if (state == NULL) { return; } /* accept an incoming connection. */ status = socket_accept(sock, &sock2); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); /* this looks strange, but is correct. We need to throttle things until the system clears enough resources to handle this new socket */ sleep(1); close(state->to_parent_fd); state->to_parent_fd = -1; TALLOC_FREE(state); return; } pid = fork(); if (pid != 0) { close(state->to_parent_fd); state->to_parent_fd = -1; if (pid > 0) { state->pid = pid; } else { TALLOC_FREE(state); } /* parent or error code ... */ talloc_free(sock2); /* go back to the event loop */ return; } /* this leaves state->to_parent_fd open */ TALLOC_FREE(state); pid = getpid(); /* This is now the child code. We need a completely new event_context to work with */ if (tevent_re_initialise(ev) != 0) { smb_panic("Failed to re-initialise tevent after fork"); } /* this will free all the listening sockets and all state that is not associated with this new connection */ talloc_free(sock); /* we don't care if the dup fails, as its only a select() speed optimisation */ socket_dup(sock2); /* tdb needs special fork handling */ ldb_wrap_fork_hook(); /* Must be done after a fork() to reset messaging contexts. */ status = imessaging_reinit_all(); if (!NT_STATUS_IS_OK(status)) { smb_panic("Failed to re-initialise imessaging after fork"); } fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ, standard_pipe_handler, NULL); if (fde == NULL) { smb_panic("Failed to add fd handler after fork"); } if (child_pipe[1] != -1) { close(child_pipe[1]); child_pipe[1] = -1; } se = tevent_add_signal(ev, ev, SIGHUP, 0, sighup_signal_handler, NULL); if (se == NULL) { smb_panic("Failed to add SIGHUP handler after fork"); } se = tevent_add_signal(ev, ev, SIGTERM, 0, sigterm_signal_handler, NULL); if (se == NULL) { smb_panic("Failed to add SIGTERM handler after fork"); } /* setup the process title */ c = socket_get_peer_addr(sock2, ev); s = socket_get_my_addr(sock2, ev); if (s && c) { setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]", c->addr, c->port, s->addr, s->port, (int)pid); } talloc_free(c); talloc_free(s); /* setup this new connection. Cluster ID is PID based for this process model */ new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data); /* we can't return to the top level here, as that event context is gone, so we now process events in the new event context until there are no more to process */ tevent_loop_wait(ev); talloc_free(ev); exit(0); }
/* handle fd recv events on a KDC socket */ static void kdc_recv_handler(struct kdc_socket *kdc_socket) { NTSTATUS status; TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket); DATA_BLOB blob; struct kdc_reply *rep; DATA_BLOB reply; size_t nread, dsize; struct socket_address *src; struct socket_address *my_addr; int ret; status = socket_pending(kdc_socket->sock, &dsize); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return; } blob = data_blob_talloc(tmp_ctx, NULL, dsize); if (blob.data == NULL) { /* hope this is a temporary low memory condition */ talloc_free(tmp_ctx); return; } status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread, tmp_ctx, &src); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return; } blob.length = nread; DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n", (long)blob.length, src->addr, (uint16_t)src->port)); my_addr = socket_get_my_addr(kdc_socket->sock, tmp_ctx); if (!my_addr) { talloc_free(tmp_ctx); return; } /* Call krb5 */ ret = kdc_socket->process(kdc_socket->kdc, tmp_ctx, &blob, &reply, src, my_addr, 1 /* Datagram */); if (!ret) { talloc_free(tmp_ctx); return; } /* queue a pending reply */ rep = talloc(kdc_socket, struct kdc_reply); if (rep == NULL) { talloc_free(tmp_ctx); return; } rep->dest = talloc_steal(rep, src); rep->packet = reply; talloc_steal(rep, reply.data); if (rep->packet.data == NULL) { talloc_free(rep); talloc_free(tmp_ctx); return; } DLIST_ADD_END(kdc_socket->send_queue, rep, struct kdc_reply *); EVENT_FD_WRITEABLE(kdc_socket->fde); talloc_free(tmp_ctx); }
/* called when a listening socket becomes readable. */ static void standard_accept_connection(struct tevent_context *ev, struct loadparm_context *lp_ctx, struct socket_context *sock, void (*new_conn)(struct tevent_context *, struct loadparm_context *, struct socket_context *, struct server_id , void *), void *private_data) { NTSTATUS status; struct socket_context *sock2; pid_t pid; struct tevent_context *ev2; struct socket_address *c, *s; /* accept an incoming connection. */ status = socket_accept(sock, &sock2); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); /* this looks strange, but is correct. We need to throttle things until the system clears enough resources to handle this new socket */ sleep(1); return; } pid = fork(); if (pid != 0) { /* parent or error code ... */ talloc_free(sock2); /* go back to the event loop */ return; } pid = getpid(); /* This is now the child code. We need a completely new event_context to work with */ ev2 = s4_event_context_init(NULL); /* the service has given us a private pointer that encapsulates the context it needs for this new connection - everything else will be freed */ talloc_steal(ev2, private_data); talloc_steal(private_data, sock2); /* this will free all the listening sockets and all state that is not associated with this new connection */ talloc_free(sock); talloc_free(ev); /* we don't care if the dup fails, as its only a select() speed optimisation */ socket_dup(sock2); /* tdb needs special fork handling */ if (tdb_reopen_all(1) == -1) { DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n")); } /* Ensure that the forked children do not expose identical random streams */ set_need_random_reseed(); /* setup the process title */ c = socket_get_peer_addr(sock2, ev2); s = socket_get_my_addr(sock2, ev2); if (s && c) { setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]", c->addr, c->port, s->addr, s->port, pid); } talloc_free(c); talloc_free(s); /* setup this new connection. Cluster ID is PID based for this process modal */ new_conn(ev2, lp_ctx, sock2, cluster_id(pid, 0), private_data); /* we can't return to the top level here, as that event context is gone, so we now process events in the new event context until there are no more to process */ event_loop_wait(ev2); talloc_free(ev2); exit(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) { 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; conn = talloc_zero(c, struct ldapsrv_connection); if (!conn) { stream_terminate_connection(c, "ldapsrv_accept: out of memory"); return; } conn->packet = NULL; conn->connection = c; conn->service = ldapsrv_service; conn->sockets.raw = c->socket; 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 == 636) { struct socket_context *tls_socket = tls_init_server(ldapsrv_service->tls_params, c->socket, c->event.fde, NULL); if (!tls_socket) { ldapsrv_terminate_connection(conn, "ldapsrv_accept: tls_init_server() failed"); return; } talloc_steal(c, tls_socket); c->socket = tls_socket; conn->sockets.tls = tls_socket; } else if (port == 3268) /* Global catalog */ { conn->global_catalog = true; } conn->packet = packet_init(conn); if (conn->packet == NULL) { ldapsrv_terminate_connection(conn, "out of memory"); return; } packet_set_private(conn->packet, conn); packet_set_socket(conn->packet, c->socket); packet_set_callback(conn->packet, ldapsrv_decode); packet_set_full_request(conn->packet, ldap_full_packet); packet_set_error_handler(conn->packet, ldapsrv_error_handler); packet_set_event_context(conn->packet, c->event.ctx); packet_set_fde(conn->packet, c->event.fde); packet_set_serialise(conn->packet); if (conn->sockets.tls) { packet_set_unreliable_select(conn->packet); } /* Ensure we don't get packets until the database is ready below */ packet_recv_disable(conn->packet); 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 = talloc_move(conn, &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"); /* set connections limits */ conn->limits.ite = event_add_timed(c->event.ctx, conn, timeval_current_ofs(conn->limits.initial_timeout, 0), ldapsrv_conn_init_timeout, conn); packet_recv_enable(conn->packet); }
/* 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); }
/* called when a listening socket becomes readable. */ static void standard_accept_connection(struct tevent_context *ev, struct loadparm_context *lp_ctx, struct socket_context *sock, void (*new_conn)(struct tevent_context *, struct loadparm_context *, struct socket_context *, struct server_id , void *), void *private_data) { NTSTATUS status; struct socket_context *sock2; pid_t pid; struct socket_address *c, *s; /* accept an incoming connection. */ status = socket_accept(sock, &sock2); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); /* this looks strange, but is correct. We need to throttle things until the system clears enough resources to handle this new socket */ sleep(1); return; } pid = fork(); if (pid != 0) { /* parent or error code ... */ talloc_free(sock2); /* go back to the event loop */ return; } pid = getpid(); /* This is now the child code. We need a completely new event_context to work with */ if (tevent_re_initialise(ev) != 0) { smb_panic("Failed to re-initialise tevent after fork"); } /* this will free all the listening sockets and all state that is not associated with this new connection */ talloc_free(sock); /* we don't care if the dup fails, as its only a select() speed optimisation */ socket_dup(sock2); /* tdb needs special fork handling */ ldb_wrap_fork_hook(); tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ, standard_pipe_handler, NULL); close(child_pipe[1]); /* Ensure that the forked children do not expose identical random streams */ set_need_random_reseed(); /* setup the process title */ c = socket_get_peer_addr(sock2, ev); s = socket_get_my_addr(sock2, ev); if (s && c) { setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]", c->addr, c->port, s->addr, s->port, (int)pid); } talloc_free(c); talloc_free(s); /* setup this new connection. Cluster ID is PID based for this process model */ new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data); /* we can't return to the top level here, as that event context is gone, so we now process events in the new event context until there are no more to process */ tevent_loop_wait(ev); talloc_free(ev); exit(0); }
/* called when we get a new connection */ static void kdc_tcp_accept(struct stream_connection *conn) { struct kdc_socket *kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket); struct kdc_tcp_connection *kdcconn; struct socket_address *src_addr; struct socket_address *my_addr; int ret; kdcconn = talloc_zero(conn, struct kdc_tcp_connection); if (!kdcconn) { stream_terminate_connection(conn, "kdc_tcp_accept: out of memory"); return; } kdcconn->conn = conn; kdcconn->kdc_socket = kdc_socket; conn->private_data = kdcconn; src_addr = socket_get_peer_addr(kdcconn->conn->socket, kdcconn); if (!src_addr) { kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory"); return; } my_addr = socket_get_my_addr(kdcconn->conn->socket, kdcconn); if (!my_addr) { kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory"); return; } ret = tsocket_address_bsd_from_sockaddr(kdcconn, src_addr->sockaddr, src_addr->sockaddrlen, &kdcconn->remote_address); if (ret < 0) { kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory"); return; } ret = tsocket_address_bsd_from_sockaddr(kdcconn, my_addr->sockaddr, my_addr->sockaddrlen, &kdcconn->local_address); if (ret < 0) { kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory"); return; } TALLOC_FREE(src_addr); TALLOC_FREE(my_addr); kdcconn->packet = packet_init(kdcconn); if (kdcconn->packet == NULL) { kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory"); return; } packet_set_private(kdcconn->packet, kdcconn); packet_set_socket(kdcconn->packet, conn->socket); packet_set_callback(kdcconn->packet, kdc_tcp_recv); packet_set_full_request(kdcconn->packet, packet_full_request_u32); packet_set_error_handler(kdcconn->packet, kdc_tcp_recv_error); packet_set_event_context(kdcconn->packet, conn->event.ctx); packet_set_fde(kdcconn->packet, conn->event.fde); packet_set_serialise(kdcconn->packet); }