From 9327ec51d11855ec0ceac3ce1f4e0a75c8b57081 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Jan 2005 01:32:56 +0000 Subject: r4728: split up server_services into: - stream_socket services the smb, ldap and rpc service which sets up a srtam socket end then waits for connections and - task services which this you can create a seperate task that do something (this is also going through the process_model subsystem so with -M standard a new process for this created with -M thread a new thread ... I'll add datagram services later when we whave support for datagram sockets in lib/socket/ see the next commit as an example for service_task's metze (This used to be commit d5fa02746c6569b09b6e05785642da2fad3ba3e0) --- source4/ldap_server/ldap_server.c | 68 +++++------- source4/ntvfs/posix/pvfs_wait.c | 2 +- source4/ntvfs/posix/vfs_posix.c | 8 +- source4/rpc_server/dcerpc_server.c | 35 +++--- source4/rpc_server/dcerpc_sock.c | 100 +++++++---------- source4/smb_server/negprot.c | 6 +- source4/smb_server/request.c | 2 - source4/smb_server/service.c | 48 -------- source4/smb_server/smb_server.c | 66 +++++------ source4/smb_server/smb_server.h | 19 +--- source4/smbd/config.mk | 19 +--- source4/smbd/process_model.c | 4 +- source4/smbd/process_model.h | 16 +-- source4/smbd/process_single.c | 71 ++++++++---- source4/smbd/process_standard.c | 115 ++++++++++++++----- source4/smbd/process_thread.c | 136 ++++++++++++++++------- source4/smbd/rewrite.c | 8 -- source4/smbd/server.c | 27 ++--- source4/smbd/server.h | 9 +- source4/smbd/service.c | 221 ++++++++++++++++++++----------------- source4/smbd/service.h | 80 ++++++++++---- 21 files changed, 566 insertions(+), 494 deletions(-) (limited to 'source4') diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index bc851713b5..52a519721f 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -34,21 +34,22 @@ static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, c server_terminate_connection(ldap_conn->connection, reason); } +static const struct server_stream_ops *ldapsrv_get_stream_ops(void); + /* add a socket address to the list of events, one event per port */ -static void add_socket(struct server_service *service, - const struct model_ops *model_ops, +static void add_socket(struct server_service *service, struct ipv4_addr *ifip) { - struct server_socket *srv_sock; + struct server_stream_socket *stream_socket; uint16_t port = 389; char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip)); - srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port); + stream_socket = service_setup_stream_socket(service, ldapsrv_get_stream_ops(), "ipv4", ip_str, &port); port = 3268; - srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port); + stream_socket = service_setup_stream_socket(service, ldapsrv_get_stream_ops(), "ipv4", ip_str, &port); talloc_free(ip_str); } @@ -56,8 +57,7 @@ static void add_socket(struct server_service *service, /**************************************************************************** Open the socket communication. ****************************************************************************/ -static void ldapsrv_init(struct server_service *service, - const struct model_ops *model_ops) +static void ldapsrv_init(struct server_service *service) { struct ldapsrv_service *ldap_service; struct ldapsrv_partition *part; @@ -97,7 +97,7 @@ static void ldapsrv_init(struct server_service *service, ldap_service->default_partition = part; DLIST_ADD_END(ldap_service->partitions, part, struct ldapsrv_partition *); - service->private_data = ldap_service; + service->service.private_data = ldap_service; if (lp_interfaces() && lp_bind_interfaces_only()) { int num_interfaces = iface_count(); @@ -116,14 +116,14 @@ static void ldapsrv_init(struct server_service *service, continue; } - add_socket(service, model_ops, ifip); + 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()); - add_socket(service, model_ops, &ifip); + add_socket(service, &ifip); } } @@ -423,7 +423,7 @@ NTSTATUS ldapsrv_flush_responses(struct ldapsrv_connection *conn) static void ldapsrv_recv(struct server_connection *conn, struct timeval t, uint16_t flags) { - struct ldapsrv_connection *ldap_conn = conn->private_data; + struct ldapsrv_connection *ldap_conn = conn->connection.private_data; uint8_t *buf; size_t buf_length, msg_length; DATA_BLOB blob; @@ -519,7 +519,7 @@ static void ldapsrv_recv(struct server_connection *conn, struct timeval t, static void ldapsrv_send(struct server_connection *conn, struct timeval t, uint16_t flags) { - struct ldapsrv_connection *ldap_conn = conn->private_data; + struct ldapsrv_connection *ldap_conn = conn->connection.private_data; DEBUG(10,("ldapsrv_send\n")); @@ -535,20 +535,6 @@ static void ldapsrv_send(struct server_connection *conn, struct timeval t, return; } -/* - called when connection is idle -*/ -static void ldapsrv_idle(struct server_connection *conn, struct timeval t) -{ - DEBUG(10,("ldapsrv_idle: not implemented!\n")); - return; -} - -static void ldapsrv_close(struct server_connection *conn, const char *reason) -{ - return; -} - /* initialise a server_context from a open socket and register a event handler for reading from that socket @@ -566,31 +552,31 @@ static void ldapsrv_accept(struct server_connection *conn) ZERO_STRUCTP(ldap_conn); ldap_conn->connection = conn; - ldap_conn->service = talloc_reference(ldap_conn, conn->service->private_data); + ldap_conn->service = talloc_reference(ldap_conn, conn->stream_socket->service); - conn->private_data = ldap_conn; + conn->connection.private_data = ldap_conn; return; } -/* - called on a fatal error that should cause this server to terminate -*/ -static void ldapsrv_exit(struct server_service *service, const char *reason) +static const struct server_stream_ops ldap_stream_ops = { + .name = "ldap", + .socket_init = NULL, + .accept_connection = ldapsrv_accept, + .recv_handler = ldapsrv_recv, + .send_handler = ldapsrv_send, + .idle_handler = NULL, + .close_connection = NULL +}; + +static const struct server_stream_ops *ldapsrv_get_stream_ops(void) { - DEBUG(10,("ldapsrv_exit\n")); - return; + return &ldap_stream_ops; } static const struct server_service_ops ldap_server_ops = { .name = "ldap", - .service_init = ldapsrv_init, - .accept_connection = ldapsrv_accept, - .recv_handler = ldapsrv_recv, - .send_handler = ldapsrv_send, - .idle_handler = ldapsrv_idle, - .close_connection = ldapsrv_close, - .service_exit = ldapsrv_exit, + .service_init = ldapsrv_init }; const struct server_service_ops *ldapsrv_get_ops(void) diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c index 479d339592..4b757e0be1 100644 --- a/source4/ntvfs/posix/pvfs_wait.c +++ b/source4/ntvfs/posix/pvfs_wait.c @@ -134,7 +134,7 @@ static int pvfs_wait_destructor(void *ptr) pwait->private = private; pwait->handler = fn; - pwait->msg_ctx = pvfs->tcon->smb_conn->connection->messaging_ctx; + pwait->msg_ctx = pvfs->tcon->smb_conn->connection->messaging.ctx; pwait->ev = req->tcon->smb_conn->connection->event.ctx; pwait->msg_type = msg_type; pwait->req = talloc_reference(pwait, req); diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e5bdc3faae..0b642adb01 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -130,16 +130,16 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->private_data = pvfs; pvfs->brl_context = brl_init(pvfs, - pvfs->tcon->smb_conn->connection->server_id, + pvfs->tcon->smb_conn->connection->connection.id, pvfs->tcon->service, - pvfs->tcon->smb_conn->connection->messaging_ctx); + pvfs->tcon->smb_conn->connection->messaging.ctx); if (pvfs->brl_context == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } pvfs->odb_context = odb_init(pvfs, - pvfs->tcon->smb_conn->connection->server_id, - pvfs->tcon->smb_conn->connection->messaging_ctx); + pvfs->tcon->smb_conn->connection->connection.id, + pvfs->tcon->smb_conn->connection->messaging.ctx); if (pvfs->odb_context == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 282860b05a..1fcd9a3261 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -1220,7 +1220,7 @@ NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_d return NT_STATUS_OK; } -static void dcesrv_init(struct server_service *service, const struct model_ops *model_ops) +static void dcesrv_init(struct server_service *service) { NTSTATUS status; struct dcesrv_context *dce_ctx; @@ -1235,7 +1235,9 @@ static void dcesrv_init(struct server_service *service, const struct model_ops * return; } - dcesrv_sock_init(service, model_ops, dce_ctx); + service->service.private_data = dce_ctx; + + dcesrv_sock_init(service); return; } @@ -1257,18 +1259,6 @@ static void dcesrv_send(struct server_connection *srv_conn, dcesrv_sock_send(srv_conn, t, flags); } -static void dcesrv_close(struct server_connection *srv_conn, const char *reason) -{ - dcesrv_sock_close(srv_conn, reason); - return; -} - -static void dcesrv_exit(struct server_service *service, const char *reason) -{ - dcesrv_sock_exit(service, reason); - return; -} - /* the list of currently registered DCERPC endpoint servers. */ static struct ep_server { @@ -1350,15 +1340,24 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void) return &critical_sizes; } -static const struct server_service_ops dcesrv_ops = { +static const struct server_stream_ops dcesrv_stream_ops = { .name = "rpc", - .service_init = dcesrv_init, + .socket_init = NULL, .accept_connection = dcesrv_accept, .recv_handler = dcesrv_recv, .send_handler = dcesrv_send, .idle_handler = NULL, - .close_connection = dcesrv_close, - .service_exit = dcesrv_exit, + .close_connection = NULL +}; + +const struct server_stream_ops *dcesrv_get_stream_ops(void) +{ + return &dcesrv_stream_ops; +} + +static const struct server_service_ops dcesrv_ops = { + .name = "rpc", + .service_init = dcesrv_init, }; const struct server_service_ops *dcesrv_get_ops(void) diff --git a/source4/rpc_server/dcerpc_sock.c b/source4/rpc_server/dcerpc_sock.c index 420c73cb1c..561482a5fe 100644 --- a/source4/rpc_server/dcerpc_sock.c +++ b/source4/rpc_server/dcerpc_sock.c @@ -53,24 +53,22 @@ static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, cons server_terminate_connection(dce_conn->srv_conn, reason); } -static void add_socket_rpc_unix(struct server_service *service, - const struct model_ops *model_ops, - struct dcesrv_context *dce_ctx, - struct dcesrv_endpoint *e) +static void add_socket_rpc_unix(struct server_service *service, struct dcesrv_endpoint *e) { - struct server_socket *sock; + struct dcesrv_context *dce_ctx = service->service.private_data; + struct server_stream_socket *stream_socket; struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 1; - sock = service_setup_socket(service,model_ops, "unix", e->ep_description.endpoint, &port); - if (!sock) { - DEBUG(0,("service_setup_socket(path=%s) failed\n",e->ep_description.endpoint)); + stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "unix", e->ep_description.endpoint, &port); + if (!stream_socket) { + DEBUG(0,("service_setup_stream_socket(path=%s) failed\n",e->ep_description.endpoint)); return; } - dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context); + dcesrv_sock = talloc_p(stream_socket, struct dcesrv_socket_context); if (!dcesrv_sock) { - DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n")); + DEBUG(0,("talloc_p(stream_socket, struct dcesrv_socket_context) failed\n")); return; } @@ -78,15 +76,13 @@ static void add_socket_rpc_unix(struct server_service *service, dcesrv_sock->endpoint = e; dcesrv_sock->dcesrv_ctx = dce_ctx; - sock->private_data = dcesrv_sock; + stream_socket->stream.private_data = dcesrv_sock; } -static void add_socket_rpc_ncalrpc(struct server_service *service, - const struct model_ops *model_ops, - struct dcesrv_context *dce_ctx, - struct dcesrv_endpoint *e) +static void add_socket_rpc_ncalrpc(struct server_service *service, struct dcesrv_endpoint *e) { - struct server_socket *sock; + struct dcesrv_context *dce_ctx = service->service.private_data; + struct server_stream_socket *stream_socket; struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 1; char *full_path; @@ -100,15 +96,15 @@ static void add_socket_rpc_ncalrpc(struct server_service *service, full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description.endpoint); - sock = service_setup_socket(service,model_ops, "unix", full_path, &port); - if (!sock) { - DEBUG(0,("service_setup_socket(identifier=%s,path=%s) failed\n",e->ep_description.endpoint, full_path)); + stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "unix", full_path, &port); + if (!stream_socket) { + DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed\n",e->ep_description.endpoint, full_path)); return; } - dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context); + dcesrv_sock = talloc_p(stream_socket, struct dcesrv_socket_context); if (!dcesrv_sock) { - DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n")); + DEBUG(0,("talloc_p(stream_socket, struct dcesrv_socket_context) failed\n")); return; } @@ -116,7 +112,7 @@ static void add_socket_rpc_ncalrpc(struct server_service *service, dcesrv_sock->endpoint = e; dcesrv_sock->dcesrv_ctx = dce_ctx; - sock->private_data = dcesrv_sock; + stream_socket->stream.private_data = dcesrv_sock; return; } @@ -125,12 +121,11 @@ static void add_socket_rpc_ncalrpc(struct server_service *service, add a socket address to the list of events, one event per dcerpc endpoint */ static void add_socket_rpc_tcp_iface(struct server_service *service, - const struct model_ops *model_ops, - struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e, struct ipv4_addr *ifip) { - struct server_socket *sock; + struct dcesrv_context *dce_ctx = service->service.private_data; + struct server_stream_socket *stream_socket; struct dcesrv_socket_context *dcesrv_sock; uint16_t port = 0; char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip)); @@ -138,9 +133,9 @@ static void add_socket_rpc_tcp_iface(struct server_service *service, if (e->ep_description.endpoint) port = atoi(e->ep_description.endpoint); - sock = service_setup_socket(service,model_ops, "ipv4", ip_str, &port); - if (!sock) { - DEBUG(0,("service_setup_socket(port=%u) failed\n",port)); + stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "ipv4", ip_str, &port); + if (!stream_socket) { + DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed\n", ip_str, port)); return; } @@ -148,9 +143,9 @@ static void add_socket_rpc_tcp_iface(struct server_service *service, e->ep_description.endpoint = talloc_asprintf(dce_ctx, "%d", port); } - dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context); + dcesrv_sock = talloc_p(stream_socket, struct dcesrv_socket_context); if (!dcesrv_sock) { - DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n")); + DEBUG(0,("talloc_p(stream_socket, struct dcesrv_socket_context) failed\n")); return; } @@ -158,17 +153,14 @@ static void add_socket_rpc_tcp_iface(struct server_service *service, dcesrv_sock->endpoint = e; dcesrv_sock->dcesrv_ctx = dce_ctx; - sock->private_data = dcesrv_sock; + stream_socket->stream.private_data = dcesrv_sock; talloc_free(ip_str); return; } -static void add_socket_rpc_tcp(struct server_service *service, - const struct model_ops *model_ops, - struct dcesrv_context *dce_ctx, - struct dcesrv_endpoint *e) +static void add_socket_rpc_tcp(struct server_service *service, struct dcesrv_endpoint *e) { /* Add TCP/IP sockets */ if (lp_interfaces() && lp_bind_interfaces_only()) { @@ -179,12 +171,12 @@ static void add_socket_rpc_tcp(struct server_service *service, if (ifip == NULL) { continue; } - add_socket_rpc_tcp_iface(service, model_ops, dce_ctx, e, ifip); + add_socket_rpc_tcp_iface(service, e, ifip); } } else { struct ipv4_addr ifip; ifip = interpret_addr2(lp_socket_address()); - add_socket_rpc_tcp_iface(service, model_ops, dce_ctx, e, &ifip); + add_socket_rpc_tcp_iface(service, e, &ifip); } return; @@ -193,8 +185,9 @@ static void add_socket_rpc_tcp(struct server_service *service, /**************************************************************************** Open the listening sockets for RPC over NCACN_IP_TCP/NCALRPC/NCACN_UNIX_STREAM ****************************************************************************/ -void dcesrv_sock_init(struct server_service *service, const struct model_ops *model_ops, struct dcesrv_context *dce_ctx) +void dcesrv_sock_init(struct server_service *service) { + struct dcesrv_context *dce_ctx = service->service.private_data; struct dcesrv_endpoint *e; DEBUG(1,("dcesrv_sock_init\n")); @@ -207,15 +200,15 @@ void dcesrv_sock_init(struct server_service *service, const struct model_ops *mo for (e=dce_ctx->endpoint_list;e;e=e->next) { switch (e->ep_description.transport) { case NCACN_UNIX_STREAM: - add_socket_rpc_unix(service, model_ops, dce_ctx, e); + add_socket_rpc_unix(service, e); break; case NCALRPC: - add_socket_rpc_ncalrpc(service, model_ops, dce_ctx, e); + add_socket_rpc_ncalrpc(service, e); break; case NCACN_IP_TCP: - add_socket_rpc_tcp(service, model_ops, dce_ctx, e); + add_socket_rpc_tcp(service, e); break; default: @@ -229,7 +222,7 @@ void dcesrv_sock_init(struct server_service *service, const struct model_ops *mo void dcesrv_sock_accept(struct server_connection *srv_conn) { NTSTATUS status; - struct dcesrv_socket_context *dcesrv_sock = srv_conn->server_socket->private_data; + struct dcesrv_socket_context *dcesrv_sock = srv_conn->stream_socket->stream.private_data; struct dcesrv_connection *dcesrv_conn = NULL; DEBUG(5,("dcesrv_sock_accept\n")); @@ -245,7 +238,7 @@ void dcesrv_sock_accept(struct server_connection *srv_conn) return; } - srv_conn->private_data = dcesrv_conn; + srv_conn->connection.private_data = dcesrv_conn; return; } @@ -253,7 +246,7 @@ void dcesrv_sock_accept(struct server_connection *srv_conn) void dcesrv_sock_recv(struct server_connection *conn, struct timeval t, uint16_t flags) { NTSTATUS status; - struct dcesrv_connection *dce_conn = conn->private_data; + struct dcesrv_connection *dce_conn = conn->connection.private_data; DATA_BLOB tmp_blob; size_t nread; @@ -292,7 +285,7 @@ void dcesrv_sock_recv(struct server_connection *conn, struct timeval t, uint16_t void dcesrv_sock_send(struct server_connection *conn, struct timeval t, uint16_t flags) { - struct dcesrv_connection *dce_conn = conn->private_data; + struct dcesrv_connection *dce_conn = conn->connection.private_data; NTSTATUS status; DEBUG(10,("dcesrv_sock_send\n")); @@ -309,20 +302,3 @@ void dcesrv_sock_send(struct server_connection *conn, struct timeval t, uint16_t return; } - -void dcesrv_sock_close(struct server_connection *conn, const char *reason) -{ - struct dcesrv_connection *dce_conn = conn->private_data; - - DEBUG(5,("dcesrv_sock_close: %s\n",reason)); - - talloc_free(dce_conn); - - return; -} - -void dcesrv_sock_exit(struct server_service *service, const char *reason) -{ - DEBUG(1,("dcesrv_sock_exit: %s\n",reason)); - return; -} diff --git a/source4/smb_server/negprot.c b/source4/smb_server/negprot.c index 77df978a05..4af8fed53b 100644 --- a/source4/smb_server/negprot.c +++ b/source4/smb_server/negprot.c @@ -144,7 +144,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->pid); + SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->connection.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 +198,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->pid); + SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->connection.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 +310,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->pid); /* session key */ + SIVAL(req->out.vwv+1, VWV(7), req->smb_conn->connection->connection.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); diff --git a/source4/smb_server/request.c b/source4/smb_server/request.c index 2ac832b439..f7f39f39d5 100644 --- a/source4/smb_server/request.c +++ b/source4/smb_server/request.c @@ -47,8 +47,6 @@ struct smbsrv_request *init_smb_request(struct smbsrv_connection *smb_conn) { struct smbsrv_request *req; - smb_conn->pkt_count++; - req = talloc_p(smb_conn, struct smbsrv_request); if (!req) { return NULL; diff --git a/source4/smb_server/service.c b/source4/smb_server/service.c index 1aa41d17a8..d4386ca77b 100644 --- a/source4/smb_server/service.c +++ b/source4/smb_server/service.c @@ -72,54 +72,6 @@ static int find_service(const char *service) iService = lp_servicenumber(service); - /* If we still don't have a service, attempt to add it as a printer. */ - if (iService == -1) { - int iPrinterService; - - if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) { - const char *pszTemp; - - DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - pszTemp = lp_printcapname(); - if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) { - DEBUG(3,("%s is a valid printer name\n", service)); - DEBUG(3,("adding %s as a printer service\n", service)); - lp_add_printer(service, iPrinterService); - iService = lp_servicenumber(service); - if (iService < 0) - DEBUG(0,("failed to add %s as a printer service!\n", service)); - } else { - DEBUG(3,("%s is not a valid printer name\n", service)); - } - } - } - - /* Check for default vfs service? Unsure whether to implement this */ - if (iService == -1) { - } - - /* just possibly it's a default service? */ - if (iService == -1) { - const char *pdefservice = lp_defaultservice(); - if (pdefservice && *pdefservice && - !strequal(pdefservice,service) && - !strstr(service,"..")) { - /* - * We need to do a local copy here as lp_defaultservice() - * returns one of the rotating lp_string buffers that - * could get overwritten by the recursive find_service() call - * below. Fix from Josef Hinteregger . - */ - pstring defservice; - pstrcpy(defservice, pdefservice); - iService = find_service(defservice); - if (iService >= 0) { - /* REWRITE: all_string_sub(service, "_","/",0); */ - iService = lp_add_service(service, iService); - } - } - } - if (iService >= 0 && !VALID_SNUM(iService)) { DEBUG(0,("Invalid snum %d for %s\n",iService, service)); iService = -1; diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index ddbaf43cc9..1cbc831a17 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -506,7 +506,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), smb_conn->connection->service->model_ops->get_id(req))); + DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->connection.id)); /* does this protocol need a valid tree connection? */ if ((flags & AS_USER) && !req->tcon) { @@ -649,21 +649,12 @@ void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char server_terminate_connection(smb_conn->connection, reason); } -/* - called on a fatal error that should cause this server to terminate -*/ -static void smbsrv_exit(struct server_service *service, const char *reason) -{ - DEBUG(1,("smbsrv_exit\n")); - return; -} +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, - const struct model_ops *model_ops, - struct socket_context *socket_ctx, +static void smb_add_socket(struct server_service *service, struct ipv4_addr *ifip) { const char **ports = lp_smb_ports(); @@ -673,7 +664,7 @@ static void smb_add_socket(struct server_service *service, for (i=0;ports[i];i++) { uint16_t port = atoi(ports[i]); if (port == 0) continue; - service_setup_socket(service, model_ops, "ipv4", ip_str, &port); + service_setup_stream_socket(service, smbsrv_stream_ops(), "ipv4", ip_str, &port); } talloc_free(ip_str); @@ -682,7 +673,7 @@ static void smb_add_socket(struct server_service *service, /**************************************************************************** Open the socket communication. ****************************************************************************/ -static void smbsrv_init(struct server_service *service, const struct model_ops *model_ops) +static void smbsrv_init(struct server_service *service) { DEBUG(1,("smbsrv_init\n")); @@ -702,13 +693,13 @@ static void smbsrv_init(struct server_service *service, const struct model_ops * continue; } - smb_add_socket(service, model_ops, NULL, ifip); + 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, model_ops, NULL, &ifip); + smb_add_socket(service, &ifip); } } @@ -717,7 +708,7 @@ static void smbsrv_init(struct server_service *service, const struct model_ops * */ static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16_t flags) { - struct smbsrv_connection *smb_conn = conn->private_data; + struct smbsrv_connection *smb_conn = conn->connection.private_data; NTSTATUS status; DEBUG(10,("smbsrv_recv\n")); @@ -738,7 +729,7 @@ static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16 */ static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16_t flags) { - struct smbsrv_connection *smb_conn = conn->private_data; + struct smbsrv_connection *smb_conn = conn->connection.private_data; while (smb_conn->pending_send) { struct smbsrv_request *req = smb_conn->pending_send; @@ -776,19 +767,9 @@ static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16 } } -/* - called when connection is idle -*/ -static void smbsrv_idle(struct server_connection *conn, struct timeval t) -{ - DEBUG(10,("smbsrv_idle: not implemented!\n")); - conn->event.idle->next_event = timeval_add(&t, 5, 0); - return; -} - static void smbsrv_close(struct server_connection *conn, const char *reason) { - struct smbsrv_connection *smb_conn = conn->private_data; + struct smbsrv_connection *smb_conn = conn->connection.private_data; DEBUG(5,("smbsrv_close: %s\n",reason)); @@ -818,7 +799,7 @@ void smbd_process_async(struct smbsrv_connection *smb_conn) initialise a server_context from a open socket and register a event handler for reading from that socket */ -void smbsrv_accept(struct server_connection *conn) +static void smbsrv_accept(struct server_connection *conn) { struct smbsrv_connection *smb_conn; @@ -827,10 +808,6 @@ void smbsrv_accept(struct server_connection *conn) smb_conn = talloc_zero_p(conn, struct smbsrv_connection); if (!smb_conn) return; - smb_conn->pid = getpid(); - - sub_set_context(&smb_conn->substitute); - /* now initialise a few default values associated with this smb socket */ smb_conn->negotiate.max_send = 0xFFFF; @@ -848,20 +825,29 @@ void smbsrv_accept(struct server_connection *conn) smb_conn->connection = conn; - conn->private_data = smb_conn; + conn->connection.private_data = smb_conn; return; } -static const struct server_service_ops smb_server_ops = { +static const struct server_stream_ops smb_stream_ops = { .name = "smb", - .service_init = smbsrv_init, + .socket_init = NULL, .accept_connection = smbsrv_accept, .recv_handler = smbsrv_recv, .send_handler = smbsrv_send, - .idle_handler = smbsrv_idle, - .close_connection = smbsrv_close, - .service_exit = smbsrv_exit, + .idle_handler = NULL, + .close_connection = smbsrv_close +}; + +static const struct server_stream_ops *smbsrv_stream_ops(void) +{ + return &smb_stream_ops; +} + +static const struct server_service_ops smb_server_ops = { + .name = "smb", + .service_init = smbsrv_init, }; const struct server_service_ops *smbsrv_get_ops(void) diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 8a21051b65..01eb63d01c 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -150,7 +150,7 @@ struct substitute_context { struct smbsrv_connection { /* a count of the number of packets we have received. We * actually only care about zero/non-zero at this stage */ - unsigned pkt_count; + //unsigned pkt_count; /* context that has been negotiated between the client and server */ struct { @@ -213,6 +213,7 @@ struct smbsrv_connection { } tree; /* the context associated with open files on an smb socket */ +#if 0 struct { struct files_struct *files; /* open files */ @@ -228,7 +229,7 @@ struct smbsrv_connection { /* limit for maximum open files */ int real_max_open_files; } file; - +#endif /* context associated with currently valid session setups */ struct { /* this holds info on session vuids that are already validated for this VC */ @@ -237,11 +238,6 @@ struct smbsrv_connection { int num_validated_vuids; } sessions; - /* this holds long term state specific to the printing subsystem */ - struct { - struct notify_queue *notify_queue_head; - } print; - /* the server_context holds a linked list of pending requests, * this is used for blocking locks and requests blocked due to oplock * break requests */ @@ -251,7 +247,7 @@ struct smbsrv_connection { /* the request itself - needs to be freed */ struct smbsrv_request *request; } *requests; - +#if 0 /* the timers context contains info on when we last did various * functions */ struct { @@ -264,13 +260,10 @@ struct smbsrv_connection { /* when we last checked the smb.conf for auto-reload */ time_t last_smb_conf_reload; } timers; - +#endif struct smb_signing_context signing; - struct substitute_context substitute; - - /* the pid of the process handling this session */ - pid_t pid; +// struct substitute_context substitute; struct server_connection *connection; diff --git a/source4/smbd/config.mk b/source4/smbd/config.mk index df421326d8..cd2fb4ab72 100644 --- a/source4/smbd/config.mk +++ b/source4/smbd/config.mk @@ -50,24 +50,15 @@ REQUIRED_SUBSYSTEMS = \ # End SUBSYSTEM SERVER ####################### -####################### -# Start SUBSYSTEM SERVER -[SUBSYSTEM::SERVER] -INIT_OBJ_FILES = \ - smbd/server.o -ADD_OBJ_FILES = \ - smbd/rewrite.o -REQUIRED_SUBSYSTEMS = \ - PROCESS_MODEL \ - SERVER_SERVICE -# End SUBSYSTEM SERVER -####################### - ################################# # Start BINARY smbd [BINARY::smbd] +OBJ_FILES = \ + smbd/server.o \ + smbd/rewrite.o REQUIRED_SUBSYSTEMS = \ - SERVER \ + PROCESS_MODEL \ + SERVER_SERVICE \ CONFIG \ LIBCMDLINE \ LIBBASIC diff --git a/source4/smbd/process_model.c b/source4/smbd/process_model.c index ad9a26d377..f2abfd0a49 100644 --- a/source4/smbd/process_model.c +++ b/source4/smbd/process_model.c @@ -27,7 +27,7 @@ /* setup the events for the chosen process model */ -const struct model_ops *process_model_startup(const char *model) +const struct model_ops *process_model_startup(struct server_context *srv_ctx, const char *model) { const struct model_ops *ops; @@ -37,7 +37,7 @@ const struct model_ops *process_model_startup(const char *model) exit(-1); } - ops->model_startup(); + ops->model_init(srv_ctx); return ops; } diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h index 92d92a70ad..fb9bdfd44b 100644 --- a/source4/smbd/process_model.h +++ b/source4/smbd/process_model.h @@ -3,7 +3,7 @@ process model manager - main loop Copyright (C) Andrew Tridgell 1992-2003 Copyright (C) James J Myers 2003 - Copyright (C) Stefan (metze) Metzmacher 2004 + Copyright (C) Stefan (metze) Metzmacher 2004-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,21 +37,23 @@ struct model_ops { const char *name; /* called at startup when the model is selected */ - void (*model_startup)(void); + void (*model_init)(struct server_context *srv_ctx); + /* called at th eend of the main server process */ + void (*model_exit)(struct server_context *srv_ctx, const char *reason); + /* function to accept new connection */ void (*accept_connection)(struct event_context *, struct fd_event *, struct timeval t, uint16_t); - /* function to terminate a connection */ void (*terminate_connection)(struct server_connection *srv_conn, const char *reason); - /* function to exit server */ - void (*exit_server)(struct server_context *srv_ctx, const char *reason); - /* returns process or thread id */ - int (*get_id)(struct smbsrv_request *req); + /* function to create a new task event_context */ + void (*create_task)(struct server_task *task); + /* function to exit this task */ + void (*terminate_task)(struct server_task *task, const char *reason); }; /* this structure is used by modules to determine the size of some critical types */ diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index da23470303..6a00ad237f 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -30,9 +30,15 @@ /* called when the process model is selected */ -static void single_start_server(void) +static void single_model_init(struct server_context *server) { - smbd_process_init(); +} + +static void single_model_exit(struct server_context *server, const char *reason) +{ + DEBUG(1,("single_exit_server: reason[%s]\n",reason)); + talloc_free(server); + exit(0); } /* @@ -43,18 +49,18 @@ static void single_accept_connection(struct event_context *ev, struct fd_event * { NTSTATUS status; struct socket_context *sock; - struct server_socket *server_socket = srv_fde->private; + struct server_stream_socket *stream_socket = srv_fde->private; struct server_connection *conn; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock); + status = socket_accept(stream_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("accept_connection_single: accept: %s\n", nt_errstr(status))); return; } - conn = server_setup_connection(ev, server_socket, sock, t, socket_get_fd(sock)); + conn = server_setup_connection(ev, stream_socket, sock, t, socket_get_fd(sock)); if (!conn) { DEBUG(10,("server_setup_connection failed\n")); return; @@ -62,8 +68,6 @@ static void single_accept_connection(struct event_context *ev, struct fd_event * talloc_steal(conn, sock); - DLIST_ADD(server_socket->connection_list,conn); - /* return to event handling */ return; } @@ -80,38 +84,57 @@ static void single_terminate_connection(struct server_connection *conn, const ch } } -static int single_get_id(struct smbsrv_request *req) +/* + called to create a new event context for a new task +*/ +static void single_create_task(struct server_task *task) { - return (int)req->smb_conn->pid; + task->task.id = (uint32_t)task; + task->event.ctx = task->service->server->event.ctx; + + /* setup to receive internal messages on this connection */ + task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx); + if (!task->messaging.ctx) { + server_terminate_task(task, "messaging_init() failed"); + return; + } + + task->task.ops->task_init(task); + return; } -static void single_exit_server(struct server_context *srv_ctx, const char *reason) +/* + called to exit from a server_task +*/ +static void single_terminate_task(struct server_task *task, const char *reason) { DEBUG(1,("single_exit_server: reason[%s]\n",reason)); + talloc_free(task); + return; } +static const struct model_ops single_ops = { + .name = "single", + + .model_init = single_model_init, + .model_exit = single_model_exit, + + .accept_connection = single_accept_connection, + .terminate_connection = single_terminate_connection, + + .create_task = single_create_task, + .terminate_task = single_terminate_task +}; + /* initialise the single process model, registering ourselves with the process model subsystem */ NTSTATUS process_model_single_init(void) { NTSTATUS ret; - struct model_ops ops; - - ZERO_STRUCT(ops); - - /* fill in our name */ - ops.name = "single"; - - /* fill in all the operations */ - ops.model_startup = single_start_server; - ops.accept_connection = single_accept_connection; - ops.terminate_connection = single_terminate_connection; - ops.exit_server = single_exit_server; - ops.get_id = single_get_id; /* register ourselves with the PROCESS_MODEL subsystem. */ - ret = register_process_model(&ops); + ret = register_process_model(&single_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register process_model 'single'!\n")); return ret; diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index 3612c6a7f4..b0f7cf1a11 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -29,10 +29,16 @@ /* called when the process model is selected */ -static void standard_model_startup(void) +static void standard_model_init(struct server_context *server) { signal(SIGCHLD, SIG_IGN); - smbd_process_init(); +} + +static void standard_model_exit(struct server_context *server, const char *reason) +{ + DEBUG(1,("standard_model_exit: reason[%s]\n",reason)); + talloc_free(server); + exit(0); } /* @@ -43,12 +49,12 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event { NTSTATUS status; struct socket_context *sock; - struct server_socket *server_socket = srv_fde->private; + struct server_stream_socket *stream_socket = srv_fde->private; struct server_connection *conn; pid_t pid; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock); + status = socket_accept(stream_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); @@ -68,7 +74,7 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event /* Child code ... */ /* close all the listening sockets */ - service_close_listening_sockets(server_socket->service->srv_ctx); + event_remove_fd_all_handler(ev, server_accept_handler); /* we don't care if the dup fails, as its only a select() speed optimisation */ @@ -83,16 +89,15 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event set_need_random_reseed(); - conn = server_setup_connection(ev, server_socket, sock, t, getpid()); + conn = server_setup_connection(ev, stream_socket, sock, t, getpid()); if (!conn) { DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n")); + exit(1); return; } talloc_steal(conn, sock); - DLIST_ADD(server_socket->connection_list,conn); - /* return to the event loop */ } @@ -103,7 +108,7 @@ static void standard_terminate_connection(struct server_connection *conn, const DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason)); if (conn) { - talloc_free(conn->service->srv_ctx); + talloc_free(conn->stream_socket->service->server); } /* this init_iconv() has the effect of freeing the iconv context memory, @@ -117,38 +122,94 @@ static void standard_terminate_connection(struct server_connection *conn, const exit(0); } -static int standard_get_id(struct smbsrv_request *req) +/* + called to create a new event context for a new task +*/ +static void standard_create_task(struct server_task *task) { - return (int)req->smb_conn->pid; + pid_t pid; + + pid = fork(); + + if (pid != 0) { + /* parent or error code ... */ + talloc_free(task); + /* go back to the event loop */ + return; + } + + /* Child code ... */ + + /* close all the listening sockets */ + event_remove_fd_all_handler(task->service->server->event.ctx, server_accept_handler); + + /* tdb needs special fork handling */ + if (tdb_reopen_all() == -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(); + + task->task.id = (uint32)getpid(); + task->event.ctx = task->service->server->event.ctx; + + /* setup to receive internal messages on this connection */ + task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx); + if (!task->messaging.ctx) { + server_terminate_task(task, "messaging_init() failed"); + return; + } + + task->task.ops->task_init(task); + + server_terminate_task(task, "exit"); + return; } -static void standard_exit_server(struct server_context *srv_ctx, const char *reason) +/* + called to destroy a new event context for a new task +*/ +static void standard_terminate_task(struct server_task *task, const char *reason) { - DEBUG(1,("standard_exit_server: reason[%s]\n",reason)); + DEBUG(2,("standard_terminate_task: reason[%s]\n",reason)); + + talloc_free(task); + + /* this init_iconv() has the effect of freeing the iconv context memory, + which makes leak checking easier */ + init_iconv(); + + /* the secrets db should really hang off the connection structure */ + secrets_shutdown(); + + /* terminate this process */ + exit(0); } +static const struct model_ops standard_ops = { + .name = "standard", + + .model_init = standard_model_init, + .model_exit = standard_model_exit, + + .accept_connection = standard_accept_connection, + .terminate_connection = standard_terminate_connection, + + .create_task = standard_create_task, + .terminate_task = standard_terminate_task +}; + /* initialise the standard process model, registering ourselves with the process model subsystem */ NTSTATUS process_model_standard_init(void) { NTSTATUS ret; - struct model_ops ops; - - ZERO_STRUCT(ops); - - /* fill in our name */ - ops.name = "standard"; - - /* fill in all the operations */ - ops.model_startup = standard_model_startup; - ops.accept_connection = standard_accept_connection; - ops.terminate_connection = standard_terminate_connection; - ops.exit_server = standard_exit_server; - ops.get_id = standard_get_id; /* register ourselves with the PROCESS_MODEL subsystem. */ - ret = register_process_model(&ops); + ret = register_process_model(&standard_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register process_model 'standard'!\n")); return ret; diff --git a/source4/smbd/process_thread.c b/source4/smbd/process_thread.c index 8e8ee23aaf..f0e98221ae 100644 --- a/source4/smbd/process_thread.c +++ b/source4/smbd/process_thread.c @@ -33,9 +33,12 @@ static void *thread_connection_fn(void *thread_parm) { - struct event_context *ev = thread_parm; + struct server_connection *conn = thread_parm; + + conn->connection.id = pthread_self(); + /* wait for action */ - event_loop_wait(ev); + event_loop_wait(conn->event.ctx); #if 0 pthread_cleanup_pop(1); /* will invoke terminate_mt_connection() */ @@ -43,11 +46,6 @@ static void *thread_connection_fn(void *thread_parm) return NULL; } -static int thread_get_id(struct smbsrv_request *req) -{ - return (int)pthread_self(); -} - /* called when a listening socket becomes readable */ @@ -59,15 +57,15 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event * int rc; pthread_t thread_id; pthread_attr_t thread_attr; - struct server_socket *server_socket = srv_fde->private; + struct server_stream_socket *stream_socket = srv_fde->private; struct server_connection *conn; /* accept an incoming connection. */ - status = socket_accept(server_socket->socket, &sock); + status = socket_accept(stream_socket->socket, &sock); if (!NT_STATUS_IS_OK(status)) { return; } - + /* create new detached thread for this connection. The new thread gets a new event_context with a single fd_event for receiving from the new socket. We set that thread running @@ -75,13 +73,13 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event * main event_context is continued. */ - ev = event_context_init(server_socket); + ev = event_context_init(stream_socket); if (!ev) { socket_destroy(sock); - return; + return; } - conn = server_setup_connection(ev, server_socket, sock, t, pthread_self()); + conn = server_setup_connection(ev, stream_socket, sock, t, -1); if (!conn) { event_context_destroy(ev); socket_destroy(sock); @@ -91,16 +89,9 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event * talloc_steal(conn, ev); talloc_steal(conn, sock); - /* TODO: is this MUTEX_LOCK in the right place here? - * --metze - */ - MUTEX_LOCK_BY_ID(MUTEX_SMBD); - DLIST_ADD(server_socket->connection_list,conn); - MUTEX_UNLOCK_BY_ID(MUTEX_SMBD); - pthread_attr_init(&thread_attr); pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, ev); + rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, conn); pthread_attr_destroy(&thread_attr); if (rc == 0) { DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n", @@ -414,7 +405,7 @@ static void thread_fault_handler(int sig) /* called when the process model is selected */ -static void thread_model_startup(void) +static void thread_model_init(struct server_context *server) { struct mutex_ops m_ops; struct debug_ops d_ops; @@ -422,8 +413,6 @@ static void thread_model_startup(void) ZERO_STRUCT(m_ops); ZERO_STRUCT(d_ops); - smbd_process_init(); - /* register mutex/rwlock handlers */ m_ops.mutex_init = thread_mutex_init; m_ops.mutex_lock = thread_mutex_lock; @@ -448,33 +437,100 @@ static void thread_model_startup(void) register_debug_handlers("thread", &d_ops); } -static void thread_exit_server(struct server_context *srv_ctx, const char *reason) +static void thread_model_exit(struct server_context *server, const char *reason) { - DEBUG(1,("thread_exit_server: reason[%s]\n",reason)); + DEBUG(1,("thread_model_exit: reason[%s]\n",reason)); + talloc_free(server); + exit(0); } +static void *thread_task_fn(void *thread_parm) +{ + struct server_task *task = thread_parm; + + task->task.id = pthread_self(); + + task->event.ctx = event_context_init(task); + if (!task->event.ctx) { + server_terminate_task(task, "event_context_init() failed"); + return NULL; + } + + task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx); + if (!task->messaging.ctx) { + server_terminate_task(task, "messaging_init() failed"); + return NULL; + } + + task->task.ops->task_init(task); + + /* wait for action */ + event_loop_wait(task->event.ctx); + + server_terminate_task(task, "exit"); +#if 0 + pthread_cleanup_pop(1); /* will invoke terminate_mt_connection() */ +#endif + return NULL; +} +/* + called to create a new event context for a new task +*/ +static void thread_create_task(struct server_task *task) +{ + int rc; + pthread_t thread_id; + pthread_attr_t thread_attr; + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, task); + pthread_attr_destroy(&thread_attr); + if (rc == 0) { + DEBUG(4,("thread_create_task: created thread_id=%lu for task='%s'\n", + (unsigned long int)thread_id, task->task.ops->name)); + } else { + DEBUG(0,("thread_create_task: thread create failed for task='%s', rc=%d\n", task->task.ops->name, rc)); + return; + } + return; +} + +/* + called to destroy a new event context for a new task +*/ +static void thread_terminate_task(struct server_task *task, const char *reason) +{ + DEBUG(2,("thread_terminate_task: reason[%s]\n",reason)); + + talloc_free(task); + + /* terminate this thread */ + pthread_exit(NULL); /* thread cleanup routine will do actual cleanup */ +} + +static const struct model_ops thread_ops = { + .name = "thread", + + .model_init = thread_model_init, + .model_exit = thread_model_exit, + + .accept_connection = thread_accept_connection, + .terminate_connection = thread_terminate_connection, + + .create_task = thread_create_task, + .terminate_task = thread_terminate_task +}; + /* initialise the thread process model, registering ourselves with the model subsystem */ NTSTATUS process_model_thread_init(void) { NTSTATUS ret; - struct model_ops ops; - - ZERO_STRUCT(ops); - - /* fill in our name */ - ops.name = "thread"; - - /* fill in all the operations */ - ops.model_startup = thread_model_startup; - ops.accept_connection = thread_accept_connection; - ops.terminate_connection = thread_terminate_connection; - ops.exit_server = thread_exit_server; - ops.get_id = thread_get_id; /* register ourselves with the PROCESS_MODEL subsystem. */ - ret = register_process_model(&ops); + ret = register_process_model(&thread_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register process_model 'thread'!\n")); return ret; diff --git a/source4/smbd/rewrite.c b/source4/smbd/rewrite.c index 8e7ddc405e..7128a0ad0d 100644 --- a/source4/smbd/rewrite.c +++ b/source4/smbd/rewrite.c @@ -1,14 +1,6 @@ #include "includes.h" #include "dynconfig.h" -/* - - this is a set of temporary stub functions used during the core smbd rewrite. - This file will need to go away before the rewrite is complete -*/ - -BOOL pcap_printername_ok(const char *service, const char *foo) -{ return True; } /* * initialize an smb process. Guaranteed to be called only once per diff --git a/source4/smbd/server.c b/source4/smbd/server.c index 830d26fa7f..369391bdbf 100644 --- a/source4/smbd/server.c +++ b/source4/smbd/server.c @@ -24,12 +24,6 @@ #include "includes.h" #include "lib/cmdline/popt_common.h" -static void exit_server(const char *reason) -{ - DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); - exit(0); -} - /**************************************************************************** main server. ****************************************************************************/ @@ -41,10 +35,10 @@ static int binary_smbd_main(int argc,const char *argv[]) BOOL log_stdout = False; int opt; poptContext pc; - struct server_context *srv_ctx; + struct server_context *server; const char *model = "standard"; struct poptOption long_options[] = { - POPT_AUTOHELP + POPT_AUTOHELP POPT_COMMON_SAMBA {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" , NULL }, {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)", NULL}, @@ -52,6 +46,7 @@ static int binary_smbd_main(int argc,const char *argv[]) {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout", NULL }, {"port", 'p', POPT_ARG_STRING, NULL, 0, "Listen on the specified ports", "PORTS"}, {"model", 'M', POPT_ARG_STRING, &model, True, "Select process model", "MODEL"}, + POPT_COMMON_VERSION POPT_TABLEEND }; @@ -77,7 +72,7 @@ static int binary_smbd_main(int argc,const char *argv[]) } setup_logging(argv[0], log_stdout?DEBUG_STDOUT:DEBUG_FILE); - fault_setup((void (*)(void *))exit_server); + fault_setup(NULL); /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); @@ -105,7 +100,7 @@ static int binary_smbd_main(int argc,const char *argv[]) reopen_logs(); DEBUG(0,("smbd version %s started.\n", SAMBA_VERSION_STRING)); - DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2004\n")); + DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2005\n")); if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); @@ -142,15 +137,21 @@ static int binary_smbd_main(int argc,const char *argv[]) init_subsystems(); + smbd_process_init(); + DEBUG(0,("Using %s process model\n", model)); - srv_ctx = server_service_startup(model); - if (!srv_ctx) { + server = server_service_startup(model, lp_server_services()); + if (!server) { DEBUG(0,("Starting Services failed.\n")); return 1; } /* wait for events */ - return event_loop_wait(srv_ctx->events); + event_loop_wait(server->event.ctx); + + server_service_shutdown(server, "exit"); + + return 0; } int main(int argc, const char *argv[]) diff --git a/source4/smbd/server.h b/source4/smbd/server.h index e76adec44d..6021df12c5 100644 --- a/source4/smbd/server.h +++ b/source4/smbd/server.h @@ -25,8 +25,15 @@ struct server_service; struct event_context; struct server_context { + struct { + struct event_context *ctx; + } event; + + struct { + const struct model_ops *ops; + } model; + struct server_service *service_list; - struct event_context *events; }; /* size of listen() backlog in smbd */ diff --git a/source4/smbd/service.c b/source4/smbd/service.c index 586c05c2c6..e0ec3cf07e 100644 --- a/source4/smbd/service.c +++ b/source4/smbd/service.c @@ -27,38 +27,33 @@ #include "dlinklist.h" #include "process_model.h" -struct server_context *server_service_startup(const char *model) +struct server_context *server_service_startup(const char *model, const char **server_services) { int i; - const char **server_services = lp_server_services(); - struct server_context *srv_ctx; - const struct model_ops *model_ops; + struct server_context *server; if (!server_services) { - DEBUG(0,("process_model_startup: no endpoint servers configured\n")); + DEBUG(0,("server_service_startup: no endpoint servers configured\n")); return NULL; } - model_ops = process_model_startup(model); - if (!model_ops) { - DEBUG(0,("process_model_startup('%s') failed\n", model)); - return NULL; - } - - srv_ctx = talloc_p(NULL, struct server_context); - if (!srv_ctx) { + server = talloc_zero(NULL, struct server_context); + if (!server) { return NULL; } - ZERO_STRUCTP(srv_ctx); + server->model.ops = process_model_startup(server, model); + if (!server->model.ops) { + DEBUG(0,("process_model_startup('%s') failed\n", model)); + return NULL; + } - srv_ctx->events = event_context_init(srv_ctx); - if (!srv_ctx->events) { + server->event.ctx = event_context_init(server); + if (!server->event.ctx) { DEBUG(0,("event_context_init() failed\n")); - return NULL; + return NULL; } - for (i=0;server_services[i];i++) { const struct server_service_ops *service_ops; struct server_service *service; @@ -69,63 +64,64 @@ struct server_context *server_service_startup(const char *model) return NULL; } - service = talloc_p(srv_ctx, struct server_service); + service = talloc_zero(server, struct server_service); if (!service) { return NULL; } - ZERO_STRUCTP(service); - service->ops = service_ops; - service->model_ops = model_ops; - service->srv_ctx = srv_ctx; - + service->service.ops = service_ops; + service->server = server; + /* TODO: service_init() should return a result */ - service->ops->service_init(service, model_ops); + service->service.ops->service_init(service); - DLIST_ADD(srv_ctx->service_list, service); + DLIST_ADD(server->service_list, service); } - return srv_ctx; + return server; +} + +void server_service_shutdown(struct server_context *server, const char *reason) +{ + server->model.ops->model_exit(server, reason); } /* setup a listen stream socket if you pass *port == 0, then a port > 1024 is used */ -struct server_socket *service_setup_socket(struct server_service *service, - const struct model_ops *model_ops, - const char *family, - const char *sock_addr, - uint16_t *port) +struct server_stream_socket *service_setup_stream_socket(struct server_service *service, + const struct server_stream_ops *stream_ops, + const char *family, + const char *sock_addr, + uint16_t *port) { NTSTATUS status; - struct server_socket *srv_sock; - struct socket_context *socket_ctx; + struct server_stream_socket *stream_socket; + struct socket_context *sock; struct fd_event fde; int i; - status = socket_create(family, SOCKET_TYPE_STREAM, &socket_ctx, 0); + status = socket_create(family, SOCKET_TYPE_STREAM, &sock, 0); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to open socket on %s:%u - %s\n", sock_addr, *port, nt_errstr(status))); return NULL; } - talloc_steal(service, socket_ctx); - /* ready to listen */ - status = socket_set_option(socket_ctx, "SO_KEEPALIVE SO_REUSEADDR=1", NULL); + status = socket_set_option(sock, "SO_KEEPALIVE SO_REUSEADDR=1", NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n", nt_errstr(status))); - socket_destroy(socket_ctx); + socket_destroy(sock); return NULL; } - status = socket_set_option(socket_ctx, lp_socket_options(), NULL); + status = socket_set_option(sock, lp_socket_options(), NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n", nt_errstr(status))); - socket_destroy(socket_ctx); + socket_destroy(sock); return NULL; } @@ -133,64 +129,70 @@ struct server_socket *service_setup_socket(struct server_service *service, if (*port == 0) { for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) { - status = socket_listen(socket_ctx, sock_addr, i, SERVER_LISTEN_BACKLOG, 0); + status = socket_listen(sock, sock_addr, i, SERVER_LISTEN_BACKLOG, 0); if (NT_STATUS_IS_OK(status)) { *port = i; break; } } } else { - status = socket_listen(socket_ctx, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0); + status = socket_listen(sock, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0); } if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to listen on %s:%u - %s\n", sock_addr, *port, nt_errstr(status))); - socket_destroy(socket_ctx); + socket_destroy(sock); return NULL; } - srv_sock = talloc_p(service, struct server_socket); - if (!srv_sock) { - DEBUG(0,("talloc_p(mem_ctx, struct server_socket) failed\n")); - socket_destroy(socket_ctx); + stream_socket = talloc_zero(service, struct server_stream_socket); + if (!stream_socket) { + DEBUG(0,("talloc_p(mem_ctx, struct server_stream_socket) failed\n")); + socket_destroy(sock); return NULL; } /* we are only interested in read events on the listen socket */ - fde.fd = socket_get_fd(socket_ctx); + fde.fd = socket_get_fd(sock); fde.flags = EVENT_FD_READ; - fde.private = srv_sock; - fde.handler = model_ops->accept_connection; - - ZERO_STRUCTP(srv_sock); - srv_sock->service = service; - srv_sock->socket = socket_ctx; - srv_sock->event.ctx = service->srv_ctx->events; - srv_sock->event.fde = event_add_fd(srv_sock->event.ctx, &fde); - if (!srv_sock->event.fde) { - DEBUG(0,("event_add_fd(srv_sock->event.ctx, &fde) failed\n")); - socket_destroy(socket_ctx); + fde.private = stream_socket; + fde.handler = server_accept_handler; + + stream_socket->stream.ops = stream_ops; + stream_socket->service = service; + stream_socket->socket = sock; + stream_socket->event.ctx = service->server->event.ctx; + stream_socket->event.fde = event_add_fd(stream_socket->event.ctx, &fde); + if (!stream_socket->event.fde) { + DEBUG(0,("event_add_fd(stream_socket->event.ctx, &fde) failed\n")); + socket_destroy(sock); return NULL; } - DLIST_ADD(service->socket_list, srv_sock); + talloc_steal(stream_socket, sock); - return srv_sock; + if (stream_socket->stream.ops->socket_init) { + stream_socket->stream.ops->socket_init(stream_socket); + } + + return stream_socket; } /* destructor that handles necessary event context changes */ -static int server_destructor(void *ptr) +static int server_connection_destructor(void *ptr) { struct server_connection *conn = ptr; - if (conn->service) { - conn->service->ops->close_connection(conn, "shutdown"); - } - - socket_destroy(conn->socket); + if (conn->stream_socket && + conn->stream_socket->stream.ops->close_connection) { + /* don't remove this! the stream service needs to free it's data + * before we destroy the server_connection + */ + conn->stream_socket->stream.ops->close_connection(conn, "shutdown"); + } if (conn->event.fde) { event_remove_fd(conn->event.ctx, conn->event.fde); @@ -201,13 +203,11 @@ static int server_destructor(void *ptr) conn->event.idle = NULL; } - DLIST_REMOVE(conn->server_socket->connection_list, conn); - return 0; } struct server_connection *server_setup_connection(struct event_context *ev, - struct server_socket *server_socket, + struct server_stream_socket *stream_socket, struct socket_context *sock, struct timeval t, servid_t server_id) @@ -216,7 +216,7 @@ struct server_connection *server_setup_connection(struct event_context *ev, struct timed_event idle; struct server_connection *srv_conn; - srv_conn = talloc_p(server_socket, struct server_connection); + srv_conn = talloc_p(stream_socket, struct server_connection); if (!srv_conn) { DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n")); return NULL; @@ -238,20 +238,19 @@ struct server_connection *server_setup_connection(struct event_context *ev, srv_conn->event.idle = &idle; srv_conn->event.idle_time = timeval_set(SERVER_DEFAULT_IDLE_TIME, 0); - srv_conn->server_socket = server_socket; - srv_conn->service = server_socket->service; + srv_conn->stream_socket = stream_socket; srv_conn->socket = sock; - srv_conn->server_id = server_id; + srv_conn->connection.id = server_id; /* create a server context and add it to out event handling */ - server_socket->service->ops->accept_connection(srv_conn); + stream_socket->stream.ops->accept_connection(srv_conn); /* accpect_connection() of the service may changed idle.next_event */ srv_conn->event.fde = event_add_fd(ev,&fde); srv_conn->event.idle = event_add_timed(ev,&idle); - talloc_set_destructor(srv_conn, server_destructor); + talloc_set_destructor(srv_conn, server_connection_destructor); if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) { server_terminate_connection(srv_conn, "denied by access rules"); @@ -259,7 +258,11 @@ struct server_connection *server_setup_connection(struct event_context *ev, } /* setup to receive internal messages on this connection */ - srv_conn->messaging_ctx = messaging_init(srv_conn, srv_conn->server_id, ev); + srv_conn->messaging.ctx = messaging_init(srv_conn, srv_conn->connection.id, ev); + if (!srv_conn->messaging.ctx) { + server_terminate_connection(srv_conn, "messaging_init() failed"); + return NULL; + } return srv_conn; } @@ -270,7 +273,15 @@ struct server_connection *server_setup_connection(struct event_context *ev, void server_terminate_connection(struct server_connection *srv_conn, const char *reason) { DEBUG(2,("server_terminate_connection\n")); - srv_conn->service->model_ops->terminate_connection(srv_conn, reason); + srv_conn->stream_socket->service->server->model.ops->terminate_connection(srv_conn, reason); +} + +void server_accept_handler(struct event_context *ev, struct fd_event *fde, + struct timeval t, uint16_t flags) +{ + struct server_stream_socket *stream_socket = fde->private; + + stream_socket->service->server->model.ops->accept_connection(ev, fde, t, flags); } void server_io_handler(struct event_context *ev, struct fd_event *fde, @@ -281,12 +292,12 @@ void server_io_handler(struct event_context *ev, struct fd_event *fde, conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time); if (flags & EVENT_FD_WRITE) { - conn->service->ops->send_handler(conn, t, flags); + conn->stream_socket->stream.ops->send_handler(conn, t, flags); return; } if (flags & EVENT_FD_READ) { - conn->service->ops->recv_handler(conn, t, flags); + conn->stream_socket->stream.ops->recv_handler(conn, t, flags); } } @@ -296,13 +307,34 @@ void server_idle_handler(struct event_context *ev, struct timed_event *idle, { struct server_connection *conn = idle->private; - conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time); - /* Not all services provide an idle handler */ - if (conn->service->ops->idle_handler) { - conn->service->ops->idle_handler(conn, t); + if (conn->stream_socket->stream.ops->idle_handler) { + conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time); + conn->stream_socket->stream.ops->idle_handler(conn, t); } } + +void server_terminate_task(struct server_task *task, const char *reason) +{ + task->service->server->model.ops->terminate_task(task, reason); + return; +} + +void server_run_task(struct server_service *service, const struct server_task_ops *ops) +{ + struct server_task *task; + + task = talloc_zero(service, struct server_task); + if (!task) { + return; + } + task->service = service; + task->task.ops = ops; + + service->server->model.ops->create_task(task); + return; +} + /* return the operations structure for a named backend of the specified type */ @@ -325,25 +357,6 @@ NTSTATUS register_server_service_ops(const void *_ops) return NT_STATUS_NOT_IMPLEMENTED; } -/* - close all listening sockets. This is called by process models that fork, to - ensure that the listen sockets from the parent are closed -*/ -void service_close_listening_sockets(struct server_context *srv_ctx) -{ - struct server_service *svc; - for (svc=srv_ctx->service_list;svc;svc=svc->next) { - struct server_socket *sock; - for (sock=svc->socket_list;sock;sock=sock->next) { - event_remove_fd(sock->event.ctx, sock->event.fde); - sock->event.fde = NULL; - socket_destroy(sock->socket); - sock->socket = NULL; - } - } -} - - /* cleanup temporary files. This is the new alternative to TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not diff --git a/source4/smbd/service.h b/source4/smbd/service.h index 20bf6e9b8f..d5335b1cef 100644 --- a/source4/smbd/service.h +++ b/source4/smbd/service.h @@ -42,7 +42,17 @@ struct server_service_ops { const char *name; /* called at startup when the server_service is selected */ - void (*service_init)(struct server_service *service, const struct model_ops *ops); + void (*service_init)(struct server_service *service); +}; + +struct server_stream_socket; + +struct server_stream_ops { + /* the name of the server_service */ + const char *name; + + /* called at startup when the server_service is selected */ + void (*socket_init)(struct server_stream_socket *socket); /* function to accept new connection */ void (*accept_connection)(struct server_connection *); @@ -56,16 +66,16 @@ struct server_service_ops { /* function to close a connection */ void (*close_connection)(struct server_connection *, const char *reason); - - /* function to exit server */ - void (*service_exit)(struct server_service *srv_ctx, const char *reason); }; struct socket_context; -struct server_socket { - struct server_socket *next,*prev; - void *private_data; +struct server_stream_socket { + struct server_stream_socket *next,*prev; + struct { + const struct server_stream_ops *ops; + void *private_data; + } stream; struct { struct event_context *ctx; @@ -75,20 +85,16 @@ struct server_socket { struct socket_context *socket; struct server_service *service; - - struct server_connection *connection_list; }; struct server_service { struct server_service *next,*prev; - void *private_data; - const struct server_service_ops *ops; - - const struct model_ops *model_ops; - - struct server_socket *socket_list; + struct { + const struct server_service_ops *ops; + void *private_data; + } service; - struct server_context *srv_ctx; + struct server_context *server; }; /* the concept of whether two operations are on the same server @@ -106,7 +112,10 @@ typedef uint32_t servid_t; struct server_connection { struct server_connection *next,*prev; - void *private_data; + struct { + void *private_data; + servid_t id; + } connection; struct { struct event_context *ctx; @@ -115,15 +124,42 @@ struct server_connection { struct timeval idle_time; } event; - servid_t server_id; - struct socket_context *socket; - struct server_socket *server_socket; + struct server_stream_socket *stream_socket; - struct server_service *service; + struct { + struct messaging_context *ctx; + } messaging; +}; + +struct server_task; + +struct server_task_ops { + /* the name of the server_task */ + const char *name; + + /* called at startup when the server_task is selected */ + void (*task_init)(struct server_task *task); +}; + +struct server_task { + struct server_task *next,*prev; + struct { + const struct server_task_ops *ops; + void *private_data; + servid_t id; + } task; + + struct { + struct event_context *ctx; + } event; + + struct { + struct messaging_context *ctx; + } messaging; - struct messaging_context *messaging_ctx; + struct server_service *service; }; #endif /* _SERVER_SERVICE_H */ -- cgit