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

📄 af_inet.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct sock *sk=sock->sk;	if (uaddr->sa_family == AF_UNSPEC)		return sk->prot->disconnect(sk, flags);	if (sk->num==0 && inet_autobind(sk) != 0)		return -EAGAIN;	return sk->prot->connect(sk, (struct sockaddr *)uaddr, addr_len);}static long inet_wait_for_connect(struct sock *sk, long timeo){	DECLARE_WAITQUEUE(wait, current);	__set_current_state(TASK_INTERRUPTIBLE);	add_wait_queue(sk->sleep, &wait);	/* Basic assumption: if someone sets sk->err, he _must_	 * change state of the socket from TCP_SYN_*.	 * Connect() does not allow to get error notifications	 * without closing the socket.	 */	while ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {		release_sock(sk);		timeo = schedule_timeout(timeo);		lock_sock(sk);		if (signal_pending(current) || !timeo)			break;		set_current_state(TASK_INTERRUPTIBLE);	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(sk->sleep, &wait);	return timeo;}/* *	Connect to a remote host. There is regrettably still a little *	TCP 'magic' in here. */ int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr,			int addr_len, int flags){	struct sock *sk=sock->sk;	int err;	long timeo;	lock_sock(sk);	if (uaddr->sa_family == AF_UNSPEC) {		err = sk->prot->disconnect(sk, flags);		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;		goto out;	}	switch (sock->state) {	default:		err = -EINVAL;		goto out;	case SS_CONNECTED:		err = -EISCONN;		goto out;	case SS_CONNECTING:		err = -EALREADY;		/* Fall out of switch with err, set for this state */		break;	case SS_UNCONNECTED:		err = -EISCONN;		if (sk->state != TCP_CLOSE) 			goto out;		err = -EAGAIN;		if (sk->num == 0) {			if (sk->prot->get_port(sk, 0) != 0)				goto out;			sk->sport = htons(sk->num);		}		err = sk->prot->connect(sk, uaddr, addr_len);		if (err < 0)			goto out;  		sock->state = SS_CONNECTING;		/* Just entered SS_CONNECTING state; the only		 * difference is that return value in non-blocking		 * case is EINPROGRESS, rather than EALREADY.		 */		err = -EINPROGRESS;		break;	}	timeo = sock_sndtimeo(sk, flags&O_NONBLOCK);	if ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {		/* Error code is set above */		if (!timeo || !inet_wait_for_connect(sk, timeo))			goto out;		err = sock_intr_errno(timeo);		if (signal_pending(current))			goto out;	}	/* Connection was closed by RST, timeout, ICMP error	 * or another process disconnected us.	 */	if (sk->state == TCP_CLOSE)		goto sock_error;	/* sk->err may be not zero now, if RECVERR was ordered by user	 * and error was received after socket entered established state.	 * Hence, it is handled normally after connect() return successfully.	 */	sock->state = SS_CONNECTED;	err = 0;out:	release_sock(sk);	return err;sock_error:	err = sock_error(sk) ? : -ECONNABORTED;	sock->state = SS_UNCONNECTED;	if (sk->prot->disconnect(sk, flags))		sock->state = SS_DISCONNECTING;	goto out;}/* *	Accept a pending connection. The TCP layer now gives BSD semantics. */int inet_accept(struct socket *sock, struct socket *newsock, int flags){	struct sock *sk1 = sock->sk;	struct sock *sk2;	int err = -EINVAL;	if((sk2 = sk1->prot->accept(sk1,flags,&err)) == NULL)		goto do_err;	lock_sock(sk2);	BUG_TRAP((1<<sk2->state)&(TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_CLOSE));	sock_graft(sk2, newsock);	newsock->state = SS_CONNECTED;	release_sock(sk2);	return 0;do_err:	return err;}/* *	This does both peername and sockname. */ static int inet_getname(struct socket *sock, struct sockaddr *uaddr,		 int *uaddr_len, int peer){	struct sock *sk		= sock->sk;	struct sockaddr_in *sin	= (struct sockaddr_in *)uaddr;  	sin->sin_family = AF_INET;	if (peer) {		if (!sk->dport)			return -ENOTCONN;		if (((1<<sk->state)&(TCPF_CLOSE|TCPF_SYN_SENT)) && peer == 1)			return -ENOTCONN;		sin->sin_port = sk->dport;		sin->sin_addr.s_addr = sk->daddr;	} else {		__u32 addr = sk->rcv_saddr;		if (!addr)			addr = sk->saddr;		sin->sin_port = sk->sport;		sin->sin_addr.s_addr = addr;	}	*uaddr_len = sizeof(*sin);	return(0);}int inet_recvmsg(struct socket *sock, struct msghdr *msg, int size,		 int flags, struct scm_cookie *scm){	struct sock *sk = sock->sk;	int addr_len = 0;	int err;	err = sk->prot->recvmsg(sk, msg, size, flags&MSG_DONTWAIT,				flags&~MSG_DONTWAIT, &addr_len);	if (err >= 0)		msg->msg_namelen = addr_len;	return err;}int inet_sendmsg(struct socket *sock, struct msghdr *msg, int size,		 struct scm_cookie *scm){	struct sock *sk = sock->sk;	/* We may need to bind the socket. */	if (sk->num==0 && inet_autobind(sk) != 0)		return -EAGAIN;	return sk->prot->sendmsg(sk, msg, size);}int inet_shutdown(struct socket *sock, int how){	struct sock *sk = sock->sk;	int err = 0;	/* This should really check to make sure	 * the socket is a TCP socket. (WHY AC...)	 */	how++; /* maps 0->1 has the advantage of making bit 1 rcvs and		       1->2 bit 2 snds.		       2->3 */	if ((how & ~SHUTDOWN_MASK) || how==0)	/* MAXINT->0 */		return -EINVAL;	lock_sock(sk);	if (sock->state == SS_CONNECTING) {		if ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV|TCPF_CLOSE))			sock->state = SS_DISCONNECTING;		else			sock->state = SS_CONNECTED;	}	switch (sk->state) {	case TCP_CLOSE:		err = -ENOTCONN;		/* Hack to wake up other listeners, who can poll for		   POLLHUP, even on eg. unconnected UDP sockets -- RR */	default:		sk->shutdown |= how;		if (sk->prot->shutdown)			sk->prot->shutdown(sk, how);		break;	/* Remaining two branches are temporary solution for missing	 * close() in multithreaded environment. It is _not_ a good idea,	 * but we have no choice until close() is repaired at VFS level.	 */	case TCP_LISTEN:		if (!(how & RCV_SHUTDOWN))			break;		/* Fall through */	case TCP_SYN_SENT:		err = sk->prot->disconnect(sk, O_NONBLOCK);		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;		break;	}	/* Wake up anyone sleeping in poll. */	sk->state_change(sk);	release_sock(sk);	return err;}/* *	ioctl() calls you can issue on an INET socket. Most of these are *	device configuration and stuff and very rarely used. Some ioctls *	pass on to the socket itself. * *	NOTE: I like the idea of a module for the config stuff. ie ifconfig *	loads the devconfigure module does its configuring and unloads it. *	There's a good 20K of config code hanging around the kernel. */static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	int err;	int pid;	switch(cmd) 	{		case FIOSETOWN:		case SIOCSPGRP:			err = get_user(pid, (int *) arg);			if (err)				return err; 			if (current->pid != pid && current->pgrp != -pid && 			    !capable(CAP_NET_ADMIN))				return -EPERM;			sk->proc = pid;			return(0);		case FIOGETOWN:		case SIOCGPGRP:			return put_user(sk->proc, (int *)arg);		case SIOCGSTAMP:			if(sk->stamp.tv_sec==0)				return -ENOENT;			err = copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));			if (err)				err = -EFAULT;			return err;		case SIOCADDRT:		case SIOCDELRT:		case SIOCRTMSG:			return(ip_rt_ioctl(cmd,(void *) arg));		case SIOCDARP:		case SIOCGARP:		case SIOCSARP:			return(arp_ioctl(cmd,(void *) arg));		case SIOCGIFADDR:		case SIOCSIFADDR:		case SIOCGIFBRDADDR:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:		case SIOCSIFPFLAGS:			case SIOCGIFPFLAGS:			case SIOCSIFFLAGS:			return(devinet_ioctl(cmd,(void *) arg));		case SIOCGIFBR:		case SIOCSIFBR:#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)#ifdef CONFIG_KMOD			if (br_ioctl_hook == NULL)				request_module("bridge");#endif			if (br_ioctl_hook != NULL)				return br_ioctl_hook(arg);#endif		case SIOCGIFDIVERT:		case SIOCSIFDIVERT:#ifdef CONFIG_NET_DIVERT			return(divert_ioctl(cmd, (struct divert_cf *) arg));#else			return -ENOPKG;#endif	/* CONFIG_NET_DIVERT */			return -ENOPKG;					case SIOCADDDLCI:		case SIOCDELDLCI:#ifdef CONFIG_DLCI			lock_kernel();			err = dlci_ioctl(cmd, (void *) arg);			unlock_kernel();			return err;#endif#ifdef CONFIG_DLCI_MODULE#ifdef CONFIG_KMOD			if (dlci_ioctl_hook == NULL)				request_module("dlci");#endif			if (dlci_ioctl_hook) {				lock_kernel();				err = (*dlci_ioctl_hook)(cmd, (void *) arg);				unlock_kernel();				return err;			}#endif			return -ENOPKG;		default:			if ((cmd >= SIOCDEVPRIVATE) &&			    (cmd <= (SIOCDEVPRIVATE + 15)))				return(dev_ioctl(cmd,(void *) arg));#ifdef WIRELESS_EXT			if((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST))				return(dev_ioctl(cmd,(void *) arg));#endif	/* WIRELESS_EXT */			if (sk->prot->ioctl==NULL || (err=sk->prot->ioctl(sk, cmd, arg))==-ENOIOCTLCMD)				return(dev_ioctl(cmd,(void *) arg));					return err;	}	/*NOTREACHED*/	return(0);}struct proto_ops inet_stream_ops = {	family:		PF_INET,	release:	inet_release,	bind:		inet_bind,	connect:	inet_stream_connect,	socketpair:	sock_no_socketpair,	accept:		inet_accept,	getname:	inet_getname, 	poll:		tcp_poll,	ioctl:		inet_ioctl,	listen:		inet_listen,	shutdown:	inet_shutdown,	setsockopt:	inet_setsockopt,	getsockopt:	inet_getsockopt,	sendmsg:	inet_sendmsg,	recvmsg:	inet_recvmsg,	mmap:		sock_no_mmap};struct proto_ops inet_dgram_ops = {	family:		PF_INET,	release:	inet_release,	bind:		inet_bind,	connect:	inet_dgram_connect,	socketpair:	sock_no_socketpair,	accept:		sock_no_accept,	getname:	inet_getname, 	poll:		datagram_poll,	ioctl:		inet_ioctl,	listen:		sock_no_listen,	shutdown:	inet_shutdown,	setsockopt:	inet_setsockopt,	getsockopt:	inet_getsockopt,	sendmsg:	inet_sendmsg,	recvmsg:	inet_recvmsg,	mmap:		sock_no_mmap,};struct net_proto_family inet_family_ops = {	PF_INET,	inet_create};extern void tcp_init(void);extern void tcp_v4_init(struct net_proto_family *);/* *	Called by socket.c on kernel startup.   */ static int __init inet_init(void){	struct sk_buff *dummy_skb;	struct inet_protocol *p;	printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n");	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb))	{		printk(KERN_CRIT "inet_proto_init: panic\n");		return -EINVAL;	}	/*	 *	Tell SOCKET that we are alive... 	 */     	(void) sock_register(&inet_family_ops);	/*	 *	Add all the protocols. 	 */	printk(KERN_INFO "IP Protocols: ");	for(p = inet_protocol_base; p != NULL;) 	{		struct inet_protocol *tmp = (struct inet_protocol *) p->next;		inet_add_protocol(p);		printk("%s%s",p->name,tmp?", ":"\n");		p = tmp;	}	/*	 *	Set the ARP module up	 */	arp_init();  	/*  	 *	Set the IP module up  	 */	ip_init();	tcp_v4_init(&inet_family_ops);	/* Setup TCP slab cache for open requests. */	tcp_init();	/*	 *	Set the ICMP layer up	 */	icmp_init(&inet_family_ops);	/* I wish inet_add_protocol had no constructor hook...	   I had to move IPIP from net/ipv4/protocol.c :-( --ANK	 */#ifdef CONFIG_NET_IPIP	ipip_init();#endif#ifdef CONFIG_NET_IPGRE	ipgre_init();#endif	/*	 *	Initialise the multicast router	 */#if defined(CONFIG_IP_MROUTE)	ip_mr_init();#endif	/*	 *	Create all the /proc entries.	 */#ifdef CONFIG_PROC_FS	proc_net_create ("raw", 0, raw_get_info);	proc_net_create ("netstat", 0, netstat_get_info);	proc_net_create ("snmp", 0, snmp_get_info);	proc_net_create ("sockstat", 0, afinet_get_info);	proc_net_create ("tcp", 0, tcp_get_info);	proc_net_create ("udp", 0, udp_get_info);#endif		/* CONFIG_PROC_FS */	return 0;}module_init(inet_init);

⌨️ 快捷键说明

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