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

📄 socket.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 3 页
字号:
	msg.msg_name=NULL;	msg.msg_namelen=0;	msg.msg_iov=&iov;	msg.msg_iovlen=1;	msg.msg_control=NULL;	msg.msg_controllen=0;	msg.msg_flags=!(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;	if (sock->type == SOCK_SEQPACKET)		msg.msg_flags |= MSG_EOR;	iov.iov_base=(void *)ubuf;	iov.iov_len=size;		return sock_sendmsg(sock, &msg, size);}ssize_t sock_sendpage(struct file *file, struct page *page,		      int offset, size_t size, loff_t *ppos, int more){	struct socket *sock;	int flags;	if (ppos != &file->f_pos)		return -ESPIPE;	sock = socki_lookup(file->f_dentry->d_inode);	flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;	if (more)		flags |= MSG_MORE;	return sock->ops->sendpage(sock, page, offset, size, flags);}int sock_readv_writev(int type, struct inode * inode, struct file * file,		      const struct iovec * iov, long count, long size){	struct msghdr msg;	struct socket *sock;	sock = socki_lookup(inode);	msg.msg_name = NULL;	msg.msg_namelen = 0;	msg.msg_control = NULL;	msg.msg_controllen = 0;	msg.msg_iov = (struct iovec *) iov;	msg.msg_iovlen = count;	msg.msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;	/* read() does a VERIFY_WRITE */	if (type == VERIFY_WRITE)		return sock_recvmsg(sock, &msg, size, msg.msg_flags);	if (sock->type == SOCK_SEQPACKET)		msg.msg_flags |= MSG_EOR;	return sock_sendmsg(sock, &msg, size);}static ssize_t sock_readv(struct file *file, const struct iovec *vector,			  unsigned long count, loff_t *ppos){	size_t tot_len = 0;	int i;        for (i = 0 ; i < count ; i++)                tot_len += vector[i].iov_len;	return sock_readv_writev(VERIFY_WRITE, file->f_dentry->d_inode,				 file, vector, count, tot_len);}	static ssize_t sock_writev(struct file *file, const struct iovec *vector,			   unsigned long count, loff_t *ppos){	size_t tot_len = 0;	int i;        for (i = 0 ; i < count ; i++)                tot_len += vector[i].iov_len;	return sock_readv_writev(VERIFY_READ, file->f_dentry->d_inode,				 file, vector, count, tot_len);}/* *	With an ioctl arg may well be a user mode pointer, but we don't know what to do *	with it - that's up to the protocol still. */int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,	   unsigned long arg){	struct socket *sock;	int err;	unlock_kernel();	sock = socki_lookup(inode);	err = sock->ops->ioctl(sock, cmd, arg);	lock_kernel();	return err;}/* No kernel lock held - perfect */static unsigned int sock_poll(struct file *file, poll_table * wait){	struct socket *sock;	/*	 *	We can't return errors to poll, so it's either yes or no. 	 */	sock = socki_lookup(file->f_dentry->d_inode);	return sock->ops->poll(file, sock, wait);}static int sock_mmap(struct file * file, struct vm_area_struct * vma){	struct socket *sock = socki_lookup(file->f_dentry->d_inode);	return sock->ops->mmap(file, sock, vma);}int sock_close(struct inode *inode, struct file *filp){	/*	 *	It was possible the inode is NULL we were 	 *	closing an unfinished socket. 	 */	if (!inode)	{		printk(KERN_DEBUG "sock_close: NULL inode\n");		return 0;	}	sock_fasync(-1, filp, 0);	sock_release(socki_lookup(inode));	return 0;}/* *	Update the socket async list * *	Fasync_list locking strategy. * *	1. fasync_list is modified only under process context socket lock *	   i.e. under semaphore. *	2. fasync_list is used under read_lock(&sk->callback_lock) *	   or under socket lock. *	3. fasync_list can be used from softirq context, so that *	   modification under socket lock have to be enhanced with *	   write_lock_bh(&sk->callback_lock). *							--ANK (990710) */static int sock_fasync(int fd, struct file *filp, int on){	struct fasync_struct *fa, *fna=NULL, **prev;	struct socket *sock;	struct sock *sk;	if (on)	{		fna=(struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);		if(fna==NULL)			return -ENOMEM;	}	sock = socki_lookup(filp->f_dentry->d_inode);		if ((sk=sock->sk) == NULL)		return -EINVAL;	lock_sock(sk);	prev=&(sock->fasync_list);	for (fa=*prev; fa!=NULL; prev=&fa->fa_next,fa=*prev)		if (fa->fa_file==filp)			break;	if(on)	{		if(fa!=NULL)		{			write_lock_bh(&sk->callback_lock);			fa->fa_fd=fd;			write_unlock_bh(&sk->callback_lock);			kfree(fna);			goto out;		}		fna->fa_file=filp;		fna->fa_fd=fd;		fna->magic=FASYNC_MAGIC;		fna->fa_next=sock->fasync_list;		write_lock_bh(&sk->callback_lock);		sock->fasync_list=fna;		write_unlock_bh(&sk->callback_lock);	}	else	{		if (fa!=NULL)		{			write_lock_bh(&sk->callback_lock);			*prev=fa->fa_next;			write_unlock_bh(&sk->callback_lock);			kfree(fa);		}	}out:	release_sock(sock->sk);	return 0;}/* This function may be called only under socket lock or callback_lock */int sock_wake_async(struct socket *sock, int how, int band){	if (!sock || !sock->fasync_list)		return -1;	switch (how)	{	case 1:				if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))			break;		goto call_kill;	case 2:		if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))			break;		/* fall through */	case 0:	call_kill:		__kill_fasync(sock->fasync_list, SIGIO, band);		break;	case 3:		__kill_fasync(sock->fasync_list, SIGURG, band);	}	return 0;}int sock_create(int family, int type, int protocol, struct socket **res){	int i;	struct socket *sock;	/*	 *	Check protocol is in range	 */	if (family < 0 || family >= NPROTO)		return -EAFNOSUPPORT;	if (type < 0 || type >= SOCK_MAX)		return -EINVAL;	/* Compatibility.	   This uglymoron is moved from INET layer to here to avoid	   deadlock in module load.	 */	if (family == PF_INET && type == SOCK_PACKET) {		static int warned; 		if (!warned) {			warned = 1;			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);		}		family = PF_PACKET;	}		#if defined(CONFIG_KMOD) && defined(CONFIG_NET)	/* Attempt to load a protocol module if the find failed. 	 * 	 * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user 	 * requested real, full-featured networking support upon configuration.	 * Otherwise module support will break!	 */	if (net_families[family]==NULL)	{		char module_name[30];		sprintf(module_name,"net-pf-%d",family);		request_module(module_name);	}#endif	net_family_read_lock();	if (net_families[family] == NULL) {		i = -EAFNOSUPPORT;		goto out;	}/* *	Allocate the socket and allow the family to set things up. if *	the protocol is 0, the family is instructed to select an appropriate *	default. */	if (!(sock = sock_alloc())) 	{		printk(KERN_WARNING "socket: no more sockets\n");		i = -ENFILE;		/* Not exactly a match, but its the					   closest posix thing */		goto out;	}	sock->type  = type;	if ((i = net_families[family]->create(sock, protocol)) < 0) 	{		sock_release(sock);		goto out;	}	*res = sock;out:	net_family_read_unlock();	return i;}asmlinkage long sys_socket(int family, int type, int protocol){	int retval;	struct socket *sock;	retval = sock_create(family, type, protocol, &sock);	if (retval < 0)		goto out;	retval = sock_map_fd(sock);	if (retval < 0)		goto out_release;out:	/* It may be already another descriptor 8) Not kernel problem. */	return retval;out_release:	sock_release(sock);	return retval;}/* *	Create a pair of connected sockets. */asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]){	struct socket *sock1, *sock2;	int fd1, fd2, err;	/*	 * Obtain the first socket and check if the underlying protocol	 * supports the socketpair call.	 */	err = sock_create(family, type, protocol, &sock1);	if (err < 0)		goto out;	err = sock_create(family, type, protocol, &sock2);	if (err < 0)		goto out_release_1;	err = sock1->ops->socketpair(sock1, sock2);	if (err < 0) 		goto out_release_both;	fd1 = fd2 = -1;	err = sock_map_fd(sock1);	if (err < 0)		goto out_release_both;	fd1 = err;	err = sock_map_fd(sock2);	if (err < 0)		goto out_close_1;	fd2 = err;	/* fd1 and fd2 may be already another descriptors.	 * Not kernel problem.	 */	err = put_user(fd1, &usockvec[0]); 	if (!err)		err = put_user(fd2, &usockvec[1]);	if (!err)		return 0;	sys_close(fd2);	sys_close(fd1);	return err;out_close_1:        sock_release(sock2);	sys_close(fd1);	return err;out_release_both:        sock_release(sock2);out_release_1:        sock_release(sock1);out:	return err;}/* *	Bind a name to a socket. Nothing much to do here since it's *	the protocol's responsibility to handle the local address. * *	We move the socket address to kernel space before we call *	the protocol layer (having also checked the address is ok). */asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen){	struct socket *sock;	char address[MAX_SOCK_ADDR];	int err;	if((sock = sockfd_lookup(fd,&err))!=NULL)	{		if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0)			err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);		sockfd_put(sock);	}				return err;}/* *	Perform a listen. Basically, we allow the protocol to do anything *	necessary for a listen, and if that works, we mark the socket as *	ready for listening. */asmlinkage long sys_listen(int fd, int backlog){	struct socket *sock;	int err;		if ((sock = sockfd_lookup(fd, &err)) != NULL) {		if ((unsigned) backlog > SOMAXCONN)			backlog = SOMAXCONN;		err=sock->ops->listen(sock, backlog);		sockfd_put(sock);	}	return err;}/* *	For accept, we attempt to create a new socket, set up the link *	with the client, wake up the client, then return the new *	connected fd. We collect the address of the connector in kernel *	space and move it to user at the very end. This is unclean because *	we open the socket then return an error. * *	1003.1g adds the ability to recvmsg() to query connection pending *	status to recvmsg. We need to add that support in a way thats *	clean when we restucture accept also. */asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen){	struct socket *sock, *newsock;	int err, len;	char address[MAX_SOCK_ADDR];	sock = sockfd_lookup(fd, &err);	if (!sock)		goto out;	err = -EMFILE;	if (!(newsock = sock_alloc())) 		goto out_put;	newsock->type = sock->type;	newsock->ops = sock->ops;	err = sock->ops->accept(sock, newsock, sock->file->f_flags);	if (err < 0)		goto out_release;	if (upeer_sockaddr) {		if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {			err = -ECONNABORTED;			goto out_release;		}		err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);		if (err < 0)			goto out_release;	}	/* File flags are not inherited via accept() unlike another OSes. */	if ((err = sock_map_fd(newsock)) < 0)		goto out_release;out_put:	sockfd_put(sock);out:	return err;out_release:	sock_release(newsock);	goto out_put;}/* *	Attempt to connect to a socket with the server address.  The address *	is in user space so we verify it is OK and move it to kernel space. * *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to *	break bindings * *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and *	other SEQPACKET protocols that take time to connect() as it doesn't *	include the -EINPROGRESS status for such sockets. */asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen){	struct socket *sock;	char address[MAX_SOCK_ADDR];	int err;	sock = sockfd_lookup(fd, &err);	if (!sock)		goto out;	err = move_addr_to_kernel(uservaddr, addrlen, address);	if (err < 0)		goto out_put;	err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,				 sock->file->f_flags);out_put:	sockfd_put(sock);out:	return err;}/* *	Get the local address ('name') of a socket object. Move the obtained *	name to user space. */asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len){	struct socket *sock;	char address[MAX_SOCK_ADDR];	int len, err;		sock = sockfd_lookup(fd, &err);	if (!sock)		goto out;	err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);	if (err)		goto out_put;	err = move_addr_to_user(address, len, usockaddr, usockaddr_len);out_put:	sockfd_put(sock);out:	return err;}/* *	Get the remote address ('name') of a socket object. Move the obtained *	name to user space. */asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len){	struct socket *sock;	char address[MAX_SOCK_ADDR];	int len, err;	if ((sock = sockfd_lookup(fd, &err))!=NULL)	{		err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);		if (!err)			err=move_addr_to_user(address,len, usockaddr, usockaddr_len);		sockfd_put(sock);	}	return err;}

⌨️ 快捷键说明

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