1725 lines · 45.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* SCTP kernel implementation * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll * * This file is part of the SCTP kernel implementation * * Initialization/cleanup for SCTP protocol support. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <linux-sctp@vger.kernel.org> * * Written or modified by: *    La Monte H.P. Yarroll <piggy@acm.org> *    Karl Knutson <karl@athena.chicago.il.us> *    Jon Grimm <jgrimm@us.ibm.com> *    Sridhar Samudrala <sri@us.ibm.com> *    Daisy Chang <daisyc@us.ibm.com> *    Ardelle Fan <ardelle.fan@intel.com> */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/seq_file.h>#include <linux/memblock.h>#include <linux/highmem.h>#include <linux/slab.h>#include <net/flow.h>#include <net/net_namespace.h>#include <net/protocol.h>#include <net/ip.h>#include <net/ipv6.h>#include <net/route.h>#include <net/sctp/sctp.h>#include <net/addrconf.h>#include <net/inet_common.h>#include <net/inet_ecn.h>#include <net/inet_sock.h>#include <net/udp_tunnel.h>#include <net/inet_dscp.h> #define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024) /* Global data structures. */struct sctp_globals sctp_globals __read_mostly; struct idr sctp_assocs_id;DEFINE_SPINLOCK(sctp_assocs_id_lock); static struct sctp_pf *sctp_pf_inet6_specific;static struct sctp_pf *sctp_pf_inet_specific;static struct sctp_af *sctp_af_v4_specific;static struct sctp_af *sctp_af_v6_specific; struct kmem_cache *sctp_chunk_cachep __read_mostly;struct kmem_cache *sctp_bucket_cachep __read_mostly; long sysctl_sctp_mem[3];int sysctl_sctp_rmem[3];int sysctl_sctp_wmem[3]; /* Private helper to extract ipv4 address and stash them in * the protocol structure. */static void sctp_v4_copy_addrlist(struct list_head *addrlist,				  struct net_device *dev){	struct in_device *in_dev;	struct in_ifaddr *ifa;	struct sctp_sockaddr_entry *addr; 	rcu_read_lock();	if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {		rcu_read_unlock();		return;	} 	in_dev_for_each_ifa_rcu(ifa, in_dev) {		/* Add the address to the local list.  */		addr = kzalloc_obj(*addr, GFP_ATOMIC);		if (addr) {			addr->a.v4.sin_family = AF_INET;			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;			addr->valid = 1;			INIT_LIST_HEAD(&addr->list);			list_add_tail(&addr->list, addrlist);		}	} 	rcu_read_unlock();} /* Extract our IP addresses from the system and stash them in the * protocol structure. */static void sctp_get_local_addr_list(struct net *net){	struct net_device *dev;	struct list_head *pos;	struct sctp_af *af; 	rcu_read_lock();	for_each_netdev_rcu(net, dev) {		list_for_each(pos, &sctp_address_families) {			af = list_entry(pos, struct sctp_af, list);			af->copy_addrlist(&net->sctp.local_addr_list, dev);		}	}	rcu_read_unlock();} /* Free the existing local addresses.  */static void sctp_free_local_addr_list(struct net *net){	struct sctp_sockaddr_entry *addr;	struct list_head *pos, *temp; 	list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {		addr = list_entry(pos, struct sctp_sockaddr_entry, list);		list_del(pos);		kfree(addr);	}} /* Copy the local addresses which are valid for 'scope' into 'bp'.  */int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,			      enum sctp_scope scope, gfp_t gfp, int copy_flags){	struct sctp_sockaddr_entry *addr;	union sctp_addr laddr;	int error = 0; 	rcu_read_lock();	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {		if (!addr->valid)			continue;		if (!sctp_in_scope(net, &addr->a, scope))			continue; 		/* Now that the address is in scope, check to see if		 * the address type is really supported by the local		 * sock as well as the remote peer.		 */		if (addr->a.sa.sa_family == AF_INET &&		    (!(copy_flags & SCTP_ADDR4_ALLOWED) ||		     !(copy_flags & SCTP_ADDR4_PEERSUPP)))			continue;		if (addr->a.sa.sa_family == AF_INET6 &&		    (!(copy_flags & SCTP_ADDR6_ALLOWED) ||		     !(copy_flags & SCTP_ADDR6_PEERSUPP)))			continue; 		laddr = addr->a;		/* also works for setting ipv6 address port */		laddr.v4.sin_port = htons(bp->port);		if (sctp_bind_addr_state(bp, &laddr) != -1)			continue; 		error = sctp_add_bind_addr(bp, &addr->a, sizeof(addr->a),					   SCTP_ADDR_SRC, GFP_ATOMIC);		if (error)			break;	} 	rcu_read_unlock();	return error;} /* Copy over any ip options */static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk){	struct inet_sock *newinet, *inet = inet_sk(sk);	struct ip_options_rcu *inet_opt, *newopt = NULL; 	newinet = inet_sk(newsk); 	rcu_read_lock();	inet_opt = rcu_dereference(inet->inet_opt);	if (inet_opt) {		newopt = sock_kmemdup(newsk, inet_opt, sizeof(*inet_opt) +				      inet_opt->opt.optlen, GFP_ATOMIC);		if (!newopt)			pr_err("%s: Failed to copy ip options\n", __func__);	}	RCU_INIT_POINTER(newinet->inet_opt, newopt);	rcu_read_unlock();} /* Account for the IP options */static int sctp_v4_ip_options_len(struct sock *sk){	struct inet_sock *inet = inet_sk(sk);	struct ip_options_rcu *inet_opt;	int len = 0; 	rcu_read_lock();	inet_opt = rcu_dereference(inet->inet_opt);	if (inet_opt)		len = inet_opt->opt.optlen; 	rcu_read_unlock();	return len;} /* Initialize a sctp_addr from in incoming skb.  */static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,			     int is_saddr){	/* Always called on head skb, so this is safe */	struct sctphdr *sh = sctp_hdr(skb);	struct sockaddr_in *sa = &addr->v4; 	addr->v4.sin_family = AF_INET; 	if (is_saddr) {		sa->sin_port = sh->source;		sa->sin_addr.s_addr = ip_hdr(skb)->saddr;	} else {		sa->sin_port = sh->dest;		sa->sin_addr.s_addr = ip_hdr(skb)->daddr;	}	memset(sa->sin_zero, 0, sizeof(sa->sin_zero));} /* Initialize an sctp_addr from a socket. */static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk){	addr->v4.sin_family = AF_INET;	addr->v4.sin_port = 0;	addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr;	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));} /* Initialize sk->sk_rcv_saddr from sctp_addr. */static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk){	inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr;} /* Initialize sk->sk_daddr from sctp_addr. */static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk){	inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr;} /* Initialize a sctp_addr from an address parameter. */static bool sctp_v4_from_addr_param(union sctp_addr *addr,				    union sctp_addr_param *param,				    __be16 port, int iif){	if (ntohs(param->v4.param_hdr.length) < sizeof(struct sctp_ipv4addr_param))		return false; 	addr->v4.sin_family = AF_INET;	addr->v4.sin_port = port;	addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); 	return true;} /* Initialize an address parameter from a sctp_addr and return the length * of the address parameter. */static int sctp_v4_to_addr_param(const union sctp_addr *addr,				 union sctp_addr_param *param){	int length = sizeof(struct sctp_ipv4addr_param); 	param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;	param->v4.param_hdr.length = htons(length);	param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; 	return length;} /* Initialize a sctp_addr from a dst_entry. */static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4,			      __be16 port){	saddr->v4.sin_family = AF_INET;	saddr->v4.sin_port = port;	saddr->v4.sin_addr.s_addr = fl4->saddr;	memset(saddr->v4.sin_zero, 0, sizeof(saddr->v4.sin_zero));} /* Compare two addresses exactly. */static int sctp_v4_cmp_addr(const union sctp_addr *addr1,			    const union sctp_addr *addr2){	if (addr1->sa.sa_family != addr2->sa.sa_family)		return 0;	if (addr1->v4.sin_port != addr2->v4.sin_port)		return 0;	if (addr1->v4.sin_addr.s_addr != addr2->v4.sin_addr.s_addr)		return 0; 	return 1;} /* Initialize addr struct to INADDR_ANY. */static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port){	addr->v4.sin_family = AF_INET;	addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);	addr->v4.sin_port = port;	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));} /* Is this a wildcard address? */static int sctp_v4_is_any(const union sctp_addr *addr){	return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;} /* This function checks if the address is a valid address to be used for * SCTP binding. * * 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_v4_addr_valid(union sctp_addr *addr,			      struct sctp_sock *sp,			      const struct sk_buff *skb){	/* IPv4 addresses not allowed */	if (sp && ipv6_only_sock(sctp_opt2sk(sp)))		return 0; 	/* Is this a non-unicast address or a unusable SCTP address? */	if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr))		return 0; 	/* Is this a broadcast address? */	if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST)		return 0; 	return 1;} /* Should this be available for binding?   */static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp){	struct sock *sk = &sp->inet.sk;	struct net *net = sock_net(sk);	int tb_id = RT_TABLE_LOCAL;	int ret; 	tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ?: tb_id;	ret = inet_addr_type_table(net, addr->v4.sin_addr.s_addr, tb_id);	if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&	   ret != RTN_LOCAL &&	   !inet_test_bit(FREEBIND, sk) &&	    !READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind))		return 0; 	if (ipv6_only_sock(sctp_opt2sk(sp)))		return 0; 	return 1;} /* Checking the loopback, private and other address scopes as defined in * RFC 1918.   The IPv4 scoping is based on the draft for SCTP IPv4 * scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>. * * Level 0 - unusable SCTP addresses * Level 1 - loopback address * Level 2 - link-local addresses * Level 3 - private addresses. * Level 4 - global addresses * For INIT and INIT-ACK address list, let L be the level of * requested destination address, sender and receiver * SHOULD include all of its addresses with level greater * than or equal to L. * * IPv4 scoping can be controlled through sysctl option * net.sctp.addr_scope_policy */static enum sctp_scope sctp_v4_scope(union sctp_addr *addr){	enum sctp_scope retval; 	/* Check for unusable SCTP addresses. */	if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) {		retval =  SCTP_SCOPE_UNUSABLE;	} else if (ipv4_is_loopback(addr->v4.sin_addr.s_addr)) {		retval = SCTP_SCOPE_LOOPBACK;	} else if (ipv4_is_linklocal_169(addr->v4.sin_addr.s_addr)) {		retval = SCTP_SCOPE_LINK;	} else if (ipv4_is_private_10(addr->v4.sin_addr.s_addr) ||		   ipv4_is_private_172(addr->v4.sin_addr.s_addr) ||		   ipv4_is_private_192(addr->v4.sin_addr.s_addr) ||		   ipv4_is_test_198(addr->v4.sin_addr.s_addr)) {		retval = SCTP_SCOPE_PRIVATE;	} else {		retval = SCTP_SCOPE_GLOBAL;	} 	return retval;} /* Returns a valid dst cache entry for the given source and destination ip * addresses. If an association is passed, trys to get a dst entry with a * source address that matches an address in the bind address list. */static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,				struct flowi *fl, struct sock *sk){	struct sctp_association *asoc = t->asoc;	struct rtable *rt;	struct flowi _fl;	struct flowi4 *fl4 = &_fl.u.ip4;	struct sctp_bind_addr *bp;	struct sctp_sockaddr_entry *laddr;	struct dst_entry *dst = NULL;	union sctp_addr *daddr = &t->ipaddr;	union sctp_addr dst_saddr;	dscp_t dscp; 	if (t->dscp & SCTP_DSCP_SET_MASK)		dscp = inet_dsfield_to_dscp(t->dscp);	else		dscp = inet_sk_dscp(inet_sk(sk)); 	memset(&_fl, 0x0, sizeof(_fl));	fl4->daddr  = daddr->v4.sin_addr.s_addr;	fl4->fl4_dport = daddr->v4.sin_port;	fl4->flowi4_proto = IPPROTO_SCTP;	if (asoc) {		fl4->flowi4_dscp = dscp;		fl4->flowi4_scope = ip_sock_rt_scope(asoc->base.sk);		fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if;		fl4->fl4_sport = htons(asoc->base.bind_addr.port);	}	if (saddr) {		fl4->saddr = saddr->v4.sin_addr.s_addr;		if (!fl4->fl4_sport)			fl4->fl4_sport = saddr->v4.sin_port;	} 	pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,		 &fl4->saddr); 	rt = ip_route_output_key(sock_net(sk), fl4);	if (!IS_ERR(rt)) {		dst = &rt->dst;		t->dst = dst;		memcpy(fl, &_fl, sizeof(_fl));	} 	/* If there is no association or if a source address is passed, no	 * more validation is required.	 */	if (!asoc || saddr)		goto out; 	bp = &asoc->base.bind_addr; 	if (dst) {		/* Walk through the bind address list and look for a bind		 * address that matches the source address of the returned dst.		 */		sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port));		rcu_read_lock();		list_for_each_entry_rcu(laddr, &bp->address_list, list) {			if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) ||			    (laddr->state != SCTP_ADDR_SRC &&			    !asoc->src_out_of_asoc_ok))				continue;			if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))				goto out_unlock;		}		rcu_read_unlock(); 		/* None of the bound addresses match the source address of the		 * dst. So release it.		 */		dst_release(dst);		dst = NULL;	} 	/* Walk through the bind address list and try to get a dst that	 * matches a bind address as the source address.	 */	rcu_read_lock();	list_for_each_entry_rcu(laddr, &bp->address_list, list) {		struct net_device *odev; 		if (!laddr->valid)

Lines 1–500 of 1725.