⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 2 页
字号:
			buffer->Flags  |= SMBFLG_CASELESS;		if ((treeCon->ses) && (treeCon->ses->server))			if (treeCon->ses->server->secMode &			  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;	}/*  endian conversion of flags is now done just before sending */	buffer->WordCount = (char) word_count;	return;}static intcheckSMBhdr(struct smb_hdr *smb, __u16 mid){	/* Make sure that this really is an SMB, that it is a response,	   and that the message ids match */	if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&		(mid == smb->Mid)) {		if (smb->Flags & SMBFLG_RESPONSE)			return 0;		else {		/* only one valid case where server sends us request */			if (smb->Command == SMB_COM_LOCKING_ANDX)				return 0;			else				cERROR(1, ("Received Request not response"));		}	} else { /* bad signature or mid */		if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))			cERROR(1,			       ("Bad protocol string signature header %x",				*(unsigned int *) smb->Protocol));		if (mid != smb->Mid)			cERROR(1, ("Mids do not match"));	}	cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));	return 1;}intcheckSMB(struct smb_hdr *smb, __u16 mid, unsigned int length){	__u32 len = smb->smb_buf_length;	__u32 clc_len;  /* calculated length */	cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));	if (length < 2 + sizeof (struct smb_hdr)) {		if ((length >= sizeof (struct smb_hdr) - 1)			    && (smb->Status.CifsError != 0)) {			smb->WordCount = 0;			/* some error cases do not return wct and bcc */			return 0;		} else if ((length == sizeof(struct smb_hdr) + 1) &&				(smb->WordCount == 0)) {			char *tmp = (char *)smb;			/* Need to work around a bug in two servers here */			/* First, check if the part of bcc they sent was zero */			if (tmp[sizeof(struct smb_hdr)] == 0) {				/* some servers return only half of bcc				 * on simple responses (wct, bcc both zero)				 * in particular have seen this on				 * ulogoffX and FindClose. This leaves				 * one byte of bcc potentially unitialized				 */				/* zero rest of bcc */				tmp[sizeof(struct smb_hdr)+1] = 0;				return 0;			}			cERROR(1, ("rcvd invalid byte count (bcc)"));		} else {			cERROR(1, ("Length less than smb header size"));		}		return 1;	}	if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {		cERROR(1, ("smb length greater than MaxBufSize, mid=%d",				   smb->Mid));		return 1;	}	if (checkSMBhdr(smb, mid))		return 1;	clc_len = smbCalcSize_LE(smb);	if (4 + len != length) {		cERROR(1, ("Length read does not match RFC1001 length %d",			   len));		return 1;	}	if (4 + len != clc_len) {		/* check if bcc wrapped around for large read responses */		if ((len > 64 * 1024) && (len > clc_len)) {			/* check if lengths match mod 64K */			if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))				return 0; /* bcc wrapped */		}		cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",				clc_len, 4 + len, smb->Mid));		/* Windows XP can return a few bytes too much, presumably		an illegal pad, at the end of byte range lock responses		so we allow for that three byte pad, as long as actual		received length is as long or longer than calculated length */		/* We have now had to extend this more, since there is a		case in which it needs to be bigger still to handle a		malformed response to transact2 findfirst from WinXP when		access denied is returned and thus bcc and wct are zero		but server says length is 0x21 bytes too long as if the server		forget to reset the smb rfc1001 length when it reset the		wct and bcc to minimum size and drop the t2 parms and data */		if ((4+len > clc_len) && (len <= clc_len + 512))			return 0;		else {			cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",					len, smb->Mid));			return 1;		}	}	return 0;}intis_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv){	struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;	struct list_head *tmp;	struct list_head *tmp1;	struct cifsTconInfo *tcon;	struct cifsFileInfo *netfile;	cFYI(1, ("Checking for oplock break or dnotify response"));	if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&	   (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {		struct smb_com_transaction_change_notify_rsp *pSMBr =			(struct smb_com_transaction_change_notify_rsp *)buf;		struct file_notify_information *pnotify;		__u32 data_offset = 0;		if (pSMBr->ByteCount > sizeof(struct file_notify_information)) {			data_offset = le32_to_cpu(pSMBr->DataOffset);			pnotify = (struct file_notify_information *)				((char *)&pSMBr->hdr.Protocol + data_offset);			cFYI(1, ("dnotify on %s Action: 0x%x",				 pnotify->FileName,				pnotify->Action));  /* BB removeme BB */			/*   cifs_dump_mem("Rcvd notify Data: ",buf,				sizeof(struct smb_hdr)+60); */			return TRUE;		}		if (pSMBr->hdr.Status.CifsError) {			cFYI(1, ("notify err 0x%d",				pSMBr->hdr.Status.CifsError));			return TRUE;		}		return FALSE;	}	if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)		return FALSE;	if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {		/* no sense logging error on invalid handle on oplock		   break - harmless race between close request and oplock		   break response is expected from time to time writing out		   large dirty files cached on the client */		if ((NT_STATUS_INVALID_HANDLE) ==		   le32_to_cpu(pSMB->hdr.Status.CifsError)) {			cFYI(1, ("invalid handle on oplock break"));			return TRUE;		} else if (ERRbadfid ==		   le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {			return TRUE;		} else {			return FALSE; /* on valid oplock brk we get "request" */		}	}	if (pSMB->hdr.WordCount != 8)		return FALSE;	cFYI(1, ("oplock type 0x%d level 0x%d",		 pSMB->LockType, pSMB->OplockLevel));	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))		return FALSE;	/* look up tcon based on tid & uid */	read_lock(&GlobalSMBSeslock);	list_for_each(tmp, &GlobalTreeConnectionList) {		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);		if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) {			cifs_stats_inc(&tcon->num_oplock_brks);			list_for_each(tmp1, &tcon->openFileList) {				netfile = list_entry(tmp1, struct cifsFileInfo,						     tlist);				if (pSMB->Fid == netfile->netfid) {					struct cifsInodeInfo *pCifsInode;					read_unlock(&GlobalSMBSeslock);					cFYI(1,					    ("file id match, oplock break"));					pCifsInode =						CIFS_I(netfile->pInode);					pCifsInode->clientCanCacheAll = FALSE;					if (pSMB->OplockLevel == 0)						pCifsInode->clientCanCacheRead							= FALSE;					pCifsInode->oplockPending = TRUE;					AllocOplockQEntry(netfile->pInode,							  netfile->netfid,							  tcon);					cFYI(1,					    ("about to wake up oplock thread"));					if (oplockThread)					    wake_up_process(oplockThread);					return TRUE;				}			}			read_unlock(&GlobalSMBSeslock);			cFYI(1, ("No matching file for oplock break"));			return TRUE;		}	}	read_unlock(&GlobalSMBSeslock);	cFYI(1, ("Can not process oplock break for non-existent connection"));	return TRUE;}voiddump_smb(struct smb_hdr *smb_buf, int smb_buf_length){	int i, j;	char debug_line[17];	unsigned char *buffer;	if (traceSMB == 0)		return;	buffer = (unsigned char *) smb_buf;	for (i = 0, j = 0; i < smb_buf_length; i++, j++) {		if (i % 8 == 0) {	/* have reached the beginning of line */			printk(KERN_DEBUG "| ");			j = 0;		}		printk("%0#4x ", buffer[i]);		debug_line[2 * j] = ' ';		if (isprint(buffer[i]))			debug_line[1 + (2 * j)] = buffer[i];		else			debug_line[1 + (2 * j)] = '_';		if (i % 8 == 7) { /* reached end of line, time to print ascii */			debug_line[16] = 0;			printk(" | %s\n", debug_line);		}	}	for (; j < 8; j++) {		printk("     ");		debug_line[2 * j] = ' ';		debug_line[1 + (2 * j)] = ' ';	}	printk( " | %s\n", debug_line);	return;}/* Windows maps these to the user defined 16 bit Unicode range since they are   reserved symbols (along with \ and /), otherwise illegal to store   in filenames in NTFS */#define UNI_ASTERIK     (__u16) ('*' + 0xF000)#define UNI_QUESTION    (__u16) ('?' + 0xF000)#define UNI_COLON       (__u16) (':' + 0xF000)#define UNI_GRTRTHAN    (__u16) ('>' + 0xF000)#define UNI_LESSTHAN    (__u16) ('<' + 0xF000)#define UNI_PIPE        (__u16) ('|' + 0xF000)#define UNI_SLASH       (__u16) ('\\' + 0xF000)/* Convert 16 bit Unicode pathname from wire format to string in current code   page.  Conversion may involve remapping up the seven characters that are   only legal in POSIX-like OS (if they are present in the string). Path   names are little endian 16 bit Unicode on the wire */intcifs_convertUCSpath(char *target, const __le16 *source, int maxlen,		    const struct nls_table *cp){	int i, j, len;	__u16 src_char;	for (i = 0, j = 0; i < maxlen; i++) {		src_char = le16_to_cpu(source[i]);		switch (src_char) {			case 0:				goto cUCS_out; /* BB check this BB */			case UNI_COLON:				target[j] = ':';				break;			case UNI_ASTERIK:				target[j] = '*';				break;			case UNI_QUESTION:				target[j] = '?';				break;			/* BB We can not handle remapping slash until			   all the calls to build_path_from_dentry			   are modified, as they use slash as separator BB */			/* case UNI_SLASH:				target[j] = '\\';				break;*/			case UNI_PIPE:				target[j] = '|';				break;			case UNI_GRTRTHAN:				target[j] = '>';				break;			case UNI_LESSTHAN:				target[j] = '<';				break;			default:				len = cp->uni2char(src_char, &target[j],						NLS_MAX_CHARSET_SIZE);				if (len > 0) {					j += len;					continue;				} else {					target[j] = '?';				}		}		j++;		/* make sure we do not overrun callers allocated temp buffer */		if (j >= (2 * NAME_MAX))			break;	}cUCS_out:	target[j] = 0;	return j;}/* Convert 16 bit Unicode pathname to wire format from string in current code   page.  Conversion may involve remapping up the seven characters that are   only legal in POSIX-like OS (if they are present in the string). Path   names are little endian 16 bit Unicode on the wire */intcifsConvertToUCS(__le16 *target, const char *source, int maxlen,		 const struct nls_table *cp, int mapChars){	int i, j, charlen;	int len_remaining = maxlen;	char src_char;	__u16 temp;	if (!mapChars)		return cifs_strtoUCS(target, source, PATH_MAX, cp);	for (i = 0, j = 0; i < maxlen; j++) {		src_char = source[i];		switch (src_char) {			case 0:				target[j] = 0;				goto ctoUCS_out;			case ':':				target[j] = cpu_to_le16(UNI_COLON);				break;			case '*':				target[j] = cpu_to_le16(UNI_ASTERIK);				break;			case '?':				target[j] = cpu_to_le16(UNI_QUESTION);				break;			case '<':				target[j] = cpu_to_le16(UNI_LESSTHAN);				break;			case '>':				target[j] = cpu_to_le16(UNI_GRTRTHAN);				break;			case '|':				target[j] = cpu_to_le16(UNI_PIPE);				break;			/* BB We can not handle remapping slash until			   all the calls to build_path_from_dentry			   are modified, as they use slash as separator BB */			/* case '\\':				target[j] = cpu_to_le16(UNI_SLASH);				break;*/			default:				charlen = cp->char2uni(source+i,					len_remaining, &temp);				/* if no match, use question mark, which				at least in some cases servers as wild card */				if (charlen < 1) {					target[j] = cpu_to_le16(0x003f);					charlen = 1;				} else					target[j] = cpu_to_le16(temp);				len_remaining -= charlen;				/* character may take more than one byte in the				   the source string, but will take exactly two				   bytes in the target string */				i += charlen;				continue;		}		i++; /* move to next char in source string */		len_remaining--;	}ctoUCS_out:	return i;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -