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

📄 ipv6.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		dccp_pr_debug("sk->sk_state == DCCP_TIME_WAIT: do_time_wait\n");		inet_twsk_put(inet_twsk(sk));		goto no_dccp_socket;	}	/*	 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage	 *	o if MinCsCov = 0, only packets with CsCov = 0 are accepted	 *	o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov	 */	min_cov = dccp_sk(sk)->dccps_pcrlen;	if (dh->dccph_cscov  &&  (min_cov == 0 || dh->dccph_cscov < min_cov))  {		dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",			      dh->dccph_cscov, min_cov);		/* FIXME: send Data Dropped option (see also dccp_v4_rcv) */		goto discard_and_relse;	}	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))		goto discard_and_relse;	return sk_receive_skb(sk, skb, 1) ? -1 : 0;no_dccp_socket:	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))		goto discard_it;	/*	 * Step 2:	 *	If no socket ...	 *		Generate Reset(No Connection) unless P.type == Reset	 *		Drop packet and return	 */	if (dh->dccph_type != DCCP_PKT_RESET) {		DCCP_SKB_CB(skb)->dccpd_reset_code =					DCCP_RESET_CODE_NO_CONNECTION;		dccp_v6_ctl_send_reset(sk, skb);	}discard_it:	kfree_skb(skb);	return 0;discard_and_relse:	sock_put(sk);	goto discard_it;}static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,			   int addr_len){	struct sockaddr_in6 *usin = (struct sockaddr_in6 *)uaddr;	struct inet_connection_sock *icsk = inet_csk(sk);	struct inet_sock *inet = inet_sk(sk);	struct ipv6_pinfo *np = inet6_sk(sk);	struct dccp_sock *dp = dccp_sk(sk);	struct in6_addr *saddr = NULL, *final_p = NULL, final;	struct flowi fl;	struct dst_entry *dst;	int addr_type;	int err;	dp->dccps_role = DCCP_ROLE_CLIENT;	if (addr_len < SIN6_LEN_RFC2133)		return -EINVAL;	if (usin->sin6_family != AF_INET6)		return -EAFNOSUPPORT;	memset(&fl, 0, sizeof(fl));	if (np->sndflow) {		fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;		IP6_ECN_flow_init(fl.fl6_flowlabel);		if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {			struct ip6_flowlabel *flowlabel;			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);			if (flowlabel == NULL)				return -EINVAL;			ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);			fl6_sock_release(flowlabel);		}	}	/*	 * connect() to INADDR_ANY means loopback (BSD'ism).	 */	if (ipv6_addr_any(&usin->sin6_addr))		usin->sin6_addr.s6_addr[15] = 1;	addr_type = ipv6_addr_type(&usin->sin6_addr);	if (addr_type & IPV6_ADDR_MULTICAST)		return -ENETUNREACH;	if (addr_type & IPV6_ADDR_LINKLOCAL) {		if (addr_len >= sizeof(struct sockaddr_in6) &&		    usin->sin6_scope_id) {			/* If interface is set while binding, indices			 * must coincide.			 */			if (sk->sk_bound_dev_if &&			    sk->sk_bound_dev_if != usin->sin6_scope_id)				return -EINVAL;			sk->sk_bound_dev_if = usin->sin6_scope_id;		}		/* Connect to link-local address requires an interface */		if (!sk->sk_bound_dev_if)			return -EINVAL;	}	ipv6_addr_copy(&np->daddr, &usin->sin6_addr);	np->flow_label = fl.fl6_flowlabel;	/*	 * DCCP over IPv4	 */	if (addr_type == IPV6_ADDR_MAPPED) {		u32 exthdrlen = icsk->icsk_ext_hdr_len;		struct sockaddr_in sin;		SOCK_DEBUG(sk, "connect: ipv4 mapped\n");		if (__ipv6_only_sock(sk))			return -ENETUNREACH;		sin.sin_family = AF_INET;		sin.sin_port = usin->sin6_port;		sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];		icsk->icsk_af_ops = &dccp_ipv6_mapped;		sk->sk_backlog_rcv = dccp_v4_do_rcv;		err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));		if (err) {			icsk->icsk_ext_hdr_len = exthdrlen;			icsk->icsk_af_ops = &dccp_ipv6_af_ops;			sk->sk_backlog_rcv = dccp_v6_do_rcv;			goto failure;		} else {			ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),				      inet->saddr);			ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),				      inet->rcv_saddr);		}		return err;	}	if (!ipv6_addr_any(&np->rcv_saddr))		saddr = &np->rcv_saddr;	fl.proto = IPPROTO_DCCP;	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);	ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);	fl.oif = sk->sk_bound_dev_if;	fl.fl_ip_dport = usin->sin6_port;	fl.fl_ip_sport = inet->sport;	security_sk_classify_flow(sk, &fl);	if (np->opt != NULL && np->opt->srcrt != NULL) {		const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;		ipv6_addr_copy(&final, &fl.fl6_dst);		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);		final_p = &final;	}	err = ip6_dst_lookup(sk, &dst, &fl);	if (err)		goto failure;	if (final_p)		ipv6_addr_copy(&fl.fl6_dst, final_p);	err = __xfrm_lookup(&dst, &fl, sk, 1);	if (err < 0) {		if (err == -EREMOTE)			err = ip6_dst_blackhole(sk, &dst, &fl);		if (err < 0)			goto failure;	}	if (saddr == NULL) {		saddr = &fl.fl6_src;		ipv6_addr_copy(&np->rcv_saddr, saddr);	}	/* set the source address */	ipv6_addr_copy(&np->saddr, saddr);	inet->rcv_saddr = LOOPBACK4_IPV6;	__ip6_dst_store(sk, dst, NULL, NULL);	icsk->icsk_ext_hdr_len = 0;	if (np->opt != NULL)		icsk->icsk_ext_hdr_len = (np->opt->opt_flen +					  np->opt->opt_nflen);	inet->dport = usin->sin6_port;	dccp_set_state(sk, DCCP_REQUESTING);	err = inet6_hash_connect(&dccp_death_row, sk);	if (err)		goto late_failure;	dp->dccps_iss = secure_dccpv6_sequence_number(np->saddr.s6_addr32,						      np->daddr.s6_addr32,						      inet->sport, inet->dport);	err = dccp_connect(sk);	if (err)		goto late_failure;	return 0;late_failure:	dccp_set_state(sk, DCCP_CLOSED);	__sk_dst_reset(sk);failure:	inet->dport = 0;	sk->sk_route_caps = 0;	return err;}static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {	.queue_xmit	   = inet6_csk_xmit,	.send_check	   = dccp_v6_send_check,	.rebuild_header	   = inet6_sk_rebuild_header,	.conn_request	   = dccp_v6_conn_request,	.syn_recv_sock	   = dccp_v6_request_recv_sock,	.net_header_len	   = sizeof(struct ipv6hdr),	.setsockopt	   = ipv6_setsockopt,	.getsockopt	   = ipv6_getsockopt,	.addr2sockaddr	   = inet6_csk_addr2sockaddr,	.sockaddr_len	   = sizeof(struct sockaddr_in6),#ifdef CONFIG_COMPAT	.compat_setsockopt = compat_ipv6_setsockopt,	.compat_getsockopt = compat_ipv6_getsockopt,#endif};/* *	DCCP over IPv4 via INET6 API */static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {	.queue_xmit	   = ip_queue_xmit,	.send_check	   = dccp_v4_send_check,	.rebuild_header	   = inet_sk_rebuild_header,	.conn_request	   = dccp_v6_conn_request,	.syn_recv_sock	   = dccp_v6_request_recv_sock,	.net_header_len	   = sizeof(struct iphdr),	.setsockopt	   = ipv6_setsockopt,	.getsockopt	   = ipv6_getsockopt,	.addr2sockaddr	   = inet6_csk_addr2sockaddr,	.sockaddr_len	   = sizeof(struct sockaddr_in6),#ifdef CONFIG_COMPAT	.compat_setsockopt = compat_ipv6_setsockopt,	.compat_getsockopt = compat_ipv6_getsockopt,#endif};/* NOTE: A lot of things set to zero explicitly by call to *       sk_alloc() so need not be done here. */static int dccp_v6_init_sock(struct sock *sk){	static __u8 dccp_v6_ctl_sock_initialized;	int err = dccp_init_sock(sk, dccp_v6_ctl_sock_initialized);	if (err == 0) {		if (unlikely(!dccp_v6_ctl_sock_initialized))			dccp_v6_ctl_sock_initialized = 1;		inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;	}	return err;}static int dccp_v6_destroy_sock(struct sock *sk){	dccp_destroy_sock(sk);	return inet6_destroy_sock(sk);}static struct timewait_sock_ops dccp6_timewait_sock_ops = {	.twsk_obj_size	= sizeof(struct dccp6_timewait_sock),};DEFINE_PROTO_INUSE(dccp_v6)static struct proto dccp_v6_prot = {	.name		   = "DCCPv6",	.owner		   = THIS_MODULE,	.close		   = dccp_close,	.connect	   = dccp_v6_connect,	.disconnect	   = dccp_disconnect,	.ioctl		   = dccp_ioctl,	.init		   = dccp_v6_init_sock,	.setsockopt	   = dccp_setsockopt,	.getsockopt	   = dccp_getsockopt,	.sendmsg	   = dccp_sendmsg,	.recvmsg	   = dccp_recvmsg,	.backlog_rcv	   = dccp_v6_do_rcv,	.hash		   = dccp_v6_hash,	.unhash		   = dccp_unhash,	.accept		   = inet_csk_accept,	.get_port	   = dccp_v6_get_port,	.shutdown	   = dccp_shutdown,	.destroy	   = dccp_v6_destroy_sock,	.orphan_count	   = &dccp_orphan_count,	.max_header	   = MAX_DCCP_HEADER,	.obj_size	   = sizeof(struct dccp6_sock),	.rsk_prot	   = &dccp6_request_sock_ops,	.twsk_prot	   = &dccp6_timewait_sock_ops,#ifdef CONFIG_COMPAT	.compat_setsockopt = compat_dccp_setsockopt,	.compat_getsockopt = compat_dccp_getsockopt,#endif	REF_PROTO_INUSE(dccp_v6)};static struct inet6_protocol dccp_v6_protocol = {	.handler	= dccp_v6_rcv,	.err_handler	= dccp_v6_err,	.flags		= INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,};static struct proto_ops inet6_dccp_ops = {	.family		   = PF_INET6,	.owner		   = THIS_MODULE,	.release	   = inet6_release,	.bind		   = inet6_bind,	.connect	   = inet_stream_connect,	.socketpair	   = sock_no_socketpair,	.accept		   = inet_accept,	.getname	   = inet6_getname,	.poll		   = dccp_poll,	.ioctl		   = inet6_ioctl,	.listen		   = inet_dccp_listen,	.shutdown	   = inet_shutdown,	.setsockopt	   = sock_common_setsockopt,	.getsockopt	   = sock_common_getsockopt,	.sendmsg	   = inet_sendmsg,	.recvmsg	   = sock_common_recvmsg,	.mmap		   = sock_no_mmap,	.sendpage	   = sock_no_sendpage,#ifdef CONFIG_COMPAT	.compat_setsockopt = compat_sock_common_setsockopt,	.compat_getsockopt = compat_sock_common_getsockopt,#endif};static struct inet_protosw dccp_v6_protosw = {	.type		= SOCK_DCCP,	.protocol	= IPPROTO_DCCP,	.prot		= &dccp_v6_prot,	.ops		= &inet6_dccp_ops,	.capability	= -1,	.flags		= INET_PROTOSW_ICSK,};static int __init dccp_v6_init(void){	int err = proto_register(&dccp_v6_prot, 1);	if (err != 0)		goto out;	err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);	if (err != 0)		goto out_unregister_proto;	inet6_register_protosw(&dccp_v6_protosw);	err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6,				       SOCK_DCCP, IPPROTO_DCCP);	if (err != 0)		goto out_unregister_protosw;out:	return err;out_unregister_protosw:	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);	inet6_unregister_protosw(&dccp_v6_protosw);out_unregister_proto:	proto_unregister(&dccp_v6_prot);	goto out;}static void __exit dccp_v6_exit(void){	inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);	inet6_unregister_protosw(&dccp_v6_protosw);	proto_unregister(&dccp_v6_prot);}module_init(dccp_v6_init);module_exit(dccp_v6_exit);/* * __stringify doesn't likes enums, so use SOCK_DCCP (6) and IPPROTO_DCCP (33) * values directly, Also cover the case where the protocol is not specified, * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP */MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6);MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6);MODULE_LICENSE("GPL");MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");

⌨️ 快捷键说明

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