]> git.ipfire.org Git - thirdparty/samba.git/blame - source3/smbd/process.c
remove reference to removed code
[thirdparty/samba.git] / source3 / smbd / process.c
CommitLineData
c3effa8b 1/*
cd68afe3 2 Unix SMB/CIFS implementation.
c3effa8b
AT
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
b91704d4 5 Copyright (C) Volker Lendecke 2005-2007
c3effa8b
AT
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
d824b98f 9 the Free Software Foundation; either version 3 of the License, or
c3effa8b
AT
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
5e54558c 18 along with this program. If not, see <http://www.gnu.org/licenses/>.
c3effa8b
AT
19*/
20
21#include "includes.h"
22
978ca848
HL
23extern struct auth_context *negprot_global_auth_context;
24extern int smb_echo_count;
25
cc6a4101
VL
26const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
27
dd2e202e
AT
28/*
29 * Size of data we can send to client. Set
30 * by the client for all protocols above CORE.
31 * Set by us for CORE protocol.
32 */
33int max_send = BUFFER_SIZE;
34/*
35 * Size of the data we can receive. Set by us.
36 * Can be modified by the max xmit parameter.
37 */
38int max_recv = BUFFER_SIZE;
39
c3effa8b 40extern int last_message;
c3effa8b 41extern int smb_read_error;
a834a73e
GC
42SIG_ATOMIC_T reload_after_sighup = 0;
43SIG_ATOMIC_T got_sig_term = 0;
54abd2aa 44extern BOOL global_machine_password_needs_changing;
c3effa8b
AT
45extern int max_send;
46
0bc56a2e
VL
47/*
48 * Initialize a struct smb_request from an inbuf
49 */
50
51void init_smb_request(struct smb_request *req, const uint8 *inbuf)
52{
ed70bc0d
JA
53 size_t req_size = smb_len(inbuf) + 4;
54 /* Ensure we have at least smb_size bytes. */
a1f593cd
JA
55 if (req_size < smb_size) {
56 DEBUG(0,("init_smb_request: invalid request size %u\n",
57 (unsigned int)req_size ));
58 exit_server_cleanly("Invalid SMB request");
59 }
0bc56a2e
VL
60 req->flags2 = SVAL(inbuf, smb_flg2);
61 req->smbpid = SVAL(inbuf, smb_pid);
62 req->mid = SVAL(inbuf, smb_mid);
63 req->vuid = SVAL(inbuf, smb_uid);
cc6a4101
VL
64 req->tid = SVAL(inbuf, smb_tid);
65 req->wct = CVAL(inbuf, smb_wct);
a662a62e 66 /* Ensure we have at least wct words and 2 bytes of bcc. */
a1f593cd
JA
67 if (smb_size + req->wct*2 > req_size) {
68 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
69 (unsigned int)req->wct,
70 (unsigned int)req_size));
71 exit_server_cleanly("Invalid SMB request");
72 }
a662a62e
JA
73 /* Ensure bcc is correct. */
74 if (((uint8 *)smb_buf(inbuf)) + smb_buflen(inbuf) > inbuf + req_size) {
75 DEBUG(0,("init_smb_request: invalid bcc number %u "
76 "(wct = %u, size %u)\n",
77 (unsigned int)smb_buflen(inbuf),
78 (unsigned int)req->wct,
79 (unsigned int)req_size));
80 exit_server_cleanly("Invalid SMB request");
81 }
cc6a4101
VL
82 req->inbuf = inbuf;
83 req->outbuf = NULL;
0bc56a2e
VL
84}
85
aab2fe02
JA
86/****************************************************************************
87 structure to hold a linked list of queued messages.
88 for processing.
89****************************************************************************/
90
54abd2aa 91static struct pending_message_list *deferred_open_queue;
aab2fe02
JA
92
93/****************************************************************************
e5a95132
GJC
94 Function to push a message onto the tail of a linked list of smb messages ready
95 for processing.
aab2fe02
JA
96****************************************************************************/
97
b578db69 98static BOOL push_queued_message(struct smb_request *req,
54abd2aa
GC
99 struct timeval request_time,
100 struct timeval end_time,
101 char *private_data, size_t private_len)
aab2fe02 102{
b578db69 103 int msg_len = smb_len(req->inbuf) + 4;
54abd2aa
GC
104 struct pending_message_list *msg;
105
106 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
aab2fe02 107
1eff0523
JA
108 if(msg == NULL) {
109 DEBUG(0,("push_message: malloc fail (1)\n"));
110 return False;
111 }
aab2fe02 112
b578db69 113 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
2fc57c9a 114 if(msg->buf.data == NULL) {
1eff0523 115 DEBUG(0,("push_message: malloc fail (2)\n"));
fb5362c0 116 TALLOC_FREE(msg);
1eff0523
JA
117 return False;
118 }
aab2fe02 119
54abd2aa
GC
120 msg->request_time = request_time;
121 msg->end_time = end_time;
2fc57c9a 122
19ca97a7 123 if (private_data) {
54abd2aa
GC
124 msg->private_data = data_blob_talloc(msg, private_data,
125 private_len);
2fc57c9a
JA
126 if (msg->private_data.data == NULL) {
127 DEBUG(0,("push_message: malloc fail (3)\n"));
fb5362c0 128 TALLOC_FREE(msg);
b6fb0462 129 return False;
2fc57c9a
JA
130 }
131 }
aab2fe02 132
258a465e 133 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
aab2fe02 134
54abd2aa
GC
135 DEBUG(10,("push_message: pushed message length %u on "
136 "deferred_open_queue\n", (unsigned int)msg_len));
2fc57c9a 137
1eff0523 138 return True;
aab2fe02
JA
139}
140
2fc57c9a
JA
141/****************************************************************************
142 Function to delete a sharing violation open message by mid.
143****************************************************************************/
144
54abd2aa 145void remove_deferred_open_smb_message(uint16 mid)
2fc57c9a
JA
146{
147 struct pending_message_list *pml;
148
54abd2aa 149 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a 150 if (mid == SVAL(pml->buf.data,smb_mid)) {
e5a95132 151 DEBUG(10,("remove_sharing_violation_open_smb_message: "
54abd2aa
GC
152 "deleting mid %u len %u\n",
153 (unsigned int)mid,
154 (unsigned int)pml->buf.length ));
155 DLIST_REMOVE(deferred_open_queue, pml);
fb5362c0 156 TALLOC_FREE(pml);
2fc57c9a
JA
157 return;
158 }
159 }
160}
161
162/****************************************************************************
163 Move a sharing violation open retry message to the front of the list and
164 schedule it for immediate processing.
165****************************************************************************/
166
54abd2aa 167void schedule_deferred_open_smb_message(uint16 mid)
2fc57c9a
JA
168{
169 struct pending_message_list *pml;
170 int i = 0;
171
54abd2aa 172 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a 173 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
e5a95132
GJC
174 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
175 (unsigned int)msg_mid ));
2fc57c9a 176 if (mid == msg_mid) {
e5a95132
GJC
177 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
178 mid ));
54abd2aa
GC
179 pml->end_time.tv_sec = 0;
180 pml->end_time.tv_usec = 0;
181 DLIST_PROMOTE(deferred_open_queue, pml);
2fc57c9a
JA
182 return;
183 }
184 }
185
e5a95132
GJC
186 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
187 mid ));
2fc57c9a
JA
188}
189
190/****************************************************************************
191 Return true if this mid is on the deferred queue.
192****************************************************************************/
193
194BOOL open_was_deferred(uint16 mid)
195{
196 struct pending_message_list *pml;
3e0f5862 197
54abd2aa 198 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a
JA
199 if (SVAL(pml->buf.data,smb_mid) == mid) {
200 return True;
201 }
202 }
203 return False;
204}
205
206/****************************************************************************
207 Return the message queued by this mid.
208****************************************************************************/
209
210struct pending_message_list *get_open_deferred_message(uint16 mid)
211{
212 struct pending_message_list *pml;
3e0f5862 213
54abd2aa 214 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a
JA
215 if (SVAL(pml->buf.data,smb_mid) == mid) {
216 return pml;
217 }
218 }
219 return NULL;
220}
221
222/****************************************************************************
54abd2aa
GC
223 Function to push a deferred open smb message onto a linked list of local smb
224 messages ready for processing.
225****************************************************************************/
226
b578db69 227BOOL push_deferred_smb_message(struct smb_request *req,
54abd2aa
GC
228 struct timeval request_time,
229 struct timeval timeout,
230 char *private_data, size_t priv_len)
231{
232 struct timeval end_time;
233
234 end_time = timeval_sum(&request_time, &timeout);
235
236 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
237 "timeout time [%u.%06u]\n",
b578db69 238 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
54abd2aa
GC
239 (unsigned int)end_time.tv_sec,
240 (unsigned int)end_time.tv_usec));
241
b578db69 242 return push_queued_message(req, request_time, end_time,
54abd2aa
GC
243 private_data, priv_len);
244}
245
54abd2aa
GC
246struct idle_event {
247 struct timed_event *te;
248 struct timeval interval;
7c2bc9c0 249 char *name;
54abd2aa
GC
250 BOOL (*handler)(const struct timeval *now, void *private_data);
251 void *private_data;
252};
253
bf219447
VL
254static void idle_event_handler(struct event_context *ctx,
255 struct timed_event *te,
54abd2aa
GC
256 const struct timeval *now,
257 void *private_data)
258{
259 struct idle_event *event =
260 talloc_get_type_abort(private_data, struct idle_event);
261
fb5362c0 262 TALLOC_FREE(event->te);
54abd2aa
GC
263
264 if (!event->handler(now, event->private_data)) {
265 /* Don't repeat, delete ourselves */
fb5362c0 266 TALLOC_FREE(event);
54abd2aa
GC
267 return;
268 }
269
7c2bc9c0 270 event->te = event_add_timed(ctx, event,
bf219447 271 timeval_sum(now, &event->interval),
7c2bc9c0 272 event->name,
54abd2aa
GC
273 idle_event_handler, event);
274
275 /* We can't do much but fail here. */
276 SMB_ASSERT(event->te != NULL);
277}
278
7c2bc9c0
VL
279struct idle_event *event_add_idle(struct event_context *event_ctx,
280 TALLOC_CTX *mem_ctx,
54abd2aa 281 struct timeval interval,
7c2bc9c0 282 const char *name,
54abd2aa
GC
283 BOOL (*handler)(const struct timeval *now,
284 void *private_data),
285 void *private_data)
286{
287 struct idle_event *result;
288 struct timeval now = timeval_current();
289
290 result = TALLOC_P(mem_ctx, struct idle_event);
291 if (result == NULL) {
292 DEBUG(0, ("talloc failed\n"));
293 return NULL;
294 }
295
296 result->interval = interval;
297 result->handler = handler;
298 result->private_data = private_data;
299
7c2bc9c0
VL
300 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
301 DEBUG(0, ("talloc failed\n"));
302 TALLOC_FREE(result);
303 return NULL;
304 }
305
306 result->te = event_add_timed(event_ctx, result,
bf219447 307 timeval_sum(&now, &interval),
7c2bc9c0 308 result->name,
54abd2aa
GC
309 idle_event_handler, result);
310 if (result->te == NULL) {
bf219447 311 DEBUG(0, ("event_add_timed failed\n"));
fb5362c0 312 TALLOC_FREE(result);
54abd2aa
GC
313 return NULL;
314 }
315
316 return result;
317}
8fbdd112 318
b2d01bd2 319/****************************************************************************
54abd2aa
GC
320 Do all async processing in here. This includes kernel oplock messages, change
321 notify events etc.
b2d01bd2 322****************************************************************************/
840279f3 323
5c149702 324static void async_processing(fd_set *pfds)
b2d01bd2 325{
e90b6528
AT
326 DEBUG(10,("async_processing: Doing async processing.\n"));
327
f2f55d70
JA
328 process_aio_queue();
329
fad7dd8a 330 process_kernel_oplocks(smbd_messaging_context(), pfds);
b2d01bd2 331
54abd2aa
GC
332 /* Do the aio check again after receive_local_message as it does a
333 select and may have eaten our signal. */
334 /* Is this till true? -- vl */
f2f55d70
JA
335 process_aio_queue();
336
840279f3 337 if (got_sig_term) {
eecdc6c9 338 exit_server_cleanly("termination signal");
840279f3
JA
339 }
340
b2d01bd2
AT
341 /* check for sighup processing */
342 if (reload_after_sighup) {
c416ff85 343 change_to_root_user();
b2d01bd2
AT
344 DEBUG(1,("Reloading services after SIGHUP\n"));
345 reload_services(False);
840279f3 346 reload_after_sighup = 0;
b2d01bd2 347 }
aab2fe02
JA
348}
349
8fbdd112
JP
350/****************************************************************************
351 Add a fd to the set we will be select(2)ing on.
352****************************************************************************/
353
354static int select_on_fd(int fd, int maxfd, fd_set *fds)
355{
356 if (fd != -1) {
357 FD_SET(fd, fds);
358 maxfd = MAX(maxfd, fd);
359 }
360
361 return maxfd;
362}
363
aab2fe02
JA
364/****************************************************************************
365 Do a select on an two fd's - with timeout.
366
367 If a local udp message has been pushed onto the
368 queue (this can only happen during oplock break
b2d01bd2 369 processing) call async_processing()
aab2fe02
JA
370
371 If a pending smb message has been pushed onto the
372 queue (this can only happen during oplock break
373 processing) return this next.
374
375 If the first smbfd is ready then read an smb from it.
376 if the second (loopback UDP) fd is ready then read a message
377 from it and setup the buffer header to identify the length
378 and from address.
379 Returns False on timeout or error.
380 Else returns True.
381
127e77e6 382The timeout is in milliseconds
aab2fe02
JA
383****************************************************************************/
384
cc6a4101
VL
385static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
386 size_t *buffer_len, int timeout)
aab2fe02 387{
bf219447 388 fd_set r_fds, w_fds;
8843a637 389 int selrtn;
cc203f3e 390 struct timeval to;
8fbdd112 391 int maxfd = 0;
cc6a4101 392 ssize_t len;
aab2fe02 393
8843a637 394 smb_read_error = 0;
aab2fe02 395
2bd3a436
JA
396 again:
397
54abd2aa
GC
398 if (timeout >= 0) {
399 to.tv_sec = timeout / 1000;
400 to.tv_usec = (timeout % 1000) * 1000;
cc203f3e
JA
401 } else {
402 to.tv_sec = SMBD_SELECT_TIMEOUT;
403 to.tv_usec = 0;
54abd2aa 404 }
2fc57c9a 405
2bd3a436
JA
406 /*
407 * Note that this call must be before processing any SMB
408 * messages as we need to synchronously process any messages
409 * we may have sent to ourselves from the previous SMB.
410 */
ac3f08dd 411 message_dispatch(smbd_messaging_context());
2bd3a436 412
2fc57c9a
JA
413 /*
414 * Check to see if we already have a message on the deferred open queue
415 * and it's time to schedule.
416 */
54abd2aa 417 if(deferred_open_queue != NULL) {
2fc57c9a 418 BOOL pop_message = False;
54abd2aa 419 struct pending_message_list *msg = deferred_open_queue;
2fc57c9a 420
54abd2aa 421 if (timeval_is_zero(&msg->end_time)) {
2fc57c9a
JA
422 pop_message = True;
423 } else {
424 struct timeval tv;
425 SMB_BIG_INT tdif;
426
427 GetTimeOfDay(&tv);
54abd2aa 428 tdif = usec_time_diff(&msg->end_time, &tv);
2fc57c9a
JA
429 if (tdif <= 0) {
430 /* Timed out. Schedule...*/
431 pop_message = True;
432 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
433 } else {
434 /* Make a more accurate select timeout. */
435 to.tv_sec = tdif / 1000000;
436 to.tv_usec = tdif % 1000000;
2fc57c9a 437 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
54abd2aa 438 (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
2fc57c9a
JA
439 }
440 }
441
442 if (pop_message) {
cc6a4101
VL
443
444 *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data,
445 msg->buf.length);
446 if (*buffer == NULL) {
447 DEBUG(0, ("talloc failed\n"));
448 smb_read_error = READ_ERROR;
449 return False;
450 }
451 *buffer_len = msg->buf.length;
452
2fc57c9a
JA
453 /* We leave this message on the queue so the open code can
454 know this is a retry. */
455 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
456 return True;
457 }
458 }
b2d01bd2 459
8843a637 460 /*
bf219447 461 * Setup the select fd sets.
8843a637
AT
462 */
463
bf219447
VL
464 FD_ZERO(&r_fds);
465 FD_ZERO(&w_fds);
e90b6528
AT
466
467 /*
468 * Ensure we process oplock break messages by preference.
469 * We have to do this before the select, after the select
470 * and if the select returns EINTR. This is due to the fact
471 * that the selects called from async_processing can eat an EINTR
472 * caused by a signal (we can't take the break message there).
473 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
474 */
475
bf219447 476 if (oplock_message_waiting(&r_fds)) {
e90b6528 477 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
bf219447 478 async_processing(&r_fds);
e90b6528
AT
479 /*
480 * After async processing we must go and do the select again, as
481 * the state of the flag in fds for the server file descriptor is
482 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
483 */
484 goto again;
485 }
54abd2aa 486
cc203f3e
JA
487 /*
488 * Are there any timed events waiting ? If so, ensure we don't
489 * select for longer than it would take to wait for them.
490 */
491
54abd2aa 492 {
bf219447
VL
493 struct timeval now;
494 GetTimeOfDay(&now);
495
496 event_add_to_select_args(smbd_event_context(), &now,
497 &r_fds, &w_fds, &to, &maxfd);
498 }
499
500 if (timeval_is_zero(&to)) {
501 /* Process a timed event now... */
502 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
503 goto again;
54abd2aa
GC
504 }
505 }
e90b6528 506
fbdcf266
JA
507 {
508 int sav;
509 START_PROFILE(smbd_idle);
510
bf219447 511 maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
bf219447 512 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
8843a637 513
bf219447 514 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
fbdcf266
JA
515 sav = errno;
516
517 END_PROFILE(smbd_idle);
518 errno = sav;
519 }
8843a637 520
bf219447
VL
521 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
522 goto again;
523 }
524
8843a637 525 /* if we get EINTR then maybe we have received an oplock
b2d01bd2
AT
526 signal - treat this as select returning 1. This is ugly, but
527 is the best we can do until the oplock code knows more about
528 signals */
8843a637 529 if (selrtn == -1 && errno == EINTR) {
bf219447 530 async_processing(&r_fds);
45706091
JA
531 /*
532 * After async processing we must go and do the select again, as
533 * the state of the flag in fds for the server file descriptor is
534 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
535 */
b2d01bd2 536 goto again;
8843a637
AT
537 }
538
539 /* Check if error */
b2d01bd2 540 if (selrtn == -1) {
8843a637
AT
541 /* something is wrong. Maybe the socket is dead? */
542 smb_read_error = READ_ERROR;
543 return False;
544 }
aab2fe02 545
8843a637
AT
546 /* Did we timeout ? */
547 if (selrtn == 0) {
548 smb_read_error = READ_TIMEOUT;
549 return False;
550 }
b2d01bd2 551
11f0402a
JA
552 /*
553 * Ensure we process oplock break messages by preference.
554 * This is IMPORTANT ! Otherwise we can starve other processes
555 * sending us an oplock break message. JRA.
556 */
557
bf219447
VL
558 if (oplock_message_waiting(&r_fds)) {
559 async_processing(&r_fds);
45706091
JA
560 /*
561 * After async processing we must go and do the select again, as
562 * the state of the flag in fds for the server file descriptor is
563 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
564 */
565 goto again;
8843a637 566 }
7a915ec3 567
cc6a4101
VL
568 len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0);
569
570 if (len == -1) {
571 return False;
572 }
573
574 *buffer_len = (size_t)len;
575
576 return True;
aab2fe02 577}
c3effa8b 578
22dbd677
JA
579/*
580 * Only allow 5 outstanding trans requests. We're allocating memory, so
581 * prevent a DoS.
582 */
aab2fe02 583
22dbd677 584NTSTATUS allow_new_trans(struct trans_state *list, int mid)
c3effa8b 585{
22dbd677
JA
586 int count = 0;
587 for (; list != NULL; list = list->next) {
c3effa8b 588
22dbd677
JA
589 if (list->mid == mid) {
590 return NT_STATUS_INVALID_PARAMETER;
591 }
592
593 count += 1;
594 }
595 if (count > 5) {
596 return NT_STATUS_INSUFFICIENT_RESOURCES;
597 }
c3effa8b 598
22dbd677 599 return NT_STATUS_OK;
c3effa8b
AT
600}
601
3db52feb
AT
602/****************************************************************************
603 We're terminating and have closed all our files/connections etc.
604 If there are any pending local messages we need to respond to them
605 before termination so that other smbds don't think we just died whilst
606 holding oplocks.
607****************************************************************************/
608
609void respond_to_all_remaining_local_messages(void)
610{
1eff0523
JA
611 /*
612 * Assert we have no exclusive open oplocks.
613 */
614
615 if(get_number_of_exclusive_open_oplocks()) {
616 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
617 get_number_of_exclusive_open_oplocks() ));
618 return;
619 }
620
fad7dd8a 621 process_kernel_oplocks(smbd_messaging_context(), NULL);
1eff0523
JA
622
623 return;
3db52feb
AT
624}
625
c3effa8b 626
c3effa8b
AT
627/*
628These flags determine some of the permissions required to do an operation
629
630Note that I don't set NEED_WRITE on some write operations because they
631are used by some brain-dead clients when printing, and I don't want to
632force write permissions on print services.
633*/
634#define AS_USER (1<<0)
ce61fb21 635#define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
c3effa8b 636#define TIME_INIT (1<<2)
ce61fb21
JA
637#define CAN_IPC (1<<3) /* Must be paired with AS_USER */
638#define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
54abd2aa 639#define DO_CHDIR (1<<6)
c3effa8b
AT
640
641/*
642 define a list of possible SMB messages and their corresponding
643 functions. Any message that has a NULL function is unimplemented -
644 please feel free to contribute implementations!
645*/
1eff0523
JA
646static const struct smb_message_struct {
647 const char *name;
cc6a4101 648 void (*fn_new)(connection_struct *conn, struct smb_request *req);
1eff0523
JA
649 int flags;
650} smb_messages[256] = {
918c3ebe 651
b578db69
VL
652/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
653/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
654/* 0x02 */ { "SMBopen",reply_open,AS_USER },
655/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
656/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
657/* 0x05 */ { "SMBflush",reply_flush,AS_USER},
658/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
659/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
660/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
661/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
662/* 0x0a */ { "SMBread",reply_read,AS_USER},
663/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
664/* 0x0c */ { "SMBlock",reply_lock,AS_USER},
665/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
666/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
667/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
668/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
669/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
670/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
671/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
672/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
673/* 0x15 */ { NULL, NULL, 0 },
674/* 0x16 */ { NULL, NULL, 0 },
675/* 0x17 */ { NULL, NULL, 0 },
676/* 0x18 */ { NULL, NULL, 0 },
677/* 0x19 */ { NULL, NULL, 0 },
678/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
679/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
680/* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
681/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
682/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
683/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
684/* 0x20 */ { "SMBwritec", NULL,0},
685/* 0x21 */ { NULL, NULL, 0 },
686/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
687/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
688/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
689/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
690/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
691/* 0x27 */ { "SMBioctl",reply_ioctl,0},
692/* 0x28 */ { "SMBioctls", NULL,AS_USER},
693/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
694/* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
695/* 0x2b */ { "SMBecho",reply_echo,0},
696/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
697/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
698/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
699/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
700/* 0x30 */ { NULL, NULL, 0 },
701/* 0x31 */ { NULL, NULL, 0 },
702/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
703/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
704/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
705/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
706/* 0x36 */ { NULL, NULL, 0 },
707/* 0x37 */ { NULL, NULL, 0 },
708/* 0x38 */ { NULL, NULL, 0 },
709/* 0x39 */ { NULL, NULL, 0 },
710/* 0x3a */ { NULL, NULL, 0 },
711/* 0x3b */ { NULL, NULL, 0 },
712/* 0x3c */ { NULL, NULL, 0 },
713/* 0x3d */ { NULL, NULL, 0 },
714/* 0x3e */ { NULL, NULL, 0 },
715/* 0x3f */ { NULL, NULL, 0 },
716/* 0x40 */ { NULL, NULL, 0 },
717/* 0x41 */ { NULL, NULL, 0 },
718/* 0x42 */ { NULL, NULL, 0 },
719/* 0x43 */ { NULL, NULL, 0 },
720/* 0x44 */ { NULL, NULL, 0 },
721/* 0x45 */ { NULL, NULL, 0 },
722/* 0x46 */ { NULL, NULL, 0 },
723/* 0x47 */ { NULL, NULL, 0 },
724/* 0x48 */ { NULL, NULL, 0 },
725/* 0x49 */ { NULL, NULL, 0 },
726/* 0x4a */ { NULL, NULL, 0 },
727/* 0x4b */ { NULL, NULL, 0 },
728/* 0x4c */ { NULL, NULL, 0 },
729/* 0x4d */ { NULL, NULL, 0 },
730/* 0x4e */ { NULL, NULL, 0 },
731/* 0x4f */ { NULL, NULL, 0 },
732/* 0x50 */ { NULL, NULL, 0 },
733/* 0x51 */ { NULL, NULL, 0 },
734/* 0x52 */ { NULL, NULL, 0 },
735/* 0x53 */ { NULL, NULL, 0 },
736/* 0x54 */ { NULL, NULL, 0 },
737/* 0x55 */ { NULL, NULL, 0 },
738/* 0x56 */ { NULL, NULL, 0 },
739/* 0x57 */ { NULL, NULL, 0 },
740/* 0x58 */ { NULL, NULL, 0 },
741/* 0x59 */ { NULL, NULL, 0 },
742/* 0x5a */ { NULL, NULL, 0 },
743/* 0x5b */ { NULL, NULL, 0 },
744/* 0x5c */ { NULL, NULL, 0 },
745/* 0x5d */ { NULL, NULL, 0 },
746/* 0x5e */ { NULL, NULL, 0 },
747/* 0x5f */ { NULL, NULL, 0 },
748/* 0x60 */ { NULL, NULL, 0 },
749/* 0x61 */ { NULL, NULL, 0 },
750/* 0x62 */ { NULL, NULL, 0 },
751/* 0x63 */ { NULL, NULL, 0 },
752/* 0x64 */ { NULL, NULL, 0 },
753/* 0x65 */ { NULL, NULL, 0 },
754/* 0x66 */ { NULL, NULL, 0 },
755/* 0x67 */ { NULL, NULL, 0 },
756/* 0x68 */ { NULL, NULL, 0 },
757/* 0x69 */ { NULL, NULL, 0 },
758/* 0x6a */ { NULL, NULL, 0 },
759/* 0x6b */ { NULL, NULL, 0 },
760/* 0x6c */ { NULL, NULL, 0 },
761/* 0x6d */ { NULL, NULL, 0 },
762/* 0x6e */ { NULL, NULL, 0 },
763/* 0x6f */ { NULL, NULL, 0 },
764/* 0x70 */ { "SMBtcon",reply_tcon,0},
765/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
766/* 0x72 */ { "SMBnegprot",reply_negprot,0},
767/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
768/* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
769/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
770/* 0x76 */ { NULL, NULL, 0 },
771/* 0x77 */ { NULL, NULL, 0 },
772/* 0x78 */ { NULL, NULL, 0 },
773/* 0x79 */ { NULL, NULL, 0 },
774/* 0x7a */ { NULL, NULL, 0 },
775/* 0x7b */ { NULL, NULL, 0 },
776/* 0x7c */ { NULL, NULL, 0 },
777/* 0x7d */ { NULL, NULL, 0 },
778/* 0x7e */ { NULL, NULL, 0 },
779/* 0x7f */ { NULL, NULL, 0 },
780/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
781/* 0x81 */ { "SMBsearch",reply_search,AS_USER},
782/* 0x82 */ { "SMBffirst",reply_search,AS_USER},
783/* 0x83 */ { "SMBfunique",reply_search,AS_USER},
784/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
785/* 0x85 */ { NULL, NULL, 0 },
786/* 0x86 */ { NULL, NULL, 0 },
787/* 0x87 */ { NULL, NULL, 0 },
788/* 0x88 */ { NULL, NULL, 0 },
789/* 0x89 */ { NULL, NULL, 0 },
790/* 0x8a */ { NULL, NULL, 0 },
791/* 0x8b */ { NULL, NULL, 0 },
792/* 0x8c */ { NULL, NULL, 0 },
793/* 0x8d */ { NULL, NULL, 0 },
794/* 0x8e */ { NULL, NULL, 0 },
795/* 0x8f */ { NULL, NULL, 0 },
796/* 0x90 */ { NULL, NULL, 0 },
797/* 0x91 */ { NULL, NULL, 0 },
798/* 0x92 */ { NULL, NULL, 0 },
799/* 0x93 */ { NULL, NULL, 0 },
800/* 0x94 */ { NULL, NULL, 0 },
801/* 0x95 */ { NULL, NULL, 0 },
802/* 0x96 */ { NULL, NULL, 0 },
803/* 0x97 */ { NULL, NULL, 0 },
804/* 0x98 */ { NULL, NULL, 0 },
805/* 0x99 */ { NULL, NULL, 0 },
806/* 0x9a */ { NULL, NULL, 0 },
807/* 0x9b */ { NULL, NULL, 0 },
808/* 0x9c */ { NULL, NULL, 0 },
809/* 0x9d */ { NULL, NULL, 0 },
810/* 0x9e */ { NULL, NULL, 0 },
811/* 0x9f */ { NULL, NULL, 0 },
812/* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
813/* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
814/* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
815/* 0xa3 */ { NULL, NULL, 0 },
816/* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
817/* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
818/* 0xa6 */ { NULL, NULL, 0 },
819/* 0xa7 */ { NULL, NULL, 0 },
820/* 0xa8 */ { NULL, NULL, 0 },
821/* 0xa9 */ { NULL, NULL, 0 },
822/* 0xaa */ { NULL, NULL, 0 },
823/* 0xab */ { NULL, NULL, 0 },
824/* 0xac */ { NULL, NULL, 0 },
825/* 0xad */ { NULL, NULL, 0 },
826/* 0xae */ { NULL, NULL, 0 },
827/* 0xaf */ { NULL, NULL, 0 },
828/* 0xb0 */ { NULL, NULL, 0 },
829/* 0xb1 */ { NULL, NULL, 0 },
830/* 0xb2 */ { NULL, NULL, 0 },
831/* 0xb3 */ { NULL, NULL, 0 },
832/* 0xb4 */ { NULL, NULL, 0 },
833/* 0xb5 */ { NULL, NULL, 0 },
834/* 0xb6 */ { NULL, NULL, 0 },
835/* 0xb7 */ { NULL, NULL, 0 },
836/* 0xb8 */ { NULL, NULL, 0 },
837/* 0xb9 */ { NULL, NULL, 0 },
838/* 0xba */ { NULL, NULL, 0 },
839/* 0xbb */ { NULL, NULL, 0 },
840/* 0xbc */ { NULL, NULL, 0 },
841/* 0xbd */ { NULL, NULL, 0 },
842/* 0xbe */ { NULL, NULL, 0 },
843/* 0xbf */ { NULL, NULL, 0 },
844/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
845/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
846/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
847/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
848/* 0xc4 */ { NULL, NULL, 0 },
849/* 0xc5 */ { NULL, NULL, 0 },
850/* 0xc6 */ { NULL, NULL, 0 },
851/* 0xc7 */ { NULL, NULL, 0 },
852/* 0xc8 */ { NULL, NULL, 0 },
853/* 0xc9 */ { NULL, NULL, 0 },
854/* 0xca */ { NULL, NULL, 0 },
855/* 0xcb */ { NULL, NULL, 0 },
856/* 0xcc */ { NULL, NULL, 0 },
857/* 0xcd */ { NULL, NULL, 0 },
858/* 0xce */ { NULL, NULL, 0 },
859/* 0xcf */ { NULL, NULL, 0 },
860/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
861/* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
862/* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
863/* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
864/* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
865/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
866/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
867/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
868/* 0xd8 */ { NULL, NULL, 0 },
869/* 0xd9 */ { NULL, NULL, 0 },
870/* 0xda */ { NULL, NULL, 0 },
871/* 0xdb */ { NULL, NULL, 0 },
872/* 0xdc */ { NULL, NULL, 0 },
873/* 0xdd */ { NULL, NULL, 0 },
874/* 0xde */ { NULL, NULL, 0 },
875/* 0xdf */ { NULL, NULL, 0 },
876/* 0xe0 */ { NULL, NULL, 0 },
877/* 0xe1 */ { NULL, NULL, 0 },
878/* 0xe2 */ { NULL, NULL, 0 },
879/* 0xe3 */ { NULL, NULL, 0 },
880/* 0xe4 */ { NULL, NULL, 0 },
881/* 0xe5 */ { NULL, NULL, 0 },
882/* 0xe6 */ { NULL, NULL, 0 },
883/* 0xe7 */ { NULL, NULL, 0 },
884/* 0xe8 */ { NULL, NULL, 0 },
885/* 0xe9 */ { NULL, NULL, 0 },
886/* 0xea */ { NULL, NULL, 0 },
887/* 0xeb */ { NULL, NULL, 0 },
888/* 0xec */ { NULL, NULL, 0 },
889/* 0xed */ { NULL, NULL, 0 },
890/* 0xee */ { NULL, NULL, 0 },
891/* 0xef */ { NULL, NULL, 0 },
892/* 0xf0 */ { NULL, NULL, 0 },
893/* 0xf1 */ { NULL, NULL, 0 },
894/* 0xf2 */ { NULL, NULL, 0 },
895/* 0xf3 */ { NULL, NULL, 0 },
896/* 0xf4 */ { NULL, NULL, 0 },
897/* 0xf5 */ { NULL, NULL, 0 },
898/* 0xf6 */ { NULL, NULL, 0 },
899/* 0xf7 */ { NULL, NULL, 0 },
900/* 0xf8 */ { NULL, NULL, 0 },
901/* 0xf9 */ { NULL, NULL, 0 },
902/* 0xfa */ { NULL, NULL, 0 },
903/* 0xfb */ { NULL, NULL, 0 },
904/* 0xfc */ { NULL, NULL, 0 },
905/* 0xfd */ { NULL, NULL, 0 },
906/* 0xfe */ { NULL, NULL, 0 },
907/* 0xff */ { NULL, NULL, 0 }
918c3ebe
JA
908
909};
c3effa8b 910
cc6a4101
VL
911/*******************************************************************
912 allocate and initialize a reply packet
913********************************************************************/
914
2fb27fcb 915void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
cc6a4101 916{
2fb27fcb
VL
917 /*
918 * Protect against integer wrap
919 */
920 if ((num_bytes > 0xffffff)
921 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
922 char *msg;
923 asprintf(&msg, "num_bytes too large: %u",
924 (unsigned)num_bytes);
925 smb_panic(msg);
926 }
927
cc6a4101
VL
928 if (!(req->outbuf = TALLOC_ARRAY(
929 req, uint8,
930 smb_size + num_words*2 + num_bytes))) {
931 smb_panic("could not allocate output buffer\n");
932 }
933
934 construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
e5a95132 935 set_message((char *)req->outbuf, num_words, num_bytes, False);
cc6a4101
VL
936 /*
937 * Zero out the word area, the caller has to take care of the bcc area
938 * himself
939 */
940 if (num_words != 0) {
941 memset(req->outbuf + smb_vwv0, 0, num_words*2);
942 }
943
944 return;
945}
946
947
712a30ed 948/*******************************************************************
a834a73e
GC
949 Dump a packet to a file.
950********************************************************************/
951
cc6a4101 952static void smb_dump(const char *name, int type, const char *data, ssize_t len)
712a30ed
LL
953{
954 int fd, i;
955 pstring fname;
956 if (DEBUGLEVEL < 50) return;
957
62707533 958 if (len < 4) len = smb_len(data)+4;
712a30ed 959 for (i=1;i<100;i++) {
f9a15ce1 960 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
712a30ed
LL
961 type ? "req" : "resp");
962 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
963 if (fd != -1 || errno != EEXIST) break;
964 }
965 if (fd != -1) {
e400bfce
JA
966 ssize_t ret = write(fd, data, len);
967 if (ret != len)
968 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
712a30ed 969 close(fd);
9c8d23e5 970 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
712a30ed
LL
971 }
972}
973
c3effa8b 974/****************************************************************************
cc6a4101
VL
975 Prepare everything for calling the actual request function, and potentially
976 call the request function via the "new" interface.
977
978 Return False if the "legacy" function needs to be called, everything is
979 prepared.
980
981 Return True if we're done.
982
983 I know this API sucks, but it is the one with the least code change I could
984 find.
c3effa8b 985****************************************************************************/
a834a73e 986
b578db69 987static void switch_message(uint8 type, struct smb_request *req, int size)
c3effa8b 988{
941db29a 989 int flags;
941db29a
VL
990 uint16 session_tag;
991 connection_struct *conn;
24f8e973 992
8579dd4d
VL
993 static uint16 last_session_tag = UID_FIELD_INVALID;
994
a834a73e 995 errno = 0;
0557c6cb 996
a834a73e 997 last_message = type;
918c3ebe 998
cc6a4101
VL
999 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1000 * so subtract 4 from it. */
1001 if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0)
1002 || (size < (smb_size - 4))) {
1003 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1004 smb_len(req->inbuf)));
eecdc6c9 1005 exit_server_cleanly("Non-SMB packet");
a834a73e 1006 }
c3effa8b 1007
b578db69 1008 if (smb_messages[type].fn_new == NULL) {
a834a73e 1009 DEBUG(0,("Unknown message type %d!\n",type));
cc6a4101
VL
1010 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1011 reply_unknown_new(req, type);
b578db69 1012 return;
941db29a 1013 }
a834a73e 1014
941db29a 1015 flags = smb_messages[type].flags;
a834a73e 1016
941db29a
VL
1017 /* In share mode security we must ignore the vuid. */
1018 session_tag = (lp_security() == SEC_SHARE)
cc6a4101
VL
1019 ? UID_FIELD_INVALID : req->vuid;
1020 conn = conn_find(req->tid);
918c3ebe 1021
8579dd4d
VL
1022 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1023 (int)sys_getpid(), (unsigned long)conn));
941db29a 1024
cc6a4101 1025 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
918c3ebe 1026
941db29a 1027 /* Ensure this value is replaced in the incoming packet. */
cc6a4101 1028 SSVAL(req->inbuf,smb_uid,session_tag);
918c3ebe 1029
941db29a
VL
1030 /*
1031 * Ensure the correct username is in current_user_info. This is a
1032 * really ugly bugfix for problems with multiple session_setup_and_X's
1033 * being done and allowing %U and %G substitutions to work correctly.
1034 * There is a reason this code is done here, don't move it unless you
8579dd4d
VL
1035 * know what you're doing... :-).
1036 * JRA.
941db29a
VL
1037 */
1038
1039 if (session_tag != last_session_tag) {
1040 user_struct *vuser = NULL;
1041
1042 last_session_tag = session_tag;
1043 if(session_tag != UID_FIELD_INVALID) {
8579dd4d 1044 vuser = get_valid_user_struct(session_tag);
941db29a
VL
1045 if (vuser) {
1046 set_current_user_info(&vuser->user);
a59149b8
JA
1047 }
1048 }
941db29a 1049 }
fcda2645 1050
941db29a
VL
1051 /* Does this call need to be run as the connected user? */
1052 if (flags & AS_USER) {
fcda2645 1053
941db29a
VL
1054 /* Does this call need a valid tree connection? */
1055 if (!conn) {
8579dd4d
VL
1056 /*
1057 * Amazingly, the error code depends on the command
1058 * (from Samba4).
1059 */
941db29a 1060 if (type == SMBntcreateX) {
cc6a4101 1061 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
941db29a 1062 } else {
cc6a4101 1063 reply_doserror(req, ERRSRV, ERRinvnid);
ce61fb21 1064 }
b578db69 1065 return;
941db29a 1066 }
c3effa8b 1067
941db29a 1068 if (!change_to_user(conn,session_tag)) {
cc6a4101 1069 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
b578db69 1070 return;
941db29a 1071 }
c3effa8b 1072
941db29a 1073 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
918c3ebe 1074
941db29a
VL
1075 /* Does it need write permission? */
1076 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
cc6a4101 1077 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
b578db69 1078 return;
ce61fb21 1079 }
918c3ebe 1080
941db29a
VL
1081 /* IPC services are limited */
1082 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
cc6a4101 1083 reply_doserror(req, ERRSRV,ERRaccess);
b578db69 1084 return;
f60ad8de 1085 }
941db29a
VL
1086 } else {
1087 /* This call needs to be run as root */
1088 change_to_root_user();
1089 }
918c3ebe 1090
941db29a
VL
1091 /* load service specific parameters */
1092 if (conn) {
cc6a4101 1093 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
8579dd4d
VL
1094 (flags & (AS_USER|DO_CHDIR)
1095 ?True:False))) {
cc6a4101 1096 reply_doserror(req, ERRSRV, ERRaccess);
b578db69 1097 return;
ce61fb21 1098 }
941db29a
VL
1099 conn->num_smb_operations++;
1100 }
918c3ebe 1101
941db29a
VL
1102 /* does this protocol need to be run as guest? */
1103 if ((flags & AS_GUEST)
8579dd4d 1104 && (!change_to_guest() ||
941db29a
VL
1105 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1106 lp_hostsdeny(-1)))) {
cc6a4101 1107 reply_doserror(req, ERRSRV, ERRaccess);
b578db69 1108 return;
cc6a4101
VL
1109 }
1110
b578db69 1111 smb_messages[type].fn_new(conn, req);
e9ea36e4
AT
1112}
1113
e9ea36e4 1114/****************************************************************************
a834a73e 1115 Construct a reply to the incoming packet.
e9ea36e4 1116****************************************************************************/
a834a73e 1117
cc6a4101 1118static void construct_reply(char *inbuf, int size)
e9ea36e4 1119{
cc6a4101 1120 uint8 type = CVAL(inbuf,smb_com);
cc6a4101 1121 struct smb_request *req;
e9ea36e4 1122
a834a73e
GC
1123 chain_size = 0;
1124 file_chain_reset();
1125 reset_chain_p();
e9ea36e4 1126
929e1d99 1127 if (!(req = talloc(talloc_tos(), struct smb_request))) {
cc6a4101
VL
1128 smb_panic("could not allocate smb_request");
1129 }
1130 init_smb_request(req, (uint8 *)inbuf);
e9ea36e4 1131
b578db69 1132 switch_message(type, req, size);
e9ea36e4 1133
b578db69
VL
1134 if (req->outbuf == NULL) {
1135 return;
cc6a4101 1136 }
e9ea36e4 1137
b578db69
VL
1138 if (CVAL(req->outbuf,0) == 0) {
1139 show_msg((char *)req->outbuf);
1140 }
e9ea36e4 1141
b578db69
VL
1142 if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) {
1143 exit_server_cleanly("construct_reply: send_smb failed.");
dc90cd89 1144 }
cc6a4101
VL
1145
1146 TALLOC_FREE(req);
1147
1148 return;
e9ea36e4
AT
1149}
1150
e9ea36e4 1151/****************************************************************************
49ecd176 1152 Process an smb from the client
e9ea36e4 1153****************************************************************************/
1eff0523 1154
cc6a4101 1155static void process_smb(char *inbuf, size_t nread)
e9ea36e4 1156{
1eff0523
JA
1157 static int trans_num;
1158 int msg_type = CVAL(inbuf,0);
1eff0523
JA
1159
1160 DO_PROFILE_INC(smb_count);
1161
1162 if (trans_num == 0) {
1163 /* on the first packet, check the global hosts allow/ hosts
1164 deny parameters before doing any parsing of the packet
1165 passed to us by the client. This prevents attacks on our
1166 parsing code from hosts not in the hosts allow list */
0be13172
VL
1167 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1168 lp_hostsdeny(-1))) {
1eff0523
JA
1169 /* send a negative session response "not listening on calling name" */
1170 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1171 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1172 (void)send_smb(smbd_server_fd(),(char *)buf);
eecdc6c9 1173 exit_server_cleanly("connection denied");
1eff0523
JA
1174 }
1175 }
1176
cc6a4101
VL
1177 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1178 smb_len(inbuf) ) );
e5cdc454 1179 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, (int)nread ) );
1eff0523 1180
cc6a4101
VL
1181 if (msg_type != 0) {
1182 /*
1183 * NetBIOS session request, keepalive, etc.
1184 */
1185 reply_special(inbuf);
1186 return;
1187 }
1eff0523 1188
cc6a4101
VL
1189 show_msg(inbuf);
1190
1191 construct_reply(inbuf,nread);
e9ea36e4 1192
1eff0523 1193 trans_num++;
e9ea36e4
AT
1194}
1195
e9ea36e4 1196/****************************************************************************
1eff0523 1197 Return a string containing the function name of a SMB command.
e9ea36e4 1198****************************************************************************/
1eff0523 1199
127e77e6 1200const char *smb_fn_name(int type)
e9ea36e4 1201{
634c5431 1202 const char *unknown_name = "SMBunknown";
e9ea36e4 1203
918c3ebe 1204 if (smb_messages[type].name == NULL)
e9ea36e4
AT
1205 return(unknown_name);
1206
918c3ebe 1207 return(smb_messages[type].name);
c3effa8b
AT
1208}
1209
dc76502c 1210/****************************************************************************
6bb8f54e 1211 Helper functions for contruct_reply.
dc76502c
JA
1212****************************************************************************/
1213
6219c997
JA
1214static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1215
1216void add_to_common_flags2(uint32 v)
1217{
1218 common_flags2 |= v;
1219}
6bb8f54e 1220
27891bde 1221void remove_from_common_flags2(uint32 v)
6bb8f54e 1222{
27891bde 1223 common_flags2 &= ~v;
6bb8f54e
JA
1224}
1225
ab7fc62e 1226void construct_reply_common(const char *inbuf, char *outbuf)
dc76502c 1227{
e5a95132
GJC
1228 set_message(outbuf,0,0,False);
1229
fc13f284
JA
1230 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1231 SIVAL(outbuf,smb_rcls,0);
b7280423
AT
1232 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1233 SSVAL(outbuf,smb_flg2,
6bb8f54e
JA
1234 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1235 common_flags2);
fc13f284 1236 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
b7280423 1237
b7280423
AT
1238 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1239 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1240 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1241 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
dc76502c 1242}
c3effa8b
AT
1243
1244/****************************************************************************
1eff0523
JA
1245 Construct a chained reply and add it to the already made reply
1246****************************************************************************/
1247
b578db69 1248void chain_reply(struct smb_request *req)
c3effa8b 1249{
1eff0523 1250 static char *orig_inbuf;
b578db69
VL
1251
1252 /*
1253 * Dirty little const_discard: We mess with req->inbuf, which is
1254 * declared as const. If maybe at some point this routine gets
1255 * rewritten, this const_discard could go away.
1256 */
1257 char *inbuf = CONST_DISCARD(char *, req->inbuf);
1258 int size = smb_len(req->inbuf)+4;
1259
1eff0523
JA
1260 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1261 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
cc6a4101 1262 char *inbuf2;
1eff0523 1263 int outsize2;
235b0f97 1264 int new_size;
1eff0523 1265 char inbuf_saved[smb_wct];
b578db69 1266 char *outbuf = (char *)req->outbuf;
cc6a4101
VL
1267 size_t outsize = smb_len(outbuf) + 4;
1268 size_t outsize_padded;
1269 size_t ofs, to_move;
1270
b578db69 1271 struct smb_request *req2;
cc6a4101
VL
1272 size_t caller_outputlen;
1273 char *caller_output;
1eff0523 1274
a0987247
JA
1275 /* Maybe its not chained, or it's an error packet. */
1276 if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1eff0523 1277 SCVAL(outbuf,smb_vwv0,0xFF);
b578db69 1278 return;
1eff0523
JA
1279 }
1280
1281 if (chain_size == 0) {
1282 /* this is the first part of the chain */
1283 orig_inbuf = inbuf;
cc6a4101
VL
1284 }
1285
1286 /*
1287 * We need to save the output the caller added to the chain so that we
1288 * can splice it into the final output buffer later.
1289 */
1290
1291 caller_outputlen = outsize - smb_wct;
1292
1293 caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen);
1294
1295 if (caller_output == NULL) {
1296 /* TODO: NT_STATUS_NO_MEMORY */
1297 smb_panic("could not dup outbuf");
1eff0523
JA
1298 }
1299
1300 /*
1301 * The original Win95 redirector dies on a reply to
1302 * a lockingX and read chain unless the chain reply is
1303 * 4 byte aligned. JRA.
1304 */
1305
cc6a4101 1306 outsize_padded = (outsize + 3) & ~3;
1eff0523 1307
cc6a4101
VL
1308 /*
1309 * remember how much the caller added to the chain, only counting
1310 * stuff after the parameter words
1311 */
1312 chain_size += outsize_padded - smb_wct;
1eff0523 1313
cc6a4101
VL
1314 /*
1315 * work out pointers into the original packets. The
1316 * headers on these need to be filled in
1317 */
1eff0523 1318 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1eff0523
JA
1319
1320 /* remember the original command type */
1321 smb_com1 = CVAL(orig_inbuf,smb_com);
1322
1323 /* save the data which will be overwritten by the new headers */
1324 memcpy(inbuf_saved,inbuf2,smb_wct);
1eff0523
JA
1325
1326 /* give the new packet the same header as the last part of the SMB */
1327 memmove(inbuf2,inbuf,smb_wct);
1328
1329 /* create the in buffer */
1330 SCVAL(inbuf2,smb_com,smb_com2);
1331
235b0f97
JA
1332 /* work out the new size for the in buffer. */
1333 new_size = size - (inbuf2 - inbuf);
1334 if (new_size < 0) {
fb564434
VL
1335 DEBUG(0,("chain_reply: chain packet size incorrect "
1336 "(orig size = %d, offset = %d)\n",
1337 size, (int)(inbuf2 - inbuf) ));
235b0f97 1338 exit_server_cleanly("Bad chained packet");
b578db69 1339 return;
235b0f97
JA
1340 }
1341
1342 /* And set it in the header. */
e5a95132 1343 smb_setlen(inbuf2, new_size - 4);
235b0f97 1344
1eff0523
JA
1345 DEBUG(3,("Chained message\n"));
1346 show_msg(inbuf2);
1347
929e1d99 1348 if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
cc6a4101
VL
1349 smb_panic("could not allocate smb_request");
1350 }
b578db69 1351 init_smb_request(req2, (uint8 *)inbuf2);
cc6a4101 1352
1eff0523 1353 /* process the request */
b578db69 1354 switch_message(smb_com2, req2, new_size);
1eff0523 1355
cc6a4101
VL
1356 /*
1357 * We don't accept deferred operations in chained requests.
1358 */
b578db69
VL
1359 SMB_ASSERT(req2->outbuf != NULL);
1360 outsize2 = smb_len(req2->outbuf)+4;
1eff0523 1361
cc6a4101
VL
1362 /*
1363 * Move away the new command output so that caller_output fits in,
1364 * copy in the caller_output saved above.
1365 */
1eff0523 1366
cc6a4101
VL
1367 SMB_ASSERT(outsize_padded >= smb_wct);
1368
1369 /*
1370 * "ofs" is the space we need for caller_output. Equal to
1371 * caller_outputlen plus the padding.
1372 */
1373
1374 ofs = outsize_padded - smb_wct;
1375
1376 /*
1377 * "to_move" is the amount of bytes the secondary routine gave us
1378 */
1379
1380 to_move = outsize2 - smb_wct;
1381
1382 if (to_move + ofs + smb_wct + chain_size > max_send) {
1383 smb_panic("replies too large -- would have to cut");
1384 }
1385
1386 /*
1387 * In the "new" API "outbuf" is allocated via reply_outbuf, just for
1388 * the first request in the chain. So we have to re-allocate it. In
1389 * the "old" API the only outbuf ever used is the global OutBuffer
1390 * which is always large enough.
1391 */
1392
b578db69
VL
1393 outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
1394 to_move + ofs + smb_wct);
1395 if (outbuf == NULL) {
1396 smb_panic("could not realloc outbuf");
1eff0523
JA
1397 }
1398
b578db69 1399 req->outbuf = (uint8 *)outbuf;
cc6a4101 1400
b578db69 1401 memmove(outbuf + smb_wct + ofs, req2->outbuf + smb_wct, to_move);
cc6a4101
VL
1402 memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
1403
1404 /*
d90f6fa1
VL
1405 * copy the new reply header over the old one but preserve the smb_com
1406 * field
cc6a4101 1407 */
b578db69 1408 memmove(outbuf, req2->outbuf, smb_wct);
cc6a4101
VL
1409 SCVAL(outbuf, smb_com, smb_com1);
1410
1411 /*
1412 * We've just copied in the whole "wct" area from the secondary
1413 * function. Fix up the chaining: com2 and the offset need to be
1414 * readjusted.
1415 */
1416
1417 SCVAL(outbuf, smb_vwv0, smb_com2);
1418 SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
1419
1420 if (outsize_padded > outsize) {
1421
1422 /*
1423 * Due to padding we have some uninitialized bytes after the
1424 * caller's output
1425 */
1426
1427 memset(outbuf + outsize, 0, outsize_padded - outsize);
1428 }
1429
e5a95132 1430 smb_setlen(outbuf, outsize2 + chain_size - 4);
cc6a4101
VL
1431
1432 /*
1433 * restore the saved data, being careful not to overwrite any data
1434 * from the reply header
1435 */
1436 memcpy(inbuf2,inbuf_saved,smb_wct);
1437
1438 SAFE_FREE(caller_output);
b578db69 1439 TALLOC_FREE(req2);
cc6a4101 1440
b578db69 1441 return;
c3effa8b
AT
1442}
1443
c3effa8b 1444/****************************************************************************
b737f267 1445 Setup the needed select timeout in milliseconds.
c3effa8b 1446****************************************************************************/
3db52feb
AT
1447
1448static int setup_select_timeout(void)
c3effa8b 1449{
cc5502a4 1450 int select_timeout;
c3effa8b 1451
496dbdf4 1452 select_timeout = SMBD_SELECT_TIMEOUT*1000;
3db52feb 1453
b737f267 1454 if (print_notify_messages_pending()) {
a834a73e 1455 select_timeout = MIN(select_timeout, 1000);
b737f267 1456 }
3db52feb 1457
cc5502a4 1458 return select_timeout;
3db52feb
AT
1459}
1460
1461/****************************************************************************
1462 Check if services need reloading.
1463****************************************************************************/
1464
54abd2aa 1465void check_reload(time_t t)
3db52feb 1466{
7ebd74e6 1467 static pid_t mypid = 0;
1eff0523 1468 static time_t last_smb_conf_reload_time = 0;
d097ea49 1469 static time_t last_printer_reload_time = 0;
67d47486 1470 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
3db52feb 1471
67d47486 1472 if(last_smb_conf_reload_time == 0) {
1eff0523 1473 last_smb_conf_reload_time = t;
67d47486
GC
1474 /* Our printing subsystem might not be ready at smbd start up.
1475 Then no printer is available till the first printers check
1476 is performed. A lower initial interval circumvents this. */
1477 if ( printcap_cache_time > 60 )
d097ea49 1478 last_printer_reload_time = t - printcap_cache_time + 60;
67d47486 1479 else
d097ea49 1480 last_printer_reload_time = t;
67d47486 1481 }
c3effa8b 1482
7ebd74e6
SS
1483 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1484 /* randomize over 60 second the printcap reload to avoid all
1485 * process hitting cupsd at the same time */
1486 int time_range = 60;
1487
1488 last_printer_reload_time += random() % time_range;
1489 mypid = getpid();
1490 }
1491
1eff0523
JA
1492 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1493 reload_services(True);
1494 reload_after_sighup = False;
1495 last_smb_conf_reload_time = t;
1496 }
67d47486
GC
1497
1498 /* 'printcap cache time = 0' disable the feature */
1499
1500 if ( printcap_cache_time != 0 )
1501 {
1502 /* see if it's time to reload or if the clock has been set back */
1503
d097ea49
GC
1504 if ( (t >= last_printer_reload_time+printcap_cache_time)
1505 || (t-last_printer_reload_time < 0) )
67d47486
GC
1506 {
1507 DEBUG( 3,( "Printcap cache time expired.\n"));
d097ea49
GC
1508 reload_printers();
1509 last_printer_reload_time = t;
67d47486
GC
1510 }
1511 }
3db52feb 1512}
c3effa8b 1513
3db52feb 1514/****************************************************************************
2afd5d5e 1515 Process any timeout housekeeping. Return False if the caller should exit.
3db52feb 1516****************************************************************************/
dd2e202e 1517
2864d86b
VL
1518static BOOL timeout_processing(int *select_timeout,
1519 time_t *last_timeout_processing_time)
3db52feb 1520{
1eff0523 1521 time_t t;
1eff0523
JA
1522
1523 if (smb_read_error == READ_EOF) {
ceb68ee0 1524 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1eff0523
JA
1525 return False;
1526 }
1527
1528 if (smb_read_error == READ_ERROR) {
ceb68ee0 1529 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1eff0523
JA
1530 strerror(errno)));
1531 return False;
1532 }
1533
ceb68ee0
JA
1534 if (smb_read_error == READ_BAD_SIG) {
1535 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1536 return False;
1537 }
1538
1eff0523
JA
1539 *last_timeout_processing_time = t = time(NULL);
1540
1eff0523
JA
1541 /* become root again if waiting */
1542 change_to_root_user();
1543
1eff0523
JA
1544 /* check if we need to reload services */
1545 check_reload(t);
1546
1eff0523
JA
1547 if(global_machine_password_needs_changing &&
1548 /* for ADS we need to do a regular ADS password change, not a domain
1549 password change */
1550 lp_security() == SEC_DOMAIN) {
1551
1552 unsigned char trust_passwd_hash[16];
1553 time_t lct;
1554
1555 /*
1556 * We're in domain level security, and the code that
1557 * read the machine password flagged that the machine
1558 * password needs changing.
1559 */
1560
1561 /*
1562 * First, open the machine password file with an exclusive lock.
1563 */
1564
1565 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1566 DEBUG(0,("process: unable to lock the machine account password for \
2f194322 1567machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1eff0523
JA
1568 return True;
1569 }
a834a73e 1570
1eff0523
JA
1571 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1572 DEBUG(0,("process: unable to read the machine account password for \
f071020f 1573machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1eff0523
JA
1574 secrets_lock_trust_account_password(lp_workgroup(), False);
1575 return True;
1576 }
c3effa8b 1577
1eff0523
JA
1578 /*
1579 * Make sure someone else hasn't already done this.
1580 */
c3effa8b 1581
1eff0523
JA
1582 if(t < lct + lp_machine_password_timeout()) {
1583 global_machine_password_needs_changing = False;
1584 secrets_lock_trust_account_password(lp_workgroup(), False);
1585 return True;
1586 }
c3effa8b 1587
1eff0523 1588 /* always just contact the PDC here */
612e1ffd 1589
1eff0523
JA
1590 change_trust_account_password( lp_workgroup(), NULL);
1591 global_machine_password_needs_changing = False;
1592 secrets_lock_trust_account_password(lp_workgroup(), False);
1593 }
1594
1eff0523 1595 /* update printer queue caches if necessary */
071af8f0 1596
1eff0523 1597 update_monitored_printq_cache();
071af8f0 1598
a633b425
VL
1599 /*
1600 * Now we are root, check if the log files need pruning.
1601 * Force a log file check.
1602 */
1603 force_check_log_size();
1604 check_log_size();
1605
1eff0523 1606 /* Send any queued printer notify message to interested smbd's. */
a834a73e 1607
fad7dd8a 1608 print_notify_send_messages(smbd_messaging_context(), 0);
a834a73e 1609
1eff0523
JA
1610 /*
1611 * Modify the select timeout depending upon
1612 * what we have remaining in our queues.
1613 */
c3effa8b 1614
1eff0523 1615 *select_timeout = setup_select_timeout();
c3effa8b 1616
1eff0523 1617 return True;
3db52feb 1618}
c3effa8b 1619
f2f55d70
JA
1620/****************************************************************************
1621 Process commands from the client
1622****************************************************************************/
1623
1624void smbd_process(void)
1625{
1626 time_t last_timeout_processing_time = time(NULL);
1627 unsigned int num_smbs = 0;
1628
b2d01bd2 1629 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
c3effa8b 1630
b2d01bd2 1631 while (True) {
b2d01bd2
AT
1632 int select_timeout = setup_select_timeout();
1633 int num_echos;
cc6a4101
VL
1634 char *inbuf;
1635 size_t inbuf_len;
929e1d99 1636 TALLOC_CTX *frame = talloc_stackframe();
dc76502c 1637
b2d01bd2
AT
1638 errno = 0;
1639
fb3e4b87
JA
1640 /* Did someone ask for immediate checks on things like blocking locks ? */
1641 if (select_timeout == 0) {
2864d86b
VL
1642 if(!timeout_processing(&select_timeout,
1643 &last_timeout_processing_time))
fb3e4b87
JA
1644 return;
1645 num_smbs = 0; /* Reset smb counter. */
1646 }
1647
bf219447 1648 run_events(smbd_event_context(), 0, NULL, NULL);
54abd2aa 1649
cc6a4101
VL
1650 while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
1651 select_timeout)) {
2864d86b
VL
1652 if(!timeout_processing(&select_timeout,
1653 &last_timeout_processing_time))
b2d01bd2
AT
1654 return;
1655 num_smbs = 0; /* Reset smb counter. */
1656 }
1657
cc6a4101 1658
b2d01bd2
AT
1659 /*
1660 * Ensure we do timeout processing if the SMB we just got was
1661 * only an echo request. This allows us to set the select
1662 * timeout in 'receive_message_or_smb()' to any value we like
1663 * without worrying that the client will send echo requests
1664 * faster than the select timeout, thus starving out the
1665 * essential processing (change notify, blocking locks) that
1666 * the timeout code does. JRA.
1667 */
1668 num_echos = smb_echo_count;
1669
cc6a4101 1670 process_smb(inbuf, inbuf_len);
1f499a79 1671
cc6a4101 1672 TALLOC_FREE(inbuf);
b2d01bd2
AT
1673
1674 if (smb_echo_count != num_echos) {
2864d86b 1675 if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
b2d01bd2
AT
1676 return;
1677 num_smbs = 0; /* Reset smb counter. */
1678 }
1679
1680 num_smbs++;
1681
1682 /*
1683 * If we are getting smb requests in a constant stream
1684 * with no echos, make sure we attempt timeout processing
1685 * every select_timeout milliseconds - but only check for this
1686 * every 200 smb requests.
1687 */
1688
1689 if ((num_smbs % 200) == 0) {
1690 time_t new_check_time = time(NULL);
5ba566ef 1691 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
2864d86b
VL
1692 if(!timeout_processing(
1693 &select_timeout,
1694 &last_timeout_processing_time))
b2d01bd2
AT
1695 return;
1696 num_smbs = 0; /* Reset smb counter. */
1697 last_timeout_processing_time = new_check_time; /* Reset time. */
1698 }
1699 }
142837e5
TP
1700
1701 /* The timeout_processing function isn't run nearly
1702 often enough to implement 'max log size' without
1703 overrunning the size of the file by many megabytes.
1704 This is especially true if we are running at debug
1705 level 10. Checking every 50 SMBs is a nice
1706 tradeoff of performance vs log file size overrun. */
1707
1708 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1709 change_to_root_user();
1710 check_log_size();
1711 }
929e1d99 1712 TALLOC_FREE(frame);
b2d01bd2 1713 }
c3effa8b 1714}