_PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) { struct socket_address *a; struct tsocket_address *r; a = socket_get_peer_addr(sock, mem_ctx); if (a == NULL) { return NULL; } r = socket_address_to_tsocket_address(mem_ctx, a); talloc_free(a); return r; }
/* return a list of open sessions */ static NTSTATUS smbsrv_session_information(struct irpc_message *msg, struct smbsrv_information *r) { struct smbsrv_connection *smb_conn = talloc_get_type(msg->private, struct smbsrv_connection); int i=0, count=0; struct smbsrv_session *sess; /* count the number of sessions */ for (sess=smb_conn->sessions.list; sess; sess=sess->next) { count++; } r->out.info.sessions.num_sessions = count; r->out.info.sessions.sessions = talloc_array(r, struct smbsrv_session_info, count); NT_STATUS_HAVE_NO_MEMORY(r->out.info.sessions.sessions); for (sess=smb_conn->sessions.list; sess; sess=sess->next) { struct smbsrv_session_info *info = &r->out.info.sessions.sessions[i]; struct socket_address *client_addr; client_addr = socket_get_peer_addr(smb_conn->connection->socket, r); if (client_addr) { info->client_ip = client_addr->addr; } else { info->client_ip = NULL; } info->vuid = sess->vuid; info->account_name = sess->session_info->server_info->account_name; info->domain_name = sess->session_info->server_info->domain_name; info->connect_time = timeval_to_nttime(&sess->statistics.connect_time); info->auth_time = timeval_to_nttime(&sess->statistics.auth_time); info->last_use_time= timeval_to_nttime(&sess->statistics.last_request_time); i++; } return NT_STATUS_OK; }
static struct socket_address *gensec_socket_get_peer_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_peer_addr(gensec->socket, mem_ctx); }
/* 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; }
/* 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); }
/* 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); }
/* 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); }