18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* SCTP kernel implementation 38c2ecf20Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 48c2ecf20Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 58c2ecf20Sopenharmony_ci * Copyright (c) 2001-2003 International Business Machines, Corp. 68c2ecf20Sopenharmony_ci * Copyright (c) 2001 Intel Corp. 78c2ecf20Sopenharmony_ci * Copyright (c) 2001 Nokia, Inc. 88c2ecf20Sopenharmony_ci * Copyright (c) 2001 La Monte H.P. Yarroll 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This file is part of the SCTP kernel implementation 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * These functions handle all input from the IP layer into SCTP. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Please send any bug reports or fixes you make to the 158c2ecf20Sopenharmony_ci * email address(es): 168c2ecf20Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * Written or modified by: 198c2ecf20Sopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 208c2ecf20Sopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 218c2ecf20Sopenharmony_ci * Xingang Guo <xingang.guo@intel.com> 228c2ecf20Sopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 238c2ecf20Sopenharmony_ci * Hui Huang <hui.huang@nokia.com> 248c2ecf20Sopenharmony_ci * Daisy Chang <daisyc@us.ibm.com> 258c2ecf20Sopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 268c2ecf20Sopenharmony_ci * Ardelle Fan <ardelle.fan@intel.com> 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/types.h> 308c2ecf20Sopenharmony_ci#include <linux/list.h> /* For struct list_head */ 318c2ecf20Sopenharmony_ci#include <linux/socket.h> 328c2ecf20Sopenharmony_ci#include <linux/ip.h> 338c2ecf20Sopenharmony_ci#include <linux/time.h> /* For struct timeval */ 348c2ecf20Sopenharmony_ci#include <linux/slab.h> 358c2ecf20Sopenharmony_ci#include <net/ip.h> 368c2ecf20Sopenharmony_ci#include <net/icmp.h> 378c2ecf20Sopenharmony_ci#include <net/snmp.h> 388c2ecf20Sopenharmony_ci#include <net/sock.h> 398c2ecf20Sopenharmony_ci#include <net/xfrm.h> 408c2ecf20Sopenharmony_ci#include <net/sctp/sctp.h> 418c2ecf20Sopenharmony_ci#include <net/sctp/sm.h> 428c2ecf20Sopenharmony_ci#include <net/sctp/checksum.h> 438c2ecf20Sopenharmony_ci#include <net/net_namespace.h> 448c2ecf20Sopenharmony_ci#include <linux/rhashtable.h> 458c2ecf20Sopenharmony_ci#include <net/sock_reuseport.h> 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* Forward declarations for internal helpers. */ 488c2ecf20Sopenharmony_cistatic int sctp_rcv_ootb(struct sk_buff *); 498c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_rcv_lookup(struct net *net, 508c2ecf20Sopenharmony_ci struct sk_buff *skb, 518c2ecf20Sopenharmony_ci const union sctp_addr *paddr, 528c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 538c2ecf20Sopenharmony_ci struct sctp_transport **transportp); 548c2ecf20Sopenharmony_cistatic struct sctp_endpoint *__sctp_rcv_lookup_endpoint( 558c2ecf20Sopenharmony_ci struct net *net, struct sk_buff *skb, 568c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 578c2ecf20Sopenharmony_ci const union sctp_addr *daddr); 588c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_lookup_association( 598c2ecf20Sopenharmony_ci struct net *net, 608c2ecf20Sopenharmony_ci const union sctp_addr *local, 618c2ecf20Sopenharmony_ci const union sctp_addr *peer, 628c2ecf20Sopenharmony_ci struct sctp_transport **pt); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic int sctp_add_backlog(struct sock *sk, struct sk_buff *skb); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* Calculate the SCTP checksum of an SCTP packet. */ 688c2ecf20Sopenharmony_cistatic inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct sctphdr *sh = sctp_hdr(skb); 718c2ecf20Sopenharmony_ci __le32 cmp = sh->checksum; 728c2ecf20Sopenharmony_ci __le32 val = sctp_compute_cksum(skb, 0); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (val != cmp) { 758c2ecf20Sopenharmony_ci /* CRC failure, dump it. */ 768c2ecf20Sopenharmony_ci __SCTP_INC_STATS(net, SCTP_MIB_CHECKSUMERRORS); 778c2ecf20Sopenharmony_ci return -1; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* 838c2ecf20Sopenharmony_ci * This is the routine which IP calls when receiving an SCTP packet. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ciint sctp_rcv(struct sk_buff *skb) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct sock *sk; 888c2ecf20Sopenharmony_ci struct sctp_association *asoc; 898c2ecf20Sopenharmony_ci struct sctp_endpoint *ep = NULL; 908c2ecf20Sopenharmony_ci struct sctp_ep_common *rcvr; 918c2ecf20Sopenharmony_ci struct sctp_transport *transport = NULL; 928c2ecf20Sopenharmony_ci struct sctp_chunk *chunk; 938c2ecf20Sopenharmony_ci union sctp_addr src; 948c2ecf20Sopenharmony_ci union sctp_addr dest; 958c2ecf20Sopenharmony_ci int bound_dev_if; 968c2ecf20Sopenharmony_ci int family; 978c2ecf20Sopenharmony_ci struct sctp_af *af; 988c2ecf20Sopenharmony_ci struct net *net = dev_net(skb->dev); 998c2ecf20Sopenharmony_ci bool is_gso = skb_is_gso(skb) && skb_is_gso_sctp(skb); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (skb->pkt_type != PACKET_HOST) 1028c2ecf20Sopenharmony_ci goto discard_it; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci __SCTP_INC_STATS(net, SCTP_MIB_INSCTPPACKS); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* If packet is too small to contain a single chunk, let's not 1078c2ecf20Sopenharmony_ci * waste time on it anymore. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci if (skb->len < sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) + 1108c2ecf20Sopenharmony_ci skb_transport_offset(skb)) 1118c2ecf20Sopenharmony_ci goto discard_it; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* If the packet is fragmented and we need to do crc checking, 1148c2ecf20Sopenharmony_ci * it's better to just linearize it otherwise crc computing 1158c2ecf20Sopenharmony_ci * takes longer. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci if ((!is_gso && skb_linearize(skb)) || 1188c2ecf20Sopenharmony_ci !pskb_may_pull(skb, sizeof(struct sctphdr))) 1198c2ecf20Sopenharmony_ci goto discard_it; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Pull up the IP header. */ 1228c2ecf20Sopenharmony_ci __skb_pull(skb, skb_transport_offset(skb)); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci skb->csum_valid = 0; /* Previous value not applicable */ 1258c2ecf20Sopenharmony_ci if (skb_csum_unnecessary(skb)) 1268c2ecf20Sopenharmony_ci __skb_decr_checksum_unnecessary(skb); 1278c2ecf20Sopenharmony_ci else if (!sctp_checksum_disable && 1288c2ecf20Sopenharmony_ci !is_gso && 1298c2ecf20Sopenharmony_ci sctp_rcv_checksum(net, skb) < 0) 1308c2ecf20Sopenharmony_ci goto discard_it; 1318c2ecf20Sopenharmony_ci skb->csum_valid = 1; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci __skb_pull(skb, sizeof(struct sctphdr)); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci family = ipver2af(ip_hdr(skb)->version); 1368c2ecf20Sopenharmony_ci af = sctp_get_af_specific(family); 1378c2ecf20Sopenharmony_ci if (unlikely(!af)) 1388c2ecf20Sopenharmony_ci goto discard_it; 1398c2ecf20Sopenharmony_ci SCTP_INPUT_CB(skb)->af = af; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Initialize local addresses for lookups. */ 1428c2ecf20Sopenharmony_ci af->from_skb(&src, skb, 1); 1438c2ecf20Sopenharmony_ci af->from_skb(&dest, skb, 0); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* If the packet is to or from a non-unicast address, 1468c2ecf20Sopenharmony_ci * silently discard the packet. 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * This is not clearly defined in the RFC except in section 1498c2ecf20Sopenharmony_ci * 8.4 - OOTB handling. However, based on the book "Stream Control 1508c2ecf20Sopenharmony_ci * Transmission Protocol" 2.1, "It is important to note that the 1518c2ecf20Sopenharmony_ci * IP address of an SCTP transport address must be a routable 1528c2ecf20Sopenharmony_ci * unicast address. In other words, IP multicast addresses and 1538c2ecf20Sopenharmony_ci * IP broadcast addresses cannot be used in an SCTP transport 1548c2ecf20Sopenharmony_ci * address." 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_ci if (!af->addr_valid(&src, NULL, skb) || 1578c2ecf20Sopenharmony_ci !af->addr_valid(&dest, NULL, skb)) 1588c2ecf20Sopenharmony_ci goto discard_it; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (!asoc) 1638c2ecf20Sopenharmony_ci ep = __sctp_rcv_lookup_endpoint(net, skb, &dest, &src); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* Retrieve the common input handling substructure. */ 1668c2ecf20Sopenharmony_ci rcvr = asoc ? &asoc->base : &ep->base; 1678c2ecf20Sopenharmony_ci sk = rcvr->sk; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* 1708c2ecf20Sopenharmony_ci * If a frame arrives on an interface and the receiving socket is 1718c2ecf20Sopenharmony_ci * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); 1748c2ecf20Sopenharmony_ci if (bound_dev_if && (bound_dev_if != af->skb_iif(skb))) { 1758c2ecf20Sopenharmony_ci if (transport) { 1768c2ecf20Sopenharmony_ci sctp_transport_put(transport); 1778c2ecf20Sopenharmony_ci asoc = NULL; 1788c2ecf20Sopenharmony_ci transport = NULL; 1798c2ecf20Sopenharmony_ci } else { 1808c2ecf20Sopenharmony_ci sctp_endpoint_put(ep); 1818c2ecf20Sopenharmony_ci ep = NULL; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci sk = net->sctp.ctl_sock; 1848c2ecf20Sopenharmony_ci ep = sctp_sk(sk)->ep; 1858c2ecf20Sopenharmony_ci sctp_endpoint_hold(ep); 1868c2ecf20Sopenharmony_ci rcvr = &ep->base; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* 1908c2ecf20Sopenharmony_ci * RFC 2960, 8.4 - Handle "Out of the blue" Packets. 1918c2ecf20Sopenharmony_ci * An SCTP packet is called an "out of the blue" (OOTB) 1928c2ecf20Sopenharmony_ci * packet if it is correctly formed, i.e., passed the 1938c2ecf20Sopenharmony_ci * receiver's checksum check, but the receiver is not 1948c2ecf20Sopenharmony_ci * able to identify the association to which this 1958c2ecf20Sopenharmony_ci * packet belongs. 1968c2ecf20Sopenharmony_ci */ 1978c2ecf20Sopenharmony_ci if (!asoc) { 1988c2ecf20Sopenharmony_ci if (sctp_rcv_ootb(skb)) { 1998c2ecf20Sopenharmony_ci __SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 2008c2ecf20Sopenharmony_ci goto discard_release; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family)) 2058c2ecf20Sopenharmony_ci goto discard_release; 2068c2ecf20Sopenharmony_ci nf_reset_ct(skb); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (sk_filter(sk, skb)) 2098c2ecf20Sopenharmony_ci goto discard_release; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* Create an SCTP packet structure. */ 2128c2ecf20Sopenharmony_ci chunk = sctp_chunkify(skb, asoc, sk, GFP_ATOMIC); 2138c2ecf20Sopenharmony_ci if (!chunk) 2148c2ecf20Sopenharmony_ci goto discard_release; 2158c2ecf20Sopenharmony_ci SCTP_INPUT_CB(skb)->chunk = chunk; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* Remember what endpoint is to handle this packet. */ 2188c2ecf20Sopenharmony_ci chunk->rcvr = rcvr; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* Remember the SCTP header. */ 2218c2ecf20Sopenharmony_ci chunk->sctp_hdr = sctp_hdr(skb); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Set the source and destination addresses of the incoming chunk. */ 2248c2ecf20Sopenharmony_ci sctp_init_addrs(chunk, &src, &dest); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci /* Remember where we came from. */ 2278c2ecf20Sopenharmony_ci chunk->transport = transport; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* Acquire access to the sock lock. Note: We are safe from other 2308c2ecf20Sopenharmony_ci * bottom halves on this lock, but a user may be in the lock too, 2318c2ecf20Sopenharmony_ci * so check if it is busy. 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ci bh_lock_sock(sk); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (sk != rcvr->sk) { 2368c2ecf20Sopenharmony_ci /* Our cached sk is different from the rcvr->sk. This is 2378c2ecf20Sopenharmony_ci * because migrate()/accept() may have moved the association 2388c2ecf20Sopenharmony_ci * to a new socket and released all the sockets. So now we 2398c2ecf20Sopenharmony_ci * are holding a lock on the old socket while the user may 2408c2ecf20Sopenharmony_ci * be doing something with the new socket. Switch our veiw 2418c2ecf20Sopenharmony_ci * of the current sk. 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_ci bh_unlock_sock(sk); 2448c2ecf20Sopenharmony_ci sk = rcvr->sk; 2458c2ecf20Sopenharmony_ci bh_lock_sock(sk); 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) { 2498c2ecf20Sopenharmony_ci if (sctp_add_backlog(sk, skb)) { 2508c2ecf20Sopenharmony_ci bh_unlock_sock(sk); 2518c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 2528c2ecf20Sopenharmony_ci skb = NULL; /* sctp_chunk_free already freed the skb */ 2538c2ecf20Sopenharmony_ci goto discard_release; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci __SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_BACKLOG); 2568c2ecf20Sopenharmony_ci } else { 2578c2ecf20Sopenharmony_ci __SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_SOFTIRQ); 2588c2ecf20Sopenharmony_ci sctp_inq_push(&chunk->rcvr->inqueue, chunk); 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci bh_unlock_sock(sk); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Release the asoc/ep ref we took in the lookup calls. */ 2648c2ecf20Sopenharmony_ci if (transport) 2658c2ecf20Sopenharmony_ci sctp_transport_put(transport); 2668c2ecf20Sopenharmony_ci else 2678c2ecf20Sopenharmony_ci sctp_endpoint_put(ep); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return 0; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cidiscard_it: 2728c2ecf20Sopenharmony_ci __SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS); 2738c2ecf20Sopenharmony_ci kfree_skb(skb); 2748c2ecf20Sopenharmony_ci return 0; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cidiscard_release: 2778c2ecf20Sopenharmony_ci /* Release the asoc/ep ref we took in the lookup calls. */ 2788c2ecf20Sopenharmony_ci if (transport) 2798c2ecf20Sopenharmony_ci sctp_transport_put(transport); 2808c2ecf20Sopenharmony_ci else 2818c2ecf20Sopenharmony_ci sctp_endpoint_put(ep); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci goto discard_it; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci/* Process the backlog queue of the socket. Every skb on 2878c2ecf20Sopenharmony_ci * the backlog holds a ref on an association or endpoint. 2888c2ecf20Sopenharmony_ci * We hold this ref throughout the state machine to make 2898c2ecf20Sopenharmony_ci * sure that the structure we need is still around. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ciint sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; 2948c2ecf20Sopenharmony_ci struct sctp_inq *inqueue = &chunk->rcvr->inqueue; 2958c2ecf20Sopenharmony_ci struct sctp_transport *t = chunk->transport; 2968c2ecf20Sopenharmony_ci struct sctp_ep_common *rcvr = NULL; 2978c2ecf20Sopenharmony_ci int backloged = 0; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci rcvr = chunk->rcvr; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* If the rcvr is dead then the association or endpoint 3028c2ecf20Sopenharmony_ci * has been deleted and we can safely drop the chunk 3038c2ecf20Sopenharmony_ci * and refs that we are holding. 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_ci if (rcvr->dead) { 3068c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 3078c2ecf20Sopenharmony_ci goto done; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci if (unlikely(rcvr->sk != sk)) { 3118c2ecf20Sopenharmony_ci /* In this case, the association moved from one socket to 3128c2ecf20Sopenharmony_ci * another. We are currently sitting on the backlog of the 3138c2ecf20Sopenharmony_ci * old socket, so we need to move. 3148c2ecf20Sopenharmony_ci * However, since we are here in the process context we 3158c2ecf20Sopenharmony_ci * need to take make sure that the user doesn't own 3168c2ecf20Sopenharmony_ci * the new socket when we process the packet. 3178c2ecf20Sopenharmony_ci * If the new socket is user-owned, queue the chunk to the 3188c2ecf20Sopenharmony_ci * backlog of the new socket without dropping any refs. 3198c2ecf20Sopenharmony_ci * Otherwise, we can safely push the chunk on the inqueue. 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci sk = rcvr->sk; 3238c2ecf20Sopenharmony_ci local_bh_disable(); 3248c2ecf20Sopenharmony_ci bh_lock_sock(sk); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) { 3278c2ecf20Sopenharmony_ci if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) 3288c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 3298c2ecf20Sopenharmony_ci else 3308c2ecf20Sopenharmony_ci backloged = 1; 3318c2ecf20Sopenharmony_ci } else 3328c2ecf20Sopenharmony_ci sctp_inq_push(inqueue, chunk); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci bh_unlock_sock(sk); 3358c2ecf20Sopenharmony_ci local_bh_enable(); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* If the chunk was backloged again, don't drop refs */ 3388c2ecf20Sopenharmony_ci if (backloged) 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_ci } else { 3418c2ecf20Sopenharmony_ci if (!sctp_newsk_ready(sk)) { 3428c2ecf20Sopenharmony_ci if (!sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf))) 3438c2ecf20Sopenharmony_ci return 0; 3448c2ecf20Sopenharmony_ci sctp_chunk_free(chunk); 3458c2ecf20Sopenharmony_ci } else { 3468c2ecf20Sopenharmony_ci sctp_inq_push(inqueue, chunk); 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cidone: 3518c2ecf20Sopenharmony_ci /* Release the refs we took in sctp_add_backlog */ 3528c2ecf20Sopenharmony_ci if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) 3538c2ecf20Sopenharmony_ci sctp_transport_put(t); 3548c2ecf20Sopenharmony_ci else if (SCTP_EP_TYPE_SOCKET == rcvr->type) 3558c2ecf20Sopenharmony_ci sctp_endpoint_put(sctp_ep(rcvr)); 3568c2ecf20Sopenharmony_ci else 3578c2ecf20Sopenharmony_ci BUG(); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci return 0; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic int sctp_add_backlog(struct sock *sk, struct sk_buff *skb) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; 3658c2ecf20Sopenharmony_ci struct sctp_transport *t = chunk->transport; 3668c2ecf20Sopenharmony_ci struct sctp_ep_common *rcvr = chunk->rcvr; 3678c2ecf20Sopenharmony_ci int ret; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci ret = sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)); 3708c2ecf20Sopenharmony_ci if (!ret) { 3718c2ecf20Sopenharmony_ci /* Hold the assoc/ep while hanging on the backlog queue. 3728c2ecf20Sopenharmony_ci * This way, we know structures we need will not disappear 3738c2ecf20Sopenharmony_ci * from us 3748c2ecf20Sopenharmony_ci */ 3758c2ecf20Sopenharmony_ci if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) 3768c2ecf20Sopenharmony_ci sctp_transport_hold(t); 3778c2ecf20Sopenharmony_ci else if (SCTP_EP_TYPE_SOCKET == rcvr->type) 3788c2ecf20Sopenharmony_ci sctp_endpoint_hold(sctp_ep(rcvr)); 3798c2ecf20Sopenharmony_ci else 3808c2ecf20Sopenharmony_ci BUG(); 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci return ret; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci/* Handle icmp frag needed error. */ 3878c2ecf20Sopenharmony_civoid sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, 3888c2ecf20Sopenharmony_ci struct sctp_transport *t, __u32 pmtu) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci if (!t || (t->pathmtu <= pmtu)) 3918c2ecf20Sopenharmony_ci return; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci if (sock_owned_by_user(sk)) { 3948c2ecf20Sopenharmony_ci atomic_set(&t->mtu_info, pmtu); 3958c2ecf20Sopenharmony_ci asoc->pmtu_pending = 1; 3968c2ecf20Sopenharmony_ci t->pmtu_pending = 1; 3978c2ecf20Sopenharmony_ci return; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci if (!(t->param_flags & SPP_PMTUD_ENABLE)) 4018c2ecf20Sopenharmony_ci /* We can't allow retransmitting in such case, as the 4028c2ecf20Sopenharmony_ci * retransmission would be sized just as before, and thus we 4038c2ecf20Sopenharmony_ci * would get another icmp, and retransmit again. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_ci return; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* Update transports view of the MTU. Return if no update was needed. 4088c2ecf20Sopenharmony_ci * If an update wasn't needed/possible, it also doesn't make sense to 4098c2ecf20Sopenharmony_ci * try to retransmit now. 4108c2ecf20Sopenharmony_ci */ 4118c2ecf20Sopenharmony_ci if (!sctp_transport_update_pmtu(t, pmtu)) 4128c2ecf20Sopenharmony_ci return; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* Update association pmtu. */ 4158c2ecf20Sopenharmony_ci sctp_assoc_sync_pmtu(asoc); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci /* Retransmit with the new pmtu setting. */ 4188c2ecf20Sopenharmony_ci sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD); 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_civoid sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t, 4228c2ecf20Sopenharmony_ci struct sk_buff *skb) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct dst_entry *dst; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (sock_owned_by_user(sk) || !t) 4278c2ecf20Sopenharmony_ci return; 4288c2ecf20Sopenharmony_ci dst = sctp_transport_dst_check(t); 4298c2ecf20Sopenharmony_ci if (dst) 4308c2ecf20Sopenharmony_ci dst->ops->redirect(dst, sk, skb); 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci/* 4348c2ecf20Sopenharmony_ci * SCTP Implementer's Guide, 2.37 ICMP handling procedures 4358c2ecf20Sopenharmony_ci * 4368c2ecf20Sopenharmony_ci * ICMP8) If the ICMP code is a "Unrecognized next header type encountered" 4378c2ecf20Sopenharmony_ci * or a "Protocol Unreachable" treat this message as an abort 4388c2ecf20Sopenharmony_ci * with the T bit set. 4398c2ecf20Sopenharmony_ci * 4408c2ecf20Sopenharmony_ci * This function sends an event to the state machine, which will abort the 4418c2ecf20Sopenharmony_ci * association. 4428c2ecf20Sopenharmony_ci * 4438c2ecf20Sopenharmony_ci */ 4448c2ecf20Sopenharmony_civoid sctp_icmp_proto_unreachable(struct sock *sk, 4458c2ecf20Sopenharmony_ci struct sctp_association *asoc, 4468c2ecf20Sopenharmony_ci struct sctp_transport *t) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci if (sock_owned_by_user(sk)) { 4498c2ecf20Sopenharmony_ci if (timer_pending(&t->proto_unreach_timer)) 4508c2ecf20Sopenharmony_ci return; 4518c2ecf20Sopenharmony_ci else { 4528c2ecf20Sopenharmony_ci if (!mod_timer(&t->proto_unreach_timer, 4538c2ecf20Sopenharmony_ci jiffies + (HZ/20))) 4548c2ecf20Sopenharmony_ci sctp_transport_hold(t); 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci } else { 4578c2ecf20Sopenharmony_ci struct net *net = sock_net(sk); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci pr_debug("%s: unrecognized next header type " 4608c2ecf20Sopenharmony_ci "encountered!\n", __func__); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci if (del_timer(&t->proto_unreach_timer)) 4638c2ecf20Sopenharmony_ci sctp_transport_put(t); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci sctp_do_sm(net, SCTP_EVENT_T_OTHER, 4668c2ecf20Sopenharmony_ci SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), 4678c2ecf20Sopenharmony_ci asoc->state, asoc->ep, asoc, t, 4688c2ecf20Sopenharmony_ci GFP_ATOMIC); 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci/* Common lookup code for icmp/icmpv6 error handler. */ 4738c2ecf20Sopenharmony_cistruct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, 4748c2ecf20Sopenharmony_ci struct sctphdr *sctphdr, 4758c2ecf20Sopenharmony_ci struct sctp_association **app, 4768c2ecf20Sopenharmony_ci struct sctp_transport **tpp) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci struct sctp_init_chunk *chunkhdr, _chunkhdr; 4798c2ecf20Sopenharmony_ci union sctp_addr saddr; 4808c2ecf20Sopenharmony_ci union sctp_addr daddr; 4818c2ecf20Sopenharmony_ci struct sctp_af *af; 4828c2ecf20Sopenharmony_ci struct sock *sk = NULL; 4838c2ecf20Sopenharmony_ci struct sctp_association *asoc; 4848c2ecf20Sopenharmony_ci struct sctp_transport *transport = NULL; 4858c2ecf20Sopenharmony_ci __u32 vtag = ntohl(sctphdr->vtag); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci *app = NULL; *tpp = NULL; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci af = sctp_get_af_specific(family); 4908c2ecf20Sopenharmony_ci if (unlikely(!af)) { 4918c2ecf20Sopenharmony_ci return NULL; 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci /* Initialize local addresses for lookups. */ 4958c2ecf20Sopenharmony_ci af->from_skb(&saddr, skb, 1); 4968c2ecf20Sopenharmony_ci af->from_skb(&daddr, skb, 0); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci /* Look for an association that matches the incoming ICMP error 4998c2ecf20Sopenharmony_ci * packet. 5008c2ecf20Sopenharmony_ci */ 5018c2ecf20Sopenharmony_ci asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport); 5028c2ecf20Sopenharmony_ci if (!asoc) 5038c2ecf20Sopenharmony_ci return NULL; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci sk = asoc->base.sk; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /* RFC 4960, Appendix C. ICMP Handling 5088c2ecf20Sopenharmony_ci * 5098c2ecf20Sopenharmony_ci * ICMP6) An implementation MUST validate that the Verification Tag 5108c2ecf20Sopenharmony_ci * contained in the ICMP message matches the Verification Tag of 5118c2ecf20Sopenharmony_ci * the peer. If the Verification Tag is not 0 and does NOT 5128c2ecf20Sopenharmony_ci * match, discard the ICMP message. If it is 0 and the ICMP 5138c2ecf20Sopenharmony_ci * message contains enough bytes to verify that the chunk type is 5148c2ecf20Sopenharmony_ci * an INIT chunk and that the Initiate Tag matches the tag of the 5158c2ecf20Sopenharmony_ci * peer, continue with ICMP7. If the ICMP message is too short 5168c2ecf20Sopenharmony_ci * or the chunk type or the Initiate Tag does not match, silently 5178c2ecf20Sopenharmony_ci * discard the packet. 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_ci if (vtag == 0) { 5208c2ecf20Sopenharmony_ci /* chunk header + first 4 octects of init header */ 5218c2ecf20Sopenharmony_ci chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) + 5228c2ecf20Sopenharmony_ci sizeof(struct sctphdr), 5238c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr) + 5248c2ecf20Sopenharmony_ci sizeof(__be32), &_chunkhdr); 5258c2ecf20Sopenharmony_ci if (!chunkhdr || 5268c2ecf20Sopenharmony_ci chunkhdr->chunk_hdr.type != SCTP_CID_INIT || 5278c2ecf20Sopenharmony_ci ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) 5288c2ecf20Sopenharmony_ci goto out; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci } else if (vtag != asoc->c.peer_vtag) { 5318c2ecf20Sopenharmony_ci goto out; 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci bh_lock_sock(sk); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* If too many ICMPs get dropped on busy 5378c2ecf20Sopenharmony_ci * servers this needs to be solved differently. 5388c2ecf20Sopenharmony_ci */ 5398c2ecf20Sopenharmony_ci if (sock_owned_by_user(sk)) 5408c2ecf20Sopenharmony_ci __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci *app = asoc; 5438c2ecf20Sopenharmony_ci *tpp = transport; 5448c2ecf20Sopenharmony_ci return sk; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ciout: 5478c2ecf20Sopenharmony_ci sctp_transport_put(transport); 5488c2ecf20Sopenharmony_ci return NULL; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci/* Common cleanup code for icmp/icmpv6 error handler. */ 5528c2ecf20Sopenharmony_civoid sctp_err_finish(struct sock *sk, struct sctp_transport *t) 5538c2ecf20Sopenharmony_ci __releases(&((__sk)->sk_lock.slock)) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci bh_unlock_sock(sk); 5568c2ecf20Sopenharmony_ci sctp_transport_put(t); 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci/* 5608c2ecf20Sopenharmony_ci * This routine is called by the ICMP module when it gets some 5618c2ecf20Sopenharmony_ci * sort of error condition. If err < 0 then the socket should 5628c2ecf20Sopenharmony_ci * be closed and the error returned to the user. If err > 0 5638c2ecf20Sopenharmony_ci * it's just the icmp type << 8 | icmp code. After adjustment 5648c2ecf20Sopenharmony_ci * header points to the first 8 bytes of the sctp header. We need 5658c2ecf20Sopenharmony_ci * to find the appropriate port. 5668c2ecf20Sopenharmony_ci * 5678c2ecf20Sopenharmony_ci * The locking strategy used here is very "optimistic". When 5688c2ecf20Sopenharmony_ci * someone else accesses the socket the ICMP is just dropped 5698c2ecf20Sopenharmony_ci * and for some paths there is no check at all. 5708c2ecf20Sopenharmony_ci * A more general error queue to queue errors for later handling 5718c2ecf20Sopenharmony_ci * is probably better. 5728c2ecf20Sopenharmony_ci * 5738c2ecf20Sopenharmony_ci */ 5748c2ecf20Sopenharmony_ciint sctp_v4_err(struct sk_buff *skb, __u32 info) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci const struct iphdr *iph = (const struct iphdr *)skb->data; 5778c2ecf20Sopenharmony_ci const int ihlen = iph->ihl * 4; 5788c2ecf20Sopenharmony_ci const int type = icmp_hdr(skb)->type; 5798c2ecf20Sopenharmony_ci const int code = icmp_hdr(skb)->code; 5808c2ecf20Sopenharmony_ci struct sock *sk; 5818c2ecf20Sopenharmony_ci struct sctp_association *asoc = NULL; 5828c2ecf20Sopenharmony_ci struct sctp_transport *transport; 5838c2ecf20Sopenharmony_ci struct inet_sock *inet; 5848c2ecf20Sopenharmony_ci __u16 saveip, savesctp; 5858c2ecf20Sopenharmony_ci int err; 5868c2ecf20Sopenharmony_ci struct net *net = dev_net(skb->dev); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci /* Fix up skb to look at the embedded net header. */ 5898c2ecf20Sopenharmony_ci saveip = skb->network_header; 5908c2ecf20Sopenharmony_ci savesctp = skb->transport_header; 5918c2ecf20Sopenharmony_ci skb_reset_network_header(skb); 5928c2ecf20Sopenharmony_ci skb_set_transport_header(skb, ihlen); 5938c2ecf20Sopenharmony_ci sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport); 5948c2ecf20Sopenharmony_ci /* Put back, the original values. */ 5958c2ecf20Sopenharmony_ci skb->network_header = saveip; 5968c2ecf20Sopenharmony_ci skb->transport_header = savesctp; 5978c2ecf20Sopenharmony_ci if (!sk) { 5988c2ecf20Sopenharmony_ci __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); 5998c2ecf20Sopenharmony_ci return -ENOENT; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci /* Warning: The sock lock is held. Remember to call 6028c2ecf20Sopenharmony_ci * sctp_err_finish! 6038c2ecf20Sopenharmony_ci */ 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci switch (type) { 6068c2ecf20Sopenharmony_ci case ICMP_PARAMETERPROB: 6078c2ecf20Sopenharmony_ci err = EPROTO; 6088c2ecf20Sopenharmony_ci break; 6098c2ecf20Sopenharmony_ci case ICMP_DEST_UNREACH: 6108c2ecf20Sopenharmony_ci if (code > NR_ICMP_UNREACH) 6118c2ecf20Sopenharmony_ci goto out_unlock; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci /* PMTU discovery (RFC1191) */ 6148c2ecf20Sopenharmony_ci if (ICMP_FRAG_NEEDED == code) { 6158c2ecf20Sopenharmony_ci sctp_icmp_frag_needed(sk, asoc, transport, 6168c2ecf20Sopenharmony_ci SCTP_TRUNC4(info)); 6178c2ecf20Sopenharmony_ci goto out_unlock; 6188c2ecf20Sopenharmony_ci } else { 6198c2ecf20Sopenharmony_ci if (ICMP_PROT_UNREACH == code) { 6208c2ecf20Sopenharmony_ci sctp_icmp_proto_unreachable(sk, asoc, 6218c2ecf20Sopenharmony_ci transport); 6228c2ecf20Sopenharmony_ci goto out_unlock; 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci err = icmp_err_convert[code].errno; 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci case ICMP_TIME_EXCEEDED: 6288c2ecf20Sopenharmony_ci /* Ignore any time exceeded errors due to fragment reassembly 6298c2ecf20Sopenharmony_ci * timeouts. 6308c2ecf20Sopenharmony_ci */ 6318c2ecf20Sopenharmony_ci if (ICMP_EXC_FRAGTIME == code) 6328c2ecf20Sopenharmony_ci goto out_unlock; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci err = EHOSTUNREACH; 6358c2ecf20Sopenharmony_ci break; 6368c2ecf20Sopenharmony_ci case ICMP_REDIRECT: 6378c2ecf20Sopenharmony_ci sctp_icmp_redirect(sk, transport, skb); 6388c2ecf20Sopenharmony_ci /* Fall through to out_unlock. */ 6398c2ecf20Sopenharmony_ci default: 6408c2ecf20Sopenharmony_ci goto out_unlock; 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci inet = inet_sk(sk); 6448c2ecf20Sopenharmony_ci if (!sock_owned_by_user(sk) && inet->recverr) { 6458c2ecf20Sopenharmony_ci sk->sk_err = err; 6468c2ecf20Sopenharmony_ci sk->sk_error_report(sk); 6478c2ecf20Sopenharmony_ci } else { /* Only an error on timeout */ 6488c2ecf20Sopenharmony_ci sk->sk_err_soft = err; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ciout_unlock: 6528c2ecf20Sopenharmony_ci sctp_err_finish(sk, transport); 6538c2ecf20Sopenharmony_ci return 0; 6548c2ecf20Sopenharmony_ci} 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci/* 6578c2ecf20Sopenharmony_ci * RFC 2960, 8.4 - Handle "Out of the blue" Packets. 6588c2ecf20Sopenharmony_ci * 6598c2ecf20Sopenharmony_ci * This function scans all the chunks in the OOTB packet to determine if 6608c2ecf20Sopenharmony_ci * the packet should be discarded right away. If a response might be needed 6618c2ecf20Sopenharmony_ci * for this packet, or, if further processing is possible, the packet will 6628c2ecf20Sopenharmony_ci * be queued to a proper inqueue for the next phase of handling. 6638c2ecf20Sopenharmony_ci * 6648c2ecf20Sopenharmony_ci * Output: 6658c2ecf20Sopenharmony_ci * Return 0 - If further processing is needed. 6668c2ecf20Sopenharmony_ci * Return 1 - If the packet can be discarded right away. 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_cistatic int sctp_rcv_ootb(struct sk_buff *skb) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci struct sctp_chunkhdr *ch, _ch; 6718c2ecf20Sopenharmony_ci int ch_end, offset = 0; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci /* Scan through all the chunks in the packet. */ 6748c2ecf20Sopenharmony_ci do { 6758c2ecf20Sopenharmony_ci /* Make sure we have at least the header there */ 6768c2ecf20Sopenharmony_ci if (offset + sizeof(_ch) > skb->len) 6778c2ecf20Sopenharmony_ci break; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci ch = skb_header_pointer(skb, offset, sizeof(*ch), &_ch); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* Break out if chunk length is less then minimal. */ 6828c2ecf20Sopenharmony_ci if (!ch || ntohs(ch->length) < sizeof(_ch)) 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci ch_end = offset + SCTP_PAD4(ntohs(ch->length)); 6868c2ecf20Sopenharmony_ci if (ch_end > skb->len) 6878c2ecf20Sopenharmony_ci break; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the 6908c2ecf20Sopenharmony_ci * receiver MUST silently discard the OOTB packet and take no 6918c2ecf20Sopenharmony_ci * further action. 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_ci if (SCTP_CID_ABORT == ch->type) 6948c2ecf20Sopenharmony_ci goto discard; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* RFC 8.4, 6) If the packet contains a SHUTDOWN COMPLETE 6978c2ecf20Sopenharmony_ci * chunk, the receiver should silently discard the packet 6988c2ecf20Sopenharmony_ci * and take no further action. 6998c2ecf20Sopenharmony_ci */ 7008c2ecf20Sopenharmony_ci if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type) 7018c2ecf20Sopenharmony_ci goto discard; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* RFC 4460, 2.11.2 7048c2ecf20Sopenharmony_ci * This will discard packets with INIT chunk bundled as 7058c2ecf20Sopenharmony_ci * subsequent chunks in the packet. When INIT is first, 7068c2ecf20Sopenharmony_ci * the normal INIT processing will discard the chunk. 7078c2ecf20Sopenharmony_ci */ 7088c2ecf20Sopenharmony_ci if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data) 7098c2ecf20Sopenharmony_ci goto discard; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci offset = ch_end; 7128c2ecf20Sopenharmony_ci } while (ch_end < skb->len); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci return 0; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cidiscard: 7178c2ecf20Sopenharmony_ci return 1; 7188c2ecf20Sopenharmony_ci} 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci/* Insert endpoint into the hash table. */ 7218c2ecf20Sopenharmony_cistatic int __sctp_hash_endpoint(struct sctp_endpoint *ep) 7228c2ecf20Sopenharmony_ci{ 7238c2ecf20Sopenharmony_ci struct sock *sk = ep->base.sk; 7248c2ecf20Sopenharmony_ci struct net *net = sock_net(sk); 7258c2ecf20Sopenharmony_ci struct sctp_hashbucket *head; 7268c2ecf20Sopenharmony_ci struct sctp_ep_common *epb; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci epb = &ep->base; 7298c2ecf20Sopenharmony_ci epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port); 7308c2ecf20Sopenharmony_ci head = &sctp_ep_hashtable[epb->hashent]; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci if (sk->sk_reuseport) { 7338c2ecf20Sopenharmony_ci bool any = sctp_is_ep_boundall(sk); 7348c2ecf20Sopenharmony_ci struct sctp_ep_common *epb2; 7358c2ecf20Sopenharmony_ci struct list_head *list; 7368c2ecf20Sopenharmony_ci int cnt = 0, err = 1; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci list_for_each(list, &ep->base.bind_addr.address_list) 7398c2ecf20Sopenharmony_ci cnt++; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci sctp_for_each_hentry(epb2, &head->chain) { 7428c2ecf20Sopenharmony_ci struct sock *sk2 = epb2->sk; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if (!net_eq(sock_net(sk2), net) || sk2 == sk || 7458c2ecf20Sopenharmony_ci !uid_eq(sock_i_uid(sk2), sock_i_uid(sk)) || 7468c2ecf20Sopenharmony_ci !sk2->sk_reuseport) 7478c2ecf20Sopenharmony_ci continue; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci err = sctp_bind_addrs_check(sctp_sk(sk2), 7508c2ecf20Sopenharmony_ci sctp_sk(sk), cnt); 7518c2ecf20Sopenharmony_ci if (!err) { 7528c2ecf20Sopenharmony_ci err = reuseport_add_sock(sk, sk2, any); 7538c2ecf20Sopenharmony_ci if (err) 7548c2ecf20Sopenharmony_ci return err; 7558c2ecf20Sopenharmony_ci break; 7568c2ecf20Sopenharmony_ci } else if (err < 0) { 7578c2ecf20Sopenharmony_ci return err; 7588c2ecf20Sopenharmony_ci } 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci if (err) { 7628c2ecf20Sopenharmony_ci err = reuseport_alloc(sk, any); 7638c2ecf20Sopenharmony_ci if (err) 7648c2ecf20Sopenharmony_ci return err; 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci write_lock(&head->lock); 7698c2ecf20Sopenharmony_ci hlist_add_head(&epb->node, &head->chain); 7708c2ecf20Sopenharmony_ci write_unlock(&head->lock); 7718c2ecf20Sopenharmony_ci return 0; 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci/* Add an endpoint to the hash. Local BH-safe. */ 7758c2ecf20Sopenharmony_ciint sctp_hash_endpoint(struct sctp_endpoint *ep) 7768c2ecf20Sopenharmony_ci{ 7778c2ecf20Sopenharmony_ci int err; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci local_bh_disable(); 7808c2ecf20Sopenharmony_ci err = __sctp_hash_endpoint(ep); 7818c2ecf20Sopenharmony_ci local_bh_enable(); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci return err; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci/* Remove endpoint from the hash table. */ 7878c2ecf20Sopenharmony_cistatic void __sctp_unhash_endpoint(struct sctp_endpoint *ep) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci struct sock *sk = ep->base.sk; 7908c2ecf20Sopenharmony_ci struct sctp_hashbucket *head; 7918c2ecf20Sopenharmony_ci struct sctp_ep_common *epb; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci epb = &ep->base; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci epb->hashent = sctp_ep_hashfn(sock_net(sk), epb->bind_addr.port); 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci head = &sctp_ep_hashtable[epb->hashent]; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci if (rcu_access_pointer(sk->sk_reuseport_cb)) 8008c2ecf20Sopenharmony_ci reuseport_detach_sock(sk); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci write_lock(&head->lock); 8038c2ecf20Sopenharmony_ci hlist_del_init(&epb->node); 8048c2ecf20Sopenharmony_ci write_unlock(&head->lock); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci/* Remove endpoint from the hash. Local BH-safe. */ 8088c2ecf20Sopenharmony_civoid sctp_unhash_endpoint(struct sctp_endpoint *ep) 8098c2ecf20Sopenharmony_ci{ 8108c2ecf20Sopenharmony_ci local_bh_disable(); 8118c2ecf20Sopenharmony_ci __sctp_unhash_endpoint(ep); 8128c2ecf20Sopenharmony_ci local_bh_enable(); 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_cistatic inline __u32 sctp_hashfn(const struct net *net, __be16 lport, 8168c2ecf20Sopenharmony_ci const union sctp_addr *paddr, __u32 seed) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci __u32 addr; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci if (paddr->sa.sa_family == AF_INET6) 8218c2ecf20Sopenharmony_ci addr = jhash(&paddr->v6.sin6_addr, 16, seed); 8228c2ecf20Sopenharmony_ci else 8238c2ecf20Sopenharmony_ci addr = (__force __u32)paddr->v4.sin_addr.s_addr; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci return jhash_3words(addr, ((__force __u32)paddr->v4.sin_port) << 16 | 8268c2ecf20Sopenharmony_ci (__force __u32)lport, net_hash_mix(net), seed); 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci/* Look up an endpoint. */ 8308c2ecf20Sopenharmony_cistatic struct sctp_endpoint *__sctp_rcv_lookup_endpoint( 8318c2ecf20Sopenharmony_ci struct net *net, struct sk_buff *skb, 8328c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 8338c2ecf20Sopenharmony_ci const union sctp_addr *paddr) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci struct sctp_hashbucket *head; 8368c2ecf20Sopenharmony_ci struct sctp_ep_common *epb; 8378c2ecf20Sopenharmony_ci struct sctp_endpoint *ep; 8388c2ecf20Sopenharmony_ci struct sock *sk; 8398c2ecf20Sopenharmony_ci __be16 lport; 8408c2ecf20Sopenharmony_ci int hash; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci lport = laddr->v4.sin_port; 8438c2ecf20Sopenharmony_ci hash = sctp_ep_hashfn(net, ntohs(lport)); 8448c2ecf20Sopenharmony_ci head = &sctp_ep_hashtable[hash]; 8458c2ecf20Sopenharmony_ci read_lock(&head->lock); 8468c2ecf20Sopenharmony_ci sctp_for_each_hentry(epb, &head->chain) { 8478c2ecf20Sopenharmony_ci ep = sctp_ep(epb); 8488c2ecf20Sopenharmony_ci if (sctp_endpoint_is_match(ep, net, laddr)) 8498c2ecf20Sopenharmony_ci goto hit; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci ep = sctp_sk(net->sctp.ctl_sock)->ep; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_cihit: 8558c2ecf20Sopenharmony_ci sk = ep->base.sk; 8568c2ecf20Sopenharmony_ci if (sk->sk_reuseport) { 8578c2ecf20Sopenharmony_ci __u32 phash = sctp_hashfn(net, lport, paddr, 0); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci sk = reuseport_select_sock(sk, phash, skb, 8608c2ecf20Sopenharmony_ci sizeof(struct sctphdr)); 8618c2ecf20Sopenharmony_ci if (sk) 8628c2ecf20Sopenharmony_ci ep = sctp_sk(sk)->ep; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci sctp_endpoint_hold(ep); 8658c2ecf20Sopenharmony_ci read_unlock(&head->lock); 8668c2ecf20Sopenharmony_ci return ep; 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci/* rhashtable for transport */ 8708c2ecf20Sopenharmony_cistruct sctp_hash_cmp_arg { 8718c2ecf20Sopenharmony_ci const union sctp_addr *paddr; 8728c2ecf20Sopenharmony_ci const struct net *net; 8738c2ecf20Sopenharmony_ci __be16 lport; 8748c2ecf20Sopenharmony_ci}; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_cistatic inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg, 8778c2ecf20Sopenharmony_ci const void *ptr) 8788c2ecf20Sopenharmony_ci{ 8798c2ecf20Sopenharmony_ci struct sctp_transport *t = (struct sctp_transport *)ptr; 8808c2ecf20Sopenharmony_ci const struct sctp_hash_cmp_arg *x = arg->key; 8818c2ecf20Sopenharmony_ci int err = 1; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr)) 8848c2ecf20Sopenharmony_ci return err; 8858c2ecf20Sopenharmony_ci if (!sctp_transport_hold(t)) 8868c2ecf20Sopenharmony_ci return err; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci if (!net_eq(t->asoc->base.net, x->net)) 8898c2ecf20Sopenharmony_ci goto out; 8908c2ecf20Sopenharmony_ci if (x->lport != htons(t->asoc->base.bind_addr.port)) 8918c2ecf20Sopenharmony_ci goto out; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci err = 0; 8948c2ecf20Sopenharmony_ciout: 8958c2ecf20Sopenharmony_ci sctp_transport_put(t); 8968c2ecf20Sopenharmony_ci return err; 8978c2ecf20Sopenharmony_ci} 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_cistatic inline __u32 sctp_hash_obj(const void *data, u32 len, u32 seed) 9008c2ecf20Sopenharmony_ci{ 9018c2ecf20Sopenharmony_ci const struct sctp_transport *t = data; 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci return sctp_hashfn(t->asoc->base.net, 9048c2ecf20Sopenharmony_ci htons(t->asoc->base.bind_addr.port), 9058c2ecf20Sopenharmony_ci &t->ipaddr, seed); 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_cistatic inline __u32 sctp_hash_key(const void *data, u32 len, u32 seed) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci const struct sctp_hash_cmp_arg *x = data; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci return sctp_hashfn(x->net, x->lport, x->paddr, seed); 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic const struct rhashtable_params sctp_hash_params = { 9168c2ecf20Sopenharmony_ci .head_offset = offsetof(struct sctp_transport, node), 9178c2ecf20Sopenharmony_ci .hashfn = sctp_hash_key, 9188c2ecf20Sopenharmony_ci .obj_hashfn = sctp_hash_obj, 9198c2ecf20Sopenharmony_ci .obj_cmpfn = sctp_hash_cmp, 9208c2ecf20Sopenharmony_ci .automatic_shrinking = true, 9218c2ecf20Sopenharmony_ci}; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ciint sctp_transport_hashtable_init(void) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci return rhltable_init(&sctp_transport_hashtable, &sctp_hash_params); 9268c2ecf20Sopenharmony_ci} 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_civoid sctp_transport_hashtable_destroy(void) 9298c2ecf20Sopenharmony_ci{ 9308c2ecf20Sopenharmony_ci rhltable_destroy(&sctp_transport_hashtable); 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ciint sctp_hash_transport(struct sctp_transport *t) 9348c2ecf20Sopenharmony_ci{ 9358c2ecf20Sopenharmony_ci struct sctp_transport *transport; 9368c2ecf20Sopenharmony_ci struct rhlist_head *tmp, *list; 9378c2ecf20Sopenharmony_ci struct sctp_hash_cmp_arg arg; 9388c2ecf20Sopenharmony_ci int err; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci if (t->asoc->temp) 9418c2ecf20Sopenharmony_ci return 0; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci arg.net = t->asoc->base.net; 9448c2ecf20Sopenharmony_ci arg.paddr = &t->ipaddr; 9458c2ecf20Sopenharmony_ci arg.lport = htons(t->asoc->base.bind_addr.port); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci rcu_read_lock(); 9488c2ecf20Sopenharmony_ci list = rhltable_lookup(&sctp_transport_hashtable, &arg, 9498c2ecf20Sopenharmony_ci sctp_hash_params); 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci rhl_for_each_entry_rcu(transport, tmp, list, node) 9528c2ecf20Sopenharmony_ci if (transport->asoc->ep == t->asoc->ep) { 9538c2ecf20Sopenharmony_ci rcu_read_unlock(); 9548c2ecf20Sopenharmony_ci return -EEXIST; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci rcu_read_unlock(); 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci err = rhltable_insert_key(&sctp_transport_hashtable, &arg, 9598c2ecf20Sopenharmony_ci &t->node, sctp_hash_params); 9608c2ecf20Sopenharmony_ci if (err) 9618c2ecf20Sopenharmony_ci pr_err_once("insert transport fail, errno %d\n", err); 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci return err; 9648c2ecf20Sopenharmony_ci} 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_civoid sctp_unhash_transport(struct sctp_transport *t) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci if (t->asoc->temp) 9698c2ecf20Sopenharmony_ci return; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci rhltable_remove(&sctp_transport_hashtable, &t->node, 9728c2ecf20Sopenharmony_ci sctp_hash_params); 9738c2ecf20Sopenharmony_ci} 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci/* return a transport with holding it */ 9768c2ecf20Sopenharmony_cistruct sctp_transport *sctp_addrs_lookup_transport( 9778c2ecf20Sopenharmony_ci struct net *net, 9788c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 9798c2ecf20Sopenharmony_ci const union sctp_addr *paddr) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct rhlist_head *tmp, *list; 9828c2ecf20Sopenharmony_ci struct sctp_transport *t; 9838c2ecf20Sopenharmony_ci struct sctp_hash_cmp_arg arg = { 9848c2ecf20Sopenharmony_ci .paddr = paddr, 9858c2ecf20Sopenharmony_ci .net = net, 9868c2ecf20Sopenharmony_ci .lport = laddr->v4.sin_port, 9878c2ecf20Sopenharmony_ci }; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci list = rhltable_lookup(&sctp_transport_hashtable, &arg, 9908c2ecf20Sopenharmony_ci sctp_hash_params); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci rhl_for_each_entry_rcu(t, tmp, list, node) { 9938c2ecf20Sopenharmony_ci if (!sctp_transport_hold(t)) 9948c2ecf20Sopenharmony_ci continue; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci if (sctp_bind_addr_match(&t->asoc->base.bind_addr, 9978c2ecf20Sopenharmony_ci laddr, sctp_sk(t->asoc->base.sk))) 9988c2ecf20Sopenharmony_ci return t; 9998c2ecf20Sopenharmony_ci sctp_transport_put(t); 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci return NULL; 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci/* return a transport without holding it, as it's only used under sock lock */ 10068c2ecf20Sopenharmony_cistruct sctp_transport *sctp_epaddr_lookup_transport( 10078c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 10088c2ecf20Sopenharmony_ci const union sctp_addr *paddr) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci struct rhlist_head *tmp, *list; 10118c2ecf20Sopenharmony_ci struct sctp_transport *t; 10128c2ecf20Sopenharmony_ci struct sctp_hash_cmp_arg arg = { 10138c2ecf20Sopenharmony_ci .paddr = paddr, 10148c2ecf20Sopenharmony_ci .net = ep->base.net, 10158c2ecf20Sopenharmony_ci .lport = htons(ep->base.bind_addr.port), 10168c2ecf20Sopenharmony_ci }; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci list = rhltable_lookup(&sctp_transport_hashtable, &arg, 10198c2ecf20Sopenharmony_ci sctp_hash_params); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci rhl_for_each_entry_rcu(t, tmp, list, node) 10228c2ecf20Sopenharmony_ci if (ep == t->asoc->ep) 10238c2ecf20Sopenharmony_ci return t; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci return NULL; 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci/* Look up an association. */ 10298c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_lookup_association( 10308c2ecf20Sopenharmony_ci struct net *net, 10318c2ecf20Sopenharmony_ci const union sctp_addr *local, 10328c2ecf20Sopenharmony_ci const union sctp_addr *peer, 10338c2ecf20Sopenharmony_ci struct sctp_transport **pt) 10348c2ecf20Sopenharmony_ci{ 10358c2ecf20Sopenharmony_ci struct sctp_transport *t; 10368c2ecf20Sopenharmony_ci struct sctp_association *asoc = NULL; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci t = sctp_addrs_lookup_transport(net, local, peer); 10398c2ecf20Sopenharmony_ci if (!t) 10408c2ecf20Sopenharmony_ci goto out; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci asoc = t->asoc; 10438c2ecf20Sopenharmony_ci *pt = t; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ciout: 10468c2ecf20Sopenharmony_ci return asoc; 10478c2ecf20Sopenharmony_ci} 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci/* Look up an association. protected by RCU read lock */ 10508c2ecf20Sopenharmony_cistatic 10518c2ecf20Sopenharmony_cistruct sctp_association *sctp_lookup_association(struct net *net, 10528c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 10538c2ecf20Sopenharmony_ci const union sctp_addr *paddr, 10548c2ecf20Sopenharmony_ci struct sctp_transport **transportp) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci struct sctp_association *asoc; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci rcu_read_lock(); 10598c2ecf20Sopenharmony_ci asoc = __sctp_lookup_association(net, laddr, paddr, transportp); 10608c2ecf20Sopenharmony_ci rcu_read_unlock(); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci return asoc; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci/* Is there an association matching the given local and peer addresses? */ 10668c2ecf20Sopenharmony_cibool sctp_has_association(struct net *net, 10678c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 10688c2ecf20Sopenharmony_ci const union sctp_addr *paddr) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci struct sctp_transport *transport; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci if (sctp_lookup_association(net, laddr, paddr, &transport)) { 10738c2ecf20Sopenharmony_ci sctp_transport_put(transport); 10748c2ecf20Sopenharmony_ci return true; 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci return false; 10788c2ecf20Sopenharmony_ci} 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci/* 10818c2ecf20Sopenharmony_ci * SCTP Implementors Guide, 2.18 Handling of address 10828c2ecf20Sopenharmony_ci * parameters within the INIT or INIT-ACK. 10838c2ecf20Sopenharmony_ci * 10848c2ecf20Sopenharmony_ci * D) When searching for a matching TCB upon reception of an INIT 10858c2ecf20Sopenharmony_ci * or INIT-ACK chunk the receiver SHOULD use not only the 10868c2ecf20Sopenharmony_ci * source address of the packet (containing the INIT or 10878c2ecf20Sopenharmony_ci * INIT-ACK) but the receiver SHOULD also use all valid 10888c2ecf20Sopenharmony_ci * address parameters contained within the chunk. 10898c2ecf20Sopenharmony_ci * 10908c2ecf20Sopenharmony_ci * 2.18.3 Solution description 10918c2ecf20Sopenharmony_ci * 10928c2ecf20Sopenharmony_ci * This new text clearly specifies to an implementor the need 10938c2ecf20Sopenharmony_ci * to look within the INIT or INIT-ACK. Any implementation that 10948c2ecf20Sopenharmony_ci * does not do this, may not be able to establish associations 10958c2ecf20Sopenharmony_ci * in certain circumstances. 10968c2ecf20Sopenharmony_ci * 10978c2ecf20Sopenharmony_ci */ 10988c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_rcv_init_lookup(struct net *net, 10998c2ecf20Sopenharmony_ci struct sk_buff *skb, 11008c2ecf20Sopenharmony_ci const union sctp_addr *laddr, struct sctp_transport **transportp) 11018c2ecf20Sopenharmony_ci{ 11028c2ecf20Sopenharmony_ci struct sctp_association *asoc; 11038c2ecf20Sopenharmony_ci union sctp_addr addr; 11048c2ecf20Sopenharmony_ci union sctp_addr *paddr = &addr; 11058c2ecf20Sopenharmony_ci struct sctphdr *sh = sctp_hdr(skb); 11068c2ecf20Sopenharmony_ci union sctp_params params; 11078c2ecf20Sopenharmony_ci struct sctp_init_chunk *init; 11088c2ecf20Sopenharmony_ci struct sctp_af *af; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci /* 11118c2ecf20Sopenharmony_ci * This code will NOT touch anything inside the chunk--it is 11128c2ecf20Sopenharmony_ci * strictly READ-ONLY. 11138c2ecf20Sopenharmony_ci * 11148c2ecf20Sopenharmony_ci * RFC 2960 3 SCTP packet Format 11158c2ecf20Sopenharmony_ci * 11168c2ecf20Sopenharmony_ci * Multiple chunks can be bundled into one SCTP packet up to 11178c2ecf20Sopenharmony_ci * the MTU size, except for the INIT, INIT ACK, and SHUTDOWN 11188c2ecf20Sopenharmony_ci * COMPLETE chunks. These chunks MUST NOT be bundled with any 11198c2ecf20Sopenharmony_ci * other chunk in a packet. See Section 6.10 for more details 11208c2ecf20Sopenharmony_ci * on chunk bundling. 11218c2ecf20Sopenharmony_ci */ 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci /* Find the start of the TLVs and the end of the chunk. This is 11248c2ecf20Sopenharmony_ci * the region we search for address parameters. 11258c2ecf20Sopenharmony_ci */ 11268c2ecf20Sopenharmony_ci init = (struct sctp_init_chunk *)skb->data; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* Walk the parameters looking for embedded addresses. */ 11298c2ecf20Sopenharmony_ci sctp_walk_params(params, init, init_hdr.params) { 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci /* Note: Ignoring hostname addresses. */ 11328c2ecf20Sopenharmony_ci af = sctp_get_af_specific(param_type2af(params.p->type)); 11338c2ecf20Sopenharmony_ci if (!af) 11348c2ecf20Sopenharmony_ci continue; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (!af->from_addr_param(paddr, params.addr, sh->source, 0)) 11378c2ecf20Sopenharmony_ci continue; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci asoc = __sctp_lookup_association(net, laddr, paddr, transportp); 11408c2ecf20Sopenharmony_ci if (asoc) 11418c2ecf20Sopenharmony_ci return asoc; 11428c2ecf20Sopenharmony_ci } 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci return NULL; 11458c2ecf20Sopenharmony_ci} 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci/* ADD-IP, Section 5.2 11488c2ecf20Sopenharmony_ci * When an endpoint receives an ASCONF Chunk from the remote peer 11498c2ecf20Sopenharmony_ci * special procedures may be needed to identify the association the 11508c2ecf20Sopenharmony_ci * ASCONF Chunk is associated with. To properly find the association 11518c2ecf20Sopenharmony_ci * the following procedures SHOULD be followed: 11528c2ecf20Sopenharmony_ci * 11538c2ecf20Sopenharmony_ci * D2) If the association is not found, use the address found in the 11548c2ecf20Sopenharmony_ci * Address Parameter TLV combined with the port number found in the 11558c2ecf20Sopenharmony_ci * SCTP common header. If found proceed to rule D4. 11568c2ecf20Sopenharmony_ci * 11578c2ecf20Sopenharmony_ci * D2-ext) If more than one ASCONF Chunks are packed together, use the 11588c2ecf20Sopenharmony_ci * address found in the ASCONF Address Parameter TLV of each of the 11598c2ecf20Sopenharmony_ci * subsequent ASCONF Chunks. If found, proceed to rule D4. 11608c2ecf20Sopenharmony_ci */ 11618c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_rcv_asconf_lookup( 11628c2ecf20Sopenharmony_ci struct net *net, 11638c2ecf20Sopenharmony_ci struct sctp_chunkhdr *ch, 11648c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 11658c2ecf20Sopenharmony_ci __be16 peer_port, 11668c2ecf20Sopenharmony_ci struct sctp_transport **transportp) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci struct sctp_addip_chunk *asconf = (struct sctp_addip_chunk *)ch; 11698c2ecf20Sopenharmony_ci struct sctp_af *af; 11708c2ecf20Sopenharmony_ci union sctp_addr_param *param; 11718c2ecf20Sopenharmony_ci union sctp_addr paddr; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (ntohs(ch->length) < sizeof(*asconf) + sizeof(struct sctp_paramhdr)) 11748c2ecf20Sopenharmony_ci return NULL; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* Skip over the ADDIP header and find the Address parameter */ 11778c2ecf20Sopenharmony_ci param = (union sctp_addr_param *)(asconf + 1); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci af = sctp_get_af_specific(param_type2af(param->p.type)); 11808c2ecf20Sopenharmony_ci if (unlikely(!af)) 11818c2ecf20Sopenharmony_ci return NULL; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci if (!af->from_addr_param(&paddr, param, peer_port, 0)) 11848c2ecf20Sopenharmony_ci return NULL; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci return __sctp_lookup_association(net, laddr, &paddr, transportp); 11878c2ecf20Sopenharmony_ci} 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci/* SCTP-AUTH, Section 6.3: 11918c2ecf20Sopenharmony_ci* If the receiver does not find a STCB for a packet containing an AUTH 11928c2ecf20Sopenharmony_ci* chunk as the first chunk and not a COOKIE-ECHO chunk as the second 11938c2ecf20Sopenharmony_ci* chunk, it MUST use the chunks after the AUTH chunk to look up an existing 11948c2ecf20Sopenharmony_ci* association. 11958c2ecf20Sopenharmony_ci* 11968c2ecf20Sopenharmony_ci* This means that any chunks that can help us identify the association need 11978c2ecf20Sopenharmony_ci* to be looked at to find this association. 11988c2ecf20Sopenharmony_ci*/ 11998c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_rcv_walk_lookup(struct net *net, 12008c2ecf20Sopenharmony_ci struct sk_buff *skb, 12018c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 12028c2ecf20Sopenharmony_ci struct sctp_transport **transportp) 12038c2ecf20Sopenharmony_ci{ 12048c2ecf20Sopenharmony_ci struct sctp_association *asoc = NULL; 12058c2ecf20Sopenharmony_ci struct sctp_chunkhdr *ch; 12068c2ecf20Sopenharmony_ci int have_auth = 0; 12078c2ecf20Sopenharmony_ci unsigned int chunk_num = 1; 12088c2ecf20Sopenharmony_ci __u8 *ch_end; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci /* Walk through the chunks looking for AUTH or ASCONF chunks 12118c2ecf20Sopenharmony_ci * to help us find the association. 12128c2ecf20Sopenharmony_ci */ 12138c2ecf20Sopenharmony_ci ch = (struct sctp_chunkhdr *)skb->data; 12148c2ecf20Sopenharmony_ci do { 12158c2ecf20Sopenharmony_ci /* Break out if chunk length is less then minimal. */ 12168c2ecf20Sopenharmony_ci if (ntohs(ch->length) < sizeof(*ch)) 12178c2ecf20Sopenharmony_ci break; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length)); 12208c2ecf20Sopenharmony_ci if (ch_end > skb_tail_pointer(skb)) 12218c2ecf20Sopenharmony_ci break; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci switch (ch->type) { 12248c2ecf20Sopenharmony_ci case SCTP_CID_AUTH: 12258c2ecf20Sopenharmony_ci have_auth = chunk_num; 12268c2ecf20Sopenharmony_ci break; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci case SCTP_CID_COOKIE_ECHO: 12298c2ecf20Sopenharmony_ci /* If a packet arrives containing an AUTH chunk as 12308c2ecf20Sopenharmony_ci * a first chunk, a COOKIE-ECHO chunk as the second 12318c2ecf20Sopenharmony_ci * chunk, and possibly more chunks after them, and 12328c2ecf20Sopenharmony_ci * the receiver does not have an STCB for that 12338c2ecf20Sopenharmony_ci * packet, then authentication is based on 12348c2ecf20Sopenharmony_ci * the contents of the COOKIE- ECHO chunk. 12358c2ecf20Sopenharmony_ci */ 12368c2ecf20Sopenharmony_ci if (have_auth == 1 && chunk_num == 2) 12378c2ecf20Sopenharmony_ci return NULL; 12388c2ecf20Sopenharmony_ci break; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci case SCTP_CID_ASCONF: 12418c2ecf20Sopenharmony_ci if (have_auth || net->sctp.addip_noauth) 12428c2ecf20Sopenharmony_ci asoc = __sctp_rcv_asconf_lookup( 12438c2ecf20Sopenharmony_ci net, ch, laddr, 12448c2ecf20Sopenharmony_ci sctp_hdr(skb)->source, 12458c2ecf20Sopenharmony_ci transportp); 12468c2ecf20Sopenharmony_ci default: 12478c2ecf20Sopenharmony_ci break; 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci if (asoc) 12518c2ecf20Sopenharmony_ci break; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci ch = (struct sctp_chunkhdr *)ch_end; 12548c2ecf20Sopenharmony_ci chunk_num++; 12558c2ecf20Sopenharmony_ci } while (ch_end + sizeof(*ch) < skb_tail_pointer(skb)); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci return asoc; 12588c2ecf20Sopenharmony_ci} 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci/* 12618c2ecf20Sopenharmony_ci * There are circumstances when we need to look inside the SCTP packet 12628c2ecf20Sopenharmony_ci * for information to help us find the association. Examples 12638c2ecf20Sopenharmony_ci * include looking inside of INIT/INIT-ACK chunks or after the AUTH 12648c2ecf20Sopenharmony_ci * chunks. 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_rcv_lookup_harder(struct net *net, 12678c2ecf20Sopenharmony_ci struct sk_buff *skb, 12688c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 12698c2ecf20Sopenharmony_ci struct sctp_transport **transportp) 12708c2ecf20Sopenharmony_ci{ 12718c2ecf20Sopenharmony_ci struct sctp_chunkhdr *ch; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci /* We do not allow GSO frames here as we need to linearize and 12748c2ecf20Sopenharmony_ci * then cannot guarantee frame boundaries. This shouldn't be an 12758c2ecf20Sopenharmony_ci * issue as packets hitting this are mostly INIT or INIT-ACK and 12768c2ecf20Sopenharmony_ci * those cannot be on GSO-style anyway. 12778c2ecf20Sopenharmony_ci */ 12788c2ecf20Sopenharmony_ci if (skb_is_gso(skb) && skb_is_gso_sctp(skb)) 12798c2ecf20Sopenharmony_ci return NULL; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci ch = (struct sctp_chunkhdr *)skb->data; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci /* The code below will attempt to walk the chunk and extract 12848c2ecf20Sopenharmony_ci * parameter information. Before we do that, we need to verify 12858c2ecf20Sopenharmony_ci * that the chunk length doesn't cause overflow. Otherwise, we'll 12868c2ecf20Sopenharmony_ci * walk off the end. 12878c2ecf20Sopenharmony_ci */ 12888c2ecf20Sopenharmony_ci if (SCTP_PAD4(ntohs(ch->length)) > skb->len) 12898c2ecf20Sopenharmony_ci return NULL; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci /* If this is INIT/INIT-ACK look inside the chunk too. */ 12928c2ecf20Sopenharmony_ci if (ch->type == SCTP_CID_INIT || ch->type == SCTP_CID_INIT_ACK) 12938c2ecf20Sopenharmony_ci return __sctp_rcv_init_lookup(net, skb, laddr, transportp); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci return __sctp_rcv_walk_lookup(net, skb, laddr, transportp); 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci/* Lookup an association for an inbound skb. */ 12998c2ecf20Sopenharmony_cistatic struct sctp_association *__sctp_rcv_lookup(struct net *net, 13008c2ecf20Sopenharmony_ci struct sk_buff *skb, 13018c2ecf20Sopenharmony_ci const union sctp_addr *paddr, 13028c2ecf20Sopenharmony_ci const union sctp_addr *laddr, 13038c2ecf20Sopenharmony_ci struct sctp_transport **transportp) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci struct sctp_association *asoc; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci asoc = __sctp_lookup_association(net, laddr, paddr, transportp); 13088c2ecf20Sopenharmony_ci if (asoc) 13098c2ecf20Sopenharmony_ci goto out; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci /* Further lookup for INIT/INIT-ACK packets. 13128c2ecf20Sopenharmony_ci * SCTP Implementors Guide, 2.18 Handling of address 13138c2ecf20Sopenharmony_ci * parameters within the INIT or INIT-ACK. 13148c2ecf20Sopenharmony_ci */ 13158c2ecf20Sopenharmony_ci asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp); 13168c2ecf20Sopenharmony_ci if (asoc) 13178c2ecf20Sopenharmony_ci goto out; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci if (paddr->sa.sa_family == AF_INET) 13208c2ecf20Sopenharmony_ci pr_debug("sctp: asoc not found for src:%pI4:%d dst:%pI4:%d\n", 13218c2ecf20Sopenharmony_ci &laddr->v4.sin_addr, ntohs(laddr->v4.sin_port), 13228c2ecf20Sopenharmony_ci &paddr->v4.sin_addr, ntohs(paddr->v4.sin_port)); 13238c2ecf20Sopenharmony_ci else 13248c2ecf20Sopenharmony_ci pr_debug("sctp: asoc not found for src:%pI6:%d dst:%pI6:%d\n", 13258c2ecf20Sopenharmony_ci &laddr->v6.sin6_addr, ntohs(laddr->v6.sin6_port), 13268c2ecf20Sopenharmony_ci &paddr->v6.sin6_addr, ntohs(paddr->v6.sin6_port)); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ciout: 13298c2ecf20Sopenharmony_ci return asoc; 13308c2ecf20Sopenharmony_ci} 1331