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

📄 af_inet.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	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;	int err = -EINVAL;	struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err);	if (!sk2)		goto do_err;	lock_sock(sk2);	BUG_TRAP((1 << sk2->sk_state) &		 (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE));	sock_graft(sk2, newsock);	newsock->state = SS_CONNECTED;	err = 0;	release_sock(sk2);do_err:	return err;}/* *	This does both peername and sockname. */int inet_getname(struct socket *sock, struct sockaddr *uaddr,			int *uaddr_len, int peer){	struct sock *sk		= sock->sk;	struct inet_opt *inet	= inet_sk(sk);	struct sockaddr_in *sin	= (struct sockaddr_in *)uaddr;	sin->sin_family = AF_INET;	if (peer) {		if (!inet->dport ||		    (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&		     peer == 1))			return -ENOTCONN;		sin->sin_port = inet->dport;		sin->sin_addr.s_addr = inet->daddr;	} else {		__u32 addr = inet->rcv_saddr;		if (!addr)			addr = inet->saddr;		sin->sin_port = inet->sport;		sin->sin_addr.s_addr = addr;	}	memset(sin->sin_zero, 0, sizeof(sin->sin_zero));	*uaddr_len = sizeof(*sin);	return 0;}int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,		 size_t size){	struct sock *sk = sock->sk;	/* We may need to bind the socket. */	if (!inet_sk(sk)->num && inet_autobind(sk))		return -EAGAIN;	return sk->sk_prot->sendmsg(iocb, sk, msg, size);}ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags){	struct sock *sk = sock->sk;	/* We may need to bind the socket. */	if (!inet_sk(sk)->num && inet_autobind(sk))		return -EAGAIN;	if (sk->sk_prot->sendpage)		return sk->sk_prot->sendpage(sk, page, offset, size, flags);	return sock_no_sendpage(sock, page, offset, size, flags);}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)	/* MAXINT->0 */		return -EINVAL;	lock_sock(sk);	if (sock->state == SS_CONNECTING) {		if ((1 << sk->sk_state) &		    (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE))			sock->state = SS_DISCONNECTING;		else			sock->state = SS_CONNECTED;	}	switch (sk->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->sk_shutdown |= how;		if (sk->sk_prot->shutdown)			sk->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->sk_prot->disconnect(sk, O_NONBLOCK);		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;		break;	}	/* Wake up anyone sleeping in poll. */	sk->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. */int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	int err = 0;	switch (cmd) {		case SIOCGSTAMP:			err = sock_get_timestamp(sk, (struct timeval __user *)arg);			break;		case SIOCADDRT:		case SIOCDELRT:		case SIOCRTMSG:			err = ip_rt_ioctl(cmd, (void __user *)arg);			break;		case SIOCDARP:		case SIOCGARP:		case SIOCSARP:			err = arp_ioctl(cmd, (void __user *)arg);			break;		case SIOCGIFADDR:		case SIOCSIFADDR:		case SIOCGIFBRDADDR:		case SIOCSIFBRDADDR:		case SIOCGIFNETMASK:		case SIOCSIFNETMASK:		case SIOCGIFDSTADDR:		case SIOCSIFDSTADDR:		case SIOCSIFPFLAGS:		case SIOCGIFPFLAGS:		case SIOCSIFFLAGS:			err = devinet_ioctl(cmd, (void __user *)arg);			break;		default:			if (!sk->sk_prot->ioctl ||			    (err = sk->sk_prot->ioctl(sk, cmd, arg)) ==			    					-ENOIOCTLCMD)				err = dev_ioctl(cmd, (void __user *)arg);			break;	}	return err;}struct proto_ops inet_stream_ops = {	.family =	PF_INET,	.owner =	THIS_MODULE,	.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 =	sock_common_setsockopt,	.getsockopt =	sock_common_getsockopt,	.sendmsg =	inet_sendmsg,	.recvmsg =	sock_common_recvmsg,	.mmap =		sock_no_mmap,	.sendpage =	tcp_sendpage};struct proto_ops inet_dgram_ops = {	.family =	PF_INET,	.owner =	THIS_MODULE,	.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 =	sock_common_setsockopt,	.getsockopt =	sock_common_getsockopt,	.sendmsg =	inet_sendmsg,	.recvmsg =	sock_common_recvmsg,	.mmap =		sock_no_mmap,	.sendpage =	inet_sendpage,};static struct net_proto_family inet_family_ops = {	.family = PF_INET,	.create = inet_create,	.owner	= THIS_MODULE,};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))void inet_register_protosw(struct inet_protosw *p){	struct list_head *lh;	struct inet_protosw *answer;	int protocol = p->protocol;	struct list_head *last_perm;	spin_lock_bh(&inetsw_lock);	if (p->type >= SOCK_MAX)		goto out_illegal;	/* If we are trying to override a permanent protocol, bail. */	answer = NULL;	last_perm = &inetsw[p->type];	list_for_each(lh, &inetsw[p->type]) {		answer = list_entry(lh, struct inet_protosw, list);		/* Check only the non-wild match. */		if (INET_PROTOSW_PERMANENT & answer->flags) {			if (protocol == answer->protocol)				break;			last_perm = lh;		}		answer = NULL;	}	if (answer)		goto out_permanent;	/* Add the new entry after the last permanent entry if any, so that	 * the new entry does not override a permanent entry when matched with	 * a wild-card protocol. But it is allowed to override any existing	 * non-permanent entry.  This means that when we remove this entry, the 	 * system automatically returns to the old behavior.	 */	list_add_rcu(&p->list, last_perm);out:	spin_unlock_bh(&inetsw_lock);	synchronize_net();	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 invalid socket type %d.\n",	       p->type);	goto out;}void inet_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 {		spin_lock_bh(&inetsw_lock);		list_del_rcu(&p->list);		spin_unlock_bh(&inetsw_lock);		synchronize_net();	}}#ifdef CONFIG_IP_MULTICASTstatic struct net_protocol igmp_protocol = {	.handler =	igmp_rcv,};#endifstatic struct net_protocol tcp_protocol = {	.handler =	tcp_v4_rcv,	.err_handler =	tcp_v4_err,	.no_policy =	1,};static struct net_protocol udp_protocol = {	.handler =	udp_rcv,	.err_handler =	udp_err,	.no_policy =	1,};static struct net_protocol icmp_protocol = {	.handler =	icmp_rcv,};static int __init init_ipv4_mibs(void){	net_statistics[0] = alloc_percpu(struct linux_mib);	net_statistics[1] = alloc_percpu(struct linux_mib);	ip_statistics[0] = alloc_percpu(struct ipstats_mib);	ip_statistics[1] = alloc_percpu(struct ipstats_mib);	icmp_statistics[0] = alloc_percpu(struct icmp_mib);	icmp_statistics[1] = alloc_percpu(struct icmp_mib);	tcp_statistics[0] = alloc_percpu(struct tcp_mib);	tcp_statistics[1] = alloc_percpu(struct tcp_mib);	udp_statistics[0] = alloc_percpu(struct udp_mib);	udp_statistics[1] = alloc_percpu(struct udp_mib);	if (!	    (net_statistics[0] && net_statistics[1] && ip_statistics[0]	     && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1]	     && udp_statistics[0] && udp_statistics[1]))		return -ENOMEM;	(void) tcp_mib_init();	return 0;}int ipv4_proc_init(void);extern void ipfrag_init(void);static int __init inet_init(void){	struct sk_buff *dummy_skb;	struct inet_protosw *q;	struct list_head *r;	int rc = -EINVAL;	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {		printk(KERN_CRIT "%s: panic\n", __FUNCTION__);		goto out;	}	rc = sk_alloc_slab(&tcp_prot, "tcp_sock");	if (rc) {		sk_alloc_slab_error(&tcp_prot);		goto out;	}	rc = sk_alloc_slab(&udp_prot, "udp_sock");	if (rc) {		sk_alloc_slab_error(&udp_prot);		goto out_tcp_free_slab;	}	rc = sk_alloc_slab(&raw_prot, "raw_sock");	if (rc) {		sk_alloc_slab_error(&raw_prot);		goto out_udp_free_slab;	}	/*	 *	Tell SOCKET that we are alive... 	 */  	(void)sock_register(&inet_family_ops);	/*	 *	Add all the base protocols.	 */	if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)		printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n");	if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)		printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n");	if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)		printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n");#ifdef CONFIG_IP_MULTICAST	if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)		printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n");#endif	/* 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);	/*	 *	Initialise the multicast router	 */#if defined(CONFIG_IP_MROUTE)	ip_mr_init();#endif	/*	 *	Initialise per-cpu ipv4 mibs	 */ 	if(init_ipv4_mibs())		printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;		ipv4_proc_init();	ipfrag_init();	rc = 0;out:	return rc;out_tcp_free_slab:	sk_free_slab(&tcp_prot);out_udp_free_slab:	sk_free_slab(&udp_prot);	goto out;}module_init(inet_init);/* ------------------------------------------------------------------------ */#ifdef CONFIG_PROC_FSextern int  fib_proc_init(void);extern void fib_proc_exit(void);extern int  ip_misc_proc_init(void);extern int  raw_proc_init(void);extern void raw_proc_exit(void);extern int  tcp4_proc_init(void);extern void tcp4_proc_exit(void);extern int  udp4_proc_init(void);extern void udp4_proc_exit(void);int __init ipv4_proc_init(void){	int rc = 0;	if (raw_proc_init())		goto out_raw;	if (tcp4_proc_init())		goto out_tcp;	if (udp4_proc_init())		goto out_udp;	if (fib_proc_init())		goto out_fib;	if (ip_misc_proc_init())		goto out_misc;out:	return rc;out_misc:	fib_proc_exit();out_fib:	udp4_proc_exit();out_udp:	tcp4_proc_exit();out_tcp:	raw_proc_exit();out_raw:	rc = -ENOMEM;	goto out;}#else /* CONFIG_PROC_FS */int __init ipv4_proc_init(void){	return 0;}#endif /* CONFIG_PROC_FS */MODULE_ALIAS_NETPROTO(PF_INET);EXPORT_SYMBOL(inet_accept);EXPORT_SYMBOL(inet_bind);EXPORT_SYMBOL(inet_dgram_connect);EXPORT_SYMBOL(inet_dgram_ops);EXPORT_SYMBOL(inet_getname);EXPORT_SYMBOL(inet_ioctl);EXPORT_SYMBOL(inet_listen);EXPORT_SYMBOL(inet_register_protosw);EXPORT_SYMBOL(inet_release);EXPORT_SYMBOL(inet_sendmsg);EXPORT_SYMBOL(inet_shutdown);EXPORT_SYMBOL(inet_sock_destruct);EXPORT_SYMBOL(inet_stream_connect);EXPORT_SYMBOL(inet_stream_ops);EXPORT_SYMBOL(inet_unregister_protosw);EXPORT_SYMBOL(net_statistics);EXPORT_SYMBOL(tcp_protocol);EXPORT_SYMBOL(udp_protocol);#ifdef INET_REFCNT_DEBUGEXPORT_SYMBOL(inet_sock_nr);#endif

⌨️ 快捷键说明

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