r6811: Another attempt at better kerberos/gssapi headers.
[samba.git] / source / smbd / process_standard.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    process model: standard (1 process per client connection)
5
6    Copyright (C) Andrew Tridgell 1992-2005
7    Copyright (C) James J Myers 2003 <myersjj@samba.org>
8    Copyright (C) Stefan (metze) Metzmacher 2004
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "lib/events/events.h"
27 #include "lib/tdb/include/tdb.h"
28 #include "dlinklist.h"
29 #include "smb_server/smb_server.h"
30 #include "system/filesys.h"
31
32 /*
33   called when the process model is selected
34 */
35 static void standard_model_init(struct event_context *ev)
36 {
37         signal(SIGCHLD, SIG_IGN);
38 }
39
40 /*
41   called when a listening socket becomes readable. 
42 */
43 static void standard_accept_connection(struct event_context *ev, 
44                                        struct socket_context *sock, 
45                                        void (*new_conn)(struct event_context *, struct socket_context *, 
46                                                         uint32_t , void *), 
47                                        void *private)
48 {
49         NTSTATUS status;
50         struct socket_context *sock2;
51         pid_t pid;
52         struct event_context *ev2;
53
54         /* accept an incoming connection. */
55         status = socket_accept(sock, &sock2);
56         if (!NT_STATUS_IS_OK(status)) {
57                 DEBUG(0,("standard_accept_connection: accept: %s\n",
58                          nt_errstr(status)));
59                 return;
60         }
61
62         pid = fork();
63
64         if (pid != 0) {
65                 /* parent or error code ... */
66                 talloc_free(sock2);
67                 /* go back to the event loop */
68                 return;
69         }
70
71         /* This is now the child code. We need a completely new event_context to work with */
72         ev2 = event_context_init(NULL);
73
74         /* the service has given us a private pointer that
75            encapsulates the context it needs for this new connection -
76            everything else will be freed */
77         talloc_steal(ev2, private);
78         talloc_steal(private, sock2);
79
80         /* this will free all the listening sockets and all state that
81            is not associated with this new connection */
82         talloc_free(sock);
83         talloc_free(ev);
84
85         /* we don't care if the dup fails, as its only a select()
86            speed optimisation */
87         socket_dup(sock2);
88                         
89         /* tdb needs special fork handling */
90         if (tdb_reopen_all() == -1) {
91                 DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n"));
92         }
93
94         /* Ensure that the forked children do not expose identical random streams */
95         set_need_random_reseed();
96
97         /* setup this new connection */
98         new_conn(ev2, sock2, getpid(), private);
99
100         /* we can't return to the top level here, as that event context is gone,
101            so we now process events in the new event context until there are no
102            more to process */      
103         event_loop_wait(ev2);
104
105         talloc_free(ev2);
106         exit(0);
107 }
108
109 /*
110   called to create a new server task
111 */
112 static void standard_new_task(struct event_context *ev, 
113                               void (*new_task)(struct event_context *, uint32_t , void *), 
114                               void *private)
115 {
116         pid_t pid;
117         struct event_context *ev2;
118
119         pid = fork();
120
121         if (pid != 0) {
122                 /* parent or error code ... go back to the event loop */
123                 return;
124         }
125
126         /* This is now the child code. We need a completely new event_context to work with */
127         ev2 = event_context_init(NULL);
128
129         /* the service has given us a private pointer that
130            encapsulates the context it needs for this new connection -
131            everything else will be freed */
132         talloc_steal(ev2, private);
133
134         /* this will free all the listening sockets and all state that
135            is not associated with this new connection */
136         talloc_free(ev);
137
138         /* tdb needs special fork handling */
139         if (tdb_reopen_all() == -1) {
140                 DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n"));
141         }
142
143         /* Ensure that the forked children do not expose identical random streams */
144         set_need_random_reseed();
145
146         /* setup this new connection */
147         new_task(ev2, getpid(), private);
148
149         /* we can't return to the top level here, as that event context is gone,
150            so we now process events in the new event context until there are no
151            more to process */      
152         event_loop_wait(ev2);
153
154         talloc_free(ev2);
155         exit(0);
156 }
157
158
159 /* called when a task goes down */
160 static void standard_terminate(struct event_context *ev, const char *reason) 
161 {
162         DEBUG(2,("standard_terminate: reason[%s]\n",reason));
163
164         /* this init_iconv() has the effect of freeing the iconv context memory,
165            which makes leak checking easier */
166         init_iconv();
167
168         /* the secrets db should really hang off the connection structure */
169         secrets_shutdown();
170
171         talloc_free(ev);
172
173         /* terminate this process */
174         exit(0);
175 }
176
177
178 static const struct model_ops standard_ops = {
179         .name                   = "standard",
180         .model_init             = standard_model_init,
181         .accept_connection      = standard_accept_connection,
182         .new_task               = standard_new_task,
183         .terminate              = standard_terminate,
184 };
185
186 /*
187   initialise the standard process model, registering ourselves with the process model subsystem
188  */
189 NTSTATUS process_model_standard_init(void)
190 {
191         return register_process_model(&standard_ops);
192 }