r3481: split out client.h and events.h
[garming/samba-autobuild/.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         event_remove_fd(conn->event.ctx, conn->event.fde);
196         conn->event.fde = NULL;
197         event_remove_timed(conn->event.ctx, conn->event.idle);
198         conn->event.idle = NULL;
199
200         DLIST_REMOVE(conn->server_socket->connection_list, conn);
201
202         return 0;
203 }
204
205 struct server_connection *server_setup_connection(struct event_context *ev, 
206                                                   struct server_socket *server_socket, 
207                                                   struct socket_context *sock, 
208                                                   time_t t,
209                                                   servid_t server_id)
210 {
211         struct fd_event fde;
212         struct timed_event idle;
213         struct server_connection *srv_conn;
214
215         srv_conn = talloc_p(server_socket, struct server_connection);
216         if (!srv_conn) {
217                 DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n"));
218                 return NULL;
219         }
220
221         ZERO_STRUCTP(srv_conn);
222
223         fde.private     = srv_conn;
224         fde.fd          = socket_get_fd(sock);
225         fde.flags       = EVENT_FD_READ;
226         fde.handler     = server_io_handler;
227
228         idle.private    = srv_conn;
229         idle.next_event = t + SERVER_DEFAULT_IDLE_TIME;
230         idle.handler    = server_idle_handler;
231
232         srv_conn->event.ctx             = ev;
233         srv_conn->event.fde             = &fde;
234         srv_conn->event.idle            = &idle;
235         srv_conn->event.idle_time       = SERVER_DEFAULT_IDLE_TIME;
236
237         srv_conn->server_socket         = server_socket;
238         srv_conn->service               = server_socket->service;
239         srv_conn->socket                = sock;
240         srv_conn->server_id             = server_id;
241
242         /* create a smb server context and add it to out event
243            handling */
244         server_socket->service->ops->accept_connection(srv_conn);
245
246         /* accpect_connection() of the service may changed idle.next_event */
247         srv_conn->event.fde     = event_add_fd(ev,&fde);
248         srv_conn->event.idle    = event_add_timed(ev,&idle);
249
250         talloc_set_destructor(srv_conn, server_destructor);
251
252         if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
253                 server_terminate_connection(srv_conn, "denied by access rules");
254                 return NULL;
255         }
256
257         /* setup to receive internal messages on this connection */
258         srv_conn->messaging_ctx = messaging_init(srv_conn, srv_conn->server_id, ev);
259
260         return srv_conn;
261 }
262
263 /*
264   close the socket and shutdown a server_context
265 */
266 void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
267 {
268         DEBUG(2,("server_terminate_connection\n"));
269         srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
270 }
271
272 void server_io_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags)
273 {
274         struct server_connection *conn = fde->private;
275
276         conn->event.idle->next_event = t + conn->event.idle_time;
277
278         if (flags & EVENT_FD_WRITE) {
279                 conn->service->ops->send_handler(conn, t, flags);
280                 return;
281         }
282
283         if (flags & EVENT_FD_READ) {
284                 conn->service->ops->recv_handler(conn, t, flags);
285         }
286
287 }
288
289 void server_idle_handler(struct event_context *ev, struct timed_event *idle, time_t t)
290 {
291         struct server_connection *conn = idle->private;
292
293         conn->event.idle->next_event = t + conn->event.idle_time;
294
295         conn->service->ops->idle_handler(conn,t);
296 }
297 /*
298   return the operations structure for a named backend of the specified type
299 */
300 const struct server_service_ops *server_service_byname(const char *name)
301 {
302         if (strcmp("smb",name)==0) {
303                 return smbsrv_get_ops();
304         }
305         if (strcmp("rpc",name)==0) {
306                 return dcesrv_get_ops();
307         }
308         if (strcmp("ldap",name)==0) {
309                 return ldapsrv_get_ops();
310         }
311         return NULL;
312 }
313
314 static NTSTATUS register_server_service_ops(const void *_ops)
315 {
316         return NT_STATUS_NOT_IMPLEMENTED;
317 }
318
319 /*
320   initialise the SERVER SERVICE subsystem
321 */
322 BOOL server_service_init(void)
323 {
324         NTSTATUS status;
325
326         status = register_subsystem("service", register_server_service_ops); 
327         if (!NT_STATUS_IS_OK(status)) {
328                 return False;
329         }
330
331         /* FIXME: Perhaps panic if a basic endpoint server, such as EPMAPER, fails to initialise? */
332         static_init_server_service;
333
334         DEBUG(3,("SERVER SERVICE subsystem version %d initialised\n", SERVER_SERVICE_VERSION));
335         return True;
336 }
337
338
339 /*
340   close all listening sockets. This is called by process models that fork, to 
341   ensure that the listen sockets from the parent are closed
342 */
343 void service_close_listening_sockets(struct server_context *srv_ctx)
344 {
345         struct server_service *svc;
346         for (svc=srv_ctx->service_list;svc;svc=svc->next) {
347                 struct server_socket *sock;
348                 for (sock=svc->socket_list;sock;sock=sock->next) {
349                         event_remove_fd(sock->event.ctx, sock->event.fde);
350                         sock->event.fde = NULL;
351                         socket_destroy(sock->socket);
352                         sock->socket = NULL;
353                 }
354         }
355 }
356
357
358 /*
359   cleanup temporary files. This is the new alternative to
360   TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
361   efficient on unix systems due to the lack of scaling of the byte
362   range locking system. So instead of putting the burden on tdb to
363   cleanup tmp files, this function deletes them. 
364 */
365 void service_cleanup_tmp_files(void)
366 {
367         char *path;
368         DIR *dir;
369         struct dirent *de;
370         TALLOC_CTX *mem_ctx = talloc_init("service_cleanup_tmp_files");
371
372         path = smbd_tmp_path(mem_ctx, NULL);
373
374         dir = opendir(path);
375         if (!dir) {
376                 talloc_free(mem_ctx);
377                 return;
378         }
379
380         for (de=readdir(dir);de;de=readdir(dir)) {
381                 char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
382                 int ret = unlink(fname);
383                 if (ret == -1 &&
384                     errno != ENOENT &&
385                     errno != EISDIR &&
386                     errno != EISDIR) {
387                         DEBUG(0,("Unabled to delete '%s' - %s\n", 
388                                  fname, strerror(errno)));
389                         smb_panic("unable to cleanup tmp files");
390                 }
391                 talloc_free(fname);
392         }
393         closedir(dir);
394
395         talloc_free(mem_ctx);
396 }