source: branches/samba-3.0/source/smbd/process.c@ 135

Last change on this file since 135 was 135, checked in by Paul Smedley, 18 years ago

Update source to 3.0.30

File size: 49.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "includes.h"
23
24uint16 global_smbpid;
25extern int keepalive;
26extern struct auth_context *negprot_global_auth_context;
27extern int smb_echo_count;
28
29static char *InBuffer = NULL;
30static char *OutBuffer = NULL;
31static char *current_inbuf = NULL;
32
33/*
34 * Size of data we can send to client. Set
35 * by the client for all protocols above CORE.
36 * Set by us for CORE protocol.
37 */
38int max_send = BUFFER_SIZE;
39/*
40 * Size of the data we can receive. Set by us.
41 * Can be modified by the max xmit parameter.
42 */
43int max_recv = BUFFER_SIZE;
44
45extern int last_message;
46extern int smb_read_error;
47SIG_ATOMIC_T reload_after_sighup = 0;
48SIG_ATOMIC_T got_sig_term = 0;
49extern BOOL global_machine_password_needs_changing;
50extern int max_send;
51
52/****************************************************************************
53 Function to return the current request mid from Inbuffer.
54****************************************************************************/
55
56uint16 get_current_mid(void)
57{
58 return SVAL(InBuffer,smb_mid);
59}
60
61/****************************************************************************
62 structure to hold a linked list of queued messages.
63 for processing.
64****************************************************************************/
65
66static struct pending_message_list *deferred_open_queue;
67
68/****************************************************************************
69 Function to push a message onto the tail of a linked list of smb messages ready
70 for processing.
71****************************************************************************/
72
73static BOOL push_queued_message(char *buf, int msg_len,
74 struct timeval request_time,
75 struct timeval end_time,
76 char *private_data, size_t private_len)
77{
78 struct pending_message_list *msg;
79
80 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
81
82 if(msg == NULL) {
83 DEBUG(0,("push_message: malloc fail (1)\n"));
84 return False;
85 }
86
87 msg->buf = data_blob_talloc(msg, buf, msg_len);
88 if(msg->buf.data == NULL) {
89 DEBUG(0,("push_message: malloc fail (2)\n"));
90 TALLOC_FREE(msg);
91 return False;
92 }
93
94 msg->request_time = request_time;
95 msg->end_time = end_time;
96
97 if (private_data) {
98 msg->private_data = data_blob_talloc(msg, private_data,
99 private_len);
100 if (msg->private_data.data == NULL) {
101 DEBUG(0,("push_message: malloc fail (3)\n"));
102 TALLOC_FREE(msg);
103 return False;
104 }
105 }
106
107 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
108
109 DEBUG(10,("push_message: pushed message length %u on "
110 "deferred_open_queue\n", (unsigned int)msg_len));
111
112 return True;
113}
114
115/****************************************************************************
116 Function to delete a sharing violation open message by mid.
117****************************************************************************/
118
119void remove_deferred_open_smb_message(uint16 mid)
120{
121 struct pending_message_list *pml;
122
123 for (pml = deferred_open_queue; pml; pml = pml->next) {
124 if (mid == SVAL(pml->buf.data,smb_mid)) {
125 DEBUG(10,("remove_sharing_violation_open_smb_message: "
126 "deleting mid %u len %u\n",
127 (unsigned int)mid,
128 (unsigned int)pml->buf.length ));
129 DLIST_REMOVE(deferred_open_queue, pml);
130 TALLOC_FREE(pml);
131 return;
132 }
133 }
134}
135
136/****************************************************************************
137 Move a sharing violation open retry message to the front of the list and
138 schedule it for immediate processing.
139****************************************************************************/
140
141void schedule_deferred_open_smb_message(uint16 mid)
142{
143 struct pending_message_list *pml;
144 int i = 0;
145
146 for (pml = deferred_open_queue; pml; pml = pml->next) {
147 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
148 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
149 (unsigned int)msg_mid ));
150 if (mid == msg_mid) {
151 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
152 mid ));
153 pml->end_time.tv_sec = 0;
154 pml->end_time.tv_usec = 0;
155 DLIST_PROMOTE(deferred_open_queue, pml);
156 return;
157 }
158 }
159
160 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
161 mid ));
162}
163
164/****************************************************************************
165 Return true if this mid is on the deferred queue.
166****************************************************************************/
167
168BOOL open_was_deferred(uint16 mid)
169{
170 struct pending_message_list *pml;
171
172 for (pml = deferred_open_queue; pml; pml = pml->next) {
173 if (SVAL(pml->buf.data,smb_mid) == mid) {
174 return True;
175 }
176 }
177 return False;
178}
179
180/****************************************************************************
181 Return the message queued by this mid.
182****************************************************************************/
183
184struct pending_message_list *get_open_deferred_message(uint16 mid)
185{
186 struct pending_message_list *pml;
187
188 for (pml = deferred_open_queue; pml; pml = pml->next) {
189 if (SVAL(pml->buf.data,smb_mid) == mid) {
190 return pml;
191 }
192 }
193 return NULL;
194}
195
196/****************************************************************************
197 Function to push a deferred open smb message onto a linked list of local smb
198 messages ready for processing.
199****************************************************************************/
200
201BOOL push_deferred_smb_message(uint16 mid,
202 struct timeval request_time,
203 struct timeval timeout,
204 char *private_data, size_t priv_len)
205{
206 struct timeval end_time;
207
208 end_time = timeval_sum(&request_time, &timeout);
209
210 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
211 "timeout time [%u.%06u]\n",
212 (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
213 (unsigned int)end_time.tv_sec,
214 (unsigned int)end_time.tv_usec));
215
216 return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
217 request_time, end_time,
218 private_data, priv_len);
219}
220
221struct idle_event {
222 struct timed_event *te;
223 struct timeval interval;
224 BOOL (*handler)(const struct timeval *now, void *private_data);
225 void *private_data;
226};
227
228static void idle_event_handler(struct event_context *ctx,
229 struct timed_event *te,
230 const struct timeval *now,
231 void *private_data)
232{
233 struct idle_event *event =
234 talloc_get_type_abort(private_data, struct idle_event);
235
236 TALLOC_FREE(event->te);
237
238 if (!event->handler(now, event->private_data)) {
239 /* Don't repeat, delete ourselves */
240 TALLOC_FREE(event);
241 return;
242 }
243
244 event->te = event_add_timed(smbd_event_context(), event,
245 timeval_sum(now, &event->interval),
246 "idle_event_handler",
247 idle_event_handler, event);
248
249 /* We can't do much but fail here. */
250 SMB_ASSERT(event->te != NULL);
251}
252
253struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
254 struct timeval interval,
255 BOOL (*handler)(const struct timeval *now,
256 void *private_data),
257 void *private_data)
258{
259 struct idle_event *result;
260 struct timeval now = timeval_current();
261
262 result = TALLOC_P(mem_ctx, struct idle_event);
263 if (result == NULL) {
264 DEBUG(0, ("talloc failed\n"));
265 return NULL;
266 }
267
268 result->interval = interval;
269 result->handler = handler;
270 result->private_data = private_data;
271
272 result->te = event_add_timed(smbd_event_context(), result,
273 timeval_sum(&now, &interval),
274 "idle_event_handler",
275 idle_event_handler, result);
276 if (result->te == NULL) {
277 DEBUG(0, ("event_add_timed failed\n"));
278 TALLOC_FREE(result);
279 return NULL;
280 }
281
282 return result;
283}
284
285/****************************************************************************
286 Do all async processing in here. This includes kernel oplock messages, change
287 notify events etc.
288****************************************************************************/
289
290static void async_processing(fd_set *pfds)
291{
292 DEBUG(10,("async_processing: Doing async processing.\n"));
293
294 process_aio_queue();
295
296 process_kernel_oplocks(pfds);
297
298 /* Do the aio check again after receive_local_message as it does a
299 select and may have eaten our signal. */
300 /* Is this till true? -- vl */
301 process_aio_queue();
302
303 if (got_sig_term) {
304 exit_server_cleanly("termination signal");
305 }
306
307 /* check for sighup processing */
308 if (reload_after_sighup) {
309 change_to_root_user();
310 DEBUG(1,("Reloading services after SIGHUP\n"));
311 reload_services(False);
312 reload_after_sighup = 0;
313 }
314}
315
316/****************************************************************************
317 Add a fd to the set we will be select(2)ing on.
318****************************************************************************/
319
320static int select_on_fd(int fd, int maxfd, fd_set *fds)
321{
322 if (fd != -1) {
323 FD_SET(fd, fds);
324 maxfd = MAX(maxfd, fd);
325 }
326
327 return maxfd;
328}
329
330/****************************************************************************
331 Do a select on an two fd's - with timeout.
332
333 If a local udp message has been pushed onto the
334 queue (this can only happen during oplock break
335 processing) call async_processing()
336
337 If a pending smb message has been pushed onto the
338 queue (this can only happen during oplock break
339 processing) return this next.
340
341 If the first smbfd is ready then read an smb from it.
342 if the second (loopback UDP) fd is ready then read a message
343 from it and setup the buffer header to identify the length
344 and from address.
345 Returns False on timeout or error.
346 Else returns True.
347
348The timeout is in milliseconds
349****************************************************************************/
350
351static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
352{
353 fd_set r_fds, w_fds;
354 int selrtn;
355 struct timeval to;
356 int maxfd = 0;
357
358 smb_read_error = 0;
359
360 again:
361
362 if (timeout >= 0) {
363 to.tv_sec = timeout / 1000;
364 to.tv_usec = (timeout % 1000) * 1000;
365 } else {
366 to.tv_sec = SMBD_SELECT_TIMEOUT;
367 to.tv_usec = 0;
368 }
369
370 /*
371 * Note that this call must be before processing any SMB
372 * messages as we need to synchronously process any messages
373 * we may have sent to ourselves from the previous SMB.
374 */
375 message_dispatch();
376