r4685: only remove events when we have them
[kai/samba.git] / source4 / smbd / service.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    SERVER SERVICE code
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan (metze) Metzmacher      2004
8    
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
25 #include "events.h"
26 #include "system/dir.h"
27 #include "dlinklist.h"
28 #include "process_model.h"
29
30 struct server_context *server_service_startup(const char *model)
31 {
32         int i;
33         const char **server_services = lp_server_services();
34         struct server_context *srv_ctx;
35         const struct model_ops *model_ops;
36
37         if (!server_services) {
38                 DEBUG(0,("process_model_startup: no endpoint servers configured\n"));
39                 return NULL;
40         }
41
42         model_ops = process_model_startup(model);
43         if (!model_ops) {
44                 DEBUG(0,("process_model_startup('%s') failed\n", model));
45                 return NULL;
46         }
47
48         srv_ctx = talloc_p(NULL, struct server_context);
49         if (!srv_ctx) {
50                 return NULL;    
51         }
52
53         ZERO_STRUCTP(srv_ctx);
54
55         srv_ctx->events = event_context_init(srv_ctx);
56         if (!srv_ctx->events) {
57                 DEBUG(0,("event_context_init() failed\n"));
58                 return NULL;    
59         }
60
61
62         for (i=0;server_services[i];i++) {
63                 const struct server_service_ops *service_ops;
64                 struct server_service *service;
65
66                 service_ops = server_service_byname(server_services[i]);
67                 if (!service_ops) {
68                         DEBUG(0,("process_model_startup: failed to find server service = '%s'\n", server_services[i]));
69                         return NULL;
70                 }
71
72                 service = talloc_p(srv_ctx, struct server_service);
73                 if (!service) {
74                         return NULL;
75                 }
76
77                 ZERO_STRUCTP(service);
78                 service->ops            = service_ops;
79                 service->model_ops      = model_ops;
80                 service->srv_ctx        = srv_ctx;
81                 
82                 /* TODO: service_init() should return a result */
83                 service->ops->service_init(service, model_ops);
84
85                 DLIST_ADD(srv_ctx->service_list, service);
86         }
87
88         return srv_ctx;
89 }
90
91 /*
92   setup a listen stream socket
93   if you pass *port == 0, then a port > 1024 is used
94  */
95 struct server_socket *service_setup_socket(struct server_service *service,
96                                            const struct model_ops *model_ops,
97                                            const char *family,
98                                            const char *sock_addr,
99                                            uint16_t *port)
100 {
101         NTSTATUS status;
102         struct server_socket *srv_sock;
103         struct socket_context *socket_ctx;
104         struct fd_event fde;
105         int i;
106
107         status = socket_create(family, SOCKET_TYPE_STREAM, &socket_ctx, 0);
108         if (!NT_STATUS_IS_OK(status)) {
109                 DEBUG(0,("Failed to open socket on %s:%u - %s\n",
110                         sock_addr, *port, nt_errstr(status)));
111                 return NULL;
112         }
113
114         talloc_steal(service, socket_ctx);
115
116         /* ready to listen */
117         status = socket_set_option(socket_ctx, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
118         if (!NT_STATUS_IS_OK(status)) {
119                 DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n",
120                         nt_errstr(status)));
121                 socket_destroy(socket_ctx);
122                 return NULL;
123         }
124         status = socket_set_option(socket_ctx, lp_socket_options(), NULL);
125         if (!NT_STATUS_IS_OK(status)) {
126                 DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n",
127                         nt_errstr(status)));
128                 socket_destroy(socket_ctx);
129                 return NULL;
130         }
131
132         /* TODO: set socket ACL's here when they're implemented */
133
134         if (*port == 0) {
135                 for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
136                         status = socket_listen(socket_ctx, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
137                         if (NT_STATUS_IS_OK(status)) {
138                                 *port = i;
139                                 break;
140                         }
141                 }
142         } else {
143                 status = socket_listen(socket_ctx, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
144         }
145
146         if (!NT_STATUS_IS_OK(status)) {
147                 DEBUG(0,("Failed to listen on %s:%u - %s\n",
148                         sock_addr, *port, nt_errstr(status)));
149                 socket_destroy(socket_ctx);
150                 return NULL;
151         }
152
153         srv_sock = talloc_p(service, struct server_socket);
154         if (!srv_sock) {
155                 DEBUG(0,("talloc_p(mem_ctx, struct server_socket) failed\n"));
156                 socket_destroy(socket_ctx);
157                 return NULL;
158         }
159
160         /* we are only interested in read events on the listen socket */
161         fde.fd          = socket_get_fd(socket_ctx);
162         fde.flags       = EVENT_FD_READ;
163         fde.private     = srv_sock;
164         fde.handler     = model_ops->accept_connection;
165
166         ZERO_STRUCTP(srv_sock);
167         srv_sock->service       = service;
168         srv_sock->socket        = socket_ctx;
169         srv_sock->event.ctx     = service->srv_ctx->events;
170         srv_sock->event.fde     = event_add_fd(srv_sock->event.ctx, &fde);
171         if (!srv_sock->event.fde) {
172                 DEBUG(0,("event_add_fd(srv_sock->event.ctx, &fde) failed\n"));
173                 socket_destroy(socket_ctx);
174                 return NULL;
175         }
176
177         DLIST_ADD(service->socket_list, srv_sock);
178
179         return srv_sock;
180 }
181
182 /*
183   destructor that handles necessary event context changes
184  */
185 static int server_destructor(void *ptr)
186 {
187         struct server_connection *conn = ptr;
188
189         if (conn->service) {
190                 conn->service->ops->close_connection(conn, "shutdown");
191         }
192
193         socket_destroy(conn->socket);
194
195         if (conn->event.fde) {
196                 event_remove_fd(conn->event.ctx, conn->event.fde);
197                 conn->event.fde = NULL;
198         }
199         if (conn->event.idle) {
200                 event_remove_timed(conn->event.ctx, conn->event.idle);
201                 conn->event.idle = NULL;
202         }
203
204         DLIST_REMOVE(conn->server_socket->connection_list, conn);
205
206         return 0;
207 }
208
209 struct server_connection *server_setup_connection(struct event_context *ev, 
210                                                   struct server_socket *server_socket, 
211                                                   struct socket_context *sock, 
212                                                   struct timeval t,
213                                                   servid_t server_id)
214 {
215         struct fd_event fde;
216         struct timed_event idle;
217         struct server_connection *srv_conn;
218
219         srv_conn = talloc_p(server_socket, struct server_connection);
220         if (!srv_conn) {
221                 DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n"));
222                 return NULL;
223         }
224
225         ZERO_STRUCTP(srv_conn);
226
227         fde.private     = srv_conn;
228         fde.fd          = socket_get_fd(sock);
229         fde.flags       = EVENT_FD_READ;
230         fde.handler     = server_io_handler;
231
232         idle.private    = srv_conn;
233         idle.next_event = timeval_add(&t, SERVER_DEFAULT_IDLE_TIME, 0);
234         idle.handler    = server_idle_handler;
235
236         srv_conn->event.ctx             = ev;
237         srv_conn->event.fde             = &fde;
238         srv_conn->event.idle            = &idle;
239         srv_conn->event.idle_time       = timeval_set(SERVER_DEFAULT_IDLE_TIME, 0);
240
241         srv_conn->server_socket         = server_socket;
242         srv_conn->service               = server_socket->service;
243         srv_conn->socket                = sock;
244         srv_conn->server_id             = server_id;
245
246         /* create a server context and add it to out event
247            handling */
248         server_socket->service->ops->accept_connection(srv_conn);
249
250         /* accpect_connection() of the service may changed idle.next_event */
251         srv_conn->event.fde     = event_add_fd(ev,&fde);
252         srv_conn->event.idle    = event_add_timed(ev,&idle);
253
254         talloc_set_destructor(srv_conn, server_destructor);
255
256         if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
257                 server_terminate_connection(srv_conn, "denied by access rules");
258                 return NULL;
259         }
260
261         /* setup to receive internal messages on this connection */
262         srv_conn->messaging_ctx = messaging_init(srv_conn, srv_conn->server_id, ev);
263
264         return srv_conn;
265 }
266
267 /*
268   close the socket and shutdown a server_context
269 */
270 void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
271 {
272         DEBUG(2,("server_terminate_connection\n"));
273         srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
274 }
275
276 void server_io_handler(struct event_context *ev, struct fd_event *fde, 
277                        struct timeval t, uint16_t flags)
278 {
279         struct server_connection *conn = fde->private;
280
281         conn->event.idle->next_event = timeval_sum(&t,  &conn->event.idle_time);
282
283         if (flags & EVENT_FD_WRITE) {
284                 conn->service->ops->send_handler(conn, t, flags);
285                 return;
286         }
287
288         if (flags & EVENT_FD_READ) {
289                 conn->service->ops->recv_handler(conn, t, flags);
290         }
291
292 }
293
294 void server_idle_handler(struct event_context *ev, struct timed_event *idle, 
295                          struct timeval t)
296 {
297         struct server_connection *conn = idle->private;
298
299         conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
300
301         /* Not all services provide an idle handler */
302         if (conn->service->ops->idle_handler) {
303                 conn->service->ops->idle_handler(conn, t);
304         }
305 }
306 /*
307   return the operations structure for a named backend of the specified type
308 */
309 const struct server_service_ops *server_service_byname(const char *name)
310 {
311         if (strcmp("smb",name)==0) {
312                 return smbsrv_get_ops();
313         }
314         if (strcmp("rpc",name)==0) {
315                 return dcesrv_get_ops();
316         }
317         if (strcmp("ldap",name)==0) {
318                 return ldapsrv_get_ops();
319         }
320         return NULL;
321 }
322
323 NTSTATUS register_server_service_ops(const void *_ops)
324 {
325         return NT_STATUS_NOT_IMPLEMENTED;
326 }
327
328 /*
329   close all listening sockets. This is called by process models that fork, to 
330   ensure that the listen sockets from the parent are closed
331 */
332 void service_close_listening_sockets(struct server_context *srv_ctx)
333 {
334         struct server_service *svc;
335         for (svc=srv_ctx->service_list;svc;svc=svc->next) {
336                 struct server_socket *sock;
337                 for (sock=svc->socket_list;sock;sock=sock->next) {
338                         event_remove_fd(sock->event.ctx, sock->event.fde);
339                         sock->event.fde = NULL;
340                         socket_destroy(sock->socket);
341                         sock->socket = NULL;
342                 }
343         }
344 }
345
346
347 /*
348   cleanup temporary files. This is the new alternative to
349   TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
350   efficient on unix systems due to the lack of scaling of the byte
351   range locking system. So instead of putting the burden on tdb to
352   cleanup tmp files, this function deletes them. 
353 */
354 void service_cleanup_tmp_files(void)
355 {
356         char *path;
357         DIR *dir;
358         struct dirent *de;
359         TALLOC_CTX *mem_ctx = talloc_init("service_cleanup_tmp_files");
360
361         path = smbd_tmp_path(mem_ctx, NULL);
362
363         dir = opendir(path);
364         if (!dir) {
365                 talloc_free(mem_ctx);
366                 return;
367         }
368
369         for (de=readdir(dir);de;de=readdir(dir)) {
370                 char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
371                 int ret = unlink(fname);
372                 if (ret == -1 &&
373                     errno != ENOENT &&
374                     errno != EISDIR &&
375                     errno != EISDIR) {
376                         DEBUG(0,("Unabled to delete '%s' - %s\n", 
377                                  fname, strerror(errno)));
378                         smb_panic("unable to cleanup tmp files");
379                 }
380                 talloc_free(fname);
381         }
382         closedir(dir);
383
384         talloc_free(mem_ctx);
385 }