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

📄 af_inet.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 2 页
字号:
		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			return -ENOPKG;		case SIOCGIFVLAN:		case SIOCSIFVLAN:#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)#ifdef CONFIG_KMOD			if (vlan_ioctl_hook == NULL)				request_module("8021q");#endif			if (vlan_ioctl_hook != NULL)				return vlan_ioctl_hook(arg);#endif			return -ENOPKG;		case SIOCGIFDIVERT:		case SIOCSIFDIVERT:#ifdef CONFIG_NET_DIVERT			return divert_ioctl(cmd, (struct divert_cf *) arg);#else			return -ENOPKG;#endif	/* CONFIG_NET_DIVERT */					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,	sendpage:	tcp_sendpage};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,	sendpage:	sock_no_sendpage,};struct net_proto_family inet_family_ops = {	family:	PF_INET,	create:	inet_create};extern void tcp_init(void);extern void tcp_v4_init(struct net_proto_family *);/* Upon startup we insert all the elements in inetsw_array[] into * the linked list inetsw. */static struct inet_protosw inetsw_array[] ={        {                type:        SOCK_STREAM,                protocol:    IPPROTO_TCP,                prot:        &tcp_prot,                ops:         &inet_stream_ops,                capability:  -1,                no_check:    0,                flags:       INET_PROTOSW_PERMANENT,        },        {                type:        SOCK_DGRAM,                protocol:    IPPROTO_UDP,                prot:        &udp_prot,                ops:         &inet_dgram_ops,                capability:  -1,                no_check:    UDP_CSUM_DEFAULT,                flags:       INET_PROTOSW_PERMANENT,       },               {               type:        SOCK_RAW,               protocol:    IPPROTO_IP,	/* wild card */               prot:        &raw_prot,               ops:         &inet_dgram_ops,               capability:  CAP_NET_RAW,               no_check:    UDP_CSUM_DEFAULT,               flags:       INET_PROTOSW_REUSE,       }};#define INETSW_ARRAY_LEN (sizeof(inetsw_array) / sizeof(struct inet_protosw))voidinet_register_protosw(struct inet_protosw *p){	struct list_head *lh;	struct inet_protosw *answer;	int protocol = p->protocol;	br_write_lock_bh(BR_NETPROTO_LOCK);	if (p->type > SOCK_MAX)		goto out_illegal;	/* If we are trying to override a permanent protocol, bail. */	answer = NULL;	list_for_each(lh, &inetsw[p->type]) {		answer = list_entry(lh, struct inet_protosw, list);		/* Check only the non-wild match. */		if (protocol == answer->protocol &&		    (INET_PROTOSW_PERMANENT & answer->flags))			break;		answer = NULL;	}	if (answer)		goto out_permanent;	/* Add to the BEGINNING so that we override any existing	 * entry.  This means that when we remove this entry, the	 * system automatically returns to the old behavior.	 */	list_add(&p->list, &inetsw[p->type]);out:	br_write_unlock_bh(BR_NETPROTO_LOCK);	return;out_permanent:	printk(KERN_ERR "Attempt to override permanent protocol %d.\n",	       protocol);	goto out;out_illegal:	printk(KERN_ERR	       "Ignoring attempt to register illegal socket type %d.\n",	       p->type);	goto out;}voidinet_unregister_protosw(struct inet_protosw *p){	if (INET_PROTOSW_PERMANENT & p->flags) {		printk(KERN_ERR		       "Attempt to unregister permanent protocol %d.\n",		       p->protocol);	} else {		br_write_lock_bh(BR_NETPROTO_LOCK);		list_del(&p->list);		br_write_unlock_bh(BR_NETPROTO_LOCK);	}}/* *	Called by socket.c on kernel startup.   */ static int __init inet_init(void){	struct sk_buff *dummy_skb;	struct inet_protocol *p;	struct inet_protosw *q;	struct list_head *r;	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;	}	/* Register the socket-side information for inet_create. */	for(r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)		INIT_LIST_HEAD(r);	for(q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)		inet_register_protosw(q);	/*	 *	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 + -