/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
process incoming packets - main loop
Copyright (C) Andrew Tridgell 1992-1998
extern int global_oplock_break;
extern userdom_struct current_user_info;
extern int smb_read_error;
-extern VOLATILE sig_atomic_t reload_after_sighup;
+SIG_ATOMIC_T reload_after_sighup = 0;
+SIG_ATOMIC_T got_sig_term = 0;
extern BOOL global_machine_password_needs_changing;
extern fstring global_myworkgroup;
extern pstring global_myname;
}
/****************************************************************************
-do all async processing in here. This includes UDB oplock messages, kernel
-oplock messages, change notify events etc.
+ Do all async processing in here. This includes UDB oplock messages, kernel
+ oplock messages, change notify events etc.
****************************************************************************/
-static void async_processing(fd_set *fds, char *buffer, int buffer_len)
+
+static void async_processing(char *buffer, int buffer_len)
{
+ DEBUG(10,("async_processing: Doing async processing.\n"));
+
/* check for oplock messages (both UDP and kernel) */
- if (receive_local_message(fds, buffer, buffer_len, 0)) {
+ if (receive_local_message(buffer, buffer_len, 1)) {
process_local_message(buffer, buffer_len);
}
+ if (got_sig_term) {
+ exit_server("Caught TERM signal");
+ }
+
/* check for async change notify events */
process_pending_change_notify_queue(0);
change_to_root_user();
DEBUG(1,("Reloading services after SIGHUP\n"));
reload_services(False);
- reload_after_sighup = False;
+ reload_after_sighup = 0;
}
}
Returns False on timeout or error.
Else returns True.
-The timeout is in milli seconds
+The timeout is in milliseconds
****************************************************************************/
static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
*/
FD_ZERO(&fds);
+
+ /*
+ * Ensure we process oplock break messages by preference.
+ * We have to do this before the select, after the select
+ * and if the select returns EINTR. This is due to the fact
+ * that the selects called from async_processing can eat an EINTR
+ * caused by a signal (we can't take the break message there).
+ * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
+ */
+
+ if (oplock_message_waiting(&fds)) {
+ DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
+ async_processing(buffer, buffer_len);
+ /*
+ * After async processing we must go and do the select again, as
+ * the state of the flag in fds for the server file descriptor is
+ * indeterminate - we may have done I/O on it in the oplock processing. JRA.
+ */
+ goto again;
+ }
+
FD_SET(smbd_server_fd(),&fds);
maxfd = setup_oplock_select_set(&fds);
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
- selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
+ selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL);
/* if we get EINTR then maybe we have received an oplock
signal - treat this as select returning 1. This is ugly, but
is the best we can do until the oplock code knows more about
signals */
if (selrtn == -1 && errno == EINTR) {
- async_processing(&fds, buffer, buffer_len);
+ async_processing(buffer, buffer_len);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
*/
if (oplock_message_waiting(&fds)) {
- async_processing(&fds, buffer, buffer_len);
+ async_processing(buffer, buffer_len);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
void respond_to_all_remaining_local_messages(void)
{
char buffer[1024];
- fd_set fds;
/*
* Assert we have no exclusive open oplocks.
return;
}
- /*
- * Setup the select read fd set.
- */
-
- FD_ZERO(&fds);
- if(!setup_oplock_select_set(&fds))
- return;
-
/*
* Keep doing receive_local_message with a 1 ms timeout until
* we have no more messages.
*/
- while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
+ while(receive_local_message(buffer, sizeof(buffer), 1)) {
/* Deal with oplock break requests from other smbd's. */
process_local_message(buffer, sizeof(buffer));
-
- FD_ZERO(&fds);
- (void)setup_oplock_select_set(&fds);
}
return;
functions. Any message that has a NULL function is unimplemented -
please feel free to contribute implementations!
*/
-static struct smb_message_struct
+const static struct smb_message_struct
{
- char *name;
+ const char *name;
int (*fn)(connection_struct *conn, char *, char *, int, int);
int flags;
}
/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
-/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
+/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
/* 0x27 */ { "SMBioctl",reply_ioctl,0},
/* 0x28 */ { "SMBioctls",NULL,AS_USER},
/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
/* 0x30 */ { NULL, NULL, 0 },
/* 0x31 */ { NULL, NULL, 0 },
-/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
+/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
/*******************************************************************
dump a prs to a file
********************************************************************/
-static void smb_dump(char *name, int type, char *data, ssize_t len)
+static void smb_dump(const char *name, int type, char *data, ssize_t len)
{
int fd, i;
pstring fname;
if (fd != -1 || errno != EEXIST) break;
}
if (fd != -1) {
- write(fd, data, len);
+ ssize_t ret = write(fd, data, len);
+ if (ret != len)
+ DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
close(fd);
DEBUG(0,("created %s len %d\n", fname, len));
}
}
/****************************************************************************
- process an smb from the client - split out from the process() code so
+ process an smb from the client - split out from the smbd_process() code so
it can be used by the oplock break code.
****************************************************************************/
void process_smb(char *inbuf, char *outbuf)
{
-#ifdef WITH_SSL
- extern BOOL sslEnabled; /* don't use function for performance reasons */
- static int sslConnected = 0;
-#endif /* WITH_SSL */
static int trans_num;
int msg_type = CVAL(inbuf,0);
int32 len = smb_len(inbuf);
DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
-#ifdef WITH_SSL
- if(sslEnabled && !sslConnected){
- sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
- if(sslConnected < 0){ /* an error occured */
- exit_server("SSL negotiation failed");
- }else if(sslConnected){
- trans_num++;
- return;
- }
- }
-#endif /* WITH_SSL */
-
if (msg_type == 0)
show_msg(inbuf);
else if(msg_type == SMBkeepalive)
/****************************************************************************
return a string containing the function name of a SMB command
****************************************************************************/
-char *smb_fn_name(int type)
+const char *smb_fn_name(int type)
{
static char *unknown_name = "SMBunknown";
memset(outbuf,'\0',smb_size);
set_message(outbuf,0,0,True);
- CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
+ SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
memcpy(outbuf+4,inbuf+4,4);
- CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
- CVAL(outbuf,smb_reh) = 0;
+ SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
+ SCVAL(outbuf,smb_reh,0);
SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
SSVAL(outbuf,smb_flg2,
- FLAGS2_UNICODE_STRINGS | FLAGS2_LONG_PATH_COMPONENTS |
+ (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
+ FLAGS2_LONG_PATH_COMPONENTS |
FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY);
SSVAL(outbuf,smb_err,SMB_SUCCESS);
/* maybe its not chained */
if (smb_com2 == 0xFF) {
- CVAL(outbuf,smb_vwv0) = 0xFF;
+ SCVAL(outbuf,smb_vwv0,0xFF);
return outsize;
}
/* we need to tell the client where the next part of the reply will be */
SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
- CVAL(outbuf,smb_vwv0) = smb_com2;
+ SCVAL(outbuf,smb_vwv0,smb_com2);
/* remember how much the caller added to the chain, only counting stuff
after the parameter words */
memmove(inbuf2,inbuf,smb_wct);
/* create the in buffer */
- CVAL(inbuf2,smb_com) = smb_com2;
+ SCVAL(inbuf2,smb_com,smb_com2);
/* create the out buffer */
construct_reply_common(inbuf2, outbuf2);
/* copy the new reply and request headers over the old ones, but
preserve the smb_com field */
memmove(orig_outbuf,outbuf2,smb_wct);
- CVAL(orig_outbuf,smb_com) = smb_com1;
+ SCVAL(orig_outbuf,smb_com,smb_com1);
/* restore the saved data, being careful not to overwrite any
data from the reply header */
int select_timeout;
int t;
- /*
- * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
- * have removed any blocking locks. JRA.
- */
-
- select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
- SMBD_SELECT_TIMEOUT*1000;
+ select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
+ select_timeout *= 1000;
t = change_notify_timeout();
if (t != -1) select_timeout = MIN(select_timeout, t*1000);
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
- /* re-initialise the timezone */
- TimeInit();
-
- /* register our message handlers */
- message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
- talloc_init_named("dummy!");
-
while (True) {
int deadtime = lp_deadtime()*60;
int select_timeout = setup_select_timeout();