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

📄 af_inet.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		schedule();		current->state = TASK_INTERRUPTIBLE;	}	current->state = TASK_RUNNING;	remove_wait_queue(sk->sleep, &wait);}/* *	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;	if(sock->state != SS_UNCONNECTED && sock->state != SS_CONNECTING) {		if(sock->state == SS_CONNECTED)			return -EISCONN;		return -EINVAL;	}	if(sock->state == SS_CONNECTING) {		/* Note: tcp_connected contains SYN_RECV, which may cause		   bogus results here. -AK */		if(tcp_connected(sk->state)) {			sock->state = SS_CONNECTED;			return 0;		}		if (sk->zapped || sk->err)			goto sock_error;		if (flags & O_NONBLOCK)			return -EALREADY;	} else {		if (sk->prot->connect == NULL)			return(-EOPNOTSUPP);		/* We may need to bind the socket. */		if (inet_autobind(sk) != 0)			return(-EAGAIN);		err = sk->prot->connect(sk, uaddr, addr_len);		/* Note: there is a theoretical race here when an wake up		   occurred before inet_wait_for_connect is entered. In 2.3		   the wait queue setup should be moved before the low level		   connect call. -AK*/		if (err < 0)			return(err);  		sock->state = SS_CONNECTING;	}	if (sk->state > TCP_FIN_WAIT2 && sock->state == SS_CONNECTING)		goto sock_error;	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))	  	return (-EINPROGRESS);	if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {		inet_wait_for_connect(sk);		if (signal_pending(current))			return -ERESTARTSYS;	}	sock->state = SS_CONNECTED;	if ((sk->state != TCP_ESTABLISHED) && sk->err)		goto sock_error;	return(0);sock_error:	/* This is ugly but needed to fix a race in the ICMP error handler */	if (sk->zapped && sk->state != TCP_CLOSE) {		lock_sock(sk);		tcp_set_state(sk, TCP_CLOSE);		release_sock(sk);		sk->zapped = 0;	}	sock->state = SS_UNCONNECTED;	return sock_error(sk);}/* *	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, *sk2;	struct sock *newsk = newsock->sk;	int err = -EINVAL;	if (sock->state != SS_UNCONNECTED || !(sock->flags & SO_ACCEPTCON))		goto do_err;	err = -EOPNOTSUPP;	if (sk1->prot->accept == NULL)		goto do_err;	if((sk2 = sk1->prot->accept(sk1,flags)) == NULL)		goto do_sk1_err;	/*	 *	We've been passed an extra socket.	 *	We need to free it up because the tcp module creates	 *	its own when it accepts one.	 */	sk2->sleep = newsk->sleep;	newsock->sk = sk2;	sk2->socket = newsock;	newsk->socket = NULL;	if (flags & O_NONBLOCK)		goto do_half_success;	if(sk2->state == TCP_ESTABLISHED)		goto do_full_success;	if(sk2->err > 0)		goto do_connect_err;	err = -ECONNABORTED;	if (sk2->state == TCP_CLOSE)		goto do_bad_connection;do_full_success:	destroy_sock(newsk);	newsock->state = SS_CONNECTED;	return 0;do_half_success:	destroy_sock(newsk);	return(0);do_connect_err:	err = sock_error(sk2);do_bad_connection:	sk2->sleep = NULL;	sk2->socket = NULL;	destroy_sock(sk2);	newsock->sk = newsk;	newsk->socket = newsock;	return err;do_sk1_err:	err = sock_error(sk1);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 (!tcp_connected(sk->state))			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;	if (sock->flags & SO_ACCEPTCON)		return(-EINVAL);	if (sk->prot->recvmsg == NULL)		return(-EOPNOTSUPP);	/* We may need to bind the socket. */	if (inet_autobind(sk) != 0)		return(-EAGAIN);	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;	if (sk->shutdown & SEND_SHUTDOWN) {		if (!(msg->msg_flags&MSG_NOSIGNAL))			send_sig(SIGPIPE, current, 1);		return(-EPIPE);	}	if (sk->prot->sendmsg == NULL)		return(-EOPNOTSUPP);	if(sk->err)		return sock_error(sk);	/* We may need to bind the socket. */	if (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;	/* 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);	if (!sk)		return(-ENOTCONN);	if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)		sock->state = SS_CONNECTED;	if (!tcp_connected(sk->state))		return(-ENOTCONN);	sk->shutdown |= how;	if (sk->prot->shutdown)		sk->prot->shutdown(sk, how);	/* Wake up anyone sleeping in poll. */	sk->state_change(sk);	return(0);}unsigned int inet_poll(struct file * file, struct socket *sock, poll_table *wait){	struct sock *sk = sock->sk;	if (sk->prot->poll == NULL)		return(0);	return sk->prot->poll(file, sock, wait);}#ifdef _HURD_#define inet_ioctl 0#else/* *	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 SIOCDRARP:		case SIOCGRARP:		case SIOCSRARP:#ifdef CONFIG_KMOD			if (rarp_ioctl_hook == NULL)				request_module("rarp");#endif			if (rarp_ioctl_hook != NULL)				return(rarp_ioctl_hook(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:#ifdef CONFIG_BRIDGE			return(br_ioctl(cmd,(void *) arg));#else			return -ENOPKG;#endif		case SIOCADDDLCI:		case SIOCDELDLCI:#ifdef CONFIG_DLCI			return(dlci_ioctl(cmd, (void *) arg));#endif#ifdef CONFIG_DLCI_MODULE#ifdef CONFIG_KMOD			if (dlci_ioctl_hook == NULL)				request_module("dlci");#endif			if (dlci_ioctl_hook)				return((*dlci_ioctl_hook)(cmd, (void *) arg));#endif			return -ENOPKG;		default:			if ((cmd >= SIOCDEVPRIVATE) &&			    (cmd <= (SIOCDEVPRIVATE + 15)))				return(dev_ioctl(cmd,(void *) arg));#ifdef CONFIG_NET_RADIO			if((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST))				return(dev_ioctl(cmd,(void *) arg));#endif			if (sk->prot->ioctl==NULL || (err=sk->prot->ioctl(sk, cmd, arg))==-ENOIOCTLCMD)				return(dev_ioctl(cmd,(void *) arg));			return err;	}	/*NOTREACHED*/	return(0);}#endifstruct proto_ops inet_stream_ops = {	PF_INET,	sock_no_dup,	inet_release,	inet_bind,	inet_stream_connect,	sock_no_socketpair,	inet_accept,	inet_getname,	inet_poll,	inet_ioctl,	inet_listen,	inet_shutdown,	inet_setsockopt,	inet_getsockopt,	sock_no_fcntl,	inet_sendmsg,	inet_recvmsg};struct proto_ops inet_dgram_ops = {	PF_INET,	sock_no_dup,	inet_release,	inet_bind,	inet_dgram_connect,	sock_no_socketpair,	sock_no_accept,	inet_getname,	datagram_poll,	inet_ioctl,	sock_no_listen,	inet_shutdown,	inet_setsockopt,	inet_getsockopt,	sock_no_fcntl,	inet_sendmsg,	inet_recvmsg};struct net_proto_family inet_family_ops = {	PF_INET,	inet_create};#ifdef CONFIG_PROC_FS#ifdef CONFIG_INET_RARPstatic struct proc_dir_entry proc_net_rarp = {	PROC_NET_RARP, 4, "rarp",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	rarp_get_info};#endif		/* RARP */static struct proc_dir_entry proc_net_raw = {	PROC_NET_RAW, 3, "raw",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	raw_get_info};static struct proc_dir_entry proc_net_netstat = {	PROC_NET_NETSTAT, 7, "netstat",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	netstat_get_info};static struct proc_dir_entry proc_net_snmp = {	PROC_NET_SNMP, 4, "snmp",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	snmp_get_info};static struct proc_dir_entry proc_net_sockstat = {	PROC_NET_SOCKSTAT, 8, "sockstat",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	afinet_get_info};static struct proc_dir_entry proc_net_tcp = {	PROC_NET_TCP, 3, "tcp",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	tcp_get_info};static struct proc_dir_entry proc_net_udp = {	PROC_NET_UDP, 3, "udp",	S_IFREG | S_IRUGO, 1, 0, 0,	0, &proc_net_inode_operations,	udp_get_info};#endif		/* CONFIG_PROC_FS */extern void tcp_init(void);extern void tcp_v4_init(struct net_proto_family *);/* *	Called by socket.c on kernel startup. */__initfunc(void inet_proto_init(struct net_proto *pro)){	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;	}	/*	 *	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	/*	 *	Set the firewalling up	 */#if defined(CONFIG_IP_FIREWALL)	ip_fw_init();#endif#ifdef CONFIG_IP_MASQUERADE	ip_masq_init();#endif	/*	 *	Initialise the multicast router	 */#if defined(CONFIG_IP_MROUTE)	ip_mr_init();#endif#ifdef CONFIG_INET_RARP	rarp_ioctl_hook = rarp_ioctl;#endif	/*	 *	Create all the /proc entries.	 */#ifdef CONFIG_PROC_FS#ifdef CONFIG_INET_RARP	proc_net_register(&proc_net_rarp);#endif		/* RARP */	proc_net_register(&proc_net_raw);	proc_net_register(&proc_net_snmp);	proc_net_register(&proc_net_netstat);	proc_net_register(&proc_net_sockstat);	proc_net_register(&proc_net_tcp);	proc_net_register(&proc_net_udp);#endif		/* CONFIG_PROC_FS */}

⌨️ 快捷键说明

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