diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/include/proto.h | 2 | ||||
-rw-r--r-- | source/include/smb.h | 12 | ||||
-rw-r--r-- | source/lib/util.c | 4 | ||||
-rw-r--r-- | source/smbd/server.c | 74 | ||||
-rw-r--r-- | source/smbd/trans2.c | 2 |
5 files changed, 57 insertions, 37 deletions
diff --git a/source/include/proto.h b/source/include/proto.h index 51433333c50..35d43afe0ca 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -722,7 +722,7 @@ int find_service(char *service); int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line); int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line); int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line); -BOOL oplock_break(uint32 dev, uint32 inode); +BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval); BOOL request_oplock_break(min_share_mode_entry *share_entry, uint32 dev, uint32 inode); BOOL snum_used(int snum); diff --git a/source/include/smb.h b/source/include/smb.h index 509c1e1cf15..66da2099c77 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -1049,17 +1049,19 @@ extern int unix_ERR_code; * * Form of this is : * - * 0 2 6 10 - * +----+--------+--------+--------+ - * | cmd| pid | dev | inode | - * +----+--------+--------+--------+ + * 0 2 6 10 14 18 22 + * +----+--------+--------+--------+-------+--------+ + * | cmd| pid | dev | inode | sec | usec | + * +----+--------+--------+--------+-------+--------+ */ #define OPLOCK_BREAK_CMD 0x1 #define OPLOCK_BREAK_PID_OFFSET 2 #define OPLOCK_BREAK_DEV_OFFSET 6 #define OPLOCK_BREAK_INODE_OFFSET 10 -#define OPLOCK_BREAK_MSG_LEN 14 +#define OPLOCK_BREAK_SEC_OFFSET 14 +#define OPLOCK_BREAK_USEC_OFFSET 18 +#define OPLOCK_BREAK_MSG_LEN 22 #define CMD_REPLY 0x8000 diff --git a/source/lib/util.c b/source/lib/util.c index e65e708139c..3317efb8041 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -2860,7 +2860,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) if (strequal(p1,"*")) return(True); - DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig)); + DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig)); if (trans2) { fstrcpy(ebase,p1); @@ -2888,7 +2888,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) matched = do_match(sbase,ebase,case_sig) && (trans2 || do_match(sext,eext,case_sig)); - DEBUG(5,("mask_match returning %d\n", matched)); + DEBUG(8,("mask_match returning %d\n", matched)); return matched; } diff --git a/source/smbd/server.c b/source/smbd/server.c index 19cc5b9abb8..d7620a5804e 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -1404,7 +1404,8 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - if (old_deny == new_deny && share_pid == getpid()) + int pid = getpid(); + if (old_deny == new_deny && share_pid == pid) return(AALL); if (old_mode == 0) return(AREAD); @@ -1487,16 +1488,12 @@ BOOL check_file_sharing(int cnum,char *fname) { min_share_mode_entry *share_entry = &old_shares[i]; - /* someone else has a share lock on it, check to see - if we can too */ - if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) - goto free_and_exit; - #ifdef USE_OPLOCKS /* - * The share modes would give us access. Check if someone - * has an oplock on this file. If so we must break it before - * continuing. + * Break oplocks before checking share modes. See comment in + * open_file_shared for details. + * Check if someone has an oplock on this file. If so we must + * break it before continuing. */ if(share_entry->op_type & BATCH_OPLOCK) { @@ -1518,6 +1515,12 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); break; } #endif /* USE_OPLOCKS */ + + /* someone else has a share lock on it, check to see + if we can too */ + if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) + goto free_and_exit; + } /* end for */ if(broke_oplock) @@ -1727,22 +1730,13 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { min_share_mode_entry *share_entry = &old_shares[i]; - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(cnum, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } #ifdef USE_OPLOCKS /* - * The share modes would give us access. Check if someone - * has an oplock on this file. If so we must break it before - * continuing. + * By observation of NetBench, oplocks are broken *before* share + * modes are checked. This allows a file to be closed by the client + * if the share mode would deny access and the client has an oplock. + * Check if someone has an oplock on this file. If so we must break + * it before continuing. */ if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) { @@ -1767,6 +1761,19 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); break; } #endif /* USE_OPLOCKS */ + + /* someone else has a share lock on it, check to see + if we can too */ + if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) + { + free((char *)old_shares); + unlock_share_entry(cnum, dev, inode, token); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } + } /* end for */ if(broke_oplock) @@ -2428,7 +2435,7 @@ static void process_smb(char *inbuf, char *outbuf) static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; DEBUG(1,("%s Connection denied from %s\n", timestring(),client_addr())); - send_smb(Client,buf); + send_smb(Client,(char *)buf); exit_server("connection denied"); } } @@ -2535,8 +2542,12 @@ should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + struct timeval tval; struct sockaddr_in toaddr; + tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); + tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); + DEBUG(5,("process_local_message: oplock break request from \ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); @@ -2549,7 +2560,7 @@ pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); if(global_oplocks_open != 0) { - if(oplock_break(dev, inode) == False) + if(oplock_break(dev, inode, &tval) == False) { DEBUG(0,("process_local_message: oplock break failed - \ not returning udp message.\n")); @@ -2595,7 +2606,7 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, /**************************************************************************** Process an oplock break directly. ****************************************************************************/ -BOOL oplock_break(uint32 dev, uint32 inode) +BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) { extern int Client; static char *inbuf = NULL; @@ -2633,7 +2644,9 @@ global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); if(OPEN_FNUM(fnum)) { fsp = &Files[fnum]; - if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode)) + if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) && + (fsp->open_time.tv_sec == tval->tv_sec) && + (fsp->open_time.tv_usec == tval->tv_usec)) break; } } @@ -2797,8 +2810,11 @@ BOOL request_oplock_break(min_share_mode_entry *share_entry, should be %d\n", pid, share_entry->op_port, oplock_port)); return False; } + + DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + /* Call oplock break direct. */ - return oplock_break(dev, inode); + return oplock_break(dev, inode, &share_entry->time); } /* We need to send a OPLOCK_BREAK_CMD message to the @@ -2808,6 +2824,8 @@ should be %d\n", pid, share_entry->op_port, oplock_port)); SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); + SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); + SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); /* set the address and port */ bzero((char *)&addr_out,sizeof(addr_out)); diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 8ab024ded28..56f153f12fb 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -319,7 +319,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l reskey = TellDir(Connections[cnum].dirptr); - DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", + DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); if (!dname) |