s3: always call run_events() before and after sys_select()
[metze/samba/wip.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         /* Process a signal and timed events now... */
822         if (run_events(smbd_event_context(), 0, NULL, NULL)) {
823                 return NT_STATUS_RETRY;
824         }
825
826         {
827                 int sav;
828                 START_PROFILE(smbd_idle);
829
830                 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
831
832                 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
833                 sav = errno;
834
835                 END_PROFILE(smbd_idle);
836                 errno = sav;
837         }
838
839         if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
840                 return NT_STATUS_RETRY;
841         }
842
843         /* if we get EINTR then maybe we have received an oplock
844            signal - treat this as select returning 1. This is ugly, but
845            is the best we can do until the oplock code knows more about
846            signals */
847         if (selrtn == -1 && errno == EINTR) {
848                 async_processing(&r_fds);
849                 /*
850                  * After async processing we must go and do the select again, as
851                  * the state of the flag in fds for the server file descriptor is
852                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
853                  */
854                 return NT_STATUS_RETRY;
855         }
856
857         /* Check if error */
858         if (selrtn == -1) {
859                 /* something is wrong. Maybe the socket is dead? */
860                 return map_nt_error_from_unix(errno);
861         }
862
863         /* Did we timeout ? */
864         if (selrtn == 0) {
865                 return NT_STATUS_RETRY;
866         }
867
868         /*
869          * Ensure we process oplock break messages by preference.
870          * This is IMPORTANT ! Otherwise we can starve other processes
871          * sending us an oplock break message. JRA.
872          */
873
874         if (oplock_message_waiting(&r_fds)) {
875                 async_processing(&r_fds);
876                 /*
877                  * After async processing we must go and do the select again, as
878                  * the state of the flag in fds for the server file descriptor is
879                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
880                  */
881                 return NT_STATUS_RETRY;
882         }
883
884         /*
885          * We've just woken up from a protentially long select sleep.
886          * Ensure we process local messages as we need to synchronously
887          * process any messages from other smbd's to avoid file rename race
888          * conditions. This call is cheap if there are no messages waiting.
889          * JRA.
890          */
891         message_dispatch(smbd_messaging_context());
892
893         return NT_STATUS_OK;
894 }
895
896 /*
897  * Only allow 5 outstanding trans requests. We're allocating memory, so
898  * prevent a DoS.
899  */
900
901 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
902 {
903         int count = 0;
904         for (; list != NULL; list = list->next) {
905
906                 if (list->mid == mid) {
907                         return NT_STATUS_INVALID_PARAMETER;
908                 }
909
910                 count += 1;
911         }
912         if (count > 5) {
913                 return NT_STATUS_INSUFFICIENT_RESOURCES;
914         }
915
916         return NT_STATUS_OK;
917 }
918
919 /****************************************************************************
920  We're terminating and have closed all our files/connections etc.
921  If there are any pending local messages we need to respond to them
922  before termination so that other smbds don't think we just died whilst
923  holding oplocks.
924 ****************************************************************************/
925
926 void respond_to_all_remaining_local_messages(void)
927 {
928         /*
929          * Assert we have no exclusive open oplocks.
930          */
931
932         if(get_number_of_exclusive_open_oplocks()) {
933                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
934                         get_number_of_exclusive_open_oplocks() ));
935                 return;
936         }
937
938         process_kernel_oplocks(smbd_messaging_context(), NULL);
939
940         return;
941 }
942
943
944 /*
945 These flags determine some of the permissions required to do an operation 
946
947 Note that I don't set NEED_WRITE on some write operations because they
948 are used by some brain-dead clients when printing, and I don't want to
949 force write permissions on print services.
950 */
951 #define AS_USER (1<<0)
952 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
953 #define TIME_INIT (1<<2)
954 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
955 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
956 #define DO_CHDIR (1<<6)
957
958 /* 
959    define a list of possible SMB messages and their corresponding
960    functions. Any message that has a NULL function is unimplemented -
961    please feel free to contribute implementations!
962 */
963 static const struct smb_message_struct {
964         const char *name;
965         void (*fn)(struct smb_request *req);
966         int flags;
967 } smb_messages[256] = {
968
969 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
970 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
971 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
972 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
973 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
974 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
975 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
976 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
977 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
978 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
979 /* 0x0a */ { "SMBread",reply_read,AS_USER},
980 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
981 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
982 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
983 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
984 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
985 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
986 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
987 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
988 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
989 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
990 /* 0x15 */ { NULL, NULL, 0 },
991 /* 0x16 */ { NULL, NULL, 0 },
992 /* 0x17 */ { NULL, NULL, 0 },
993 /* 0x18 */ { NULL, NULL, 0 },
994 /* 0x19 */ { NULL, NULL, 0 },
995 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
996 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
997 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
998 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
999 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
1000 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
1001 /* 0x20 */ { "SMBwritec", NULL,0},
1002 /* 0x21 */ { NULL, NULL, 0 },
1003 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
1004 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
1005 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
1006 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
1007 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
1008 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
1009 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
1010 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
1011 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
1012 /* 0x2b */ { "SMBecho",reply_echo,0},
1013 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
1014 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
1015 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
1016 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
1017 /* 0x30 */ { NULL, NULL, 0 },
1018 /* 0x31 */ { NULL, NULL, 0 },
1019 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
1020 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
1021 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
1022 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
1023 /* 0x36 */ { NULL, NULL, 0 },
1024 /* 0x37 */ { NULL, NULL, 0 },
1025 /* 0x38 */ { NULL, NULL, 0 },
1026 /* 0x39 */ { NULL, NULL, 0 },
1027 /* 0x3a */ { NULL, NULL, 0 },
1028 /* 0x3b */ { NULL, NULL, 0 },
1029 /* 0x3c */ { NULL, NULL, 0 },
1030 /* 0x3d */ { NULL, NULL, 0 },
1031 /* 0x3e */ { NULL, NULL, 0 },
1032 /* 0x3f */ { NULL, NULL, 0 },
1033 /* 0x40 */ { NULL, NULL, 0 },
1034 /* 0x41 */ { NULL, NULL, 0 },
1035 /* 0x42 */ { NULL, NULL, 0 },
1036 /* 0x43 */ { NULL, NULL, 0 },
1037 /* 0x44 */ { NULL, NULL, 0 },
1038 /* 0x45 */ { NULL, NULL, 0 },
1039 /* 0x46 */ { NULL, NULL, 0 },
1040 /* 0x47 */ { NULL, NULL, 0 },
1041 /* 0x48 */ { NULL, NULL, 0 },
1042 /* 0x49 */ { NULL, NULL, 0 },
1043 /* 0x4a */ { NULL, NULL, 0 },
1044 /* 0x4b */ { NULL, NULL, 0 },
1045 /* 0x4c */ { NULL, NULL, 0 },
1046 /* 0x4d */ { NULL, NULL, 0 },
1047 /* 0x4e */ { NULL, NULL, 0 },
1048 /* 0x4f */ { NULL, NULL, 0 },
1049 /* 0x50 */ { NULL, NULL, 0 },
1050 /* 0x51 */ { NULL, NULL, 0 },
1051 /* 0x52 */ { NULL, NULL, 0 },
1052 /* 0x53 */ { NULL, NULL, 0 },
1053 /* 0x54 */ { NULL, NULL, 0 },
1054 /* 0x55 */ { NULL, NULL, 0 },
1055 /* 0x56 */ { NULL, NULL, 0 },
1056 /* 0x57 */ { NULL, NULL, 0 },
1057 /* 0x58 */ { NULL, NULL, 0 },
1058 /* 0x59 */ { NULL, NULL, 0 },
1059 /* 0x5a */ { NULL, NULL, 0 },
1060 /* 0x5b */ { NULL, NULL, 0 },
1061 /* 0x5c */ { NULL, NULL, 0 },
1062 /* 0x5d */ { NULL, NULL, 0 },
1063 /* 0x5e */ { NULL, NULL, 0 },
1064 /* 0x5f */ { NULL, NULL, 0 },
1065 /* 0x60 */ { NULL, NULL, 0 },
1066 /* 0x61 */ { NULL, NULL, 0 },
1067 /* 0x62 */ { NULL, NULL, 0 },
1068 /* 0x63 */ { NULL, NULL, 0 },
1069 /* 0x64 */ { NULL, NULL, 0 },
1070 /* 0x65 */ { NULL, NULL, 0 },
1071 /* 0x66 */ { NULL, NULL, 0 },
1072 /* 0x67 */ { NULL, NULL, 0 },
1073 /* 0x68 */ { NULL, NULL, 0 },
1074 /* 0x69 */ { NULL, NULL, 0 },
1075 /* 0x6a */ { NULL, NULL, 0 },
1076 /* 0x6b */ { NULL, NULL, 0 },
1077 /* 0x6c */ { NULL, NULL, 0 },
1078 /* 0x6d */ { NULL, NULL, 0 },
1079 /* 0x6e */ { NULL, NULL, 0 },
1080 /* 0x6f */ { NULL, NULL, 0 },
1081 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1082 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1083 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1084 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1085 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1086 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1087 /* 0x76 */ { NULL, NULL, 0 },
1088 /* 0x77 */ { NULL, NULL, 0 },
1089 /* 0x78 */ { NULL, NULL, 0 },
1090 /* 0x79 */ { NULL, NULL, 0 },
1091 /* 0x7a */ { NULL, NULL, 0 },
1092 /* 0x7b */ { NULL, NULL, 0 },
1093 /* 0x7c */ { NULL, NULL, 0 },
1094 /* 0x7d */ { NULL, NULL, 0 },
1095 /* 0x7e */ { NULL, NULL, 0 },
1096 /* 0x7f */ { NULL, NULL, 0 },
1097 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1098 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1099 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1100 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1101 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1102 /* 0x85 */ { NULL, NULL, 0 },
1103 /* 0x86 */ { NULL, NULL, 0 },
1104 /* 0x87 */ { NULL, NULL, 0 },
1105 /* 0x88 */ { NULL, NULL, 0 },
1106 /* 0x89 */ { NULL, NULL, 0 },
1107 /* 0x8a */ { NULL, NULL, 0 },
1108 /* 0x8b */ { NULL, NULL, 0 },
1109 /* 0x8c */ { NULL, NULL, 0 },
1110 /* 0x8d */ { NULL, NULL, 0 },
1111 /* 0x8e */ { NULL, NULL, 0 },
1112 /* 0x8f */ { NULL, NULL, 0 },
1113 /* 0x90 */ { NULL, NULL, 0 },
1114 /* 0x91 */ { NULL, NULL, 0 },
1115 /* 0x92 */ { NULL, NULL, 0 },
1116 /* 0x93 */ { NULL, NULL, 0 },
1117 /* 0x94 */ { NULL, NULL, 0 },
1118 /* 0x95 */ { NULL, NULL, 0 },
1119 /* 0x96 */ { NULL, NULL, 0 },
1120 /* 0x97 */ { NULL, NULL, 0 },
1121 /* 0x98 */ { NULL, NULL, 0 },
1122 /* 0x99 */ { NULL, NULL, 0 },
1123 /* 0x9a */ { NULL, NULL, 0 },
1124 /* 0x9b */ { NULL, NULL, 0 },
1125 /* 0x9c */ { NULL, NULL, 0 },
1126 /* 0x9d */ { NULL, NULL, 0 },
1127 /* 0x9e */ { NULL, NULL, 0 },
1128 /* 0x9f */ { NULL, NULL, 0 },
1129 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1130 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1131 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1132 /* 0xa3 */ { NULL, NULL, 0 },
1133 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1134 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1135 /* 0xa6 */ { NULL, NULL, 0 },
1136 /* 0xa7 */ { NULL, NULL, 0 },
1137 /* 0xa8 */ { NULL, NULL, 0 },
1138 /* 0xa9 */ { NULL, NULL, 0 },
1139 /* 0xaa */ { NULL, NULL, 0 },
1140 /* 0xab */ { NULL, NULL, 0 },
1141 /* 0xac */ { NULL, NULL, 0 },
1142 /* 0xad */ { NULL, NULL, 0 },
1143 /* 0xae */ { NULL, NULL, 0 },
1144 /* 0xaf */ { NULL, NULL, 0 },
1145 /* 0xb0 */ { NULL, NULL, 0 },
1146 /* 0xb1 */ { NULL, NULL, 0 },
1147 /* 0xb2 */ { NULL, NULL, 0 },
1148 /* 0xb3 */ { NULL, NULL, 0 },
1149 /* 0xb4 */ { NULL, NULL, 0 },
1150 /* 0xb5 */ { NULL, NULL, 0 },
1151 /* 0xb6 */ { NULL, NULL, 0 },
1152 /* 0xb7 */ { NULL, NULL, 0 },
1153 /* 0xb8 */ { NULL, NULL, 0 },
1154 /* 0xb9 */ { NULL, NULL, 0 },
1155 /* 0xba */ { NULL, NULL, 0 },
1156 /* 0xbb */ { NULL, NULL, 0 },
1157 /* 0xbc */ { NULL, NULL, 0 },
1158 /* 0xbd */ { NULL, NULL, 0 },
1159 /* 0xbe */ { NULL, NULL, 0 },
1160 /* 0xbf */ { NULL, NULL, 0 },
1161 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1162 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1163 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1164 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1165 /* 0xc4 */ { NULL, NULL, 0 },
1166 /* 0xc5 */ { NULL, NULL, 0 },
1167 /* 0xc6 */ { NULL, NULL, 0 },
1168 /* 0xc7 */ { NULL, NULL, 0 },
1169 /* 0xc8 */ { NULL, NULL, 0 },
1170 /* 0xc9 */ { NULL, NULL, 0 },
1171 /* 0xca */ { NULL, NULL, 0 },
1172 /* 0xcb */ { NULL, NULL, 0 },
1173 /* 0xcc */ { NULL, NULL, 0 },
1174 /* 0xcd */ { NULL, NULL, 0 },
1175 /* 0xce */ { NULL, NULL, 0 },
1176 /* 0xcf */ { NULL, NULL, 0 },
1177 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1178 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1179 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1180 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1181 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1182 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1183 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1184 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1185 /* 0xd8 */ { NULL, NULL, 0 },
1186 /* 0xd9 */ { NULL, NULL, 0 },
1187 /* 0xda */ { NULL, NULL, 0 },
1188 /* 0xdb */ { NULL, NULL, 0 },
1189 /* 0xdc */ { NULL, NULL, 0 },
1190 /* 0xdd */ { NULL, NULL, 0 },
1191 /* 0xde */ { NULL, NULL, 0 },
1192 /* 0xdf */ { NULL, NULL, 0 },
1193 /* 0xe0 */ { NULL, NULL, 0 },
1194 /* 0xe1 */ { NULL, NULL, 0 },
1195 /* 0xe2 */ { NULL, NULL, 0 },
1196 /* 0xe3 */ { NULL, NULL, 0 },
1197 /* 0xe4 */ { NULL, NULL, 0 },
1198 /* 0xe5 */ { NULL, NULL, 0 },
1199 /* 0xe6 */ { NULL, NULL, 0 },
1200 /* 0xe7 */ { NULL, NULL, 0 },
1201 /* 0xe8 */ { NULL, NULL, 0 },
1202 /* 0xe9 */ { NULL, NULL, 0 },
1203 /* 0xea */ { NULL, NULL, 0 },
1204 /* 0xeb */ { NULL, NULL, 0 },
1205 /* 0xec */ { NULL, NULL, 0 },
1206 /* 0xed */ { NULL, NULL, 0 },
1207 /* 0xee */ { NULL, NULL, 0 },
1208 /* 0xef */ { NULL, NULL, 0 },
1209 /* 0xf0 */ { NULL, NULL, 0 },
1210 /* 0xf1 */ { NULL, NULL, 0 },
1211 /* 0xf2 */ { NULL, NULL, 0 },
1212 /* 0xf3 */ { NULL, NULL, 0 },
1213 /* 0xf4 */ { NULL, NULL, 0 },
1214 /* 0xf5 */ { NULL, NULL, 0 },
1215 /* 0xf6 */ { NULL, NULL, 0 },
1216 /* 0xf7 */ { NULL, NULL, 0 },
1217 /* 0xf8 */ { NULL, NULL, 0 },
1218 /* 0xf9 */ { NULL, NULL, 0 },
1219 /* 0xfa */ { NULL, NULL, 0 },
1220 /* 0xfb */ { NULL, NULL, 0 },
1221 /* 0xfc */ { NULL, NULL, 0 },
1222 /* 0xfd */ { NULL, NULL, 0 },
1223 /* 0xfe */ { NULL, NULL, 0 },
1224 /* 0xff */ { NULL, NULL, 0 }
1225
1226 };
1227
1228 /*******************************************************************
1229  allocate and initialize a reply packet
1230 ********************************************************************/
1231
1232 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1233                           const char *inbuf, char **outbuf, uint8_t num_words,
1234                           uint32_t num_bytes)
1235 {
1236         /*
1237          * Protect against integer wrap
1238          */
1239         if ((num_bytes > 0xffffff)
1240             || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1241                 char *msg;
1242                 if (asprintf(&msg, "num_bytes too large: %u",
1243                              (unsigned)num_bytes) == -1) {
1244                         msg = CONST_DISCARD(char *, "num_bytes too large");
1245                 }
1246                 smb_panic(msg);
1247         }
1248
1249         *outbuf = TALLOC_ARRAY(mem_ctx, char,
1250                                smb_size + num_words*2 + num_bytes);
1251         if (*outbuf == NULL) {
1252                 return false;
1253         }
1254
1255         construct_reply_common(req, inbuf, *outbuf);
1256         srv_set_message(*outbuf, num_words, num_bytes, false);
1257         /*
1258          * Zero out the word area, the caller has to take care of the bcc area
1259          * himself
1260          */
1261         if (num_words != 0) {
1262                 memset(*outbuf + smb_vwv0, 0, num_words*2);
1263         }
1264
1265         return true;
1266 }
1267
1268 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1269 {
1270         char *outbuf;
1271         if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1272                            num_bytes)) {
1273                 smb_panic("could not allocate output buffer\n");
1274         }
1275         req->outbuf = (uint8_t *)outbuf;
1276 }
1277
1278
1279 /*******************************************************************
1280  Dump a packet to a file.
1281 ********************************************************************/
1282
1283 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1284 {
1285         int fd, i;
1286         char *fname = NULL;
1287         if (DEBUGLEVEL < 50) {
1288                 return;
1289         }
1290
1291         if (len < 4) len = smb_len(data)+4;
1292         for (i=1;i<100;i++) {
1293                 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1294                              type ? "req" : "resp") == -1) {
1295                         return;
1296                 }
1297                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1298                 if (fd != -1 || errno != EEXIST) break;
1299         }
1300         if (fd != -1) {
1301                 ssize_t ret = write(fd, data, len);
1302                 if (ret != len)
1303                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1304                 close(fd);
1305                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1306         }
1307         SAFE_FREE(fname);
1308 }
1309
1310 /****************************************************************************
1311  Prepare everything for calling the actual request function, and potentially
1312  call the request function via the "new" interface.
1313
1314  Return False if the "legacy" function needs to be called, everything is
1315  prepared.
1316
1317  Return True if we're done.
1318
1319  I know this API sucks, but it is the one with the least code change I could
1320  find.
1321 ****************************************************************************/
1322
1323 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1324 {
1325         int flags;
1326         uint16 session_tag;
1327         connection_struct *conn = NULL;
1328
1329         errno = 0;
1330
1331         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1332          * so subtract 4 from it. */
1333         if (!valid_smb_header(req->inbuf)
1334             || (size < (smb_size - 4))) {
1335                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1336                          smb_len(req->inbuf)));
1337                 exit_server_cleanly("Non-SMB packet");
1338         }
1339
1340         if (smb_messages[type].fn == NULL) {
1341                 DEBUG(0,("Unknown message type %d!\n",type));
1342                 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1343                 reply_unknown_new(req, type);
1344                 return NULL;
1345         }
1346
1347         flags = smb_messages[type].flags;
1348
1349         /* In share mode security we must ignore the vuid. */
1350         session_tag = (lp_security() == SEC_SHARE)
1351                 ? UID_FIELD_INVALID : req->vuid;
1352         conn = req->conn;
1353
1354         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1355                  (int)sys_getpid(), (unsigned long)conn));
1356
1357         smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1358
1359         /* Ensure this value is replaced in the incoming packet. */
1360         SSVAL(req->inbuf,smb_uid,session_tag);
1361
1362         /*
1363          * Ensure the correct username is in current_user_info.  This is a
1364          * really ugly bugfix for problems with multiple session_setup_and_X's
1365          * being done and allowing %U and %G substitutions to work correctly.
1366          * There is a reason this code is done here, don't move it unless you
1367          * know what you're doing... :-).
1368          * JRA.
1369          */
1370
1371         if (session_tag != last_session_tag) {
1372                 user_struct *vuser = NULL;
1373
1374                 last_session_tag = session_tag;
1375                 if(session_tag != UID_FIELD_INVALID) {
1376                         vuser = get_valid_user_struct(session_tag);
1377                         if (vuser) {
1378                                 set_current_user_info(
1379                                         vuser->server_info->sanitized_username,
1380                                         vuser->server_info->unix_name,
1381                                         pdb_get_domain(vuser->server_info
1382                                                        ->sam_account));
1383                         }
1384                 }
1385         }
1386
1387         /* Does this call need to be run as the connected user? */
1388         if (flags & AS_USER) {
1389
1390                 /* Does this call need a valid tree connection? */
1391                 if (!conn) {
1392                         /*
1393                          * Amazingly, the error code depends on the command
1394                          * (from Samba4).
1395                          */
1396                         if (type == SMBntcreateX) {
1397                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1398                         } else {
1399                                 reply_doserror(req, ERRSRV, ERRinvnid);
1400                         }
1401                         return NULL;
1402                 }
1403
1404                 if (!change_to_user(conn,session_tag)) {
1405                         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1406                         remove_deferred_open_smb_message(req->mid);
1407                         return conn;
1408                 }
1409
1410                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1411
1412                 /* Does it need write permission? */
1413                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1414                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1415                         return conn;
1416                 }
1417
1418                 /* IPC services are limited */
1419                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1420                         reply_doserror(req, ERRSRV,ERRaccess);
1421                         return conn;
1422                 }
1423         } else {
1424                 /* This call needs to be run as root */
1425                 change_to_root_user();
1426         }
1427
1428         /* load service specific parameters */
1429         if (conn) {
1430                 if (req->encrypted) {
1431                         conn->encrypted_tid = true;
1432                         /* encrypted required from now on. */
1433                         conn->encrypt_level = Required;
1434                 } else if (ENCRYPTION_REQUIRED(conn)) {
1435                         if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1436                                 exit_server_cleanly("encryption required "
1437                                         "on connection");
1438                                 return conn;
1439                         }
1440                 }
1441
1442                 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1443                                          (flags & (AS_USER|DO_CHDIR)
1444                                           ?True:False))) {
1445                         reply_doserror(req, ERRSRV, ERRaccess);
1446                         return conn;
1447                 }
1448                 conn->num_smb_operations++;
1449         }
1450
1451         /* does this protocol need to be run as guest? */
1452         if ((flags & AS_GUEST)
1453             && (!change_to_guest() ||
1454                 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1455                               lp_hostsdeny(-1)))) {
1456                 reply_doserror(req, ERRSRV, ERRaccess);
1457                 return conn;
1458         }
1459
1460         smb_messages[type].fn(req);
1461         return req->conn;
1462 }
1463
1464 /****************************************************************************
1465  Construct a reply to the incoming packet.
1466 ****************************************************************************/
1467
1468 static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
1469 {
1470         connection_struct *conn;
1471         struct smb_request *req;
1472
1473         chain_size = 0;
1474
1475         if (!(req = talloc(talloc_tos(), struct smb_request))) {
1476                 smb_panic("could not allocate smb_request");
1477         }
1478         init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1479         req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
1480
1481         conn = switch_message(req->cmd, req, size);
1482
1483         if (req->unread_bytes) {
1484                 /* writeX failed. drain socket. */
1485                 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1486                                 req->unread_bytes) {
1487                         smb_panic("failed to drain pending bytes");
1488                 }
1489                 req->unread_bytes = 0;
1490         }
1491
1492         if (req->outbuf == NULL) {
1493                 return;
1494         }
1495
1496         if (CVAL(req->outbuf,0) == 0) {
1497                 show_msg((char *)req->outbuf);
1498         }
1499
1500         if (!srv_send_smb(smbd_server_fd(),
1501                         (char *)req->outbuf,
1502                         IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
1503                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1504         }
1505
1506         TALLOC_FREE(req);
1507
1508         return;
1509 }
1510
1511 /****************************************************************************
1512  Process an smb from the client
1513 ****************************************************************************/
1514
1515 static void process_smb(struct smbd_server_connection *conn,
1516                         uint8_t *inbuf, size_t nread, size_t unread_bytes,
1517                         bool encrypted)
1518 {
1519         int msg_type = CVAL(inbuf,0);
1520
1521         DO_PROFILE_INC(smb_count);
1522
1523         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1524                     smb_len(inbuf) ) );
1525         DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1526                                 (int)nread,
1527                                 (unsigned int)unread_bytes ));
1528
1529         if (msg_type != 0) {
1530                 /*
1531                  * NetBIOS session request, keepalive, etc.
1532                  */
1533                 reply_special((char *)inbuf);
1534                 goto done;
1535         }
1536
1537         show_msg((char *)inbuf);
1538
1539         construct_reply((char *)inbuf,nread,unread_bytes,encrypted);
1540
1541         trans_num++;
1542
1543 done:
1544         conn->num_requests++;
1545
1546         /* The timeout_processing function isn't run nearly
1547            often enough to implement 'max log size' without
1548            overrunning the size of the file by many megabytes.
1549            This is especially true if we are running at debug
1550            level 10.  Checking every 50 SMBs is a nice
1551            tradeoff of performance vs log file size overrun. */
1552
1553         if ((conn->num_requests % 50) == 0 &&
1554             need_to_check_log_size()) {
1555                 change_to_root_user();
1556                 check_log_size();
1557         }
1558 }
1559
1560 /****************************************************************************
1561  Return a string containing the function name of a SMB command.
1562 ****************************************************************************/
1563
1564 const char *smb_fn_name(int type)
1565 {
1566         const char *unknown_name = "SMBunknown";
1567
1568         if (smb_messages[type].name == NULL)
1569                 return(unknown_name);
1570
1571         return(smb_messages[type].name);
1572 }
1573
1574 /****************************************************************************
1575  Helper functions for contruct_reply.
1576 ****************************************************************************/
1577
1578 void add_to_common_flags2(uint32 v)
1579 {
1580         common_flags2 |= v;
1581 }
1582
1583 void remove_from_common_flags2(uint32 v)
1584 {
1585         common_flags2 &= ~v;
1586 }
1587
1588 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1589                                    char *outbuf)
1590 {
1591         srv_set_message(outbuf,0,0,false);
1592         
1593         SCVAL(outbuf, smb_com, req->cmd);
1594         SIVAL(outbuf,smb_rcls,0);
1595         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1596         SSVAL(outbuf,smb_flg2,
1597                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1598                 common_flags2);
1599         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1600
1601         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1602         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1603         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1604         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1605 }
1606
1607 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1608 {
1609         construct_reply_common(req, (char *)req->inbuf, outbuf);
1610 }
1611
1612 /*
1613  * How many bytes have we already accumulated up to the current wct field
1614  * offset?
1615  */
1616
1617 size_t req_wct_ofs(struct smb_request *req)
1618 {
1619         size_t buf_size;
1620
1621         if (req->chain_outbuf == NULL) {
1622                 return smb_wct - 4;
1623         }
1624         buf_size = talloc_get_size(req->chain_outbuf);
1625         if ((buf_size % 4) != 0) {
1626                 buf_size += (4 - (buf_size % 4));
1627         }
1628         return buf_size - 4;
1629 }
1630
1631 /*
1632  * Hack around reply_nterror & friends not being aware of chained requests,
1633  * generating illegal (i.e. wct==0) chain replies.
1634  */
1635
1636 static void fixup_chain_error_packet(struct smb_request *req)
1637 {
1638         uint8_t *outbuf = req->outbuf;
1639         req->outbuf = NULL;
1640         reply_outbuf(req, 2, 0);
1641         memcpy(req->outbuf, outbuf, smb_wct);
1642         TALLOC_FREE(outbuf);
1643         SCVAL(req->outbuf, smb_vwv0, 0xff);
1644 }
1645
1646 /****************************************************************************
1647  Construct a chained reply and add it to the already made reply
1648 ****************************************************************************/
1649
1650 void chain_reply(struct smb_request *req)
1651 {
1652         size_t smblen = smb_len(req->inbuf);
1653         size_t already_used, length_needed;
1654         uint8_t chain_cmd;
1655         uint32_t chain_offset;  /* uint32_t to avoid overflow */
1656
1657         uint8_t wct;
1658         uint16_t *vwv;
1659         uint16_t buflen;
1660         uint8_t *buf;
1661
1662         if (IVAL(req->outbuf, smb_rcls) != 0) {
1663                 fixup_chain_error_packet(req);
1664         }
1665
1666         /*
1667          * Any of the AndX requests and replies have at least a wct of
1668          * 2. vwv[0] is the next command, vwv[1] is the offset from the
1669          * beginning of the SMB header to the next wct field.
1670          *
1671          * None of the AndX requests put anything valuable in vwv[0] and [1],
1672          * so we can overwrite it here to form the chain.
1673          */
1674
1675         if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1676                 goto error;
1677         }
1678
1679         /*
1680          * Here we assume that this is the end of the chain. For that we need
1681          * to set "next command" to 0xff and the offset to 0. If we later find
1682          * more commands in the chain, this will be overwritten again.
1683          */
1684
1685         SCVAL(req->outbuf, smb_vwv0, 0xff);
1686         SCVAL(req->outbuf, smb_vwv0+1, 0);
1687         SSVAL(req->outbuf, smb_vwv1, 0);
1688
1689         if (req->chain_outbuf == NULL) {
1690                 /*
1691                  * In req->chain_outbuf we collect all the replies. Start the
1692                  * chain by copying in the first reply.
1693                  */
1694                 req->chain_outbuf = req->outbuf;
1695                 req->outbuf = NULL;
1696         } else {
1697                 if (!smb_splice_chain(&req->chain_outbuf,
1698                                       CVAL(req->outbuf, smb_com),
1699                                       CVAL(req->outbuf, smb_wct),
1700                                       (uint16_t *)(req->outbuf + smb_vwv),
1701                                       0, smb_buflen(req->outbuf),
1702                                       (uint8_t *)smb_buf(req->outbuf))) {
1703                         goto error;
1704                 }
1705                 TALLOC_FREE(req->outbuf);
1706         }
1707
1708         /*
1709          * We use the old request's vwv field to grab the next chained command
1710          * and offset into the chained fields.
1711          */
1712
1713         chain_cmd = CVAL(req->vwv+0, 0);
1714         chain_offset = SVAL(req->vwv+1, 0);
1715
1716         if (chain_cmd == 0xff) {
1717                 /*
1718                  * End of chain, no more requests from the client. So ship the
1719                  * replies.
1720                  */
1721                 smb_setlen((char *)(req->chain_outbuf),
1722                            talloc_get_size(req->chain_outbuf) - 4);
1723                 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1724                                   IS_CONN_ENCRYPTED(req->conn)
1725                                   ||req->encrypted)) {
1726                         exit_server_cleanly("chain_reply: srv_send_smb "
1727                                             "failed.");
1728                 }
1729                 return;
1730         }
1731
1732         /*
1733          * Check if the client tries to fool us. The request so far uses the
1734          * space to the end of the byte buffer in the request just
1735          * processed. The chain_offset can't point into that area. If that was
1736          * the case, we could end up with an endless processing of the chain,
1737          * we would always handle the same request.
1738          */
1739
1740         already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1741         if (chain_offset < already_used) {
1742                 goto error;
1743         }
1744
1745         /*
1746          * Next check: Make sure the chain offset does not point beyond the
1747          * overall smb request length.
1748          */
1749
1750         length_needed = chain_offset+1; /* wct */
1751         if (length_needed > smblen) {
1752                 goto error;
1753         }
1754
1755         /*
1756          * Now comes the pointer magic. Goal here is to set up req->vwv and
1757          * req->buf correctly again to be able to call the subsequent
1758          * switch_message(). The chain offset (the former vwv[1]) points at
1759          * the new wct field.
1760          */
1761
1762         wct = CVAL(smb_base(req->inbuf), chain_offset);
1763
1764         /*
1765          * Next consistency check: Make the new vwv array fits in the overall
1766          * smb request.
1767          */
1768
1769         length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1770         if (length_needed > smblen) {
1771                 goto error;
1772         }
1773         vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1774
1775         /*
1776          * Now grab the new byte buffer....
1777          */
1778
1779         buflen = SVAL(vwv+wct, 0);
1780
1781         /*
1782          * .. and check that it fits.
1783          */
1784
1785         length_needed += buflen;
1786         if (length_needed > smblen) {
1787                 goto error;
1788         }
1789         buf = (uint8_t *)(vwv+wct+1);
1790
1791         req->cmd = chain_cmd;
1792         req->wct = wct;
1793         req->vwv = vwv;
1794         req->buflen = buflen;
1795         req->buf = buf;
1796
1797         switch_message(chain_cmd, req, smblen);
1798
1799         if (req->outbuf == NULL) {
1800                 /*
1801                  * This happens if the chained command has suspended itself or
1802                  * if it has called srv_send_smb() itself.
1803                  */
1804                 return;
1805         }
1806
1807         /*
1808          * We end up here if the chained command was not itself chained or
1809          * suspended, but for example a close() command. We now need to splice
1810          * the chained commands' outbuf into the already built up chain_outbuf
1811          * and ship the result.
1812          */
1813         goto done;
1814
1815  error:
1816         /*
1817          * We end up here if there's any error in the chain syntax. Report a
1818          * DOS error, just like Windows does.
1819          */
1820         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1821         fixup_chain_error_packet(req);
1822
1823  done:
1824         if (!smb_splice_chain(&req->chain_outbuf,
1825                               CVAL(req->outbuf, smb_com),
1826                               CVAL(req->outbuf, smb_wct),
1827                               (uint16_t *)(req->outbuf + smb_vwv),
1828                               0, smb_buflen(req->outbuf),
1829                               (uint8_t *)smb_buf(req->outbuf))) {
1830                 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1831         }
1832         TALLOC_FREE(req->outbuf);
1833
1834         smb_setlen((char *)(req->chain_outbuf),
1835                    talloc_get_size(req->chain_outbuf) - 4);
1836
1837         show_msg((char *)(req->chain_outbuf));
1838
1839         if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1840                           IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) {
1841                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1842         }
1843 }
1844
1845 /****************************************************************************
1846  Check if services need reloading.
1847 ****************************************************************************/
1848
1849 void check_reload(time_t t)
1850 {
1851         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1852
1853         if(last_smb_conf_reload_time == 0) {
1854                 last_smb_conf_reload_time = t;
1855                 /* Our printing subsystem might not be ready at smbd start up.
1856                    Then no printer is available till the first printers check
1857                    is performed.  A lower initial interval circumvents this. */
1858                 if ( printcap_cache_time > 60 )
1859                         last_printer_reload_time = t - printcap_cache_time + 60;
1860                 else
1861                         last_printer_reload_time = t;
1862         }
1863
1864         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1865                 /* randomize over 60 second the printcap reload to avoid all
1866                  * process hitting cupsd at the same time */
1867                 int time_range = 60;
1868
1869                 last_printer_reload_time += random() % time_range;
1870                 mypid = getpid();
1871         }
1872
1873         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1874                 reload_services(True);
1875                 reload_after_sighup = False;
1876                 last_smb_conf_reload_time = t;
1877         }
1878
1879         /* 'printcap cache time = 0' disable the feature */
1880         
1881         if ( printcap_cache_time != 0 )
1882         { 
1883                 /* see if it's time to reload or if the clock has been set back */
1884                 
1885                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1886                         || (t-last_printer_reload_time  < 0) ) 
1887                 {
1888                         DEBUG( 3,( "Printcap cache time expired.\n"));
1889                         reload_printers();
1890                         last_printer_reload_time = t;
1891                 }
1892         }
1893 }
1894
1895 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1896 {
1897         /* TODO: make write nonblocking */
1898 }
1899
1900 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1901 {
1902         uint8_t *inbuf = NULL;
1903         size_t inbuf_len = 0;
1904         size_t unread_bytes = 0;
1905         bool encrypted = false;
1906         TALLOC_CTX *mem_ctx = talloc_tos();
1907         NTSTATUS status;
1908
1909         /* TODO: remove this hack */
1910         message_dispatch(smbd_messaging_context());
1911
1912         /* TODO: make this completely nonblocking */
1913
1914         status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1915                                     (char **)(void *)&inbuf,
1916                                     0, /* timeout */
1917                                     &unread_bytes,
1918                                     &encrypted,
1919                                     &inbuf_len);
1920         if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1921                 goto process;
1922         }
1923         if (NT_STATUS_IS_ERR(status)) {
1924                 exit_server_cleanly("failed to receive smb request");
1925         }
1926         if (!NT_STATUS_IS_OK(status)) {
1927                 return;
1928         }
1929
1930 process:
1931         process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted);
1932 }
1933
1934 static void smbd_server_connection_handler(struct event_context *ev,
1935                                            struct fd_event *fde,
1936                                            uint16_t flags,
1937                                            void *private_data)
1938 {
1939         struct smbd_server_connection *conn = talloc_get_type(private_data,
1940                                               struct smbd_server_connection);
1941
1942         if (flags & EVENT_FD_WRITE) {
1943                 smbd_server_connection_write_handler(conn);
1944         } else if (flags & EVENT_FD_READ) {
1945                 smbd_server_connection_read_handler(conn);
1946         }
1947 }
1948
1949 /****************************************************************************
1950  Process commands from the client
1951 ****************************************************************************/
1952
1953 void smbd_process(void)
1954 {
1955         /*
1956          * Before the first packet, check the global hosts allow/ hosts deny
1957          * parameters before doing any parsing of packets passed to us by the
1958          * client. This prevents attacks on our parsing code from hosts not in
1959          * the hosts allow list.
1960          */
1961
1962         if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1963                           lp_hostsdeny(-1))) {
1964                 char addr[INET6_ADDRSTRLEN];
1965
1966                 /*
1967                  * send a negative session response "not listening on calling
1968                  * name"
1969                  */
1970                 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1971                 DEBUG( 1, ("Connection denied from %s\n",
1972                            client_addr(get_client_fd(),addr,sizeof(addr)) ) );
1973                 (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
1974                 exit_server_cleanly("connection denied");
1975         }
1976
1977         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1978
1979         smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
1980         if (!smbd_server_conn) {
1981                 exit_server("failed to create smbd_server_connection");
1982         }
1983         smbd_server_conn->fde = event_add_fd(smbd_event_context(),
1984                                              smbd_server_conn,
1985                                              smbd_server_fd(),
1986                                              EVENT_FD_READ,
1987                                              smbd_server_connection_handler,
1988                                              smbd_server_conn);
1989         if (!smbd_server_conn->fde) {
1990                 exit_server("failed to create smbd_server_connection fde");
1991         }
1992
1993         while (True) {
1994                 NTSTATUS status;
1995                 TALLOC_CTX *frame = talloc_stackframe_pool(8192);
1996
1997                 errno = 0;
1998
1999                 status = smbd_server_connection_loop_once(smbd_server_conn);
2000                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2001                     !NT_STATUS_IS_OK(status)) {
2002                         DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2003                                   " exiting\n", nt_errstr(status)));
2004                         return;
2005                 }
2006
2007                 TALLOC_FREE(frame);
2008         }
2009 }