X-Git-Url: http://git.samba.org/samba.git/?p=tprouty%2Fsamba.git;a=blobdiff_plain;f=source%2Fsmbd%2Fprocess.c;h=f2b2a5c15a62eab18db26cbcfd4b76cfa2258c97;hp=ff53acbd9eee803e148211b7221f7724ad1becd7;hb=123eee6206d9afb28c169540dc63824957b505f4;hpb=274b04d4a6123fbfe363afc214e908ab36c7e8a7 diff --git a/source/smbd/process.c b/source/smbd/process.c index ff53acbd9e..f2b2a5c15a 100644 --- a/source/smbd/process.c +++ b/source/smbd/process.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. process incoming packets - main loop Copyright (C) Andrew Tridgell 1992-1998 @@ -43,7 +42,8 @@ extern int last_message; 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; @@ -105,16 +105,23 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len) } /**************************************************************************** -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); @@ -123,7 +130,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); - reload_after_sighup = False; + reload_after_sighup = 0; } } @@ -145,7 +152,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len) 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) @@ -188,20 +195,41 @@ 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 @@ -230,7 +258,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ 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 @@ -270,7 +298,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { char buffer[1024]; - fd_set fds; /* * Assert we have no exclusive open oplocks. @@ -282,24 +309,13 @@ void respond_to_all_remaining_local_messages(void) 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; @@ -325,9 +341,9 @@ force write permissions on print services. 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; } @@ -370,7 +386,7 @@ static struct smb_message_struct /* 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}, @@ -383,7 +399,7 @@ static struct smb_message_struct /* 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}, @@ -595,7 +611,7 @@ static struct smb_message_struct /******************************************************************* 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; @@ -609,7 +625,9 @@ static void smb_dump(char *name, int type, char *data, ssize_t len) 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)); } @@ -817,15 +835,11 @@ set. Ignoring max smbd restriction.\n")); } /**************************************************************************** - 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); @@ -853,18 +867,6 @@ void process_smb(char *inbuf, char *outbuf) 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) @@ -894,7 +896,7 @@ void process_smb(char *inbuf, char *outbuf) /**************************************************************************** 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"; @@ -914,14 +916,15 @@ void construct_reply_common(char *inbuf,char *outbuf) 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); @@ -949,7 +952,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* maybe its not chained */ if (smb_com2 == 0xFF) { - CVAL(outbuf,smb_vwv0) = 0xFF; + SCVAL(outbuf,smb_vwv0,0xFF); return outsize; } @@ -969,7 +972,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* 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 */ @@ -991,7 +994,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) 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); @@ -1006,7 +1009,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* 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 */ @@ -1029,13 +1032,8 @@ static int setup_select_timeout(void) 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); @@ -1225,13 +1223,6 @@ void smbd_process(void) 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();