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

📄 ipv6.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
{	return ipv6_addr_any(&addr->v6.sin6_addr);}/* Should this be available for binding?   */static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp){	int type;	struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;	type = ipv6_addr_type(in6);	if (IPV6_ADDR_ANY == type)		return 1;	if (type == IPV6_ADDR_MAPPED) {		if (sp && !sp->v4mapped)			return 0;		if (sp && ipv6_only_sock(sctp_opt2sk(sp)))			return 0;		sctp_v6_map_v4(addr);		return sctp_get_af_specific(AF_INET)->available(addr, sp);	}	if (!(type & IPV6_ADDR_UNICAST))		return 0;	return ipv6_chk_addr(&init_net, in6, NULL, 0);}/* This function checks if the address is a valid address to be used for * SCTP. * * Output: * Return 0 - If the address is a non-unicast or an illegal address. * Return 1 - If the address is a unicast. */static int sctp_v6_addr_valid(union sctp_addr *addr,			      struct sctp_sock *sp,			      const struct sk_buff *skb){	int ret = ipv6_addr_type(&addr->v6.sin6_addr);	/* Support v4-mapped-v6 address. */	if (ret == IPV6_ADDR_MAPPED) {		/* Note: This routine is used in input, so v4-mapped-v6		 * are disallowed here when there is no sctp_sock.		 */		if (!sp || !sp->v4mapped)			return 0;		if (sp && ipv6_only_sock(sctp_opt2sk(sp)))			return 0;		sctp_v6_map_v4(addr);		return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp, skb);	}	/* Is this a non-unicast address */	if (!(ret & IPV6_ADDR_UNICAST))		return 0;	return 1;}/* What is the scope of 'addr'?  */static sctp_scope_t sctp_v6_scope(union sctp_addr *addr){	int v6scope;	sctp_scope_t retval;	/* The IPv6 scope is really a set of bit fields.	 * See IFA_* in <net/if_inet6.h>.  Map to a generic SCTP scope.	 */	v6scope = ipv6_addr_scope(&addr->v6.sin6_addr);	switch (v6scope) {	case IFA_HOST:		retval = SCTP_SCOPE_LOOPBACK;		break;	case IFA_LINK:		retval = SCTP_SCOPE_LINK;		break;	case IFA_SITE:		retval = SCTP_SCOPE_PRIVATE;		break;	default:		retval = SCTP_SCOPE_GLOBAL;		break;	}	return retval;}/* Create and initialize a new sk for the socket to be returned by accept(). */static struct sock *sctp_v6_create_accept_sk(struct sock *sk,					     struct sctp_association *asoc){	struct inet_sock *inet = inet_sk(sk);	struct sock *newsk;	struct inet_sock *newinet;	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);	struct sctp6_sock *newsctp6sk;	newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot);	if (!newsk)		goto out;	sock_init_data(NULL, newsk);	newsk->sk_type = SOCK_STREAM;	newsk->sk_prot = sk->sk_prot;	newsk->sk_no_check = sk->sk_no_check;	newsk->sk_reuse = sk->sk_reuse;	newsk->sk_destruct = inet_sock_destruct;	newsk->sk_family = PF_INET6;	newsk->sk_protocol = IPPROTO_SCTP;	newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;	newsk->sk_shutdown = sk->sk_shutdown;	sock_reset_flag(sk, SOCK_ZAPPED);	newsctp6sk = (struct sctp6_sock *)newsk;	inet_sk(newsk)->pinet6 = &newsctp6sk->inet6;	sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped;	newinet = inet_sk(newsk);	newnp = inet6_sk(newsk);	memcpy(newnp, np, sizeof(struct ipv6_pinfo));	/* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()	 * and getpeername().	 */	newinet->sport = inet->sport;	newnp->saddr = np->saddr;	newnp->rcv_saddr = np->rcv_saddr;	newinet->dport = htons(asoc->peer.port);	sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);	/* Init the ipv4 part of the socket since we can have sockets	 * using v6 API for ipv4.	 */	newinet->uc_ttl = -1;	newinet->mc_loop = 1;	newinet->mc_ttl = 1;	newinet->mc_index = 0;	newinet->mc_list = NULL;	if (ipv4_config.no_pmtu_disc)		newinet->pmtudisc = IP_PMTUDISC_DONT;	else		newinet->pmtudisc = IP_PMTUDISC_WANT;	sk_refcnt_debug_inc(newsk);	if (newsk->sk_prot->init(newsk)) {		sk_common_release(newsk);		newsk = NULL;	}out:	return newsk;}/* Map v4 address to mapped v6 address */static void sctp_v6_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr){	if (sp->v4mapped && AF_INET == addr->sa.sa_family)		sctp_v4_map_v6(addr);}/* Where did this skb come from?  */static int sctp_v6_skb_iif(const struct sk_buff *skb){	struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;	return opt->iif;}/* Was this packet marked by Explicit Congestion Notification? */static int sctp_v6_is_ce(const struct sk_buff *skb){	return *((__u32 *)(ipv6_hdr(skb))) & htonl(1 << 20);}/* Dump the v6 addr to the seq file. */static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr){	seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr));}/* Initialize a PF_INET6 socket msg_name. */static void sctp_inet6_msgname(char *msgname, int *addr_len){	struct sockaddr_in6 *sin6;	sin6 = (struct sockaddr_in6 *)msgname;	sin6->sin6_family = AF_INET6;	sin6->sin6_flowinfo = 0;	sin6->sin6_scope_id = 0; /*FIXME */	*addr_len = sizeof(struct sockaddr_in6);}/* Initialize a PF_INET msgname from a ulpevent. */static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,				     char *msgname, int *addrlen){	struct sockaddr_in6 *sin6, *sin6from;	if (msgname) {		union sctp_addr *addr;		struct sctp_association *asoc;		asoc = event->asoc;		sctp_inet6_msgname(msgname, addrlen);		sin6 = (struct sockaddr_in6 *)msgname;		sin6->sin6_port = htons(asoc->peer.port);		addr = &asoc->peer.primary_addr;		/* Note: If we go to a common v6 format, this code		 * will change.		 */		/* Map ipv4 address into v4-mapped-on-v6 address.  */		if (sctp_sk(asoc->base.sk)->v4mapped &&		    AF_INET == addr->sa.sa_family) {			sctp_v4_map_v6((union sctp_addr *)sin6);			sin6->sin6_addr.s6_addr32[3] =				addr->v4.sin_addr.s_addr;			return;		}		sin6from = &asoc->peer.primary_addr.v6;		ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr);		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)			sin6->sin6_scope_id = sin6from->sin6_scope_id;	}}/* Initialize a msg_name from an inbound skb. */static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,				   int *addr_len){	struct sctphdr *sh;	struct sockaddr_in6 *sin6;	if (msgname) {		sctp_inet6_msgname(msgname, addr_len);		sin6 = (struct sockaddr_in6 *)msgname;		sh = sctp_hdr(skb);		sin6->sin6_port = sh->source;		/* Map ipv4 address into v4-mapped-on-v6 address. */		if (sctp_sk(skb->sk)->v4mapped &&		    ip_hdr(skb)->version == 4) {			sctp_v4_map_v6((union sctp_addr *)sin6);			sin6->sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr;			return;		}		/* Otherwise, just copy the v6 address. */		ipv6_addr_copy(&sin6->sin6_addr, &ipv6_hdr(skb)->saddr);		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {			struct sctp_ulpevent *ev = sctp_skb2event(skb);			sin6->sin6_scope_id = ev->iif;		}	}}/* Do we support this AF? */static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp){	switch (family) {	case AF_INET6:		return 1;	/* v4-mapped-v6 addresses */	case AF_INET:		if (!__ipv6_only_sock(sctp_opt2sk(sp)) && sp->v4mapped)			return 1;	default:		return 0;	}}/* Address matching with wildcards allowed.  This extra level * of indirection lets us choose whether a PF_INET6 should * disallow any v4 addresses if we so choose. */static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,			       const union sctp_addr *addr2,			       struct sctp_sock *opt){	struct sctp_af *af1, *af2;	af1 = sctp_get_af_specific(addr1->sa.sa_family);	af2 = sctp_get_af_specific(addr2->sa.sa_family);	if (!af1 || !af2)		return 0;	/* Today, wildcard AF_INET/AF_INET6. */	if (sctp_is_any(addr1) || sctp_is_any(addr2))		return 1;	if (addr1->sa.sa_family != addr2->sa.sa_family)		return 0;	return af1->cmp_addr(addr1, addr2);}/* Verify that the provided sockaddr looks bindable.   Common verification, * has already been taken care of. */static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr){	struct sctp_af *af;	/* ASSERT: address family has already been verified. */	if (addr->sa.sa_family != AF_INET6)		af = sctp_get_af_specific(addr->sa.sa_family);	else {		int type = ipv6_addr_type(&addr->v6.sin6_addr);		struct net_device *dev;		if (type & IPV6_ADDR_LINKLOCAL) {			if (!addr->v6.sin6_scope_id)				return 0;			dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);			if (!dev)				return 0;			if (!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,					   dev, 0)) {				dev_put(dev);				return 0;			}			dev_put(dev);		}		af = opt->pf->af;	}	return af->available(addr, opt);}/* Verify that the provided sockaddr looks sendable.   Common verification, * has already been taken care of. */static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr){	struct sctp_af *af = NULL;	/* ASSERT: address family has already been verified. */	if (addr->sa.sa_family != AF_INET6)		af = sctp_get_af_specific(addr->sa.sa_family);	else {		int type = ipv6_addr_type(&addr->v6.sin6_addr);		struct net_device *dev;		if (type & IPV6_ADDR_LINKLOCAL) {			if (!addr->v6.sin6_scope_id)				return 0;			dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);			if (!dev)				return 0;			dev_put(dev);		}		af = opt->pf->af;	}	return af != NULL;}/* Fill in Supported Address Type information for INIT and INIT-ACK * chunks.   Note: In the future, we may want to look at sock options * to determine whether a PF_INET6 socket really wants to have IPV4 * addresses. * Returns number of addresses supported. */static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,				      __be16 *types){	types[0] = SCTP_PARAM_IPV4_ADDRESS;	types[1] = SCTP_PARAM_IPV6_ADDRESS;	return 2;}static const struct proto_ops inet6_seqpacket_ops = {	.family		   = PF_INET6,	.owner		   = THIS_MODULE,	.release	   = inet6_release,	.bind		   = inet6_bind,	.connect	   = inet_dgram_connect,	.socketpair	   = sock_no_socketpair,	.accept		   = inet_accept,	.getname	   = inet6_getname,	.poll		   = sctp_poll,	.ioctl		   = inet6_ioctl,	.listen		   = sctp_inet_listen,	.shutdown	   = inet_shutdown,	.setsockopt	   = sock_common_setsockopt,	.getsockopt	   = sock_common_getsockopt,	.sendmsg	   = inet_sendmsg,	.recvmsg	   = sock_common_recvmsg,	.mmap		   = sock_no_mmap,#ifdef CONFIG_COMPAT	.compat_setsockopt = compat_sock_common_setsockopt,	.compat_getsockopt = compat_sock_common_getsockopt,#endif};static struct inet_protosw sctpv6_seqpacket_protosw = {	.type          = SOCK_SEQPACKET,	.protocol      = IPPROTO_SCTP,	.prot 	       = &sctpv6_prot,	.ops           = &inet6_seqpacket_ops,	.capability    = -1,	.no_check      = 0,	.flags         = SCTP_PROTOSW_FLAG};static struct inet_protosw sctpv6_stream_protosw = {	.type          = SOCK_STREAM,	.protocol      = IPPROTO_SCTP,	.prot 	       = &sctpv6_prot,	.ops           = &inet6_seqpacket_ops,	.capability    = -1,	.no_check      = 0,	.flags         = SCTP_PROTOSW_FLAG,};static int sctp6_rcv(struct sk_buff *skb){	return sctp_rcv(skb) ? -1 : 0;}static struct inet6_protocol sctpv6_protocol = {	.handler      = sctp6_rcv,	.err_handler  = sctp_v6_err,	.flags        = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,};static struct sctp_af sctp_af_inet6 = {	.sa_family	   = AF_INET6,	.sctp_xmit	   = sctp_v6_xmit,	.setsockopt	   = ipv6_setsockopt,	.getsockopt	   = ipv6_getsockopt,	.get_dst	   = sctp_v6_get_dst,	.get_saddr	   = sctp_v6_get_saddr,	.copy_addrlist	   = sctp_v6_copy_addrlist,	.from_skb	   = sctp_v6_from_skb,	.from_sk	   = sctp_v6_from_sk,	.to_sk_saddr	   = sctp_v6_to_sk_saddr,	.to_sk_daddr	   = sctp_v6_to_sk_daddr,	.from_addr_param   = sctp_v6_from_addr_param,	.to_addr_param	   = sctp_v6_to_addr_param,	.dst_saddr	   = sctp_v6_dst_saddr,	.cmp_addr	   = sctp_v6_cmp_addr,	.scope		   = sctp_v6_scope,	.addr_valid	   = sctp_v6_addr_valid,	.inaddr_any	   = sctp_v6_inaddr_any,	.is_any		   = sctp_v6_is_any,	.available	   = sctp_v6_available,	.skb_iif	   = sctp_v6_skb_iif,	.is_ce		   = sctp_v6_is_ce,	.seq_dump_addr	   = sctp_v6_seq_dump_addr,	.net_header_len	   = sizeof(struct ipv6hdr),	.sockaddr_len	   = sizeof(struct sockaddr_in6),#ifdef CONFIG_COMPAT	.compat_setsockopt = compat_ipv6_setsockopt,	.compat_getsockopt = compat_ipv6_getsockopt,#endif};static struct sctp_pf sctp_pf_inet6 = {	.event_msgname = sctp_inet6_event_msgname,	.skb_msgname   = sctp_inet6_skb_msgname,	.af_supported  = sctp_inet6_af_supported,	.cmp_addr      = sctp_inet6_cmp_addr,	.bind_verify   = sctp_inet6_bind_verify,	.send_verify   = sctp_inet6_send_verify,	.supported_addrs = sctp_inet6_supported_addrs,	.create_accept_sk = sctp_v6_create_accept_sk,	.addr_v4map    = sctp_v6_addr_v4map,	.af            = &sctp_af_inet6,};/* Initialize IPv6 support and register with socket layer.  */void sctp_v6_pf_init(void){	/* Register the SCTP specific PF_INET6 functions. */	sctp_register_pf(&sctp_pf_inet6, PF_INET6);	/* Register the SCTP specific AF_INET6 functions. */	sctp_register_af(&sctp_af_inet6);}void sctp_v6_pf_exit(void){	list_del(&sctp_af_inet6.list);}/* Initialize IPv6 support and register with socket layer.  */int sctp_v6_protosw_init(void){	int rc;	rc = proto_register(&sctpv6_prot, 1);	if (rc)		return rc;	/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */	inet6_register_protosw(&sctpv6_seqpacket_protosw);	inet6_register_protosw(&sctpv6_stream_protosw);	return 0;}void sctp_v6_protosw_exit(void){	inet6_unregister_protosw(&sctpv6_seqpacket_protosw);	inet6_unregister_protosw(&sctpv6_stream_protosw);	proto_unregister(&sctpv6_prot);}/* Register with inet6 layer. */int sctp_v6_add_protocol(void){	/* Register notifier for inet6 address additions/deletions. */	register_inet6addr_notifier(&sctp_inet6addr_notifier);	if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)		return -EAGAIN;	return 0;}/* Unregister with inet6 layer. */void sctp_v6_del_protocol(void){	inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);	unregister_inet6addr_notifier(&sctp_inet6addr_notifier);}

⌨️ 快捷键说明

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