s3:smbd: call message_dispatch() before processing incoming PDUs
[samba.git] / source3 / smbd / process.c
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-2007
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/globals.h"
23
24 extern bool global_machine_password_needs_changing;
25
26 static void construct_reply_common(struct smb_request *req, const char *inbuf,
27                                    char *outbuf);
28
29 /* Accessor function for smb_read_error for smbd functions. */
30
31 /****************************************************************************
32  Send an smb to a fd.
33 ****************************************************************************/
34
35 bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
36 {
37         size_t len;
38         size_t nwritten=0;
39         ssize_t ret;
40         char *buf_out = buffer;
41
42         /* Sign the outgoing packet if required. */
43         srv_calculate_sign_mac(buf_out);
44
45         if (do_encrypt) {
46                 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
47                 if (!NT_STATUS_IS_OK(status)) {
48                         DEBUG(0, ("send_smb: SMB encryption failed "
49                                 "on outgoing packet! Error %s\n",
50                                 nt_errstr(status) ));
51                         return false;
52                 }
53         }
54
55         len = smb_len(buf_out) + 4;
56
57         while (nwritten < len) {
58                 ret = write_data(fd,buf_out+nwritten,len - nwritten);
59                 if (ret <= 0) {
60                         DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
61                                 (int)len,(int)ret, strerror(errno) ));
62                         srv_free_enc_buffer(buf_out);
63                         return false;
64                 }
65                 nwritten += ret;
66         }
67
68         srv_free_enc_buffer(buf_out);
69         return true;
70 }
71
72 /*******************************************************************
73  Setup the word count and byte count for a smb message.
74 ********************************************************************/
75
76 int srv_set_message(char *buf,
77                         int num_words,
78                         int num_bytes,
79                         bool zero)
80 {
81         if (zero && (num_words || num_bytes)) {
82                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
83         }
84         SCVAL(buf,smb_wct,num_words);
85         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
86         smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
87         return (smb_size + num_words*2 + num_bytes);
88 }
89
90 static bool valid_smb_header(const uint8_t *inbuf)
91 {
92         if (is_encrypted_packet(inbuf)) {
93                 return true;
94         }
95         /*
96          * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
97          * but it just looks weird to call strncmp for this one.
98          */
99         return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
100 }
101
102 /* Socket functions for smbd packet processing. */
103
104 static bool valid_packet_size(size_t len)
105 {
106         /*
107          * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
108          * of header. Don't print the error if this fits.... JRA.
109          */
110
111         if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
112                 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
113                                         (unsigned long)len));
114                 return false;
115         }
116         return true;
117 }
118
119 static NTSTATUS read_packet_remainder(int fd, char *buffer,
120                                       unsigned int timeout, ssize_t len)
121 {
122         if (len <= 0) {
123                 return NT_STATUS_OK;
124         }
125
126         return read_socket_with_timeout(fd, buffer, len, len, timeout, NULL);
127 }
128
129 /****************************************************************************
130  Attempt a zerocopy writeX read. We know here that len > smb_size-4
131 ****************************************************************************/
132
133 /*
134  * Unfortunately, earlier versions of smbclient/libsmbclient
135  * don't send this "standard" writeX header. I've fixed this
136  * for 3.2 but we'll use the old method with earlier versions.
137  * Windows and CIFSFS at least use this standard size. Not
138  * sure about MacOSX.
139  */
140
141 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
142                                 (2*14) + /* word count (including bcc) */ \
143                                 1 /* pad byte */)
144
145 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
146                                                     const char lenbuf[4],
147                                                     int fd, char **buffer,
148                                                     unsigned int timeout,
149                                                     size_t *p_unread,
150                                                     size_t *len_ret)
151 {
152         /* Size of a WRITEX call (+4 byte len). */
153         char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
154         ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
155         ssize_t toread;
156         NTSTATUS status;
157
158         memcpy(writeX_header, lenbuf, 4);
159
160         status = read_socket_with_timeout(
161                 fd, writeX_header + 4,
162                 STANDARD_WRITE_AND_X_HEADER_SIZE,
163                 STANDARD_WRITE_AND_X_HEADER_SIZE,
164                 timeout, NULL);
165
166         if (!NT_STATUS_IS_OK(status)) {
167                 return status;
168         }
169
170         /*
171          * Ok - now try and see if this is a possible
172          * valid writeX call.
173          */
174
175         if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
176                 /*
177                  * If the data offset is beyond what
178                  * we've read, drain the extra bytes.
179                  */
180                 uint16_t doff = SVAL(writeX_header,smb_vwv11);
181                 ssize_t newlen;
182
183                 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
184                         size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
185                         if (drain_socket(smbd_server_fd(), drain) != drain) {
186                                 smb_panic("receive_smb_raw_talloc_partial_read:"
187                                         " failed to drain pending bytes");
188                         }
189                 } else {
190                         doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
191                 }
192
193                 /* Spoof down the length and null out the bcc. */
194                 set_message_bcc(writeX_header, 0);
195                 newlen = smb_len(writeX_header);
196
197                 /* Copy the header we've written. */
198
199                 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
200                                 writeX_header,
201                                 sizeof(writeX_header));
202
203                 if (*buffer == NULL) {
204                         DEBUG(0, ("Could not allocate inbuf of length %d\n",
205                                   (int)sizeof(writeX_header)));
206                         return NT_STATUS_NO_MEMORY;
207                 }
208
209                 /* Work out the remaining bytes. */
210                 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
211                 *len_ret = newlen + 4;
212                 return NT_STATUS_OK;
213         }
214
215         if (!valid_packet_size(len)) {
216                 return NT_STATUS_INVALID_PARAMETER;
217         }
218
219         /*
220          * Not a valid writeX call. Just do the standard
221          * talloc and return.
222          */
223
224         *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
225
226         if (*buffer == NULL) {
227                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
228                           (int)len+4));
229                 return NT_STATUS_NO_MEMORY;
230         }
231
232         /* Copy in what we already read. */
233         memcpy(*buffer,
234                 writeX_header,
235                 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
236         toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
237
238         if(toread > 0) {
239                 status = read_packet_remainder(
240                         fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
241                         timeout, toread);
242
243                 if (!NT_STATUS_IS_OK(status)) {
244                         DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
245                                    nt_errstr(status)));
246                         return status;
247                 }
248         }
249
250         *len_ret = len + 4;
251         return NT_STATUS_OK;
252 }
253
254 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
255                                        char **buffer, unsigned int timeout,
256                                        size_t *p_unread, size_t *plen)
257 {
258         char lenbuf[4];
259         size_t len;
260         int min_recv_size = lp_min_receive_file_size();
261         NTSTATUS status;
262
263         *p_unread = 0;
264
265         status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
266         if (!NT_STATUS_IS_OK(status)) {
267                 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
268                 return status;
269         }
270
271         if (CVAL(lenbuf,0) == 0 &&
272                         min_recv_size &&
273                         smb_len_large(lenbuf) > (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE) && /* Could be a UNIX large writeX. */
274                         !srv_is_signing_active()) {
275
276                 return receive_smb_raw_talloc_partial_read(
277                         mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
278         }
279
280         if (!valid_packet_size(len)) {
281                 return NT_STATUS_INVALID_PARAMETER;
282         }
283
284         /*
285          * The +4 here can't wrap, we've checked the length above already.
286          */
287
288         *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
289
290         if (*buffer == NULL) {
291                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
292                           (int)len+4));
293                 return NT_STATUS_NO_MEMORY;
294         }
295
296         memcpy(*buffer, lenbuf, sizeof(lenbuf));
297
298         status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
299         if (!NT_STATUS_IS_OK(status)) {
300                 return status;
301         }
302
303         *plen = len + 4;
304         return NT_STATUS_OK;
305 }
306
307 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
308                                    char **buffer, unsigned int timeout,
309                                    size_t *p_unread, bool *p_encrypted,
310                                    size_t *p_len)
311 {
312         size_t len = 0;
313         NTSTATUS status;
314
315         *p_encrypted = false;
316
317         status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
318                                         p_unread, &len);
319         if (!NT_STATUS_IS_OK(status)) {
320                 return status;
321         }
322
323         if (is_encrypted_packet((uint8_t *)*buffer)) {
324                 status = srv_decrypt_buffer(*buffer);
325                 if (!NT_STATUS_IS_OK(status)) {
326                         DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
327                                 "incoming packet! Error %s\n",
328                                 nt_errstr(status) ));
329                         return status;
330                 }
331                 *p_encrypted = true;
332         }
333
334         /* Check the incoming SMB signature. */
335         if (!srv_check_sign_mac(*buffer, true)) {
336                 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
337                           "incoming packet!\n"));
338                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
339         }
340
341         *p_len = len;
342         return NT_STATUS_OK;
343 }
344
345 /*
346  * Initialize a struct smb_request from an inbuf
347  */
348
349 void init_smb_request(struct smb_request *req,
350                         const uint8 *inbuf,
351                         size_t unread_bytes,
352                         bool encrypted)
353 {
354         size_t req_size = smb_len(inbuf) + 4;
355         /* Ensure we have at least smb_size bytes. */
356         if (req_size < smb_size) {
357                 DEBUG(0,("init_smb_request: invalid request size %u\n",
358                         (unsigned int)req_size ));
359                 exit_server_cleanly("Invalid SMB request");
360         }
361         req->cmd    = CVAL(inbuf, smb_com);
362         req->flags2 = SVAL(inbuf, smb_flg2);
363         req->smbpid = SVAL(inbuf, smb_pid);
364         req->mid    = SVAL(inbuf, smb_mid);
365         req->vuid   = SVAL(inbuf, smb_uid);
366         req->tid    = SVAL(inbuf, smb_tid);
367         req->wct    = CVAL(inbuf, smb_wct);
368         req->vwv    = (uint16_t *)(inbuf+smb_vwv);
369         req->buflen = smb_buflen(inbuf);
370         req->buf    = (const uint8_t *)smb_buf(inbuf);
371         req->unread_bytes = unread_bytes;
372         req->encrypted = encrypted;
373         req->conn = conn_find(req->tid);
374         req->chain_fsp = NULL;
375         req->chain_outbuf = NULL;
376
377         /* Ensure we have at least wct words and 2 bytes of bcc. */
378         if (smb_size + req->wct*2 > req_size) {
379                 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
380                         (unsigned int)req->wct,
381                         (unsigned int)req_size));
382                 exit_server_cleanly("Invalid SMB request");
383         }
384         /* Ensure bcc is correct. */
385         if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
386                 DEBUG(0,("init_smb_request: invalid bcc number %u "
387                         "(wct = %u, size %u)\n",
388                         (unsigned int)req->buflen,
389                         (unsigned int)req->wct,
390                         (unsigned int)req_size));
391                 exit_server_cleanly("Invalid SMB request");
392         }
393         req->outbuf = NULL;
394 }
395
396 static void process_smb(struct smbd_server_connection *conn,
397                         uint8_t *inbuf, size_t nread, size_t unread_bytes,
398                         bool encrypted);
399
400 static void smbd_deferred_open_timer(struct event_context *ev,
401                                      struct timed_event *te,
402                                      struct timeval _tval,
403                                      void *private_data)
404 {
405         struct pending_message_list *msg = talloc_get_type(private_data,
406                                            struct pending_message_list);
407         TALLOC_CTX *mem_ctx = talloc_tos();
408         uint8_t *inbuf;
409
410         /* TODO: remove this hack */
411         message_dispatch(smbd_messaging_context());
412
413         inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
414                                          msg->buf.length);
415         if (inbuf == NULL) {
416                 exit_server("smbd_deferred_open_timer: talloc failed\n");
417                 return;
418         }
419
420         /* We leave this message on the queue so the open code can
421            know this is a retry. */
422         DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
423                 (unsigned int)SVAL(msg->buf.data,smb_mid)));
424
425         process_smb(smbd_server_conn, inbuf,
426                     msg->buf.length, 0,
427                     msg->encrypted);
428 }
429
430 /****************************************************************************
431  Function to push a message onto the tail of a linked list of smb messages ready
432  for processing.
433 ****************************************************************************/
434
435 static bool push_queued_message(struct smb_request *req,
436                                 struct timeval request_time,
437                                 struct timeval end_time,
438                                 char *private_data, size_t private_len)
439 {
440         int msg_len = smb_len(req->inbuf) + 4;
441         struct pending_message_list *msg;
442
443         msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
444
445         if(msg == NULL) {
446                 DEBUG(0,("push_message: malloc fail (1)\n"));
447                 return False;
448         }
449
450         msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
451         if(msg->buf.data == NULL) {
452                 DEBUG(0,("push_message: malloc fail (2)\n"));
453                 TALLOC_FREE(msg);
454                 return False;
455         }
456
457         msg->request_time = request_time;
458         msg->encrypted = req->encrypted;
459
460         if (private_data) {
461                 msg->private_data = data_blob_talloc(msg, private_data,
462                                                      private_len);
463                 if (msg->private_data.data == NULL) {
464                         DEBUG(0,("push_message: malloc fail (3)\n"));
465                         TALLOC_FREE(msg);
466                         return False;
467                 }
468         }
469
470         msg->te = event_add_timed(smbd_event_context(),
471                                   msg,
472                                   end_time,
473                                   smbd_deferred_open_timer,
474                                   msg);
475         if (!msg->te) {
476                 DEBUG(0,("push_message: event_add_timed failed\n"));
477                 TALLOC_FREE(msg);
478                 return false;
479         }
480
481         DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
482
483         DEBUG(10,("push_message: pushed message length %u on "
484                   "deferred_open_queue\n", (unsigned int)msg_len));
485
486         return True;
487 }
488
489 /****************************************************************************
490  Function to delete a sharing violation open message by mid.
491 ****************************************************************************/
492
493 void remove_deferred_open_smb_message(uint16 mid)
494 {
495         struct pending_message_list *pml;
496
497         for (pml = deferred_open_queue; pml; pml = pml->next) {
498                 if (mid == SVAL(pml->buf.data,smb_mid)) {
499                         DEBUG(10,("remove_sharing_violation_open_smb_message: "
500                                   "deleting mid %u len %u\n",
501                                   (unsigned int)mid,
502                                   (unsigned int)pml->buf.length ));
503                         DLIST_REMOVE(deferred_open_queue, pml);
504                         TALLOC_FREE(pml);
505                         return;
506                 }
507         }
508 }
509
510 /****************************************************************************
511  Move a sharing violation open retry message to the front of the list and
512  schedule it for immediate processing.
513 ****************************************************************************/
514
515 void schedule_deferred_open_smb_message(uint16 mid)
516 {
517         struct pending_message_list *pml;
518         int i = 0;
519
520         for (pml = deferred_open_queue; pml; pml = pml->next) {
521                 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
522
523                 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
524                         (unsigned int)msg_mid ));
525
526                 if (mid == msg_mid) {
527                         struct timed_event *te;
528
529                         DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
530                                 mid ));
531
532                         te = event_add_timed(smbd_event_context(),
533                                              pml,
534                                              timeval_zero(),
535                                              smbd_deferred_open_timer,
536                                              pml);
537                         if (!te) {
538                                 DEBUG(10,("schedule_deferred_open_smb_message: "
539                                           "event_add_timed() failed, skipping mid %u\n",
540                                           mid ));
541                         }
542
543                         TALLOC_FREE(pml->te);
544                         pml->te = te;
545                         DLIST_PROMOTE(deferred_open_queue, pml);
546                         return;
547                 }
548         }
549
550         DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
551                 mid ));
552 }
553
554 /****************************************************************************
555  Return true if this mid is on the deferred queue.
556 ****************************************************************************/
557
558 bool open_was_deferred(uint16 mid)
559 {
560         struct pending_message_list *pml;
561
562         for (pml = deferred_open_queue; pml; pml = pml->next) {
563                 if (SVAL(pml->buf.data,smb_mid) == mid) {
564                         return True;
565                 }
566         }
567         return False;
568 }
569
570 /****************************************************************************
571  Return the message queued by this mid.
572 ****************************************************************************/
573
574 struct pending_message_list *get_open_deferred_message(uint16 mid)
575 {
576         struct pending_message_list *pml;
577
578         for (pml = deferred_open_queue; pml; pml = pml->next) {
579                 if (SVAL(pml->buf.data,smb_mid) == mid) {
580                         return pml;
581                 }
582         }
583         return NULL;
584 }
585
586 /****************************************************************************
587  Function to push a deferred open smb message onto a linked list of local smb
588  messages ready for processing.
589 ****************************************************************************/
590
591 bool push_deferred_smb_message(struct smb_request *req,
592                                struct timeval request_time,
593                                struct timeval timeout,
594                                char *private_data, size_t priv_len)
595 {
596         struct timeval end_time;
597
598         if (req->unread_bytes) {
599                 DEBUG(0,("push_deferred_smb_message: logic error ! "
600                         "unread_bytes = %u\n",
601                         (unsigned int)req->unread_bytes ));
602                 smb_panic("push_deferred_smb_message: "
603                         "logic error unread_bytes != 0" );
604         }
605
606         end_time = timeval_sum(&request_time, &timeout);
607
608         DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
609                   "timeout time [%u.%06u]\n",
610                   (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
611                   (unsigned int)end_time.tv_sec,
612                   (unsigned int)end_time.tv_usec));
613
614         return push_queued_message(req, request_time, end_time,
615                                    private_data, priv_len);
616 }
617
618 struct idle_event {
619         struct timed_event *te;
620         struct timeval interval;
621         char *name;
622         bool (*handler)(const struct timeval *now, void *private_data);
623         void *private_data;
624 };
625
626 static void smbd_idle_event_handler(struct event_context *ctx,
627                                     struct timed_event *te,
628                                     struct timeval now,
629                                     void *private_data)
630 {
631         struct idle_event *event =
632                 talloc_get_type_abort(private_data, struct idle_event);
633
634         TALLOC_FREE(event->te);
635
636         DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
637                   event->name, event->te));
638
639         if (!event->handler(&now, event->private_data)) {
640                 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
641                           event->name, event->te));
642                 /* Don't repeat, delete ourselves */
643                 TALLOC_FREE(event);
644                 return;
645         }
646
647         DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
648                   event->name, event->te));
649
650         event->te = event_add_timed(ctx, event,
651                                     timeval_sum(&now, &event->interval),
652                                     smbd_idle_event_handler, event);
653
654         /* We can't do much but fail here. */
655         SMB_ASSERT(event->te != NULL);
656 }
657
658 struct idle_event *event_add_idle(struct event_context *event_ctx,
659                                   TALLOC_CTX *mem_ctx,
660                                   struct timeval interval,
661                                   const char *name,
662                                   bool (*handler)(const struct timeval *now,
663                                                   void *private_data),
664                                   void *private_data)
665 {
666         struct idle_event *result;
667         struct timeval now = timeval_current();
668
669         result = TALLOC_P(mem_ctx, struct idle_event);
670         if (result == NULL) {
671                 DEBUG(0, ("talloc failed\n"));
672                 return NULL;
673         }
674
675         result->interval = interval;
676         result->handler = handler;
677         result->private_data = private_data;
678
679         if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
680                 DEBUG(0, ("talloc failed\n"));
681                 TALLOC_FREE(result);
682                 return NULL;
683         }
684
685         result->te = event_add_timed(event_ctx, result,
686                                      timeval_sum(&now, &interval),
687                                      smbd_idle_event_handler, result);
688         if (result->te == NULL) {
689                 DEBUG(0, ("event_add_timed failed\n"));
690                 TALLOC_FREE(result);
691                 return NULL;
692         }
693
694         DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
695         return result;
696 }
697
698 /****************************************************************************
699  Do all async processing in here. This includes kernel oplock messages, change
700  notify events etc.
701 ****************************************************************************/
702
703 static void async_processing(fd_set *pfds)
704 {
705         DEBUG(10,("async_processing: Doing async processing.\n"));
706
707         process_aio_queue();
708
709         process_kernel_oplocks(smbd_messaging_context(), pfds);
710
711         /* Do the aio check again after receive_local_message as it does a
712            select and may have eaten our signal. */
713         /* Is this till true? -- vl */
714         process_aio_queue();
715
716         if (got_sig_term) {
717                 exit_server_cleanly("termination signal");
718         }
719
720         /* check for sighup processing */
721         if (reload_after_sighup) {
722                 change_to_root_user();
723                 DEBUG(1,("Reloading services after SIGHUP\n"));
724                 reload_services(False);
725                 reload_after_sighup = 0;
726         }
727 }
728
729 /****************************************************************************
730  Add a fd to the set we will be select(2)ing on.
731 ****************************************************************************/
732
733 static int select_on_fd(int fd, int maxfd, fd_set *fds)
734 {
735         if (fd != -1) {
736                 FD_SET(fd, fds);
737                 maxfd = MAX(maxfd, fd);
738         }
739
740         return maxfd;
741 }
742
743 /****************************************************************************
744   Do a select on an two fd's - with timeout. 
745
746   If a local udp message has been pushed onto the
747   queue (this can only happen during oplock break
748   processing) call async_processing()
749
750   If a pending smb message has been pushed onto the
751   queue (this can only happen during oplock break
752   processing) return this next.
753
754   If the first smbfd is ready then read an smb from it.
755   if the second (loopback UDP) fd is ready then read a message
756   from it and setup the buffer header to identify the length
757   and from address.
758   Returns False on timeout or error.
759   Else returns True.
760
761 The timeout is in milliseconds
762 ****************************************************************************/
763
764 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
765 {
766         fd_set r_fds, w_fds;
767         int selrtn;
768         struct timeval to;
769         int maxfd = 0;
770
771         to.tv_sec = SMBD_SELECT_TIMEOUT;
772         to.tv_usec = 0;
773
774         /*
775          * Note that this call must be before processing any SMB
776          * messages as we need to synchronously process any messages
777          * we may have sent to ourselves from the previous SMB.
778          */
779         message_dispatch(smbd_messaging_context());
780
781         /*
782          * Setup the select fd sets.
783          */
784
785         FD_ZERO(&r_fds);
786         FD_ZERO(&w_fds);
787
788         /*
789          * Ensure we process oplock break messages by preference.
790          * We have to do this before the select, after the select
791          * and if the select returns EINTR. This is due to the fact
792          * that the selects called from async_processing can eat an EINTR
793          * caused by a signal (we can't take the break message there).
794          * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
795          */
796
797         if (oplock_message_waiting(&r_fds)) {
798                 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
799                 async_processing(&r_fds);
800                 /*
801                  * After async processing we must go and do the select again, as
802                  * the state of the flag in fds for the server file descriptor is
803                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
804                  */
805                 return NT_STATUS_RETRY;
806         }
807
808         /*
809          * Are there any timed events waiting ? If so, ensure we don't
810          * select for longer than it would take to wait for them.
811          */
812
813         {
814                 struct timeval now;
815                 GetTimeOfDay(&now);
816
817                 event_add_to_select_args(smbd_event_context(), &now,
818                                          &r_fds, &w_fds, &to, &maxfd);
819         }
820
821         if (timeval_is_zero(&to)) {
822                 /* Process a timed event now... */
823                 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
824                         return NT_STATUS_RETRY;
825                 }
826         }
827         
828         {
829                 int sav;
830                 START_PROFILE(smbd_idle);
831
832                 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
833
834                 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
835                 sav = errno;
836
837                 END_PROFILE(smbd_idle);
838                 errno = sav;
839         }
840
841         if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
842                 return NT_STATUS_RETRY;
843         }
844
845         /* if we get EINTR then maybe we have received an oplock
846            signal - treat this as select returning 1. This is ugly, but
847            is the best we can do until the oplock code knows more about
848            signals */
849         if (selrtn == -1 && errno == EINTR) {
850                 async_processing(&r_fds);
851                 /*
852                  * After async processing we must go and do the select again, as
853                  * the state of the flag in fds for the server file descriptor is
854                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
855                  */
856                 return NT_STATUS_RETRY;
857         }
858
859         /* Check if error */
860         if (selrtn == -1) {
861                 /* something is wrong. Maybe the socket is dead? */
862                 return map_nt_error_from_unix(errno);
863         }
864
865         /* Did we timeout ? */
866         if (selrtn == 0) {
867                 return NT_STATUS_RETRY;
868         }
869
870         /*
871          * Ensure we process oplock break messages by preference.
872          * This is IMPORTANT ! Otherwise we can starve other processes
873          * sending us an oplock break message. JRA.
874          */
875
876         if (oplock_message_waiting(&r_fds)) {
877                 async_processing(&r_fds);
878                 /*
879                  * After async processing we must go and do the select again, as
880                  * the state of the flag in fds for the server file descriptor is
881                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
882                  */
883                 return NT_STATUS_RETRY;
884         }
885
886         /*
887          * We've just woken up from a protentially long select sleep.
888          * Ensure we process local messages as we need to synchronously
889          * process any messages from other smbd's to avoid file rename race
890          * conditions. This call is cheap if there are no messages waiting.
891          * JRA.
892          */
893         message_dispatch(smbd_messaging_context());
894
895         return NT_STATUS_OK;
896 }
897
898 /*
899  * Only allow 5 outstanding trans requests. We're allocating memory, so
900  * prevent a DoS.
901  */
902
903 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
904 {
905         int count = 0;
906         for (; list != NULL; list = list->next) {
907
908                 if (list->mid == mid) {
909                         return NT_STATUS_INVALID_PARAMETER;
910                 }
911
912                 count += 1;
913         }
914         if (count > 5) {
915                 return NT_STATUS_INSUFFICIENT_RESOURCES;
916         }
917
918         return NT_STATUS_OK;
919 }
920
921 /****************************************************************************
922  We're terminating and have closed all our files/connections etc.
923  If there are any pending local messages we need to respond to them
924  before termination so that other smbds don't think we just died whilst
925  holding oplocks.
926 ****************************************************************************/
927
928 void respond_to_all_remaining_local_messages(void)
929 {
930         /*
931          * Assert we have no exclusive open oplocks.
932          */
933
934         if(get_number_of_exclusive_open_oplocks()) {
935                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
936                         get_number_of_exclusive_open_oplocks() ));
937                 return;
938         }
939
940         process_kernel_oplocks(smbd_messaging_context(), NULL);
941
942         return;
943 }
944
945
946 /*
947 These flags determine some of the permissions required to do an operation 
948
949 Note that I don't set NEED_WRITE on some write operations because they
950 are used by some brain-dead clients when printing, and I don't want to
951 force write permissions on print services.
952 */
953 #define AS_USER (1<<0)
954 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
955 #define TIME_INIT (1<<2)
956 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
957 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
958 #define DO_CHDIR (1<<6)
959
960 /* 
961    define a list of possible SMB messages and their corresponding
962    functions. Any message that has a NULL function is unimplemented -
963    please feel free to contribute implementations!
964 */
965 static const struct smb_message_struct {
966         const char *name;
967         void (*fn)(struct smb_request *req);
968         int flags;
969 } smb_messages[256] = {
970
971 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
972 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
973 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
974 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
975 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
976 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
977 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
978 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
979 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
980 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
981 /* 0x0a */ { "SMBread",reply_read,AS_USER},
982 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
983 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
984 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
985 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
986 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
987 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
988 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
989 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
990 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
991 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
992 /* 0x15 */ { NULL, NULL, 0 },
993 /* 0x16 */ { NULL, NULL, 0 },
994 /* 0x17 */ { NULL, NULL, 0 },
995 /* 0x18 */ { NULL, NULL, 0 },
996 /* 0x19 */ { NULL, NULL, 0 },
997 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
998 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
999 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
1000 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
1001 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
1002 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
1003 /* 0x20 */ { "SMBwritec", NULL,0},
1004 /* 0x21 */ { NULL, NULL, 0 },
1005 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
1006 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
1007 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
1008 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
1009 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
1010 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
1011 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
1012 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
1013 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
1014 /* 0x2b */ { "SMBecho",reply_echo,0},
1015 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
1016 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
1017 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
1018 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
1019 /* 0x30 */ { NULL, NULL, 0 },
1020 /* 0x31 */ { NULL, NULL, 0 },
1021 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
1022 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
1023 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
1024 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
1025 /* 0x36 */ { NULL, NULL, 0 },
1026 /* 0x37 */ { NULL, NULL, 0 },
1027 /* 0x38 */ { NULL, NULL, 0 },
1028 /* 0x39 */ { NULL, NULL, 0 },
1029 /* 0x3a */ { NULL, NULL, 0 },
1030 /* 0x3b */ { NULL, NULL, 0 },
1031 /* 0x3c */ { NULL, NULL, 0 },
1032 /* 0x3d */ { NULL, NULL, 0 },
1033 /* 0x3e */ { NULL, NULL, 0 },
1034 /* 0x3f */ { NULL, NULL, 0 },
1035 /* 0x40 */ { NULL, NULL, 0 },
1036 /* 0x41 */ { NULL, NULL, 0 },
1037 /* 0x42 */ { NULL, NULL, 0 },
1038 /* 0x43 */ { NULL, NULL, 0 },
1039 /* 0x44 */ { NULL, NULL, 0 },
1040 /* 0x45 */ { NULL, NULL, 0 },
1041 /* 0x46 */ { NULL, NULL, 0 },
1042 /* 0x47 */ { NULL, NULL, 0 },
1043 /* 0x48 */ { NULL, NULL, 0 },
1044 /* 0x49 */ { NULL, NULL, 0 },
1045 /* 0x4a */ { NULL, NULL, 0 },
1046 /* 0x4b */ { NULL, NULL, 0 },
1047 /* 0x4c */ { NULL, NULL, 0 },
1048 /* 0x4d */ { NULL, NULL, 0 },
1049 /* 0x4e */ { NULL, NULL, 0 },
1050 /* 0x4f */ { NULL, NULL, 0 },
1051 /* 0x50 */ { NULL, NULL, 0 },
1052 /* 0x51 */ { NULL, NULL, 0 },
1053 /* 0x52 */ { NULL, NULL, 0 },
1054 /* 0x53 */ { NULL, NULL, 0 },
1055 /* 0x54 */ { NULL, NULL, 0 },
1056 /* 0x55 */ { NULL, NULL, 0 },
1057 /* 0x56 */ { NULL, NULL, 0 },
1058 /* 0x57 */ { NULL, NULL, 0 },
1059 /* 0x58 */ { NULL, NULL, 0 },
1060 /* 0x59 */ { NULL, NULL, 0 },
1061 /* 0x5a */ { NULL, NULL, 0 },
1062 /* 0x5b */ { NULL, NULL, 0 },
1063 /* 0x5c */ { NULL, NULL, 0 },
1064 /* 0x5d */ { NULL, NULL, 0 },
1065 /* 0x5e */ { NULL, NULL, 0 },
1066 /* 0x5f */ { NULL, NULL, 0 },
1067 /* 0x60 */ { NULL, NULL, 0 },
1068 /* 0x61 */ { NULL, NULL, 0 },
1069 /* 0x62 */ { NULL, NULL, 0 },
1070 /* 0x63 */ { NULL, NULL, 0 },
1071 /* 0x64 */ { NULL, NULL, 0 },
1072 /* 0x65 */ { NULL, NULL, 0 },
1073 /* 0x66 */ { NULL, NULL, 0 },
1074 /* 0x67 */ { NULL, NULL, 0 },
1075 /* 0x68 */ { NULL, NULL, 0 },
1076 /* 0x69 */ { NULL, NULL, 0 },
1077 /* 0x6a */ { NULL, NULL, 0 },
1078 /* 0x6b */ { NULL, NULL, 0 },
1079 /* 0x6c */ { NULL, NULL, 0 },
1080 /* 0x6d */ { NULL, NULL, 0 },
1081 /* 0x6e */ { NULL, NULL, 0 },
1082 /* 0x6f */ { NULL, NULL, 0 },
1083 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1084 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1085 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1086 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1087 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1088 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1089 /* 0x76 */ { NULL, NULL, 0 },
1090 /* 0x77 */ { NULL, NULL, 0 },
1091 /* 0x78 */ { NULL, NULL, 0 },
1092 /* 0x79 */ { NULL, NULL, 0 },
1093 /* 0x7a */ { NULL, NULL, 0 },
1094 /* 0x7b */ { NULL, NULL, 0 },
1095 /* 0x7c */ { NULL, NULL, 0 },
1096 /* 0x7d */ { NULL, NULL, 0 },
1097 /* 0x7e */ { NULL, NULL, 0 },
1098 /* 0x7f */ { NULL, NULL, 0 },
1099 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1100 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1101 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1102 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1103 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1104 /* 0x85 */ { NULL, NULL, 0 },
1105 /* 0x86 */ { NULL, NULL, 0 },
1106 /* 0x87 */ { NULL, NULL, 0 },
1107 /* 0x88 */ { NULL, NULL, 0 },
1108 /* 0x89 */ { NULL, NULL, 0 },
1109 /* 0x8a */ { NULL, NULL, 0 },
1110 /* 0x8b */ { NULL, NULL, 0 },
1111 /* 0x8c */ { NULL, NULL, 0 },
1112 /* 0x8d */ { NULL, NULL, 0 },
1113 /* 0x8e */ { NULL, NULL, 0 },
1114 /* 0x8f */ { NULL, NULL, 0 },
1115 /* 0x90 */ { NULL, NULL, 0 },
1116 /* 0x91 */ { NULL, NULL, 0 },
1117 /* 0x92 */ { NULL, NULL, 0 },
1118 /* 0x93 */ { NULL, NULL, 0 },
1119 /* 0x94 */ { NULL, NULL, 0 },
1120 /* 0x95 */ { NULL, NULL, 0 },
1121 /* 0x96 */ { NULL, NULL, 0 },
1122 /* 0x97 */ { NULL, NULL, 0 },
1123 /* 0x98 */ { NULL, NULL, 0 },
1124 /* 0x99 */ { NULL, NULL, 0 },
1125 /* 0x9a */ { NULL, NULL, 0 },
1126 /* 0x9b */ { NULL, NULL, 0 },
1127 /* 0x9c */ { NULL, NULL, 0 },
1128 /* 0x9d */ { NULL, NULL, 0 },
1129 /* 0x9e */ { NULL, NULL, 0 },
1130 /* 0x9f */ { NULL, NULL, 0 },
1131 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1132 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1133 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1134 /* 0xa3 */ { NULL, NULL, 0 },
1135 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1136 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1137 /* 0xa6 */ { NULL, NULL, 0 },
1138 /* 0xa7 */ { NULL, NULL, 0 },
1139 /* 0xa8 */ { NULL, NULL, 0 },
1140 /* 0xa9 */ { NULL, NULL, 0 },
1141 /* 0xaa */ { NULL, NULL, 0 },
1142 /* 0xab */ { NULL, NULL, 0 },
1143 /* 0xac */ { NULL, NULL, 0 },
1144 /* 0xad */ { NULL, NULL, 0 },
1145 /* 0xae */ { NULL, NULL, 0 },
1146 /* 0xaf */ { NULL, NULL, 0 },
1147 /* 0xb0 */ { NULL, NULL, 0 },
1148 /* 0xb1 */ { NULL, NULL, 0 },
1149 /* 0xb2 */ { NULL, NULL, 0 },
1150 /* 0xb3 */ { NULL, NULL, 0 },
1151 /* 0xb4 */ { NULL, NULL, 0 },
1152 /* 0xb5 */ { NULL, NULL, 0 },
1153 /* 0xb6 */ { NULL, NULL, 0 },
1154 /* 0xb7 */ { NULL, NULL, 0 },
1155 /* 0xb8 */ { NULL, NULL, 0 },
1156 /* 0xb9 */ { NULL, NULL, 0 },
1157 /* 0xba */ { NULL, NULL, 0 },
1158 /* 0xbb */ { NULL, NULL, 0 },
1159 /* 0xbc */ { NULL, NULL, 0 },
1160 /* 0xbd */ { NULL, NULL, 0 },
1161 /* 0xbe */ { NULL, NULL, 0 },
1162 /* 0xbf */ { NULL, NULL, 0 },
1163 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1164 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1165 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1166 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1167 /* 0xc4 */ { NULL, NULL, 0 },
1168 /* 0xc5 */ { NULL, NULL, 0 },
1169 /* 0xc6 */ { NULL, NULL, 0 },
1170 /* 0xc7 */ { NULL, NULL, 0 },
1171 /* 0xc8 */ { NULL, NULL, 0 },
1172 /* 0xc9 */ { NULL, NULL, 0 },
1173 /* 0xca */ { NULL, NULL, 0 },
1174 /* 0xcb */ { NULL, NULL, 0 },
1175 /* 0xcc */ { NULL, NULL, 0 },
1176 /* 0xcd */ { NULL, NULL, 0 },
1177 /* 0xce */ { NULL, NULL, 0 },
1178 /* 0xcf */ { NULL, NULL, 0 },
1179 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1180 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1181 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1182 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1183 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1184 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1185 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1186 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1187 /* 0xd8 */ { NULL, NULL, 0 },
1188 /* 0xd9 */ { NULL, NULL, 0 },
1189 /* 0xda */ { NULL, NULL, 0 },
1190 /* 0xdb */ { NULL, NULL, 0 },
1191 /* 0xdc */ { NULL, NULL, 0 },
1192 /* 0xdd */ { NULL, NULL, 0 },
1193 /* 0xde */ { NULL, NULL, 0 },
1194 /* 0xdf */ { NULL, NULL, 0 },
1195 /* 0xe0 */ { NULL, NULL, 0 },
1196 /* 0xe1 */ { NULL, NULL, 0 },
1197 /* 0xe2 */ { NULL, NULL, 0 },
1198 /* 0xe3 */ { NULL, NULL, 0 },
1199 /* 0xe4 */ { NULL, NULL, 0 },
1200 /* 0xe5 */ { NULL, NULL, 0 },
1201 /* 0xe6 */ { NULL, NULL, 0 },
1202 /* 0xe7 */ { NULL, NULL, 0 },
1203 /* 0xe8 */ { NULL, NULL, 0 },
1204 /* 0xe9 */ { NULL, NULL, 0 },
1205 /* 0xea */ { NULL, NULL, 0 },
1206 /* 0xeb */ { NULL, NULL, 0 },
1207 /* 0xec */ { NULL, NULL, 0 },
1208 /* 0xed */ { NULL, NULL, 0 },
1209 /* 0xee */ { NULL, NULL, 0 },
1210 /* 0xef */ { NULL, NULL, 0 },
1211 /* 0xf0 */ { NULL, NULL, 0 },
1212 /* 0xf1 */ { NULL, NULL, 0 },
1213 /* 0xf2 */ { NULL, NULL, 0 },
1214 /* 0xf3 */ { NULL, NULL, 0 },
1215 /* 0xf4 */ { NULL, NULL, 0 },
1216 /* 0xf5 */ { NULL, NULL, 0 },
1217 /* 0xf6 */ { NULL, NULL, 0 },
1218 /* 0xf7 */ { NULL, NULL, 0 },
1219 /* 0xf8 */ { NULL, NULL, 0 },
1220 /* 0xf9 */ { NULL, NULL, 0 },
1221 /* 0xfa */ { NULL, NULL, 0 },
1222 /* 0xfb */ { NULL, NULL, 0 },
1223 /* 0xfc */ { NULL, NULL, 0 },
1224 /* 0xfd */ { NULL, NULL, 0 },
1225 /* 0xfe */ { NULL, NULL, 0 },
1226 /* 0xff */ { NULL, NULL, 0 }
1227
1228 };
1229
1230 /*******************************************************************
1231  allocate and initialize a reply packet
1232 ********************************************************************/
1233
1234 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1235                           const char *inbuf, char **outbuf, uint8_t num_words,
1236                           uint32_t num_bytes)
1237 {
1238         /*
1239          * Protect against integer wrap
1240          */
1241         if ((num_bytes > 0xffffff)
1242             || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1243                 char *msg;
1244                 if (asprintf(&msg, "num_bytes too large: %u",
1245                              (unsigned)num_bytes) == -1) {
1246                         msg = CONST_DISCARD(char *, "num_bytes too large");
1247                 }
1248                 smb_panic(msg);
1249         }
1250
1251         *outbuf = TALLOC_ARRAY(mem_ctx, char,
1252                                smb_size + num_words*2 + num_bytes);
1253         if (*outbuf == NULL) {
1254                 return false;
1255         }
1256
1257         construct_reply_common(req, inbuf, *outbuf);
1258         srv_set_message(*outbuf, num_words, num_bytes, false);
1259         /*
1260          * Zero out the word area, the caller has to take care of the bcc area
1261          * himself
1262          */
1263         if (num_words != 0) {
1264                 memset(*outbuf + smb_vwv0, 0, num_words*2);
1265         }
1266
1267         return true;
1268 }
1269
1270 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1271 {
1272         char *outbuf;
1273         if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1274                            num_bytes)) {
1275                 smb_panic("could not allocate output buffer\n");
1276         }
1277         req->outbuf = (uint8_t *)outbuf;
1278 }
1279
1280
1281 /*******************************************************************
1282  Dump a packet to a file.
1283 ********************************************************************/
1284
1285 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1286 {
1287         int fd, i;
1288         char *fname = NULL;
1289         if (DEBUGLEVEL < 50) {
1290                 return;
1291         }
1292
1293         if (len < 4) len = smb_len(data)+4;
1294         for (i=1;i<100;i++) {
1295                 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1296                              type ? "req" : "resp") == -1) {
1297                         return;
1298                 }
1299                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1300                 if (fd != -1 || errno != EEXIST) break;
1301         }
1302         if (fd != -1) {
1303                 ssize_t ret = write(fd, data, len);
1304                 if (ret != len)
1305                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1306                 close(fd);
1307                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1308         }
1309         SAFE_FREE(fname);
1310 }
1311
1312 /****************************************************************************
1313  Prepare everything for calling the actual request function, and potentially
1314  call the request function via the "new" interface.
1315
1316  Return False if the "legacy" function needs to be called, everything is
1317  prepared.
1318
1319  Return True if we're done.
1320
1321  I know this API sucks, but it is the one with the least code change I could
1322  find.
1323 ****************************************************************************/
1324
1325 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1326 {
1327         int flags;
1328         uint16 session_tag;
1329         connection_struct *conn = NULL;
1330
1331         errno = 0;
1332
1333         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1334          * so subtract 4 from it. */
1335         if (!valid_smb_header(req->inbuf)
1336             || (size < (smb_size - 4))) {
1337                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1338                          smb_len(req->inbuf)));
1339                 exit_server_cleanly("Non-SMB packet");
1340         }
1341
1342         if (smb_messages[type].fn == NULL) {
1343                 DEBUG(0,("Unknown message type %d!\n",type));
1344                 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1345                 reply_unknown_new(req, type);
1346                 return NULL;
1347         }
1348
1349         flags = smb_messages[type].flags;
1350
1351         /* In share mode security we must ignore the vuid. */
1352         session_tag = (lp_security() == SEC_SHARE)
1353                 ? UID_FIELD_INVALID : req->vuid;
1354         conn = req->conn;
1355
1356         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1357                  (int)sys_getpid(), (unsigned long)conn));
1358
1359         smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1360
1361         /* Ensure this value is replaced in the incoming packet. */
1362         SSVAL(req->inbuf,smb_uid,session_tag);
1363
1364         /*
1365          * Ensure the correct username is in current_user_info.  This is a
1366          * really ugly bugfix for problems with multiple session_setup_and_X's
1367          * being done and allowing %U and %G substitutions to work correctly.
1368          * There is a reason this code is done here, don't move it unless you
1369          * know what you're doing... :-).
1370          * JRA.
1371          */
1372
1373         if (session_tag != last_session_tag) {
1374                 user_struct *vuser = NULL;
1375
1376                 last_session_tag = session_tag;
1377                 if(session_tag != UID_FIELD_INVALID) {
1378                         vuser = get_valid_user_struct(session_tag);
1379                         if (vuser) {
1380                                 set_current_user_info(
1381                                         vuser->server_info->sanitized_username,
1382                                         vuser->server_info->unix_name,
1383                                         pdb_get_fullname(vuser->server_info
1384                                                          ->sam_account),
1385                                         pdb_get_domain(vuser->server_info
1386                                                        ->sam_account));
1387                         }
1388                 }
1389         }
1390
1391         /* Does this call need to be run as the connected user? */
1392         if (flags & AS_USER) {
1393
1394                 /* Does this call need a valid tree connection? */
1395                 if (!conn) {
1396                         /*
1397                          * Amazingly, the error code depends on the command
1398                          * (from Samba4).
1399                          */
1400                         if (type == SMBntcreateX) {
1401                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1402                         } else {
1403                                 reply_doserror(req, ERRSRV, ERRinvnid);
1404                         }
1405                         return NULL;
1406                 }
1407
1408                 if (!change_to_user(conn,session_tag)) {
1409                         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1410                         remove_deferred_open_smb_message(req->mid);
1411                         return conn;
1412                 }
1413
1414                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1415
1416                 /* Does it need write permission? */
1417                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1418                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1419                         return conn;
1420                 }
1421
1422                 /* IPC services are limited */
1423                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1424                         reply_doserror(req, ERRSRV,ERRaccess);
1425                         return conn;
1426                 }
1427         } else {
1428                 /* This call needs to be run as root */
1429                 change_to_root_user();
1430         }
1431
1432         /* load service specific parameters */
1433         if (conn) {
1434                 if (req->encrypted) {
1435                         conn->encrypted_tid = true;
1436                         /* encrypted required from now on. */
1437                         conn->encrypt_level = Required;
1438                 } else if (ENCRYPTION_REQUIRED(conn)) {
1439                         if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1440                                 exit_server_cleanly("encryption required "
1441                                         "on connection");
1442                                 return conn;
1443                         }
1444                 }
1445
1446                 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1447                                          (flags & (AS_USER|DO_CHDIR)
1448                                           ?True:False))) {
1449                         reply_doserror(req, ERRSRV, ERRaccess);
1450                         return conn;
1451                 }
1452                 conn->num_smb_operations++;
1453         }
1454
1455         /* does this protocol need to be run as guest? */
1456         if ((flags & AS_GUEST)
1457             && (!change_to_guest() ||
1458                 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1459                               lp_hostsdeny(-1)))) {
1460                 reply_doserror(req, ERRSRV, ERRaccess);
1461                 return conn;
1462         }
1463
1464         smb_messages[type].fn(req);
1465         return req->conn;
1466 }
1467
1468 /****************************************************************************
1469  Construct a reply to the incoming packet.
1470 ****************************************************************************/
1471
1472 static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
1473 {
1474         connection_struct *conn;
1475         struct smb_request *req;
1476
1477         chain_size = 0;
1478
1479         if (!(req = talloc(talloc_tos(), struct smb_request))) {
1480                 smb_panic("could not allocate smb_request");
1481         }
1482         init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1483         req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
1484
1485         conn = switch_message(req->cmd, req, size);
1486
1487         if (req->unread_bytes) {
1488                 /* writeX failed. drain socket. */
1489                 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1490                                 req->unread_bytes) {
1491                         smb_panic("failed to drain pending bytes");
1492                 }
1493                 req->unread_bytes = 0;
1494         }
1495
1496         if (req->outbuf == NULL) {
1497                 return;
1498         }
1499
1500         if (CVAL(req->outbuf,0) == 0) {
1501                 show_msg((char *)req->outbuf);
1502         }
1503
1504         if (!srv_send_smb(smbd_server_fd(),
1505                         (char *)req->outbuf,
1506                         IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
1507                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1508         }
1509
1510         TALLOC_FREE(req);
1511
1512         return;
1513 }
1514
1515 /****************************************************************************
1516  Process an smb from the client
1517 ****************************************************************************/
1518
1519 static void process_smb(struct smbd_server_connection *conn,
1520                         uint8_t *inbuf, size_t nread, size_t unread_bytes,
1521                         bool encrypted)
1522 {
1523         int msg_type = CVAL(inbuf,0);
1524
1525         DO_PROFILE_INC(smb_count);
1526
1527         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1528                     smb_len(inbuf) ) );
1529         DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1530                                 (int)nread,
1531                                 (unsigned int)unread_bytes ));
1532
1533         if (msg_type != 0) {
1534                 /*
1535                  * NetBIOS session request, keepalive, etc.
1536                  */
1537                 reply_special((char *)inbuf);
1538                 goto done;
1539         }
1540
1541         show_msg((char *)inbuf);
1542
1543         construct_reply((char *)inbuf,nread,unread_bytes,encrypted);
1544
1545         trans_num++;
1546
1547 done:
1548         conn->num_requests++;
1549
1550         /* The timeout_processing function isn't run nearly
1551            often enough to implement 'max log size' without
1552            overrunning the size of the file by many megabytes.
1553            This is especially true if we are running at debug
1554            level 10.  Checking every 50 SMBs is a nice
1555            tradeoff of performance vs log file size overrun. */
1556
1557         if ((conn->num_requests % 50) == 0 &&
1558             need_to_check_log_size()) {
1559                 change_to_root_user();
1560                 check_log_size();
1561         }
1562 }
1563
1564 /****************************************************************************
1565  Return a string containing the function name of a SMB command.
1566 ****************************************************************************/
1567
1568 const char *smb_fn_name(int type)
1569 {
1570         const char *unknown_name = "SMBunknown";
1571
1572         if (smb_messages[type].name == NULL)
1573                 return(unknown_name);
1574
1575         return(smb_messages[type].name);
1576 }
1577
1578 /****************************************************************************
1579  Helper functions for contruct_reply.
1580 ****************************************************************************/
1581
1582 void add_to_common_flags2(uint32 v)
1583 {
1584         common_flags2 |= v;
1585 }
1586
1587 void remove_from_common_flags2(uint32 v)
1588 {
1589         common_flags2 &= ~v;
1590 }
1591
1592 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1593                                    char *outbuf)
1594 {
1595         srv_set_message(outbuf,0,0,false);
1596         
1597         SCVAL(outbuf, smb_com, req->cmd);
1598         SIVAL(outbuf,smb_rcls,0);
1599         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1600         SSVAL(outbuf,smb_flg2,
1601                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1602                 common_flags2);
1603         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1604
1605         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1606         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1607         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1608         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1609 }
1610
1611 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1612 {
1613         construct_reply_common(req, (char *)req->inbuf, outbuf);
1614 }
1615
1616 /*
1617  * How many bytes have we already accumulated up to the current wct field
1618  * offset?
1619  */
1620
1621 size_t req_wct_ofs(struct smb_request *req)
1622 {
1623         size_t buf_size;
1624
1625         if (req->chain_outbuf == NULL) {
1626                 return smb_wct - 4;
1627         }
1628         buf_size = talloc_get_size(req->chain_outbuf);
1629         if ((buf_size % 4) != 0) {
1630                 buf_size += (4 - (buf_size % 4));
1631         }
1632         return buf_size - 4;
1633 }
1634
1635 /*
1636  * Hack around reply_nterror & friends not being aware of chained requests,
1637  * generating illegal (i.e. wct==0) chain replies.
1638  */
1639
1640 static void fixup_chain_error_packet(struct smb_request *req)
1641 {
1642         uint8_t *outbuf = req->outbuf;
1643         req->outbuf = NULL;
1644         reply_outbuf(req, 2, 0);
1645         memcpy(req->outbuf, outbuf, smb_wct);
1646         TALLOC_FREE(outbuf);
1647         SCVAL(req->outbuf, smb_vwv0, 0xff);
1648 }
1649
1650 /****************************************************************************
1651  Construct a chained reply and add it to the already made reply
1652 ****************************************************************************/
1653
1654 void chain_reply(struct smb_request *req)
1655 {
1656         size_t smblen = smb_len(req->inbuf);
1657         size_t already_used, length_needed;
1658         uint8_t chain_cmd;
1659         uint32_t chain_offset;  /* uint32_t to avoid overflow */
1660
1661         uint8_t wct;
1662         uint16_t *vwv;
1663         uint16_t buflen;
1664         uint8_t *buf;
1665
1666         if (IVAL(req->outbuf, smb_rcls) != 0) {
1667                 fixup_chain_error_packet(req);
1668         }
1669
1670         /*
1671          * Any of the AndX requests and replies have at least a wct of
1672          * 2. vwv[0] is the next command, vwv[1] is the offset from the
1673          * beginning of the SMB header to the next wct field.
1674          *
1675          * None of the AndX requests put anything valuable in vwv[0] and [1],
1676          * so we can overwrite it here to form the chain.
1677          */
1678
1679         if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1680                 goto error;
1681         }
1682
1683         /*
1684          * Here we assume that this is the end of the chain. For that we need
1685          * to set "next command" to 0xff and the offset to 0. If we later find
1686          * more commands in the chain, this will be overwritten again.
1687          */
1688
1689         SCVAL(req->outbuf, smb_vwv0, 0xff);
1690         SCVAL(req->outbuf, smb_vwv0+1, 0);
1691         SSVAL(req->outbuf, smb_vwv1, 0);
1692
1693         if (req->chain_outbuf == NULL) {
1694                 /*
1695                  * In req->chain_outbuf we collect all the replies. Start the
1696                  * chain by copying in the first reply.
1697                  */
1698                 req->chain_outbuf = req->outbuf;
1699                 req->outbuf = NULL;
1700         } else {
1701                 if (!smb_splice_chain(&req->chain_outbuf,
1702                                       CVAL(req->outbuf, smb_com),
1703                                       CVAL(req->outbuf, smb_wct),
1704                                       (uint16_t *)(req->outbuf + smb_vwv),
1705                                       0, smb_buflen(req->outbuf),
1706                                       (uint8_t *)smb_buf(req->outbuf))) {
1707                         goto error;
1708                 }
1709                 TALLOC_FREE(req->outbuf);
1710         }
1711
1712         /*
1713          * We use the old request's vwv field to grab the next chained command
1714          * and offset into the chained fields.
1715          */
1716
1717         chain_cmd = CVAL(req->vwv+0, 0);
1718         chain_offset = SVAL(req->vwv+1, 0);
1719
1720         if (chain_cmd == 0xff) {
1721                 /*
1722                  * End of chain, no more requests from the client. So ship the
1723                  * replies.
1724                  */
1725                 smb_setlen((char *)(req->chain_outbuf),
1726                            talloc_get_size(req->chain_outbuf) - 4);
1727                 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1728                                   IS_CONN_ENCRYPTED(req->conn)
1729                                   ||req->encrypted)) {
1730                         exit_server_cleanly("chain_reply: srv_send_smb "
1731                                             "failed.");
1732                 }
1733                 return;
1734         }
1735
1736         /*
1737          * Check if the client tries to fool us. The request so far uses the
1738          * space to the end of the byte buffer in the request just
1739          * processed. The chain_offset can't point into that area. If that was
1740          * the case, we could end up with an endless processing of the chain,
1741          * we would always handle the same request.
1742          */
1743
1744         already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1745         if (chain_offset < already_used) {
1746                 goto error;
1747         }
1748
1749         /*
1750          * Next check: Make sure the chain offset does not point beyond the
1751          * overall smb request length.
1752          */
1753
1754         length_needed = chain_offset+1; /* wct */
1755         if (length_needed > smblen) {
1756                 goto error;
1757         }
1758
1759         /*
1760          * Now comes the pointer magic. Goal here is to set up req->vwv and
1761          * req->buf correctly again to be able to call the subsequent
1762          * switch_message(). The chain offset (the former vwv[1]) points at
1763          * the new wct field.
1764          */
1765
1766         wct = CVAL(smb_base(req->inbuf), chain_offset);
1767
1768         /*
1769          * Next consistency check: Make the new vwv array fits in the overall
1770          * smb request.
1771          */
1772
1773         length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1774         if (length_needed > smblen) {
1775                 goto error;
1776         }
1777         vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1778
1779         /*
1780          * Now grab the new byte buffer....
1781          */
1782
1783         buflen = SVAL(vwv+wct, 0);
1784
1785         /*
1786          * .. and check that it fits.
1787          */
1788
1789         length_needed += buflen;
1790         if (length_needed > smblen) {
1791                 goto error;
1792         }
1793         buf = (uint8_t *)(vwv+wct+1);
1794
1795         req->cmd = chain_cmd;
1796         req->wct = wct;
1797         req->vwv = vwv;
1798         req->buflen = buflen;
1799         req->buf = buf;
1800
1801         switch_message(chain_cmd, req, smblen);
1802
1803         if (req->outbuf == NULL) {
1804                 /*
1805                  * This happens if the chained command has suspended itself or
1806                  * if it has called srv_send_smb() itself.
1807                  */
1808                 return;
1809         }
1810
1811         /*
1812          * We end up here if the chained command was not itself chained or
1813          * suspended, but for example a close() command. We now need to splice
1814          * the chained commands' outbuf into the already built up chain_outbuf
1815          * and ship the result.
1816          */
1817         goto done;
1818
1819  error:
1820         /*
1821          * We end up here if there's any error in the chain syntax. Report a
1822          * DOS error, just like Windows does.
1823          */
1824         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1825         fixup_chain_error_packet(req);
1826
1827  done:
1828         if (!smb_splice_chain(&req->chain_outbuf,
1829                               CVAL(req->outbuf, smb_com),
1830                               CVAL(req->outbuf, smb_wct),
1831                               (uint16_t *)(req->outbuf + smb_vwv),
1832                               0, smb_buflen(req->outbuf),
1833                               (uint8_t *)smb_buf(req->outbuf))) {
1834                 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1835         }
1836         TALLOC_FREE(req->outbuf);
1837
1838         smb_setlen((char *)(req->chain_outbuf),
1839                    talloc_get_size(req->chain_outbuf) - 4);
1840
1841         show_msg((char *)(req->chain_outbuf));
1842
1843         if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1844                           IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) {
1845                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1846         }
1847 }
1848
1849 /****************************************************************************
1850  Check if services need reloading.
1851 ****************************************************************************/
1852
1853 void check_reload(time_t t)
1854 {
1855         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1856
1857         if(last_smb_conf_reload_time == 0) {
1858                 last_smb_conf_reload_time = t;
1859                 /* Our printing subsystem might not be ready at smbd start up.
1860                    Then no printer is available till the first printers check
1861                    is performed.  A lower initial interval circumvents this. */
1862                 if ( printcap_cache_time > 60 )
1863                         last_printer_reload_time = t - printcap_cache_time + 60;
1864                 else
1865                         last_printer_reload_time = t;
1866         }
1867
1868         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1869                 /* randomize over 60 second the printcap reload to avoid all
1870                  * process hitting cupsd at the same time */
1871                 int time_range = 60;
1872
1873                 last_printer_reload_time += random() % time_range;
1874                 mypid = getpid();
1875         }
1876
1877         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1878                 reload_services(True);
1879                 reload_after_sighup = False;
1880                 last_smb_conf_reload_time = t;
1881         }
1882
1883         /* 'printcap cache time = 0' disable the feature */
1884         
1885         if ( printcap_cache_time != 0 )
1886         { 
1887                 /* see if it's time to reload or if the clock has been set back */
1888                 
1889                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1890                         || (t-last_printer_reload_time  < 0) ) 
1891                 {
1892                         DEBUG( 3,( "Printcap cache time expired.\n"));
1893                         reload_printers();
1894                         last_printer_reload_time = t;
1895                 }
1896         }
1897 }
1898
1899 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1900 {
1901         /* TODO: make write nonblocking */
1902 }
1903
1904 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1905 {
1906         uint8_t *inbuf = NULL;
1907         size_t inbuf_len = 0;
1908         size_t unread_bytes = 0;
1909         bool encrypted = false;
1910         TALLOC_CTX *mem_ctx = talloc_tos();
1911         NTSTATUS status;
1912
1913         /* TODO: remove this hack */
1914         message_dispatch(smbd_messaging_context());
1915
1916         /* TODO: make this completely nonblocking */
1917
1918         status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1919                                     (char **)(void *)&inbuf,
1920                                     0, /* timeout */
1921                                     &unread_bytes,
1922                                     &encrypted,
1923                                     &inbuf_len);
1924         if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1925                 goto process;
1926         }
1927         if (NT_STATUS_IS_ERR(status)) {
1928                 exit_server_cleanly("failed to receive smb request");
1929         }
1930         if (!NT_STATUS_IS_OK(status)) {
1931                 return;
1932         }
1933
1934 process:
1935         process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted);
1936 }
1937
1938 static void smbd_server_connection_handler(struct event_context *ev,
1939                                            struct fd_event *fde,
1940                                            uint16_t flags,
1941                                            void *private_data)
1942 {
1943         struct smbd_server_connection *conn = talloc_get_type(private_data,
1944                                               struct smbd_server_connection);
1945
1946         if (flags & EVENT_FD_WRITE) {
1947                 smbd_server_connection_write_handler(conn);
1948         } else if (flags & EVENT_FD_READ) {
1949                 smbd_server_connection_read_handler(conn);
1950         }
1951 }
1952
1953 /****************************************************************************
1954  Process commands from the client
1955 ****************************************************************************/
1956
1957 void smbd_process(void)
1958 {
1959         /*
1960          * Before the first packet, check the global hosts allow/ hosts deny
1961          * parameters before doing any parsing of packets passed to us by the
1962          * client. This prevents attacks on our parsing code from hosts not in
1963          * the hosts allow list.
1964          */
1965
1966         if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1967                           lp_hostsdeny(-1))) {
1968                 char addr[INET6_ADDRSTRLEN];
1969
1970                 /*
1971                  * send a negative session response "not listening on calling
1972                  * name"
1973                  */
1974                 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1975                 DEBUG( 1, ("Connection denied from %s\n",
1976                            client_addr(get_client_fd(),addr,sizeof(addr)) ) );
1977                 (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
1978                 exit_server_cleanly("connection denied");
1979         }
1980
1981         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1982
1983         smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
1984         if (!smbd_server_conn) {
1985                 exit_server("failed to create smbd_server_connection");
1986         }
1987         smbd_server_conn->fde = event_add_fd(smbd_event_context(),
1988                                              smbd_server_conn,
1989                                              smbd_server_fd(),
1990                                              EVENT_FD_READ,
1991                                              smbd_server_connection_handler,
1992                                              smbd_server_conn);
1993         if (!smbd_server_conn->fde) {
1994                 exit_server("failed to create smbd_server_connection fde");
1995         }
1996
1997         while (True) {
1998                 NTSTATUS status;
1999                 TALLOC_CTX *frame = talloc_stackframe_pool(8192);
2000
2001                 errno = 0;
2002
2003                 status = smbd_server_connection_loop_once(smbd_server_conn);
2004                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2005                     !NT_STATUS_IS_OK(status)) {
2006                         DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2007                                   " exiting\n", nt_errstr(status)));
2008                         return;
2009                 }
2010
2011                 TALLOC_FREE(frame);
2012         }
2013 }