2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Stefan (metze) Metzmacher 2004
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "system/dir.h"
26 #include "dlinklist.h"
28 struct server_context *server_service_startup(const char *model)
31 const char **server_services = lp_server_services();
32 struct server_context *srv_ctx;
33 const struct model_ops *model_ops;
35 if (!server_services) {
36 DEBUG(0,("process_model_startup: no endpoint servers configured\n"));
40 model_ops = process_model_startup(model);
42 DEBUG(0,("process_model_startup('%s') failed\n", model));
46 srv_ctx = talloc_p(NULL, struct server_context);
51 ZERO_STRUCTP(srv_ctx);
53 srv_ctx->events = event_context_init(srv_ctx);
54 if (!srv_ctx->events) {
55 DEBUG(0,("event_context_init() failed\n"));
60 for (i=0;server_services[i];i++) {
61 const struct server_service_ops *service_ops;
62 struct server_service *service;
64 service_ops = server_service_byname(server_services[i]);
66 DEBUG(0,("process_model_startup: failed to find server service = '%s'\n", server_services[i]));
70 service = talloc_p(srv_ctx, struct server_service);
75 ZERO_STRUCTP(service);
76 service->ops = service_ops;
77 service->model_ops = model_ops;
78 service->srv_ctx = srv_ctx;
80 /* TODO: service_init() should return a result */
81 service->ops->service_init(service, model_ops);
83 DLIST_ADD(srv_ctx->service_list, service);
90 setup a listen stream socket
91 if you pass *port == 0, then a port > 1024 is used
93 struct server_socket *service_setup_socket(struct server_service *service,
94 const struct model_ops *model_ops,
96 const char *sock_addr,
100 struct server_socket *srv_sock;
101 struct socket_context *socket_ctx;
105 status = socket_create(family, SOCKET_TYPE_STREAM, &socket_ctx, 0);
106 if (!NT_STATUS_IS_OK(status)) {
107 DEBUG(0,("Failed to open socket on %s:%u - %s\n",
108 sock_addr, *port, nt_errstr(status)));
112 talloc_steal(service, socket_ctx);
114 /* ready to listen */
115 status = socket_set_option(socket_ctx, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
116 if (!NT_STATUS_IS_OK(status)) {
117 DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n",
119 socket_destroy(socket_ctx);
122 status = socket_set_option(socket_ctx, lp_socket_options(), NULL);
123 if (!NT_STATUS_IS_OK(status)) {
124 DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n",
126 socket_destroy(socket_ctx);
130 /* TODO: set socket ACL's here when they're implemented */
133 for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
134 status = socket_listen(socket_ctx, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
135 if (NT_STATUS_IS_OK(status)) {
141 status = socket_listen(socket_ctx, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
144 if (!NT_STATUS_IS_OK(status)) {
145 DEBUG(0,("Failed to listen on %s:%u - %s\n",
146 sock_addr, *port, nt_errstr(status)));
147 socket_destroy(socket_ctx);
151 srv_sock = talloc_p(service, struct server_socket);
153 DEBUG(0,("talloc_p(mem_ctx, struct server_socket) failed\n"));
154 socket_destroy(socket_ctx);
158 /* we are only interested in read events on the listen socket */
159 fde.fd = socket_get_fd(socket_ctx);
160 fde.flags = EVENT_FD_READ;
161 fde.private = srv_sock;
162 fde.handler = model_ops->accept_connection;
164 ZERO_STRUCTP(srv_sock);
165 srv_sock->service = service;
166 srv_sock->socket = socket_ctx;
167 srv_sock->event.ctx = service->srv_ctx->events;
168 srv_sock->event.fde = event_add_fd(srv_sock->event.ctx, &fde);
169 if (!srv_sock->event.fde) {
170 DEBUG(0,("event_add_fd(srv_sock->event.ctx, &fde) failed\n"));
171 socket_destroy(socket_ctx);
175 DLIST_ADD(service->socket_list, srv_sock);
181 destructor that handles necessary event context changes
183 static int server_destructor(void *ptr)
185 struct server_connection *conn = ptr;
188 conn->service->ops->close_connection(conn, "shutdown");
191 socket_destroy(conn->socket);
193 event_remove_fd(conn->event.ctx, conn->event.fde);
194 conn->event.fde = NULL;
195 event_remove_timed(conn->event.ctx, conn->event.idle);
196 conn->event.idle = NULL;
198 DLIST_REMOVE(conn->server_socket->connection_list, conn);
203 struct server_connection *server_setup_connection(struct event_context *ev,
204 struct server_socket *server_socket,
205 struct socket_context *sock,
210 struct timed_event idle;
211 struct server_connection *srv_conn;
213 srv_conn = talloc_p(server_socket, struct server_connection);
215 DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n"));
219 ZERO_STRUCTP(srv_conn);
221 fde.private = srv_conn;
222 fde.fd = socket_get_fd(sock);
223 fde.flags = EVENT_FD_READ;
224 fde.handler = server_io_handler;
226 idle.private = srv_conn;
227 idle.next_event = t + SERVER_DEFAULT_IDLE_TIME;
228 idle.handler = server_idle_handler;
230 srv_conn->event.ctx = ev;
231 srv_conn->event.fde = &fde;
232 srv_conn->event.idle = &idle;
233 srv_conn->event.idle_time = SERVER_DEFAULT_IDLE_TIME;
235 srv_conn->server_socket = server_socket;
236 srv_conn->service = server_socket->service;
237 srv_conn->socket = sock;
238 srv_conn->server_id = server_id;
240 /* create a smb server context and add it to out event
242 server_socket->service->ops->accept_connection(srv_conn);
244 /* accpect_connection() of the service may changed idle.next_event */
245 srv_conn->event.fde = event_add_fd(ev,&fde);
246 srv_conn->event.idle = event_add_timed(ev,&idle);
248 talloc_set_destructor(srv_conn, server_destructor);
250 if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
251 server_terminate_connection(srv_conn, "denied by access rules");
255 /* setup to receive internal messages on this connection */
256 srv_conn->messaging_ctx = messaging_init(srv_conn, srv_conn->server_id, ev);
262 close the socket and shutdown a server_context
264 void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
266 DEBUG(2,("server_terminate_connection\n"));
267 srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
270 void server_io_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags)
272 struct server_connection *conn = fde->private;
274 conn->event.idle->next_event = t + conn->event.idle_time;
276 if (flags & EVENT_FD_WRITE) {
277 conn->service->ops->send_handler(conn, t, flags);
281 if (flags & EVENT_FD_READ) {
282 conn->service->ops->recv_handler(conn, t, flags);
287 void server_idle_handler(struct event_context *ev, struct timed_event *idle, time_t t)
289 struct server_connection *conn = idle->private;
291 conn->event.idle->next_event = t + conn->event.idle_time;
293 conn->service->ops->idle_handler(conn,t);
296 return the operations structure for a named backend of the specified type
298 const struct server_service_ops *server_service_byname(const char *name)
300 if (strcmp("smb",name)==0) {
301 return smbsrv_get_ops();
303 if (strcmp("rpc",name)==0) {
304 return dcesrv_get_ops();
306 if (strcmp("ldap",name)==0) {
307 return ldapsrv_get_ops();
312 static NTSTATUS register_server_service_ops(const void *_ops)
314 return NT_STATUS_NOT_IMPLEMENTED;
318 initialise the SERVER SERVICE subsystem
320 BOOL server_service_init(void)
324 status = register_subsystem("service", register_server_service_ops);
325 if (!NT_STATUS_IS_OK(status)) {
329 /* FIXME: Perhaps panic if a basic endpoint server, such as EPMAPER, fails to initialise? */
330 static_init_server_service;
332 DEBUG(3,("SERVER SERVICE subsystem version %d initialised\n", SERVER_SERVICE_VERSION));
338 close all listening sockets. This is called by process models that fork, to
339 ensure that the listen sockets from the parent are closed
341 void service_close_listening_sockets(struct server_context *srv_ctx)
343 struct server_service *svc;
344 for (svc=srv_ctx->service_list;svc;svc=svc->next) {
345 struct server_socket *sock;
346 for (sock=svc->socket_list;sock;sock=sock->next) {
347 event_remove_fd(sock->event.ctx, sock->event.fde);
348 sock->event.fde = NULL;
349 socket_destroy(sock->socket);
357 cleanup temporary files. This is the new alternative to
358 TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
359 efficient on unix systems due to the lack of scaling of the byte
360 range locking system. So instead of putting the burden on tdb to
361 cleanup tmp files, this function deletes them.
363 void service_cleanup_tmp_files(void)
368 TALLOC_CTX *mem_ctx = talloc_init("service_cleanup_tmp_files");
370 path = smbd_tmp_path(mem_ctx, NULL);
374 talloc_free(mem_ctx);
378 for (de=readdir(dir);de;de=readdir(dir)) {
379 char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
380 int ret = unlink(fname);
385 DEBUG(0,("Unabled to delete '%s' - %s\n",
386 fname, strerror(errno)));
387 smb_panic("unable to cleanup tmp files");
393 talloc_free(mem_ctx);