static BOOL process_lock(blocking_lock_record *blr) { char *outbuf = OutBuffer; char *inbuf = blr->inbuf; int outsize; SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; BOOL my_lock_ctx = False; count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); errno = 0; status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx); if (NT_STATUS_IS_ERR(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { /* * We have other than a "can't get lock" * error. Send an error. * Return True so we get dequeued. */ blocking_lock_reply_error(blr, status); return True; } /* * Still can't get the lock - keep waiting. */ DEBUG(10,("process_lock: failed to get lock for file = %s. Still waiting....\n", fsp->fsp_name)); return False; } /* * Success - we got the lock. */ DEBUG(3,("process_lock : file=%s fnum=%d offset=%.0f count=%.0f\n", fsp->fsp_name, fsp->fnum, (double)offset, (double)count)); construct_reply_common(inbuf, outbuf); outsize = set_message(outbuf,0,0,True); send_blocking_reply(outbuf,outsize); return True; }
static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) { char *outbuf = OutBuffer; char *inbuf = blr->inbuf; construct_reply_common(inbuf, outbuf); /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to FILE_LOCK_CONFLICT! (tridge) */ if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { status = NT_STATUS_FILE_LOCK_CONFLICT; } ERROR_NT(status); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("generic_blocking_lock_error: send_smb failed."); }
/**************************************************************************** construct a reply to the incoming packet ****************************************************************************/ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize, int ProcSockID, int threadid) { int type = CVAL(inbuf,smb_com); int outsize = 0; int msg_type = CVAL(inbuf,0); chain_size[threadid] = 0; if (msg_type != 0) return(reply_special(inbuf,outbuf)); construct_reply_common(inbuf, outbuf); outsize = switch_message(type,inbuf,outbuf,size,bufsize, ProcSockID, threadid); outsize += chain_size[threadid]; if(outsize > 4) smb_setlen(outbuf,outsize - 4); return(outsize); }
static void reply_lockingX_success(blocking_lock_record *blr) { char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; int outsize = 0; construct_reply_common(inbuf, outbuf); set_message(outbuf,2,0,True); /* * As this message is a lockingX call we must handle * any following chained message correctly. * This is normally handled in construct_reply(), * but as that calls switch_message, we can't use * that here and must set up the chain info manually. */ outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); outsize += chain_size; send_blocking_reply(outbuf,outsize); }
static BOOL process_lockread(blocking_lock_record *blr) { char *outbuf = OutBuffer; char *inbuf = blr->inbuf; ssize_t nread = -1; char *data, *p; int outsize = 0; SMB_BIG_UINT startpos; size_t numtoread; NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; BOOL my_lock_ctx = False; numtoread = SVAL(inbuf,smb_vwv1); startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx); if (NT_STATUS_V(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { /* * We have other than a "can't get lock" * error. Send an error. * Return True so we get dequeued. */ generic_blocking_lock_error(blr, status); return True; } /* * Still waiting for lock.... */ DEBUG(10,("process_lockread: failed to get lock for file = %s. Still waiting....\n", fsp->fsp_name)); return False; } nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { generic_blocking_lock_error(blr,NT_STATUS_ACCESS_DENIED); return True; } construct_reply_common(inbuf, outbuf); outsize = set_message(outbuf,5,0,True); outsize += nread; SSVAL(outbuf,smb_vwv0,nread); SSVAL(outbuf,smb_vwv5,nread+3); p = smb_buf(outbuf); *p++ = 1; SSVAL(p,0,nread); p += 2; set_message_end(outbuf, p+nread); DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); send_blocking_reply(outbuf,outsize); return True; }
/**************************************************************************** construct a chained reply and add it to the already made reply **************************************************************************/ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize, int ProcSockID ,int threadid) { static char *orig_inbuf[NUM_SMBTHREAD]; static char *orig_outbuf[NUM_SMBTHREAD]; int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); unsigned smb_off2 = SVAL(inbuf,smb_vwv1); char *inbuf2, *outbuf2; int outsize2; char inbuf_saved[smb_wct]; char outbuf_saved[smb_wct]; int wct = CVAL(outbuf,smb_wct); int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); /* maybe its not chained */ if (smb_com2 == 0xFF) { CVAL(outbuf,smb_vwv0) = 0xFF; return outsize; } if (chain_size[threadid] == 0) { /* this is the first part of the chain */ orig_inbuf[threadid] = inbuf; orig_outbuf[threadid] = outbuf; } /* * The original Win95 redirector dies on a reply to * a lockingX and read chain unless the chain reply is * 4 byte aligned. JRA. */ outsize = (outsize + 3) & ~3; /* we need to tell the client where the next part of the reply will be */ //0706 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); SSVAL(outbuf,smb_vwv1,(PTR_DIFF(outbuf+outsize,outbuf+4) + chain_size[threadid])); //smb_offset(p,buf) CVAL(outbuf,smb_vwv0) = smb_com2; /* remember how much the caller added to the chain, only counting stuff after the parameter words */ chain_size[threadid] += outsize - smb_wct; /* work out pointers into the original packets. The headers on these need to be filled in */ inbuf2 = orig_inbuf[threadid] + smb_off2 + 4 - smb_wct; outbuf2 = orig_outbuf[threadid] + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; /* remember the original command type */ smb_com1 = CVAL(orig_inbuf[threadid],smb_com); /* save the data which will be overwritten by the new headers */ memcpy(inbuf_saved,inbuf2,smb_wct); memcpy(outbuf_saved,outbuf2,smb_wct); /* give the new packet the same header as the last part of the SMB */ memmove(inbuf2,inbuf,smb_wct); /* create the in buffer */ CVAL(inbuf2,smb_com) = smb_com2; /* create the out buffer */ construct_reply_common(inbuf2, outbuf2); // DEBUG(3,("Chained message\n")); //0123 show_msg(inbuf2); /* process the request */ outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size[threadid], bufsize-chain_size[threadid], ProcSockID, threadid); /* copy the new reply and request headers over the old ones, but preserve the smb_com field */ memmove(orig_outbuf[threadid],outbuf2,smb_wct); CVAL(orig_outbuf[threadid],smb_com) = smb_com1; /* restore the saved data, being careful not to overwrite any data from the reply header */ memcpy(inbuf2,inbuf_saved,smb_wct); { int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf[threadid]); if (ofs < 0) ofs = 0; memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); } return outsize2; }