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 struct server_context *server_service_startup(const char *model)
29 const char **server_services = lp_server_services();
30 struct server_context *srv_ctx;
31 const struct model_ops *model_ops;
33 if (!server_services) {
34 DEBUG(0,("process_model_startup: no endpoint servers configured\n"));
38 model_ops = process_model_startup(model);
40 DEBUG(0,("process_model_startup('%s') failed\n", model));
44 srv_ctx = talloc_p(NULL, struct server_context);
49 ZERO_STRUCTP(srv_ctx);
51 srv_ctx->events = event_context_init();
52 if (!srv_ctx->events) {
53 DEBUG(0,("event_context_init() failed\n"));
58 for (i=0;server_services[i];i++) {
59 const struct server_service_ops *service_ops;
60 struct server_service *service;
62 service_ops = server_service_byname(server_services[i]);
64 DEBUG(0,("process_model_startup: failed to find server service = '%s'\n", server_services[i]));
68 service = talloc_p(srv_ctx, struct server_service);
73 ZERO_STRUCTP(service);
74 service->ops = service_ops;
75 service->model_ops = model_ops;
76 service->srv_ctx = srv_ctx;
78 /* TODO: service_init() should return a result */
79 service->ops->service_init(service, model_ops);
86 setup a listen stream socket
87 if you pass *port == 0, then a port > 1024 is used
89 struct server_socket *service_setup_socket(struct server_service *service,
90 const struct model_ops *model_ops,
91 const char *sock_addr,
95 struct server_socket *srv_sock;
96 struct socket_context *socket_ctx;
100 status = socket_create("ipv4", SOCKET_TYPE_STREAM, &socket_ctx, 0);
101 if (!NT_STATUS_IS_OK(status)) {
102 DEBUG(0,("Failed to open socket on %s:%u - %s\n",
103 sock_addr, *port, nt_errstr(status)));
107 talloc_steal(service, socket_ctx);
109 /* ready to listen */
110 status = socket_set_option(socket_ctx, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
111 if (!NT_STATUS_IS_OK(status)) {
112 DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n",
114 socket_destroy(socket_ctx);
117 status = socket_set_option(socket_ctx, lp_socket_options(), NULL);
118 if (!NT_STATUS_IS_OK(status)) {
119 DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n",
121 socket_destroy(socket_ctx);
125 /* TODO: set socket ACL's here when they're implemented */
128 for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
129 status = socket_listen(socket_ctx, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
130 if (NT_STATUS_IS_OK(status)) {
136 status = socket_listen(socket_ctx, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
139 if (!NT_STATUS_IS_OK(status)) {
140 DEBUG(0,("Failed to listen on %s:%u - %s\n",
141 sock_addr, *port, nt_errstr(status)));
142 socket_destroy(socket_ctx);
146 srv_sock = talloc_p(service, struct server_socket);
148 DEBUG(0,("talloc_p(mem_ctx, struct server_socket) failed\n"));
149 socket_destroy(socket_ctx);
153 /* we are only interested in read events on the listen socket */
154 fde.fd = socket_get_fd(socket_ctx);
155 fde.flags = EVENT_FD_READ;
156 fde.private = srv_sock;
157 fde.handler = model_ops->accept_connection;
159 ZERO_STRUCTP(srv_sock);
160 srv_sock->service = service;
161 srv_sock->socket = socket_ctx;
162 srv_sock->event.ctx = service->srv_ctx->events;
163 srv_sock->event.fde = event_add_fd(srv_sock->event.ctx, &fde);
164 if (!srv_sock->event.fde) {
165 DEBUG(0,("event_add_fd(srv_sock->event.ctx, &fde) failed\n"));
166 socket_destroy(socket_ctx);
170 DLIST_ADD(service->socket_list, srv_sock);
176 destructor that handles necessary event context changes
178 static int server_destructor(void *ptr)
180 struct server_connection *conn = ptr;
183 conn->service->ops->close_connection(conn, "shutdown");
186 socket_destroy(conn->socket);
188 event_remove_fd(conn->event.ctx, conn->event.fde);
189 conn->event.fde = NULL;
190 event_remove_timed(conn->event.ctx, conn->event.idle);
191 conn->event.idle = NULL;
193 DLIST_REMOVE(conn->server_socket->connection_list, conn);
198 struct server_connection *server_setup_connection(struct event_context *ev,
199 struct server_socket *server_socket,
200 struct socket_context *sock,
204 struct timed_event idle;
205 struct server_connection *srv_conn;
207 srv_conn = talloc_p(server_socket, struct server_connection);
209 DEBUG(0,("talloc_p(mem_ctx, struct server_service_connection) failed\n"));
213 ZERO_STRUCTP(srv_conn);
215 fde.private = srv_conn;
216 fde.fd = socket_get_fd(sock);
217 fde.flags = EVENT_FD_READ;
218 fde.handler = server_io_handler;
220 idle.private = srv_conn;
221 idle.next_event = t + SERVER_DEFAULT_IDLE_TIME;
222 idle.handler = server_idle_handler;
224 srv_conn->event.ctx = ev;
225 srv_conn->event.fde = &fde;
226 srv_conn->event.idle = &idle;
227 srv_conn->event.idle_time = SERVER_DEFAULT_IDLE_TIME;
229 srv_conn->server_socket = server_socket;
230 srv_conn->service = server_socket->service;
231 srv_conn->socket = sock;
233 /* create a smb server context and add it to out event
235 server_socket->service->ops->accept_connection(srv_conn);
237 /* accpect_connection() of the service may changed idle.next_event */
238 srv_conn->event.fde = event_add_fd(ev,&fde);
239 srv_conn->event.idle = event_add_timed(ev,&idle);
241 talloc_set_destructor(srv_conn, server_destructor);
243 if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
244 server_terminate_connection(srv_conn, "denied by access rules");
252 close the socket and shutdown a server_context
254 void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
256 DEBUG(2,("server_terminate_connection\n"));
257 srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
260 void server_io_handler(struct event_context *ev, struct fd_event *fde, time_t t, uint16_t flags)
262 struct server_connection *conn = fde->private;
264 conn->event.idle->next_event = t + conn->event.idle_time;
266 if (flags & EVENT_FD_WRITE) {
267 conn->service->ops->send_handler(conn, t, flags);
271 if (flags & EVENT_FD_READ) {
272 conn->service->ops->recv_handler(conn, t, flags);
277 void server_idle_handler(struct event_context *ev, struct timed_event *idle, time_t t)
279 struct server_connection *conn = idle->private;
281 conn->event.idle->next_event = t + conn->event.idle_time;
283 conn->service->ops->idle_handler(conn,t);
286 return the operations structure for a named backend of the specified type
288 const struct server_service_ops *server_service_byname(const char *name)
290 if (strcmp("smb",name)==0) {
291 return smbsrv_get_ops();
293 if (strcmp("rpc",name)==0) {
294 return dcesrv_get_ops();
296 if (strcmp("ldap",name)==0) {
297 return ldapsrv_get_ops();
302 static NTSTATUS register_server_service_ops(const void *_ops)
304 return NT_STATUS_NOT_IMPLEMENTED;
308 initialise the SERVER SERVICE subsystem
310 BOOL server_service_init(void)
314 status = register_subsystem("service", register_server_service_ops);
315 if (!NT_STATUS_IS_OK(status)) {
319 /* FIXME: Perhaps panic if a basic endpoint server, such as EPMAPER, fails to initialise? */
320 static_init_server_service;
322 DEBUG(3,("SERVER SERVICE subsystem version %d initialised\n", SERVER_SERVICE_VERSION));