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

📄 af_inet6.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
			return -ENOTCONN;		sin->sin6_port = inet->dport;		ipv6_addr_copy(&sin->sin6_addr, &np->daddr);		if (np->sndflow)			sin->sin6_flowinfo = np->flow_label;	} else {		if (ipv6_addr_any(&np->rcv_saddr))			ipv6_addr_copy(&sin->sin6_addr, &np->saddr);		else			ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr);		sin->sin6_port = inet->sport;	}	if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)		sin->sin6_scope_id = sk->sk_bound_dev_if;	*uaddr_len = sizeof(*sin);	return(0);}int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	int err = -EINVAL;	switch(cmd) 	{	case SIOCGSTAMP:		return sock_get_timestamp(sk, (struct timeval __user *)arg);	case SIOCADDRT:	case SIOCDELRT:	  		return(ipv6_route_ioctl(cmd,(void __user *)arg));	case SIOCSIFADDR:		return addrconf_add_ifaddr((void __user *) arg);	case SIOCDIFADDR:		return addrconf_del_ifaddr((void __user *) arg);	case SIOCSIFDSTADDR:		return addrconf_set_dstaddr((void __user *) arg);	default:		if (!sk->sk_prot->ioctl ||		    (err = sk->sk_prot->ioctl(sk, cmd, arg)) == -ENOIOCTLCMD)			return(dev_ioctl(cmd,(void __user *) arg));				return err;	}	/*NOTREACHED*/	return(0);}struct proto_ops inet6_stream_ops = {	.family =	PF_INET6,	.owner =	THIS_MODULE,	.release =	inet6_release,	.bind =		inet6_bind,	.connect =	inet_stream_connect,		/* ok		*/	.socketpair =	sock_no_socketpair,		/* a do nothing	*/	.accept =	inet_accept,			/* ok		*/	.getname =	inet6_getname, 	.poll =		tcp_poll,			/* ok		*/	.ioctl =	inet6_ioctl,			/* must change  */	.listen =	inet_listen,			/* ok		*/	.shutdown =	inet_shutdown,			/* ok		*/	.setsockopt =	sock_common_setsockopt,		/* ok		*/	.getsockopt =	sock_common_getsockopt,		/* ok		*/	.sendmsg =	inet_sendmsg,			/* ok		*/	.recvmsg =	sock_common_recvmsg,		/* ok		*/	.mmap =		sock_no_mmap,	.sendpage =	tcp_sendpage};struct proto_ops inet6_dgram_ops = {	.family =	PF_INET6,	.owner =	THIS_MODULE,	.release =	inet6_release,	.bind =		inet6_bind,	.connect =	inet_dgram_connect,		/* ok		*/	.socketpair =	sock_no_socketpair,		/* a do nothing	*/	.accept =	sock_no_accept,			/* a do nothing	*/	.getname =	inet6_getname, 	.poll =		datagram_poll,			/* ok		*/	.ioctl =	inet6_ioctl,			/* must change  */	.listen =	sock_no_listen,			/* ok		*/	.shutdown =	inet_shutdown,			/* ok		*/	.setsockopt =	sock_common_setsockopt,		/* ok		*/	.getsockopt =	sock_common_getsockopt,		/* ok		*/	.sendmsg =	inet_sendmsg,			/* ok		*/	.recvmsg =	sock_common_recvmsg,		/* ok		*/	.mmap =		sock_no_mmap,	.sendpage =	sock_no_sendpage,};static struct net_proto_family inet6_family_ops = {	.family = PF_INET6,	.create = inet6_create,	.owner	= THIS_MODULE,};#ifdef CONFIG_SYSCTLextern void ipv6_sysctl_register(void);extern void ipv6_sysctl_unregister(void);#endifstatic struct inet_protosw rawv6_protosw = {	.type		= SOCK_RAW,	.protocol	= IPPROTO_IP,	/* wild card */	.prot		= &rawv6_prot,	.ops		= &inet6_dgram_ops,	.capability	= CAP_NET_RAW,	.no_check	= UDP_CSUM_DEFAULT,	.flags		= INET_PROTOSW_REUSE,};voidinet6_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(&inetsw6_lock);	if (p->type >= SOCK_MAX)		goto out_illegal;	/* If we are trying to override a permanent protocol, bail. */	answer = NULL;	last_perm = &inetsw6[p->type];	list_for_each(lh, &inetsw6[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(&inetsw6_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 invalid socket type %d.\n",	       p->type);	goto out;}voidinet6_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(&inetsw6_lock);		list_del_rcu(&p->list);		spin_unlock_bh(&inetsw6_lock);		synchronize_net();	}}intsnmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign){	if (ptr == NULL)		return -EINVAL;	ptr[0] = __alloc_percpu(mibsize, mibalign);	if (!ptr[0])		goto err0;	ptr[1] = __alloc_percpu(mibsize, mibalign);	if (!ptr[1])		goto err1;	return 0;err1:	free_percpu(ptr[0]);	ptr[0] = NULL;err0:	return -ENOMEM;}voidsnmp6_mib_free(void *ptr[2]){	if (ptr == NULL)		return;	free_percpu(ptr[0]);	free_percpu(ptr[1]);	ptr[0] = ptr[1] = NULL;}static int __init init_ipv6_mibs(void){	if (snmp6_mib_init((void **)ipv6_statistics, sizeof (struct ipstats_mib),			   __alignof__(struct ipstats_mib)) < 0)		goto err_ip_mib;	if (snmp6_mib_init((void **)icmpv6_statistics, sizeof (struct icmpv6_mib),			   __alignof__(struct icmpv6_mib)) < 0)		goto err_icmp_mib;	if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib),			   __alignof__(struct udp_mib)) < 0)		goto err_udp_mib;	return 0;err_udp_mib:	snmp6_mib_free((void **)icmpv6_statistics);err_icmp_mib:	snmp6_mib_free((void **)ipv6_statistics);err_ip_mib:	return -ENOMEM;	}static void cleanup_ipv6_mibs(void){	snmp6_mib_free((void **)ipv6_statistics);	snmp6_mib_free((void **)icmpv6_statistics);	snmp6_mib_free((void **)udp_stats_in6);}extern int ipv6_misc_proc_init(void);static int __init inet6_init(void){	struct sk_buff *dummy_skb;        struct list_head *r;	int err;#ifdef MODULE#if 0 /* FIXME --RR */	if (!mod_member_present(&__this_module, can_unload))	  return -EINVAL;	__this_module.can_unload = &ipv6_unload;#endif#endif	if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) {		printk(KERN_CRIT "inet6_proto_init: size fault\n");		return -EINVAL;	}	err = sk_alloc_slab(&tcpv6_prot, "tcpv6_sock");	if (err) {		sk_alloc_slab_error(&tcpv6_prot);		goto out;	}	err = sk_alloc_slab(&udpv6_prot, "udpv6_sock");	if (err) {		sk_alloc_slab_error(&udpv6_prot);		goto out_tcp_free_slab;	}	err = sk_alloc_slab(&rawv6_prot, "rawv6_sock");	if (err) {		sk_alloc_slab_error(&rawv6_prot);		goto out_udp_free_slab;	}	/* Register the socket-side information for inet6_create.  */	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)		INIT_LIST_HEAD(r);	/* We MUST register RAW sockets before we create the ICMP6,	 * IGMP6, or NDISC control sockets.	 */	inet6_register_protosw(&rawv6_protosw);	/* Register the family here so that the init calls below will	 * be able to create sockets. (?? is this dangerous ??)	 */	(void) sock_register(&inet6_family_ops);	/* Initialise ipv6 mibs */	err = init_ipv6_mibs();	if (err)		goto out_raw_free_slab;		/*	 *	ipngwg API draft makes clear that the correct semantics	 *	for TCP and UDP is to consider one TCP and UDP instance	 *	in a host availiable by both INET and INET6 APIs and	 *	able to communicate via both network protocols.	 */#ifdef CONFIG_SYSCTL	ipv6_sysctl_register();#endif	err = icmpv6_init(&inet6_family_ops);	if (err)		goto icmp_fail;	err = ndisc_init(&inet6_family_ops);	if (err)		goto ndisc_fail;	err = igmp6_init(&inet6_family_ops);	if (err)		goto igmp_fail;	/* Create /proc/foo6 entries. */#ifdef CONFIG_PROC_FS	err = -ENOMEM;	if (raw6_proc_init())		goto proc_raw6_fail;	if (tcp6_proc_init())		goto proc_tcp6_fail;	if (udp6_proc_init())		goto proc_udp6_fail;	if (ipv6_misc_proc_init())		goto proc_misc6_fail;	if (ac6_proc_init())		goto proc_anycast6_fail;	if (if6_proc_init())		goto proc_if6_fail;#endif	ipv6_packet_init();	ip6_route_init();	ip6_flowlabel_init();	addrconf_init();	sit_init();	/* Init v6 extension headers. */	ipv6_rthdr_init();	ipv6_frag_init();	ipv6_nodata_init();	ipv6_destopt_init();	/* Init v6 transport protocols. */	udpv6_init();	tcpv6_init();	err = 0;out:	return err;#ifdef CONFIG_PROC_FSproc_if6_fail:	ac6_proc_exit();proc_anycast6_fail:	ipv6_misc_proc_exit();proc_misc6_fail:	udp6_proc_exit();proc_udp6_fail:	tcp6_proc_exit();proc_tcp6_fail:	raw6_proc_exit();proc_raw6_fail:	igmp6_cleanup();#endifigmp_fail:	ndisc_cleanup();ndisc_fail:	icmpv6_cleanup();icmp_fail:#ifdef CONFIG_SYSCTL	ipv6_sysctl_unregister();#endif	cleanup_ipv6_mibs();out_raw_free_slab:	sk_free_slab(&rawv6_prot);out_udp_free_slab:	sk_free_slab(&udpv6_prot);out_tcp_free_slab:	sk_free_slab(&tcpv6_prot);	goto out;}module_init(inet6_init);static void __exit inet6_exit(void){	/* First of all disallow new sockets creation. */	sock_unregister(PF_INET6);#ifdef CONFIG_PROC_FS	if6_proc_exit();	ac6_proc_exit(); 	ipv6_misc_proc_exit(); 	udp6_proc_exit(); 	tcp6_proc_exit(); 	raw6_proc_exit();#endif	/* Cleanup code parts. */	sit_cleanup();	ip6_flowlabel_cleanup();	addrconf_cleanup();	ip6_route_cleanup();	ipv6_packet_cleanup();	igmp6_cleanup();	ndisc_cleanup();	icmpv6_cleanup();#ifdef CONFIG_SYSCTL	ipv6_sysctl_unregister();	#endif	cleanup_ipv6_mibs();	sk_free_slab(&rawv6_prot);	sk_free_slab(&udpv6_prot);	sk_free_slab(&tcpv6_prot);}module_exit(inet6_exit);MODULE_ALIAS_NETPROTO(PF_INET6);

⌨️ 快捷键说明

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