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.
26 #include "system/dir.h"
27 #include "dlinklist.h"
28 #include "process_model.h"
30 struct server_context *server_service_startup(const char *model, const char **server_services)
33 struct server_context *server;
35 if (!server_services) {
36 DEBUG(0,("server_service_startup: no endpoint servers configured\n"));
40 server = talloc_zero(NULL, struct server_context);
45 server->model.ops = process_model_startup(server, model);
46 if (!server->model.ops) {
47 DEBUG(0,("process_model_startup('%s') failed\n", model));
51 server->event.ctx = event_context_init(server);
52 if (!server->event.ctx) {
53 DEBUG(0,("event_context_init() failed\n"));
57 for (i=0;server_services[i];i++) {
58 const struct server_service_ops *service_ops;
59 struct server_service *service;
61 service_ops = server_service_byname(server_services[i]);
63 DEBUG(0,("process_model_startup: failed to find server service = '%s'\n", server_services[i]));
67 service = talloc_zero(server, struct server_service);
72 service->service.ops = service_ops;
73 service->server = server;
75 /* TODO: service_init() should return a result */
76 service->service.ops->service_init(service);
78 DLIST_ADD(server->service_list, service);
84 void server_service_shutdown(struct server_context *server, const char *reason)
86 server->model.ops->model_exit(server, reason);
90 setup a listen stream socket
91 if you pass *port == 0, then a port > 1024 is used
93 struct server_stream_socket *service_setup_stream_socket(struct server_service *service,
94 const struct server_stream_ops *stream_ops,
96 const char *sock_addr,
100 struct server_stream_socket *stream_socket;
101 struct socket_context *sock;
105 status = socket_create(family, SOCKET_TYPE_STREAM, &sock, 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 /* ready to listen */
113 status = socket_set_option(sock, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
114 if (!NT_STATUS_IS_OK(status)) {
115 DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n",
117 socket_destroy(sock);
120 status = socket_set_option(sock, lp_socket_options(), NULL);
121 if (!NT_STATUS_IS_OK(status)) {
122 DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n",
124 socket_destroy(sock);
128 /* TODO: set socket ACL's here when they're implemented */
131 for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
132 status = socket_listen(sock, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
133 if (NT_STATUS_IS_OK(status)) {
139 status = socket_listen(sock, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
142 if (!NT_STATUS_IS_OK(status)) {
143 DEBUG(0,("Failed to listen on %s:%u - %s\n",
144 sock_addr, *port, nt_errstr(status)));
145 socket_destroy(sock);
149 stream_socket = talloc_zero(service, struct server_stream_socket);
150 if (!stream_socket) {
151 DEBUG(0,("talloc_p(mem_ctx, struct server_stream_socket) failed\n"));
152 socket_destroy(sock);
156 /* we are only interested in read events on the listen socket */
157 fde.fd = socket_get_fd(sock);
158 fde.flags = EVENT_FD_READ;
159 fde.private = stream_socket;
160 fde.handler = server_accept_handler;
162 stream_socket->stream.ops = stream_ops;
163 stream_socket->service = service;
164 stream_socket->socket = sock;
165 stream_socket->event.ctx = service->server->event.ctx;
166 stream_socket->event.fde = event_add_fd(stream_socket->event.ctx, &fde);
167 if (!stream_socket->event.fde) {
168 DEBUG(0,("event_add_fd(stream_socket->event.ctx, &fde) failed\n"));
169 socket_destroy(sock);
173 talloc_steal(stream_socket, sock);
175 if (stream_socket->stream.ops->socket_init) {
176 stream_socket->stream.ops->socket_init(stream_socket);
179 return stream_socket;
183 destructor that handles necessary event context changes
185 static int server_connection_destructor(void *ptr)
187 struct server_connection *conn = ptr;
189 if (conn->stream_socket &&
190 conn->stream_socket->stream.ops->close_connection) {
191 /* don't remove this! the stream service needs to free it's data
192 * before we destroy the server_connection
194 conn->stream_socket->stream.ops->close_connection(conn, "shutdown");
197 if (conn->event.fde) {
198 event_remove_fd(conn->event.ctx, conn->event.fde);
199 conn->event.fde = NULL;
201 if (conn->event.idle) {
202 event_remove_timed(conn->event.ctx, conn->event.idle);
203 conn->event.idle = NULL;
209 struct server_connection *server_setup_connection(struct event_context *ev,
210 struct server_stream_socket *stream_socket,
211 struct socket_context *sock,
216 struct timed_event idle;
217 struct server_connection *srv_conn;
219 srv_conn = talloc_p(stream_socket, struct server_connection);
221 DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n"));
225 ZERO_STRUCTP(srv_conn);
227 fde.private = srv_conn;
228 fde.fd = socket_get_fd(sock);
229 fde.flags = EVENT_FD_READ;
230 fde.handler = server_io_handler;
232 idle.private = srv_conn;
233 idle.next_event = timeval_add(&t, SERVER_DEFAULT_IDLE_TIME, 0);
234 idle.handler = server_idle_handler;
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);
241 srv_conn->stream_socket = stream_socket;
242 srv_conn->socket = sock;
243 srv_conn->connection.id = server_id;
245 /* create a server context and add it to out event
247 stream_socket->stream.ops->accept_connection(srv_conn);
249 /* accpect_connection() of the service may changed idle.next_event */
250 srv_conn->event.fde = event_add_fd(ev,&fde);
251 srv_conn->event.idle = event_add_timed(ev,&idle);
253 talloc_set_destructor(srv_conn, server_connection_destructor);
255 if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
256 server_terminate_connection(srv_conn, "denied by access rules");
260 /* setup to receive internal messages on this connection */
261 srv_conn->messaging.ctx = messaging_init(srv_conn, srv_conn->connection.id, ev);
262 if (!srv_conn->messaging.ctx) {
263 server_terminate_connection(srv_conn, "messaging_init() failed");
271 close the socket and shutdown a server_context
273 void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
275 DEBUG(2,("server_terminate_connection\n"));
276 srv_conn->stream_socket->service->server->model.ops->terminate_connection(srv_conn, reason);
279 void server_accept_handler(struct event_context *ev, struct fd_event *fde,
280 struct timeval t, uint16_t flags)
282 struct server_stream_socket *stream_socket = fde->private;
284 stream_socket->service->server->model.ops->accept_connection(ev, fde, t, flags);
287 void server_io_handler(struct event_context *ev, struct fd_event *fde,
288 struct timeval t, uint16_t flags)
290 struct server_connection *conn = fde->private;
292 conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
294 if (flags & EVENT_FD_WRITE) {
295 conn->stream_socket->stream.ops->send_handler(conn, t, flags);
299 if (flags & EVENT_FD_READ) {
300 conn->stream_socket->stream.ops->recv_handler(conn, t, flags);
305 void server_idle_handler(struct event_context *ev, struct timed_event *idle,
308 struct server_connection *conn = idle->private;
310 /* Not all services provide an idle handler */
311 if (conn->stream_socket->stream.ops->idle_handler) {
312 conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
313 conn->stream_socket->stream.ops->idle_handler(conn, t);
317 void server_terminate_task(struct server_task *task, const char *reason)
319 task->service->server->model.ops->terminate_task(task, reason);
323 void server_run_task(struct server_service *service, const struct server_task_ops *ops)
325 struct server_task *task;
327 task = talloc_zero(service, struct server_task);
331 task->service = service;
332 task->task.ops = ops;
334 service->server->model.ops->create_task(task);
339 return the operations structure for a named backend of the specified type
341 const struct server_service_ops *server_service_byname(const char *name)
343 if (strcmp("smb",name)==0) {
344 return smbsrv_get_ops();
346 if (strcmp("rpc",name)==0) {
347 return dcesrv_get_ops();
349 if (strcmp("ldap",name)==0) {
350 return ldapsrv_get_ops();
355 NTSTATUS register_server_service_ops(const void *_ops)
357 return NT_STATUS_NOT_IMPLEMENTED;
361 cleanup temporary files. This is the new alternative to
362 TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
363 efficient on unix systems due to the lack of scaling of the byte
364 range locking system. So instead of putting the burden on tdb to
365 cleanup tmp files, this function deletes them.
367 void service_cleanup_tmp_files(void)
372 TALLOC_CTX *mem_ctx = talloc_init("service_cleanup_tmp_files");
374 path = smbd_tmp_path(mem_ctx, NULL);
378 talloc_free(mem_ctx);
382 for (de=readdir(dir);de;de=readdir(dir)) {
383 char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
384 int ret = unlink(fname);
389 DEBUG(0,("Unabled to delete '%s' - %s\n",
390 fname, strerror(errno)));
391 smb_panic("unable to cleanup tmp files");
397 talloc_free(mem_ctx);