From 55d4d36993293fee914a009f1d8f05810e347f2b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Jan 2005 00:54:57 +0000 Subject: r5102: This is a major simplification of the logic for controlling top level servers in smbd. The old code still contained a fairly bit of legacy from the time when smbd was only handling SMB connection. The new code gets rid of all of the smb_server specific code in smbd/, and creates a much simpler infrastructures for new server code. Major changes include: - simplified the process model code a lot. - got rid of the top level server and service structures completely. The top level context is now the event_context. This got rid of service.h and server.h completely (they were the most confusing parts of the old code) - added service_stream.[ch] for the helper functions that are specific to stream type services (services that handle streams, and use a logically separate process per connection) - got rid of the builtin idle_handler code in the service logic, as none of the servers were using it, and it can easily be handled by a server in future by adding its own timed_event to the event context. - fixed some major memory leaks in the rpc server code. - added registration of servers, rather than hard coding our list of possible servers. This allows for servers as modules in the future. - temporarily disabled the winbind code until I add the helper functions for that type of server - added error checking on service startup. If a configured server fails to startup then smbd doesn't startup. - cleaned up the command line handling in smbd, removing unused options (This used to be commit cf6a46c3cbde7b1eb1b86bd3882b953a2de3a42e) --- source4/smb_server/conn.c | 1 + source4/smb_server/negprot.c | 8 +- source4/smb_server/request.c | 1 + source4/smb_server/service.c | 1 + source4/smb_server/sesssetup.c | 1 + source4/smb_server/smb_server.c | 165 ++++++++++++++-------------------------- source4/smb_server/smb_server.h | 2 +- 7 files changed, 68 insertions(+), 111 deletions(-) (limited to 'source4/smb_server') diff --git a/source4/smb_server/conn.c b/source4/smb_server/conn.c index 427add0aa2..45c5376e25 100644 --- a/source4/smb_server/conn.c +++ b/source4/smb_server/conn.c @@ -23,6 +23,7 @@ #include "system/filesys.h" #include "dlinklist.h" #include "smb_server/smb_server.h" +#include "smbd/service_stream.h" /**************************************************************************** diff --git a/source4/smb_server/negprot.c b/source4/smb_server/negprot.c index 4af8fed53b..8223f66dc7 100644 --- a/source4/smb_server/negprot.c +++ b/source4/smb_server/negprot.c @@ -21,6 +21,7 @@ #include "includes.h" #include "auth/auth.h" #include "smb_server/smb_server.h" +#include "smbd/service_stream.h" /* initialise the auth_context for this server and return the cryptkey */ @@ -144,7 +145,7 @@ static void reply_lanman1(struct smbsrv_request *req, uint16_t choice) SSVAL(req->out.vwv, VWV(3), lp_maxmux()); SSVAL(req->out.vwv, VWV(4), 1); SSVAL(req->out.vwv, VWV(5), raw); - SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->connection.id); + SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->server_id); srv_push_dos_date(req->smb_conn, req->out.vwv, VWV(8), t); SSVAL(req->out.vwv, VWV(10), req->smb_conn->negotiate.zone_offset/60); SIVAL(req->out.vwv, VWV(11), 0); /* reserved */ @@ -198,7 +199,7 @@ static void reply_lanman2(struct smbsrv_request *req, uint16_t choice) SSVAL(req->out.vwv, VWV(3), lp_maxmux()); SSVAL(req->out.vwv, VWV(4), 1); SSVAL(req->out.vwv, VWV(5), raw); - SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->connection.id); + SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->server_id); srv_push_dos_date(req->smb_conn, req->out.vwv, VWV(8), t); SSVAL(req->out.vwv, VWV(10), req->smb_conn->negotiate.zone_offset/60); SIVAL(req->out.vwv, VWV(11), 0); @@ -310,7 +311,7 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice) SSVAL(req->out.vwv+1, VWV(2), 1); /* num vcs */ SIVAL(req->out.vwv+1, VWV(3), req->smb_conn->negotiate.max_recv); SIVAL(req->out.vwv+1, VWV(5), 0x10000); /* raw size. full 64k */ - SIVAL(req->out.vwv+1, VWV(7), req->smb_conn->connection->connection.id); /* session key */ + SIVAL(req->out.vwv+1, VWV(7), req->smb_conn->connection->server_id); /* session key */ SIVAL(req->out.vwv+1, VWV(9), capabilities); push_nttime(req->out.vwv+1, VWV(11), nttime); SSVALS(req->out.vwv+1,VWV(15), req->smb_conn->negotiate.zone_offset/60); @@ -443,7 +444,6 @@ void reply_negprot(struct smbsrv_request *req) if(choice != -1) { sub_set_remote_proto(supported_protocols[protocol].short_name); - reload_services(req->smb_conn, True); supported_protocols[protocol].proto_reply_fn(req, choice); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); } else { diff --git a/source4/smb_server/request.c b/source4/smb_server/request.c index c2aca04661..26988bf205 100644 --- a/source4/smb_server/request.c +++ b/source4/smb_server/request.c @@ -26,6 +26,7 @@ #include "events.h" #include "dlinklist.h" #include "smb_server/smb_server.h" +#include "smbd/service_stream.h" /* we over allocate the data buffer to prevent too many realloc calls */ diff --git a/source4/smb_server/service.c b/source4/smb_server/service.c index d4386ca77b..180deaf8c5 100644 --- a/source4/smb_server/service.c +++ b/source4/smb_server/service.c @@ -20,6 +20,7 @@ #include "includes.h" #include "smb_server/smb_server.h" +#include "smbd/service_stream.h" diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index eb6c8b9647..dc3a60874a 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -25,6 +25,7 @@ #include "version.h" #include "auth/auth.h" #include "smb_server/smb_server.h" +#include "smbd/service_stream.h" /* diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 394923635d..1537bf6a47 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -24,6 +24,7 @@ #include "events.h" #include "system/time.h" #include "dlinklist.h" +#include "smbd/service_stream.h" #include "smb_server/smb_server.h" @@ -506,7 +507,7 @@ static void switch_message(int type, struct smbsrv_request *req) session_tag = req->session->vuid; } - DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->connection.id)); + DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->server_id)); /* does this protocol need a valid tree connection? */ if ((flags & AS_USER) && !req->tcon) { @@ -646,69 +647,15 @@ error: */ void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char *reason) { - server_terminate_connection(smb_conn->connection, reason); -} - -static const struct server_stream_ops *smbsrv_stream_ops(void); - -/* - add a socket address to the list of events, one event per port -*/ -static void smb_add_socket(struct server_service *service, - struct ipv4_addr *ifip) -{ - const char **ports = lp_smb_ports(); - int i; - char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip)); - - for (i=0;ports[i];i++) { - uint16_t port = atoi(ports[i]); - if (port == 0) continue; - service_setup_stream_socket(service, smbsrv_stream_ops(), "ipv4", ip_str, &port); - } - - talloc_free(ip_str); -} - -/**************************************************************************** - Open the socket communication. -****************************************************************************/ -static void smbsrv_init(struct server_service *service) -{ - DEBUG(1,("smbsrv_init\n")); - - if (lp_interfaces() && lp_bind_interfaces_only()) { - int num_interfaces = iface_count(); - int i; - - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - for(i = 0; i < num_interfaces; i++) { - struct ipv4_addr *ifip = iface_n_ip(i); - - if (ifip == NULL) { - DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); - continue; - } - - smb_add_socket(service, ifip); - } - } else { - struct ipv4_addr ifip; - /* Just bind to lp_socket_address() (usually 0.0.0.0) */ - ifip = interpret_addr2(lp_socket_address()); - smb_add_socket(service, &ifip); - } + stream_terminate_connection(smb_conn->connection, reason); } /* called when a SMB socket becomes readable */ -static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16_t flags) +static void smbsrv_recv(struct stream_connection *conn, struct timeval t, uint16_t flags) { - struct smbsrv_connection *smb_conn = conn->connection.private_data; + struct smbsrv_connection *smb_conn = talloc_get_type(conn->private, struct smbsrv_connection); NTSTATUS status; DEBUG(10,("smbsrv_recv\n")); @@ -727,9 +674,9 @@ static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16 /* called when a SMB socket becomes writable */ -static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16_t flags) +static void smbsrv_send(struct stream_connection *conn, struct timeval t, uint16_t flags) { - struct smbsrv_connection *smb_conn = conn->connection.private_data; + struct smbsrv_connection *smb_conn = talloc_get_type(conn->private, struct smbsrv_connection); while (smb_conn->pending_send) { struct smbsrv_request *req = smb_conn->pending_send; @@ -767,39 +714,11 @@ static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16 } } -static void smbsrv_close(struct server_connection *conn, const char *reason) -{ - struct smbsrv_connection *smb_conn = conn->connection.private_data; - - DEBUG(5,("smbsrv_close: %s\n",reason)); - - talloc_free(smb_conn); - - return; -} - -/* - process a message from an SMB socket while still processing a - previous message this is used by backends who need to ensure that - new messages from clients are still processed while they are - performing long operations -*/ -void smbd_process_async(struct smbsrv_connection *smb_conn) -{ - NTSTATUS status; - - status = receive_smb_request(smb_conn, timeval_current()); - if (NT_STATUS_IS_ERR(status)) { - smbsrv_terminate_connection(smb_conn, nt_errstr(status)); - } -} - - /* initialise a server_context from a open socket and register a event handler for reading from that socket */ -static void smbsrv_accept(struct server_connection *conn) +static void smbsrv_accept(struct stream_connection *conn) { struct smbsrv_connection *smb_conn; @@ -825,37 +744,71 @@ static void smbsrv_accept(struct server_connection *conn) smb_conn->connection = conn; - conn->connection.private_data = smb_conn; - - return; + conn->private = smb_conn; } -static const struct server_stream_ops smb_stream_ops = { + +static const struct stream_server_ops smb_stream_ops = { .name = "smb", - .socket_init = NULL, .accept_connection = smbsrv_accept, .recv_handler = smbsrv_recv, .send_handler = smbsrv_send, - .idle_handler = NULL, - .close_connection = smbsrv_close }; -static const struct server_stream_ops *smbsrv_stream_ops(void) +/* + setup a listening socket on all the SMB ports for a particular address +*/ +static NTSTATUS smb_add_socket(struct event_context *event_context, + const struct model_ops *model_ops, + const char *address) { - return &smb_stream_ops; + const char **ports = lp_smb_ports(); + int i; + NTSTATUS status; + + for (i=0;ports[i];i++) { + uint16_t port = atoi(ports[i]); + if (port == 0) continue; + status = stream_setup_socket(event_context, model_ops, &smb_stream_ops, + "ipv4", address, &port, NULL); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; } -static const struct server_service_ops smb_server_ops = { - .name = "smb", - .service_init = smbsrv_init, -}; +/* + called on startup of the smb server service It's job is to start + listening on all configured SMB server sockets +*/ +static NTSTATUS smbsrv_init(struct event_context *event_context, const struct model_ops *model_ops) +{ + NTSTATUS status; -const struct server_service_ops *smbsrv_get_ops(void) -{ - return &smb_server_ops; + if (lp_interfaces() && lp_bind_interfaces_only()) { + int num_interfaces = iface_count(); + int i; + + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + for(i = 0; i < num_interfaces; i++) { + const char *address = sys_inet_ntoa(*iface_n_ip(i)); + status = smb_add_socket(event_context, model_ops, address); + NT_STATUS_NOT_OK_RETURN(status); + } + } else { + /* Just bind to lp_socket_address() (usually 0.0.0.0) */ + status = smb_add_socket(event_context, model_ops, lp_socket_address()); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; } +/* called at smbd startup - register ourselves as a server service */ NTSTATUS server_service_smb_init(void) { - return NT_STATUS_OK; + return register_server_service("smb", smbsrv_init); } diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 2b1ca87cb9..02070f2b13 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -232,7 +232,7 @@ struct smbsrv_connection { struct smb_signing_context signing; - struct server_connection *connection; + struct stream_connection *connection; /* this holds a partially received request */ struct smbsrv_request *partial_req; -- cgit