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

📄 connect.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 5 页
字号:
		} else if (strnicmp(data, "in6_addr", 8) == 0) {			if (!value || !*value) {				vol->in6_addr = NULL;			} else if (strnlen(value, 49) == 48) {				vol->in6_addr = value;			} else {				printk(KERN_WARNING "CIFS: ip v6 address not "						    "48 characters long\n");				return 1;			}		} else if (strnicmp(data, "noac", 4) == 0) {			printk(KERN_WARNING "CIFS: Mount option noac not "				"supported. Instead set "				"/proc/fs/cifs/LookupCacheEnabled to 0\n");		} else			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",						data);	}	if (vol->UNC == NULL) {		if (devname == NULL) {			printk(KERN_WARNING "CIFS: Missing UNC name for mount "						"target\n");			return 1;		}		if ((temp_len = strnlen(devname, 300)) < 300) {			vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);			if (vol->UNC == NULL)				return 1;			strcpy(vol->UNC, devname);			if (strncmp(vol->UNC, "//", 2) == 0) {				vol->UNC[0] = '\\';				vol->UNC[1] = '\\';			} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {				printk(KERN_WARNING "CIFS: UNC Path does not "						    "begin with // or \\\\ \n");				return 1;			}		} else {			printk(KERN_WARNING "CIFS: UNC name too long\n");			return 1;		}	}	if (vol->UNCip == NULL)		vol->UNCip = &vol->UNC[2];	return 0;}static struct cifsSesInfo *cifs_find_tcp_session(struct in_addr *target_ip_addr,		struct in6_addr *target_ip6_addr,		 char *userName, struct TCP_Server_Info **psrvTcp){	struct list_head *tmp;	struct cifsSesInfo *ses;	*psrvTcp = NULL;	read_lock(&GlobalSMBSeslock);	list_for_each(tmp, &GlobalSMBSessionList) {		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);		if (ses->server) {			if ((target_ip_addr &&				(ses->server->addr.sockAddr.sin_addr.s_addr				  == target_ip_addr->s_addr)) || (target_ip6_addr				&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,					target_ip6_addr, sizeof(*target_ip6_addr)))) {				/* BB lock server and tcp session and increment				      use count here?? */				/* found a match on the TCP session */				*psrvTcp = ses->server;				/* BB check if reconnection needed */				if (strncmp				    (ses->userName, userName,				     MAX_USERNAME_SIZE) == 0){					read_unlock(&GlobalSMBSeslock);					/* Found exact match on both TCP and					   SMB sessions */					return ses;				}			}		}		/* else tcp and smb sessions need reconnection */	}	read_unlock(&GlobalSMBSeslock);	return NULL;}static struct cifsTconInfo *find_unc(__be32 new_target_ip_addr, char *uncName, char *userName){	struct list_head *tmp;	struct cifsTconInfo *tcon;	read_lock(&GlobalSMBSeslock);	list_for_each(tmp, &GlobalTreeConnectionList) {		cFYI(1, ("Next tcon"));		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);		if (tcon->ses) {			if (tcon->ses->server) {				cFYI(1,				     ("old ip addr: %x == new ip %x ?",				      tcon->ses->server->addr.sockAddr.sin_addr.				      s_addr, new_target_ip_addr));				if (tcon->ses->server->addr.sockAddr.sin_addr.				    s_addr == new_target_ip_addr) {	/* BB lock tcon, server and tcp session and increment use count here? */					/* found a match on the TCP session */					/* BB check if reconnection needed */					cFYI(1,					      ("IP match, old UNC: %s new: %s",					      tcon->treeName, uncName));					if (strncmp					    (tcon->treeName, uncName,					     MAX_TREE_SIZE) == 0) {						cFYI(1,						     ("and old usr: %s new: %s",						      tcon->treeName, uncName));						if (strncmp						    (tcon->ses->userName,						     userName,						     MAX_USERNAME_SIZE) == 0) {							read_unlock(&GlobalSMBSeslock);							/* matched smb session							(user name */							return tcon;						}					}				}			}		}	}	read_unlock(&GlobalSMBSeslock);	return NULL;}intconnect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,		    const char *old_path, const struct nls_table *nls_codepage,		    int remap){	unsigned char *referrals = NULL;	unsigned int num_referrals;	int rc = 0;	rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage,			&num_referrals, &referrals, remap);	/* BB Add in code to: if valid refrl, if not ip address contact		the helper that resolves tcp names, mount to it, try to		tcon to it unmount it if fail */	kfree(referrals);	return rc;}intget_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,	     const struct nls_table *nls_codepage, unsigned int *pnum_referrals,	     unsigned char **preferrals, int remap){	char *temp_unc;	int rc = 0;	*pnum_referrals = 0;	if (pSesInfo->ipc_tid == 0) {		temp_unc = kmalloc(2 /* for slashes */ +			strnlen(pSesInfo->serverName,				SERVER_NAME_LEN_WITH_NULL * 2)				 + 1 + 4 /* slash IPC$ */  + 2,				GFP_KERNEL);		if (temp_unc == NULL)			return -ENOMEM;		temp_unc[0] = '\\';		temp_unc[1] = '\\';		strcpy(temp_unc + 2, pSesInfo->serverName);		strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");		rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);		cFYI(1,		     ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));		kfree(temp_unc);	}	if (rc == 0)		rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,				     pnum_referrals, nls_codepage, remap);	return rc;}/* See RFC1001 section 14 on representation of Netbios names */static void rfc1002mangle(char *target, char *source, unsigned int length){	unsigned int i, j;	for (i = 0, j = 0; i < (length); i++) {		/* mask a nibble at a time and encode */		target[j] = 'A' + (0x0F & (source[i] >> 4));		target[j+1] = 'A' + (0x0F & source[i]);		j += 2;	}}static intipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,	     char *netbios_name, char *target_name){	int rc = 0;	int connected = 0;	__be16 orig_port = 0;	if (*csocket == NULL) {		rc = sock_create_kern(PF_INET, SOCK_STREAM,				      IPPROTO_TCP, csocket);		if (rc < 0) {			cERROR(1, ("Error %d creating socket", rc));			*csocket = NULL;			return rc;		} else {		/* BB other socket options to set KEEPALIVE, NODELAY? */			cFYI(1, ("Socket created"));#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)			(*csocket)->sk->sk_allocation = GFP_NOFS;#else			(*csocket)->sk->allocation = GFP_NOFS;#endif		}	}	psin_server->sin_family = AF_INET;	if (psin_server->sin_port) { /* user overrode default port */		rc = (*csocket)->ops->connect(*csocket,				(struct sockaddr *) psin_server,				sizeof (struct sockaddr_in), 0);		if (rc >= 0)			connected = 1;	}	if (!connected) {		/* save original port so we can retry user specified port			later if fall back ports fail this time  */		orig_port = psin_server->sin_port;		/* do not retry on the same port we just failed on */		if (psin_server->sin_port != htons(CIFS_PORT)) {			psin_server->sin_port = htons(CIFS_PORT);			rc = (*csocket)->ops->connect(*csocket,					(struct sockaddr *) psin_server,					sizeof (struct sockaddr_in), 0);			if (rc >= 0)				connected = 1;		}	}	if (!connected) {		psin_server->sin_port = htons(RFC1001_PORT);		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)					      psin_server,					      sizeof (struct sockaddr_in), 0);		if (rc >= 0)			connected = 1;	}	/* give up here - unless we want to retry on different		protocol families some day */	if (!connected) {		if (orig_port)			psin_server->sin_port = orig_port;		cFYI(1, ("Error %d connecting to server via ipv4", rc));		sock_release(*csocket);		*csocket = NULL;		return rc;	}	/* Eventually check for other socket options to change from		the default. sock_setsockopt not used because it expects		user space buffer */#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",		 (*csocket)->sk->sk_sndbuf,		 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;	/* make the bufsizes depend on wsize/rsize and max requests */	if ((*csocket)->sk->sk_sndbuf < (200 * 1024))		(*csocket)->sk->sk_sndbuf = 200 * 1024;	if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))		(*csocket)->sk->sk_rcvbuf = 140 * 1024;#else         cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sndbuf,                 (*csocket)->sk->rcvbuf, (*csocket)->sk->rcvtimeo));        (*csocket)->sk->rcvtimeo = 7 * HZ;        /* make the bufsizes depend on wsize/rsize and max requests */        if((*csocket)->sk->sndbuf < (200 * 1024))                (*csocket)->sk->sndbuf = 200 * 1024;        if((*csocket)->sk->rcvbuf < (140 * 1024))                (*csocket)->sk->rcvbuf = 140 * 1024;#endif	/* send RFC1001 sessinit */	if (psin_server->sin_port == htons(RFC1001_PORT)) {		/* some servers require RFC1001 sessinit before sending		negprot - BB check reconnection in case where second		sessinit is sent but no second negprot */		struct rfc1002_session_packet *ses_init_buf;		struct smb_hdr *smb_buf;		ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),				       GFP_KERNEL);		if (ses_init_buf) {			ses_init_buf->trailer.session_req.called_len = 32;			if (target_name && (target_name[0] != 0)) {				rfc1002mangle(ses_init_buf->trailer.session_req.called_name,					target_name, 16);			} else {				rfc1002mangle(ses_init_buf->trailer.session_req.called_name,					DEFAULT_CIFS_CALLED_NAME, 16);			}			ses_init_buf->trailer.session_req.calling_len = 32;			/* calling name ends in null (byte 16) from old smb			convention. */			if (netbios_name && (netbios_name[0] != 0)) {				rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,					netbios_name, 16);			} else {				rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,					"LINUX_CIFS_CLNT", 16);			}			ses_init_buf->trailer.session_req.scope1 = 0;			ses_init_buf->trailer.session_req.scope2 = 0;			smb_buf = (struct smb_hdr *)ses_init_buf;			/* sizeof RFC1002_SESSION_REQUEST with no scope */			smb_buf->smb_buf_length = 0x81000044;			rc = smb_send(*csocket, smb_buf, 0x44,				(struct sockaddr *)psin_server);			kfree(ses_init_buf);			msleep(1); /* RFC1001 layer in at least one server				      requires very short break before negprot				      presumably because not expecting negprot				      to follow so fast.  This is a simple				      solution that works without				      complicating the code and causes no				      significant slowing down on mount				      for everyone else */		}		/* else the negprot may still work without this		even though malloc failed */	}	return rc;}static intipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket){	int rc = 0;	int connected = 0;	__be16 orig_port = 0;	if (*csocket == NULL) {		rc = sock_create_kern(PF_INET6, SOCK_STREAM,				      IPPROTO_TCP, csocket);		if (rc < 0) {			cERROR(1, ("Error %d creating ipv6 socket", rc));			*csocket = NULL;			return rc;		} else {		/* BB other socket options to set KEEPALIVE, NODELAY? */			 cFYI(1, ("ipv6 Socket created"));#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)			(*csocket)->sk->sk_allocation = GFP_NOFS;#else			(*csocket)->sk->allocation = GFP_NOFS;#endif		}	}	psin_server->sin6_family = AF_INET6;	if (psin_server->sin6_port) { /* user overrode default port */		rc = (*csocket)->ops->connect(*csocket,				(struct sockaddr *) psin_server,				sizeof (struct sockaddr_in6), 0);		if (rc >= 0)			connected = 1;	}	if (!connected) {		/* save original port so we can retry user specified port			later if fall back ports fail this time  */		orig_port = psin_server->sin6_port;		/* do not retry on the same port we just failed on */		if (psin_server->sin6_port != htons(CIFS_PORT)) {			psin_server->sin6_port = htons(CIFS_PORT);			rc = (*csocket)->ops->connect(*csocket,					(struct sockaddr *) psin_server,					sizeof (struct sockaddr_in6), 0);			if (rc >= 0)				connected = 1;		}	}	if (!connected) {		psin_server->sin6_port = htons(RFC1001_PORT);		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)				 psin_server, sizeof (struct sockaddr_in6), 0);		if (rc >= 0)			connected = 1;	}	/* give up here - unless we want to retry on different		protocol families some day */	if (!connected) {		if (orig_port)			psin_server->sin6_port = orig_port;		cFYI(1, ("Error %d connecting to server via ipv6", rc));		sock_release(*csocket);		*csocket = NULL;		return rc;	}	/* Eventually check for other socket options to change from		the default. sock_setsockopt not used because it expects		user space buffer */#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;#else	(*csocket)->sk->rcvtimeo = 7 * HZ;#endif

⌨️ 快捷键说明

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