diff --git a/source3/include/proto.h b/source3/include/proto.h index fceb83b2822..9624116f824 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -172,7 +172,7 @@ struct in_addr *iface_ip(struct in_addr ip); /*The following definitions come from ipc.c */ int get_printerdrivernumber(int snum); -int reply_trans(char *inbuf,char *outbuf); +int reply_trans(char *inbuf,char *outbuf, int size, int bufsize); /*The following definitions come from kanji.c */ @@ -1071,6 +1071,7 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval); BOOL request_oplock_break(share_mode_entry *share_entry, uint32 dev, uint32 inode); +BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout); BOOL snum_used(int snum); BOOL reload_services(BOOL test); int setup_groups(char *user, int uid, int gid, int *p_ngroups, diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 741290d2a2a..c862ff3b389 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -62,6 +62,8 @@ extern fstring myworkgroup; #define QNLEN 12 /* queue name maximum length */ extern int Client; +extern int oplock_sock; +extern int smb_read_error; static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, @@ -3203,7 +3205,7 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, /**************************************************************************** reply to a SMBtrans ****************************************************************************/ -int reply_trans(char *inbuf,char *outbuf) +int reply_trans(char *inbuf,char *outbuf, int size, int bufsize) { fstring name; @@ -3266,12 +3268,18 @@ int reply_trans(char *inbuf,char *outbuf) /* receive the rest of the trans packet */ while (pscnt < tpscnt || dscnt < tdscnt) { + BOOL ret; int pcnt,poff,dcnt,doff,pdisp,ddisp; - if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || - CVAL(inbuf, smb_com) != SMBtrans) + ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT); + + if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) { - DEBUG(2,("Invalid secondary trans2 packet\n")); + if(ret) + DEBUG(0,("reply_trans: Invalid secondary trans packet\n")); + else + DEBUG(0,("reply_trans: %s in getting secondary trans response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); if (params) free(params); if (data) free(data); if (setup) free(setup); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 78dad6f02f5..0d5f0166139 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3495,7 +3495,14 @@ dev = %x, inode = %x\n", /* if this is a pure oplock break request then don't send a reply */ if (num_locks == 0 && num_ulocks == 0) - return -1; + { + /* Sanity check - ensure a pure oplock break is not a + chained request. */ + if(CVAL(inbuf,smb_vwv0) != 0xff) + DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", + (unsigned int)CVAL(inbuf,smb_vwv0) )); + return -1; + } } /* Data now points at the beginning of the list diff --git a/source3/smbd/server.c b/source3/smbd/server.c index d51c43c2f79..3f4f6c70347 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3086,6 +3086,32 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", return True; } +/**************************************************************************** +Get the next SMB packet, doing the local message processing automatically. +****************************************************************************/ + +BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout) +{ + BOOL got_smb = False; + BOOL ret; + + do + { + ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize, + timeout,&got_smb); + + if(ret && !got_smb) + { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(oplock_sock, inbuf, bufsize); + continue; + } + } + while(ret && !got_smb); + + return ret; +} + /**************************************************************************** check if a snum is in use ****************************************************************************/ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 6a7fc292fae..0ca678b7682 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -30,6 +30,8 @@ extern connection_struct Connections[]; extern files_struct Files[]; extern BOOL case_sensitive; extern int Client; +extern int oplock_sock; +extern int smb_read_error; /**************************************************************************** Send the required number of replies back. @@ -1702,11 +1704,19 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) while( num_data_sofar < total_data || num_params_sofar < total_params) { - if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || - CVAL(inbuf, smb_com) != SMBtranss2) + BOOL ret; + + ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize, + SMB_SECONDARY_WAIT); + + if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) { outsize = set_message(outbuf,0,0,True); - DEBUG(2,("Invalid secondary trans2 packet\n")); + if(ret) + DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n")); + else + DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n", + (smb_read_error == READ_ERROR) ? "error" : "timeout" )); free(params); free(data); return(ERROR(ERRSRV,ERRerror));