r3463: separated out some more headers (asn_1.h, messages.h, dlinklist.h and ioctl.h)
[bbaumbach/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 "system/dir.h"
26 #include "dlinklist.h"
27
28 struct server_context *server_service_startup(const char *model)
29 {
30         int i;
31         const char **server_services = lp_server_services();
32         struct server_context *srv_ctx;
33         const struct model_ops *model_ops;
34
35         if (!server_services) {
36                 DEBUG(0,("process_model_startup: no endpoint servers configured\n"));
37                 return NULL;
38         }
39
40         model_ops = process_model_startup(model);
41         if (!model_ops) {
42                 DEBUG(0,("process_model_startup('%s') failed\n", model));
43                 return NULL;
44         }
45
46         srv_ctx = talloc_p(NULL, struct server_context);
47         if (!srv_ctx) {
48                 return NULL;    
49         }
50
51         ZERO_STRUCTP(srv_ctx);
52
53         srv_ctx->events = event_context_init(srv_ctx);
54         if (!srv_ctx->events) {
55                 DEBUG(0,("event_context_init() failed\n"));
56                 return NULL;    
57         }
58
59
60         for (i=0;server_services[i];i++) {
61                 const struct server_service_ops *service_ops;
62                 struct server_service *service;
63
64                 service_ops = server_service_byname(server_services[i]);
65                 if (!service_ops) {
66                         DEBUG(0,("process_model_startup: failed to find server service = '%s'\n", server_services[i]));
67                         return NULL;
68                 }
69
70                 service = talloc_p(srv_ctx, struct server_service);
71                 if (!service) {
72                         return NULL;
73                 }
74
75                 ZERO_STRUCTP(service);
76                 service->ops            = service_ops;
77                 service->model_ops      = model_ops;
78                 service->srv_ctx        = srv_ctx;
79                 
80                 /* TODO: service_init() should return a result */
81                 service->ops->service_init(service, model_ops);
82
83                 DLIST_ADD(srv_ctx->service_list, service);
84         }
85
86         return srv_ctx;
87 }
88
89 /*
90   setup a listen stream socket
91   if you pass *port == 0, then a port > 1024 is used
92  */
93 struct server_socket *service_setup_socket(struct server_service *service,
94                                            const struct model_ops *model_ops,
95                                            const char *family,
96                                            const char *sock_addr,
97                                            uint16_t *port)
98 {
99         NTSTATUS status;
100         struct server_socket *srv_sock;
101         struct socket_context *socket_ctx;
102         struct fd_event fde;
103         int i;
104
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)));
109                 return NULL;
110         }
111
112         talloc_steal(service, socket_ctx);
113
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",
118                         nt_errstr(status)));
119                 socket_destroy(socket_ctx);
120                 return NULL;
121         }
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",
125                         nt_errstr(status)));
126                 socket_destroy(socket_ctx);
127                 return NULL;
128         }
129
130         /* TODO: set socket ACL's here when they're implemented */
131
132         if (*port == 0) {
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)) {
136                                 *port = i;
137                                 break;
138                         }
139                 }
140         } else {
141                 status = socket_listen(socket_ctx, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
142         }
143
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);
148                 return NULL;
149         }
150
151         srv_sock = talloc_p(service, struct server_socket);
152         if (!srv_sock) {
153                 DEBUG(0,("talloc_p(mem_ctx, struct server_socket) failed\n"));
154                 socket_destroy(socket_ctx);
155                 return NULL;
156         }
157
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;
163
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);
172                 return NULL;
173         }
174
175         DLIST_ADD(service->socket_list, srv_sock);
176
177         return srv_sock;
178 }
179
180 /*
181   destructor that handles necessary event context changes
182  */
183 static int server_destructor(void *ptr)
184 {
185         struct server_connection *conn = ptr;
186
187         if (conn->service) {
188                 conn->service->ops->close_connection(conn, "shutdown");
189         }
190
191         socket_destroy(conn->socket);
192
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;
197
198         DLIST_REMOVE(conn->server_socket->connection_list, conn);
199
200         return 0;
201 }
202
203 struct server_connection *server_setup_connection(struct event_context *ev, 
204                                                   struct server_socket *server_socket, 
205                                                   struct socket_context *sock, 
206                                                   time_t t,
207                                                   servid_t server_id)
208 {
209         struct fd_event fde;
210         struct timed_event idle;
211         struct server_connection *srv_conn;
212
213         srv_conn = talloc_p(server_socket, struct server_connection);
214         if (!srv_conn) {
215                 DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n"));
216                 return NULL;
217         }
218
219         ZERO_STRUCTP(srv_conn);
220
221         fde.private     = srv_conn;
222         fde.fd          = socket_get_fd(sock);
223         fde.flags       = EVENT_FD_READ;
224         fde.handler     = server_io_handler;
225
226         idle.private    = srv_conn;
227         idle.next_event = t + SERVER_DEFAULT_IDLE_TIME;
228         idle.handler    = server_idle_handler;
229
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;
234
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;
239
240         /* create a smb server context and add it to out event
241            handling */
242         server_socket->service->ops->accept_connection(srv_conn);
243
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);
247
248         talloc_set_destructor(srv_conn, server_destructor);
249
250         if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
251                 server_terminate_connection(srv_conn, "denied by access rules");
252                 return NULL;
253         }
254
255         /* setup to receive internal messages on this connection */
256         srv_conn->messaging_ctx = messaging_init(srv_conn, srv_conn->server_id, ev);
257
258         return srv_conn;
259 }
260
261 /*
262   close the socket and shutdown a server_context
263 */
264 void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
265 {
266         DEBUG(2,("server_terminate_connection\n"));
267         srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
268 }
269
270 void server_io_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags)
271 {
272         struct server_connection *conn = fde->private;
273
274         conn->event.idle->next_event = t + conn->event.idle_time;
275
276         if (flags & EVENT_FD_WRITE) {
277                 conn->service->ops->send_handler(conn, t, flags);
278                 return;
279         }
280
281         if (flags & EVENT_FD_READ) {
282                 conn->service->ops->recv_handler(conn, t, flags);
283         }
284
285 }
286
287 void server_idle_handler(struct event_context *ev, struct timed_event *idle, time_t t)
288 {
289         struct server_connection *conn = idle->private;
290
291         conn->event.idle->next_event = t + conn->event.idle_time;
292
293         conn->service->ops->idle_handler(conn,t);
294 }
295 /*
296   return the operations structure for a named backend of the specified type
297 */
298 const struct server_service_ops *server_service_byname(const char *name)
299 {
300         if (strcmp("smb",name)==0) {
301                 return smbsrv_get_ops();
302         }
303         if (strcmp("rpc",name)==0) {
304                 return dcesrv_get_ops();
305         }
306         if (strcmp("ldap",name)==0) {
307                 return ldapsrv_get_ops();
308         }
309         return NULL;
310 }
311
312 static NTSTATUS register_server_service_ops(const void *_ops)
313 {
314         return NT_STATUS_NOT_IMPLEMENTED;
315 }
316
317 /*
318   initialise the SERVER SERVICE subsystem
319 */
320 BOOL server_service_init(void)
321 {
322         NTSTATUS status;
323
324         status = register_subsystem("service", register_server_service_ops); 
325         if (!NT_STATUS_IS_OK(status)) {
326                 return False;
327         }
328
329         /* FIXME: Perhaps panic if a basic endpoint server, such as EPMAPER, fails to initialise? */
330         static_init_server_service;
331
332         DEBUG(3,("SERVER SERVICE subsystem version %d initialised\n", SERVER_SERVICE_VERSION));
333         return True;
334 }
335
336
337 /*
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
340 */
341 void service_close_listening_sockets(struct server_context *srv_ctx)
342 {
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);
350                         sock->socket = NULL;
351                 }
352         }
353 }
354
355
356 /*
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. 
362 */
363 void service_cleanup_tmp_files(void)
364 {
365         char *path;
366         DIR *dir;
367         struct dirent *de;
368         TALLOC_CTX *mem_ctx = talloc_init("service_cleanup_tmp_files");
369
370         path = smbd_tmp_path(mem_ctx, NULL);
371
372         dir = opendir(path);
373         if (!dir) {
374                 talloc_free(mem_ctx);
375                 return;
376         }
377
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);
381                 if (ret == -1 &&
382                     errno != ENOENT &&
383                     errno != EISDIR &&
384                     errno != EISDIR) {
385                         DEBUG(0,("Unabled to delete '%s' - %s\n", 
386                                  fname, strerror(errno)));
387                         smb_panic("unable to cleanup tmp files");
388                 }
389                 talloc_free(fname);
390         }
391         closedir(dir);
392
393         talloc_free(mem_ctx);
394 }