162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* SCTP kernel implementation 362306a36Sopenharmony_ci * (C) Copyright IBM Corp. 2001, 2004 462306a36Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 562306a36Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 662306a36Sopenharmony_ci * Copyright (c) 2001 Intel Corp. 762306a36Sopenharmony_ci * Copyright (c) 2001 Nokia, Inc. 862306a36Sopenharmony_ci * Copyright (c) 2001 La Monte H.P. Yarroll 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * This file is part of the SCTP kernel implementation 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Initialization/cleanup for SCTP protocol support. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the 1562306a36Sopenharmony_ci * email address(es): 1662306a36Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Written or modified by: 1962306a36Sopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 2062306a36Sopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 2162306a36Sopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 2262306a36Sopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 2362306a36Sopenharmony_ci * Daisy Chang <daisyc@us.ibm.com> 2462306a36Sopenharmony_ci * Ardelle Fan <ardelle.fan@intel.com> 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <linux/module.h> 3062306a36Sopenharmony_ci#include <linux/init.h> 3162306a36Sopenharmony_ci#include <linux/netdevice.h> 3262306a36Sopenharmony_ci#include <linux/inetdevice.h> 3362306a36Sopenharmony_ci#include <linux/seq_file.h> 3462306a36Sopenharmony_ci#include <linux/memblock.h> 3562306a36Sopenharmony_ci#include <linux/highmem.h> 3662306a36Sopenharmony_ci#include <linux/slab.h> 3762306a36Sopenharmony_ci#include <net/net_namespace.h> 3862306a36Sopenharmony_ci#include <net/protocol.h> 3962306a36Sopenharmony_ci#include <net/ip.h> 4062306a36Sopenharmony_ci#include <net/ipv6.h> 4162306a36Sopenharmony_ci#include <net/route.h> 4262306a36Sopenharmony_ci#include <net/sctp/sctp.h> 4362306a36Sopenharmony_ci#include <net/addrconf.h> 4462306a36Sopenharmony_ci#include <net/inet_common.h> 4562306a36Sopenharmony_ci#include <net/inet_ecn.h> 4662306a36Sopenharmony_ci#include <net/udp_tunnel.h> 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* Global data structures. */ 5162306a36Sopenharmony_cistruct sctp_globals sctp_globals __read_mostly; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct idr sctp_assocs_id; 5462306a36Sopenharmony_ciDEFINE_SPINLOCK(sctp_assocs_id_lock); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic struct sctp_pf *sctp_pf_inet6_specific; 5762306a36Sopenharmony_cistatic struct sctp_pf *sctp_pf_inet_specific; 5862306a36Sopenharmony_cistatic struct sctp_af *sctp_af_v4_specific; 5962306a36Sopenharmony_cistatic struct sctp_af *sctp_af_v6_specific; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistruct kmem_cache *sctp_chunk_cachep __read_mostly; 6262306a36Sopenharmony_cistruct kmem_cache *sctp_bucket_cachep __read_mostly; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cilong sysctl_sctp_mem[3]; 6562306a36Sopenharmony_ciint sysctl_sctp_rmem[3]; 6662306a36Sopenharmony_ciint sysctl_sctp_wmem[3]; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* Private helper to extract ipv4 address and stash them in 6962306a36Sopenharmony_ci * the protocol structure. 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_cistatic void sctp_v4_copy_addrlist(struct list_head *addrlist, 7262306a36Sopenharmony_ci struct net_device *dev) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct in_device *in_dev; 7562306a36Sopenharmony_ci struct in_ifaddr *ifa; 7662306a36Sopenharmony_ci struct sctp_sockaddr_entry *addr; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci rcu_read_lock(); 7962306a36Sopenharmony_ci if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { 8062306a36Sopenharmony_ci rcu_read_unlock(); 8162306a36Sopenharmony_ci return; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci in_dev_for_each_ifa_rcu(ifa, in_dev) { 8562306a36Sopenharmony_ci /* Add the address to the local list. */ 8662306a36Sopenharmony_ci addr = kzalloc(sizeof(*addr), GFP_ATOMIC); 8762306a36Sopenharmony_ci if (addr) { 8862306a36Sopenharmony_ci addr->a.v4.sin_family = AF_INET; 8962306a36Sopenharmony_ci addr->a.v4.sin_addr.s_addr = ifa->ifa_local; 9062306a36Sopenharmony_ci addr->valid = 1; 9162306a36Sopenharmony_ci INIT_LIST_HEAD(&addr->list); 9262306a36Sopenharmony_ci list_add_tail(&addr->list, addrlist); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci rcu_read_unlock(); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* Extract our IP addresses from the system and stash them in the 10062306a36Sopenharmony_ci * protocol structure. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_cistatic void sctp_get_local_addr_list(struct net *net) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct net_device *dev; 10562306a36Sopenharmony_ci struct list_head *pos; 10662306a36Sopenharmony_ci struct sctp_af *af; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci rcu_read_lock(); 10962306a36Sopenharmony_ci for_each_netdev_rcu(net, dev) { 11062306a36Sopenharmony_ci list_for_each(pos, &sctp_address_families) { 11162306a36Sopenharmony_ci af = list_entry(pos, struct sctp_af, list); 11262306a36Sopenharmony_ci af->copy_addrlist(&net->sctp.local_addr_list, dev); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci rcu_read_unlock(); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* Free the existing local addresses. */ 11962306a36Sopenharmony_cistatic void sctp_free_local_addr_list(struct net *net) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct sctp_sockaddr_entry *addr; 12262306a36Sopenharmony_ci struct list_head *pos, *temp; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { 12562306a36Sopenharmony_ci addr = list_entry(pos, struct sctp_sockaddr_entry, list); 12662306a36Sopenharmony_ci list_del(pos); 12762306a36Sopenharmony_ci kfree(addr); 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* Copy the local addresses which are valid for 'scope' into 'bp'. */ 13262306a36Sopenharmony_ciint sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, 13362306a36Sopenharmony_ci enum sctp_scope scope, gfp_t gfp, int copy_flags) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct sctp_sockaddr_entry *addr; 13662306a36Sopenharmony_ci union sctp_addr laddr; 13762306a36Sopenharmony_ci int error = 0; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci rcu_read_lock(); 14062306a36Sopenharmony_ci list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { 14162306a36Sopenharmony_ci if (!addr->valid) 14262306a36Sopenharmony_ci continue; 14362306a36Sopenharmony_ci if (!sctp_in_scope(net, &addr->a, scope)) 14462306a36Sopenharmony_ci continue; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* Now that the address is in scope, check to see if 14762306a36Sopenharmony_ci * the address type is really supported by the local 14862306a36Sopenharmony_ci * sock as well as the remote peer. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ci if (addr->a.sa.sa_family == AF_INET && 15162306a36Sopenharmony_ci (!(copy_flags & SCTP_ADDR4_ALLOWED) || 15262306a36Sopenharmony_ci !(copy_flags & SCTP_ADDR4_PEERSUPP))) 15362306a36Sopenharmony_ci continue; 15462306a36Sopenharmony_ci if (addr->a.sa.sa_family == AF_INET6 && 15562306a36Sopenharmony_ci (!(copy_flags & SCTP_ADDR6_ALLOWED) || 15662306a36Sopenharmony_ci !(copy_flags & SCTP_ADDR6_PEERSUPP))) 15762306a36Sopenharmony_ci continue; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci laddr = addr->a; 16062306a36Sopenharmony_ci /* also works for setting ipv6 address port */ 16162306a36Sopenharmony_ci laddr.v4.sin_port = htons(bp->port); 16262306a36Sopenharmony_ci if (sctp_bind_addr_state(bp, &laddr) != -1) 16362306a36Sopenharmony_ci continue; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci error = sctp_add_bind_addr(bp, &addr->a, sizeof(addr->a), 16662306a36Sopenharmony_ci SCTP_ADDR_SRC, GFP_ATOMIC); 16762306a36Sopenharmony_ci if (error) 16862306a36Sopenharmony_ci break; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci rcu_read_unlock(); 17262306a36Sopenharmony_ci return error; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* Copy over any ip options */ 17662306a36Sopenharmony_cistatic void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct inet_sock *newinet, *inet = inet_sk(sk); 17962306a36Sopenharmony_ci struct ip_options_rcu *inet_opt, *newopt = NULL; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci newinet = inet_sk(newsk); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci rcu_read_lock(); 18462306a36Sopenharmony_ci inet_opt = rcu_dereference(inet->inet_opt); 18562306a36Sopenharmony_ci if (inet_opt) { 18662306a36Sopenharmony_ci newopt = sock_kmalloc(newsk, sizeof(*inet_opt) + 18762306a36Sopenharmony_ci inet_opt->opt.optlen, GFP_ATOMIC); 18862306a36Sopenharmony_ci if (newopt) 18962306a36Sopenharmony_ci memcpy(newopt, inet_opt, sizeof(*inet_opt) + 19062306a36Sopenharmony_ci inet_opt->opt.optlen); 19162306a36Sopenharmony_ci else 19262306a36Sopenharmony_ci pr_err("%s: Failed to copy ip options\n", __func__); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci RCU_INIT_POINTER(newinet->inet_opt, newopt); 19562306a36Sopenharmony_ci rcu_read_unlock(); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* Account for the IP options */ 19962306a36Sopenharmony_cistatic int sctp_v4_ip_options_len(struct sock *sk) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 20262306a36Sopenharmony_ci struct ip_options_rcu *inet_opt; 20362306a36Sopenharmony_ci int len = 0; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci rcu_read_lock(); 20662306a36Sopenharmony_ci inet_opt = rcu_dereference(inet->inet_opt); 20762306a36Sopenharmony_ci if (inet_opt) 20862306a36Sopenharmony_ci len = inet_opt->opt.optlen; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci rcu_read_unlock(); 21162306a36Sopenharmony_ci return len; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/* Initialize a sctp_addr from in incoming skb. */ 21562306a36Sopenharmony_cistatic void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, 21662306a36Sopenharmony_ci int is_saddr) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci /* Always called on head skb, so this is safe */ 21962306a36Sopenharmony_ci struct sctphdr *sh = sctp_hdr(skb); 22062306a36Sopenharmony_ci struct sockaddr_in *sa = &addr->v4; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci addr->v4.sin_family = AF_INET; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (is_saddr) { 22562306a36Sopenharmony_ci sa->sin_port = sh->source; 22662306a36Sopenharmony_ci sa->sin_addr.s_addr = ip_hdr(skb)->saddr; 22762306a36Sopenharmony_ci } else { 22862306a36Sopenharmony_ci sa->sin_port = sh->dest; 22962306a36Sopenharmony_ci sa->sin_addr.s_addr = ip_hdr(skb)->daddr; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci memset(sa->sin_zero, 0, sizeof(sa->sin_zero)); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/* Initialize an sctp_addr from a socket. */ 23562306a36Sopenharmony_cistatic void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci addr->v4.sin_family = AF_INET; 23862306a36Sopenharmony_ci addr->v4.sin_port = 0; 23962306a36Sopenharmony_ci addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr; 24062306a36Sopenharmony_ci memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/* Initialize sk->sk_rcv_saddr from sctp_addr. */ 24462306a36Sopenharmony_cistatic void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/* Initialize sk->sk_daddr from sctp_addr. */ 25062306a36Sopenharmony_cistatic void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci/* Initialize a sctp_addr from an address parameter. */ 25662306a36Sopenharmony_cistatic bool sctp_v4_from_addr_param(union sctp_addr *addr, 25762306a36Sopenharmony_ci union sctp_addr_param *param, 25862306a36Sopenharmony_ci __be16 port, int iif) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci if (ntohs(param->v4.param_hdr.length) < sizeof(struct sctp_ipv4addr_param)) 26162306a36Sopenharmony_ci return false; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci addr->v4.sin_family = AF_INET; 26462306a36Sopenharmony_ci addr->v4.sin_port = port; 26562306a36Sopenharmony_ci addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; 26662306a36Sopenharmony_ci memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return true; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/* Initialize an address parameter from a sctp_addr and return the length 27262306a36Sopenharmony_ci * of the address parameter. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_cistatic int sctp_v4_to_addr_param(const union sctp_addr *addr, 27562306a36Sopenharmony_ci union sctp_addr_param *param) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci int length = sizeof(struct sctp_ipv4addr_param); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; 28062306a36Sopenharmony_ci param->v4.param_hdr.length = htons(length); 28162306a36Sopenharmony_ci param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return length; 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci/* Initialize a sctp_addr from a dst_entry. */ 28762306a36Sopenharmony_cistatic void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4, 28862306a36Sopenharmony_ci __be16 port) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci saddr->v4.sin_family = AF_INET; 29162306a36Sopenharmony_ci saddr->v4.sin_port = port; 29262306a36Sopenharmony_ci saddr->v4.sin_addr.s_addr = fl4->saddr; 29362306a36Sopenharmony_ci memset(saddr->v4.sin_zero, 0, sizeof(saddr->v4.sin_zero)); 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci/* Compare two addresses exactly. */ 29762306a36Sopenharmony_cistatic int sctp_v4_cmp_addr(const union sctp_addr *addr1, 29862306a36Sopenharmony_ci const union sctp_addr *addr2) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci if (addr1->sa.sa_family != addr2->sa.sa_family) 30162306a36Sopenharmony_ci return 0; 30262306a36Sopenharmony_ci if (addr1->v4.sin_port != addr2->v4.sin_port) 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci if (addr1->v4.sin_addr.s_addr != addr2->v4.sin_addr.s_addr) 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return 1; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci/* Initialize addr struct to INADDR_ANY. */ 31162306a36Sopenharmony_cistatic void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci addr->v4.sin_family = AF_INET; 31462306a36Sopenharmony_ci addr->v4.sin_addr.s_addr = htonl(INADDR_ANY); 31562306a36Sopenharmony_ci addr->v4.sin_port = port; 31662306a36Sopenharmony_ci memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/* Is this a wildcard address? */ 32062306a36Sopenharmony_cistatic int sctp_v4_is_any(const union sctp_addr *addr) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* This function checks if the address is a valid address to be used for 32662306a36Sopenharmony_ci * SCTP binding. 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci * Output: 32962306a36Sopenharmony_ci * Return 0 - If the address is a non-unicast or an illegal address. 33062306a36Sopenharmony_ci * Return 1 - If the address is a unicast. 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_cistatic int sctp_v4_addr_valid(union sctp_addr *addr, 33362306a36Sopenharmony_ci struct sctp_sock *sp, 33462306a36Sopenharmony_ci const struct sk_buff *skb) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci /* IPv4 addresses not allowed */ 33762306a36Sopenharmony_ci if (sp && ipv6_only_sock(sctp_opt2sk(sp))) 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* Is this a non-unicast address or a unusable SCTP address? */ 34162306a36Sopenharmony_ci if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) 34262306a36Sopenharmony_ci return 0; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* Is this a broadcast address? */ 34562306a36Sopenharmony_ci if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST) 34662306a36Sopenharmony_ci return 0; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci return 1; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* Should this be available for binding? */ 35262306a36Sopenharmony_cistatic int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct sock *sk = &sp->inet.sk; 35562306a36Sopenharmony_ci struct net *net = sock_net(sk); 35662306a36Sopenharmony_ci int tb_id = RT_TABLE_LOCAL; 35762306a36Sopenharmony_ci int ret; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ?: tb_id; 36062306a36Sopenharmony_ci ret = inet_addr_type_table(net, addr->v4.sin_addr.s_addr, tb_id); 36162306a36Sopenharmony_ci if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && 36262306a36Sopenharmony_ci ret != RTN_LOCAL && 36362306a36Sopenharmony_ci !inet_test_bit(FREEBIND, sk) && 36462306a36Sopenharmony_ci !READ_ONCE(net->ipv4.sysctl_ip_nonlocal_bind)) 36562306a36Sopenharmony_ci return 0; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (ipv6_only_sock(sctp_opt2sk(sp))) 36862306a36Sopenharmony_ci return 0; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci return 1; 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci/* Checking the loopback, private and other address scopes as defined in 37462306a36Sopenharmony_ci * RFC 1918. The IPv4 scoping is based on the draft for SCTP IPv4 37562306a36Sopenharmony_ci * scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>. 37662306a36Sopenharmony_ci * 37762306a36Sopenharmony_ci * Level 0 - unusable SCTP addresses 37862306a36Sopenharmony_ci * Level 1 - loopback address 37962306a36Sopenharmony_ci * Level 2 - link-local addresses 38062306a36Sopenharmony_ci * Level 3 - private addresses. 38162306a36Sopenharmony_ci * Level 4 - global addresses 38262306a36Sopenharmony_ci * For INIT and INIT-ACK address list, let L be the level of 38362306a36Sopenharmony_ci * requested destination address, sender and receiver 38462306a36Sopenharmony_ci * SHOULD include all of its addresses with level greater 38562306a36Sopenharmony_ci * than or equal to L. 38662306a36Sopenharmony_ci * 38762306a36Sopenharmony_ci * IPv4 scoping can be controlled through sysctl option 38862306a36Sopenharmony_ci * net.sctp.addr_scope_policy 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_cistatic enum sctp_scope sctp_v4_scope(union sctp_addr *addr) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci enum sctp_scope retval; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* Check for unusable SCTP addresses. */ 39562306a36Sopenharmony_ci if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) { 39662306a36Sopenharmony_ci retval = SCTP_SCOPE_UNUSABLE; 39762306a36Sopenharmony_ci } else if (ipv4_is_loopback(addr->v4.sin_addr.s_addr)) { 39862306a36Sopenharmony_ci retval = SCTP_SCOPE_LOOPBACK; 39962306a36Sopenharmony_ci } else if (ipv4_is_linklocal_169(addr->v4.sin_addr.s_addr)) { 40062306a36Sopenharmony_ci retval = SCTP_SCOPE_LINK; 40162306a36Sopenharmony_ci } else if (ipv4_is_private_10(addr->v4.sin_addr.s_addr) || 40262306a36Sopenharmony_ci ipv4_is_private_172(addr->v4.sin_addr.s_addr) || 40362306a36Sopenharmony_ci ipv4_is_private_192(addr->v4.sin_addr.s_addr) || 40462306a36Sopenharmony_ci ipv4_is_test_198(addr->v4.sin_addr.s_addr)) { 40562306a36Sopenharmony_ci retval = SCTP_SCOPE_PRIVATE; 40662306a36Sopenharmony_ci } else { 40762306a36Sopenharmony_ci retval = SCTP_SCOPE_GLOBAL; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return retval; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci/* Returns a valid dst cache entry for the given source and destination ip 41462306a36Sopenharmony_ci * addresses. If an association is passed, trys to get a dst entry with a 41562306a36Sopenharmony_ci * source address that matches an address in the bind address list. 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_cistatic void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, 41862306a36Sopenharmony_ci struct flowi *fl, struct sock *sk) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct sctp_association *asoc = t->asoc; 42162306a36Sopenharmony_ci struct rtable *rt; 42262306a36Sopenharmony_ci struct flowi _fl; 42362306a36Sopenharmony_ci struct flowi4 *fl4 = &_fl.u.ip4; 42462306a36Sopenharmony_ci struct sctp_bind_addr *bp; 42562306a36Sopenharmony_ci struct sctp_sockaddr_entry *laddr; 42662306a36Sopenharmony_ci struct dst_entry *dst = NULL; 42762306a36Sopenharmony_ci union sctp_addr *daddr = &t->ipaddr; 42862306a36Sopenharmony_ci union sctp_addr dst_saddr; 42962306a36Sopenharmony_ci __u8 tos = inet_sk(sk)->tos; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (t->dscp & SCTP_DSCP_SET_MASK) 43262306a36Sopenharmony_ci tos = t->dscp & SCTP_DSCP_VAL_MASK; 43362306a36Sopenharmony_ci memset(&_fl, 0x0, sizeof(_fl)); 43462306a36Sopenharmony_ci fl4->daddr = daddr->v4.sin_addr.s_addr; 43562306a36Sopenharmony_ci fl4->fl4_dport = daddr->v4.sin_port; 43662306a36Sopenharmony_ci fl4->flowi4_proto = IPPROTO_SCTP; 43762306a36Sopenharmony_ci if (asoc) { 43862306a36Sopenharmony_ci fl4->flowi4_tos = RT_TOS(tos); 43962306a36Sopenharmony_ci fl4->flowi4_scope = ip_sock_rt_scope(asoc->base.sk); 44062306a36Sopenharmony_ci fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; 44162306a36Sopenharmony_ci fl4->fl4_sport = htons(asoc->base.bind_addr.port); 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci if (saddr) { 44462306a36Sopenharmony_ci fl4->saddr = saddr->v4.sin_addr.s_addr; 44562306a36Sopenharmony_ci if (!fl4->fl4_sport) 44662306a36Sopenharmony_ci fl4->fl4_sport = saddr->v4.sin_port; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr, 45062306a36Sopenharmony_ci &fl4->saddr); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci rt = ip_route_output_key(sock_net(sk), fl4); 45362306a36Sopenharmony_ci if (!IS_ERR(rt)) { 45462306a36Sopenharmony_ci dst = &rt->dst; 45562306a36Sopenharmony_ci t->dst = dst; 45662306a36Sopenharmony_ci memcpy(fl, &_fl, sizeof(_fl)); 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* If there is no association or if a source address is passed, no 46062306a36Sopenharmony_ci * more validation is required. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci if (!asoc || saddr) 46362306a36Sopenharmony_ci goto out; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci bp = &asoc->base.bind_addr; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (dst) { 46862306a36Sopenharmony_ci /* Walk through the bind address list and look for a bind 46962306a36Sopenharmony_ci * address that matches the source address of the returned dst. 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_ci sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port)); 47262306a36Sopenharmony_ci rcu_read_lock(); 47362306a36Sopenharmony_ci list_for_each_entry_rcu(laddr, &bp->address_list, list) { 47462306a36Sopenharmony_ci if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) || 47562306a36Sopenharmony_ci (laddr->state != SCTP_ADDR_SRC && 47662306a36Sopenharmony_ci !asoc->src_out_of_asoc_ok)) 47762306a36Sopenharmony_ci continue; 47862306a36Sopenharmony_ci if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) 47962306a36Sopenharmony_ci goto out_unlock; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci rcu_read_unlock(); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* None of the bound addresses match the source address of the 48462306a36Sopenharmony_ci * dst. So release it. 48562306a36Sopenharmony_ci */ 48662306a36Sopenharmony_ci dst_release(dst); 48762306a36Sopenharmony_ci dst = NULL; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* Walk through the bind address list and try to get a dst that 49162306a36Sopenharmony_ci * matches a bind address as the source address. 49262306a36Sopenharmony_ci */ 49362306a36Sopenharmony_ci rcu_read_lock(); 49462306a36Sopenharmony_ci list_for_each_entry_rcu(laddr, &bp->address_list, list) { 49562306a36Sopenharmony_ci struct net_device *odev; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci if (!laddr->valid) 49862306a36Sopenharmony_ci continue; 49962306a36Sopenharmony_ci if (laddr->state != SCTP_ADDR_SRC || 50062306a36Sopenharmony_ci AF_INET != laddr->a.sa.sa_family) 50162306a36Sopenharmony_ci continue; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci fl4->fl4_sport = laddr->a.v4.sin_port; 50462306a36Sopenharmony_ci flowi4_update_output(fl4, asoc->base.sk->sk_bound_dev_if, 50562306a36Sopenharmony_ci daddr->v4.sin_addr.s_addr, 50662306a36Sopenharmony_ci laddr->a.v4.sin_addr.s_addr); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci rt = ip_route_output_key(sock_net(sk), fl4); 50962306a36Sopenharmony_ci if (IS_ERR(rt)) 51062306a36Sopenharmony_ci continue; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci /* Ensure the src address belongs to the output 51362306a36Sopenharmony_ci * interface. 51462306a36Sopenharmony_ci */ 51562306a36Sopenharmony_ci odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr, 51662306a36Sopenharmony_ci false); 51762306a36Sopenharmony_ci if (!odev || odev->ifindex != fl4->flowi4_oif) { 51862306a36Sopenharmony_ci if (!dst) { 51962306a36Sopenharmony_ci dst = &rt->dst; 52062306a36Sopenharmony_ci t->dst = dst; 52162306a36Sopenharmony_ci memcpy(fl, &_fl, sizeof(_fl)); 52262306a36Sopenharmony_ci } else { 52362306a36Sopenharmony_ci dst_release(&rt->dst); 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci continue; 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci dst_release(dst); 52962306a36Sopenharmony_ci dst = &rt->dst; 53062306a36Sopenharmony_ci t->dst = dst; 53162306a36Sopenharmony_ci memcpy(fl, &_fl, sizeof(_fl)); 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ciout_unlock: 53662306a36Sopenharmony_ci rcu_read_unlock(); 53762306a36Sopenharmony_ciout: 53862306a36Sopenharmony_ci if (dst) { 53962306a36Sopenharmony_ci pr_debug("rt_dst:%pI4, rt_src:%pI4\n", 54062306a36Sopenharmony_ci &fl->u.ip4.daddr, &fl->u.ip4.saddr); 54162306a36Sopenharmony_ci } else { 54262306a36Sopenharmony_ci t->dst = NULL; 54362306a36Sopenharmony_ci pr_debug("no route\n"); 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci/* For v4, the source address is cached in the route entry(dst). So no need 54862306a36Sopenharmony_ci * to cache it separately and hence this is an empty routine. 54962306a36Sopenharmony_ci */ 55062306a36Sopenharmony_cistatic void sctp_v4_get_saddr(struct sctp_sock *sk, 55162306a36Sopenharmony_ci struct sctp_transport *t, 55262306a36Sopenharmony_ci struct flowi *fl) 55362306a36Sopenharmony_ci{ 55462306a36Sopenharmony_ci union sctp_addr *saddr = &t->saddr; 55562306a36Sopenharmony_ci struct rtable *rt = (struct rtable *)t->dst; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (rt) { 55862306a36Sopenharmony_ci saddr->v4.sin_family = AF_INET; 55962306a36Sopenharmony_ci saddr->v4.sin_addr.s_addr = fl->u.ip4.saddr; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci/* What interface did this skb arrive on? */ 56462306a36Sopenharmony_cistatic int sctp_v4_skb_iif(const struct sk_buff *skb) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci return inet_iif(skb); 56762306a36Sopenharmony_ci} 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistatic int sctp_v4_skb_sdif(const struct sk_buff *skb) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci return inet_sdif(skb); 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci/* Was this packet marked by Explicit Congestion Notification? */ 57562306a36Sopenharmony_cistatic int sctp_v4_is_ce(const struct sk_buff *skb) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci return INET_ECN_is_ce(ip_hdr(skb)->tos); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci/* Create and initialize a new sk for the socket returned by accept(). */ 58162306a36Sopenharmony_cistatic struct sock *sctp_v4_create_accept_sk(struct sock *sk, 58262306a36Sopenharmony_ci struct sctp_association *asoc, 58362306a36Sopenharmony_ci bool kern) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL, 58662306a36Sopenharmony_ci sk->sk_prot, kern); 58762306a36Sopenharmony_ci struct inet_sock *newinet; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci if (!newsk) 59062306a36Sopenharmony_ci goto out; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci sock_init_data(NULL, newsk); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci sctp_copy_sock(newsk, sk, asoc); 59562306a36Sopenharmony_ci sock_reset_flag(newsk, SOCK_ZAPPED); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci sctp_v4_copy_ip_options(sk, newsk); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci newinet = inet_sk(newsk); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci if (newsk->sk_prot->init(newsk)) { 60462306a36Sopenharmony_ci sk_common_release(newsk); 60562306a36Sopenharmony_ci newsk = NULL; 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ciout: 60962306a36Sopenharmony_ci return newsk; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_cistatic int sctp_v4_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr) 61362306a36Sopenharmony_ci{ 61462306a36Sopenharmony_ci /* No address mapping for V4 sockets */ 61562306a36Sopenharmony_ci memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); 61662306a36Sopenharmony_ci return sizeof(struct sockaddr_in); 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci/* Dump the v4 addr to the seq file. */ 62062306a36Sopenharmony_cistatic void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci seq_printf(seq, "%pI4 ", &addr->v4.sin_addr); 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic void sctp_v4_ecn_capable(struct sock *sk) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci INET_ECN_xmit(sk); 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic void sctp_addr_wq_timeout_handler(struct timer_list *t) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci struct net *net = from_timer(net, t, sctp.addr_wq_timer); 63362306a36Sopenharmony_ci struct sctp_sockaddr_entry *addrw, *temp; 63462306a36Sopenharmony_ci struct sctp_sock *sp; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci spin_lock_bh(&net->sctp.addr_wq_lock); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { 63962306a36Sopenharmony_ci pr_debug("%s: the first ent in wq:%p is addr:%pISc for cmd:%d at " 64062306a36Sopenharmony_ci "entry:%p\n", __func__, &net->sctp.addr_waitq, &addrw->a.sa, 64162306a36Sopenharmony_ci addrw->state, addrw); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 64462306a36Sopenharmony_ci /* Now we send an ASCONF for each association */ 64562306a36Sopenharmony_ci /* Note. we currently don't handle link local IPv6 addressees */ 64662306a36Sopenharmony_ci if (addrw->a.sa.sa_family == AF_INET6) { 64762306a36Sopenharmony_ci struct in6_addr *in6; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci if (ipv6_addr_type(&addrw->a.v6.sin6_addr) & 65062306a36Sopenharmony_ci IPV6_ADDR_LINKLOCAL) 65162306a36Sopenharmony_ci goto free_next; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; 65462306a36Sopenharmony_ci if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && 65562306a36Sopenharmony_ci addrw->state == SCTP_ADDR_NEW) { 65662306a36Sopenharmony_ci unsigned long timeo_val; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci pr_debug("%s: this is on DAD, trying %d sec " 65962306a36Sopenharmony_ci "later\n", __func__, 66062306a36Sopenharmony_ci SCTP_ADDRESS_TICK_DELAY); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci timeo_val = jiffies; 66362306a36Sopenharmony_ci timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); 66462306a36Sopenharmony_ci mod_timer(&net->sctp.addr_wq_timer, timeo_val); 66562306a36Sopenharmony_ci break; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci#endif 66962306a36Sopenharmony_ci list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) { 67062306a36Sopenharmony_ci struct sock *sk; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci sk = sctp_opt2sk(sp); 67362306a36Sopenharmony_ci /* ignore bound-specific endpoints */ 67462306a36Sopenharmony_ci if (!sctp_is_ep_boundall(sk)) 67562306a36Sopenharmony_ci continue; 67662306a36Sopenharmony_ci bh_lock_sock(sk); 67762306a36Sopenharmony_ci if (sctp_asconf_mgmt(sp, addrw) < 0) 67862306a36Sopenharmony_ci pr_debug("%s: sctp_asconf_mgmt failed\n", __func__); 67962306a36Sopenharmony_ci bh_unlock_sock(sk); 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 68262306a36Sopenharmony_cifree_next: 68362306a36Sopenharmony_ci#endif 68462306a36Sopenharmony_ci list_del(&addrw->list); 68562306a36Sopenharmony_ci kfree(addrw); 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.addr_wq_lock); 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_cistatic void sctp_free_addr_wq(struct net *net) 69162306a36Sopenharmony_ci{ 69262306a36Sopenharmony_ci struct sctp_sockaddr_entry *addrw; 69362306a36Sopenharmony_ci struct sctp_sockaddr_entry *temp; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci spin_lock_bh(&net->sctp.addr_wq_lock); 69662306a36Sopenharmony_ci del_timer(&net->sctp.addr_wq_timer); 69762306a36Sopenharmony_ci list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { 69862306a36Sopenharmony_ci list_del(&addrw->list); 69962306a36Sopenharmony_ci kfree(addrw); 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.addr_wq_lock); 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci/* lookup the entry for the same address in the addr_waitq 70562306a36Sopenharmony_ci * sctp_addr_wq MUST be locked 70662306a36Sopenharmony_ci */ 70762306a36Sopenharmony_cistatic struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net, 70862306a36Sopenharmony_ci struct sctp_sockaddr_entry *addr) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci struct sctp_sockaddr_entry *addrw; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci list_for_each_entry(addrw, &net->sctp.addr_waitq, list) { 71362306a36Sopenharmony_ci if (addrw->a.sa.sa_family != addr->a.sa.sa_family) 71462306a36Sopenharmony_ci continue; 71562306a36Sopenharmony_ci if (addrw->a.sa.sa_family == AF_INET) { 71662306a36Sopenharmony_ci if (addrw->a.v4.sin_addr.s_addr == 71762306a36Sopenharmony_ci addr->a.v4.sin_addr.s_addr) 71862306a36Sopenharmony_ci return addrw; 71962306a36Sopenharmony_ci } else if (addrw->a.sa.sa_family == AF_INET6) { 72062306a36Sopenharmony_ci if (ipv6_addr_equal(&addrw->a.v6.sin6_addr, 72162306a36Sopenharmony_ci &addr->a.v6.sin6_addr)) 72262306a36Sopenharmony_ci return addrw; 72362306a36Sopenharmony_ci } 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci return NULL; 72662306a36Sopenharmony_ci} 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_civoid sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci struct sctp_sockaddr_entry *addrw; 73162306a36Sopenharmony_ci unsigned long timeo_val; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci /* first, we check if an opposite message already exist in the queue. 73462306a36Sopenharmony_ci * If we found such message, it is removed. 73562306a36Sopenharmony_ci * This operation is a bit stupid, but the DHCP client attaches the 73662306a36Sopenharmony_ci * new address after a couple of addition and deletion of that address 73762306a36Sopenharmony_ci */ 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci spin_lock_bh(&net->sctp.addr_wq_lock); 74062306a36Sopenharmony_ci /* Offsets existing events in addr_wq */ 74162306a36Sopenharmony_ci addrw = sctp_addr_wq_lookup(net, addr); 74262306a36Sopenharmony_ci if (addrw) { 74362306a36Sopenharmony_ci if (addrw->state != cmd) { 74462306a36Sopenharmony_ci pr_debug("%s: offsets existing entry for %d, addr:%pISc " 74562306a36Sopenharmony_ci "in wq:%p\n", __func__, addrw->state, &addrw->a.sa, 74662306a36Sopenharmony_ci &net->sctp.addr_waitq); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci list_del(&addrw->list); 74962306a36Sopenharmony_ci kfree(addrw); 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.addr_wq_lock); 75262306a36Sopenharmony_ci return; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci /* OK, we have to add the new address to the wait queue */ 75662306a36Sopenharmony_ci addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); 75762306a36Sopenharmony_ci if (addrw == NULL) { 75862306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.addr_wq_lock); 75962306a36Sopenharmony_ci return; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci addrw->state = cmd; 76262306a36Sopenharmony_ci list_add_tail(&addrw->list, &net->sctp.addr_waitq); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci pr_debug("%s: add new entry for cmd:%d, addr:%pISc in wq:%p\n", 76562306a36Sopenharmony_ci __func__, addrw->state, &addrw->a.sa, &net->sctp.addr_waitq); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (!timer_pending(&net->sctp.addr_wq_timer)) { 76862306a36Sopenharmony_ci timeo_val = jiffies; 76962306a36Sopenharmony_ci timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); 77062306a36Sopenharmony_ci mod_timer(&net->sctp.addr_wq_timer, timeo_val); 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.addr_wq_lock); 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci/* Event handler for inet address addition/deletion events. 77662306a36Sopenharmony_ci * The sctp_local_addr_list needs to be protocted by a spin lock since 77762306a36Sopenharmony_ci * multiple notifiers (say IPv4 and IPv6) may be running at the same 77862306a36Sopenharmony_ci * time and thus corrupt the list. 77962306a36Sopenharmony_ci * The reader side is protected with RCU. 78062306a36Sopenharmony_ci */ 78162306a36Sopenharmony_cistatic int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, 78262306a36Sopenharmony_ci void *ptr) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; 78562306a36Sopenharmony_ci struct sctp_sockaddr_entry *addr = NULL; 78662306a36Sopenharmony_ci struct sctp_sockaddr_entry *temp; 78762306a36Sopenharmony_ci struct net *net = dev_net(ifa->ifa_dev->dev); 78862306a36Sopenharmony_ci int found = 0; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci switch (ev) { 79162306a36Sopenharmony_ci case NETDEV_UP: 79262306a36Sopenharmony_ci addr = kzalloc(sizeof(*addr), GFP_ATOMIC); 79362306a36Sopenharmony_ci if (addr) { 79462306a36Sopenharmony_ci addr->a.v4.sin_family = AF_INET; 79562306a36Sopenharmony_ci addr->a.v4.sin_addr.s_addr = ifa->ifa_local; 79662306a36Sopenharmony_ci addr->valid = 1; 79762306a36Sopenharmony_ci spin_lock_bh(&net->sctp.local_addr_lock); 79862306a36Sopenharmony_ci list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); 79962306a36Sopenharmony_ci sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); 80062306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.local_addr_lock); 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci case NETDEV_DOWN: 80462306a36Sopenharmony_ci spin_lock_bh(&net->sctp.local_addr_lock); 80562306a36Sopenharmony_ci list_for_each_entry_safe(addr, temp, 80662306a36Sopenharmony_ci &net->sctp.local_addr_list, list) { 80762306a36Sopenharmony_ci if (addr->a.sa.sa_family == AF_INET && 80862306a36Sopenharmony_ci addr->a.v4.sin_addr.s_addr == 80962306a36Sopenharmony_ci ifa->ifa_local) { 81062306a36Sopenharmony_ci sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); 81162306a36Sopenharmony_ci found = 1; 81262306a36Sopenharmony_ci addr->valid = 0; 81362306a36Sopenharmony_ci list_del_rcu(&addr->list); 81462306a36Sopenharmony_ci break; 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci spin_unlock_bh(&net->sctp.local_addr_lock); 81862306a36Sopenharmony_ci if (found) 81962306a36Sopenharmony_ci kfree_rcu(addr, rcu); 82062306a36Sopenharmony_ci break; 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci return NOTIFY_DONE; 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci/* 82762306a36Sopenharmony_ci * Initialize the control inode/socket with a control endpoint data 82862306a36Sopenharmony_ci * structure. This endpoint is reserved exclusively for the OOTB processing. 82962306a36Sopenharmony_ci */ 83062306a36Sopenharmony_cistatic int sctp_ctl_sock_init(struct net *net) 83162306a36Sopenharmony_ci{ 83262306a36Sopenharmony_ci int err; 83362306a36Sopenharmony_ci sa_family_t family = PF_INET; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci if (sctp_get_pf_specific(PF_INET6)) 83662306a36Sopenharmony_ci family = PF_INET6; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci err = inet_ctl_sock_create(&net->sctp.ctl_sock, family, 83962306a36Sopenharmony_ci SOCK_SEQPACKET, IPPROTO_SCTP, net); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci /* If IPv6 socket could not be created, try the IPv4 socket */ 84262306a36Sopenharmony_ci if (err < 0 && family == PF_INET6) 84362306a36Sopenharmony_ci err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET, 84462306a36Sopenharmony_ci SOCK_SEQPACKET, IPPROTO_SCTP, 84562306a36Sopenharmony_ci net); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (err < 0) { 84862306a36Sopenharmony_ci pr_err("Failed to create the SCTP control socket\n"); 84962306a36Sopenharmony_ci return err; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci return 0; 85262306a36Sopenharmony_ci} 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_cistatic int sctp_udp_rcv(struct sock *sk, struct sk_buff *skb) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci SCTP_INPUT_CB(skb)->encap_port = udp_hdr(skb)->source; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci skb_set_transport_header(skb, sizeof(struct udphdr)); 85962306a36Sopenharmony_ci sctp_rcv(skb); 86062306a36Sopenharmony_ci return 0; 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ciint sctp_udp_sock_start(struct net *net) 86462306a36Sopenharmony_ci{ 86562306a36Sopenharmony_ci struct udp_tunnel_sock_cfg tuncfg = {NULL}; 86662306a36Sopenharmony_ci struct udp_port_cfg udp_conf = {0}; 86762306a36Sopenharmony_ci struct socket *sock; 86862306a36Sopenharmony_ci int err; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci udp_conf.family = AF_INET; 87162306a36Sopenharmony_ci udp_conf.local_ip.s_addr = htonl(INADDR_ANY); 87262306a36Sopenharmony_ci udp_conf.local_udp_port = htons(net->sctp.udp_port); 87362306a36Sopenharmony_ci err = udp_sock_create(net, &udp_conf, &sock); 87462306a36Sopenharmony_ci if (err) { 87562306a36Sopenharmony_ci pr_err("Failed to create the SCTP UDP tunneling v4 sock\n"); 87662306a36Sopenharmony_ci return err; 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci tuncfg.encap_type = 1; 88062306a36Sopenharmony_ci tuncfg.encap_rcv = sctp_udp_rcv; 88162306a36Sopenharmony_ci tuncfg.encap_err_lookup = sctp_udp_v4_err; 88262306a36Sopenharmony_ci setup_udp_tunnel_sock(net, sock, &tuncfg); 88362306a36Sopenharmony_ci net->sctp.udp4_sock = sock->sk; 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 88662306a36Sopenharmony_ci memset(&udp_conf, 0, sizeof(udp_conf)); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci udp_conf.family = AF_INET6; 88962306a36Sopenharmony_ci udp_conf.local_ip6 = in6addr_any; 89062306a36Sopenharmony_ci udp_conf.local_udp_port = htons(net->sctp.udp_port); 89162306a36Sopenharmony_ci udp_conf.use_udp6_rx_checksums = true; 89262306a36Sopenharmony_ci udp_conf.ipv6_v6only = true; 89362306a36Sopenharmony_ci err = udp_sock_create(net, &udp_conf, &sock); 89462306a36Sopenharmony_ci if (err) { 89562306a36Sopenharmony_ci pr_err("Failed to create the SCTP UDP tunneling v6 sock\n"); 89662306a36Sopenharmony_ci udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket); 89762306a36Sopenharmony_ci net->sctp.udp4_sock = NULL; 89862306a36Sopenharmony_ci return err; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci tuncfg.encap_type = 1; 90262306a36Sopenharmony_ci tuncfg.encap_rcv = sctp_udp_rcv; 90362306a36Sopenharmony_ci tuncfg.encap_err_lookup = sctp_udp_v6_err; 90462306a36Sopenharmony_ci setup_udp_tunnel_sock(net, sock, &tuncfg); 90562306a36Sopenharmony_ci net->sctp.udp6_sock = sock->sk; 90662306a36Sopenharmony_ci#endif 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci return 0; 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_civoid sctp_udp_sock_stop(struct net *net) 91262306a36Sopenharmony_ci{ 91362306a36Sopenharmony_ci if (net->sctp.udp4_sock) { 91462306a36Sopenharmony_ci udp_tunnel_sock_release(net->sctp.udp4_sock->sk_socket); 91562306a36Sopenharmony_ci net->sctp.udp4_sock = NULL; 91662306a36Sopenharmony_ci } 91762306a36Sopenharmony_ci if (net->sctp.udp6_sock) { 91862306a36Sopenharmony_ci udp_tunnel_sock_release(net->sctp.udp6_sock->sk_socket); 91962306a36Sopenharmony_ci net->sctp.udp6_sock = NULL; 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci/* Register address family specific functions. */ 92462306a36Sopenharmony_ciint sctp_register_af(struct sctp_af *af) 92562306a36Sopenharmony_ci{ 92662306a36Sopenharmony_ci switch (af->sa_family) { 92762306a36Sopenharmony_ci case AF_INET: 92862306a36Sopenharmony_ci if (sctp_af_v4_specific) 92962306a36Sopenharmony_ci return 0; 93062306a36Sopenharmony_ci sctp_af_v4_specific = af; 93162306a36Sopenharmony_ci break; 93262306a36Sopenharmony_ci case AF_INET6: 93362306a36Sopenharmony_ci if (sctp_af_v6_specific) 93462306a36Sopenharmony_ci return 0; 93562306a36Sopenharmony_ci sctp_af_v6_specific = af; 93662306a36Sopenharmony_ci break; 93762306a36Sopenharmony_ci default: 93862306a36Sopenharmony_ci return 0; 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci INIT_LIST_HEAD(&af->list); 94262306a36Sopenharmony_ci list_add_tail(&af->list, &sctp_address_families); 94362306a36Sopenharmony_ci return 1; 94462306a36Sopenharmony_ci} 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci/* Get the table of functions for manipulating a particular address 94762306a36Sopenharmony_ci * family. 94862306a36Sopenharmony_ci */ 94962306a36Sopenharmony_cistruct sctp_af *sctp_get_af_specific(sa_family_t family) 95062306a36Sopenharmony_ci{ 95162306a36Sopenharmony_ci switch (family) { 95262306a36Sopenharmony_ci case AF_INET: 95362306a36Sopenharmony_ci return sctp_af_v4_specific; 95462306a36Sopenharmony_ci case AF_INET6: 95562306a36Sopenharmony_ci return sctp_af_v6_specific; 95662306a36Sopenharmony_ci default: 95762306a36Sopenharmony_ci return NULL; 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci/* Common code to initialize a AF_INET msg_name. */ 96262306a36Sopenharmony_cistatic void sctp_inet_msgname(char *msgname, int *addr_len) 96362306a36Sopenharmony_ci{ 96462306a36Sopenharmony_ci struct sockaddr_in *sin; 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci sin = (struct sockaddr_in *)msgname; 96762306a36Sopenharmony_ci *addr_len = sizeof(struct sockaddr_in); 96862306a36Sopenharmony_ci sin->sin_family = AF_INET; 96962306a36Sopenharmony_ci memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci/* Copy the primary address of the peer primary address as the msg_name. */ 97362306a36Sopenharmony_cistatic void sctp_inet_event_msgname(struct sctp_ulpevent *event, char *msgname, 97462306a36Sopenharmony_ci int *addr_len) 97562306a36Sopenharmony_ci{ 97662306a36Sopenharmony_ci struct sockaddr_in *sin, *sinfrom; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci if (msgname) { 97962306a36Sopenharmony_ci struct sctp_association *asoc; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci asoc = event->asoc; 98262306a36Sopenharmony_ci sctp_inet_msgname(msgname, addr_len); 98362306a36Sopenharmony_ci sin = (struct sockaddr_in *)msgname; 98462306a36Sopenharmony_ci sinfrom = &asoc->peer.primary_addr.v4; 98562306a36Sopenharmony_ci sin->sin_port = htons(asoc->peer.port); 98662306a36Sopenharmony_ci sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr; 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci} 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci/* Initialize and copy out a msgname from an inbound skb. */ 99162306a36Sopenharmony_cistatic void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) 99262306a36Sopenharmony_ci{ 99362306a36Sopenharmony_ci if (msgname) { 99462306a36Sopenharmony_ci struct sctphdr *sh = sctp_hdr(skb); 99562306a36Sopenharmony_ci struct sockaddr_in *sin = (struct sockaddr_in *)msgname; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci sctp_inet_msgname(msgname, len); 99862306a36Sopenharmony_ci sin->sin_port = sh->source; 99962306a36Sopenharmony_ci sin->sin_addr.s_addr = ip_hdr(skb)->saddr; 100062306a36Sopenharmony_ci } 100162306a36Sopenharmony_ci} 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci/* Do we support this AF? */ 100462306a36Sopenharmony_cistatic int sctp_inet_af_supported(sa_family_t family, struct sctp_sock *sp) 100562306a36Sopenharmony_ci{ 100662306a36Sopenharmony_ci /* PF_INET only supports AF_INET addresses. */ 100762306a36Sopenharmony_ci return AF_INET == family; 100862306a36Sopenharmony_ci} 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci/* Address matching with wildcards allowed. */ 101162306a36Sopenharmony_cistatic int sctp_inet_cmp_addr(const union sctp_addr *addr1, 101262306a36Sopenharmony_ci const union sctp_addr *addr2, 101362306a36Sopenharmony_ci struct sctp_sock *opt) 101462306a36Sopenharmony_ci{ 101562306a36Sopenharmony_ci /* PF_INET only supports AF_INET addresses. */ 101662306a36Sopenharmony_ci if (addr1->sa.sa_family != addr2->sa.sa_family) 101762306a36Sopenharmony_ci return 0; 101862306a36Sopenharmony_ci if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr || 101962306a36Sopenharmony_ci htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr) 102062306a36Sopenharmony_ci return 1; 102162306a36Sopenharmony_ci if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr) 102262306a36Sopenharmony_ci return 1; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci return 0; 102562306a36Sopenharmony_ci} 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci/* Verify that provided sockaddr looks bindable. Common verification has 102862306a36Sopenharmony_ci * already been taken care of. 102962306a36Sopenharmony_ci */ 103062306a36Sopenharmony_cistatic int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) 103162306a36Sopenharmony_ci{ 103262306a36Sopenharmony_ci return sctp_v4_available(addr, opt); 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci/* Verify that sockaddr looks sendable. Common verification has already 103662306a36Sopenharmony_ci * been taken care of. 103762306a36Sopenharmony_ci */ 103862306a36Sopenharmony_cistatic int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr) 103962306a36Sopenharmony_ci{ 104062306a36Sopenharmony_ci return 1; 104162306a36Sopenharmony_ci} 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci/* Fill in Supported Address Type information for INIT and INIT-ACK 104462306a36Sopenharmony_ci * chunks. Returns number of addresses supported. 104562306a36Sopenharmony_ci */ 104662306a36Sopenharmony_cistatic int sctp_inet_supported_addrs(const struct sctp_sock *opt, 104762306a36Sopenharmony_ci __be16 *types) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci types[0] = SCTP_PARAM_IPV4_ADDRESS; 105062306a36Sopenharmony_ci return 1; 105162306a36Sopenharmony_ci} 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci/* Wrapper routine that calls the ip transmit routine. */ 105462306a36Sopenharmony_cistatic inline int sctp_v4_xmit(struct sk_buff *skb, struct sctp_transport *t) 105562306a36Sopenharmony_ci{ 105662306a36Sopenharmony_ci struct dst_entry *dst = dst_clone(t->dst); 105762306a36Sopenharmony_ci struct flowi4 *fl4 = &t->fl.u.ip4; 105862306a36Sopenharmony_ci struct sock *sk = skb->sk; 105962306a36Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 106062306a36Sopenharmony_ci __u8 dscp = inet->tos; 106162306a36Sopenharmony_ci __be16 df = 0; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb, 106462306a36Sopenharmony_ci skb->len, &fl4->saddr, &fl4->daddr); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (t->dscp & SCTP_DSCP_SET_MASK) 106762306a36Sopenharmony_ci dscp = t->dscp & SCTP_DSCP_VAL_MASK; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci inet->pmtudisc = t->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO 107062306a36Sopenharmony_ci : IP_PMTUDISC_DONT; 107162306a36Sopenharmony_ci SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci if (!t->encap_port || !sctp_sk(sk)->udp_port) { 107462306a36Sopenharmony_ci skb_dst_set(skb, dst); 107562306a36Sopenharmony_ci return __ip_queue_xmit(sk, skb, &t->fl, dscp); 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci if (skb_is_gso(skb)) 107962306a36Sopenharmony_ci skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci if (ip_dont_fragment(sk, dst) && !skb->ignore_df) 108262306a36Sopenharmony_ci df = htons(IP_DF); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci skb->encapsulation = 1; 108562306a36Sopenharmony_ci skb_reset_inner_mac_header(skb); 108662306a36Sopenharmony_ci skb_reset_inner_transport_header(skb); 108762306a36Sopenharmony_ci skb_set_inner_ipproto(skb, IPPROTO_SCTP); 108862306a36Sopenharmony_ci udp_tunnel_xmit_skb((struct rtable *)dst, sk, skb, fl4->saddr, 108962306a36Sopenharmony_ci fl4->daddr, dscp, ip4_dst_hoplimit(dst), df, 109062306a36Sopenharmony_ci sctp_sk(sk)->udp_port, t->encap_port, false, false); 109162306a36Sopenharmony_ci return 0; 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_cistatic struct sctp_af sctp_af_inet; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_cistatic struct sctp_pf sctp_pf_inet = { 109762306a36Sopenharmony_ci .event_msgname = sctp_inet_event_msgname, 109862306a36Sopenharmony_ci .skb_msgname = sctp_inet_skb_msgname, 109962306a36Sopenharmony_ci .af_supported = sctp_inet_af_supported, 110062306a36Sopenharmony_ci .cmp_addr = sctp_inet_cmp_addr, 110162306a36Sopenharmony_ci .bind_verify = sctp_inet_bind_verify, 110262306a36Sopenharmony_ci .send_verify = sctp_inet_send_verify, 110362306a36Sopenharmony_ci .supported_addrs = sctp_inet_supported_addrs, 110462306a36Sopenharmony_ci .create_accept_sk = sctp_v4_create_accept_sk, 110562306a36Sopenharmony_ci .addr_to_user = sctp_v4_addr_to_user, 110662306a36Sopenharmony_ci .to_sk_saddr = sctp_v4_to_sk_saddr, 110762306a36Sopenharmony_ci .to_sk_daddr = sctp_v4_to_sk_daddr, 110862306a36Sopenharmony_ci .copy_ip_options = sctp_v4_copy_ip_options, 110962306a36Sopenharmony_ci .af = &sctp_af_inet 111062306a36Sopenharmony_ci}; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci/* Notifier for inetaddr addition/deletion events. */ 111362306a36Sopenharmony_cistatic struct notifier_block sctp_inetaddr_notifier = { 111462306a36Sopenharmony_ci .notifier_call = sctp_inetaddr_event, 111562306a36Sopenharmony_ci}; 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci/* Socket operations. */ 111862306a36Sopenharmony_cistatic const struct proto_ops inet_seqpacket_ops = { 111962306a36Sopenharmony_ci .family = PF_INET, 112062306a36Sopenharmony_ci .owner = THIS_MODULE, 112162306a36Sopenharmony_ci .release = inet_release, /* Needs to be wrapped... */ 112262306a36Sopenharmony_ci .bind = inet_bind, 112362306a36Sopenharmony_ci .connect = sctp_inet_connect, 112462306a36Sopenharmony_ci .socketpair = sock_no_socketpair, 112562306a36Sopenharmony_ci .accept = inet_accept, 112662306a36Sopenharmony_ci .getname = inet_getname, /* Semantics are different. */ 112762306a36Sopenharmony_ci .poll = sctp_poll, 112862306a36Sopenharmony_ci .ioctl = inet_ioctl, 112962306a36Sopenharmony_ci .gettstamp = sock_gettstamp, 113062306a36Sopenharmony_ci .listen = sctp_inet_listen, 113162306a36Sopenharmony_ci .shutdown = inet_shutdown, /* Looks harmless. */ 113262306a36Sopenharmony_ci .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem */ 113362306a36Sopenharmony_ci .getsockopt = sock_common_getsockopt, 113462306a36Sopenharmony_ci .sendmsg = inet_sendmsg, 113562306a36Sopenharmony_ci .recvmsg = inet_recvmsg, 113662306a36Sopenharmony_ci .mmap = sock_no_mmap, 113762306a36Sopenharmony_ci}; 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci/* Registration with AF_INET family. */ 114062306a36Sopenharmony_cistatic struct inet_protosw sctp_seqpacket_protosw = { 114162306a36Sopenharmony_ci .type = SOCK_SEQPACKET, 114262306a36Sopenharmony_ci .protocol = IPPROTO_SCTP, 114362306a36Sopenharmony_ci .prot = &sctp_prot, 114462306a36Sopenharmony_ci .ops = &inet_seqpacket_ops, 114562306a36Sopenharmony_ci .flags = SCTP_PROTOSW_FLAG 114662306a36Sopenharmony_ci}; 114762306a36Sopenharmony_cistatic struct inet_protosw sctp_stream_protosw = { 114862306a36Sopenharmony_ci .type = SOCK_STREAM, 114962306a36Sopenharmony_ci .protocol = IPPROTO_SCTP, 115062306a36Sopenharmony_ci .prot = &sctp_prot, 115162306a36Sopenharmony_ci .ops = &inet_seqpacket_ops, 115262306a36Sopenharmony_ci .flags = SCTP_PROTOSW_FLAG 115362306a36Sopenharmony_ci}; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_cistatic int sctp4_rcv(struct sk_buff *skb) 115662306a36Sopenharmony_ci{ 115762306a36Sopenharmony_ci SCTP_INPUT_CB(skb)->encap_port = 0; 115862306a36Sopenharmony_ci return sctp_rcv(skb); 115962306a36Sopenharmony_ci} 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci/* Register with IP layer. */ 116262306a36Sopenharmony_cistatic const struct net_protocol sctp_protocol = { 116362306a36Sopenharmony_ci .handler = sctp4_rcv, 116462306a36Sopenharmony_ci .err_handler = sctp_v4_err, 116562306a36Sopenharmony_ci .no_policy = 1, 116662306a36Sopenharmony_ci .icmp_strict_tag_validation = 1, 116762306a36Sopenharmony_ci}; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci/* IPv4 address related functions. */ 117062306a36Sopenharmony_cistatic struct sctp_af sctp_af_inet = { 117162306a36Sopenharmony_ci .sa_family = AF_INET, 117262306a36Sopenharmony_ci .sctp_xmit = sctp_v4_xmit, 117362306a36Sopenharmony_ci .setsockopt = ip_setsockopt, 117462306a36Sopenharmony_ci .getsockopt = ip_getsockopt, 117562306a36Sopenharmony_ci .get_dst = sctp_v4_get_dst, 117662306a36Sopenharmony_ci .get_saddr = sctp_v4_get_saddr, 117762306a36Sopenharmony_ci .copy_addrlist = sctp_v4_copy_addrlist, 117862306a36Sopenharmony_ci .from_skb = sctp_v4_from_skb, 117962306a36Sopenharmony_ci .from_sk = sctp_v4_from_sk, 118062306a36Sopenharmony_ci .from_addr_param = sctp_v4_from_addr_param, 118162306a36Sopenharmony_ci .to_addr_param = sctp_v4_to_addr_param, 118262306a36Sopenharmony_ci .cmp_addr = sctp_v4_cmp_addr, 118362306a36Sopenharmony_ci .addr_valid = sctp_v4_addr_valid, 118462306a36Sopenharmony_ci .inaddr_any = sctp_v4_inaddr_any, 118562306a36Sopenharmony_ci .is_any = sctp_v4_is_any, 118662306a36Sopenharmony_ci .available = sctp_v4_available, 118762306a36Sopenharmony_ci .scope = sctp_v4_scope, 118862306a36Sopenharmony_ci .skb_iif = sctp_v4_skb_iif, 118962306a36Sopenharmony_ci .skb_sdif = sctp_v4_skb_sdif, 119062306a36Sopenharmony_ci .is_ce = sctp_v4_is_ce, 119162306a36Sopenharmony_ci .seq_dump_addr = sctp_v4_seq_dump_addr, 119262306a36Sopenharmony_ci .ecn_capable = sctp_v4_ecn_capable, 119362306a36Sopenharmony_ci .net_header_len = sizeof(struct iphdr), 119462306a36Sopenharmony_ci .sockaddr_len = sizeof(struct sockaddr_in), 119562306a36Sopenharmony_ci .ip_options_len = sctp_v4_ip_options_len, 119662306a36Sopenharmony_ci}; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cistruct sctp_pf *sctp_get_pf_specific(sa_family_t family) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci switch (family) { 120162306a36Sopenharmony_ci case PF_INET: 120262306a36Sopenharmony_ci return sctp_pf_inet_specific; 120362306a36Sopenharmony_ci case PF_INET6: 120462306a36Sopenharmony_ci return sctp_pf_inet6_specific; 120562306a36Sopenharmony_ci default: 120662306a36Sopenharmony_ci return NULL; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci/* Register the PF specific function table. */ 121162306a36Sopenharmony_ciint sctp_register_pf(struct sctp_pf *pf, sa_family_t family) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci switch (family) { 121462306a36Sopenharmony_ci case PF_INET: 121562306a36Sopenharmony_ci if (sctp_pf_inet_specific) 121662306a36Sopenharmony_ci return 0; 121762306a36Sopenharmony_ci sctp_pf_inet_specific = pf; 121862306a36Sopenharmony_ci break; 121962306a36Sopenharmony_ci case PF_INET6: 122062306a36Sopenharmony_ci if (sctp_pf_inet6_specific) 122162306a36Sopenharmony_ci return 0; 122262306a36Sopenharmony_ci sctp_pf_inet6_specific = pf; 122362306a36Sopenharmony_ci break; 122462306a36Sopenharmony_ci default: 122562306a36Sopenharmony_ci return 0; 122662306a36Sopenharmony_ci } 122762306a36Sopenharmony_ci return 1; 122862306a36Sopenharmony_ci} 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_cistatic inline int init_sctp_mibs(struct net *net) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci net->sctp.sctp_statistics = alloc_percpu(struct sctp_mib); 123362306a36Sopenharmony_ci if (!net->sctp.sctp_statistics) 123462306a36Sopenharmony_ci return -ENOMEM; 123562306a36Sopenharmony_ci return 0; 123662306a36Sopenharmony_ci} 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_cistatic inline void cleanup_sctp_mibs(struct net *net) 123962306a36Sopenharmony_ci{ 124062306a36Sopenharmony_ci free_percpu(net->sctp.sctp_statistics); 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_cistatic void sctp_v4_pf_init(void) 124462306a36Sopenharmony_ci{ 124562306a36Sopenharmony_ci /* Initialize the SCTP specific PF functions. */ 124662306a36Sopenharmony_ci sctp_register_pf(&sctp_pf_inet, PF_INET); 124762306a36Sopenharmony_ci sctp_register_af(&sctp_af_inet); 124862306a36Sopenharmony_ci} 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_cistatic void sctp_v4_pf_exit(void) 125162306a36Sopenharmony_ci{ 125262306a36Sopenharmony_ci list_del(&sctp_af_inet.list); 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_cistatic int sctp_v4_protosw_init(void) 125662306a36Sopenharmony_ci{ 125762306a36Sopenharmony_ci int rc; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci rc = proto_register(&sctp_prot, 1); 126062306a36Sopenharmony_ci if (rc) 126162306a36Sopenharmony_ci return rc; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* Register SCTP(UDP and TCP style) with socket layer. */ 126462306a36Sopenharmony_ci inet_register_protosw(&sctp_seqpacket_protosw); 126562306a36Sopenharmony_ci inet_register_protosw(&sctp_stream_protosw); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci return 0; 126862306a36Sopenharmony_ci} 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_cistatic void sctp_v4_protosw_exit(void) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci inet_unregister_protosw(&sctp_stream_protosw); 127362306a36Sopenharmony_ci inet_unregister_protosw(&sctp_seqpacket_protosw); 127462306a36Sopenharmony_ci proto_unregister(&sctp_prot); 127562306a36Sopenharmony_ci} 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_cistatic int sctp_v4_add_protocol(void) 127862306a36Sopenharmony_ci{ 127962306a36Sopenharmony_ci /* Register notifier for inet address additions/deletions. */ 128062306a36Sopenharmony_ci register_inetaddr_notifier(&sctp_inetaddr_notifier); 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci /* Register SCTP with inet layer. */ 128362306a36Sopenharmony_ci if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) 128462306a36Sopenharmony_ci return -EAGAIN; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci return 0; 128762306a36Sopenharmony_ci} 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_cistatic void sctp_v4_del_protocol(void) 129062306a36Sopenharmony_ci{ 129162306a36Sopenharmony_ci inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); 129262306a36Sopenharmony_ci unregister_inetaddr_notifier(&sctp_inetaddr_notifier); 129362306a36Sopenharmony_ci} 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_cistatic int __net_init sctp_defaults_init(struct net *net) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci int status; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci /* 130062306a36Sopenharmony_ci * 14. Suggested SCTP Protocol Parameter Values 130162306a36Sopenharmony_ci */ 130262306a36Sopenharmony_ci /* The following protocol parameters are RECOMMENDED: */ 130362306a36Sopenharmony_ci /* RTO.Initial - 3 seconds */ 130462306a36Sopenharmony_ci net->sctp.rto_initial = SCTP_RTO_INITIAL; 130562306a36Sopenharmony_ci /* RTO.Min - 1 second */ 130662306a36Sopenharmony_ci net->sctp.rto_min = SCTP_RTO_MIN; 130762306a36Sopenharmony_ci /* RTO.Max - 60 seconds */ 130862306a36Sopenharmony_ci net->sctp.rto_max = SCTP_RTO_MAX; 130962306a36Sopenharmony_ci /* RTO.Alpha - 1/8 */ 131062306a36Sopenharmony_ci net->sctp.rto_alpha = SCTP_RTO_ALPHA; 131162306a36Sopenharmony_ci /* RTO.Beta - 1/4 */ 131262306a36Sopenharmony_ci net->sctp.rto_beta = SCTP_RTO_BETA; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci /* Valid.Cookie.Life - 60 seconds */ 131562306a36Sopenharmony_ci net->sctp.valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci /* Whether Cookie Preservative is enabled(1) or not(0) */ 131862306a36Sopenharmony_ci net->sctp.cookie_preserve_enable = 1; 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci /* Default sctp sockets to use md5 as their hmac alg */ 132162306a36Sopenharmony_ci#if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5) 132262306a36Sopenharmony_ci net->sctp.sctp_hmac_alg = "md5"; 132362306a36Sopenharmony_ci#elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1) 132462306a36Sopenharmony_ci net->sctp.sctp_hmac_alg = "sha1"; 132562306a36Sopenharmony_ci#else 132662306a36Sopenharmony_ci net->sctp.sctp_hmac_alg = NULL; 132762306a36Sopenharmony_ci#endif 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci /* Max.Burst - 4 */ 133062306a36Sopenharmony_ci net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci /* Disable of Primary Path Switchover by default */ 133362306a36Sopenharmony_ci net->sctp.ps_retrans = SCTP_PS_RETRANS_MAX; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci /* Enable pf state by default */ 133662306a36Sopenharmony_ci net->sctp.pf_enable = 1; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci /* Ignore pf exposure feature by default */ 133962306a36Sopenharmony_ci net->sctp.pf_expose = SCTP_PF_EXPOSE_UNSET; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci /* Association.Max.Retrans - 10 attempts 134262306a36Sopenharmony_ci * Path.Max.Retrans - 5 attempts (per destination address) 134362306a36Sopenharmony_ci * Max.Init.Retransmits - 8 attempts 134462306a36Sopenharmony_ci */ 134562306a36Sopenharmony_ci net->sctp.max_retrans_association = 10; 134662306a36Sopenharmony_ci net->sctp.max_retrans_path = 5; 134762306a36Sopenharmony_ci net->sctp.max_retrans_init = 8; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci /* Sendbuffer growth - do per-socket accounting */ 135062306a36Sopenharmony_ci net->sctp.sndbuf_policy = 0; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci /* Rcvbuffer growth - do per-socket accounting */ 135362306a36Sopenharmony_ci net->sctp.rcvbuf_policy = 0; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci /* HB.interval - 30 seconds */ 135662306a36Sopenharmony_ci net->sctp.hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci /* delayed SACK timeout */ 135962306a36Sopenharmony_ci net->sctp.sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci /* Disable ADDIP by default. */ 136262306a36Sopenharmony_ci net->sctp.addip_enable = 0; 136362306a36Sopenharmony_ci net->sctp.addip_noauth = 0; 136462306a36Sopenharmony_ci net->sctp.default_auto_asconf = 0; 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* Enable PR-SCTP by default. */ 136762306a36Sopenharmony_ci net->sctp.prsctp_enable = 1; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci /* Disable RECONF by default. */ 137062306a36Sopenharmony_ci net->sctp.reconf_enable = 0; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci /* Disable AUTH by default. */ 137362306a36Sopenharmony_ci net->sctp.auth_enable = 0; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci /* Enable ECN by default. */ 137662306a36Sopenharmony_ci net->sctp.ecn_enable = 1; 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci /* Set UDP tunneling listening port to 0 by default */ 137962306a36Sopenharmony_ci net->sctp.udp_port = 0; 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci /* Set remote encap port to 0 by default */ 138262306a36Sopenharmony_ci net->sctp.encap_port = 0; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci /* Set SCOPE policy to enabled */ 138562306a36Sopenharmony_ci net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci /* Set the default rwnd update threshold */ 138862306a36Sopenharmony_ci net->sctp.rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci /* Initialize maximum autoclose timeout. */ 139162306a36Sopenharmony_ci net->sctp.max_autoclose = INT_MAX / HZ; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci#ifdef CONFIG_NET_L3_MASTER_DEV 139462306a36Sopenharmony_ci net->sctp.l3mdev_accept = 1; 139562306a36Sopenharmony_ci#endif 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci status = sctp_sysctl_net_register(net); 139862306a36Sopenharmony_ci if (status) 139962306a36Sopenharmony_ci goto err_sysctl_register; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci /* Allocate and initialise sctp mibs. */ 140262306a36Sopenharmony_ci status = init_sctp_mibs(net); 140362306a36Sopenharmony_ci if (status) 140462306a36Sopenharmony_ci goto err_init_mibs; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 140762306a36Sopenharmony_ci /* Initialize proc fs directory. */ 140862306a36Sopenharmony_ci status = sctp_proc_init(net); 140962306a36Sopenharmony_ci if (status) 141062306a36Sopenharmony_ci goto err_init_proc; 141162306a36Sopenharmony_ci#endif 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci sctp_dbg_objcnt_init(net); 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci /* Initialize the local address list. */ 141662306a36Sopenharmony_ci INIT_LIST_HEAD(&net->sctp.local_addr_list); 141762306a36Sopenharmony_ci spin_lock_init(&net->sctp.local_addr_lock); 141862306a36Sopenharmony_ci sctp_get_local_addr_list(net); 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci /* Initialize the address event list */ 142162306a36Sopenharmony_ci INIT_LIST_HEAD(&net->sctp.addr_waitq); 142262306a36Sopenharmony_ci INIT_LIST_HEAD(&net->sctp.auto_asconf_splist); 142362306a36Sopenharmony_ci spin_lock_init(&net->sctp.addr_wq_lock); 142462306a36Sopenharmony_ci net->sctp.addr_wq_timer.expires = 0; 142562306a36Sopenharmony_ci timer_setup(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler, 0); 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci return 0; 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 143062306a36Sopenharmony_cierr_init_proc: 143162306a36Sopenharmony_ci cleanup_sctp_mibs(net); 143262306a36Sopenharmony_ci#endif 143362306a36Sopenharmony_cierr_init_mibs: 143462306a36Sopenharmony_ci sctp_sysctl_net_unregister(net); 143562306a36Sopenharmony_cierr_sysctl_register: 143662306a36Sopenharmony_ci return status; 143762306a36Sopenharmony_ci} 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_cistatic void __net_exit sctp_defaults_exit(struct net *net) 144062306a36Sopenharmony_ci{ 144162306a36Sopenharmony_ci /* Free the local address list */ 144262306a36Sopenharmony_ci sctp_free_addr_wq(net); 144362306a36Sopenharmony_ci sctp_free_local_addr_list(net); 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 144662306a36Sopenharmony_ci remove_proc_subtree("sctp", net->proc_net); 144762306a36Sopenharmony_ci net->sctp.proc_net_sctp = NULL; 144862306a36Sopenharmony_ci#endif 144962306a36Sopenharmony_ci cleanup_sctp_mibs(net); 145062306a36Sopenharmony_ci sctp_sysctl_net_unregister(net); 145162306a36Sopenharmony_ci} 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_cistatic struct pernet_operations sctp_defaults_ops = { 145462306a36Sopenharmony_ci .init = sctp_defaults_init, 145562306a36Sopenharmony_ci .exit = sctp_defaults_exit, 145662306a36Sopenharmony_ci}; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_cistatic int __net_init sctp_ctrlsock_init(struct net *net) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci int status; 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci /* Initialize the control inode/socket for handling OOTB packets. */ 146362306a36Sopenharmony_ci status = sctp_ctl_sock_init(net); 146462306a36Sopenharmony_ci if (status) 146562306a36Sopenharmony_ci pr_err("Failed to initialize the SCTP control sock\n"); 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci return status; 146862306a36Sopenharmony_ci} 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_cistatic void __net_exit sctp_ctrlsock_exit(struct net *net) 147162306a36Sopenharmony_ci{ 147262306a36Sopenharmony_ci /* Free the control endpoint. */ 147362306a36Sopenharmony_ci inet_ctl_sock_destroy(net->sctp.ctl_sock); 147462306a36Sopenharmony_ci} 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_cistatic struct pernet_operations sctp_ctrlsock_ops = { 147762306a36Sopenharmony_ci .init = sctp_ctrlsock_init, 147862306a36Sopenharmony_ci .exit = sctp_ctrlsock_exit, 147962306a36Sopenharmony_ci}; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci/* Initialize the universe into something sensible. */ 148262306a36Sopenharmony_cistatic __init int sctp_init(void) 148362306a36Sopenharmony_ci{ 148462306a36Sopenharmony_ci unsigned long nr_pages = totalram_pages(); 148562306a36Sopenharmony_ci unsigned long limit; 148662306a36Sopenharmony_ci unsigned long goal; 148762306a36Sopenharmony_ci int max_entry_order; 148862306a36Sopenharmony_ci int num_entries; 148962306a36Sopenharmony_ci int max_share; 149062306a36Sopenharmony_ci int status; 149162306a36Sopenharmony_ci int order; 149262306a36Sopenharmony_ci int i; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci sock_skb_cb_check_size(sizeof(struct sctp_ulpevent)); 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci /* Allocate bind_bucket and chunk caches. */ 149762306a36Sopenharmony_ci status = -ENOBUFS; 149862306a36Sopenharmony_ci sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", 149962306a36Sopenharmony_ci sizeof(struct sctp_bind_bucket), 150062306a36Sopenharmony_ci 0, SLAB_HWCACHE_ALIGN, 150162306a36Sopenharmony_ci NULL); 150262306a36Sopenharmony_ci if (!sctp_bucket_cachep) 150362306a36Sopenharmony_ci goto out; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci sctp_chunk_cachep = kmem_cache_create("sctp_chunk", 150662306a36Sopenharmony_ci sizeof(struct sctp_chunk), 150762306a36Sopenharmony_ci 0, SLAB_HWCACHE_ALIGN, 150862306a36Sopenharmony_ci NULL); 150962306a36Sopenharmony_ci if (!sctp_chunk_cachep) 151062306a36Sopenharmony_ci goto err_chunk_cachep; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci status = percpu_counter_init(&sctp_sockets_allocated, 0, GFP_KERNEL); 151362306a36Sopenharmony_ci if (status) 151462306a36Sopenharmony_ci goto err_percpu_counter_init; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* Implementation specific variables. */ 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci /* Initialize default stream count setup information. */ 151962306a36Sopenharmony_ci sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; 152062306a36Sopenharmony_ci sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci /* Initialize handle used for association ids. */ 152362306a36Sopenharmony_ci idr_init(&sctp_assocs_id); 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci limit = nr_free_buffer_pages() / 8; 152662306a36Sopenharmony_ci limit = max(limit, 128UL); 152762306a36Sopenharmony_ci sysctl_sctp_mem[0] = limit / 4 * 3; 152862306a36Sopenharmony_ci sysctl_sctp_mem[1] = limit; 152962306a36Sopenharmony_ci sysctl_sctp_mem[2] = sysctl_sctp_mem[0] * 2; 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci /* Set per-socket limits to no more than 1/128 the pressure threshold*/ 153262306a36Sopenharmony_ci limit = (sysctl_sctp_mem[1]) << (PAGE_SHIFT - 7); 153362306a36Sopenharmony_ci max_share = min(4UL*1024*1024, limit); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci sysctl_sctp_rmem[0] = PAGE_SIZE; /* give each asoc 1 page min */ 153662306a36Sopenharmony_ci sysctl_sctp_rmem[1] = 1500 * SKB_TRUESIZE(1); 153762306a36Sopenharmony_ci sysctl_sctp_rmem[2] = max(sysctl_sctp_rmem[1], max_share); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci sysctl_sctp_wmem[0] = PAGE_SIZE; 154062306a36Sopenharmony_ci sysctl_sctp_wmem[1] = 16*1024; 154162306a36Sopenharmony_ci sysctl_sctp_wmem[2] = max(64*1024, max_share); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci /* Size and allocate the association hash table. 154462306a36Sopenharmony_ci * The methodology is similar to that of the tcp hash tables. 154562306a36Sopenharmony_ci * Though not identical. Start by getting a goal size 154662306a36Sopenharmony_ci */ 154762306a36Sopenharmony_ci if (nr_pages >= (128 * 1024)) 154862306a36Sopenharmony_ci goal = nr_pages >> (22 - PAGE_SHIFT); 154962306a36Sopenharmony_ci else 155062306a36Sopenharmony_ci goal = nr_pages >> (24 - PAGE_SHIFT); 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci /* Then compute the page order for said goal */ 155362306a36Sopenharmony_ci order = get_order(goal); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci /* Now compute the required page order for the maximum sized table we 155662306a36Sopenharmony_ci * want to create 155762306a36Sopenharmony_ci */ 155862306a36Sopenharmony_ci max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES * 155962306a36Sopenharmony_ci sizeof(struct sctp_bind_hashbucket)); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci /* Limit the page order by that maximum hash table size */ 156262306a36Sopenharmony_ci order = min(order, max_entry_order); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci /* Allocate and initialize the endpoint hash table. */ 156562306a36Sopenharmony_ci sctp_ep_hashsize = 64; 156662306a36Sopenharmony_ci sctp_ep_hashtable = 156762306a36Sopenharmony_ci kmalloc_array(64, sizeof(struct sctp_hashbucket), GFP_KERNEL); 156862306a36Sopenharmony_ci if (!sctp_ep_hashtable) { 156962306a36Sopenharmony_ci pr_err("Failed endpoint_hash alloc\n"); 157062306a36Sopenharmony_ci status = -ENOMEM; 157162306a36Sopenharmony_ci goto err_ehash_alloc; 157262306a36Sopenharmony_ci } 157362306a36Sopenharmony_ci for (i = 0; i < sctp_ep_hashsize; i++) { 157462306a36Sopenharmony_ci rwlock_init(&sctp_ep_hashtable[i].lock); 157562306a36Sopenharmony_ci INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); 157662306a36Sopenharmony_ci } 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci /* Allocate and initialize the SCTP port hash table. 157962306a36Sopenharmony_ci * Note that order is initalized to start at the max sized 158062306a36Sopenharmony_ci * table we want to support. If we can't get that many pages 158162306a36Sopenharmony_ci * reduce the order and try again 158262306a36Sopenharmony_ci */ 158362306a36Sopenharmony_ci do { 158462306a36Sopenharmony_ci sctp_port_hashtable = (struct sctp_bind_hashbucket *) 158562306a36Sopenharmony_ci __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); 158662306a36Sopenharmony_ci } while (!sctp_port_hashtable && --order > 0); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci if (!sctp_port_hashtable) { 158962306a36Sopenharmony_ci pr_err("Failed bind hash alloc\n"); 159062306a36Sopenharmony_ci status = -ENOMEM; 159162306a36Sopenharmony_ci goto err_bhash_alloc; 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci /* Now compute the number of entries that will fit in the 159562306a36Sopenharmony_ci * port hash space we allocated 159662306a36Sopenharmony_ci */ 159762306a36Sopenharmony_ci num_entries = (1UL << order) * PAGE_SIZE / 159862306a36Sopenharmony_ci sizeof(struct sctp_bind_hashbucket); 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci /* And finish by rounding it down to the nearest power of two. 160162306a36Sopenharmony_ci * This wastes some memory of course, but it's needed because 160262306a36Sopenharmony_ci * the hash function operates based on the assumption that 160362306a36Sopenharmony_ci * the number of entries is a power of two. 160462306a36Sopenharmony_ci */ 160562306a36Sopenharmony_ci sctp_port_hashsize = rounddown_pow_of_two(num_entries); 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci for (i = 0; i < sctp_port_hashsize; i++) { 160862306a36Sopenharmony_ci spin_lock_init(&sctp_port_hashtable[i].lock); 160962306a36Sopenharmony_ci INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); 161062306a36Sopenharmony_ci } 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci status = sctp_transport_hashtable_init(); 161362306a36Sopenharmony_ci if (status) 161462306a36Sopenharmony_ci goto err_thash_alloc; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci pr_info("Hash tables configured (bind %d/%d)\n", sctp_port_hashsize, 161762306a36Sopenharmony_ci num_entries); 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci sctp_sysctl_register(); 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci INIT_LIST_HEAD(&sctp_address_families); 162262306a36Sopenharmony_ci sctp_v4_pf_init(); 162362306a36Sopenharmony_ci sctp_v6_pf_init(); 162462306a36Sopenharmony_ci sctp_sched_ops_init(); 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci status = register_pernet_subsys(&sctp_defaults_ops); 162762306a36Sopenharmony_ci if (status) 162862306a36Sopenharmony_ci goto err_register_defaults; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci status = sctp_v4_protosw_init(); 163162306a36Sopenharmony_ci if (status) 163262306a36Sopenharmony_ci goto err_protosw_init; 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci status = sctp_v6_protosw_init(); 163562306a36Sopenharmony_ci if (status) 163662306a36Sopenharmony_ci goto err_v6_protosw_init; 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci status = register_pernet_subsys(&sctp_ctrlsock_ops); 163962306a36Sopenharmony_ci if (status) 164062306a36Sopenharmony_ci goto err_register_ctrlsock; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci status = sctp_v4_add_protocol(); 164362306a36Sopenharmony_ci if (status) 164462306a36Sopenharmony_ci goto err_add_protocol; 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci /* Register SCTP with inet6 layer. */ 164762306a36Sopenharmony_ci status = sctp_v6_add_protocol(); 164862306a36Sopenharmony_ci if (status) 164962306a36Sopenharmony_ci goto err_v6_add_protocol; 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci if (sctp_offload_init() < 0) 165262306a36Sopenharmony_ci pr_crit("%s: Cannot add SCTP protocol offload\n", __func__); 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ciout: 165562306a36Sopenharmony_ci return status; 165662306a36Sopenharmony_cierr_v6_add_protocol: 165762306a36Sopenharmony_ci sctp_v4_del_protocol(); 165862306a36Sopenharmony_cierr_add_protocol: 165962306a36Sopenharmony_ci unregister_pernet_subsys(&sctp_ctrlsock_ops); 166062306a36Sopenharmony_cierr_register_ctrlsock: 166162306a36Sopenharmony_ci sctp_v6_protosw_exit(); 166262306a36Sopenharmony_cierr_v6_protosw_init: 166362306a36Sopenharmony_ci sctp_v4_protosw_exit(); 166462306a36Sopenharmony_cierr_protosw_init: 166562306a36Sopenharmony_ci unregister_pernet_subsys(&sctp_defaults_ops); 166662306a36Sopenharmony_cierr_register_defaults: 166762306a36Sopenharmony_ci sctp_v4_pf_exit(); 166862306a36Sopenharmony_ci sctp_v6_pf_exit(); 166962306a36Sopenharmony_ci sctp_sysctl_unregister(); 167062306a36Sopenharmony_ci free_pages((unsigned long)sctp_port_hashtable, 167162306a36Sopenharmony_ci get_order(sctp_port_hashsize * 167262306a36Sopenharmony_ci sizeof(struct sctp_bind_hashbucket))); 167362306a36Sopenharmony_cierr_bhash_alloc: 167462306a36Sopenharmony_ci sctp_transport_hashtable_destroy(); 167562306a36Sopenharmony_cierr_thash_alloc: 167662306a36Sopenharmony_ci kfree(sctp_ep_hashtable); 167762306a36Sopenharmony_cierr_ehash_alloc: 167862306a36Sopenharmony_ci percpu_counter_destroy(&sctp_sockets_allocated); 167962306a36Sopenharmony_cierr_percpu_counter_init: 168062306a36Sopenharmony_ci kmem_cache_destroy(sctp_chunk_cachep); 168162306a36Sopenharmony_cierr_chunk_cachep: 168262306a36Sopenharmony_ci kmem_cache_destroy(sctp_bucket_cachep); 168362306a36Sopenharmony_ci goto out; 168462306a36Sopenharmony_ci} 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci/* Exit handler for the SCTP protocol. */ 168762306a36Sopenharmony_cistatic __exit void sctp_exit(void) 168862306a36Sopenharmony_ci{ 168962306a36Sopenharmony_ci /* BUG. This should probably do something useful like clean 169062306a36Sopenharmony_ci * up all the remaining associations and all that memory. 169162306a36Sopenharmony_ci */ 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci /* Unregister with inet6/inet layers. */ 169462306a36Sopenharmony_ci sctp_v6_del_protocol(); 169562306a36Sopenharmony_ci sctp_v4_del_protocol(); 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci unregister_pernet_subsys(&sctp_ctrlsock_ops); 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci /* Free protosw registrations */ 170062306a36Sopenharmony_ci sctp_v6_protosw_exit(); 170162306a36Sopenharmony_ci sctp_v4_protosw_exit(); 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci unregister_pernet_subsys(&sctp_defaults_ops); 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci /* Unregister with socket layer. */ 170662306a36Sopenharmony_ci sctp_v6_pf_exit(); 170762306a36Sopenharmony_ci sctp_v4_pf_exit(); 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci sctp_sysctl_unregister(); 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci free_pages((unsigned long)sctp_port_hashtable, 171262306a36Sopenharmony_ci get_order(sctp_port_hashsize * 171362306a36Sopenharmony_ci sizeof(struct sctp_bind_hashbucket))); 171462306a36Sopenharmony_ci kfree(sctp_ep_hashtable); 171562306a36Sopenharmony_ci sctp_transport_hashtable_destroy(); 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci percpu_counter_destroy(&sctp_sockets_allocated); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci rcu_barrier(); /* Wait for completion of call_rcu()'s */ 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci kmem_cache_destroy(sctp_chunk_cachep); 172262306a36Sopenharmony_ci kmem_cache_destroy(sctp_bucket_cachep); 172362306a36Sopenharmony_ci} 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_cimodule_init(sctp_init); 172662306a36Sopenharmony_cimodule_exit(sctp_exit); 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci/* 172962306a36Sopenharmony_ci * __stringify doesn't likes enums, so use IPPROTO_SCTP value (132) directly. 173062306a36Sopenharmony_ci */ 173162306a36Sopenharmony_ciMODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132"); 173262306a36Sopenharmony_ciMODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); 173362306a36Sopenharmony_ciMODULE_AUTHOR("Linux Kernel SCTP developers <linux-sctp@vger.kernel.org>"); 173462306a36Sopenharmony_ciMODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); 173562306a36Sopenharmony_cimodule_param_named(no_checksums, sctp_checksum_disable, bool, 0644); 173662306a36Sopenharmony_ciMODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification"); 173762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1738