18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* SCTP kernel implementation 38c2ecf20Sopenharmony_ci * (C) Copyright IBM Corp. 2001, 2004 48c2ecf20Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 58c2ecf20Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 68c2ecf20Sopenharmony_ci * Copyright (c) 2001-2002 Intel Corp. 78c2ecf20Sopenharmony_ci * Copyright (c) 2002 Nokia Corp. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This is part of the SCTP Linux Kernel Implementation. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * These are the state functions for the state machine. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Please send any bug reports or fixes you make to the 148c2ecf20Sopenharmony_ci * email address(es): 158c2ecf20Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Written or modified by: 188c2ecf20Sopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 198c2ecf20Sopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 208c2ecf20Sopenharmony_ci * Mathew Kotowsky <kotowsky@sctp.org> 218c2ecf20Sopenharmony_ci * Sridhar Samudrala <samudrala@us.ibm.com> 228c2ecf20Sopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 238c2ecf20Sopenharmony_ci * Hui Huang <hui.huang@nokia.com> 248c2ecf20Sopenharmony_ci * Dajiang Zhang <dajiang.zhang@nokia.com> 258c2ecf20Sopenharmony_ci * Daisy Chang <daisyc@us.ibm.com> 268c2ecf20Sopenharmony_ci * Ardelle Fan <ardelle.fan@intel.com> 278c2ecf20Sopenharmony_ci * Ryan Layer <rmlayer@us.ibm.com> 288c2ecf20Sopenharmony_ci * Kevin Gao <kevin.gao@intel.com> 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <linux/types.h> 348c2ecf20Sopenharmony_ci#include <linux/kernel.h> 358c2ecf20Sopenharmony_ci#include <linux/ip.h> 368c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 378c2ecf20Sopenharmony_ci#include <linux/net.h> 388c2ecf20Sopenharmony_ci#include <linux/inet.h> 398c2ecf20Sopenharmony_ci#include <linux/slab.h> 408c2ecf20Sopenharmony_ci#include <net/sock.h> 418c2ecf20Sopenharmony_ci#include <net/inet_ecn.h> 428c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 438c2ecf20Sopenharmony_ci#include <net/sctp/sctp.h> 448c2ecf20Sopenharmony_ci#include <net/sctp/sm.h> 458c2ecf20Sopenharmony_ci#include <net/sctp/structs.h> 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS 488c2ecf20Sopenharmony_ci#include <trace/events/sctp.h> 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic struct sctp_packet *sctp_abort_pkt_new( 518c2ecf20Sopenharmony_ci struct net *net, 528c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 538c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 548c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 558c2ecf20Sopenharmony_ci const void *payload, size_t paylen); 568c2ecf20Sopenharmony_cistatic int sctp_eat_data(const struct sctp_association *asoc, 578c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 588c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 598c2ecf20Sopenharmony_cistatic struct sctp_packet *sctp_ootb_pkt_new( 608c2ecf20Sopenharmony_ci struct net *net, 618c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 628c2ecf20Sopenharmony_ci const struct sctp_chunk *chunk); 638c2ecf20Sopenharmony_cistatic void sctp_send_stale_cookie_err(struct net *net, 648c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 658c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 668c2ecf20Sopenharmony_ci const struct sctp_chunk *chunk, 678c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 688c2ecf20Sopenharmony_ci struct sctp_chunk *err_chunk); 698c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_5_2_6_stale( 708c2ecf20Sopenharmony_ci struct net *net, 718c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 728c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 738c2ecf20Sopenharmony_ci const union sctp_subtype type, 748c2ecf20Sopenharmony_ci void *arg, 758c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 768c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_shut_8_4_5( 778c2ecf20Sopenharmony_ci struct net *net, 788c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 798c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 808c2ecf20Sopenharmony_ci const union sctp_subtype type, 818c2ecf20Sopenharmony_ci void *arg, 828c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 838c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_tabort_8_4_8( 848c2ecf20Sopenharmony_ci struct net *net, 858c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 868c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 878c2ecf20Sopenharmony_ci const union sctp_subtype type, 888c2ecf20Sopenharmony_ci void *arg, 898c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 908c2ecf20Sopenharmony_cistatic struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_stop_t1_and_abort( 938c2ecf20Sopenharmony_ci struct net *net, 948c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 958c2ecf20Sopenharmony_ci __be16 error, int sk_err, 968c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 978c2ecf20Sopenharmony_ci struct sctp_transport *transport); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_abort_violation( 1008c2ecf20Sopenharmony_ci struct net *net, 1018c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 1028c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1038c2ecf20Sopenharmony_ci void *arg, 1048c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 1058c2ecf20Sopenharmony_ci const __u8 *payload, 1068c2ecf20Sopenharmony_ci const size_t paylen); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunklen( 1098c2ecf20Sopenharmony_ci struct net *net, 1108c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 1118c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1128c2ecf20Sopenharmony_ci const union sctp_subtype type, 1138c2ecf20Sopenharmony_ci void *arg, 1148c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_paramlen( 1178c2ecf20Sopenharmony_ci struct net *net, 1188c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 1198c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1208c2ecf20Sopenharmony_ci const union sctp_subtype type, 1218c2ecf20Sopenharmony_ci void *arg, void *ext, 1228c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_ctsn( 1258c2ecf20Sopenharmony_ci struct net *net, 1268c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 1278c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1288c2ecf20Sopenharmony_ci const union sctp_subtype type, 1298c2ecf20Sopenharmony_ci void *arg, 1308c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunk( 1338c2ecf20Sopenharmony_ci struct net *net, 1348c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 1358c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1368c2ecf20Sopenharmony_ci const union sctp_subtype type, 1378c2ecf20Sopenharmony_ci void *arg, 1388c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic enum sctp_ierror sctp_sf_authenticate( 1418c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1428c2ecf20Sopenharmony_ci struct sctp_chunk *chunk); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic enum sctp_disposition __sctp_sf_do_9_1_abort( 1458c2ecf20Sopenharmony_ci struct net *net, 1468c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 1478c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1488c2ecf20Sopenharmony_ci const union sctp_subtype type, 1498c2ecf20Sopenharmony_ci void *arg, 1508c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic enum sctp_disposition 1538c2ecf20Sopenharmony_ci__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, 1548c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 1558c2ecf20Sopenharmony_ci const union sctp_subtype type, void *arg, 1568c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* Small helper function that checks if the chunk length 1598c2ecf20Sopenharmony_ci * is of the appropriate length. The 'required_length' argument 1608c2ecf20Sopenharmony_ci * is set to be the size of a specific chunk we are testing. 1618c2ecf20Sopenharmony_ci * Return Values: true = Valid length 1628c2ecf20Sopenharmony_ci * false = Invalid length 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_cistatic inline bool sctp_chunk_length_valid(struct sctp_chunk *chunk, 1668c2ecf20Sopenharmony_ci __u16 required_length) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci __u16 chunk_length = ntohs(chunk->chunk_hdr->length); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* Previously already marked? */ 1718c2ecf20Sopenharmony_ci if (unlikely(chunk->pdiscard)) 1728c2ecf20Sopenharmony_ci return false; 1738c2ecf20Sopenharmony_ci if (unlikely(chunk_length < required_length)) 1748c2ecf20Sopenharmony_ci return false; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci return true; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/* Check for format error in an ABORT chunk */ 1808c2ecf20Sopenharmony_cistatic inline bool sctp_err_chunk_valid(struct sctp_chunk *chunk) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci struct sctp_errhdr *err; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci sctp_walk_errors(err, chunk->chunk_hdr); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci return (void *)err == (void *)chunk->chunk_end; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci/********************************************************** 1908c2ecf20Sopenharmony_ci * These are the state functions for handling chunk events. 1918c2ecf20Sopenharmony_ci **********************************************************/ 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci/* 1948c2ecf20Sopenharmony_ci * Process the final SHUTDOWN COMPLETE. 1958c2ecf20Sopenharmony_ci * 1968c2ecf20Sopenharmony_ci * Section: 4 (C) (diagram), 9.2 1978c2ecf20Sopenharmony_ci * Upon reception of the SHUTDOWN COMPLETE chunk the endpoint will verify 1988c2ecf20Sopenharmony_ci * that it is in SHUTDOWN-ACK-SENT state, if it is not the chunk should be 1998c2ecf20Sopenharmony_ci * discarded. If the endpoint is in the SHUTDOWN-ACK-SENT state the endpoint 2008c2ecf20Sopenharmony_ci * should stop the T2-shutdown timer and remove all knowledge of the 2018c2ecf20Sopenharmony_ci * association (and thus the association enters the CLOSED state). 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * Verification Tag: 8.5.1(C), sctpimpguide 2.41. 2048c2ecf20Sopenharmony_ci * C) Rules for packet carrying SHUTDOWN COMPLETE: 2058c2ecf20Sopenharmony_ci * ... 2068c2ecf20Sopenharmony_ci * - The receiver of a SHUTDOWN COMPLETE shall accept the packet 2078c2ecf20Sopenharmony_ci * if the Verification Tag field of the packet matches its own tag and 2088c2ecf20Sopenharmony_ci * the T bit is not set 2098c2ecf20Sopenharmony_ci * OR 2108c2ecf20Sopenharmony_ci * it is set to its peer's tag and the T bit is set in the Chunk 2118c2ecf20Sopenharmony_ci * Flags. 2128c2ecf20Sopenharmony_ci * Otherwise, the receiver MUST silently discard the packet 2138c2ecf20Sopenharmony_ci * and take no further action. An endpoint MUST ignore the 2148c2ecf20Sopenharmony_ci * SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state. 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Inputs 2178c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * Outputs 2208c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 2218c2ecf20Sopenharmony_ci * 2228c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_4_C(struct net *net, 2258c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 2268c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 2278c2ecf20Sopenharmony_ci const union sctp_subtype type, 2288c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 2318c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 2348c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* RFC 2960 6.10 Bundling 2378c2ecf20Sopenharmony_ci * 2388c2ecf20Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 2398c2ecf20Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 2408c2ecf20Sopenharmony_ci */ 2418c2ecf20Sopenharmony_ci if (!chunk->singleton) 2428c2ecf20Sopenharmony_ci return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */ 2458c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 2468c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 2478c2ecf20Sopenharmony_ci commands); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* RFC 2960 10.2 SCTP-to-ULP 2508c2ecf20Sopenharmony_ci * 2518c2ecf20Sopenharmony_ci * H) SHUTDOWN COMPLETE notification 2528c2ecf20Sopenharmony_ci * 2538c2ecf20Sopenharmony_ci * When SCTP completes the shutdown procedures (section 9.2) this 2548c2ecf20Sopenharmony_ci * notification is passed to the upper layer. 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, 2578c2ecf20Sopenharmony_ci 0, 0, 0, NULL, GFP_ATOMIC); 2588c2ecf20Sopenharmony_ci if (ev) 2598c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 2608c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ev)); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint 2638c2ecf20Sopenharmony_ci * will verify that it is in SHUTDOWN-ACK-SENT state, if it is 2648c2ecf20Sopenharmony_ci * not the chunk should be discarded. If the endpoint is in 2658c2ecf20Sopenharmony_ci * the SHUTDOWN-ACK-SENT state the endpoint should stop the 2668c2ecf20Sopenharmony_ci * T2-shutdown timer and remove all knowledge of the 2678c2ecf20Sopenharmony_ci * association (and thus the association enters the CLOSED 2688c2ecf20Sopenharmony_ci * state). 2698c2ecf20Sopenharmony_ci */ 2708c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 2718c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 2748c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 2778c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); 2808c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci/* 2888c2ecf20Sopenharmony_ci * Respond to a normal INIT chunk. 2898c2ecf20Sopenharmony_ci * We are the side that is being asked for an association. 2908c2ecf20Sopenharmony_ci * 2918c2ecf20Sopenharmony_ci * Section: 5.1 Normal Establishment of an Association, B 2928c2ecf20Sopenharmony_ci * B) "Z" shall respond immediately with an INIT ACK chunk. The 2938c2ecf20Sopenharmony_ci * destination IP address of the INIT ACK MUST be set to the source 2948c2ecf20Sopenharmony_ci * IP address of the INIT to which this INIT ACK is responding. In 2958c2ecf20Sopenharmony_ci * the response, besides filling in other parameters, "Z" must set the 2968c2ecf20Sopenharmony_ci * Verification Tag field to Tag_A, and also provide its own 2978c2ecf20Sopenharmony_ci * Verification Tag (Tag_Z) in the Initiate Tag field. 2988c2ecf20Sopenharmony_ci * 2998c2ecf20Sopenharmony_ci * Verification Tag: Must be 0. 3008c2ecf20Sopenharmony_ci * 3018c2ecf20Sopenharmony_ci * Inputs 3028c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 3038c2ecf20Sopenharmony_ci * 3048c2ecf20Sopenharmony_ci * Outputs 3058c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 3068c2ecf20Sopenharmony_ci * 3078c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 3088c2ecf20Sopenharmony_ci */ 3098c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1B_init(struct net *net, 3108c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 3118c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 3128c2ecf20Sopenharmony_ci const union sctp_subtype type, 3138c2ecf20Sopenharmony_ci void *arg, 3148c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg, *repl, *err_chunk; 3178c2ecf20Sopenharmony_ci struct sctp_unrecognized_param *unk_param; 3188c2ecf20Sopenharmony_ci struct sctp_association *new_asoc; 3198c2ecf20Sopenharmony_ci struct sctp_packet *packet; 3208c2ecf20Sopenharmony_ci int len; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Update socket peer label if first association. */ 3238c2ecf20Sopenharmony_ci if (security_sctp_assoc_request((struct sctp_endpoint *)ep, 3248c2ecf20Sopenharmony_ci chunk->skb)) 3258c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* 6.10 Bundling 3288c2ecf20Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 3298c2ecf20Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 3308c2ecf20Sopenharmony_ci * 3318c2ecf20Sopenharmony_ci * IG Section 2.11.2 3328c2ecf20Sopenharmony_ci * Furthermore, we require that the receiver of an INIT chunk MUST 3338c2ecf20Sopenharmony_ci * enforce these rules by silently discarding an arriving packet 3348c2ecf20Sopenharmony_ci * with an INIT chunk that is bundled with other chunks. 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_ci if (!chunk->singleton) 3378c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* Make sure that the INIT chunk has a valid length. 3408c2ecf20Sopenharmony_ci * Normally, this would cause an ABORT with a Protocol Violation 3418c2ecf20Sopenharmony_ci * error, but since we don't have an association, we'll 3428c2ecf20Sopenharmony_ci * just discard the packet. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) 3458c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci /* If the packet is an OOTB packet which is temporarily on the 3488c2ecf20Sopenharmony_ci * control endpoint, respond with an ABORT. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci if (ep == sctp_sk(net->sctp.ctl_sock)->ep) { 3518c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 3528c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* 3.1 A packet containing an INIT chunk MUST have a zero Verification 3568c2ecf20Sopenharmony_ci * Tag. 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_ci if (chunk->sctp_hdr->vtag != 0) 3598c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* If the INIT is coming toward a closing socket, we'll send back 3628c2ecf20Sopenharmony_ci * and ABORT. Essentially, this catches the race of INIT being 3638c2ecf20Sopenharmony_ci * backloged to the socket at the same time as the user isses close(). 3648c2ecf20Sopenharmony_ci * Since the socket and all its associations are going away, we 3658c2ecf20Sopenharmony_ci * can treat this OOTB 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ci if (sctp_sstate(ep->base.sk, CLOSING)) 3688c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* Verify the INIT chunk before processing it. */ 3718c2ecf20Sopenharmony_ci err_chunk = NULL; 3728c2ecf20Sopenharmony_ci if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, 3738c2ecf20Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, chunk, 3748c2ecf20Sopenharmony_ci &err_chunk)) { 3758c2ecf20Sopenharmony_ci /* This chunk contains fatal error. It is to be discarded. 3768c2ecf20Sopenharmony_ci * Send an ABORT, with causes if there is any. 3778c2ecf20Sopenharmony_ci */ 3788c2ecf20Sopenharmony_ci if (err_chunk) { 3798c2ecf20Sopenharmony_ci packet = sctp_abort_pkt_new(net, ep, asoc, arg, 3808c2ecf20Sopenharmony_ci (__u8 *)(err_chunk->chunk_hdr) + 3818c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr), 3828c2ecf20Sopenharmony_ci ntohs(err_chunk->chunk_hdr->length) - 3838c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci sctp_chunk_free(err_chunk); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (packet) { 3888c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 3898c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 3908c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 3918c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 3928c2ecf20Sopenharmony_ci } else { 3938c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci } else { 3968c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, 3978c2ecf20Sopenharmony_ci commands); 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* Grab the INIT header. */ 4028c2ecf20Sopenharmony_ci chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* Tag the variable length parameters. */ 4058c2ecf20Sopenharmony_ci chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(struct sctp_inithdr)); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC); 4088c2ecf20Sopenharmony_ci if (!new_asoc) 4098c2ecf20Sopenharmony_ci goto nomem; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (sctp_assoc_set_bind_addr_from_ep(new_asoc, 4128c2ecf20Sopenharmony_ci sctp_scope(sctp_source(chunk)), 4138c2ecf20Sopenharmony_ci GFP_ATOMIC) < 0) 4148c2ecf20Sopenharmony_ci goto nomem_init; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci /* The call, sctp_process_init(), can fail on memory allocation. */ 4178c2ecf20Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), 4188c2ecf20Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, 4198c2ecf20Sopenharmony_ci GFP_ATOMIC)) 4208c2ecf20Sopenharmony_ci goto nomem_init; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* B) "Z" shall respond immediately with an INIT ACK chunk. */ 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 4258c2ecf20Sopenharmony_ci * make sure to reserve enough room in the INIT ACK for them. 4268c2ecf20Sopenharmony_ci */ 4278c2ecf20Sopenharmony_ci len = 0; 4288c2ecf20Sopenharmony_ci if (err_chunk) 4298c2ecf20Sopenharmony_ci len = ntohs(err_chunk->chunk_hdr->length) - 4308c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); 4338c2ecf20Sopenharmony_ci if (!repl) 4348c2ecf20Sopenharmony_ci goto nomem_init; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 4378c2ecf20Sopenharmony_ci * include them in the outgoing INIT ACK as "Unrecognized parameter" 4388c2ecf20Sopenharmony_ci * parameter. 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci if (err_chunk) { 4418c2ecf20Sopenharmony_ci /* Get the "Unrecognized parameter" parameter(s) out of the 4428c2ecf20Sopenharmony_ci * ERROR chunk generated by sctp_verify_init(). Since the 4438c2ecf20Sopenharmony_ci * error cause code for "unknown parameter" and the 4448c2ecf20Sopenharmony_ci * "Unrecognized parameter" type is the same, we can 4458c2ecf20Sopenharmony_ci * construct the parameters in INIT ACK by copying the 4468c2ecf20Sopenharmony_ci * ERROR causes over. 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci unk_param = (struct sctp_unrecognized_param *) 4498c2ecf20Sopenharmony_ci ((__u8 *)(err_chunk->chunk_hdr) + 4508c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 4518c2ecf20Sopenharmony_ci /* Replace the cause code with the "Unrecognized parameter" 4528c2ecf20Sopenharmony_ci * parameter type. 4538c2ecf20Sopenharmony_ci */ 4548c2ecf20Sopenharmony_ci sctp_addto_chunk(repl, len, unk_param); 4558c2ecf20Sopenharmony_ci sctp_chunk_free(err_chunk); 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* 4638c2ecf20Sopenharmony_ci * Note: After sending out INIT ACK with the State Cookie parameter, 4648c2ecf20Sopenharmony_ci * "Z" MUST NOT allocate any resources, nor keep any states for the 4658c2ecf20Sopenharmony_ci * new association. Otherwise, "Z" will be vulnerable to resource 4668c2ecf20Sopenharmony_ci * attacks. 4678c2ecf20Sopenharmony_ci */ 4688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cinomem_init: 4738c2ecf20Sopenharmony_ci sctp_association_free(new_asoc); 4748c2ecf20Sopenharmony_cinomem: 4758c2ecf20Sopenharmony_ci if (err_chunk) 4768c2ecf20Sopenharmony_ci sctp_chunk_free(err_chunk); 4778c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/* 4818c2ecf20Sopenharmony_ci * Respond to a normal INIT ACK chunk. 4828c2ecf20Sopenharmony_ci * We are the side that is initiating the association. 4838c2ecf20Sopenharmony_ci * 4848c2ecf20Sopenharmony_ci * Section: 5.1 Normal Establishment of an Association, C 4858c2ecf20Sopenharmony_ci * C) Upon reception of the INIT ACK from "Z", "A" shall stop the T1-init 4868c2ecf20Sopenharmony_ci * timer and leave COOKIE-WAIT state. "A" shall then send the State 4878c2ecf20Sopenharmony_ci * Cookie received in the INIT ACK chunk in a COOKIE ECHO chunk, start 4888c2ecf20Sopenharmony_ci * the T1-cookie timer, and enter the COOKIE-ECHOED state. 4898c2ecf20Sopenharmony_ci * 4908c2ecf20Sopenharmony_ci * Note: The COOKIE ECHO chunk can be bundled with any pending outbound 4918c2ecf20Sopenharmony_ci * DATA chunks, but it MUST be the first chunk in the packet and 4928c2ecf20Sopenharmony_ci * until the COOKIE ACK is returned the sender MUST NOT send any 4938c2ecf20Sopenharmony_ci * other packets to the peer. 4948c2ecf20Sopenharmony_ci * 4958c2ecf20Sopenharmony_ci * Verification Tag: 3.3.3 4968c2ecf20Sopenharmony_ci * If the value of the Initiate Tag in a received INIT ACK chunk is 4978c2ecf20Sopenharmony_ci * found to be 0, the receiver MUST treat it as an error and close the 4988c2ecf20Sopenharmony_ci * association by transmitting an ABORT. 4998c2ecf20Sopenharmony_ci * 5008c2ecf20Sopenharmony_ci * Inputs 5018c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 5028c2ecf20Sopenharmony_ci * 5038c2ecf20Sopenharmony_ci * Outputs 5048c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 5058c2ecf20Sopenharmony_ci * 5068c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 5078c2ecf20Sopenharmony_ci */ 5088c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net, 5098c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 5108c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 5118c2ecf20Sopenharmony_ci const union sctp_subtype type, 5128c2ecf20Sopenharmony_ci void *arg, 5138c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct sctp_init_chunk *initchunk; 5168c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 5178c2ecf20Sopenharmony_ci struct sctp_chunk *err_chunk; 5188c2ecf20Sopenharmony_ci struct sctp_packet *packet; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 5218c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* 6.10 Bundling 5248c2ecf20Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 5258c2ecf20Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 5268c2ecf20Sopenharmony_ci */ 5278c2ecf20Sopenharmony_ci if (!chunk->singleton) 5288c2ecf20Sopenharmony_ci return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* Make sure that the INIT-ACK chunk has a valid length */ 5318c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_initack_chunk))) 5328c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 5338c2ecf20Sopenharmony_ci commands); 5348c2ecf20Sopenharmony_ci /* Grab the INIT header. */ 5358c2ecf20Sopenharmony_ci chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* Verify the INIT chunk before processing it. */ 5388c2ecf20Sopenharmony_ci err_chunk = NULL; 5398c2ecf20Sopenharmony_ci if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, 5408c2ecf20Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, chunk, 5418c2ecf20Sopenharmony_ci &err_chunk)) { 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci enum sctp_error error = SCTP_ERROR_NO_RESOURCE; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* This chunk contains fatal error. It is to be discarded. 5468c2ecf20Sopenharmony_ci * Send an ABORT, with causes. If there are no causes, 5478c2ecf20Sopenharmony_ci * then there wasn't enough memory. Just terminate 5488c2ecf20Sopenharmony_ci * the association. 5498c2ecf20Sopenharmony_ci */ 5508c2ecf20Sopenharmony_ci if (err_chunk) { 5518c2ecf20Sopenharmony_ci packet = sctp_abort_pkt_new(net, ep, asoc, arg, 5528c2ecf20Sopenharmony_ci (__u8 *)(err_chunk->chunk_hdr) + 5538c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr), 5548c2ecf20Sopenharmony_ci ntohs(err_chunk->chunk_hdr->length) - 5558c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci sctp_chunk_free(err_chunk); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci if (packet) { 5608c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 5618c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 5628c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 5638c2ecf20Sopenharmony_ci error = SCTP_ERROR_INV_PARAM; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci /* SCTP-AUTH, Section 6.3: 5688c2ecf20Sopenharmony_ci * It should be noted that if the receiver wants to tear 5698c2ecf20Sopenharmony_ci * down an association in an authenticated way only, the 5708c2ecf20Sopenharmony_ci * handling of malformed packets should not result in 5718c2ecf20Sopenharmony_ci * tearing down the association. 5728c2ecf20Sopenharmony_ci * 5738c2ecf20Sopenharmony_ci * This means that if we only want to abort associations 5748c2ecf20Sopenharmony_ci * in an authenticated way (i.e AUTH+ABORT), then we 5758c2ecf20Sopenharmony_ci * can't destroy this association just because the packet 5768c2ecf20Sopenharmony_ci * was malformed. 5778c2ecf20Sopenharmony_ci */ 5788c2ecf20Sopenharmony_ci if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 5798c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 5828c2ecf20Sopenharmony_ci return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, 5838c2ecf20Sopenharmony_ci asoc, chunk->transport); 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /* Tag the variable length parameters. Note that we never 5878c2ecf20Sopenharmony_ci * convert the parameters in an INIT chunk. 5888c2ecf20Sopenharmony_ci */ 5898c2ecf20Sopenharmony_ci chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(struct sctp_inithdr)); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci initchunk = (struct sctp_init_chunk *)chunk->chunk_hdr; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, 5948c2ecf20Sopenharmony_ci SCTP_PEER_INIT(initchunk)); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci /* Reset init error count upon receipt of INIT-ACK. */ 5978c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* 5.1 C) "A" shall stop the T1-init timer and leave 6008c2ecf20Sopenharmony_ci * COOKIE-WAIT state. "A" shall then ... start the T1-cookie 6018c2ecf20Sopenharmony_ci * timer, and enter the COOKIE-ECHOED state. 6028c2ecf20Sopenharmony_ci */ 6038c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 6048c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 6058c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 6068c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 6078c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 6088c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_COOKIE_ECHOED)); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci /* SCTP-AUTH: genereate the assocition shared keys so that 6118c2ecf20Sopenharmony_ci * we can potentially signe the COOKIE-ECHO. 6128c2ecf20Sopenharmony_ci */ 6138c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_SHKEY, SCTP_NULL()); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* 5.1 C) "A" shall then send the State Cookie received in the 6168c2ecf20Sopenharmony_ci * INIT ACK chunk in a COOKIE ECHO chunk, ... 6178c2ecf20Sopenharmony_ci */ 6188c2ecf20Sopenharmony_ci /* If there is any errors to report, send the ERROR chunk generated 6198c2ecf20Sopenharmony_ci * for unknown parameters as well. 6208c2ecf20Sopenharmony_ci */ 6218c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_COOKIE_ECHO, 6228c2ecf20Sopenharmony_ci SCTP_CHUNK(err_chunk)); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, 6288c2ecf20Sopenharmony_ci const struct sctp_association *asoc) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci struct sctp_chunk auth; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci if (!chunk->auth_chunk) 6338c2ecf20Sopenharmony_ci return true; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo 6368c2ecf20Sopenharmony_ci * is supposed to be authenticated and we have to do delayed 6378c2ecf20Sopenharmony_ci * authentication. We've just recreated the association using 6388c2ecf20Sopenharmony_ci * the information in the cookie and now it's much easier to 6398c2ecf20Sopenharmony_ci * do the authentication. 6408c2ecf20Sopenharmony_ci */ 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* Make sure that we and the peer are AUTH capable */ 6438c2ecf20Sopenharmony_ci if (!net->sctp.auth_enable || !asoc->peer.auth_capable) 6448c2ecf20Sopenharmony_ci return false; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci /* set-up our fake chunk so that we can process it */ 6478c2ecf20Sopenharmony_ci auth.skb = chunk->auth_chunk; 6488c2ecf20Sopenharmony_ci auth.asoc = chunk->asoc; 6498c2ecf20Sopenharmony_ci auth.sctp_hdr = chunk->sctp_hdr; 6508c2ecf20Sopenharmony_ci auth.chunk_hdr = (struct sctp_chunkhdr *) 6518c2ecf20Sopenharmony_ci skb_push(chunk->auth_chunk, 6528c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 6538c2ecf20Sopenharmony_ci skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr)); 6548c2ecf20Sopenharmony_ci auth.transport = chunk->transport; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR; 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci/* 6608c2ecf20Sopenharmony_ci * Respond to a normal COOKIE ECHO chunk. 6618c2ecf20Sopenharmony_ci * We are the side that is being asked for an association. 6628c2ecf20Sopenharmony_ci * 6638c2ecf20Sopenharmony_ci * Section: 5.1 Normal Establishment of an Association, D 6648c2ecf20Sopenharmony_ci * D) Upon reception of the COOKIE ECHO chunk, Endpoint "Z" will reply 6658c2ecf20Sopenharmony_ci * with a COOKIE ACK chunk after building a TCB and moving to 6668c2ecf20Sopenharmony_ci * the ESTABLISHED state. A COOKIE ACK chunk may be bundled with 6678c2ecf20Sopenharmony_ci * any pending DATA chunks (and/or SACK chunks), but the COOKIE ACK 6688c2ecf20Sopenharmony_ci * chunk MUST be the first chunk in the packet. 6698c2ecf20Sopenharmony_ci * 6708c2ecf20Sopenharmony_ci * IMPLEMENTATION NOTE: An implementation may choose to send the 6718c2ecf20Sopenharmony_ci * Communication Up notification to the SCTP user upon reception 6728c2ecf20Sopenharmony_ci * of a valid COOKIE ECHO chunk. 6738c2ecf20Sopenharmony_ci * 6748c2ecf20Sopenharmony_ci * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules 6758c2ecf20Sopenharmony_ci * D) Rules for packet carrying a COOKIE ECHO 6768c2ecf20Sopenharmony_ci * 6778c2ecf20Sopenharmony_ci * - When sending a COOKIE ECHO, the endpoint MUST use the value of the 6788c2ecf20Sopenharmony_ci * Initial Tag received in the INIT ACK. 6798c2ecf20Sopenharmony_ci * 6808c2ecf20Sopenharmony_ci * - The receiver of a COOKIE ECHO follows the procedures in Section 5. 6818c2ecf20Sopenharmony_ci * 6828c2ecf20Sopenharmony_ci * Inputs 6838c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 6848c2ecf20Sopenharmony_ci * 6858c2ecf20Sopenharmony_ci * Outputs 6868c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 6878c2ecf20Sopenharmony_ci * 6888c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 6898c2ecf20Sopenharmony_ci */ 6908c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net, 6918c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 6928c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 6938c2ecf20Sopenharmony_ci const union sctp_subtype type, 6948c2ecf20Sopenharmony_ci void *arg, 6958c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev, *ai_ev = NULL, *auth_ev = NULL; 6988c2ecf20Sopenharmony_ci struct sctp_association *new_asoc; 6998c2ecf20Sopenharmony_ci struct sctp_init_chunk *peer_init; 7008c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 7018c2ecf20Sopenharmony_ci struct sctp_chunk *err_chk_p; 7028c2ecf20Sopenharmony_ci struct sctp_chunk *repl; 7038c2ecf20Sopenharmony_ci struct sock *sk; 7048c2ecf20Sopenharmony_ci int error = 0; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci if (asoc && !sctp_vtag_verify(chunk, asoc)) 7078c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci /* If the packet is an OOTB packet which is temporarily on the 7108c2ecf20Sopenharmony_ci * control endpoint, respond with an ABORT. 7118c2ecf20Sopenharmony_ci */ 7128c2ecf20Sopenharmony_ci if (ep == sctp_sk(net->sctp.ctl_sock)->ep) { 7138c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 7148c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci /* Make sure that the COOKIE_ECHO chunk has a valid length. 7188c2ecf20Sopenharmony_ci * In this case, we check that we have enough for at least a 7198c2ecf20Sopenharmony_ci * chunk header. More detailed verification is done 7208c2ecf20Sopenharmony_ci * in sctp_unpack_cookie(). 7218c2ecf20Sopenharmony_ci */ 7228c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 7238c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 7248c2ecf20Sopenharmony_ci commands); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* If the endpoint is not listening or if the number of associations 7278c2ecf20Sopenharmony_ci * on the TCP-style socket exceed the max backlog, respond with an 7288c2ecf20Sopenharmony_ci * ABORT. 7298c2ecf20Sopenharmony_ci */ 7308c2ecf20Sopenharmony_ci sk = ep->base.sk; 7318c2ecf20Sopenharmony_ci if (!sctp_sstate(sk, LISTENING) || 7328c2ecf20Sopenharmony_ci (sctp_style(sk, TCP) && sk_acceptq_is_full(sk))) 7338c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci /* "Decode" the chunk. We have no optional parameters so we 7368c2ecf20Sopenharmony_ci * are in good shape. 7378c2ecf20Sopenharmony_ci */ 7388c2ecf20Sopenharmony_ci chunk->subh.cookie_hdr = 7398c2ecf20Sopenharmony_ci (struct sctp_signed_cookie *)chunk->skb->data; 7408c2ecf20Sopenharmony_ci if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - 7418c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr))) 7428c2ecf20Sopenharmony_ci goto nomem; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci /* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint 7458c2ecf20Sopenharmony_ci * "Z" will reply with a COOKIE ACK chunk after building a TCB 7468c2ecf20Sopenharmony_ci * and moving to the ESTABLISHED state. 7478c2ecf20Sopenharmony_ci */ 7488c2ecf20Sopenharmony_ci new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error, 7498c2ecf20Sopenharmony_ci &err_chk_p); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* FIXME: 7528c2ecf20Sopenharmony_ci * If the re-build failed, what is the proper error path 7538c2ecf20Sopenharmony_ci * from here? 7548c2ecf20Sopenharmony_ci * 7558c2ecf20Sopenharmony_ci * [We should abort the association. --piggy] 7568c2ecf20Sopenharmony_ci */ 7578c2ecf20Sopenharmony_ci if (!new_asoc) { 7588c2ecf20Sopenharmony_ci /* FIXME: Several errors are possible. A bad cookie should 7598c2ecf20Sopenharmony_ci * be silently discarded, but think about logging it too. 7608c2ecf20Sopenharmony_ci */ 7618c2ecf20Sopenharmony_ci switch (error) { 7628c2ecf20Sopenharmony_ci case -SCTP_IERROR_NOMEM: 7638c2ecf20Sopenharmony_ci goto nomem; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci case -SCTP_IERROR_STALE_COOKIE: 7668c2ecf20Sopenharmony_ci sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands, 7678c2ecf20Sopenharmony_ci err_chk_p); 7688c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci case -SCTP_IERROR_BAD_SIG: 7718c2ecf20Sopenharmony_ci default: 7728c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci /* Delay state machine commands until later. 7788c2ecf20Sopenharmony_ci * 7798c2ecf20Sopenharmony_ci * Re-build the bind address for the association is done in 7808c2ecf20Sopenharmony_ci * the sctp_unpack_cookie() already. 7818c2ecf20Sopenharmony_ci */ 7828c2ecf20Sopenharmony_ci /* This is a brand-new association, so these are not yet side 7838c2ecf20Sopenharmony_ci * effects--it is safe to run them here. 7848c2ecf20Sopenharmony_ci */ 7858c2ecf20Sopenharmony_ci peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, 7888c2ecf20Sopenharmony_ci &chunk->subh.cookie_hdr->c.peer_addr, 7898c2ecf20Sopenharmony_ci peer_init, GFP_ATOMIC)) 7908c2ecf20Sopenharmony_ci goto nomem_init; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci /* SCTP-AUTH: Now that we've populate required fields in 7938c2ecf20Sopenharmony_ci * sctp_process_init, set up the assocaition shared keys as 7948c2ecf20Sopenharmony_ci * necessary so that we can potentially authenticate the ACK 7958c2ecf20Sopenharmony_ci */ 7968c2ecf20Sopenharmony_ci error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC); 7978c2ecf20Sopenharmony_ci if (error) 7988c2ecf20Sopenharmony_ci goto nomem_init; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) { 8018c2ecf20Sopenharmony_ci sctp_association_free(new_asoc); 8028c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 8038c2ecf20Sopenharmony_ci } 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci repl = sctp_make_cookie_ack(new_asoc, chunk); 8068c2ecf20Sopenharmony_ci if (!repl) 8078c2ecf20Sopenharmony_ci goto nomem_init; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 8108c2ecf20Sopenharmony_ci * 8118c2ecf20Sopenharmony_ci * D) IMPLEMENTATION NOTE: An implementation may choose to 8128c2ecf20Sopenharmony_ci * send the Communication Up notification to the SCTP user 8138c2ecf20Sopenharmony_ci * upon reception of a valid COOKIE ECHO chunk. 8148c2ecf20Sopenharmony_ci */ 8158c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, SCTP_COMM_UP, 0, 8168c2ecf20Sopenharmony_ci new_asoc->c.sinit_num_ostreams, 8178c2ecf20Sopenharmony_ci new_asoc->c.sinit_max_instreams, 8188c2ecf20Sopenharmony_ci NULL, GFP_ATOMIC); 8198c2ecf20Sopenharmony_ci if (!ev) 8208c2ecf20Sopenharmony_ci goto nomem_ev; 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 8238c2ecf20Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter , SCTP 8248c2ecf20Sopenharmony_ci * delivers this notification to inform the application that of the 8258c2ecf20Sopenharmony_ci * peers requested adaptation layer. 8268c2ecf20Sopenharmony_ci */ 8278c2ecf20Sopenharmony_ci if (new_asoc->peer.adaptation_ind) { 8288c2ecf20Sopenharmony_ci ai_ev = sctp_ulpevent_make_adaptation_indication(new_asoc, 8298c2ecf20Sopenharmony_ci GFP_ATOMIC); 8308c2ecf20Sopenharmony_ci if (!ai_ev) 8318c2ecf20Sopenharmony_ci goto nomem_aiev; 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci if (!new_asoc->peer.auth_capable) { 8358c2ecf20Sopenharmony_ci auth_ev = sctp_ulpevent_make_authkey(new_asoc, 0, 8368c2ecf20Sopenharmony_ci SCTP_AUTH_NO_AUTH, 8378c2ecf20Sopenharmony_ci GFP_ATOMIC); 8388c2ecf20Sopenharmony_ci if (!auth_ev) 8398c2ecf20Sopenharmony_ci goto nomem_authev; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci /* Add all the state machine commands now since we've created 8438c2ecf20Sopenharmony_ci * everything. This way we don't introduce memory corruptions 8448c2ecf20Sopenharmony_ci * during side-effect processing and correclty count established 8458c2ecf20Sopenharmony_ci * associations. 8468c2ecf20Sopenharmony_ci */ 8478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 8488c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 8498c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 8508c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 8518c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); 8528c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 8558c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 8568c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci /* This will send the COOKIE ACK */ 8598c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci /* Queue the ASSOC_CHANGE event */ 8628c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* Send up the Adaptation Layer Indication event */ 8658c2ecf20Sopenharmony_ci if (ai_ev) 8668c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 8678c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ai_ev)); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (auth_ev) 8708c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 8718c2ecf20Sopenharmony_ci SCTP_ULPEVENT(auth_ev)); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_cinomem_authev: 8768c2ecf20Sopenharmony_ci sctp_ulpevent_free(ai_ev); 8778c2ecf20Sopenharmony_cinomem_aiev: 8788c2ecf20Sopenharmony_ci sctp_ulpevent_free(ev); 8798c2ecf20Sopenharmony_cinomem_ev: 8808c2ecf20Sopenharmony_ci sctp_chunk_free(repl); 8818c2ecf20Sopenharmony_cinomem_init: 8828c2ecf20Sopenharmony_ci sctp_association_free(new_asoc); 8838c2ecf20Sopenharmony_cinomem: 8848c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci/* 8888c2ecf20Sopenharmony_ci * Respond to a normal COOKIE ACK chunk. 8898c2ecf20Sopenharmony_ci * We are the side that is asking for an association. 8908c2ecf20Sopenharmony_ci * 8918c2ecf20Sopenharmony_ci * RFC 2960 5.1 Normal Establishment of an Association 8928c2ecf20Sopenharmony_ci * 8938c2ecf20Sopenharmony_ci * E) Upon reception of the COOKIE ACK, endpoint "A" will move from the 8948c2ecf20Sopenharmony_ci * COOKIE-ECHOED state to the ESTABLISHED state, stopping the T1-cookie 8958c2ecf20Sopenharmony_ci * timer. It may also notify its ULP about the successful 8968c2ecf20Sopenharmony_ci * establishment of the association with a Communication Up 8978c2ecf20Sopenharmony_ci * notification (see Section 10). 8988c2ecf20Sopenharmony_ci * 8998c2ecf20Sopenharmony_ci * Verification Tag: 9008c2ecf20Sopenharmony_ci * Inputs 9018c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 9028c2ecf20Sopenharmony_ci * 9038c2ecf20Sopenharmony_ci * Outputs 9048c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 9058c2ecf20Sopenharmony_ci * 9068c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 9078c2ecf20Sopenharmony_ci */ 9088c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net, 9098c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 9108c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 9118c2ecf20Sopenharmony_ci const union sctp_subtype type, 9128c2ecf20Sopenharmony_ci void *arg, 9138c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 9168c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 9198c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci /* Verify that the chunk length for the COOKIE-ACK is OK. 9228c2ecf20Sopenharmony_ci * If we don't do this, any bundled chunks may be junked. 9238c2ecf20Sopenharmony_ci */ 9248c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 9258c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 9268c2ecf20Sopenharmony_ci commands); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci /* Reset init error count upon receipt of COOKIE-ACK, 9298c2ecf20Sopenharmony_ci * to avoid problems with the managemement of this 9308c2ecf20Sopenharmony_ci * counter in stale cookie situations when a transition back 9318c2ecf20Sopenharmony_ci * from the COOKIE-ECHOED state to the COOKIE-WAIT 9328c2ecf20Sopenharmony_ci * state is performed. 9338c2ecf20Sopenharmony_ci */ 9348c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci /* Set peer label for connection. */ 9378c2ecf20Sopenharmony_ci security_inet_conn_established(ep->base.sk, chunk->skb); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 9408c2ecf20Sopenharmony_ci * 9418c2ecf20Sopenharmony_ci * E) Upon reception of the COOKIE ACK, endpoint "A" will move 9428c2ecf20Sopenharmony_ci * from the COOKIE-ECHOED state to the ESTABLISHED state, 9438c2ecf20Sopenharmony_ci * stopping the T1-cookie timer. 9448c2ecf20Sopenharmony_ci */ 9458c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 9468c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 9478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 9488c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 9498c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 9508c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); 9518c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); 9528c2ecf20Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 9538c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 9548c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci /* It may also notify its ULP about the successful 9578c2ecf20Sopenharmony_ci * establishment of the association with a Communication Up 9588c2ecf20Sopenharmony_ci * notification (see Section 10). 9598c2ecf20Sopenharmony_ci */ 9608c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 9618c2ecf20Sopenharmony_ci 0, asoc->c.sinit_num_ostreams, 9628c2ecf20Sopenharmony_ci asoc->c.sinit_max_instreams, 9638c2ecf20Sopenharmony_ci NULL, GFP_ATOMIC); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (!ev) 9668c2ecf20Sopenharmony_ci goto nomem; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 9718c2ecf20Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter , SCTP 9728c2ecf20Sopenharmony_ci * delivers this notification to inform the application that of the 9738c2ecf20Sopenharmony_ci * peers requested adaptation layer. 9748c2ecf20Sopenharmony_ci */ 9758c2ecf20Sopenharmony_ci if (asoc->peer.adaptation_ind) { 9768c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC); 9778c2ecf20Sopenharmony_ci if (!ev) 9788c2ecf20Sopenharmony_ci goto nomem; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 9818c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ev)); 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci if (!asoc->peer.auth_capable) { 9858c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_authkey(asoc, 0, SCTP_AUTH_NO_AUTH, 9868c2ecf20Sopenharmony_ci GFP_ATOMIC); 9878c2ecf20Sopenharmony_ci if (!ev) 9888c2ecf20Sopenharmony_ci goto nomem; 9898c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 9908c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ev)); 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 9948c2ecf20Sopenharmony_cinomem: 9958c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci/* Generate and sendout a heartbeat packet. */ 9998c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_heartbeat( 10008c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 10018c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 10028c2ecf20Sopenharmony_ci const union sctp_subtype type, 10038c2ecf20Sopenharmony_ci void *arg, 10048c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 10058c2ecf20Sopenharmony_ci{ 10068c2ecf20Sopenharmony_ci struct sctp_transport *transport = (struct sctp_transport *) arg; 10078c2ecf20Sopenharmony_ci struct sctp_chunk *reply; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci /* Send a heartbeat to our peer. */ 10108c2ecf20Sopenharmony_ci reply = sctp_make_heartbeat(asoc, transport); 10118c2ecf20Sopenharmony_ci if (!reply) 10128c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci /* Set rto_pending indicating that an RTT measurement 10158c2ecf20Sopenharmony_ci * is started with this heartbeat chunk. 10168c2ecf20Sopenharmony_ci */ 10178c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_RTO_PENDING, 10188c2ecf20Sopenharmony_ci SCTP_TRANSPORT(transport)); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 10218c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 10228c2ecf20Sopenharmony_ci} 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci/* Generate a HEARTBEAT packet on the given transport. */ 10258c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_sendbeat_8_3(struct net *net, 10268c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 10278c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 10288c2ecf20Sopenharmony_ci const union sctp_subtype type, 10298c2ecf20Sopenharmony_ci void *arg, 10308c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci struct sctp_transport *transport = (struct sctp_transport *) arg; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 10358c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 10368c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 10378c2ecf20Sopenharmony_ci /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 10388c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 10398c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 10408c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 10418c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 10428c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 10438c2ecf20Sopenharmony_ci } 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* Section 3.3.5. 10468c2ecf20Sopenharmony_ci * The Sender-specific Heartbeat Info field should normally include 10478c2ecf20Sopenharmony_ci * information about the sender's current time when this HEARTBEAT 10488c2ecf20Sopenharmony_ci * chunk is sent and the destination transport address to which this 10498c2ecf20Sopenharmony_ci * HEARTBEAT is sent (see Section 8.3). 10508c2ecf20Sopenharmony_ci */ 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (transport->param_flags & SPP_HB_ENABLE) { 10538c2ecf20Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == 10548c2ecf20Sopenharmony_ci sctp_sf_heartbeat(ep, asoc, type, arg, 10558c2ecf20Sopenharmony_ci commands)) 10568c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* Set transport error counter and association error counter 10598c2ecf20Sopenharmony_ci * when sending heartbeat. 10608c2ecf20Sopenharmony_ci */ 10618c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, 10628c2ecf20Sopenharmony_ci SCTP_TRANSPORT(transport)); 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE, 10658c2ecf20Sopenharmony_ci SCTP_TRANSPORT(transport)); 10668c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE, 10678c2ecf20Sopenharmony_ci SCTP_TRANSPORT(transport)); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 10708c2ecf20Sopenharmony_ci} 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci/* resend asoc strreset_chunk. */ 10738c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_send_reconf(struct net *net, 10748c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 10758c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 10768c2ecf20Sopenharmony_ci const union sctp_subtype type, 10778c2ecf20Sopenharmony_ci void *arg, 10788c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 10798c2ecf20Sopenharmony_ci{ 10808c2ecf20Sopenharmony_ci struct sctp_transport *transport = arg; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 10838c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 10848c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 10858c2ecf20Sopenharmony_ci /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 10868c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 10878c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 10888c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 10898c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 10908c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci sctp_chunk_hold(asoc->strreset_chunk); 10948c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 10958c2ecf20Sopenharmony_ci SCTP_CHUNK(asoc->strreset_chunk)); 10968c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 10998c2ecf20Sopenharmony_ci} 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci/* 11028c2ecf20Sopenharmony_ci * Process an heartbeat request. 11038c2ecf20Sopenharmony_ci * 11048c2ecf20Sopenharmony_ci * Section: 8.3 Path Heartbeat 11058c2ecf20Sopenharmony_ci * The receiver of the HEARTBEAT should immediately respond with a 11068c2ecf20Sopenharmony_ci * HEARTBEAT ACK that contains the Heartbeat Information field copied 11078c2ecf20Sopenharmony_ci * from the received HEARTBEAT chunk. 11088c2ecf20Sopenharmony_ci * 11098c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 11108c2ecf20Sopenharmony_ci * When receiving an SCTP packet, the endpoint MUST ensure that the 11118c2ecf20Sopenharmony_ci * value in the Verification Tag field of the received SCTP packet 11128c2ecf20Sopenharmony_ci * matches its own Tag. If the received Verification Tag value does not 11138c2ecf20Sopenharmony_ci * match the receiver's own tag value, the receiver shall silently 11148c2ecf20Sopenharmony_ci * discard the packet and shall not process it any further except for 11158c2ecf20Sopenharmony_ci * those cases listed in Section 8.5.1 below. 11168c2ecf20Sopenharmony_ci * 11178c2ecf20Sopenharmony_ci * Inputs 11188c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 11198c2ecf20Sopenharmony_ci * 11208c2ecf20Sopenharmony_ci * Outputs 11218c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 11228c2ecf20Sopenharmony_ci * 11238c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_beat_8_3(struct net *net, 11268c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 11278c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 11288c2ecf20Sopenharmony_ci const union sctp_subtype type, 11298c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci struct sctp_paramhdr *param_hdr; 11328c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 11338c2ecf20Sopenharmony_ci struct sctp_chunk *reply; 11348c2ecf20Sopenharmony_ci size_t paylen = 0; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 11378c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci /* Make sure that the HEARTBEAT chunk has a valid length. */ 11408c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, 11418c2ecf20Sopenharmony_ci sizeof(struct sctp_heartbeat_chunk))) 11428c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 11438c2ecf20Sopenharmony_ci commands); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci /* 8.3 The receiver of the HEARTBEAT should immediately 11468c2ecf20Sopenharmony_ci * respond with a HEARTBEAT ACK that contains the Heartbeat 11478c2ecf20Sopenharmony_ci * Information field copied from the received HEARTBEAT chunk. 11488c2ecf20Sopenharmony_ci */ 11498c2ecf20Sopenharmony_ci chunk->subh.hb_hdr = (struct sctp_heartbeathdr *)chunk->skb->data; 11508c2ecf20Sopenharmony_ci param_hdr = (struct sctp_paramhdr *)chunk->subh.hb_hdr; 11518c2ecf20Sopenharmony_ci paylen = ntohs(chunk->chunk_hdr->length) - sizeof(struct sctp_chunkhdr); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci if (ntohs(param_hdr->length) > paylen) 11548c2ecf20Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 11558c2ecf20Sopenharmony_ci param_hdr, commands); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci if (!pskb_pull(chunk->skb, paylen)) 11588c2ecf20Sopenharmony_ci goto nomem; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci reply = sctp_make_heartbeat_ack(asoc, chunk, param_hdr, paylen); 11618c2ecf20Sopenharmony_ci if (!reply) 11628c2ecf20Sopenharmony_ci goto nomem; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 11658c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_cinomem: 11688c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 11698c2ecf20Sopenharmony_ci} 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci/* 11728c2ecf20Sopenharmony_ci * Process the returning HEARTBEAT ACK. 11738c2ecf20Sopenharmony_ci * 11748c2ecf20Sopenharmony_ci * Section: 8.3 Path Heartbeat 11758c2ecf20Sopenharmony_ci * Upon the receipt of the HEARTBEAT ACK, the sender of the HEARTBEAT 11768c2ecf20Sopenharmony_ci * should clear the error counter of the destination transport 11778c2ecf20Sopenharmony_ci * address to which the HEARTBEAT was sent, and mark the destination 11788c2ecf20Sopenharmony_ci * transport address as active if it is not so marked. The endpoint may 11798c2ecf20Sopenharmony_ci * optionally report to the upper layer when an inactive destination 11808c2ecf20Sopenharmony_ci * address is marked as active due to the reception of the latest 11818c2ecf20Sopenharmony_ci * HEARTBEAT ACK. The receiver of the HEARTBEAT ACK must also 11828c2ecf20Sopenharmony_ci * clear the association overall error count as well (as defined 11838c2ecf20Sopenharmony_ci * in section 8.1). 11848c2ecf20Sopenharmony_ci * 11858c2ecf20Sopenharmony_ci * The receiver of the HEARTBEAT ACK should also perform an RTT 11868c2ecf20Sopenharmony_ci * measurement for that destination transport address using the time 11878c2ecf20Sopenharmony_ci * value carried in the HEARTBEAT ACK chunk. 11888c2ecf20Sopenharmony_ci * 11898c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 11908c2ecf20Sopenharmony_ci * 11918c2ecf20Sopenharmony_ci * Inputs 11928c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 11938c2ecf20Sopenharmony_ci * 11948c2ecf20Sopenharmony_ci * Outputs 11958c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 11968c2ecf20Sopenharmony_ci * 11978c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 11988c2ecf20Sopenharmony_ci */ 11998c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_backbeat_8_3(struct net *net, 12008c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 12018c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 12028c2ecf20Sopenharmony_ci const union sctp_subtype type, 12038c2ecf20Sopenharmony_ci void *arg, 12048c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 12058c2ecf20Sopenharmony_ci{ 12068c2ecf20Sopenharmony_ci struct sctp_sender_hb_info *hbinfo; 12078c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 12088c2ecf20Sopenharmony_ci struct sctp_transport *link; 12098c2ecf20Sopenharmony_ci unsigned long max_interval; 12108c2ecf20Sopenharmony_ci union sctp_addr from_addr; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 12138c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci /* Make sure that the HEARTBEAT-ACK chunk has a valid length. */ 12168c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr) + 12178c2ecf20Sopenharmony_ci sizeof(*hbinfo))) 12188c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 12198c2ecf20Sopenharmony_ci commands); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci hbinfo = (struct sctp_sender_hb_info *)chunk->skb->data; 12228c2ecf20Sopenharmony_ci /* Make sure that the length of the parameter is what we expect */ 12238c2ecf20Sopenharmony_ci if (ntohs(hbinfo->param_hdr.length) != sizeof(*hbinfo)) 12248c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci from_addr = hbinfo->daddr; 12278c2ecf20Sopenharmony_ci link = sctp_assoc_lookup_paddr(asoc, &from_addr); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci /* This should never happen, but lets log it if so. */ 12308c2ecf20Sopenharmony_ci if (unlikely(!link)) { 12318c2ecf20Sopenharmony_ci if (from_addr.sa.sa_family == AF_INET6) { 12328c2ecf20Sopenharmony_ci net_warn_ratelimited("%s association %p could not find address %pI6\n", 12338c2ecf20Sopenharmony_ci __func__, 12348c2ecf20Sopenharmony_ci asoc, 12358c2ecf20Sopenharmony_ci &from_addr.v6.sin6_addr); 12368c2ecf20Sopenharmony_ci } else { 12378c2ecf20Sopenharmony_ci net_warn_ratelimited("%s association %p could not find address %pI4\n", 12388c2ecf20Sopenharmony_ci __func__, 12398c2ecf20Sopenharmony_ci asoc, 12408c2ecf20Sopenharmony_ci &from_addr.v4.sin_addr.s_addr); 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci /* Validate the 64-bit random nonce. */ 12468c2ecf20Sopenharmony_ci if (hbinfo->hb_nonce != link->hb_nonce) 12478c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci max_interval = link->hbinterval + link->rto; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci /* Check if the timestamp looks valid. */ 12528c2ecf20Sopenharmony_ci if (time_after(hbinfo->sent_at, jiffies) || 12538c2ecf20Sopenharmony_ci time_after(jiffies, hbinfo->sent_at + max_interval)) { 12548c2ecf20Sopenharmony_ci pr_debug("%s: HEARTBEAT ACK with invalid timestamp received " 12558c2ecf20Sopenharmony_ci "for transport:%p\n", __func__, link); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 12588c2ecf20Sopenharmony_ci } 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of 12618c2ecf20Sopenharmony_ci * the HEARTBEAT should clear the error counter of the 12628c2ecf20Sopenharmony_ci * destination transport address to which the HEARTBEAT was 12638c2ecf20Sopenharmony_ci * sent and mark the destination transport address as active if 12648c2ecf20Sopenharmony_ci * it is not so marked. 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON, SCTP_TRANSPORT(link)); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 12698c2ecf20Sopenharmony_ci} 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci/* Helper function to send out an abort for the restart 12728c2ecf20Sopenharmony_ci * condition. 12738c2ecf20Sopenharmony_ci */ 12748c2ecf20Sopenharmony_cistatic int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa, 12758c2ecf20Sopenharmony_ci struct sctp_chunk *init, 12768c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 12778c2ecf20Sopenharmony_ci{ 12788c2ecf20Sopenharmony_ci struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family); 12798c2ecf20Sopenharmony_ci union sctp_addr_param *addrparm; 12808c2ecf20Sopenharmony_ci struct sctp_errhdr *errhdr; 12818c2ecf20Sopenharmony_ci char buffer[sizeof(*errhdr) + sizeof(*addrparm)]; 12828c2ecf20Sopenharmony_ci struct sctp_endpoint *ep; 12838c2ecf20Sopenharmony_ci struct sctp_packet *pkt; 12848c2ecf20Sopenharmony_ci int len; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci /* Build the error on the stack. We are way to malloc crazy 12878c2ecf20Sopenharmony_ci * throughout the code today. 12888c2ecf20Sopenharmony_ci */ 12898c2ecf20Sopenharmony_ci errhdr = (struct sctp_errhdr *)buffer; 12908c2ecf20Sopenharmony_ci addrparm = (union sctp_addr_param *)errhdr->variable; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* Copy into a parm format. */ 12938c2ecf20Sopenharmony_ci len = af->to_addr_param(ssa, addrparm); 12948c2ecf20Sopenharmony_ci len += sizeof(*errhdr); 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci errhdr->cause = SCTP_ERROR_RESTART; 12978c2ecf20Sopenharmony_ci errhdr->length = htons(len); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci /* Assign to the control socket. */ 13008c2ecf20Sopenharmony_ci ep = sctp_sk(net->sctp.ctl_sock)->ep; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci /* Association is NULL since this may be a restart attack and we 13038c2ecf20Sopenharmony_ci * want to send back the attacker's vtag. 13048c2ecf20Sopenharmony_ci */ 13058c2ecf20Sopenharmony_ci pkt = sctp_abort_pkt_new(net, ep, NULL, init, errhdr, len); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci if (!pkt) 13088c2ecf20Sopenharmony_ci goto out; 13098c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt)); 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci /* Discard the rest of the inbound packet. */ 13148c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ciout: 13178c2ecf20Sopenharmony_ci /* Even if there is no memory, treat as a failure so 13188c2ecf20Sopenharmony_ci * the packet will get dropped. 13198c2ecf20Sopenharmony_ci */ 13208c2ecf20Sopenharmony_ci return 0; 13218c2ecf20Sopenharmony_ci} 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_cistatic bool list_has_sctp_addr(const struct list_head *list, 13248c2ecf20Sopenharmony_ci union sctp_addr *ipaddr) 13258c2ecf20Sopenharmony_ci{ 13268c2ecf20Sopenharmony_ci struct sctp_transport *addr; 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci list_for_each_entry(addr, list, transports) { 13298c2ecf20Sopenharmony_ci if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr)) 13308c2ecf20Sopenharmony_ci return true; 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci return false; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci/* A restart is occurring, check to make sure no new addresses 13368c2ecf20Sopenharmony_ci * are being added as we may be under a takeover attack. 13378c2ecf20Sopenharmony_ci */ 13388c2ecf20Sopenharmony_cistatic int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, 13398c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 13408c2ecf20Sopenharmony_ci struct sctp_chunk *init, 13418c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 13428c2ecf20Sopenharmony_ci{ 13438c2ecf20Sopenharmony_ci struct net *net = new_asoc->base.net; 13448c2ecf20Sopenharmony_ci struct sctp_transport *new_addr; 13458c2ecf20Sopenharmony_ci int ret = 1; 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci /* Implementor's Guide - Section 5.2.2 13488c2ecf20Sopenharmony_ci * ... 13498c2ecf20Sopenharmony_ci * Before responding the endpoint MUST check to see if the 13508c2ecf20Sopenharmony_ci * unexpected INIT adds new addresses to the association. If new 13518c2ecf20Sopenharmony_ci * addresses are added to the association, the endpoint MUST respond 13528c2ecf20Sopenharmony_ci * with an ABORT.. 13538c2ecf20Sopenharmony_ci */ 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci /* Search through all current addresses and make sure 13568c2ecf20Sopenharmony_ci * we aren't adding any new ones. 13578c2ecf20Sopenharmony_ci */ 13588c2ecf20Sopenharmony_ci list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, 13598c2ecf20Sopenharmony_ci transports) { 13608c2ecf20Sopenharmony_ci if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, 13618c2ecf20Sopenharmony_ci &new_addr->ipaddr)) { 13628c2ecf20Sopenharmony_ci sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init, 13638c2ecf20Sopenharmony_ci commands); 13648c2ecf20Sopenharmony_ci ret = 0; 13658c2ecf20Sopenharmony_ci break; 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci /* Return success if all addresses were found. */ 13708c2ecf20Sopenharmony_ci return ret; 13718c2ecf20Sopenharmony_ci} 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci/* Populate the verification/tie tags based on overlapping INIT 13748c2ecf20Sopenharmony_ci * scenario. 13758c2ecf20Sopenharmony_ci * 13768c2ecf20Sopenharmony_ci * Note: Do not use in CLOSED or SHUTDOWN-ACK-SENT state. 13778c2ecf20Sopenharmony_ci */ 13788c2ecf20Sopenharmony_cistatic void sctp_tietags_populate(struct sctp_association *new_asoc, 13798c2ecf20Sopenharmony_ci const struct sctp_association *asoc) 13808c2ecf20Sopenharmony_ci{ 13818c2ecf20Sopenharmony_ci switch (asoc->state) { 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci /* 5.2.1 INIT received in COOKIE-WAIT or COOKIE-ECHOED State */ 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci case SCTP_STATE_COOKIE_WAIT: 13868c2ecf20Sopenharmony_ci new_asoc->c.my_vtag = asoc->c.my_vtag; 13878c2ecf20Sopenharmony_ci new_asoc->c.my_ttag = asoc->c.my_vtag; 13888c2ecf20Sopenharmony_ci new_asoc->c.peer_ttag = 0; 13898c2ecf20Sopenharmony_ci break; 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci case SCTP_STATE_COOKIE_ECHOED: 13928c2ecf20Sopenharmony_ci new_asoc->c.my_vtag = asoc->c.my_vtag; 13938c2ecf20Sopenharmony_ci new_asoc->c.my_ttag = asoc->c.my_vtag; 13948c2ecf20Sopenharmony_ci new_asoc->c.peer_ttag = asoc->c.peer_vtag; 13958c2ecf20Sopenharmony_ci break; 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci /* 5.2.2 Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED, 13988c2ecf20Sopenharmony_ci * COOKIE-WAIT and SHUTDOWN-ACK-SENT 13998c2ecf20Sopenharmony_ci */ 14008c2ecf20Sopenharmony_ci default: 14018c2ecf20Sopenharmony_ci new_asoc->c.my_ttag = asoc->c.my_vtag; 14028c2ecf20Sopenharmony_ci new_asoc->c.peer_ttag = asoc->c.peer_vtag; 14038c2ecf20Sopenharmony_ci break; 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci /* Other parameters for the endpoint SHOULD be copied from the 14078c2ecf20Sopenharmony_ci * existing parameters of the association (e.g. number of 14088c2ecf20Sopenharmony_ci * outbound streams) into the INIT ACK and cookie. 14098c2ecf20Sopenharmony_ci */ 14108c2ecf20Sopenharmony_ci new_asoc->rwnd = asoc->rwnd; 14118c2ecf20Sopenharmony_ci new_asoc->c.sinit_num_ostreams = asoc->c.sinit_num_ostreams; 14128c2ecf20Sopenharmony_ci new_asoc->c.sinit_max_instreams = asoc->c.sinit_max_instreams; 14138c2ecf20Sopenharmony_ci new_asoc->c.initial_tsn = asoc->c.initial_tsn; 14148c2ecf20Sopenharmony_ci} 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci/* 14178c2ecf20Sopenharmony_ci * Compare vtag/tietag values to determine unexpected COOKIE-ECHO 14188c2ecf20Sopenharmony_ci * handling action. 14198c2ecf20Sopenharmony_ci * 14208c2ecf20Sopenharmony_ci * RFC 2960 5.2.4 Handle a COOKIE ECHO when a TCB exists. 14218c2ecf20Sopenharmony_ci * 14228c2ecf20Sopenharmony_ci * Returns value representing action to be taken. These action values 14238c2ecf20Sopenharmony_ci * correspond to Action/Description values in RFC 2960, Table 2. 14248c2ecf20Sopenharmony_ci */ 14258c2ecf20Sopenharmony_cistatic char sctp_tietags_compare(struct sctp_association *new_asoc, 14268c2ecf20Sopenharmony_ci const struct sctp_association *asoc) 14278c2ecf20Sopenharmony_ci{ 14288c2ecf20Sopenharmony_ci /* In this case, the peer may have restarted. */ 14298c2ecf20Sopenharmony_ci if ((asoc->c.my_vtag != new_asoc->c.my_vtag) && 14308c2ecf20Sopenharmony_ci (asoc->c.peer_vtag != new_asoc->c.peer_vtag) && 14318c2ecf20Sopenharmony_ci (asoc->c.my_vtag == new_asoc->c.my_ttag) && 14328c2ecf20Sopenharmony_ci (asoc->c.peer_vtag == new_asoc->c.peer_ttag)) 14338c2ecf20Sopenharmony_ci return 'A'; 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci /* Collision case B. */ 14368c2ecf20Sopenharmony_ci if ((asoc->c.my_vtag == new_asoc->c.my_vtag) && 14378c2ecf20Sopenharmony_ci ((asoc->c.peer_vtag != new_asoc->c.peer_vtag) || 14388c2ecf20Sopenharmony_ci (0 == asoc->c.peer_vtag))) { 14398c2ecf20Sopenharmony_ci return 'B'; 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci /* Collision case D. */ 14438c2ecf20Sopenharmony_ci if ((asoc->c.my_vtag == new_asoc->c.my_vtag) && 14448c2ecf20Sopenharmony_ci (asoc->c.peer_vtag == new_asoc->c.peer_vtag)) 14458c2ecf20Sopenharmony_ci return 'D'; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci /* Collision case C. */ 14488c2ecf20Sopenharmony_ci if ((asoc->c.my_vtag != new_asoc->c.my_vtag) && 14498c2ecf20Sopenharmony_ci (asoc->c.peer_vtag == new_asoc->c.peer_vtag) && 14508c2ecf20Sopenharmony_ci (0 == new_asoc->c.my_ttag) && 14518c2ecf20Sopenharmony_ci (0 == new_asoc->c.peer_ttag)) 14528c2ecf20Sopenharmony_ci return 'C'; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* No match to any of the special cases; discard this packet. */ 14558c2ecf20Sopenharmony_ci return 'E'; 14568c2ecf20Sopenharmony_ci} 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci/* Common helper routine for both duplicate and simulataneous INIT 14598c2ecf20Sopenharmony_ci * chunk handling. 14608c2ecf20Sopenharmony_ci */ 14618c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_unexpected_init( 14628c2ecf20Sopenharmony_ci struct net *net, 14638c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 14648c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 14658c2ecf20Sopenharmony_ci const union sctp_subtype type, 14668c2ecf20Sopenharmony_ci void *arg, 14678c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 14688c2ecf20Sopenharmony_ci{ 14698c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg, *repl, *err_chunk; 14708c2ecf20Sopenharmony_ci struct sctp_unrecognized_param *unk_param; 14718c2ecf20Sopenharmony_ci struct sctp_association *new_asoc; 14728c2ecf20Sopenharmony_ci enum sctp_disposition retval; 14738c2ecf20Sopenharmony_ci struct sctp_packet *packet; 14748c2ecf20Sopenharmony_ci int len; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci /* Update socket peer label if first association. */ 14778c2ecf20Sopenharmony_ci if (security_sctp_assoc_request((struct sctp_endpoint *)ep, 14788c2ecf20Sopenharmony_ci chunk->skb)) 14798c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci /* 6.10 Bundling 14828c2ecf20Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 14838c2ecf20Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 14848c2ecf20Sopenharmony_ci * 14858c2ecf20Sopenharmony_ci * IG Section 2.11.2 14868c2ecf20Sopenharmony_ci * Furthermore, we require that the receiver of an INIT chunk MUST 14878c2ecf20Sopenharmony_ci * enforce these rules by silently discarding an arriving packet 14888c2ecf20Sopenharmony_ci * with an INIT chunk that is bundled with other chunks. 14898c2ecf20Sopenharmony_ci */ 14908c2ecf20Sopenharmony_ci if (!chunk->singleton) 14918c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci /* Make sure that the INIT chunk has a valid length. */ 14948c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) 14958c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci /* 3.1 A packet containing an INIT chunk MUST have a zero Verification 14988c2ecf20Sopenharmony_ci * Tag. 14998c2ecf20Sopenharmony_ci */ 15008c2ecf20Sopenharmony_ci if (chunk->sctp_hdr->vtag != 0) 15018c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci /* Grab the INIT header. */ 15048c2ecf20Sopenharmony_ci chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci /* Tag the variable length parameters. */ 15078c2ecf20Sopenharmony_ci chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(struct sctp_inithdr)); 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci /* Verify the INIT chunk before processing it. */ 15108c2ecf20Sopenharmony_ci err_chunk = NULL; 15118c2ecf20Sopenharmony_ci if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, 15128c2ecf20Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, chunk, 15138c2ecf20Sopenharmony_ci &err_chunk)) { 15148c2ecf20Sopenharmony_ci /* This chunk contains fatal error. It is to be discarded. 15158c2ecf20Sopenharmony_ci * Send an ABORT, with causes if there is any. 15168c2ecf20Sopenharmony_ci */ 15178c2ecf20Sopenharmony_ci if (err_chunk) { 15188c2ecf20Sopenharmony_ci packet = sctp_abort_pkt_new(net, ep, asoc, arg, 15198c2ecf20Sopenharmony_ci (__u8 *)(err_chunk->chunk_hdr) + 15208c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr), 15218c2ecf20Sopenharmony_ci ntohs(err_chunk->chunk_hdr->length) - 15228c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci if (packet) { 15258c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 15268c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 15278c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 15288c2ecf20Sopenharmony_ci retval = SCTP_DISPOSITION_CONSUME; 15298c2ecf20Sopenharmony_ci } else { 15308c2ecf20Sopenharmony_ci retval = SCTP_DISPOSITION_NOMEM; 15318c2ecf20Sopenharmony_ci } 15328c2ecf20Sopenharmony_ci goto cleanup; 15338c2ecf20Sopenharmony_ci } else { 15348c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, 15358c2ecf20Sopenharmony_ci commands); 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci } 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci /* 15408c2ecf20Sopenharmony_ci * Other parameters for the endpoint SHOULD be copied from the 15418c2ecf20Sopenharmony_ci * existing parameters of the association (e.g. number of 15428c2ecf20Sopenharmony_ci * outbound streams) into the INIT ACK and cookie. 15438c2ecf20Sopenharmony_ci * FIXME: We are copying parameters from the endpoint not the 15448c2ecf20Sopenharmony_ci * association. 15458c2ecf20Sopenharmony_ci */ 15468c2ecf20Sopenharmony_ci new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC); 15478c2ecf20Sopenharmony_ci if (!new_asoc) 15488c2ecf20Sopenharmony_ci goto nomem; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci if (sctp_assoc_set_bind_addr_from_ep(new_asoc, 15518c2ecf20Sopenharmony_ci sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0) 15528c2ecf20Sopenharmony_ci goto nomem; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci /* In the outbound INIT ACK the endpoint MUST copy its current 15558c2ecf20Sopenharmony_ci * Verification Tag and Peers Verification tag into a reserved 15568c2ecf20Sopenharmony_ci * place (local tie-tag and per tie-tag) within the state cookie. 15578c2ecf20Sopenharmony_ci */ 15588c2ecf20Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), 15598c2ecf20Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, 15608c2ecf20Sopenharmony_ci GFP_ATOMIC)) 15618c2ecf20Sopenharmony_ci goto nomem; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci /* Make sure no new addresses are being added during the 15648c2ecf20Sopenharmony_ci * restart. Do not do this check for COOKIE-WAIT state, 15658c2ecf20Sopenharmony_ci * since there are no peer addresses to check against. 15668c2ecf20Sopenharmony_ci * Upon return an ABORT will have been sent if needed. 15678c2ecf20Sopenharmony_ci */ 15688c2ecf20Sopenharmony_ci if (!sctp_state(asoc, COOKIE_WAIT)) { 15698c2ecf20Sopenharmony_ci if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, 15708c2ecf20Sopenharmony_ci commands)) { 15718c2ecf20Sopenharmony_ci retval = SCTP_DISPOSITION_CONSUME; 15728c2ecf20Sopenharmony_ci goto nomem_retval; 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci sctp_tietags_populate(new_asoc, asoc); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci /* B) "Z" shall respond immediately with an INIT ACK chunk. */ 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 15818c2ecf20Sopenharmony_ci * make sure to reserve enough room in the INIT ACK for them. 15828c2ecf20Sopenharmony_ci */ 15838c2ecf20Sopenharmony_ci len = 0; 15848c2ecf20Sopenharmony_ci if (err_chunk) { 15858c2ecf20Sopenharmony_ci len = ntohs(err_chunk->chunk_hdr->length) - 15868c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr); 15878c2ecf20Sopenharmony_ci } 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); 15908c2ecf20Sopenharmony_ci if (!repl) 15918c2ecf20Sopenharmony_ci goto nomem; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 15948c2ecf20Sopenharmony_ci * include them in the outgoing INIT ACK as "Unrecognized parameter" 15958c2ecf20Sopenharmony_ci * parameter. 15968c2ecf20Sopenharmony_ci */ 15978c2ecf20Sopenharmony_ci if (err_chunk) { 15988c2ecf20Sopenharmony_ci /* Get the "Unrecognized parameter" parameter(s) out of the 15998c2ecf20Sopenharmony_ci * ERROR chunk generated by sctp_verify_init(). Since the 16008c2ecf20Sopenharmony_ci * error cause code for "unknown parameter" and the 16018c2ecf20Sopenharmony_ci * "Unrecognized parameter" type is the same, we can 16028c2ecf20Sopenharmony_ci * construct the parameters in INIT ACK by copying the 16038c2ecf20Sopenharmony_ci * ERROR causes over. 16048c2ecf20Sopenharmony_ci */ 16058c2ecf20Sopenharmony_ci unk_param = (struct sctp_unrecognized_param *) 16068c2ecf20Sopenharmony_ci ((__u8 *)(err_chunk->chunk_hdr) + 16078c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 16088c2ecf20Sopenharmony_ci /* Replace the cause code with the "Unrecognized parameter" 16098c2ecf20Sopenharmony_ci * parameter type. 16108c2ecf20Sopenharmony_ci */ 16118c2ecf20Sopenharmony_ci sctp_addto_chunk(repl, len, unk_param); 16128c2ecf20Sopenharmony_ci } 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 16158c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci /* 16188c2ecf20Sopenharmony_ci * Note: After sending out INIT ACK with the State Cookie parameter, 16198c2ecf20Sopenharmony_ci * "Z" MUST NOT allocate any resources for this new association. 16208c2ecf20Sopenharmony_ci * Otherwise, "Z" will be vulnerable to resource attacks. 16218c2ecf20Sopenharmony_ci */ 16228c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 16238c2ecf20Sopenharmony_ci retval = SCTP_DISPOSITION_CONSUME; 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci return retval; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_cinomem: 16288c2ecf20Sopenharmony_ci retval = SCTP_DISPOSITION_NOMEM; 16298c2ecf20Sopenharmony_cinomem_retval: 16308c2ecf20Sopenharmony_ci if (new_asoc) 16318c2ecf20Sopenharmony_ci sctp_association_free(new_asoc); 16328c2ecf20Sopenharmony_cicleanup: 16338c2ecf20Sopenharmony_ci if (err_chunk) 16348c2ecf20Sopenharmony_ci sctp_chunk_free(err_chunk); 16358c2ecf20Sopenharmony_ci return retval; 16368c2ecf20Sopenharmony_ci} 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci/* 16398c2ecf20Sopenharmony_ci * Handle simultaneous INIT. 16408c2ecf20Sopenharmony_ci * This means we started an INIT and then we got an INIT request from 16418c2ecf20Sopenharmony_ci * our peer. 16428c2ecf20Sopenharmony_ci * 16438c2ecf20Sopenharmony_ci * Section: 5.2.1 INIT received in COOKIE-WAIT or COOKIE-ECHOED State (Item B) 16448c2ecf20Sopenharmony_ci * This usually indicates an initialization collision, i.e., each 16458c2ecf20Sopenharmony_ci * endpoint is attempting, at about the same time, to establish an 16468c2ecf20Sopenharmony_ci * association with the other endpoint. 16478c2ecf20Sopenharmony_ci * 16488c2ecf20Sopenharmony_ci * Upon receipt of an INIT in the COOKIE-WAIT or COOKIE-ECHOED state, an 16498c2ecf20Sopenharmony_ci * endpoint MUST respond with an INIT ACK using the same parameters it 16508c2ecf20Sopenharmony_ci * sent in its original INIT chunk (including its Verification Tag, 16518c2ecf20Sopenharmony_ci * unchanged). These original parameters are combined with those from the 16528c2ecf20Sopenharmony_ci * newly received INIT chunk. The endpoint shall also generate a State 16538c2ecf20Sopenharmony_ci * Cookie with the INIT ACK. The endpoint uses the parameters sent in its 16548c2ecf20Sopenharmony_ci * INIT to calculate the State Cookie. 16558c2ecf20Sopenharmony_ci * 16568c2ecf20Sopenharmony_ci * After that, the endpoint MUST NOT change its state, the T1-init 16578c2ecf20Sopenharmony_ci * timer shall be left running and the corresponding TCB MUST NOT be 16588c2ecf20Sopenharmony_ci * destroyed. The normal procedures for handling State Cookies when 16598c2ecf20Sopenharmony_ci * a TCB exists will resolve the duplicate INITs to a single association. 16608c2ecf20Sopenharmony_ci * 16618c2ecf20Sopenharmony_ci * For an endpoint that is in the COOKIE-ECHOED state it MUST populate 16628c2ecf20Sopenharmony_ci * its Tie-Tags with the Tag information of itself and its peer (see 16638c2ecf20Sopenharmony_ci * section 5.2.2 for a description of the Tie-Tags). 16648c2ecf20Sopenharmony_ci * 16658c2ecf20Sopenharmony_ci * Verification Tag: Not explicit, but an INIT can not have a valid 16668c2ecf20Sopenharmony_ci * verification tag, so we skip the check. 16678c2ecf20Sopenharmony_ci * 16688c2ecf20Sopenharmony_ci * Inputs 16698c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 16708c2ecf20Sopenharmony_ci * 16718c2ecf20Sopenharmony_ci * Outputs 16728c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 16738c2ecf20Sopenharmony_ci * 16748c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 16758c2ecf20Sopenharmony_ci */ 16768c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_1_siminit( 16778c2ecf20Sopenharmony_ci struct net *net, 16788c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 16798c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 16808c2ecf20Sopenharmony_ci const union sctp_subtype type, 16818c2ecf20Sopenharmony_ci void *arg, 16828c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 16838c2ecf20Sopenharmony_ci{ 16848c2ecf20Sopenharmony_ci /* Call helper to do the real work for both simulataneous and 16858c2ecf20Sopenharmony_ci * duplicate INIT chunk handling. 16868c2ecf20Sopenharmony_ci */ 16878c2ecf20Sopenharmony_ci return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands); 16888c2ecf20Sopenharmony_ci} 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci/* 16918c2ecf20Sopenharmony_ci * Handle duplicated INIT messages. These are usually delayed 16928c2ecf20Sopenharmony_ci * restransmissions. 16938c2ecf20Sopenharmony_ci * 16948c2ecf20Sopenharmony_ci * Section: 5.2.2 Unexpected INIT in States Other than CLOSED, 16958c2ecf20Sopenharmony_ci * COOKIE-ECHOED and COOKIE-WAIT 16968c2ecf20Sopenharmony_ci * 16978c2ecf20Sopenharmony_ci * Unless otherwise stated, upon reception of an unexpected INIT for 16988c2ecf20Sopenharmony_ci * this association, the endpoint shall generate an INIT ACK with a 16998c2ecf20Sopenharmony_ci * State Cookie. In the outbound INIT ACK the endpoint MUST copy its 17008c2ecf20Sopenharmony_ci * current Verification Tag and peer's Verification Tag into a reserved 17018c2ecf20Sopenharmony_ci * place within the state cookie. We shall refer to these locations as 17028c2ecf20Sopenharmony_ci * the Peer's-Tie-Tag and the Local-Tie-Tag. The outbound SCTP packet 17038c2ecf20Sopenharmony_ci * containing this INIT ACK MUST carry a Verification Tag value equal to 17048c2ecf20Sopenharmony_ci * the Initiation Tag found in the unexpected INIT. And the INIT ACK 17058c2ecf20Sopenharmony_ci * MUST contain a new Initiation Tag (randomly generated see Section 17068c2ecf20Sopenharmony_ci * 5.3.1). Other parameters for the endpoint SHOULD be copied from the 17078c2ecf20Sopenharmony_ci * existing parameters of the association (e.g. number of outbound 17088c2ecf20Sopenharmony_ci * streams) into the INIT ACK and cookie. 17098c2ecf20Sopenharmony_ci * 17108c2ecf20Sopenharmony_ci * After sending out the INIT ACK, the endpoint shall take no further 17118c2ecf20Sopenharmony_ci * actions, i.e., the existing association, including its current state, 17128c2ecf20Sopenharmony_ci * and the corresponding TCB MUST NOT be changed. 17138c2ecf20Sopenharmony_ci * 17148c2ecf20Sopenharmony_ci * Note: Only when a TCB exists and the association is not in a COOKIE- 17158c2ecf20Sopenharmony_ci * WAIT state are the Tie-Tags populated. For a normal association INIT 17168c2ecf20Sopenharmony_ci * (i.e. the endpoint is in a COOKIE-WAIT state), the Tie-Tags MUST be 17178c2ecf20Sopenharmony_ci * set to 0 (indicating that no previous TCB existed). The INIT ACK and 17188c2ecf20Sopenharmony_ci * State Cookie are populated as specified in section 5.2.1. 17198c2ecf20Sopenharmony_ci * 17208c2ecf20Sopenharmony_ci * Verification Tag: Not specified, but an INIT has no way of knowing 17218c2ecf20Sopenharmony_ci * what the verification tag could be, so we ignore it. 17228c2ecf20Sopenharmony_ci * 17238c2ecf20Sopenharmony_ci * Inputs 17248c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 17258c2ecf20Sopenharmony_ci * 17268c2ecf20Sopenharmony_ci * Outputs 17278c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 17288c2ecf20Sopenharmony_ci * 17298c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 17308c2ecf20Sopenharmony_ci */ 17318c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_2_dupinit( 17328c2ecf20Sopenharmony_ci struct net *net, 17338c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 17348c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 17358c2ecf20Sopenharmony_ci const union sctp_subtype type, 17368c2ecf20Sopenharmony_ci void *arg, 17378c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 17388c2ecf20Sopenharmony_ci{ 17398c2ecf20Sopenharmony_ci /* Call helper to do the real work for both simulataneous and 17408c2ecf20Sopenharmony_ci * duplicate INIT chunk handling. 17418c2ecf20Sopenharmony_ci */ 17428c2ecf20Sopenharmony_ci return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands); 17438c2ecf20Sopenharmony_ci} 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci/* 17478c2ecf20Sopenharmony_ci * Unexpected INIT-ACK handler. 17488c2ecf20Sopenharmony_ci * 17498c2ecf20Sopenharmony_ci * Section 5.2.3 17508c2ecf20Sopenharmony_ci * If an INIT ACK received by an endpoint in any state other than the 17518c2ecf20Sopenharmony_ci * COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk. 17528c2ecf20Sopenharmony_ci * An unexpected INIT ACK usually indicates the processing of an old or 17538c2ecf20Sopenharmony_ci * duplicated INIT chunk. 17548c2ecf20Sopenharmony_ci*/ 17558c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_3_initack( 17568c2ecf20Sopenharmony_ci struct net *net, 17578c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 17588c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 17598c2ecf20Sopenharmony_ci const union sctp_subtype type, 17608c2ecf20Sopenharmony_ci void *arg, 17618c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 17628c2ecf20Sopenharmony_ci{ 17638c2ecf20Sopenharmony_ci /* Per the above section, we'll discard the chunk if we have an 17648c2ecf20Sopenharmony_ci * endpoint. If this is an OOTB INIT-ACK, treat it as such. 17658c2ecf20Sopenharmony_ci */ 17668c2ecf20Sopenharmony_ci if (ep == sctp_sk(net->sctp.ctl_sock)->ep) 17678c2ecf20Sopenharmony_ci return sctp_sf_ootb(net, ep, asoc, type, arg, commands); 17688c2ecf20Sopenharmony_ci else 17698c2ecf20Sopenharmony_ci return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); 17708c2ecf20Sopenharmony_ci} 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci/* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A') 17738c2ecf20Sopenharmony_ci * 17748c2ecf20Sopenharmony_ci * Section 5.2.4 17758c2ecf20Sopenharmony_ci * A) In this case, the peer may have restarted. 17768c2ecf20Sopenharmony_ci */ 17778c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_a( 17788c2ecf20Sopenharmony_ci struct net *net, 17798c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 17808c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 17818c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 17828c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 17838c2ecf20Sopenharmony_ci struct sctp_association *new_asoc) 17848c2ecf20Sopenharmony_ci{ 17858c2ecf20Sopenharmony_ci struct sctp_init_chunk *peer_init; 17868c2ecf20Sopenharmony_ci enum sctp_disposition disposition; 17878c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev; 17888c2ecf20Sopenharmony_ci struct sctp_chunk *repl; 17898c2ecf20Sopenharmony_ci struct sctp_chunk *err; 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci /* new_asoc is a brand-new association, so these are not yet 17928c2ecf20Sopenharmony_ci * side effects--it is safe to run them here. 17938c2ecf20Sopenharmony_ci */ 17948c2ecf20Sopenharmony_ci peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, 17978c2ecf20Sopenharmony_ci GFP_ATOMIC)) 17988c2ecf20Sopenharmony_ci goto nomem; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci if (sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC)) 18018c2ecf20Sopenharmony_ci goto nomem; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) 18048c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci /* Make sure no new addresses are being added during the 18078c2ecf20Sopenharmony_ci * restart. Though this is a pretty complicated attack 18088c2ecf20Sopenharmony_ci * since you'd have to get inside the cookie. 18098c2ecf20Sopenharmony_ci */ 18108c2ecf20Sopenharmony_ci if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) 18118c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci /* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes 18148c2ecf20Sopenharmony_ci * the peer has restarted (Action A), it MUST NOT setup a new 18158c2ecf20Sopenharmony_ci * association but instead resend the SHUTDOWN ACK and send an ERROR 18168c2ecf20Sopenharmony_ci * chunk with a "Cookie Received while Shutting Down" error cause to 18178c2ecf20Sopenharmony_ci * its peer. 18188c2ecf20Sopenharmony_ci */ 18198c2ecf20Sopenharmony_ci if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) { 18208c2ecf20Sopenharmony_ci disposition = __sctp_sf_do_9_2_reshutack(net, ep, asoc, 18218c2ecf20Sopenharmony_ci SCTP_ST_CHUNK(chunk->chunk_hdr->type), 18228c2ecf20Sopenharmony_ci chunk, commands); 18238c2ecf20Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == disposition) 18248c2ecf20Sopenharmony_ci goto nomem; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci err = sctp_make_op_error(asoc, chunk, 18278c2ecf20Sopenharmony_ci SCTP_ERROR_COOKIE_IN_SHUTDOWN, 18288c2ecf20Sopenharmony_ci NULL, 0, 0); 18298c2ecf20Sopenharmony_ci if (err) 18308c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 18318c2ecf20Sopenharmony_ci SCTP_CHUNK(err)); 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 18348c2ecf20Sopenharmony_ci } 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci /* For now, stop pending T3-rtx and SACK timers, fail any unsent/unacked 18378c2ecf20Sopenharmony_ci * data. Consider the optional choice of resending of this data. 18388c2ecf20Sopenharmony_ci */ 18398c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL()); 18408c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 18418c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); 18428c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci /* Stop pending T4-rto timer, teardown ASCONF queue, ASCONF-ACK queue 18458c2ecf20Sopenharmony_ci * and ASCONF-ACK cache. 18468c2ecf20Sopenharmony_ci */ 18478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 18488c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 18498c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL()); 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci /* Update the content of current association. */ 18528c2ecf20Sopenharmony_ci if (sctp_assoc_update((struct sctp_association *)asoc, new_asoc)) { 18538c2ecf20Sopenharmony_ci struct sctp_chunk *abort; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci abort = sctp_make_abort(asoc, NULL, sizeof(struct sctp_errhdr)); 18568c2ecf20Sopenharmony_ci if (abort) { 18578c2ecf20Sopenharmony_ci sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); 18588c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); 18618c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 18628c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_RSRC_LOW)); 18638c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 18648c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 18658c2ecf20Sopenharmony_ci goto nomem; 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci repl = sctp_make_cookie_ack(asoc, chunk); 18698c2ecf20Sopenharmony_ci if (!repl) 18708c2ecf20Sopenharmony_ci goto nomem; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci /* Report association restart to upper layer. */ 18738c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, 18748c2ecf20Sopenharmony_ci asoc->c.sinit_num_ostreams, 18758c2ecf20Sopenharmony_ci asoc->c.sinit_max_instreams, 18768c2ecf20Sopenharmony_ci NULL, GFP_ATOMIC); 18778c2ecf20Sopenharmony_ci if (!ev) 18788c2ecf20Sopenharmony_ci goto nomem_ev; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 18818c2ecf20Sopenharmony_ci if ((sctp_state(asoc, SHUTDOWN_PENDING) || 18828c2ecf20Sopenharmony_ci sctp_state(asoc, SHUTDOWN_SENT)) && 18838c2ecf20Sopenharmony_ci (sctp_sstate(asoc->base.sk, CLOSING) || 18848c2ecf20Sopenharmony_ci sock_flag(asoc->base.sk, SOCK_DEAD))) { 18858c2ecf20Sopenharmony_ci /* If the socket has been closed by user, don't 18868c2ecf20Sopenharmony_ci * transition to ESTABLISHED. Instead trigger SHUTDOWN 18878c2ecf20Sopenharmony_ci * bundled with COOKIE_ACK. 18888c2ecf20Sopenharmony_ci */ 18898c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 18908c2ecf20Sopenharmony_ci return sctp_sf_do_9_2_start_shutdown(net, ep, asoc, 18918c2ecf20Sopenharmony_ci SCTP_ST_CHUNK(0), repl, 18928c2ecf20Sopenharmony_ci commands); 18938c2ecf20Sopenharmony_ci } else { 18948c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 18958c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 18968c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_cinomem_ev: 19018c2ecf20Sopenharmony_ci sctp_chunk_free(repl); 19028c2ecf20Sopenharmony_cinomem: 19038c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 19048c2ecf20Sopenharmony_ci} 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci/* Unexpected COOKIE-ECHO handler for setup collision (Table 2, action 'B') 19078c2ecf20Sopenharmony_ci * 19088c2ecf20Sopenharmony_ci * Section 5.2.4 19098c2ecf20Sopenharmony_ci * B) In this case, both sides may be attempting to start an association 19108c2ecf20Sopenharmony_ci * at about the same time but the peer endpoint started its INIT 19118c2ecf20Sopenharmony_ci * after responding to the local endpoint's INIT 19128c2ecf20Sopenharmony_ci */ 19138c2ecf20Sopenharmony_ci/* This case represents an initialization collision. */ 19148c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_b( 19158c2ecf20Sopenharmony_ci struct net *net, 19168c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 19178c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 19188c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 19198c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 19208c2ecf20Sopenharmony_ci struct sctp_association *new_asoc) 19218c2ecf20Sopenharmony_ci{ 19228c2ecf20Sopenharmony_ci struct sctp_init_chunk *peer_init; 19238c2ecf20Sopenharmony_ci struct sctp_chunk *repl; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci /* new_asoc is a brand-new association, so these are not yet 19268c2ecf20Sopenharmony_ci * side effects--it is safe to run them here. 19278c2ecf20Sopenharmony_ci */ 19288c2ecf20Sopenharmony_ci peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; 19298c2ecf20Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, 19308c2ecf20Sopenharmony_ci GFP_ATOMIC)) 19318c2ecf20Sopenharmony_ci goto nomem; 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci if (sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC)) 19348c2ecf20Sopenharmony_ci goto nomem; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) 19378c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci /* Update the content of current association. */ 19408c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); 19418c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 19428c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 19438c2ecf20Sopenharmony_ci if (asoc->state < SCTP_STATE_ESTABLISHED) 19448c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 19458c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci repl = sctp_make_cookie_ack(new_asoc, chunk); 19488c2ecf20Sopenharmony_ci if (!repl) 19498c2ecf20Sopenharmony_ci goto nomem; 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 19548c2ecf20Sopenharmony_ci * 19558c2ecf20Sopenharmony_ci * D) IMPLEMENTATION NOTE: An implementation may choose to 19568c2ecf20Sopenharmony_ci * send the Communication Up notification to the SCTP user 19578c2ecf20Sopenharmony_ci * upon reception of a valid COOKIE ECHO chunk. 19588c2ecf20Sopenharmony_ci * 19598c2ecf20Sopenharmony_ci * Sadly, this needs to be implemented as a side-effect, because 19608c2ecf20Sopenharmony_ci * we are not guaranteed to have set the association id of the real 19618c2ecf20Sopenharmony_ci * association and so these notifications need to be delayed until 19628c2ecf20Sopenharmony_ci * the association id is allocated. 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_CHANGE, SCTP_U8(SCTP_COMM_UP)); 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 19688c2ecf20Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter , SCTP 19698c2ecf20Sopenharmony_ci * delivers this notification to inform the application that of the 19708c2ecf20Sopenharmony_ci * peers requested adaptation layer. 19718c2ecf20Sopenharmony_ci * 19728c2ecf20Sopenharmony_ci * This also needs to be done as a side effect for the same reason as 19738c2ecf20Sopenharmony_ci * above. 19748c2ecf20Sopenharmony_ci */ 19758c2ecf20Sopenharmony_ci if (asoc->peer.adaptation_ind) 19768c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL()); 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci if (!asoc->peer.auth_capable) 19798c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PEER_NO_AUTH, SCTP_NULL()); 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_cinomem: 19848c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 19858c2ecf20Sopenharmony_ci} 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci/* Unexpected COOKIE-ECHO handler for setup collision (Table 2, action 'C') 19888c2ecf20Sopenharmony_ci * 19898c2ecf20Sopenharmony_ci * Section 5.2.4 19908c2ecf20Sopenharmony_ci * C) In this case, the local endpoint's cookie has arrived late. 19918c2ecf20Sopenharmony_ci * Before it arrived, the local endpoint sent an INIT and received an 19928c2ecf20Sopenharmony_ci * INIT-ACK and finally sent a COOKIE ECHO with the peer's same tag 19938c2ecf20Sopenharmony_ci * but a new tag of its own. 19948c2ecf20Sopenharmony_ci */ 19958c2ecf20Sopenharmony_ci/* This case represents an initialization collision. */ 19968c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_c( 19978c2ecf20Sopenharmony_ci struct net *net, 19988c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 19998c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 20008c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 20018c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 20028c2ecf20Sopenharmony_ci struct sctp_association *new_asoc) 20038c2ecf20Sopenharmony_ci{ 20048c2ecf20Sopenharmony_ci /* The cookie should be silently discarded. 20058c2ecf20Sopenharmony_ci * The endpoint SHOULD NOT change states and should leave 20068c2ecf20Sopenharmony_ci * any timers running. 20078c2ecf20Sopenharmony_ci */ 20088c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 20098c2ecf20Sopenharmony_ci} 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci/* Unexpected COOKIE-ECHO handler lost chunk (Table 2, action 'D') 20128c2ecf20Sopenharmony_ci * 20138c2ecf20Sopenharmony_ci * Section 5.2.4 20148c2ecf20Sopenharmony_ci * 20158c2ecf20Sopenharmony_ci * D) When both local and remote tags match the endpoint should always 20168c2ecf20Sopenharmony_ci * enter the ESTABLISHED state, if it has not already done so. 20178c2ecf20Sopenharmony_ci */ 20188c2ecf20Sopenharmony_ci/* This case represents an initialization collision. */ 20198c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_d( 20208c2ecf20Sopenharmony_ci struct net *net, 20218c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 20228c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 20238c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 20248c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 20258c2ecf20Sopenharmony_ci struct sctp_association *new_asoc) 20268c2ecf20Sopenharmony_ci{ 20278c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev = NULL, *ai_ev = NULL, *auth_ev = NULL; 20288c2ecf20Sopenharmony_ci struct sctp_chunk *repl; 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci /* Clarification from Implementor's Guide: 20318c2ecf20Sopenharmony_ci * D) When both local and remote tags match the endpoint should 20328c2ecf20Sopenharmony_ci * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state. 20338c2ecf20Sopenharmony_ci * It should stop any cookie timer that may be running and send 20348c2ecf20Sopenharmony_ci * a COOKIE ACK. 20358c2ecf20Sopenharmony_ci */ 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, asoc)) 20388c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci /* Don't accidentally move back into established state. */ 20418c2ecf20Sopenharmony_ci if (asoc->state < SCTP_STATE_ESTABLISHED) { 20428c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 20438c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 20448c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 20458c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 20468c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 20478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, 20488c2ecf20Sopenharmony_ci SCTP_NULL()); 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 20518c2ecf20Sopenharmony_ci * 20528c2ecf20Sopenharmony_ci * D) IMPLEMENTATION NOTE: An implementation may choose 20538c2ecf20Sopenharmony_ci * to send the Communication Up notification to the 20548c2ecf20Sopenharmony_ci * SCTP user upon reception of a valid COOKIE 20558c2ecf20Sopenharmony_ci * ECHO chunk. 20568c2ecf20Sopenharmony_ci */ 20578c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, 20588c2ecf20Sopenharmony_ci SCTP_COMM_UP, 0, 20598c2ecf20Sopenharmony_ci asoc->c.sinit_num_ostreams, 20608c2ecf20Sopenharmony_ci asoc->c.sinit_max_instreams, 20618c2ecf20Sopenharmony_ci NULL, GFP_ATOMIC); 20628c2ecf20Sopenharmony_ci if (!ev) 20638c2ecf20Sopenharmony_ci goto nomem; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 20668c2ecf20Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter, 20678c2ecf20Sopenharmony_ci * SCTP delivers this notification to inform the application 20688c2ecf20Sopenharmony_ci * that of the peers requested adaptation layer. 20698c2ecf20Sopenharmony_ci */ 20708c2ecf20Sopenharmony_ci if (asoc->peer.adaptation_ind) { 20718c2ecf20Sopenharmony_ci ai_ev = sctp_ulpevent_make_adaptation_indication(asoc, 20728c2ecf20Sopenharmony_ci GFP_ATOMIC); 20738c2ecf20Sopenharmony_ci if (!ai_ev) 20748c2ecf20Sopenharmony_ci goto nomem; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci } 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci if (!asoc->peer.auth_capable) { 20798c2ecf20Sopenharmony_ci auth_ev = sctp_ulpevent_make_authkey(asoc, 0, 20808c2ecf20Sopenharmony_ci SCTP_AUTH_NO_AUTH, 20818c2ecf20Sopenharmony_ci GFP_ATOMIC); 20828c2ecf20Sopenharmony_ci if (!auth_ev) 20838c2ecf20Sopenharmony_ci goto nomem; 20848c2ecf20Sopenharmony_ci } 20858c2ecf20Sopenharmony_ci } 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci repl = sctp_make_cookie_ack(asoc, chunk); 20888c2ecf20Sopenharmony_ci if (!repl) 20898c2ecf20Sopenharmony_ci goto nomem; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci if (ev) 20948c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 20958c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ev)); 20968c2ecf20Sopenharmony_ci if (ai_ev) 20978c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 20988c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ai_ev)); 20998c2ecf20Sopenharmony_ci if (auth_ev) 21008c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 21018c2ecf20Sopenharmony_ci SCTP_ULPEVENT(auth_ev)); 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_cinomem: 21068c2ecf20Sopenharmony_ci if (auth_ev) 21078c2ecf20Sopenharmony_ci sctp_ulpevent_free(auth_ev); 21088c2ecf20Sopenharmony_ci if (ai_ev) 21098c2ecf20Sopenharmony_ci sctp_ulpevent_free(ai_ev); 21108c2ecf20Sopenharmony_ci if (ev) 21118c2ecf20Sopenharmony_ci sctp_ulpevent_free(ev); 21128c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 21138c2ecf20Sopenharmony_ci} 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci/* 21168c2ecf20Sopenharmony_ci * Handle a duplicate COOKIE-ECHO. This usually means a cookie-carrying 21178c2ecf20Sopenharmony_ci * chunk was retransmitted and then delayed in the network. 21188c2ecf20Sopenharmony_ci * 21198c2ecf20Sopenharmony_ci * Section: 5.2.4 Handle a COOKIE ECHO when a TCB exists 21208c2ecf20Sopenharmony_ci * 21218c2ecf20Sopenharmony_ci * Verification Tag: None. Do cookie validation. 21228c2ecf20Sopenharmony_ci * 21238c2ecf20Sopenharmony_ci * Inputs 21248c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 21258c2ecf20Sopenharmony_ci * 21268c2ecf20Sopenharmony_ci * Outputs 21278c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 21288c2ecf20Sopenharmony_ci * 21298c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 21308c2ecf20Sopenharmony_ci */ 21318c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_4_dupcook( 21328c2ecf20Sopenharmony_ci struct net *net, 21338c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 21348c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 21358c2ecf20Sopenharmony_ci const union sctp_subtype type, 21368c2ecf20Sopenharmony_ci void *arg, 21378c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 21388c2ecf20Sopenharmony_ci{ 21398c2ecf20Sopenharmony_ci struct sctp_association *new_asoc; 21408c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 21418c2ecf20Sopenharmony_ci enum sctp_disposition retval; 21428c2ecf20Sopenharmony_ci struct sctp_chunk *err_chk_p; 21438c2ecf20Sopenharmony_ci int error = 0; 21448c2ecf20Sopenharmony_ci char action; 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci /* Make sure that the chunk has a valid length from the protocol 21478c2ecf20Sopenharmony_ci * perspective. In this case check to make sure we have at least 21488c2ecf20Sopenharmony_ci * enough for the chunk header. Cookie length verification is 21498c2ecf20Sopenharmony_ci * done later. 21508c2ecf20Sopenharmony_ci */ 21518c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) { 21528c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 21538c2ecf20Sopenharmony_ci asoc = NULL; 21548c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, commands); 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci /* "Decode" the chunk. We have no optional parameters so we 21588c2ecf20Sopenharmony_ci * are in good shape. 21598c2ecf20Sopenharmony_ci */ 21608c2ecf20Sopenharmony_ci chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; 21618c2ecf20Sopenharmony_ci if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - 21628c2ecf20Sopenharmony_ci sizeof(struct sctp_chunkhdr))) 21638c2ecf20Sopenharmony_ci goto nomem; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci /* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie 21668c2ecf20Sopenharmony_ci * of a duplicate COOKIE ECHO match the Verification Tags of the 21678c2ecf20Sopenharmony_ci * current association, consider the State Cookie valid even if 21688c2ecf20Sopenharmony_ci * the lifespan is exceeded. 21698c2ecf20Sopenharmony_ci */ 21708c2ecf20Sopenharmony_ci new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error, 21718c2ecf20Sopenharmony_ci &err_chk_p); 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci /* FIXME: 21748c2ecf20Sopenharmony_ci * If the re-build failed, what is the proper error path 21758c2ecf20Sopenharmony_ci * from here? 21768c2ecf20Sopenharmony_ci * 21778c2ecf20Sopenharmony_ci * [We should abort the association. --piggy] 21788c2ecf20Sopenharmony_ci */ 21798c2ecf20Sopenharmony_ci if (!new_asoc) { 21808c2ecf20Sopenharmony_ci /* FIXME: Several errors are possible. A bad cookie should 21818c2ecf20Sopenharmony_ci * be silently discarded, but think about logging it too. 21828c2ecf20Sopenharmony_ci */ 21838c2ecf20Sopenharmony_ci switch (error) { 21848c2ecf20Sopenharmony_ci case -SCTP_IERROR_NOMEM: 21858c2ecf20Sopenharmony_ci goto nomem; 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_ci case -SCTP_IERROR_STALE_COOKIE: 21888c2ecf20Sopenharmony_ci sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands, 21898c2ecf20Sopenharmony_ci err_chk_p); 21908c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 21918c2ecf20Sopenharmony_ci case -SCTP_IERROR_BAD_SIG: 21928c2ecf20Sopenharmony_ci default: 21938c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 21948c2ecf20Sopenharmony_ci } 21958c2ecf20Sopenharmony_ci } 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci /* Update socket peer label if first association. */ 21988c2ecf20Sopenharmony_ci if (security_sctp_assoc_request((struct sctp_endpoint *)ep, 21998c2ecf20Sopenharmony_ci chunk->skb)) { 22008c2ecf20Sopenharmony_ci sctp_association_free(new_asoc); 22018c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 22028c2ecf20Sopenharmony_ci } 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci /* Set temp so that it won't be added into hashtable */ 22058c2ecf20Sopenharmony_ci new_asoc->temp = 1; 22068c2ecf20Sopenharmony_ci 22078c2ecf20Sopenharmony_ci /* Compare the tie_tag in cookie with the verification tag of 22088c2ecf20Sopenharmony_ci * current association. 22098c2ecf20Sopenharmony_ci */ 22108c2ecf20Sopenharmony_ci action = sctp_tietags_compare(new_asoc, asoc); 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci switch (action) { 22138c2ecf20Sopenharmony_ci case 'A': /* Association restart. */ 22148c2ecf20Sopenharmony_ci retval = sctp_sf_do_dupcook_a(net, ep, asoc, chunk, commands, 22158c2ecf20Sopenharmony_ci new_asoc); 22168c2ecf20Sopenharmony_ci break; 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci case 'B': /* Collision case B. */ 22198c2ecf20Sopenharmony_ci retval = sctp_sf_do_dupcook_b(net, ep, asoc, chunk, commands, 22208c2ecf20Sopenharmony_ci new_asoc); 22218c2ecf20Sopenharmony_ci break; 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_ci case 'C': /* Collision case C. */ 22248c2ecf20Sopenharmony_ci retval = sctp_sf_do_dupcook_c(net, ep, asoc, chunk, commands, 22258c2ecf20Sopenharmony_ci new_asoc); 22268c2ecf20Sopenharmony_ci break; 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci case 'D': /* Collision case D. */ 22298c2ecf20Sopenharmony_ci retval = sctp_sf_do_dupcook_d(net, ep, asoc, chunk, commands, 22308c2ecf20Sopenharmony_ci new_asoc); 22318c2ecf20Sopenharmony_ci break; 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ci default: /* Discard packet for all others. */ 22348c2ecf20Sopenharmony_ci retval = sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 22358c2ecf20Sopenharmony_ci break; 22368c2ecf20Sopenharmony_ci } 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci /* Delete the tempory new association. */ 22398c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc)); 22408c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci /* Restore association pointer to provide SCTP command interpeter 22438c2ecf20Sopenharmony_ci * with a valid context in case it needs to manipulate 22448c2ecf20Sopenharmony_ci * the queues */ 22458c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, 22468c2ecf20Sopenharmony_ci SCTP_ASOC((struct sctp_association *)asoc)); 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci return retval; 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_cinomem: 22518c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 22528c2ecf20Sopenharmony_ci} 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ci/* 22558c2ecf20Sopenharmony_ci * Process an ABORT. (SHUTDOWN-PENDING state) 22568c2ecf20Sopenharmony_ci * 22578c2ecf20Sopenharmony_ci * See sctp_sf_do_9_1_abort(). 22588c2ecf20Sopenharmony_ci */ 22598c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_pending_abort( 22608c2ecf20Sopenharmony_ci struct net *net, 22618c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 22628c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 22638c2ecf20Sopenharmony_ci const union sctp_subtype type, 22648c2ecf20Sopenharmony_ci void *arg, 22658c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 22668c2ecf20Sopenharmony_ci{ 22678c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 22708c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 22738c2ecf20Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 22748c2ecf20Sopenharmony_ci * because of the following text: 22758c2ecf20Sopenharmony_ci * RFC 2960, Section 3.3.7 22768c2ecf20Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 22778c2ecf20Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 22788c2ecf20Sopenharmony_ci * Because the length is "invalid", we can't really discard just 22798c2ecf20Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 22808c2ecf20Sopenharmony_ci * packet. 22818c2ecf20Sopenharmony_ci */ 22828c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 22838c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci /* ADD-IP: Special case for ABORT chunks 22868c2ecf20Sopenharmony_ci * F4) One special consideration is that ABORT Chunks arriving 22878c2ecf20Sopenharmony_ci * destined to the IP address being deleted MUST be 22888c2ecf20Sopenharmony_ci * ignored (see Section 5.3.1 for further details). 22898c2ecf20Sopenharmony_ci */ 22908c2ecf20Sopenharmony_ci if (SCTP_ADDR_DEL == 22918c2ecf20Sopenharmony_ci sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) 22928c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci if (!sctp_err_chunk_valid(chunk)) 22958c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); 22988c2ecf20Sopenharmony_ci} 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci/* 23018c2ecf20Sopenharmony_ci * Process an ABORT. (SHUTDOWN-SENT state) 23028c2ecf20Sopenharmony_ci * 23038c2ecf20Sopenharmony_ci * See sctp_sf_do_9_1_abort(). 23048c2ecf20Sopenharmony_ci */ 23058c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_sent_abort( 23068c2ecf20Sopenharmony_ci struct net *net, 23078c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 23088c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 23098c2ecf20Sopenharmony_ci const union sctp_subtype type, 23108c2ecf20Sopenharmony_ci void *arg, 23118c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 23128c2ecf20Sopenharmony_ci{ 23138c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 23168c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 23198c2ecf20Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 23208c2ecf20Sopenharmony_ci * because of the following text: 23218c2ecf20Sopenharmony_ci * RFC 2960, Section 3.3.7 23228c2ecf20Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 23238c2ecf20Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 23248c2ecf20Sopenharmony_ci * Because the length is "invalid", we can't really discard just 23258c2ecf20Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 23268c2ecf20Sopenharmony_ci * packet. 23278c2ecf20Sopenharmony_ci */ 23288c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 23298c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci /* ADD-IP: Special case for ABORT chunks 23328c2ecf20Sopenharmony_ci * F4) One special consideration is that ABORT Chunks arriving 23338c2ecf20Sopenharmony_ci * destined to the IP address being deleted MUST be 23348c2ecf20Sopenharmony_ci * ignored (see Section 5.3.1 for further details). 23358c2ecf20Sopenharmony_ci */ 23368c2ecf20Sopenharmony_ci if (SCTP_ADDR_DEL == 23378c2ecf20Sopenharmony_ci sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) 23388c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci if (!sctp_err_chunk_valid(chunk)) 23418c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci /* Stop the T2-shutdown timer. */ 23448c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 23458c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci /* Stop the T5-shutdown guard timer. */ 23488c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 23498c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_ci return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); 23528c2ecf20Sopenharmony_ci} 23538c2ecf20Sopenharmony_ci 23548c2ecf20Sopenharmony_ci/* 23558c2ecf20Sopenharmony_ci * Process an ABORT. (SHUTDOWN-ACK-SENT state) 23568c2ecf20Sopenharmony_ci * 23578c2ecf20Sopenharmony_ci * See sctp_sf_do_9_1_abort(). 23588c2ecf20Sopenharmony_ci */ 23598c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_ack_sent_abort( 23608c2ecf20Sopenharmony_ci struct net *net, 23618c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 23628c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 23638c2ecf20Sopenharmony_ci const union sctp_subtype type, 23648c2ecf20Sopenharmony_ci void *arg, 23658c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 23668c2ecf20Sopenharmony_ci{ 23678c2ecf20Sopenharmony_ci /* The same T2 timer, so we should be able to use 23688c2ecf20Sopenharmony_ci * common function with the SHUTDOWN-SENT state. 23698c2ecf20Sopenharmony_ci */ 23708c2ecf20Sopenharmony_ci return sctp_sf_shutdown_sent_abort(net, ep, asoc, type, arg, commands); 23718c2ecf20Sopenharmony_ci} 23728c2ecf20Sopenharmony_ci 23738c2ecf20Sopenharmony_ci/* 23748c2ecf20Sopenharmony_ci * Handle an Error received in COOKIE_ECHOED state. 23758c2ecf20Sopenharmony_ci * 23768c2ecf20Sopenharmony_ci * Only handle the error type of stale COOKIE Error, the other errors will 23778c2ecf20Sopenharmony_ci * be ignored. 23788c2ecf20Sopenharmony_ci * 23798c2ecf20Sopenharmony_ci * Inputs 23808c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 23818c2ecf20Sopenharmony_ci * 23828c2ecf20Sopenharmony_ci * Outputs 23838c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 23848c2ecf20Sopenharmony_ci * 23858c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 23868c2ecf20Sopenharmony_ci */ 23878c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_err( 23888c2ecf20Sopenharmony_ci struct net *net, 23898c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 23908c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 23918c2ecf20Sopenharmony_ci const union sctp_subtype type, 23928c2ecf20Sopenharmony_ci void *arg, 23938c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 23948c2ecf20Sopenharmony_ci{ 23958c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 23968c2ecf20Sopenharmony_ci struct sctp_errhdr *err; 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 23998c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci /* Make sure that the ERROR chunk has a valid length. 24028c2ecf20Sopenharmony_ci * The parameter walking depends on this as well. 24038c2ecf20Sopenharmony_ci */ 24048c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_operr_chunk))) 24058c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 24068c2ecf20Sopenharmony_ci commands); 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci /* Process the error here */ 24098c2ecf20Sopenharmony_ci /* FUTURE FIXME: When PR-SCTP related and other optional 24108c2ecf20Sopenharmony_ci * parms are emitted, this will have to change to handle multiple 24118c2ecf20Sopenharmony_ci * errors. 24128c2ecf20Sopenharmony_ci */ 24138c2ecf20Sopenharmony_ci sctp_walk_errors(err, chunk->chunk_hdr) { 24148c2ecf20Sopenharmony_ci if (SCTP_ERROR_STALE_COOKIE == err->cause) 24158c2ecf20Sopenharmony_ci return sctp_sf_do_5_2_6_stale(net, ep, asoc, type, 24168c2ecf20Sopenharmony_ci arg, commands); 24178c2ecf20Sopenharmony_ci } 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci /* It is possible to have malformed error causes, and that 24208c2ecf20Sopenharmony_ci * will cause us to end the walk early. However, since 24218c2ecf20Sopenharmony_ci * we are discarding the packet, there should be no adverse 24228c2ecf20Sopenharmony_ci * affects. 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 24258c2ecf20Sopenharmony_ci} 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci/* 24288c2ecf20Sopenharmony_ci * Handle a Stale COOKIE Error 24298c2ecf20Sopenharmony_ci * 24308c2ecf20Sopenharmony_ci * Section: 5.2.6 Handle Stale COOKIE Error 24318c2ecf20Sopenharmony_ci * If the association is in the COOKIE-ECHOED state, the endpoint may elect 24328c2ecf20Sopenharmony_ci * one of the following three alternatives. 24338c2ecf20Sopenharmony_ci * ... 24348c2ecf20Sopenharmony_ci * 3) Send a new INIT chunk to the endpoint, adding a Cookie 24358c2ecf20Sopenharmony_ci * Preservative parameter requesting an extension to the lifetime of 24368c2ecf20Sopenharmony_ci * the State Cookie. When calculating the time extension, an 24378c2ecf20Sopenharmony_ci * implementation SHOULD use the RTT information measured based on the 24388c2ecf20Sopenharmony_ci * previous COOKIE ECHO / ERROR exchange, and should add no more 24398c2ecf20Sopenharmony_ci * than 1 second beyond the measured RTT, due to long State Cookie 24408c2ecf20Sopenharmony_ci * lifetimes making the endpoint more subject to a replay attack. 24418c2ecf20Sopenharmony_ci * 24428c2ecf20Sopenharmony_ci * Verification Tag: Not explicit, but safe to ignore. 24438c2ecf20Sopenharmony_ci * 24448c2ecf20Sopenharmony_ci * Inputs 24458c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 24468c2ecf20Sopenharmony_ci * 24478c2ecf20Sopenharmony_ci * Outputs 24488c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 24498c2ecf20Sopenharmony_ci * 24508c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 24518c2ecf20Sopenharmony_ci */ 24528c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_5_2_6_stale( 24538c2ecf20Sopenharmony_ci struct net *net, 24548c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 24558c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 24568c2ecf20Sopenharmony_ci const union sctp_subtype type, 24578c2ecf20Sopenharmony_ci void *arg, 24588c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 24598c2ecf20Sopenharmony_ci{ 24608c2ecf20Sopenharmony_ci int attempts = asoc->init_err_counter + 1; 24618c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg, *reply; 24628c2ecf20Sopenharmony_ci struct sctp_cookie_preserve_param bht; 24638c2ecf20Sopenharmony_ci struct sctp_bind_addr *bp; 24648c2ecf20Sopenharmony_ci struct sctp_errhdr *err; 24658c2ecf20Sopenharmony_ci u32 stale; 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci if (attempts > asoc->max_init_attempts) { 24688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 24698c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 24708c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 24718c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_STALE_COOKIE)); 24728c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 24738c2ecf20Sopenharmony_ci } 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_ci err = (struct sctp_errhdr *)(chunk->skb->data); 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_ci /* When calculating the time extension, an implementation 24788c2ecf20Sopenharmony_ci * SHOULD use the RTT information measured based on the 24798c2ecf20Sopenharmony_ci * previous COOKIE ECHO / ERROR exchange, and should add no 24808c2ecf20Sopenharmony_ci * more than 1 second beyond the measured RTT, due to long 24818c2ecf20Sopenharmony_ci * State Cookie lifetimes making the endpoint more subject to 24828c2ecf20Sopenharmony_ci * a replay attack. 24838c2ecf20Sopenharmony_ci * Measure of Staleness's unit is usec. (1/1000000 sec) 24848c2ecf20Sopenharmony_ci * Suggested Cookie Life-span Increment's unit is msec. 24858c2ecf20Sopenharmony_ci * (1/1000 sec) 24868c2ecf20Sopenharmony_ci * In general, if you use the suggested cookie life, the value 24878c2ecf20Sopenharmony_ci * found in the field of measure of staleness should be doubled 24888c2ecf20Sopenharmony_ci * to give ample time to retransmit the new cookie and thus 24898c2ecf20Sopenharmony_ci * yield a higher probability of success on the reattempt. 24908c2ecf20Sopenharmony_ci */ 24918c2ecf20Sopenharmony_ci stale = ntohl(*(__be32 *)((u8 *)err + sizeof(*err))); 24928c2ecf20Sopenharmony_ci stale = (stale * 2) / 1000; 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE; 24958c2ecf20Sopenharmony_ci bht.param_hdr.length = htons(sizeof(bht)); 24968c2ecf20Sopenharmony_ci bht.lifespan_increment = htonl(stale); 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ci /* Build that new INIT chunk. */ 24998c2ecf20Sopenharmony_ci bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; 25008c2ecf20Sopenharmony_ci reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht)); 25018c2ecf20Sopenharmony_ci if (!reply) 25028c2ecf20Sopenharmony_ci goto nomem; 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci sctp_addto_chunk(reply, sizeof(bht), &bht); 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci /* Clear peer's init_tag cached in assoc as we are sending a new INIT */ 25078c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL()); 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci /* Stop pending T3-rtx and heartbeat timers */ 25108c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL()); 25118c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ci /* Delete non-primary peer ip addresses since we are transitioning 25148c2ecf20Sopenharmony_ci * back to the COOKIE-WAIT state 25158c2ecf20Sopenharmony_ci */ 25168c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL()); 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci /* If we've sent any data bundled with COOKIE-ECHO we will need to 25198c2ecf20Sopenharmony_ci * resend 25208c2ecf20Sopenharmony_ci */ 25218c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN, 25228c2ecf20Sopenharmony_ci SCTP_TRANSPORT(asoc->peer.primary_path)); 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci /* Cast away the const modifier, as we want to just 25258c2ecf20Sopenharmony_ci * rerun it through as a sideffect. 25268c2ecf20Sopenharmony_ci */ 25278c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL()); 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 25308c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 25318c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 25328c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_COOKIE_WAIT)); 25338c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 25348c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_cinomem: 25418c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 25428c2ecf20Sopenharmony_ci} 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci/* 25458c2ecf20Sopenharmony_ci * Process an ABORT. 25468c2ecf20Sopenharmony_ci * 25478c2ecf20Sopenharmony_ci * Section: 9.1 25488c2ecf20Sopenharmony_ci * After checking the Verification Tag, the receiving endpoint shall 25498c2ecf20Sopenharmony_ci * remove the association from its record, and shall report the 25508c2ecf20Sopenharmony_ci * termination to its upper layer. 25518c2ecf20Sopenharmony_ci * 25528c2ecf20Sopenharmony_ci * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules 25538c2ecf20Sopenharmony_ci * B) Rules for packet carrying ABORT: 25548c2ecf20Sopenharmony_ci * 25558c2ecf20Sopenharmony_ci * - The endpoint shall always fill in the Verification Tag field of the 25568c2ecf20Sopenharmony_ci * outbound packet with the destination endpoint's tag value if it 25578c2ecf20Sopenharmony_ci * is known. 25588c2ecf20Sopenharmony_ci * 25598c2ecf20Sopenharmony_ci * - If the ABORT is sent in response to an OOTB packet, the endpoint 25608c2ecf20Sopenharmony_ci * MUST follow the procedure described in Section 8.4. 25618c2ecf20Sopenharmony_ci * 25628c2ecf20Sopenharmony_ci * - The receiver MUST accept the packet if the Verification Tag 25638c2ecf20Sopenharmony_ci * matches either its own tag, OR the tag of its peer. Otherwise, the 25648c2ecf20Sopenharmony_ci * receiver MUST silently discard the packet and take no further 25658c2ecf20Sopenharmony_ci * action. 25668c2ecf20Sopenharmony_ci * 25678c2ecf20Sopenharmony_ci * Inputs 25688c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 25698c2ecf20Sopenharmony_ci * 25708c2ecf20Sopenharmony_ci * Outputs 25718c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 25728c2ecf20Sopenharmony_ci * 25738c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 25748c2ecf20Sopenharmony_ci */ 25758c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_1_abort( 25768c2ecf20Sopenharmony_ci struct net *net, 25778c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 25788c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 25798c2ecf20Sopenharmony_ci const union sctp_subtype type, 25808c2ecf20Sopenharmony_ci void *arg, 25818c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 25828c2ecf20Sopenharmony_ci{ 25838c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 25868c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 25898c2ecf20Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 25908c2ecf20Sopenharmony_ci * because of the following text: 25918c2ecf20Sopenharmony_ci * RFC 2960, Section 3.3.7 25928c2ecf20Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 25938c2ecf20Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 25948c2ecf20Sopenharmony_ci * Because the length is "invalid", we can't really discard just 25958c2ecf20Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 25968c2ecf20Sopenharmony_ci * packet. 25978c2ecf20Sopenharmony_ci */ 25988c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 25998c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci /* ADD-IP: Special case for ABORT chunks 26028c2ecf20Sopenharmony_ci * F4) One special consideration is that ABORT Chunks arriving 26038c2ecf20Sopenharmony_ci * destined to the IP address being deleted MUST be 26048c2ecf20Sopenharmony_ci * ignored (see Section 5.3.1 for further details). 26058c2ecf20Sopenharmony_ci */ 26068c2ecf20Sopenharmony_ci if (SCTP_ADDR_DEL == 26078c2ecf20Sopenharmony_ci sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) 26088c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_ci if (!sctp_err_chunk_valid(chunk)) 26118c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 26128c2ecf20Sopenharmony_ci 26138c2ecf20Sopenharmony_ci return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); 26148c2ecf20Sopenharmony_ci} 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_cistatic enum sctp_disposition __sctp_sf_do_9_1_abort( 26178c2ecf20Sopenharmony_ci struct net *net, 26188c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 26198c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 26208c2ecf20Sopenharmony_ci const union sctp_subtype type, 26218c2ecf20Sopenharmony_ci void *arg, 26228c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 26238c2ecf20Sopenharmony_ci{ 26248c2ecf20Sopenharmony_ci __be16 error = SCTP_ERROR_NO_ERROR; 26258c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 26268c2ecf20Sopenharmony_ci unsigned int len; 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci /* See if we have an error cause code in the chunk. */ 26298c2ecf20Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 26308c2ecf20Sopenharmony_ci if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) 26318c2ecf20Sopenharmony_ci error = ((struct sctp_errhdr *)chunk->skb->data)->cause; 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); 26348c2ecf20Sopenharmony_ci /* ASSOC_FAILED will DELETE_TCB. */ 26358c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error)); 26368c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 26378c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 26408c2ecf20Sopenharmony_ci} 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci/* 26438c2ecf20Sopenharmony_ci * Process an ABORT. (COOKIE-WAIT state) 26448c2ecf20Sopenharmony_ci * 26458c2ecf20Sopenharmony_ci * See sctp_sf_do_9_1_abort() above. 26468c2ecf20Sopenharmony_ci */ 26478c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_abort( 26488c2ecf20Sopenharmony_ci struct net *net, 26498c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 26508c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 26518c2ecf20Sopenharmony_ci const union sctp_subtype type, 26528c2ecf20Sopenharmony_ci void *arg, 26538c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 26548c2ecf20Sopenharmony_ci{ 26558c2ecf20Sopenharmony_ci __be16 error = SCTP_ERROR_NO_ERROR; 26568c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 26578c2ecf20Sopenharmony_ci unsigned int len; 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 26608c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 26618c2ecf20Sopenharmony_ci 26628c2ecf20Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 26638c2ecf20Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 26648c2ecf20Sopenharmony_ci * because of the following text: 26658c2ecf20Sopenharmony_ci * RFC 2960, Section 3.3.7 26668c2ecf20Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 26678c2ecf20Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 26688c2ecf20Sopenharmony_ci * Because the length is "invalid", we can't really discard just 26698c2ecf20Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 26708c2ecf20Sopenharmony_ci * packet. 26718c2ecf20Sopenharmony_ci */ 26728c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 26738c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 26748c2ecf20Sopenharmony_ci 26758c2ecf20Sopenharmony_ci /* See if we have an error cause code in the chunk. */ 26768c2ecf20Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 26778c2ecf20Sopenharmony_ci if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) 26788c2ecf20Sopenharmony_ci error = ((struct sctp_errhdr *)chunk->skb->data)->cause; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, asoc, 26818c2ecf20Sopenharmony_ci chunk->transport); 26828c2ecf20Sopenharmony_ci} 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci/* 26858c2ecf20Sopenharmony_ci * Process an incoming ICMP as an ABORT. (COOKIE-WAIT state) 26868c2ecf20Sopenharmony_ci */ 26878c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_icmp_abort( 26888c2ecf20Sopenharmony_ci struct net *net, 26898c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 26908c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 26918c2ecf20Sopenharmony_ci const union sctp_subtype type, 26928c2ecf20Sopenharmony_ci void *arg, 26938c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 26948c2ecf20Sopenharmony_ci{ 26958c2ecf20Sopenharmony_ci return sctp_stop_t1_and_abort(net, commands, SCTP_ERROR_NO_ERROR, 26968c2ecf20Sopenharmony_ci ENOPROTOOPT, asoc, 26978c2ecf20Sopenharmony_ci (struct sctp_transport *)arg); 26988c2ecf20Sopenharmony_ci} 26998c2ecf20Sopenharmony_ci 27008c2ecf20Sopenharmony_ci/* 27018c2ecf20Sopenharmony_ci * Process an ABORT. (COOKIE-ECHOED state) 27028c2ecf20Sopenharmony_ci */ 27038c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_abort( 27048c2ecf20Sopenharmony_ci struct net *net, 27058c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 27068c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 27078c2ecf20Sopenharmony_ci const union sctp_subtype type, 27088c2ecf20Sopenharmony_ci void *arg, 27098c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 27108c2ecf20Sopenharmony_ci{ 27118c2ecf20Sopenharmony_ci /* There is a single T1 timer, so we should be able to use 27128c2ecf20Sopenharmony_ci * common function with the COOKIE-WAIT state. 27138c2ecf20Sopenharmony_ci */ 27148c2ecf20Sopenharmony_ci return sctp_sf_cookie_wait_abort(net, ep, asoc, type, arg, commands); 27158c2ecf20Sopenharmony_ci} 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci/* 27188c2ecf20Sopenharmony_ci * Stop T1 timer and abort association with "INIT failed". 27198c2ecf20Sopenharmony_ci * 27208c2ecf20Sopenharmony_ci * This is common code called by several sctp_sf_*_abort() functions above. 27218c2ecf20Sopenharmony_ci */ 27228c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_stop_t1_and_abort( 27238c2ecf20Sopenharmony_ci struct net *net, 27248c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 27258c2ecf20Sopenharmony_ci __be16 error, int sk_err, 27268c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 27278c2ecf20Sopenharmony_ci struct sctp_transport *transport) 27288c2ecf20Sopenharmony_ci{ 27298c2ecf20Sopenharmony_ci pr_debug("%s: ABORT received (INIT)\n", __func__); 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 27328c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 27338c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 27348c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 27358c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 27368c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); 27378c2ecf20Sopenharmony_ci /* CMD_INIT_FAILED will DELETE_TCB. */ 27388c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 27398c2ecf20Sopenharmony_ci SCTP_PERR(error)); 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 27428c2ecf20Sopenharmony_ci} 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci/* 27458c2ecf20Sopenharmony_ci * sctp_sf_do_9_2_shut 27468c2ecf20Sopenharmony_ci * 27478c2ecf20Sopenharmony_ci * Section: 9.2 27488c2ecf20Sopenharmony_ci * Upon the reception of the SHUTDOWN, the peer endpoint shall 27498c2ecf20Sopenharmony_ci * - enter the SHUTDOWN-RECEIVED state, 27508c2ecf20Sopenharmony_ci * 27518c2ecf20Sopenharmony_ci * - stop accepting new data from its SCTP user 27528c2ecf20Sopenharmony_ci * 27538c2ecf20Sopenharmony_ci * - verify, by checking the Cumulative TSN Ack field of the chunk, 27548c2ecf20Sopenharmony_ci * that all its outstanding DATA chunks have been received by the 27558c2ecf20Sopenharmony_ci * SHUTDOWN sender. 27568c2ecf20Sopenharmony_ci * 27578c2ecf20Sopenharmony_ci * Once an endpoint as reached the SHUTDOWN-RECEIVED state it MUST NOT 27588c2ecf20Sopenharmony_ci * send a SHUTDOWN in response to a ULP request. And should discard 27598c2ecf20Sopenharmony_ci * subsequent SHUTDOWN chunks. 27608c2ecf20Sopenharmony_ci * 27618c2ecf20Sopenharmony_ci * If there are still outstanding DATA chunks left, the SHUTDOWN 27628c2ecf20Sopenharmony_ci * receiver shall continue to follow normal data transmission 27638c2ecf20Sopenharmony_ci * procedures defined in Section 6 until all outstanding DATA chunks 27648c2ecf20Sopenharmony_ci * are acknowledged; however, the SHUTDOWN receiver MUST NOT accept 27658c2ecf20Sopenharmony_ci * new data from its SCTP user. 27668c2ecf20Sopenharmony_ci * 27678c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 27688c2ecf20Sopenharmony_ci * 27698c2ecf20Sopenharmony_ci * Inputs 27708c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 27718c2ecf20Sopenharmony_ci * 27728c2ecf20Sopenharmony_ci * Outputs 27738c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 27748c2ecf20Sopenharmony_ci * 27758c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 27768c2ecf20Sopenharmony_ci */ 27778c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_shutdown( 27788c2ecf20Sopenharmony_ci struct net *net, 27798c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 27808c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 27818c2ecf20Sopenharmony_ci const union sctp_subtype type, 27828c2ecf20Sopenharmony_ci void *arg, 27838c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 27848c2ecf20Sopenharmony_ci{ 27858c2ecf20Sopenharmony_ci enum sctp_disposition disposition; 27868c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 27878c2ecf20Sopenharmony_ci struct sctp_shutdownhdr *sdh; 27888c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev; 27898c2ecf20Sopenharmony_ci __u32 ctsn; 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 27928c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci /* Make sure that the SHUTDOWN chunk has a valid length. */ 27958c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk))) 27968c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 27978c2ecf20Sopenharmony_ci commands); 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci /* Convert the elaborate header. */ 28008c2ecf20Sopenharmony_ci sdh = (struct sctp_shutdownhdr *)chunk->skb->data; 28018c2ecf20Sopenharmony_ci skb_pull(chunk->skb, sizeof(*sdh)); 28028c2ecf20Sopenharmony_ci chunk->subh.shutdown_hdr = sdh; 28038c2ecf20Sopenharmony_ci ctsn = ntohl(sdh->cum_tsn_ack); 28048c2ecf20Sopenharmony_ci 28058c2ecf20Sopenharmony_ci if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { 28068c2ecf20Sopenharmony_ci pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, 28078c2ecf20Sopenharmony_ci asoc->ctsn_ack_point); 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci /* If Cumulative TSN Ack beyond the max tsn currently 28138c2ecf20Sopenharmony_ci * send, terminating the association and respond to the 28148c2ecf20Sopenharmony_ci * sender with an ABORT. 28158c2ecf20Sopenharmony_ci */ 28168c2ecf20Sopenharmony_ci if (!TSN_lt(ctsn, asoc->next_tsn)) 28178c2ecf20Sopenharmony_ci return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT 28208c2ecf20Sopenharmony_ci * When a peer sends a SHUTDOWN, SCTP delivers this notification to 28218c2ecf20Sopenharmony_ci * inform the application that it should cease sending data. 28228c2ecf20Sopenharmony_ci */ 28238c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC); 28248c2ecf20Sopenharmony_ci if (!ev) { 28258c2ecf20Sopenharmony_ci disposition = SCTP_DISPOSITION_NOMEM; 28268c2ecf20Sopenharmony_ci goto out; 28278c2ecf20Sopenharmony_ci } 28288c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci /* Upon the reception of the SHUTDOWN, the peer endpoint shall 28318c2ecf20Sopenharmony_ci * - enter the SHUTDOWN-RECEIVED state, 28328c2ecf20Sopenharmony_ci * - stop accepting new data from its SCTP user 28338c2ecf20Sopenharmony_ci * 28348c2ecf20Sopenharmony_ci * [This is implicit in the new state.] 28358c2ecf20Sopenharmony_ci */ 28368c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 28378c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_RECEIVED)); 28388c2ecf20Sopenharmony_ci disposition = SCTP_DISPOSITION_CONSUME; 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_ci if (sctp_outq_is_empty(&asoc->outqueue)) { 28418c2ecf20Sopenharmony_ci disposition = sctp_sf_do_9_2_shutdown_ack(net, ep, asoc, type, 28428c2ecf20Sopenharmony_ci arg, commands); 28438c2ecf20Sopenharmony_ci } 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == disposition) 28468c2ecf20Sopenharmony_ci goto out; 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci /* - verify, by checking the Cumulative TSN Ack field of the 28498c2ecf20Sopenharmony_ci * chunk, that all its outstanding DATA chunks have been 28508c2ecf20Sopenharmony_ci * received by the SHUTDOWN sender. 28518c2ecf20Sopenharmony_ci */ 28528c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, 28538c2ecf20Sopenharmony_ci SCTP_BE32(chunk->subh.shutdown_hdr->cum_tsn_ack)); 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_ciout: 28568c2ecf20Sopenharmony_ci return disposition; 28578c2ecf20Sopenharmony_ci} 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_ci/* 28608c2ecf20Sopenharmony_ci * sctp_sf_do_9_2_shut_ctsn 28618c2ecf20Sopenharmony_ci * 28628c2ecf20Sopenharmony_ci * Once an endpoint has reached the SHUTDOWN-RECEIVED state, 28638c2ecf20Sopenharmony_ci * it MUST NOT send a SHUTDOWN in response to a ULP request. 28648c2ecf20Sopenharmony_ci * The Cumulative TSN Ack of the received SHUTDOWN chunk 28658c2ecf20Sopenharmony_ci * MUST be processed. 28668c2ecf20Sopenharmony_ci */ 28678c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_shut_ctsn( 28688c2ecf20Sopenharmony_ci struct net *net, 28698c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 28708c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 28718c2ecf20Sopenharmony_ci const union sctp_subtype type, 28728c2ecf20Sopenharmony_ci void *arg, 28738c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 28748c2ecf20Sopenharmony_ci{ 28758c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 28768c2ecf20Sopenharmony_ci struct sctp_shutdownhdr *sdh; 28778c2ecf20Sopenharmony_ci __u32 ctsn; 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 28808c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci /* Make sure that the SHUTDOWN chunk has a valid length. */ 28838c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk))) 28848c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 28858c2ecf20Sopenharmony_ci commands); 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci sdh = (struct sctp_shutdownhdr *)chunk->skb->data; 28888c2ecf20Sopenharmony_ci ctsn = ntohl(sdh->cum_tsn_ack); 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { 28918c2ecf20Sopenharmony_ci pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, 28928c2ecf20Sopenharmony_ci asoc->ctsn_ack_point); 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 28958c2ecf20Sopenharmony_ci } 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci /* If Cumulative TSN Ack beyond the max tsn currently 28988c2ecf20Sopenharmony_ci * send, terminating the association and respond to the 28998c2ecf20Sopenharmony_ci * sender with an ABORT. 29008c2ecf20Sopenharmony_ci */ 29018c2ecf20Sopenharmony_ci if (!TSN_lt(ctsn, asoc->next_tsn)) 29028c2ecf20Sopenharmony_ci return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 29038c2ecf20Sopenharmony_ci 29048c2ecf20Sopenharmony_ci /* verify, by checking the Cumulative TSN Ack field of the 29058c2ecf20Sopenharmony_ci * chunk, that all its outstanding DATA chunks have been 29068c2ecf20Sopenharmony_ci * received by the SHUTDOWN sender. 29078c2ecf20Sopenharmony_ci */ 29088c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, 29098c2ecf20Sopenharmony_ci SCTP_BE32(sdh->cum_tsn_ack)); 29108c2ecf20Sopenharmony_ci 29118c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 29128c2ecf20Sopenharmony_ci} 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci/* RFC 2960 9.2 29158c2ecf20Sopenharmony_ci * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk 29168c2ecf20Sopenharmony_ci * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination 29178c2ecf20Sopenharmony_ci * transport addresses (either in the IP addresses or in the INIT chunk) 29188c2ecf20Sopenharmony_ci * that belong to this association, it should discard the INIT chunk and 29198c2ecf20Sopenharmony_ci * retransmit the SHUTDOWN ACK chunk. 29208c2ecf20Sopenharmony_ci */ 29218c2ecf20Sopenharmony_cistatic enum sctp_disposition 29228c2ecf20Sopenharmony_ci__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, 29238c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 29248c2ecf20Sopenharmony_ci const union sctp_subtype type, void *arg, 29258c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 29268c2ecf20Sopenharmony_ci{ 29278c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 29288c2ecf20Sopenharmony_ci struct sctp_chunk *reply; 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ci /* Make sure that the chunk has a valid length */ 29318c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 29328c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 29338c2ecf20Sopenharmony_ci commands); 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci /* Since we are not going to really process this INIT, there 29368c2ecf20Sopenharmony_ci * is no point in verifying chunk boundries. Just generate 29378c2ecf20Sopenharmony_ci * the SHUTDOWN ACK. 29388c2ecf20Sopenharmony_ci */ 29398c2ecf20Sopenharmony_ci reply = sctp_make_shutdown_ack(asoc, chunk); 29408c2ecf20Sopenharmony_ci if (NULL == reply) 29418c2ecf20Sopenharmony_ci goto nomem; 29428c2ecf20Sopenharmony_ci 29438c2ecf20Sopenharmony_ci /* Set the transport for the SHUTDOWN ACK chunk and the timeout for 29448c2ecf20Sopenharmony_ci * the T2-SHUTDOWN timer. 29458c2ecf20Sopenharmony_ci */ 29468c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci /* and restart the T2-shutdown timer. */ 29498c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 29508c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 29518c2ecf20Sopenharmony_ci 29528c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 29538c2ecf20Sopenharmony_ci 29548c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 29558c2ecf20Sopenharmony_cinomem: 29568c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 29578c2ecf20Sopenharmony_ci} 29588c2ecf20Sopenharmony_ci 29598c2ecf20Sopenharmony_cienum sctp_disposition 29608c2ecf20Sopenharmony_cisctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, 29618c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 29628c2ecf20Sopenharmony_ci const union sctp_subtype type, void *arg, 29638c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 29648c2ecf20Sopenharmony_ci{ 29658c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 29668c2ecf20Sopenharmony_ci 29678c2ecf20Sopenharmony_ci if (!chunk->singleton) 29688c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 29698c2ecf20Sopenharmony_ci 29708c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) 29718c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 29728c2ecf20Sopenharmony_ci 29738c2ecf20Sopenharmony_ci if (chunk->sctp_hdr->vtag != 0) 29748c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci return __sctp_sf_do_9_2_reshutack(net, ep, asoc, type, arg, commands); 29778c2ecf20Sopenharmony_ci} 29788c2ecf20Sopenharmony_ci 29798c2ecf20Sopenharmony_ci/* 29808c2ecf20Sopenharmony_ci * sctp_sf_do_ecn_cwr 29818c2ecf20Sopenharmony_ci * 29828c2ecf20Sopenharmony_ci * Section: Appendix A: Explicit Congestion Notification 29838c2ecf20Sopenharmony_ci * 29848c2ecf20Sopenharmony_ci * CWR: 29858c2ecf20Sopenharmony_ci * 29868c2ecf20Sopenharmony_ci * RFC 2481 details a specific bit for a sender to send in the header of 29878c2ecf20Sopenharmony_ci * its next outbound TCP segment to indicate to its peer that it has 29888c2ecf20Sopenharmony_ci * reduced its congestion window. This is termed the CWR bit. For 29898c2ecf20Sopenharmony_ci * SCTP the same indication is made by including the CWR chunk. 29908c2ecf20Sopenharmony_ci * This chunk contains one data element, i.e. the TSN number that 29918c2ecf20Sopenharmony_ci * was sent in the ECNE chunk. This element represents the lowest 29928c2ecf20Sopenharmony_ci * TSN number in the datagram that was originally marked with the 29938c2ecf20Sopenharmony_ci * CE bit. 29948c2ecf20Sopenharmony_ci * 29958c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 29968c2ecf20Sopenharmony_ci * Inputs 29978c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 29988c2ecf20Sopenharmony_ci * 29998c2ecf20Sopenharmony_ci * Outputs 30008c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 30018c2ecf20Sopenharmony_ci * 30028c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 30038c2ecf20Sopenharmony_ci */ 30048c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_ecn_cwr(struct net *net, 30058c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 30068c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 30078c2ecf20Sopenharmony_ci const union sctp_subtype type, 30088c2ecf20Sopenharmony_ci void *arg, 30098c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 30108c2ecf20Sopenharmony_ci{ 30118c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 30128c2ecf20Sopenharmony_ci struct sctp_cwrhdr *cwr; 30138c2ecf20Sopenharmony_ci u32 lowest_tsn; 30148c2ecf20Sopenharmony_ci 30158c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 30168c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_ecne_chunk))) 30198c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 30208c2ecf20Sopenharmony_ci commands); 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_ci cwr = (struct sctp_cwrhdr *)chunk->skb->data; 30238c2ecf20Sopenharmony_ci skb_pull(chunk->skb, sizeof(*cwr)); 30248c2ecf20Sopenharmony_ci 30258c2ecf20Sopenharmony_ci lowest_tsn = ntohl(cwr->lowest_tsn); 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_ci /* Does this CWR ack the last sent congestion notification? */ 30288c2ecf20Sopenharmony_ci if (TSN_lte(asoc->last_ecne_tsn, lowest_tsn)) { 30298c2ecf20Sopenharmony_ci /* Stop sending ECNE. */ 30308c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, 30318c2ecf20Sopenharmony_ci SCTP_CMD_ECN_CWR, 30328c2ecf20Sopenharmony_ci SCTP_U32(lowest_tsn)); 30338c2ecf20Sopenharmony_ci } 30348c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 30358c2ecf20Sopenharmony_ci} 30368c2ecf20Sopenharmony_ci 30378c2ecf20Sopenharmony_ci/* 30388c2ecf20Sopenharmony_ci * sctp_sf_do_ecne 30398c2ecf20Sopenharmony_ci * 30408c2ecf20Sopenharmony_ci * Section: Appendix A: Explicit Congestion Notification 30418c2ecf20Sopenharmony_ci * 30428c2ecf20Sopenharmony_ci * ECN-Echo 30438c2ecf20Sopenharmony_ci * 30448c2ecf20Sopenharmony_ci * RFC 2481 details a specific bit for a receiver to send back in its 30458c2ecf20Sopenharmony_ci * TCP acknowledgements to notify the sender of the Congestion 30468c2ecf20Sopenharmony_ci * Experienced (CE) bit having arrived from the network. For SCTP this 30478c2ecf20Sopenharmony_ci * same indication is made by including the ECNE chunk. This chunk 30488c2ecf20Sopenharmony_ci * contains one data element, i.e. the lowest TSN associated with the IP 30498c2ecf20Sopenharmony_ci * datagram marked with the CE bit..... 30508c2ecf20Sopenharmony_ci * 30518c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 30528c2ecf20Sopenharmony_ci * Inputs 30538c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 30548c2ecf20Sopenharmony_ci * 30558c2ecf20Sopenharmony_ci * Outputs 30568c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 30578c2ecf20Sopenharmony_ci * 30588c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 30598c2ecf20Sopenharmony_ci */ 30608c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_ecne(struct net *net, 30618c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 30628c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 30638c2ecf20Sopenharmony_ci const union sctp_subtype type, 30648c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 30658c2ecf20Sopenharmony_ci{ 30668c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 30678c2ecf20Sopenharmony_ci struct sctp_ecnehdr *ecne; 30688c2ecf20Sopenharmony_ci 30698c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 30708c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_ecne_chunk))) 30738c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 30748c2ecf20Sopenharmony_ci commands); 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci ecne = (struct sctp_ecnehdr *)chunk->skb->data; 30778c2ecf20Sopenharmony_ci skb_pull(chunk->skb, sizeof(*ecne)); 30788c2ecf20Sopenharmony_ci 30798c2ecf20Sopenharmony_ci /* If this is a newer ECNE than the last CWR packet we sent out */ 30808c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ECN_ECNE, 30818c2ecf20Sopenharmony_ci SCTP_U32(ntohl(ecne->lowest_tsn))); 30828c2ecf20Sopenharmony_ci 30838c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 30848c2ecf20Sopenharmony_ci} 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_ci/* 30878c2ecf20Sopenharmony_ci * Section: 6.2 Acknowledgement on Reception of DATA Chunks 30888c2ecf20Sopenharmony_ci * 30898c2ecf20Sopenharmony_ci * The SCTP endpoint MUST always acknowledge the reception of each valid 30908c2ecf20Sopenharmony_ci * DATA chunk. 30918c2ecf20Sopenharmony_ci * 30928c2ecf20Sopenharmony_ci * The guidelines on delayed acknowledgement algorithm specified in 30938c2ecf20Sopenharmony_ci * Section 4.2 of [RFC2581] SHOULD be followed. Specifically, an 30948c2ecf20Sopenharmony_ci * acknowledgement SHOULD be generated for at least every second packet 30958c2ecf20Sopenharmony_ci * (not every second DATA chunk) received, and SHOULD be generated within 30968c2ecf20Sopenharmony_ci * 200 ms of the arrival of any unacknowledged DATA chunk. In some 30978c2ecf20Sopenharmony_ci * situations it may be beneficial for an SCTP transmitter to be more 30988c2ecf20Sopenharmony_ci * conservative than the algorithms detailed in this document allow. 30998c2ecf20Sopenharmony_ci * However, an SCTP transmitter MUST NOT be more aggressive than the 31008c2ecf20Sopenharmony_ci * following algorithms allow. 31018c2ecf20Sopenharmony_ci * 31028c2ecf20Sopenharmony_ci * A SCTP receiver MUST NOT generate more than one SACK for every 31038c2ecf20Sopenharmony_ci * incoming packet, other than to update the offered window as the 31048c2ecf20Sopenharmony_ci * receiving application consumes new data. 31058c2ecf20Sopenharmony_ci * 31068c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 31078c2ecf20Sopenharmony_ci * 31088c2ecf20Sopenharmony_ci * Inputs 31098c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 31108c2ecf20Sopenharmony_ci * 31118c2ecf20Sopenharmony_ci * Outputs 31128c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 31138c2ecf20Sopenharmony_ci * 31148c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 31158c2ecf20Sopenharmony_ci */ 31168c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_eat_data_6_2(struct net *net, 31178c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 31188c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 31198c2ecf20Sopenharmony_ci const union sctp_subtype type, 31208c2ecf20Sopenharmony_ci void *arg, 31218c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 31228c2ecf20Sopenharmony_ci{ 31238c2ecf20Sopenharmony_ci union sctp_arg force = SCTP_NOFORCE(); 31248c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 31258c2ecf20Sopenharmony_ci int error; 31268c2ecf20Sopenharmony_ci 31278c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 31288c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 31298c2ecf20Sopenharmony_ci SCTP_NULL()); 31308c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 31318c2ecf20Sopenharmony_ci } 31328c2ecf20Sopenharmony_ci 31338c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_datachk_len(&asoc->stream))) 31348c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 31358c2ecf20Sopenharmony_ci commands); 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_ci error = sctp_eat_data(asoc, chunk, commands); 31388c2ecf20Sopenharmony_ci switch (error) { 31398c2ecf20Sopenharmony_ci case SCTP_IERROR_NO_ERROR: 31408c2ecf20Sopenharmony_ci break; 31418c2ecf20Sopenharmony_ci case SCTP_IERROR_HIGH_TSN: 31428c2ecf20Sopenharmony_ci case SCTP_IERROR_BAD_STREAM: 31438c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); 31448c2ecf20Sopenharmony_ci goto discard_noforce; 31458c2ecf20Sopenharmony_ci case SCTP_IERROR_DUP_TSN: 31468c2ecf20Sopenharmony_ci case SCTP_IERROR_IGNORE_TSN: 31478c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); 31488c2ecf20Sopenharmony_ci goto discard_force; 31498c2ecf20Sopenharmony_ci case SCTP_IERROR_NO_DATA: 31508c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 31518c2ecf20Sopenharmony_ci case SCTP_IERROR_PROTO_VIOLATION: 31528c2ecf20Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, 31538c2ecf20Sopenharmony_ci (u8 *)chunk->subh.data_hdr, 31548c2ecf20Sopenharmony_ci sctp_datahdr_len(&asoc->stream)); 31558c2ecf20Sopenharmony_ci default: 31568c2ecf20Sopenharmony_ci BUG(); 31578c2ecf20Sopenharmony_ci } 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) 31608c2ecf20Sopenharmony_ci force = SCTP_FORCE(); 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { 31638c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 31648c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 31658c2ecf20Sopenharmony_ci } 31668c2ecf20Sopenharmony_ci 31678c2ecf20Sopenharmony_ci /* If this is the last chunk in a packet, we need to count it 31688c2ecf20Sopenharmony_ci * toward sack generation. Note that we need to SACK every 31698c2ecf20Sopenharmony_ci * OTHER packet containing data chunks, EVEN IF WE DISCARD 31708c2ecf20Sopenharmony_ci * THEM. We elect to NOT generate SACK's if the chunk fails 31718c2ecf20Sopenharmony_ci * the verification tag test. 31728c2ecf20Sopenharmony_ci * 31738c2ecf20Sopenharmony_ci * RFC 2960 6.2 Acknowledgement on Reception of DATA Chunks 31748c2ecf20Sopenharmony_ci * 31758c2ecf20Sopenharmony_ci * The SCTP endpoint MUST always acknowledge the reception of 31768c2ecf20Sopenharmony_ci * each valid DATA chunk. 31778c2ecf20Sopenharmony_ci * 31788c2ecf20Sopenharmony_ci * The guidelines on delayed acknowledgement algorithm 31798c2ecf20Sopenharmony_ci * specified in Section 4.2 of [RFC2581] SHOULD be followed. 31808c2ecf20Sopenharmony_ci * Specifically, an acknowledgement SHOULD be generated for at 31818c2ecf20Sopenharmony_ci * least every second packet (not every second DATA chunk) 31828c2ecf20Sopenharmony_ci * received, and SHOULD be generated within 200 ms of the 31838c2ecf20Sopenharmony_ci * arrival of any unacknowledged DATA chunk. In some 31848c2ecf20Sopenharmony_ci * situations it may be beneficial for an SCTP transmitter to 31858c2ecf20Sopenharmony_ci * be more conservative than the algorithms detailed in this 31868c2ecf20Sopenharmony_ci * document allow. However, an SCTP transmitter MUST NOT be 31878c2ecf20Sopenharmony_ci * more aggressive than the following algorithms allow. 31888c2ecf20Sopenharmony_ci */ 31898c2ecf20Sopenharmony_ci if (chunk->end_of_packet) 31908c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_cidiscard_force: 31958c2ecf20Sopenharmony_ci /* RFC 2960 6.2 Acknowledgement on Reception of DATA Chunks 31968c2ecf20Sopenharmony_ci * 31978c2ecf20Sopenharmony_ci * When a packet arrives with duplicate DATA chunk(s) and with 31988c2ecf20Sopenharmony_ci * no new DATA chunk(s), the endpoint MUST immediately send a 31998c2ecf20Sopenharmony_ci * SACK with no delay. If a packet arrives with duplicate 32008c2ecf20Sopenharmony_ci * DATA chunk(s) bundled with new DATA chunks, the endpoint 32018c2ecf20Sopenharmony_ci * MAY immediately send a SACK. Normally receipt of duplicate 32028c2ecf20Sopenharmony_ci * DATA chunks will occur when the original SACK chunk was lost 32038c2ecf20Sopenharmony_ci * and the peer's RTO has expired. The duplicate TSN number(s) 32048c2ecf20Sopenharmony_ci * SHOULD be reported in the SACK as duplicate. 32058c2ecf20Sopenharmony_ci */ 32068c2ecf20Sopenharmony_ci /* In our case, we split the MAY SACK advice up whether or not 32078c2ecf20Sopenharmony_ci * the last chunk is a duplicate.' 32088c2ecf20Sopenharmony_ci */ 32098c2ecf20Sopenharmony_ci if (chunk->end_of_packet) 32108c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 32118c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 32128c2ecf20Sopenharmony_ci 32138c2ecf20Sopenharmony_cidiscard_noforce: 32148c2ecf20Sopenharmony_ci if (chunk->end_of_packet) 32158c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 32188c2ecf20Sopenharmony_ci} 32198c2ecf20Sopenharmony_ci 32208c2ecf20Sopenharmony_ci/* 32218c2ecf20Sopenharmony_ci * sctp_sf_eat_data_fast_4_4 32228c2ecf20Sopenharmony_ci * 32238c2ecf20Sopenharmony_ci * Section: 4 (4) 32248c2ecf20Sopenharmony_ci * (4) In SHUTDOWN-SENT state the endpoint MUST acknowledge any received 32258c2ecf20Sopenharmony_ci * DATA chunks without delay. 32268c2ecf20Sopenharmony_ci * 32278c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 32288c2ecf20Sopenharmony_ci * Inputs 32298c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 32308c2ecf20Sopenharmony_ci * 32318c2ecf20Sopenharmony_ci * Outputs 32328c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 32338c2ecf20Sopenharmony_ci * 32348c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 32358c2ecf20Sopenharmony_ci */ 32368c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_eat_data_fast_4_4( 32378c2ecf20Sopenharmony_ci struct net *net, 32388c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 32398c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 32408c2ecf20Sopenharmony_ci const union sctp_subtype type, 32418c2ecf20Sopenharmony_ci void *arg, 32428c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 32438c2ecf20Sopenharmony_ci{ 32448c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 32458c2ecf20Sopenharmony_ci int error; 32468c2ecf20Sopenharmony_ci 32478c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 32488c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 32498c2ecf20Sopenharmony_ci SCTP_NULL()); 32508c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 32518c2ecf20Sopenharmony_ci } 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_datachk_len(&asoc->stream))) 32548c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 32558c2ecf20Sopenharmony_ci commands); 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci error = sctp_eat_data(asoc, chunk, commands); 32588c2ecf20Sopenharmony_ci switch (error) { 32598c2ecf20Sopenharmony_ci case SCTP_IERROR_NO_ERROR: 32608c2ecf20Sopenharmony_ci case SCTP_IERROR_HIGH_TSN: 32618c2ecf20Sopenharmony_ci case SCTP_IERROR_DUP_TSN: 32628c2ecf20Sopenharmony_ci case SCTP_IERROR_IGNORE_TSN: 32638c2ecf20Sopenharmony_ci case SCTP_IERROR_BAD_STREAM: 32648c2ecf20Sopenharmony_ci break; 32658c2ecf20Sopenharmony_ci case SCTP_IERROR_NO_DATA: 32668c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 32678c2ecf20Sopenharmony_ci case SCTP_IERROR_PROTO_VIOLATION: 32688c2ecf20Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, 32698c2ecf20Sopenharmony_ci (u8 *)chunk->subh.data_hdr, 32708c2ecf20Sopenharmony_ci sctp_datahdr_len(&asoc->stream)); 32718c2ecf20Sopenharmony_ci default: 32728c2ecf20Sopenharmony_ci BUG(); 32738c2ecf20Sopenharmony_ci } 32748c2ecf20Sopenharmony_ci 32758c2ecf20Sopenharmony_ci /* Go a head and force a SACK, since we are shutting down. */ 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_ci /* Implementor's Guide. 32788c2ecf20Sopenharmony_ci * 32798c2ecf20Sopenharmony_ci * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately 32808c2ecf20Sopenharmony_ci * respond to each received packet containing one or more DATA chunk(s) 32818c2ecf20Sopenharmony_ci * with a SACK, a SHUTDOWN chunk, and restart the T2-shutdown timer 32828c2ecf20Sopenharmony_ci */ 32838c2ecf20Sopenharmony_ci if (chunk->end_of_packet) { 32848c2ecf20Sopenharmony_ci /* We must delay the chunk creation since the cumulative 32858c2ecf20Sopenharmony_ci * TSN has not been updated yet. 32868c2ecf20Sopenharmony_ci */ 32878c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SHUTDOWN, SCTP_NULL()); 32888c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 32898c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 32908c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 32918c2ecf20Sopenharmony_ci } 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 32948c2ecf20Sopenharmony_ci} 32958c2ecf20Sopenharmony_ci 32968c2ecf20Sopenharmony_ci/* 32978c2ecf20Sopenharmony_ci * Section: 6.2 Processing a Received SACK 32988c2ecf20Sopenharmony_ci * D) Any time a SACK arrives, the endpoint performs the following: 32998c2ecf20Sopenharmony_ci * 33008c2ecf20Sopenharmony_ci * i) If Cumulative TSN Ack is less than the Cumulative TSN Ack Point, 33018c2ecf20Sopenharmony_ci * then drop the SACK. Since Cumulative TSN Ack is monotonically 33028c2ecf20Sopenharmony_ci * increasing, a SACK whose Cumulative TSN Ack is less than the 33038c2ecf20Sopenharmony_ci * Cumulative TSN Ack Point indicates an out-of-order SACK. 33048c2ecf20Sopenharmony_ci * 33058c2ecf20Sopenharmony_ci * ii) Set rwnd equal to the newly received a_rwnd minus the number 33068c2ecf20Sopenharmony_ci * of bytes still outstanding after processing the Cumulative TSN Ack 33078c2ecf20Sopenharmony_ci * and the Gap Ack Blocks. 33088c2ecf20Sopenharmony_ci * 33098c2ecf20Sopenharmony_ci * iii) If the SACK is missing a TSN that was previously 33108c2ecf20Sopenharmony_ci * acknowledged via a Gap Ack Block (e.g., the data receiver 33118c2ecf20Sopenharmony_ci * reneged on the data), then mark the corresponding DATA chunk 33128c2ecf20Sopenharmony_ci * as available for retransmit: Mark it as missing for fast 33138c2ecf20Sopenharmony_ci * retransmit as described in Section 7.2.4 and if no retransmit 33148c2ecf20Sopenharmony_ci * timer is running for the destination address to which the DATA 33158c2ecf20Sopenharmony_ci * chunk was originally transmitted, then T3-rtx is started for 33168c2ecf20Sopenharmony_ci * that destination address. 33178c2ecf20Sopenharmony_ci * 33188c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 33198c2ecf20Sopenharmony_ci * 33208c2ecf20Sopenharmony_ci * Inputs 33218c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 33228c2ecf20Sopenharmony_ci * 33238c2ecf20Sopenharmony_ci * Outputs 33248c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 33258c2ecf20Sopenharmony_ci * 33268c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 33278c2ecf20Sopenharmony_ci */ 33288c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_eat_sack_6_2(struct net *net, 33298c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 33308c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 33318c2ecf20Sopenharmony_ci const union sctp_subtype type, 33328c2ecf20Sopenharmony_ci void *arg, 33338c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 33348c2ecf20Sopenharmony_ci{ 33358c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 33368c2ecf20Sopenharmony_ci struct sctp_sackhdr *sackh; 33378c2ecf20Sopenharmony_ci __u32 ctsn; 33388c2ecf20Sopenharmony_ci 33398c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 33408c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 33418c2ecf20Sopenharmony_ci 33428c2ecf20Sopenharmony_ci /* Make sure that the SACK chunk has a valid length. */ 33438c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_sack_chunk))) 33448c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 33458c2ecf20Sopenharmony_ci commands); 33468c2ecf20Sopenharmony_ci 33478c2ecf20Sopenharmony_ci /* Pull the SACK chunk from the data buffer */ 33488c2ecf20Sopenharmony_ci sackh = sctp_sm_pull_sack(chunk); 33498c2ecf20Sopenharmony_ci /* Was this a bogus SACK? */ 33508c2ecf20Sopenharmony_ci if (!sackh) 33518c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 33528c2ecf20Sopenharmony_ci chunk->subh.sack_hdr = sackh; 33538c2ecf20Sopenharmony_ci ctsn = ntohl(sackh->cum_tsn_ack); 33548c2ecf20Sopenharmony_ci 33558c2ecf20Sopenharmony_ci /* If Cumulative TSN Ack beyond the max tsn currently 33568c2ecf20Sopenharmony_ci * send, terminating the association and respond to the 33578c2ecf20Sopenharmony_ci * sender with an ABORT. 33588c2ecf20Sopenharmony_ci */ 33598c2ecf20Sopenharmony_ci if (TSN_lte(asoc->next_tsn, ctsn)) 33608c2ecf20Sopenharmony_ci return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 33618c2ecf20Sopenharmony_ci 33628c2ecf20Sopenharmony_ci trace_sctp_probe(ep, asoc, chunk); 33638c2ecf20Sopenharmony_ci 33648c2ecf20Sopenharmony_ci /* i) If Cumulative TSN Ack is less than the Cumulative TSN 33658c2ecf20Sopenharmony_ci * Ack Point, then drop the SACK. Since Cumulative TSN 33668c2ecf20Sopenharmony_ci * Ack is monotonically increasing, a SACK whose 33678c2ecf20Sopenharmony_ci * Cumulative TSN Ack is less than the Cumulative TSN Ack 33688c2ecf20Sopenharmony_ci * Point indicates an out-of-order SACK. 33698c2ecf20Sopenharmony_ci */ 33708c2ecf20Sopenharmony_ci if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { 33718c2ecf20Sopenharmony_ci pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, 33728c2ecf20Sopenharmony_ci asoc->ctsn_ack_point); 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 33758c2ecf20Sopenharmony_ci } 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci /* Return this SACK for further processing. */ 33788c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk)); 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci /* Note: We do the rest of the work on the PROCESS_SACK 33818c2ecf20Sopenharmony_ci * sideeffect. 33828c2ecf20Sopenharmony_ci */ 33838c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 33848c2ecf20Sopenharmony_ci} 33858c2ecf20Sopenharmony_ci 33868c2ecf20Sopenharmony_ci/* 33878c2ecf20Sopenharmony_ci * Generate an ABORT in response to a packet. 33888c2ecf20Sopenharmony_ci * 33898c2ecf20Sopenharmony_ci * Section: 8.4 Handle "Out of the blue" Packets, sctpimpguide 2.41 33908c2ecf20Sopenharmony_ci * 33918c2ecf20Sopenharmony_ci * 8) The receiver should respond to the sender of the OOTB packet with 33928c2ecf20Sopenharmony_ci * an ABORT. When sending the ABORT, the receiver of the OOTB packet 33938c2ecf20Sopenharmony_ci * MUST fill in the Verification Tag field of the outbound packet 33948c2ecf20Sopenharmony_ci * with the value found in the Verification Tag field of the OOTB 33958c2ecf20Sopenharmony_ci * packet and set the T-bit in the Chunk Flags to indicate that the 33968c2ecf20Sopenharmony_ci * Verification Tag is reflected. After sending this ABORT, the 33978c2ecf20Sopenharmony_ci * receiver of the OOTB packet shall discard the OOTB packet and take 33988c2ecf20Sopenharmony_ci * no further action. 33998c2ecf20Sopenharmony_ci * 34008c2ecf20Sopenharmony_ci * Verification Tag: 34018c2ecf20Sopenharmony_ci * 34028c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 34038c2ecf20Sopenharmony_ci*/ 34048c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_tabort_8_4_8( 34058c2ecf20Sopenharmony_ci struct net *net, 34068c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 34078c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 34088c2ecf20Sopenharmony_ci const union sctp_subtype type, 34098c2ecf20Sopenharmony_ci void *arg, 34108c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 34118c2ecf20Sopenharmony_ci{ 34128c2ecf20Sopenharmony_ci struct sctp_packet *packet = NULL; 34138c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 34148c2ecf20Sopenharmony_ci struct sctp_chunk *abort; 34158c2ecf20Sopenharmony_ci 34168c2ecf20Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 34178c2ecf20Sopenharmony_ci if (!packet) 34188c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 34198c2ecf20Sopenharmony_ci 34208c2ecf20Sopenharmony_ci /* Make an ABORT. The T bit will be set if the asoc 34218c2ecf20Sopenharmony_ci * is NULL. 34228c2ecf20Sopenharmony_ci */ 34238c2ecf20Sopenharmony_ci abort = sctp_make_abort(asoc, chunk, 0); 34248c2ecf20Sopenharmony_ci if (!abort) { 34258c2ecf20Sopenharmony_ci sctp_ootb_pkt_free(packet); 34268c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 34278c2ecf20Sopenharmony_ci } 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci /* Reflect vtag if T-Bit is set */ 34308c2ecf20Sopenharmony_ci if (sctp_test_T_bit(abort)) 34318c2ecf20Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 34348c2ecf20Sopenharmony_ci abort->skb->sk = ep->base.sk; 34358c2ecf20Sopenharmony_ci 34368c2ecf20Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 34378c2ecf20Sopenharmony_ci 34388c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 34398c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 34408c2ecf20Sopenharmony_ci 34418c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 34428c2ecf20Sopenharmony_ci 34438c2ecf20Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 34448c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 34458c2ecf20Sopenharmony_ci} 34468c2ecf20Sopenharmony_ci 34478c2ecf20Sopenharmony_ci/* 34488c2ecf20Sopenharmony_ci * Received an ERROR chunk from peer. Generate SCTP_REMOTE_ERROR 34498c2ecf20Sopenharmony_ci * event as ULP notification for each cause included in the chunk. 34508c2ecf20Sopenharmony_ci * 34518c2ecf20Sopenharmony_ci * API 5.3.1.3 - SCTP_REMOTE_ERROR 34528c2ecf20Sopenharmony_ci * 34538c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 34548c2ecf20Sopenharmony_ci*/ 34558c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_operr_notify(struct net *net, 34568c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 34578c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 34588c2ecf20Sopenharmony_ci const union sctp_subtype type, 34598c2ecf20Sopenharmony_ci void *arg, 34608c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 34618c2ecf20Sopenharmony_ci{ 34628c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 34638c2ecf20Sopenharmony_ci struct sctp_errhdr *err; 34648c2ecf20Sopenharmony_ci 34658c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 34668c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ci /* Make sure that the ERROR chunk has a valid length. */ 34698c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_operr_chunk))) 34708c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 34718c2ecf20Sopenharmony_ci commands); 34728c2ecf20Sopenharmony_ci sctp_walk_errors(err, chunk->chunk_hdr); 34738c2ecf20Sopenharmony_ci if ((void *)err != (void *)chunk->chunk_end) 34748c2ecf20Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 34758c2ecf20Sopenharmony_ci (void *)err, commands); 34768c2ecf20Sopenharmony_ci 34778c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, 34788c2ecf20Sopenharmony_ci SCTP_CHUNK(chunk)); 34798c2ecf20Sopenharmony_ci 34808c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 34818c2ecf20Sopenharmony_ci} 34828c2ecf20Sopenharmony_ci 34838c2ecf20Sopenharmony_ci/* 34848c2ecf20Sopenharmony_ci * Process an inbound SHUTDOWN ACK. 34858c2ecf20Sopenharmony_ci * 34868c2ecf20Sopenharmony_ci * From Section 9.2: 34878c2ecf20Sopenharmony_ci * Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall 34888c2ecf20Sopenharmony_ci * stop the T2-shutdown timer, send a SHUTDOWN COMPLETE chunk to its 34898c2ecf20Sopenharmony_ci * peer, and remove all record of the association. 34908c2ecf20Sopenharmony_ci * 34918c2ecf20Sopenharmony_ci * The return value is the disposition. 34928c2ecf20Sopenharmony_ci */ 34938c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_final(struct net *net, 34948c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 34958c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 34968c2ecf20Sopenharmony_ci const union sctp_subtype type, 34978c2ecf20Sopenharmony_ci void *arg, 34988c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 34998c2ecf20Sopenharmony_ci{ 35008c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 35018c2ecf20Sopenharmony_ci struct sctp_chunk *reply; 35028c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev; 35038c2ecf20Sopenharmony_ci 35048c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 35058c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ 35088c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 35098c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 35108c2ecf20Sopenharmony_ci commands); 35118c2ecf20Sopenharmony_ci /* 10.2 H) SHUTDOWN COMPLETE notification 35128c2ecf20Sopenharmony_ci * 35138c2ecf20Sopenharmony_ci * When SCTP completes the shutdown procedures (section 9.2) this 35148c2ecf20Sopenharmony_ci * notification is passed to the upper layer. 35158c2ecf20Sopenharmony_ci */ 35168c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, 35178c2ecf20Sopenharmony_ci 0, 0, 0, NULL, GFP_ATOMIC); 35188c2ecf20Sopenharmony_ci if (!ev) 35198c2ecf20Sopenharmony_ci goto nomem; 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ 35228c2ecf20Sopenharmony_ci reply = sctp_make_shutdown_complete(asoc, chunk); 35238c2ecf20Sopenharmony_ci if (!reply) 35248c2ecf20Sopenharmony_ci goto nomem_chunk; 35258c2ecf20Sopenharmony_ci 35268c2ecf20Sopenharmony_ci /* Do all the commands now (after allocation), so that we 35278c2ecf20Sopenharmony_ci * have consistent state if memory allocation failes 35288c2ecf20Sopenharmony_ci */ 35298c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 35308c2ecf20Sopenharmony_ci 35318c2ecf20Sopenharmony_ci /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall 35328c2ecf20Sopenharmony_ci * stop the T2-shutdown timer, 35338c2ecf20Sopenharmony_ci */ 35348c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 35358c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 35388c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 35398c2ecf20Sopenharmony_ci 35408c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 35418c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 35428c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); 35438c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 35448c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 35458c2ecf20Sopenharmony_ci 35468c2ecf20Sopenharmony_ci /* ...and remove all record of the association. */ 35478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 35488c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 35498c2ecf20Sopenharmony_ci 35508c2ecf20Sopenharmony_cinomem_chunk: 35518c2ecf20Sopenharmony_ci sctp_ulpevent_free(ev); 35528c2ecf20Sopenharmony_cinomem: 35538c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 35548c2ecf20Sopenharmony_ci} 35558c2ecf20Sopenharmony_ci 35568c2ecf20Sopenharmony_ci/* 35578c2ecf20Sopenharmony_ci * RFC 2960, 8.4 - Handle "Out of the blue" Packets, sctpimpguide 2.41. 35588c2ecf20Sopenharmony_ci * 35598c2ecf20Sopenharmony_ci * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should 35608c2ecf20Sopenharmony_ci * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. 35618c2ecf20Sopenharmony_ci * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB 35628c2ecf20Sopenharmony_ci * packet must fill in the Verification Tag field of the outbound 35638c2ecf20Sopenharmony_ci * packet with the Verification Tag received in the SHUTDOWN ACK and 35648c2ecf20Sopenharmony_ci * set the T-bit in the Chunk Flags to indicate that the Verification 35658c2ecf20Sopenharmony_ci * Tag is reflected. 35668c2ecf20Sopenharmony_ci * 35678c2ecf20Sopenharmony_ci * 8) The receiver should respond to the sender of the OOTB packet with 35688c2ecf20Sopenharmony_ci * an ABORT. When sending the ABORT, the receiver of the OOTB packet 35698c2ecf20Sopenharmony_ci * MUST fill in the Verification Tag field of the outbound packet 35708c2ecf20Sopenharmony_ci * with the value found in the Verification Tag field of the OOTB 35718c2ecf20Sopenharmony_ci * packet and set the T-bit in the Chunk Flags to indicate that the 35728c2ecf20Sopenharmony_ci * Verification Tag is reflected. After sending this ABORT, the 35738c2ecf20Sopenharmony_ci * receiver of the OOTB packet shall discard the OOTB packet and take 35748c2ecf20Sopenharmony_ci * no further action. 35758c2ecf20Sopenharmony_ci */ 35768c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_ootb(struct net *net, 35778c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 35788c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 35798c2ecf20Sopenharmony_ci const union sctp_subtype type, 35808c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 35818c2ecf20Sopenharmony_ci{ 35828c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 35838c2ecf20Sopenharmony_ci struct sk_buff *skb = chunk->skb; 35848c2ecf20Sopenharmony_ci struct sctp_chunkhdr *ch; 35858c2ecf20Sopenharmony_ci struct sctp_errhdr *err; 35868c2ecf20Sopenharmony_ci int ootb_cookie_ack = 0; 35878c2ecf20Sopenharmony_ci int ootb_shut_ack = 0; 35888c2ecf20Sopenharmony_ci __u8 *ch_end; 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_ci if (asoc && !sctp_vtag_verify(chunk, asoc)) 35938c2ecf20Sopenharmony_ci asoc = NULL; 35948c2ecf20Sopenharmony_ci 35958c2ecf20Sopenharmony_ci ch = (struct sctp_chunkhdr *)chunk->chunk_hdr; 35968c2ecf20Sopenharmony_ci do { 35978c2ecf20Sopenharmony_ci /* Report violation if the chunk is less then minimal */ 35988c2ecf20Sopenharmony_ci if (ntohs(ch->length) < sizeof(*ch)) 35998c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 36008c2ecf20Sopenharmony_ci commands); 36018c2ecf20Sopenharmony_ci 36028c2ecf20Sopenharmony_ci /* Report violation if chunk len overflows */ 36038c2ecf20Sopenharmony_ci ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length)); 36048c2ecf20Sopenharmony_ci if (ch_end > skb_tail_pointer(skb)) 36058c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 36068c2ecf20Sopenharmony_ci commands); 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci /* Now that we know we at least have a chunk header, 36098c2ecf20Sopenharmony_ci * do things that are type appropriate. 36108c2ecf20Sopenharmony_ci */ 36118c2ecf20Sopenharmony_ci if (SCTP_CID_SHUTDOWN_ACK == ch->type) 36128c2ecf20Sopenharmony_ci ootb_shut_ack = 1; 36138c2ecf20Sopenharmony_ci 36148c2ecf20Sopenharmony_ci /* RFC 2960, Section 3.3.7 36158c2ecf20Sopenharmony_ci * Moreover, under any circumstances, an endpoint that 36168c2ecf20Sopenharmony_ci * receives an ABORT MUST NOT respond to that ABORT by 36178c2ecf20Sopenharmony_ci * sending an ABORT of its own. 36188c2ecf20Sopenharmony_ci */ 36198c2ecf20Sopenharmony_ci if (SCTP_CID_ABORT == ch->type) 36208c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 36218c2ecf20Sopenharmony_ci 36228c2ecf20Sopenharmony_ci /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR 36238c2ecf20Sopenharmony_ci * or a COOKIE ACK the SCTP Packet should be silently 36248c2ecf20Sopenharmony_ci * discarded. 36258c2ecf20Sopenharmony_ci */ 36268c2ecf20Sopenharmony_ci 36278c2ecf20Sopenharmony_ci if (SCTP_CID_COOKIE_ACK == ch->type) 36288c2ecf20Sopenharmony_ci ootb_cookie_ack = 1; 36298c2ecf20Sopenharmony_ci 36308c2ecf20Sopenharmony_ci if (SCTP_CID_ERROR == ch->type) { 36318c2ecf20Sopenharmony_ci sctp_walk_errors(err, ch) { 36328c2ecf20Sopenharmony_ci if (SCTP_ERROR_STALE_COOKIE == err->cause) { 36338c2ecf20Sopenharmony_ci ootb_cookie_ack = 1; 36348c2ecf20Sopenharmony_ci break; 36358c2ecf20Sopenharmony_ci } 36368c2ecf20Sopenharmony_ci } 36378c2ecf20Sopenharmony_ci } 36388c2ecf20Sopenharmony_ci 36398c2ecf20Sopenharmony_ci ch = (struct sctp_chunkhdr *)ch_end; 36408c2ecf20Sopenharmony_ci } while (ch_end < skb_tail_pointer(skb)); 36418c2ecf20Sopenharmony_ci 36428c2ecf20Sopenharmony_ci if (ootb_shut_ack) 36438c2ecf20Sopenharmony_ci return sctp_sf_shut_8_4_5(net, ep, asoc, type, arg, commands); 36448c2ecf20Sopenharmony_ci else if (ootb_cookie_ack) 36458c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 36468c2ecf20Sopenharmony_ci else 36478c2ecf20Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 36488c2ecf20Sopenharmony_ci} 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_ci/* 36518c2ecf20Sopenharmony_ci * Handle an "Out of the blue" SHUTDOWN ACK. 36528c2ecf20Sopenharmony_ci * 36538c2ecf20Sopenharmony_ci * Section: 8.4 5, sctpimpguide 2.41. 36548c2ecf20Sopenharmony_ci * 36558c2ecf20Sopenharmony_ci * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should 36568c2ecf20Sopenharmony_ci * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. 36578c2ecf20Sopenharmony_ci * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB 36588c2ecf20Sopenharmony_ci * packet must fill in the Verification Tag field of the outbound 36598c2ecf20Sopenharmony_ci * packet with the Verification Tag received in the SHUTDOWN ACK and 36608c2ecf20Sopenharmony_ci * set the T-bit in the Chunk Flags to indicate that the Verification 36618c2ecf20Sopenharmony_ci * Tag is reflected. 36628c2ecf20Sopenharmony_ci * 36638c2ecf20Sopenharmony_ci * Inputs 36648c2ecf20Sopenharmony_ci * (endpoint, asoc, type, arg, commands) 36658c2ecf20Sopenharmony_ci * 36668c2ecf20Sopenharmony_ci * Outputs 36678c2ecf20Sopenharmony_ci * (enum sctp_disposition) 36688c2ecf20Sopenharmony_ci * 36698c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 36708c2ecf20Sopenharmony_ci */ 36718c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_shut_8_4_5( 36728c2ecf20Sopenharmony_ci struct net *net, 36738c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 36748c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 36758c2ecf20Sopenharmony_ci const union sctp_subtype type, 36768c2ecf20Sopenharmony_ci void *arg, 36778c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 36788c2ecf20Sopenharmony_ci{ 36798c2ecf20Sopenharmony_ci struct sctp_packet *packet = NULL; 36808c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 36818c2ecf20Sopenharmony_ci struct sctp_chunk *shut; 36828c2ecf20Sopenharmony_ci 36838c2ecf20Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 36848c2ecf20Sopenharmony_ci if (!packet) 36858c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 36868c2ecf20Sopenharmony_ci 36878c2ecf20Sopenharmony_ci /* Make an SHUTDOWN_COMPLETE. 36888c2ecf20Sopenharmony_ci * The T bit will be set if the asoc is NULL. 36898c2ecf20Sopenharmony_ci */ 36908c2ecf20Sopenharmony_ci shut = sctp_make_shutdown_complete(asoc, chunk); 36918c2ecf20Sopenharmony_ci if (!shut) { 36928c2ecf20Sopenharmony_ci sctp_ootb_pkt_free(packet); 36938c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 36948c2ecf20Sopenharmony_ci } 36958c2ecf20Sopenharmony_ci 36968c2ecf20Sopenharmony_ci /* Reflect vtag if T-Bit is set */ 36978c2ecf20Sopenharmony_ci if (sctp_test_T_bit(shut)) 36988c2ecf20Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 37018c2ecf20Sopenharmony_ci shut->skb->sk = ep->base.sk; 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci sctp_packet_append_chunk(packet, shut); 37048c2ecf20Sopenharmony_ci 37058c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 37068c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 37078c2ecf20Sopenharmony_ci 37088c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_ci /* We need to discard the rest of the packet to prevent 37118c2ecf20Sopenharmony_ci * potential bomming attacks from additional bundled chunks. 37128c2ecf20Sopenharmony_ci * This is documented in SCTP Threats ID. 37138c2ecf20Sopenharmony_ci */ 37148c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 37158c2ecf20Sopenharmony_ci} 37168c2ecf20Sopenharmony_ci 37178c2ecf20Sopenharmony_ci/* 37188c2ecf20Sopenharmony_ci * Handle SHUTDOWN ACK in COOKIE_ECHOED or COOKIE_WAIT state. 37198c2ecf20Sopenharmony_ci * 37208c2ecf20Sopenharmony_ci * Verification Tag: 8.5.1 E) Rules for packet carrying a SHUTDOWN ACK 37218c2ecf20Sopenharmony_ci * If the receiver is in COOKIE-ECHOED or COOKIE-WAIT state the 37228c2ecf20Sopenharmony_ci * procedures in section 8.4 SHOULD be followed, in other words it 37238c2ecf20Sopenharmony_ci * should be treated as an Out Of The Blue packet. 37248c2ecf20Sopenharmony_ci * [This means that we do NOT check the Verification Tag on these 37258c2ecf20Sopenharmony_ci * chunks. --piggy ] 37268c2ecf20Sopenharmony_ci * 37278c2ecf20Sopenharmony_ci */ 37288c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_8_5_1_E_sa(struct net *net, 37298c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 37308c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 37318c2ecf20Sopenharmony_ci const union sctp_subtype type, 37328c2ecf20Sopenharmony_ci void *arg, 37338c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 37348c2ecf20Sopenharmony_ci{ 37358c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 37388c2ecf20Sopenharmony_ci asoc = NULL; 37398c2ecf20Sopenharmony_ci 37408c2ecf20Sopenharmony_ci /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ 37418c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 37428c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 37438c2ecf20Sopenharmony_ci commands); 37448c2ecf20Sopenharmony_ci 37458c2ecf20Sopenharmony_ci /* Although we do have an association in this case, it corresponds 37468c2ecf20Sopenharmony_ci * to a restarted association. So the packet is treated as an OOTB 37478c2ecf20Sopenharmony_ci * packet and the state function that handles OOTB SHUTDOWN_ACK is 37488c2ecf20Sopenharmony_ci * called with a NULL association. 37498c2ecf20Sopenharmony_ci */ 37508c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci return sctp_sf_shut_8_4_5(net, ep, NULL, type, arg, commands); 37538c2ecf20Sopenharmony_ci} 37548c2ecf20Sopenharmony_ci 37558c2ecf20Sopenharmony_ci/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */ 37568c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_asconf(struct net *net, 37578c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 37588c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 37598c2ecf20Sopenharmony_ci const union sctp_subtype type, 37608c2ecf20Sopenharmony_ci void *arg, 37618c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 37628c2ecf20Sopenharmony_ci{ 37638c2ecf20Sopenharmony_ci struct sctp_paramhdr *err_param = NULL; 37648c2ecf20Sopenharmony_ci struct sctp_chunk *asconf_ack = NULL; 37658c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 37668c2ecf20Sopenharmony_ci struct sctp_addiphdr *hdr; 37678c2ecf20Sopenharmony_ci __u32 serial; 37688c2ecf20Sopenharmony_ci 37698c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 37708c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 37718c2ecf20Sopenharmony_ci SCTP_NULL()); 37728c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 37738c2ecf20Sopenharmony_ci } 37748c2ecf20Sopenharmony_ci 37758c2ecf20Sopenharmony_ci /* Make sure that the ASCONF ADDIP chunk has a valid length. */ 37768c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk))) 37778c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 37788c2ecf20Sopenharmony_ci commands); 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_ci /* ADD-IP: Section 4.1.1 37818c2ecf20Sopenharmony_ci * This chunk MUST be sent in an authenticated way by using 37828c2ecf20Sopenharmony_ci * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk 37838c2ecf20Sopenharmony_ci * is received unauthenticated it MUST be silently discarded as 37848c2ecf20Sopenharmony_ci * described in [I-D.ietf-tsvwg-sctp-auth]. 37858c2ecf20Sopenharmony_ci */ 37868c2ecf20Sopenharmony_ci if (!asoc->peer.asconf_capable || 37878c2ecf20Sopenharmony_ci (!net->sctp.addip_noauth && !chunk->auth)) 37888c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 37898c2ecf20Sopenharmony_ci 37908c2ecf20Sopenharmony_ci hdr = (struct sctp_addiphdr *)chunk->skb->data; 37918c2ecf20Sopenharmony_ci serial = ntohl(hdr->serial); 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci /* Verify the ASCONF chunk before processing it. */ 37948c2ecf20Sopenharmony_ci if (!sctp_verify_asconf(asoc, chunk, true, &err_param)) 37958c2ecf20Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 37968c2ecf20Sopenharmony_ci (void *)err_param, commands); 37978c2ecf20Sopenharmony_ci 37988c2ecf20Sopenharmony_ci /* ADDIP 5.2 E1) Compare the value of the serial number to the value 37998c2ecf20Sopenharmony_ci * the endpoint stored in a new association variable 38008c2ecf20Sopenharmony_ci * 'Peer-Serial-Number'. 38018c2ecf20Sopenharmony_ci */ 38028c2ecf20Sopenharmony_ci if (serial == asoc->peer.addip_serial + 1) { 38038c2ecf20Sopenharmony_ci /* If this is the first instance of ASCONF in the packet, 38048c2ecf20Sopenharmony_ci * we can clean our old ASCONF-ACKs. 38058c2ecf20Sopenharmony_ci */ 38068c2ecf20Sopenharmony_ci if (!chunk->has_asconf) 38078c2ecf20Sopenharmony_ci sctp_assoc_clean_asconf_ack_cache(asoc); 38088c2ecf20Sopenharmony_ci 38098c2ecf20Sopenharmony_ci /* ADDIP 5.2 E4) When the Sequence Number matches the next one 38108c2ecf20Sopenharmony_ci * expected, process the ASCONF as described below and after 38118c2ecf20Sopenharmony_ci * processing the ASCONF Chunk, append an ASCONF-ACK Chunk to 38128c2ecf20Sopenharmony_ci * the response packet and cache a copy of it (in the event it 38138c2ecf20Sopenharmony_ci * later needs to be retransmitted). 38148c2ecf20Sopenharmony_ci * 38158c2ecf20Sopenharmony_ci * Essentially, do V1-V5. 38168c2ecf20Sopenharmony_ci */ 38178c2ecf20Sopenharmony_ci asconf_ack = sctp_process_asconf((struct sctp_association *) 38188c2ecf20Sopenharmony_ci asoc, chunk); 38198c2ecf20Sopenharmony_ci if (!asconf_ack) 38208c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 38218c2ecf20Sopenharmony_ci } else if (serial < asoc->peer.addip_serial + 1) { 38228c2ecf20Sopenharmony_ci /* ADDIP 5.2 E2) 38238c2ecf20Sopenharmony_ci * If the value found in the Sequence Number is less than the 38248c2ecf20Sopenharmony_ci * ('Peer- Sequence-Number' + 1), simply skip to the next 38258c2ecf20Sopenharmony_ci * ASCONF, and include in the outbound response packet 38268c2ecf20Sopenharmony_ci * any previously cached ASCONF-ACK response that was 38278c2ecf20Sopenharmony_ci * sent and saved that matches the Sequence Number of the 38288c2ecf20Sopenharmony_ci * ASCONF. Note: It is possible that no cached ASCONF-ACK 38298c2ecf20Sopenharmony_ci * Chunk exists. This will occur when an older ASCONF 38308c2ecf20Sopenharmony_ci * arrives out of order. In such a case, the receiver 38318c2ecf20Sopenharmony_ci * should skip the ASCONF Chunk and not include ASCONF-ACK 38328c2ecf20Sopenharmony_ci * Chunk for that chunk. 38338c2ecf20Sopenharmony_ci */ 38348c2ecf20Sopenharmony_ci asconf_ack = sctp_assoc_lookup_asconf_ack(asoc, hdr->serial); 38358c2ecf20Sopenharmony_ci if (!asconf_ack) 38368c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 38378c2ecf20Sopenharmony_ci 38388c2ecf20Sopenharmony_ci /* Reset the transport so that we select the correct one 38398c2ecf20Sopenharmony_ci * this time around. This is to make sure that we don't 38408c2ecf20Sopenharmony_ci * accidentally use a stale transport that's been removed. 38418c2ecf20Sopenharmony_ci */ 38428c2ecf20Sopenharmony_ci asconf_ack->transport = NULL; 38438c2ecf20Sopenharmony_ci } else { 38448c2ecf20Sopenharmony_ci /* ADDIP 5.2 E5) Otherwise, the ASCONF Chunk is discarded since 38458c2ecf20Sopenharmony_ci * it must be either a stale packet or from an attacker. 38468c2ecf20Sopenharmony_ci */ 38478c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 38488c2ecf20Sopenharmony_ci } 38498c2ecf20Sopenharmony_ci 38508c2ecf20Sopenharmony_ci /* ADDIP 5.2 E6) The destination address of the SCTP packet 38518c2ecf20Sopenharmony_ci * containing the ASCONF-ACK Chunks MUST be the source address of 38528c2ecf20Sopenharmony_ci * the SCTP packet that held the ASCONF Chunks. 38538c2ecf20Sopenharmony_ci * 38548c2ecf20Sopenharmony_ci * To do this properly, we'll set the destination address of the chunk 38558c2ecf20Sopenharmony_ci * and at the transmit time, will try look up the transport to use. 38568c2ecf20Sopenharmony_ci * Since ASCONFs may be bundled, the correct transport may not be 38578c2ecf20Sopenharmony_ci * created until we process the entire packet, thus this workaround. 38588c2ecf20Sopenharmony_ci */ 38598c2ecf20Sopenharmony_ci asconf_ack->dest = chunk->source; 38608c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack)); 38618c2ecf20Sopenharmony_ci if (asoc->new_transport) { 38628c2ecf20Sopenharmony_ci sctp_sf_heartbeat(ep, asoc, type, asoc->new_transport, commands); 38638c2ecf20Sopenharmony_ci ((struct sctp_association *)asoc)->new_transport = NULL; 38648c2ecf20Sopenharmony_ci } 38658c2ecf20Sopenharmony_ci 38668c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 38678c2ecf20Sopenharmony_ci} 38688c2ecf20Sopenharmony_ci 38698c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_send_next_asconf( 38708c2ecf20Sopenharmony_ci struct net *net, 38718c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 38728c2ecf20Sopenharmony_ci struct sctp_association *asoc, 38738c2ecf20Sopenharmony_ci const union sctp_subtype type, 38748c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 38758c2ecf20Sopenharmony_ci{ 38768c2ecf20Sopenharmony_ci struct sctp_chunk *asconf; 38778c2ecf20Sopenharmony_ci struct list_head *entry; 38788c2ecf20Sopenharmony_ci 38798c2ecf20Sopenharmony_ci if (list_empty(&asoc->addip_chunk_list)) 38808c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 38818c2ecf20Sopenharmony_ci 38828c2ecf20Sopenharmony_ci entry = asoc->addip_chunk_list.next; 38838c2ecf20Sopenharmony_ci asconf = list_entry(entry, struct sctp_chunk, list); 38848c2ecf20Sopenharmony_ci 38858c2ecf20Sopenharmony_ci list_del_init(entry); 38868c2ecf20Sopenharmony_ci sctp_chunk_hold(asconf); 38878c2ecf20Sopenharmony_ci asoc->addip_last_asconf = asconf; 38888c2ecf20Sopenharmony_ci 38898c2ecf20Sopenharmony_ci return sctp_sf_do_prm_asconf(net, ep, asoc, type, asconf, commands); 38908c2ecf20Sopenharmony_ci} 38918c2ecf20Sopenharmony_ci 38928c2ecf20Sopenharmony_ci/* 38938c2ecf20Sopenharmony_ci * ADDIP Section 4.3 General rules for address manipulation 38948c2ecf20Sopenharmony_ci * When building TLV parameters for the ASCONF Chunk that will add or 38958c2ecf20Sopenharmony_ci * delete IP addresses the D0 to D13 rules should be applied: 38968c2ecf20Sopenharmony_ci */ 38978c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_asconf_ack(struct net *net, 38988c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 38998c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 39008c2ecf20Sopenharmony_ci const union sctp_subtype type, 39018c2ecf20Sopenharmony_ci void *arg, 39028c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 39038c2ecf20Sopenharmony_ci{ 39048c2ecf20Sopenharmony_ci struct sctp_chunk *last_asconf = asoc->addip_last_asconf; 39058c2ecf20Sopenharmony_ci struct sctp_paramhdr *err_param = NULL; 39068c2ecf20Sopenharmony_ci struct sctp_chunk *asconf_ack = arg; 39078c2ecf20Sopenharmony_ci struct sctp_addiphdr *addip_hdr; 39088c2ecf20Sopenharmony_ci __u32 sent_serial, rcvd_serial; 39098c2ecf20Sopenharmony_ci struct sctp_chunk *abort; 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(asconf_ack, asoc)) { 39128c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 39138c2ecf20Sopenharmony_ci SCTP_NULL()); 39148c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 39158c2ecf20Sopenharmony_ci } 39168c2ecf20Sopenharmony_ci 39178c2ecf20Sopenharmony_ci /* Make sure that the ADDIP chunk has a valid length. */ 39188c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(asconf_ack, 39198c2ecf20Sopenharmony_ci sizeof(struct sctp_addip_chunk))) 39208c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 39218c2ecf20Sopenharmony_ci commands); 39228c2ecf20Sopenharmony_ci 39238c2ecf20Sopenharmony_ci /* ADD-IP, Section 4.1.2: 39248c2ecf20Sopenharmony_ci * This chunk MUST be sent in an authenticated way by using 39258c2ecf20Sopenharmony_ci * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk 39268c2ecf20Sopenharmony_ci * is received unauthenticated it MUST be silently discarded as 39278c2ecf20Sopenharmony_ci * described in [I-D.ietf-tsvwg-sctp-auth]. 39288c2ecf20Sopenharmony_ci */ 39298c2ecf20Sopenharmony_ci if (!asoc->peer.asconf_capable || 39308c2ecf20Sopenharmony_ci (!net->sctp.addip_noauth && !asconf_ack->auth)) 39318c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci addip_hdr = (struct sctp_addiphdr *)asconf_ack->skb->data; 39348c2ecf20Sopenharmony_ci rcvd_serial = ntohl(addip_hdr->serial); 39358c2ecf20Sopenharmony_ci 39368c2ecf20Sopenharmony_ci /* Verify the ASCONF-ACK chunk before processing it. */ 39378c2ecf20Sopenharmony_ci if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param)) 39388c2ecf20Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 39398c2ecf20Sopenharmony_ci (void *)err_param, commands); 39408c2ecf20Sopenharmony_ci 39418c2ecf20Sopenharmony_ci if (last_asconf) { 39428c2ecf20Sopenharmony_ci addip_hdr = (struct sctp_addiphdr *)last_asconf->subh.addip_hdr; 39438c2ecf20Sopenharmony_ci sent_serial = ntohl(addip_hdr->serial); 39448c2ecf20Sopenharmony_ci } else { 39458c2ecf20Sopenharmony_ci sent_serial = asoc->addip_serial - 1; 39468c2ecf20Sopenharmony_ci } 39478c2ecf20Sopenharmony_ci 39488c2ecf20Sopenharmony_ci /* D0) If an endpoint receives an ASCONF-ACK that is greater than or 39498c2ecf20Sopenharmony_ci * equal to the next serial number to be used but no ASCONF chunk is 39508c2ecf20Sopenharmony_ci * outstanding the endpoint MUST ABORT the association. Note that a 39518c2ecf20Sopenharmony_ci * sequence number is greater than if it is no more than 2^^31-1 39528c2ecf20Sopenharmony_ci * larger than the current sequence number (using serial arithmetic). 39538c2ecf20Sopenharmony_ci */ 39548c2ecf20Sopenharmony_ci if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) && 39558c2ecf20Sopenharmony_ci !(asoc->addip_last_asconf)) { 39568c2ecf20Sopenharmony_ci abort = sctp_make_abort(asoc, asconf_ack, 39578c2ecf20Sopenharmony_ci sizeof(struct sctp_errhdr)); 39588c2ecf20Sopenharmony_ci if (abort) { 39598c2ecf20Sopenharmony_ci sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0); 39608c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 39618c2ecf20Sopenharmony_ci SCTP_CHUNK(abort)); 39628c2ecf20Sopenharmony_ci } 39638c2ecf20Sopenharmony_ci /* We are going to ABORT, so we might as well stop 39648c2ecf20Sopenharmony_ci * processing the rest of the chunks in the packet. 39658c2ecf20Sopenharmony_ci */ 39668c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 39678c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 39688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 39698c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 39708c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 39718c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 39728c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); 39738c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 39748c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 39758c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 39768c2ecf20Sopenharmony_ci } 39778c2ecf20Sopenharmony_ci 39788c2ecf20Sopenharmony_ci if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) { 39798c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 39808c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci if (!sctp_process_asconf_ack((struct sctp_association *)asoc, 39838c2ecf20Sopenharmony_ci asconf_ack)) 39848c2ecf20Sopenharmony_ci return sctp_send_next_asconf(net, ep, 39858c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, 39868c2ecf20Sopenharmony_ci type, commands); 39878c2ecf20Sopenharmony_ci 39888c2ecf20Sopenharmony_ci abort = sctp_make_abort(asoc, asconf_ack, 39898c2ecf20Sopenharmony_ci sizeof(struct sctp_errhdr)); 39908c2ecf20Sopenharmony_ci if (abort) { 39918c2ecf20Sopenharmony_ci sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); 39928c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 39938c2ecf20Sopenharmony_ci SCTP_CHUNK(abort)); 39948c2ecf20Sopenharmony_ci } 39958c2ecf20Sopenharmony_ci /* We are going to ABORT, so we might as well stop 39968c2ecf20Sopenharmony_ci * processing the rest of the chunks in the packet. 39978c2ecf20Sopenharmony_ci */ 39988c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 39998c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 40008c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 40018c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 40028c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); 40038c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 40048c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 40058c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 40068c2ecf20Sopenharmony_ci } 40078c2ecf20Sopenharmony_ci 40088c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 40098c2ecf20Sopenharmony_ci} 40108c2ecf20Sopenharmony_ci 40118c2ecf20Sopenharmony_ci/* RE-CONFIG Section 5.2 Upon reception of an RECONF Chunk. */ 40128c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_reconf(struct net *net, 40138c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 40148c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 40158c2ecf20Sopenharmony_ci const union sctp_subtype type, 40168c2ecf20Sopenharmony_ci void *arg, 40178c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 40188c2ecf20Sopenharmony_ci{ 40198c2ecf20Sopenharmony_ci struct sctp_paramhdr *err_param = NULL; 40208c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 40218c2ecf20Sopenharmony_ci struct sctp_reconf_chunk *hdr; 40228c2ecf20Sopenharmony_ci union sctp_params param; 40238c2ecf20Sopenharmony_ci 40248c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 40258c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 40268c2ecf20Sopenharmony_ci SCTP_NULL()); 40278c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 40288c2ecf20Sopenharmony_ci } 40298c2ecf20Sopenharmony_ci 40308c2ecf20Sopenharmony_ci /* Make sure that the RECONF chunk has a valid length. */ 40318c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(*hdr))) 40328c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 40338c2ecf20Sopenharmony_ci commands); 40348c2ecf20Sopenharmony_ci 40358c2ecf20Sopenharmony_ci if (!sctp_verify_reconf(asoc, chunk, &err_param)) 40368c2ecf20Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 40378c2ecf20Sopenharmony_ci (void *)err_param, commands); 40388c2ecf20Sopenharmony_ci 40398c2ecf20Sopenharmony_ci hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; 40408c2ecf20Sopenharmony_ci sctp_walk_params(param, hdr, params) { 40418c2ecf20Sopenharmony_ci struct sctp_chunk *reply = NULL; 40428c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev = NULL; 40438c2ecf20Sopenharmony_ci 40448c2ecf20Sopenharmony_ci if (param.p->type == SCTP_PARAM_RESET_OUT_REQUEST) 40458c2ecf20Sopenharmony_ci reply = sctp_process_strreset_outreq( 40468c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 40478c2ecf20Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST) 40488c2ecf20Sopenharmony_ci reply = sctp_process_strreset_inreq( 40498c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 40508c2ecf20Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST) 40518c2ecf20Sopenharmony_ci reply = sctp_process_strreset_tsnreq( 40528c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 40538c2ecf20Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) 40548c2ecf20Sopenharmony_ci reply = sctp_process_strreset_addstrm_out( 40558c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 40568c2ecf20Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) 40578c2ecf20Sopenharmony_ci reply = sctp_process_strreset_addstrm_in( 40588c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 40598c2ecf20Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_RESPONSE) 40608c2ecf20Sopenharmony_ci reply = sctp_process_strreset_resp( 40618c2ecf20Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci if (ev) 40648c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 40658c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ev)); 40668c2ecf20Sopenharmony_ci 40678c2ecf20Sopenharmony_ci if (reply) 40688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 40698c2ecf20Sopenharmony_ci SCTP_CHUNK(reply)); 40708c2ecf20Sopenharmony_ci } 40718c2ecf20Sopenharmony_ci 40728c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 40738c2ecf20Sopenharmony_ci} 40748c2ecf20Sopenharmony_ci 40758c2ecf20Sopenharmony_ci/* 40768c2ecf20Sopenharmony_ci * PR-SCTP Section 3.6 Receiver Side Implementation of PR-SCTP 40778c2ecf20Sopenharmony_ci * 40788c2ecf20Sopenharmony_ci * When a FORWARD TSN chunk arrives, the data receiver MUST first update 40798c2ecf20Sopenharmony_ci * its cumulative TSN point to the value carried in the FORWARD TSN 40808c2ecf20Sopenharmony_ci * chunk, and then MUST further advance its cumulative TSN point locally 40818c2ecf20Sopenharmony_ci * if possible. 40828c2ecf20Sopenharmony_ci * After the above processing, the data receiver MUST stop reporting any 40838c2ecf20Sopenharmony_ci * missing TSNs earlier than or equal to the new cumulative TSN point. 40848c2ecf20Sopenharmony_ci * 40858c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 40868c2ecf20Sopenharmony_ci * 40878c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 40888c2ecf20Sopenharmony_ci */ 40898c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_eat_fwd_tsn(struct net *net, 40908c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 40918c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 40928c2ecf20Sopenharmony_ci const union sctp_subtype type, 40938c2ecf20Sopenharmony_ci void *arg, 40948c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 40958c2ecf20Sopenharmony_ci{ 40968c2ecf20Sopenharmony_ci struct sctp_fwdtsn_hdr *fwdtsn_hdr; 40978c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 40988c2ecf20Sopenharmony_ci __u16 len; 40998c2ecf20Sopenharmony_ci __u32 tsn; 41008c2ecf20Sopenharmony_ci 41018c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 41028c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 41038c2ecf20Sopenharmony_ci SCTP_NULL()); 41048c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 41058c2ecf20Sopenharmony_ci } 41068c2ecf20Sopenharmony_ci 41078c2ecf20Sopenharmony_ci if (!asoc->peer.prsctp_capable) 41088c2ecf20Sopenharmony_ci return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); 41098c2ecf20Sopenharmony_ci 41108c2ecf20Sopenharmony_ci /* Make sure that the FORWARD_TSN chunk has valid length. */ 41118c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_ftsnchk_len(&asoc->stream))) 41128c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 41138c2ecf20Sopenharmony_ci commands); 41148c2ecf20Sopenharmony_ci 41158c2ecf20Sopenharmony_ci fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; 41168c2ecf20Sopenharmony_ci chunk->subh.fwdtsn_hdr = fwdtsn_hdr; 41178c2ecf20Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 41188c2ecf20Sopenharmony_ci len -= sizeof(struct sctp_chunkhdr); 41198c2ecf20Sopenharmony_ci skb_pull(chunk->skb, len); 41208c2ecf20Sopenharmony_ci 41218c2ecf20Sopenharmony_ci tsn = ntohl(fwdtsn_hdr->new_cum_tsn); 41228c2ecf20Sopenharmony_ci pr_debug("%s: TSN 0x%x\n", __func__, tsn); 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci /* The TSN is too high--silently discard the chunk and count on it 41258c2ecf20Sopenharmony_ci * getting retransmitted later. 41268c2ecf20Sopenharmony_ci */ 41278c2ecf20Sopenharmony_ci if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) 41288c2ecf20Sopenharmony_ci goto discard_noforce; 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci if (!asoc->stream.si->validate_ftsn(chunk)) 41318c2ecf20Sopenharmony_ci goto discard_noforce; 41328c2ecf20Sopenharmony_ci 41338c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); 41348c2ecf20Sopenharmony_ci if (len > sctp_ftsnhdr_len(&asoc->stream)) 41358c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 41368c2ecf20Sopenharmony_ci SCTP_CHUNK(chunk)); 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ci /* Count this as receiving DATA. */ 41398c2ecf20Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { 41408c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 41418c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 41428c2ecf20Sopenharmony_ci } 41438c2ecf20Sopenharmony_ci 41448c2ecf20Sopenharmony_ci /* FIXME: For now send a SACK, but DATA processing may 41458c2ecf20Sopenharmony_ci * send another. 41468c2ecf20Sopenharmony_ci */ 41478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE()); 41488c2ecf20Sopenharmony_ci 41498c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 41508c2ecf20Sopenharmony_ci 41518c2ecf20Sopenharmony_cidiscard_noforce: 41528c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 41538c2ecf20Sopenharmony_ci} 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_eat_fwd_tsn_fast( 41568c2ecf20Sopenharmony_ci struct net *net, 41578c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 41588c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 41598c2ecf20Sopenharmony_ci const union sctp_subtype type, 41608c2ecf20Sopenharmony_ci void *arg, 41618c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 41628c2ecf20Sopenharmony_ci{ 41638c2ecf20Sopenharmony_ci struct sctp_fwdtsn_hdr *fwdtsn_hdr; 41648c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 41658c2ecf20Sopenharmony_ci __u16 len; 41668c2ecf20Sopenharmony_ci __u32 tsn; 41678c2ecf20Sopenharmony_ci 41688c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 41698c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 41708c2ecf20Sopenharmony_ci SCTP_NULL()); 41718c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 41728c2ecf20Sopenharmony_ci } 41738c2ecf20Sopenharmony_ci 41748c2ecf20Sopenharmony_ci if (!asoc->peer.prsctp_capable) 41758c2ecf20Sopenharmony_ci return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); 41768c2ecf20Sopenharmony_ci 41778c2ecf20Sopenharmony_ci /* Make sure that the FORWARD_TSN chunk has a valid length. */ 41788c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_ftsnchk_len(&asoc->stream))) 41798c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 41808c2ecf20Sopenharmony_ci commands); 41818c2ecf20Sopenharmony_ci 41828c2ecf20Sopenharmony_ci fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; 41838c2ecf20Sopenharmony_ci chunk->subh.fwdtsn_hdr = fwdtsn_hdr; 41848c2ecf20Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 41858c2ecf20Sopenharmony_ci len -= sizeof(struct sctp_chunkhdr); 41868c2ecf20Sopenharmony_ci skb_pull(chunk->skb, len); 41878c2ecf20Sopenharmony_ci 41888c2ecf20Sopenharmony_ci tsn = ntohl(fwdtsn_hdr->new_cum_tsn); 41898c2ecf20Sopenharmony_ci pr_debug("%s: TSN 0x%x\n", __func__, tsn); 41908c2ecf20Sopenharmony_ci 41918c2ecf20Sopenharmony_ci /* The TSN is too high--silently discard the chunk and count on it 41928c2ecf20Sopenharmony_ci * getting retransmitted later. 41938c2ecf20Sopenharmony_ci */ 41948c2ecf20Sopenharmony_ci if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) 41958c2ecf20Sopenharmony_ci goto gen_shutdown; 41968c2ecf20Sopenharmony_ci 41978c2ecf20Sopenharmony_ci if (!asoc->stream.si->validate_ftsn(chunk)) 41988c2ecf20Sopenharmony_ci goto gen_shutdown; 41998c2ecf20Sopenharmony_ci 42008c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); 42018c2ecf20Sopenharmony_ci if (len > sctp_ftsnhdr_len(&asoc->stream)) 42028c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 42038c2ecf20Sopenharmony_ci SCTP_CHUNK(chunk)); 42048c2ecf20Sopenharmony_ci 42058c2ecf20Sopenharmony_ci /* Go a head and force a SACK, since we are shutting down. */ 42068c2ecf20Sopenharmony_cigen_shutdown: 42078c2ecf20Sopenharmony_ci /* Implementor's Guide. 42088c2ecf20Sopenharmony_ci * 42098c2ecf20Sopenharmony_ci * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately 42108c2ecf20Sopenharmony_ci * respond to each received packet containing one or more DATA chunk(s) 42118c2ecf20Sopenharmony_ci * with a SACK, a SHUTDOWN chunk, and restart the T2-shutdown timer 42128c2ecf20Sopenharmony_ci */ 42138c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SHUTDOWN, SCTP_NULL()); 42148c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 42158c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 42168c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 42178c2ecf20Sopenharmony_ci 42188c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 42198c2ecf20Sopenharmony_ci} 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci/* 42228c2ecf20Sopenharmony_ci * SCTP-AUTH Section 6.3 Receiving authenticated chukns 42238c2ecf20Sopenharmony_ci * 42248c2ecf20Sopenharmony_ci * The receiver MUST use the HMAC algorithm indicated in the HMAC 42258c2ecf20Sopenharmony_ci * Identifier field. If this algorithm was not specified by the 42268c2ecf20Sopenharmony_ci * receiver in the HMAC-ALGO parameter in the INIT or INIT-ACK chunk 42278c2ecf20Sopenharmony_ci * during association setup, the AUTH chunk and all chunks after it MUST 42288c2ecf20Sopenharmony_ci * be discarded and an ERROR chunk SHOULD be sent with the error cause 42298c2ecf20Sopenharmony_ci * defined in Section 4.1. 42308c2ecf20Sopenharmony_ci * 42318c2ecf20Sopenharmony_ci * If an endpoint with no shared key receives a Shared Key Identifier 42328c2ecf20Sopenharmony_ci * other than 0, it MUST silently discard all authenticated chunks. If 42338c2ecf20Sopenharmony_ci * the endpoint has at least one endpoint pair shared key for the peer, 42348c2ecf20Sopenharmony_ci * it MUST use the key specified by the Shared Key Identifier if a 42358c2ecf20Sopenharmony_ci * key has been configured for that Shared Key Identifier. If no 42368c2ecf20Sopenharmony_ci * endpoint pair shared key has been configured for that Shared Key 42378c2ecf20Sopenharmony_ci * Identifier, all authenticated chunks MUST be silently discarded. 42388c2ecf20Sopenharmony_ci * 42398c2ecf20Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 42408c2ecf20Sopenharmony_ci * 42418c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 42428c2ecf20Sopenharmony_ci */ 42438c2ecf20Sopenharmony_cistatic enum sctp_ierror sctp_sf_authenticate( 42448c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 42458c2ecf20Sopenharmony_ci struct sctp_chunk *chunk) 42468c2ecf20Sopenharmony_ci{ 42478c2ecf20Sopenharmony_ci struct sctp_shared_key *sh_key = NULL; 42488c2ecf20Sopenharmony_ci struct sctp_authhdr *auth_hdr; 42498c2ecf20Sopenharmony_ci __u8 *save_digest, *digest; 42508c2ecf20Sopenharmony_ci struct sctp_hmac *hmac; 42518c2ecf20Sopenharmony_ci unsigned int sig_len; 42528c2ecf20Sopenharmony_ci __u16 key_id; 42538c2ecf20Sopenharmony_ci 42548c2ecf20Sopenharmony_ci /* Pull in the auth header, so we can do some more verification */ 42558c2ecf20Sopenharmony_ci auth_hdr = (struct sctp_authhdr *)chunk->skb->data; 42568c2ecf20Sopenharmony_ci chunk->subh.auth_hdr = auth_hdr; 42578c2ecf20Sopenharmony_ci skb_pull(chunk->skb, sizeof(*auth_hdr)); 42588c2ecf20Sopenharmony_ci 42598c2ecf20Sopenharmony_ci /* Make sure that we support the HMAC algorithm from the auth 42608c2ecf20Sopenharmony_ci * chunk. 42618c2ecf20Sopenharmony_ci */ 42628c2ecf20Sopenharmony_ci if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id)) 42638c2ecf20Sopenharmony_ci return SCTP_IERROR_AUTH_BAD_HMAC; 42648c2ecf20Sopenharmony_ci 42658c2ecf20Sopenharmony_ci /* Make sure that the provided shared key identifier has been 42668c2ecf20Sopenharmony_ci * configured 42678c2ecf20Sopenharmony_ci */ 42688c2ecf20Sopenharmony_ci key_id = ntohs(auth_hdr->shkey_id); 42698c2ecf20Sopenharmony_ci if (key_id != asoc->active_key_id) { 42708c2ecf20Sopenharmony_ci sh_key = sctp_auth_get_shkey(asoc, key_id); 42718c2ecf20Sopenharmony_ci if (!sh_key) 42728c2ecf20Sopenharmony_ci return SCTP_IERROR_AUTH_BAD_KEYID; 42738c2ecf20Sopenharmony_ci } 42748c2ecf20Sopenharmony_ci 42758c2ecf20Sopenharmony_ci /* Make sure that the length of the signature matches what 42768c2ecf20Sopenharmony_ci * we expect. 42778c2ecf20Sopenharmony_ci */ 42788c2ecf20Sopenharmony_ci sig_len = ntohs(chunk->chunk_hdr->length) - 42798c2ecf20Sopenharmony_ci sizeof(struct sctp_auth_chunk); 42808c2ecf20Sopenharmony_ci hmac = sctp_auth_get_hmac(ntohs(auth_hdr->hmac_id)); 42818c2ecf20Sopenharmony_ci if (sig_len != hmac->hmac_len) 42828c2ecf20Sopenharmony_ci return SCTP_IERROR_PROTO_VIOLATION; 42838c2ecf20Sopenharmony_ci 42848c2ecf20Sopenharmony_ci /* Now that we've done validation checks, we can compute and 42858c2ecf20Sopenharmony_ci * verify the hmac. The steps involved are: 42868c2ecf20Sopenharmony_ci * 1. Save the digest from the chunk. 42878c2ecf20Sopenharmony_ci * 2. Zero out the digest in the chunk. 42888c2ecf20Sopenharmony_ci * 3. Compute the new digest 42898c2ecf20Sopenharmony_ci * 4. Compare saved and new digests. 42908c2ecf20Sopenharmony_ci */ 42918c2ecf20Sopenharmony_ci digest = auth_hdr->hmac; 42928c2ecf20Sopenharmony_ci skb_pull(chunk->skb, sig_len); 42938c2ecf20Sopenharmony_ci 42948c2ecf20Sopenharmony_ci save_digest = kmemdup(digest, sig_len, GFP_ATOMIC); 42958c2ecf20Sopenharmony_ci if (!save_digest) 42968c2ecf20Sopenharmony_ci goto nomem; 42978c2ecf20Sopenharmony_ci 42988c2ecf20Sopenharmony_ci memset(digest, 0, sig_len); 42998c2ecf20Sopenharmony_ci 43008c2ecf20Sopenharmony_ci sctp_auth_calculate_hmac(asoc, chunk->skb, 43018c2ecf20Sopenharmony_ci (struct sctp_auth_chunk *)chunk->chunk_hdr, 43028c2ecf20Sopenharmony_ci sh_key, GFP_ATOMIC); 43038c2ecf20Sopenharmony_ci 43048c2ecf20Sopenharmony_ci /* Discard the packet if the digests do not match */ 43058c2ecf20Sopenharmony_ci if (memcmp(save_digest, digest, sig_len)) { 43068c2ecf20Sopenharmony_ci kfree(save_digest); 43078c2ecf20Sopenharmony_ci return SCTP_IERROR_BAD_SIG; 43088c2ecf20Sopenharmony_ci } 43098c2ecf20Sopenharmony_ci 43108c2ecf20Sopenharmony_ci kfree(save_digest); 43118c2ecf20Sopenharmony_ci chunk->auth = 1; 43128c2ecf20Sopenharmony_ci 43138c2ecf20Sopenharmony_ci return SCTP_IERROR_NO_ERROR; 43148c2ecf20Sopenharmony_cinomem: 43158c2ecf20Sopenharmony_ci return SCTP_IERROR_NOMEM; 43168c2ecf20Sopenharmony_ci} 43178c2ecf20Sopenharmony_ci 43188c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_eat_auth(struct net *net, 43198c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 43208c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 43218c2ecf20Sopenharmony_ci const union sctp_subtype type, 43228c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 43238c2ecf20Sopenharmony_ci{ 43248c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 43258c2ecf20Sopenharmony_ci struct sctp_authhdr *auth_hdr; 43268c2ecf20Sopenharmony_ci struct sctp_chunk *err_chunk; 43278c2ecf20Sopenharmony_ci enum sctp_ierror error; 43288c2ecf20Sopenharmony_ci 43298c2ecf20Sopenharmony_ci /* Make sure that the peer has AUTH capable */ 43308c2ecf20Sopenharmony_ci if (!asoc->peer.auth_capable) 43318c2ecf20Sopenharmony_ci return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); 43328c2ecf20Sopenharmony_ci 43338c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 43348c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 43358c2ecf20Sopenharmony_ci SCTP_NULL()); 43368c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 43378c2ecf20Sopenharmony_ci } 43388c2ecf20Sopenharmony_ci 43398c2ecf20Sopenharmony_ci /* Make sure that the AUTH chunk has valid length. */ 43408c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk))) 43418c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 43428c2ecf20Sopenharmony_ci commands); 43438c2ecf20Sopenharmony_ci 43448c2ecf20Sopenharmony_ci auth_hdr = (struct sctp_authhdr *)chunk->skb->data; 43458c2ecf20Sopenharmony_ci error = sctp_sf_authenticate(asoc, chunk); 43468c2ecf20Sopenharmony_ci switch (error) { 43478c2ecf20Sopenharmony_ci case SCTP_IERROR_AUTH_BAD_HMAC: 43488c2ecf20Sopenharmony_ci /* Generate the ERROR chunk and discard the rest 43498c2ecf20Sopenharmony_ci * of the packet 43508c2ecf20Sopenharmony_ci */ 43518c2ecf20Sopenharmony_ci err_chunk = sctp_make_op_error(asoc, chunk, 43528c2ecf20Sopenharmony_ci SCTP_ERROR_UNSUP_HMAC, 43538c2ecf20Sopenharmony_ci &auth_hdr->hmac_id, 43548c2ecf20Sopenharmony_ci sizeof(__u16), 0); 43558c2ecf20Sopenharmony_ci if (err_chunk) { 43568c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 43578c2ecf20Sopenharmony_ci SCTP_CHUNK(err_chunk)); 43588c2ecf20Sopenharmony_ci } 43598c2ecf20Sopenharmony_ci fallthrough; 43608c2ecf20Sopenharmony_ci case SCTP_IERROR_AUTH_BAD_KEYID: 43618c2ecf20Sopenharmony_ci case SCTP_IERROR_BAD_SIG: 43628c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 43638c2ecf20Sopenharmony_ci 43648c2ecf20Sopenharmony_ci case SCTP_IERROR_PROTO_VIOLATION: 43658c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 43668c2ecf20Sopenharmony_ci commands); 43678c2ecf20Sopenharmony_ci 43688c2ecf20Sopenharmony_ci case SCTP_IERROR_NOMEM: 43698c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 43708c2ecf20Sopenharmony_ci 43718c2ecf20Sopenharmony_ci default: /* Prevent gcc warnings */ 43728c2ecf20Sopenharmony_ci break; 43738c2ecf20Sopenharmony_ci } 43748c2ecf20Sopenharmony_ci 43758c2ecf20Sopenharmony_ci if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) { 43768c2ecf20Sopenharmony_ci struct sctp_ulpevent *ev; 43778c2ecf20Sopenharmony_ci 43788c2ecf20Sopenharmony_ci ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id), 43798c2ecf20Sopenharmony_ci SCTP_AUTH_NEW_KEY, GFP_ATOMIC); 43808c2ecf20Sopenharmony_ci 43818c2ecf20Sopenharmony_ci if (!ev) 43828c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 43838c2ecf20Sopenharmony_ci 43848c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 43858c2ecf20Sopenharmony_ci SCTP_ULPEVENT(ev)); 43868c2ecf20Sopenharmony_ci } 43878c2ecf20Sopenharmony_ci 43888c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 43898c2ecf20Sopenharmony_ci} 43908c2ecf20Sopenharmony_ci 43918c2ecf20Sopenharmony_ci/* 43928c2ecf20Sopenharmony_ci * Process an unknown chunk. 43938c2ecf20Sopenharmony_ci * 43948c2ecf20Sopenharmony_ci * Section: 3.2. Also, 2.1 in the implementor's guide. 43958c2ecf20Sopenharmony_ci * 43968c2ecf20Sopenharmony_ci * Chunk Types are encoded such that the highest-order two bits specify 43978c2ecf20Sopenharmony_ci * the action that must be taken if the processing endpoint does not 43988c2ecf20Sopenharmony_ci * recognize the Chunk Type. 43998c2ecf20Sopenharmony_ci * 44008c2ecf20Sopenharmony_ci * 00 - Stop processing this SCTP packet and discard it, do not process 44018c2ecf20Sopenharmony_ci * any further chunks within it. 44028c2ecf20Sopenharmony_ci * 44038c2ecf20Sopenharmony_ci * 01 - Stop processing this SCTP packet and discard it, do not process 44048c2ecf20Sopenharmony_ci * any further chunks within it, and report the unrecognized 44058c2ecf20Sopenharmony_ci * chunk in an 'Unrecognized Chunk Type'. 44068c2ecf20Sopenharmony_ci * 44078c2ecf20Sopenharmony_ci * 10 - Skip this chunk and continue processing. 44088c2ecf20Sopenharmony_ci * 44098c2ecf20Sopenharmony_ci * 11 - Skip this chunk and continue processing, but report in an ERROR 44108c2ecf20Sopenharmony_ci * Chunk using the 'Unrecognized Chunk Type' cause of error. 44118c2ecf20Sopenharmony_ci * 44128c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 44138c2ecf20Sopenharmony_ci */ 44148c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_unk_chunk(struct net *net, 44158c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 44168c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 44178c2ecf20Sopenharmony_ci const union sctp_subtype type, 44188c2ecf20Sopenharmony_ci void *arg, 44198c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 44208c2ecf20Sopenharmony_ci{ 44218c2ecf20Sopenharmony_ci struct sctp_chunk *unk_chunk = arg; 44228c2ecf20Sopenharmony_ci struct sctp_chunk *err_chunk; 44238c2ecf20Sopenharmony_ci struct sctp_chunkhdr *hdr; 44248c2ecf20Sopenharmony_ci 44258c2ecf20Sopenharmony_ci pr_debug("%s: processing unknown chunk id:%d\n", __func__, type.chunk); 44268c2ecf20Sopenharmony_ci 44278c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(unk_chunk, asoc)) 44288c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 44298c2ecf20Sopenharmony_ci 44308c2ecf20Sopenharmony_ci /* Make sure that the chunk has a valid length. 44318c2ecf20Sopenharmony_ci * Since we don't know the chunk type, we use a general 44328c2ecf20Sopenharmony_ci * chunkhdr structure to make a comparison. 44338c2ecf20Sopenharmony_ci */ 44348c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(unk_chunk, sizeof(*hdr))) 44358c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 44368c2ecf20Sopenharmony_ci commands); 44378c2ecf20Sopenharmony_ci 44388c2ecf20Sopenharmony_ci switch (type.chunk & SCTP_CID_ACTION_MASK) { 44398c2ecf20Sopenharmony_ci case SCTP_CID_ACTION_DISCARD: 44408c2ecf20Sopenharmony_ci /* Discard the packet. */ 44418c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 44428c2ecf20Sopenharmony_ci case SCTP_CID_ACTION_DISCARD_ERR: 44438c2ecf20Sopenharmony_ci /* Generate an ERROR chunk as response. */ 44448c2ecf20Sopenharmony_ci hdr = unk_chunk->chunk_hdr; 44458c2ecf20Sopenharmony_ci err_chunk = sctp_make_op_error(asoc, unk_chunk, 44468c2ecf20Sopenharmony_ci SCTP_ERROR_UNKNOWN_CHUNK, hdr, 44478c2ecf20Sopenharmony_ci SCTP_PAD4(ntohs(hdr->length)), 44488c2ecf20Sopenharmony_ci 0); 44498c2ecf20Sopenharmony_ci if (err_chunk) { 44508c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 44518c2ecf20Sopenharmony_ci SCTP_CHUNK(err_chunk)); 44528c2ecf20Sopenharmony_ci } 44538c2ecf20Sopenharmony_ci 44548c2ecf20Sopenharmony_ci /* Discard the packet. */ 44558c2ecf20Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 44568c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 44578c2ecf20Sopenharmony_ci case SCTP_CID_ACTION_SKIP: 44588c2ecf20Sopenharmony_ci /* Skip the chunk. */ 44598c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 44608c2ecf20Sopenharmony_ci case SCTP_CID_ACTION_SKIP_ERR: 44618c2ecf20Sopenharmony_ci /* Generate an ERROR chunk as response. */ 44628c2ecf20Sopenharmony_ci hdr = unk_chunk->chunk_hdr; 44638c2ecf20Sopenharmony_ci err_chunk = sctp_make_op_error(asoc, unk_chunk, 44648c2ecf20Sopenharmony_ci SCTP_ERROR_UNKNOWN_CHUNK, hdr, 44658c2ecf20Sopenharmony_ci SCTP_PAD4(ntohs(hdr->length)), 44668c2ecf20Sopenharmony_ci 0); 44678c2ecf20Sopenharmony_ci if (err_chunk) { 44688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 44698c2ecf20Sopenharmony_ci SCTP_CHUNK(err_chunk)); 44708c2ecf20Sopenharmony_ci } 44718c2ecf20Sopenharmony_ci /* Skip the chunk. */ 44728c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 44738c2ecf20Sopenharmony_ci default: 44748c2ecf20Sopenharmony_ci break; 44758c2ecf20Sopenharmony_ci } 44768c2ecf20Sopenharmony_ci 44778c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 44788c2ecf20Sopenharmony_ci} 44798c2ecf20Sopenharmony_ci 44808c2ecf20Sopenharmony_ci/* 44818c2ecf20Sopenharmony_ci * Discard the chunk. 44828c2ecf20Sopenharmony_ci * 44838c2ecf20Sopenharmony_ci * Section: 0.2, 5.2.3, 5.2.5, 5.2.6, 6.0, 8.4.6, 8.5.1c, 9.2 44848c2ecf20Sopenharmony_ci * [Too numerous to mention...] 44858c2ecf20Sopenharmony_ci * Verification Tag: No verification needed. 44868c2ecf20Sopenharmony_ci * Inputs 44878c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 44888c2ecf20Sopenharmony_ci * 44898c2ecf20Sopenharmony_ci * Outputs 44908c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 44918c2ecf20Sopenharmony_ci * 44928c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 44938c2ecf20Sopenharmony_ci */ 44948c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_discard_chunk(struct net *net, 44958c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 44968c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 44978c2ecf20Sopenharmony_ci const union sctp_subtype type, 44988c2ecf20Sopenharmony_ci void *arg, 44998c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 45008c2ecf20Sopenharmony_ci{ 45018c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 45028c2ecf20Sopenharmony_ci 45038c2ecf20Sopenharmony_ci if (asoc && !sctp_vtag_verify(chunk, asoc)) 45048c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 45058c2ecf20Sopenharmony_ci 45068c2ecf20Sopenharmony_ci /* Make sure that the chunk has a valid length. 45078c2ecf20Sopenharmony_ci * Since we don't know the chunk type, we use a general 45088c2ecf20Sopenharmony_ci * chunkhdr structure to make a comparison. 45098c2ecf20Sopenharmony_ci */ 45108c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 45118c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 45128c2ecf20Sopenharmony_ci commands); 45138c2ecf20Sopenharmony_ci 45148c2ecf20Sopenharmony_ci pr_debug("%s: chunk:%d is discarded\n", __func__, type.chunk); 45158c2ecf20Sopenharmony_ci 45168c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 45178c2ecf20Sopenharmony_ci} 45188c2ecf20Sopenharmony_ci 45198c2ecf20Sopenharmony_ci/* 45208c2ecf20Sopenharmony_ci * Discard the whole packet. 45218c2ecf20Sopenharmony_ci * 45228c2ecf20Sopenharmony_ci * Section: 8.4 2) 45238c2ecf20Sopenharmony_ci * 45248c2ecf20Sopenharmony_ci * 2) If the OOTB packet contains an ABORT chunk, the receiver MUST 45258c2ecf20Sopenharmony_ci * silently discard the OOTB packet and take no further action. 45268c2ecf20Sopenharmony_ci * 45278c2ecf20Sopenharmony_ci * Verification Tag: No verification necessary 45288c2ecf20Sopenharmony_ci * 45298c2ecf20Sopenharmony_ci * Inputs 45308c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 45318c2ecf20Sopenharmony_ci * 45328c2ecf20Sopenharmony_ci * Outputs 45338c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 45348c2ecf20Sopenharmony_ci * 45358c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 45368c2ecf20Sopenharmony_ci */ 45378c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_pdiscard(struct net *net, 45388c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 45398c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 45408c2ecf20Sopenharmony_ci const union sctp_subtype type, 45418c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 45428c2ecf20Sopenharmony_ci{ 45438c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS); 45448c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 45458c2ecf20Sopenharmony_ci 45468c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 45478c2ecf20Sopenharmony_ci} 45488c2ecf20Sopenharmony_ci 45498c2ecf20Sopenharmony_ci 45508c2ecf20Sopenharmony_ci/* 45518c2ecf20Sopenharmony_ci * The other end is violating protocol. 45528c2ecf20Sopenharmony_ci * 45538c2ecf20Sopenharmony_ci * Section: Not specified 45548c2ecf20Sopenharmony_ci * Verification Tag: Not specified 45558c2ecf20Sopenharmony_ci * Inputs 45568c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 45578c2ecf20Sopenharmony_ci * 45588c2ecf20Sopenharmony_ci * Outputs 45598c2ecf20Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 45608c2ecf20Sopenharmony_ci * 45618c2ecf20Sopenharmony_ci * We simply tag the chunk as a violation. The state machine will log 45628c2ecf20Sopenharmony_ci * the violation and continue. 45638c2ecf20Sopenharmony_ci */ 45648c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_violation(struct net *net, 45658c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 45668c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 45678c2ecf20Sopenharmony_ci const union sctp_subtype type, 45688c2ecf20Sopenharmony_ci void *arg, 45698c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 45708c2ecf20Sopenharmony_ci{ 45718c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 45728c2ecf20Sopenharmony_ci 45738c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 45748c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 45758c2ecf20Sopenharmony_ci 45768c2ecf20Sopenharmony_ci /* Make sure that the chunk has a valid length. */ 45778c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 45788c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 45798c2ecf20Sopenharmony_ci commands); 45808c2ecf20Sopenharmony_ci 45818c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_VIOLATION; 45828c2ecf20Sopenharmony_ci} 45838c2ecf20Sopenharmony_ci 45848c2ecf20Sopenharmony_ci/* 45858c2ecf20Sopenharmony_ci * Common function to handle a protocol violation. 45868c2ecf20Sopenharmony_ci */ 45878c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_abort_violation( 45888c2ecf20Sopenharmony_ci struct net *net, 45898c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 45908c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 45918c2ecf20Sopenharmony_ci void *arg, 45928c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 45938c2ecf20Sopenharmony_ci const __u8 *payload, 45948c2ecf20Sopenharmony_ci const size_t paylen) 45958c2ecf20Sopenharmony_ci{ 45968c2ecf20Sopenharmony_ci struct sctp_packet *packet = NULL; 45978c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 45988c2ecf20Sopenharmony_ci struct sctp_chunk *abort = NULL; 45998c2ecf20Sopenharmony_ci 46008c2ecf20Sopenharmony_ci /* SCTP-AUTH, Section 6.3: 46018c2ecf20Sopenharmony_ci * It should be noted that if the receiver wants to tear 46028c2ecf20Sopenharmony_ci * down an association in an authenticated way only, the 46038c2ecf20Sopenharmony_ci * handling of malformed packets should not result in 46048c2ecf20Sopenharmony_ci * tearing down the association. 46058c2ecf20Sopenharmony_ci * 46068c2ecf20Sopenharmony_ci * This means that if we only want to abort associations 46078c2ecf20Sopenharmony_ci * in an authenticated way (i.e AUTH+ABORT), then we 46088c2ecf20Sopenharmony_ci * can't destroy this association just because the packet 46098c2ecf20Sopenharmony_ci * was malformed. 46108c2ecf20Sopenharmony_ci */ 46118c2ecf20Sopenharmony_ci if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 46128c2ecf20Sopenharmony_ci goto discard; 46138c2ecf20Sopenharmony_ci 46148c2ecf20Sopenharmony_ci /* Make the abort chunk. */ 46158c2ecf20Sopenharmony_ci abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); 46168c2ecf20Sopenharmony_ci if (!abort) 46178c2ecf20Sopenharmony_ci goto nomem; 46188c2ecf20Sopenharmony_ci 46198c2ecf20Sopenharmony_ci if (asoc) { 46208c2ecf20Sopenharmony_ci /* Treat INIT-ACK as a special case during COOKIE-WAIT. */ 46218c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK && 46228c2ecf20Sopenharmony_ci !asoc->peer.i.init_tag) { 46238c2ecf20Sopenharmony_ci struct sctp_initack_chunk *initack; 46248c2ecf20Sopenharmony_ci 46258c2ecf20Sopenharmony_ci initack = (struct sctp_initack_chunk *)chunk->chunk_hdr; 46268c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(*initack))) 46278c2ecf20Sopenharmony_ci abort->chunk_hdr->flags |= SCTP_CHUNK_FLAG_T; 46288c2ecf20Sopenharmony_ci else { 46298c2ecf20Sopenharmony_ci unsigned int inittag; 46308c2ecf20Sopenharmony_ci 46318c2ecf20Sopenharmony_ci inittag = ntohl(initack->init_hdr.init_tag); 46328c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_INITTAG, 46338c2ecf20Sopenharmony_ci SCTP_U32(inittag)); 46348c2ecf20Sopenharmony_ci } 46358c2ecf20Sopenharmony_ci } 46368c2ecf20Sopenharmony_ci 46378c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 46388c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 46398c2ecf20Sopenharmony_ci 46408c2ecf20Sopenharmony_ci if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { 46418c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 46428c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 46438c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 46448c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNREFUSED)); 46458c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 46468c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); 46478c2ecf20Sopenharmony_ci } else { 46488c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 46498c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 46508c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 46518c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); 46528c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 46538c2ecf20Sopenharmony_ci } 46548c2ecf20Sopenharmony_ci } else { 46558c2ecf20Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 46568c2ecf20Sopenharmony_ci 46578c2ecf20Sopenharmony_ci if (!packet) 46588c2ecf20Sopenharmony_ci goto nomem_pkt; 46598c2ecf20Sopenharmony_ci 46608c2ecf20Sopenharmony_ci if (sctp_test_T_bit(abort)) 46618c2ecf20Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 46628c2ecf20Sopenharmony_ci 46638c2ecf20Sopenharmony_ci abort->skb->sk = ep->base.sk; 46648c2ecf20Sopenharmony_ci 46658c2ecf20Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 46668c2ecf20Sopenharmony_ci 46678c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 46688c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 46698c2ecf20Sopenharmony_ci 46708c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 46718c2ecf20Sopenharmony_ci } 46728c2ecf20Sopenharmony_ci 46738c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 46748c2ecf20Sopenharmony_ci 46758c2ecf20Sopenharmony_cidiscard: 46768c2ecf20Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands); 46778c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 46788c2ecf20Sopenharmony_ci 46798c2ecf20Sopenharmony_cinomem_pkt: 46808c2ecf20Sopenharmony_ci sctp_chunk_free(abort); 46818c2ecf20Sopenharmony_cinomem: 46828c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 46838c2ecf20Sopenharmony_ci} 46848c2ecf20Sopenharmony_ci 46858c2ecf20Sopenharmony_ci/* 46868c2ecf20Sopenharmony_ci * Handle a protocol violation when the chunk length is invalid. 46878c2ecf20Sopenharmony_ci * "Invalid" length is identified as smaller than the minimal length a 46888c2ecf20Sopenharmony_ci * given chunk can be. For example, a SACK chunk has invalid length 46898c2ecf20Sopenharmony_ci * if its length is set to be smaller than the size of struct sctp_sack_chunk. 46908c2ecf20Sopenharmony_ci * 46918c2ecf20Sopenharmony_ci * We inform the other end by sending an ABORT with a Protocol Violation 46928c2ecf20Sopenharmony_ci * error code. 46938c2ecf20Sopenharmony_ci * 46948c2ecf20Sopenharmony_ci * Section: Not specified 46958c2ecf20Sopenharmony_ci * Verification Tag: Nothing to do 46968c2ecf20Sopenharmony_ci * Inputs 46978c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 46988c2ecf20Sopenharmony_ci * 46998c2ecf20Sopenharmony_ci * Outputs 47008c2ecf20Sopenharmony_ci * (reply_msg, msg_up, counters) 47018c2ecf20Sopenharmony_ci * 47028c2ecf20Sopenharmony_ci * Generate an ABORT chunk and terminate the association. 47038c2ecf20Sopenharmony_ci */ 47048c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunklen( 47058c2ecf20Sopenharmony_ci struct net *net, 47068c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 47078c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 47088c2ecf20Sopenharmony_ci const union sctp_subtype type, 47098c2ecf20Sopenharmony_ci void *arg, 47108c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 47118c2ecf20Sopenharmony_ci{ 47128c2ecf20Sopenharmony_ci static const char err_str[] = "The following chunk had invalid length:"; 47138c2ecf20Sopenharmony_ci 47148c2ecf20Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, 47158c2ecf20Sopenharmony_ci sizeof(err_str)); 47168c2ecf20Sopenharmony_ci} 47178c2ecf20Sopenharmony_ci 47188c2ecf20Sopenharmony_ci/* 47198c2ecf20Sopenharmony_ci * Handle a protocol violation when the parameter length is invalid. 47208c2ecf20Sopenharmony_ci * If the length is smaller than the minimum length of a given parameter, 47218c2ecf20Sopenharmony_ci * or accumulated length in multi parameters exceeds the end of the chunk, 47228c2ecf20Sopenharmony_ci * the length is considered as invalid. 47238c2ecf20Sopenharmony_ci */ 47248c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_paramlen( 47258c2ecf20Sopenharmony_ci struct net *net, 47268c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 47278c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 47288c2ecf20Sopenharmony_ci const union sctp_subtype type, 47298c2ecf20Sopenharmony_ci void *arg, void *ext, 47308c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 47318c2ecf20Sopenharmony_ci{ 47328c2ecf20Sopenharmony_ci struct sctp_paramhdr *param = ext; 47338c2ecf20Sopenharmony_ci struct sctp_chunk *abort = NULL; 47348c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 47358c2ecf20Sopenharmony_ci 47368c2ecf20Sopenharmony_ci if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 47378c2ecf20Sopenharmony_ci goto discard; 47388c2ecf20Sopenharmony_ci 47398c2ecf20Sopenharmony_ci /* Make the abort chunk. */ 47408c2ecf20Sopenharmony_ci abort = sctp_make_violation_paramlen(asoc, chunk, param); 47418c2ecf20Sopenharmony_ci if (!abort) 47428c2ecf20Sopenharmony_ci goto nomem; 47438c2ecf20Sopenharmony_ci 47448c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 47458c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 47468c2ecf20Sopenharmony_ci 47478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 47488c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 47498c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 47508c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); 47518c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 47528c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 47538c2ecf20Sopenharmony_ci 47548c2ecf20Sopenharmony_cidiscard: 47558c2ecf20Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands); 47568c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 47578c2ecf20Sopenharmony_cinomem: 47588c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 47598c2ecf20Sopenharmony_ci} 47608c2ecf20Sopenharmony_ci 47618c2ecf20Sopenharmony_ci/* Handle a protocol violation when the peer trying to advance the 47628c2ecf20Sopenharmony_ci * cumulative tsn ack to a point beyond the max tsn currently sent. 47638c2ecf20Sopenharmony_ci * 47648c2ecf20Sopenharmony_ci * We inform the other end by sending an ABORT with a Protocol Violation 47658c2ecf20Sopenharmony_ci * error code. 47668c2ecf20Sopenharmony_ci */ 47678c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_ctsn( 47688c2ecf20Sopenharmony_ci struct net *net, 47698c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 47708c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 47718c2ecf20Sopenharmony_ci const union sctp_subtype type, 47728c2ecf20Sopenharmony_ci void *arg, 47738c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 47748c2ecf20Sopenharmony_ci{ 47758c2ecf20Sopenharmony_ci static const char err_str[] = "The cumulative tsn ack beyond the max tsn currently sent:"; 47768c2ecf20Sopenharmony_ci 47778c2ecf20Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, 47788c2ecf20Sopenharmony_ci sizeof(err_str)); 47798c2ecf20Sopenharmony_ci} 47808c2ecf20Sopenharmony_ci 47818c2ecf20Sopenharmony_ci/* Handle protocol violation of an invalid chunk bundling. For example, 47828c2ecf20Sopenharmony_ci * when we have an association and we receive bundled INIT-ACK, or 47838c2ecf20Sopenharmony_ci * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" 47848c2ecf20Sopenharmony_ci * statement from the specs. Additionally, there might be an attacker 47858c2ecf20Sopenharmony_ci * on the path and we may not want to continue this communication. 47868c2ecf20Sopenharmony_ci */ 47878c2ecf20Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunk( 47888c2ecf20Sopenharmony_ci struct net *net, 47898c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 47908c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 47918c2ecf20Sopenharmony_ci const union sctp_subtype type, 47928c2ecf20Sopenharmony_ci void *arg, 47938c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 47948c2ecf20Sopenharmony_ci{ 47958c2ecf20Sopenharmony_ci static const char err_str[] = "The following chunk violates protocol:"; 47968c2ecf20Sopenharmony_ci 47978c2ecf20Sopenharmony_ci if (!asoc) 47988c2ecf20Sopenharmony_ci return sctp_sf_violation(net, ep, asoc, type, arg, commands); 47998c2ecf20Sopenharmony_ci 48008c2ecf20Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, 48018c2ecf20Sopenharmony_ci sizeof(err_str)); 48028c2ecf20Sopenharmony_ci} 48038c2ecf20Sopenharmony_ci/*************************************************************************** 48048c2ecf20Sopenharmony_ci * These are the state functions for handling primitive (Section 10) events. 48058c2ecf20Sopenharmony_ci ***************************************************************************/ 48068c2ecf20Sopenharmony_ci/* 48078c2ecf20Sopenharmony_ci * sctp_sf_do_prm_asoc 48088c2ecf20Sopenharmony_ci * 48098c2ecf20Sopenharmony_ci * Section: 10.1 ULP-to-SCTP 48108c2ecf20Sopenharmony_ci * B) Associate 48118c2ecf20Sopenharmony_ci * 48128c2ecf20Sopenharmony_ci * Format: ASSOCIATE(local SCTP instance name, destination transport addr, 48138c2ecf20Sopenharmony_ci * outbound stream count) 48148c2ecf20Sopenharmony_ci * -> association id [,destination transport addr list] [,outbound stream 48158c2ecf20Sopenharmony_ci * count] 48168c2ecf20Sopenharmony_ci * 48178c2ecf20Sopenharmony_ci * This primitive allows the upper layer to initiate an association to a 48188c2ecf20Sopenharmony_ci * specific peer endpoint. 48198c2ecf20Sopenharmony_ci * 48208c2ecf20Sopenharmony_ci * The peer endpoint shall be specified by one of the transport addresses 48218c2ecf20Sopenharmony_ci * which defines the endpoint (see Section 1.4). If the local SCTP 48228c2ecf20Sopenharmony_ci * instance has not been initialized, the ASSOCIATE is considered an 48238c2ecf20Sopenharmony_ci * error. 48248c2ecf20Sopenharmony_ci * [This is not relevant for the kernel implementation since we do all 48258c2ecf20Sopenharmony_ci * initialization at boot time. It we hadn't initialized we wouldn't 48268c2ecf20Sopenharmony_ci * get anywhere near this code.] 48278c2ecf20Sopenharmony_ci * 48288c2ecf20Sopenharmony_ci * An association id, which is a local handle to the SCTP association, 48298c2ecf20Sopenharmony_ci * will be returned on successful establishment of the association. If 48308c2ecf20Sopenharmony_ci * SCTP is not able to open an SCTP association with the peer endpoint, 48318c2ecf20Sopenharmony_ci * an error is returned. 48328c2ecf20Sopenharmony_ci * [In the kernel implementation, the struct sctp_association needs to 48338c2ecf20Sopenharmony_ci * be created BEFORE causing this primitive to run.] 48348c2ecf20Sopenharmony_ci * 48358c2ecf20Sopenharmony_ci * Other association parameters may be returned, including the 48368c2ecf20Sopenharmony_ci * complete destination transport addresses of the peer as well as the 48378c2ecf20Sopenharmony_ci * outbound stream count of the local endpoint. One of the transport 48388c2ecf20Sopenharmony_ci * address from the returned destination addresses will be selected by 48398c2ecf20Sopenharmony_ci * the local endpoint as default primary path for sending SCTP packets 48408c2ecf20Sopenharmony_ci * to this peer. The returned "destination transport addr list" can 48418c2ecf20Sopenharmony_ci * be used by the ULP to change the default primary path or to force 48428c2ecf20Sopenharmony_ci * sending a packet to a specific transport address. [All of this 48438c2ecf20Sopenharmony_ci * stuff happens when the INIT ACK arrives. This is a NON-BLOCKING 48448c2ecf20Sopenharmony_ci * function.] 48458c2ecf20Sopenharmony_ci * 48468c2ecf20Sopenharmony_ci * Mandatory attributes: 48478c2ecf20Sopenharmony_ci * 48488c2ecf20Sopenharmony_ci * o local SCTP instance name - obtained from the INITIALIZE operation. 48498c2ecf20Sopenharmony_ci * [This is the argument asoc.] 48508c2ecf20Sopenharmony_ci * o destination transport addr - specified as one of the transport 48518c2ecf20Sopenharmony_ci * addresses of the peer endpoint with which the association is to be 48528c2ecf20Sopenharmony_ci * established. 48538c2ecf20Sopenharmony_ci * [This is asoc->peer.active_path.] 48548c2ecf20Sopenharmony_ci * o outbound stream count - the number of outbound streams the ULP 48558c2ecf20Sopenharmony_ci * would like to open towards this peer endpoint. 48568c2ecf20Sopenharmony_ci * [BUG: This is not currently implemented.] 48578c2ecf20Sopenharmony_ci * Optional attributes: 48588c2ecf20Sopenharmony_ci * 48598c2ecf20Sopenharmony_ci * None. 48608c2ecf20Sopenharmony_ci * 48618c2ecf20Sopenharmony_ci * The return value is a disposition. 48628c2ecf20Sopenharmony_ci */ 48638c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_asoc(struct net *net, 48648c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 48658c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 48668c2ecf20Sopenharmony_ci const union sctp_subtype type, 48678c2ecf20Sopenharmony_ci void *arg, 48688c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 48698c2ecf20Sopenharmony_ci{ 48708c2ecf20Sopenharmony_ci struct sctp_association *my_asoc; 48718c2ecf20Sopenharmony_ci struct sctp_chunk *repl; 48728c2ecf20Sopenharmony_ci 48738c2ecf20Sopenharmony_ci /* The comment below says that we enter COOKIE-WAIT AFTER 48748c2ecf20Sopenharmony_ci * sending the INIT, but that doesn't actually work in our 48758c2ecf20Sopenharmony_ci * implementation... 48768c2ecf20Sopenharmony_ci */ 48778c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 48788c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_COOKIE_WAIT)); 48798c2ecf20Sopenharmony_ci 48808c2ecf20Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 48818c2ecf20Sopenharmony_ci * 48828c2ecf20Sopenharmony_ci * A) "A" first sends an INIT chunk to "Z". In the INIT, "A" 48838c2ecf20Sopenharmony_ci * must provide its Verification Tag (Tag_A) in the Initiate 48848c2ecf20Sopenharmony_ci * Tag field. Tag_A SHOULD be a random number in the range of 48858c2ecf20Sopenharmony_ci * 1 to 4294967295 (see 5.3.1 for Tag value selection). ... 48868c2ecf20Sopenharmony_ci */ 48878c2ecf20Sopenharmony_ci 48888c2ecf20Sopenharmony_ci repl = sctp_make_init(asoc, &asoc->base.bind_addr, GFP_ATOMIC, 0); 48898c2ecf20Sopenharmony_ci if (!repl) 48908c2ecf20Sopenharmony_ci goto nomem; 48918c2ecf20Sopenharmony_ci 48928c2ecf20Sopenharmony_ci /* Choose transport for INIT. */ 48938c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, 48948c2ecf20Sopenharmony_ci SCTP_CHUNK(repl)); 48958c2ecf20Sopenharmony_ci 48968c2ecf20Sopenharmony_ci /* Cast away the const modifier, as we want to just 48978c2ecf20Sopenharmony_ci * rerun it through as a sideffect. 48988c2ecf20Sopenharmony_ci */ 48998c2ecf20Sopenharmony_ci my_asoc = (struct sctp_association *)asoc; 49008c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(my_asoc)); 49018c2ecf20Sopenharmony_ci 49028c2ecf20Sopenharmony_ci /* After sending the INIT, "A" starts the T1-init timer and 49038c2ecf20Sopenharmony_ci * enters the COOKIE-WAIT state. 49048c2ecf20Sopenharmony_ci */ 49058c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 49068c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 49078c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 49088c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 49098c2ecf20Sopenharmony_ci 49108c2ecf20Sopenharmony_cinomem: 49118c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 49128c2ecf20Sopenharmony_ci} 49138c2ecf20Sopenharmony_ci 49148c2ecf20Sopenharmony_ci/* 49158c2ecf20Sopenharmony_ci * Process the SEND primitive. 49168c2ecf20Sopenharmony_ci * 49178c2ecf20Sopenharmony_ci * Section: 10.1 ULP-to-SCTP 49188c2ecf20Sopenharmony_ci * E) Send 49198c2ecf20Sopenharmony_ci * 49208c2ecf20Sopenharmony_ci * Format: SEND(association id, buffer address, byte count [,context] 49218c2ecf20Sopenharmony_ci * [,stream id] [,life time] [,destination transport address] 49228c2ecf20Sopenharmony_ci * [,unorder flag] [,no-bundle flag] [,payload protocol-id] ) 49238c2ecf20Sopenharmony_ci * -> result 49248c2ecf20Sopenharmony_ci * 49258c2ecf20Sopenharmony_ci * This is the main method to send user data via SCTP. 49268c2ecf20Sopenharmony_ci * 49278c2ecf20Sopenharmony_ci * Mandatory attributes: 49288c2ecf20Sopenharmony_ci * 49298c2ecf20Sopenharmony_ci * o association id - local handle to the SCTP association 49308c2ecf20Sopenharmony_ci * 49318c2ecf20Sopenharmony_ci * o buffer address - the location where the user message to be 49328c2ecf20Sopenharmony_ci * transmitted is stored; 49338c2ecf20Sopenharmony_ci * 49348c2ecf20Sopenharmony_ci * o byte count - The size of the user data in number of bytes; 49358c2ecf20Sopenharmony_ci * 49368c2ecf20Sopenharmony_ci * Optional attributes: 49378c2ecf20Sopenharmony_ci * 49388c2ecf20Sopenharmony_ci * o context - an optional 32 bit integer that will be carried in the 49398c2ecf20Sopenharmony_ci * sending failure notification to the ULP if the transportation of 49408c2ecf20Sopenharmony_ci * this User Message fails. 49418c2ecf20Sopenharmony_ci * 49428c2ecf20Sopenharmony_ci * o stream id - to indicate which stream to send the data on. If not 49438c2ecf20Sopenharmony_ci * specified, stream 0 will be used. 49448c2ecf20Sopenharmony_ci * 49458c2ecf20Sopenharmony_ci * o life time - specifies the life time of the user data. The user data 49468c2ecf20Sopenharmony_ci * will not be sent by SCTP after the life time expires. This 49478c2ecf20Sopenharmony_ci * parameter can be used to avoid efforts to transmit stale 49488c2ecf20Sopenharmony_ci * user messages. SCTP notifies the ULP if the data cannot be 49498c2ecf20Sopenharmony_ci * initiated to transport (i.e. sent to the destination via SCTP's 49508c2ecf20Sopenharmony_ci * send primitive) within the life time variable. However, the 49518c2ecf20Sopenharmony_ci * user data will be transmitted if SCTP has attempted to transmit a 49528c2ecf20Sopenharmony_ci * chunk before the life time expired. 49538c2ecf20Sopenharmony_ci * 49548c2ecf20Sopenharmony_ci * o destination transport address - specified as one of the destination 49558c2ecf20Sopenharmony_ci * transport addresses of the peer endpoint to which this packet 49568c2ecf20Sopenharmony_ci * should be sent. Whenever possible, SCTP should use this destination 49578c2ecf20Sopenharmony_ci * transport address for sending the packets, instead of the current 49588c2ecf20Sopenharmony_ci * primary path. 49598c2ecf20Sopenharmony_ci * 49608c2ecf20Sopenharmony_ci * o unorder flag - this flag, if present, indicates that the user 49618c2ecf20Sopenharmony_ci * would like the data delivered in an unordered fashion to the peer 49628c2ecf20Sopenharmony_ci * (i.e., the U flag is set to 1 on all DATA chunks carrying this 49638c2ecf20Sopenharmony_ci * message). 49648c2ecf20Sopenharmony_ci * 49658c2ecf20Sopenharmony_ci * o no-bundle flag - instructs SCTP not to bundle this user data with 49668c2ecf20Sopenharmony_ci * other outbound DATA chunks. SCTP MAY still bundle even when 49678c2ecf20Sopenharmony_ci * this flag is present, when faced with network congestion. 49688c2ecf20Sopenharmony_ci * 49698c2ecf20Sopenharmony_ci * o payload protocol-id - A 32 bit unsigned integer that is to be 49708c2ecf20Sopenharmony_ci * passed to the peer indicating the type of payload protocol data 49718c2ecf20Sopenharmony_ci * being transmitted. This value is passed as opaque data by SCTP. 49728c2ecf20Sopenharmony_ci * 49738c2ecf20Sopenharmony_ci * The return value is the disposition. 49748c2ecf20Sopenharmony_ci */ 49758c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_send(struct net *net, 49768c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 49778c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 49788c2ecf20Sopenharmony_ci const union sctp_subtype type, 49798c2ecf20Sopenharmony_ci void *arg, 49808c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 49818c2ecf20Sopenharmony_ci{ 49828c2ecf20Sopenharmony_ci struct sctp_datamsg *msg = arg; 49838c2ecf20Sopenharmony_ci 49848c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_MSG, SCTP_DATAMSG(msg)); 49858c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 49868c2ecf20Sopenharmony_ci} 49878c2ecf20Sopenharmony_ci 49888c2ecf20Sopenharmony_ci/* 49898c2ecf20Sopenharmony_ci * Process the SHUTDOWN primitive. 49908c2ecf20Sopenharmony_ci * 49918c2ecf20Sopenharmony_ci * Section: 10.1: 49928c2ecf20Sopenharmony_ci * C) Shutdown 49938c2ecf20Sopenharmony_ci * 49948c2ecf20Sopenharmony_ci * Format: SHUTDOWN(association id) 49958c2ecf20Sopenharmony_ci * -> result 49968c2ecf20Sopenharmony_ci * 49978c2ecf20Sopenharmony_ci * Gracefully closes an association. Any locally queued user data 49988c2ecf20Sopenharmony_ci * will be delivered to the peer. The association will be terminated only 49998c2ecf20Sopenharmony_ci * after the peer acknowledges all the SCTP packets sent. A success code 50008c2ecf20Sopenharmony_ci * will be returned on successful termination of the association. If 50018c2ecf20Sopenharmony_ci * attempting to terminate the association results in a failure, an error 50028c2ecf20Sopenharmony_ci * code shall be returned. 50038c2ecf20Sopenharmony_ci * 50048c2ecf20Sopenharmony_ci * Mandatory attributes: 50058c2ecf20Sopenharmony_ci * 50068c2ecf20Sopenharmony_ci * o association id - local handle to the SCTP association 50078c2ecf20Sopenharmony_ci * 50088c2ecf20Sopenharmony_ci * Optional attributes: 50098c2ecf20Sopenharmony_ci * 50108c2ecf20Sopenharmony_ci * None. 50118c2ecf20Sopenharmony_ci * 50128c2ecf20Sopenharmony_ci * The return value is the disposition. 50138c2ecf20Sopenharmony_ci */ 50148c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_prm_shutdown( 50158c2ecf20Sopenharmony_ci struct net *net, 50168c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 50178c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 50188c2ecf20Sopenharmony_ci const union sctp_subtype type, 50198c2ecf20Sopenharmony_ci void *arg, 50208c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 50218c2ecf20Sopenharmony_ci{ 50228c2ecf20Sopenharmony_ci enum sctp_disposition disposition; 50238c2ecf20Sopenharmony_ci 50248c2ecf20Sopenharmony_ci /* From 9.2 Shutdown of an Association 50258c2ecf20Sopenharmony_ci * Upon receipt of the SHUTDOWN primitive from its upper 50268c2ecf20Sopenharmony_ci * layer, the endpoint enters SHUTDOWN-PENDING state and 50278c2ecf20Sopenharmony_ci * remains there until all outstanding data has been 50288c2ecf20Sopenharmony_ci * acknowledged by its peer. The endpoint accepts no new data 50298c2ecf20Sopenharmony_ci * from its upper layer, but retransmits data to the far end 50308c2ecf20Sopenharmony_ci * if necessary to fill gaps. 50318c2ecf20Sopenharmony_ci */ 50328c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 50338c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); 50348c2ecf20Sopenharmony_ci 50358c2ecf20Sopenharmony_ci disposition = SCTP_DISPOSITION_CONSUME; 50368c2ecf20Sopenharmony_ci if (sctp_outq_is_empty(&asoc->outqueue)) { 50378c2ecf20Sopenharmony_ci disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type, 50388c2ecf20Sopenharmony_ci arg, commands); 50398c2ecf20Sopenharmony_ci } 50408c2ecf20Sopenharmony_ci 50418c2ecf20Sopenharmony_ci return disposition; 50428c2ecf20Sopenharmony_ci} 50438c2ecf20Sopenharmony_ci 50448c2ecf20Sopenharmony_ci/* 50458c2ecf20Sopenharmony_ci * Process the ABORT primitive. 50468c2ecf20Sopenharmony_ci * 50478c2ecf20Sopenharmony_ci * Section: 10.1: 50488c2ecf20Sopenharmony_ci * C) Abort 50498c2ecf20Sopenharmony_ci * 50508c2ecf20Sopenharmony_ci * Format: Abort(association id [, cause code]) 50518c2ecf20Sopenharmony_ci * -> result 50528c2ecf20Sopenharmony_ci * 50538c2ecf20Sopenharmony_ci * Ungracefully closes an association. Any locally queued user data 50548c2ecf20Sopenharmony_ci * will be discarded and an ABORT chunk is sent to the peer. A success code 50558c2ecf20Sopenharmony_ci * will be returned on successful abortion of the association. If 50568c2ecf20Sopenharmony_ci * attempting to abort the association results in a failure, an error 50578c2ecf20Sopenharmony_ci * code shall be returned. 50588c2ecf20Sopenharmony_ci * 50598c2ecf20Sopenharmony_ci * Mandatory attributes: 50608c2ecf20Sopenharmony_ci * 50618c2ecf20Sopenharmony_ci * o association id - local handle to the SCTP association 50628c2ecf20Sopenharmony_ci * 50638c2ecf20Sopenharmony_ci * Optional attributes: 50648c2ecf20Sopenharmony_ci * 50658c2ecf20Sopenharmony_ci * o cause code - reason of the abort to be passed to the peer 50668c2ecf20Sopenharmony_ci * 50678c2ecf20Sopenharmony_ci * None. 50688c2ecf20Sopenharmony_ci * 50698c2ecf20Sopenharmony_ci * The return value is the disposition. 50708c2ecf20Sopenharmony_ci */ 50718c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_1_prm_abort( 50728c2ecf20Sopenharmony_ci struct net *net, 50738c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 50748c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 50758c2ecf20Sopenharmony_ci const union sctp_subtype type, 50768c2ecf20Sopenharmony_ci void *arg, 50778c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 50788c2ecf20Sopenharmony_ci{ 50798c2ecf20Sopenharmony_ci /* From 9.1 Abort of an Association 50808c2ecf20Sopenharmony_ci * Upon receipt of the ABORT primitive from its upper 50818c2ecf20Sopenharmony_ci * layer, the endpoint enters CLOSED state and 50828c2ecf20Sopenharmony_ci * discard all outstanding data has been 50838c2ecf20Sopenharmony_ci * acknowledged by its peer. The endpoint accepts no new data 50848c2ecf20Sopenharmony_ci * from its upper layer, but retransmits data to the far end 50858c2ecf20Sopenharmony_ci * if necessary to fill gaps. 50868c2ecf20Sopenharmony_ci */ 50878c2ecf20Sopenharmony_ci struct sctp_chunk *abort = arg; 50888c2ecf20Sopenharmony_ci 50898c2ecf20Sopenharmony_ci if (abort) 50908c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 50918c2ecf20Sopenharmony_ci 50928c2ecf20Sopenharmony_ci /* Even if we can't send the ABORT due to low memory delete the 50938c2ecf20Sopenharmony_ci * TCB. This is a departure from our typical NOMEM handling. 50948c2ecf20Sopenharmony_ci */ 50958c2ecf20Sopenharmony_ci 50968c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 50978c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 50988c2ecf20Sopenharmony_ci /* Delete the established association. */ 50998c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 51008c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_USER_ABORT)); 51018c2ecf20Sopenharmony_ci 51028c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 51038c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 51048c2ecf20Sopenharmony_ci 51058c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 51068c2ecf20Sopenharmony_ci} 51078c2ecf20Sopenharmony_ci 51088c2ecf20Sopenharmony_ci/* We tried an illegal operation on an association which is closed. */ 51098c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_error_closed(struct net *net, 51108c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 51118c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 51128c2ecf20Sopenharmony_ci const union sctp_subtype type, 51138c2ecf20Sopenharmony_ci void *arg, 51148c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 51158c2ecf20Sopenharmony_ci{ 51168c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_ERROR, SCTP_ERROR(-EINVAL)); 51178c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 51188c2ecf20Sopenharmony_ci} 51198c2ecf20Sopenharmony_ci 51208c2ecf20Sopenharmony_ci/* We tried an illegal operation on an association which is shutting 51218c2ecf20Sopenharmony_ci * down. 51228c2ecf20Sopenharmony_ci */ 51238c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_error_shutdown( 51248c2ecf20Sopenharmony_ci struct net *net, 51258c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 51268c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 51278c2ecf20Sopenharmony_ci const union sctp_subtype type, 51288c2ecf20Sopenharmony_ci void *arg, 51298c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 51308c2ecf20Sopenharmony_ci{ 51318c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_ERROR, 51328c2ecf20Sopenharmony_ci SCTP_ERROR(-ESHUTDOWN)); 51338c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 51348c2ecf20Sopenharmony_ci} 51358c2ecf20Sopenharmony_ci 51368c2ecf20Sopenharmony_ci/* 51378c2ecf20Sopenharmony_ci * sctp_cookie_wait_prm_shutdown 51388c2ecf20Sopenharmony_ci * 51398c2ecf20Sopenharmony_ci * Section: 4 Note: 2 51408c2ecf20Sopenharmony_ci * Verification Tag: 51418c2ecf20Sopenharmony_ci * Inputs 51428c2ecf20Sopenharmony_ci * (endpoint, asoc) 51438c2ecf20Sopenharmony_ci * 51448c2ecf20Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 51458c2ecf20Sopenharmony_ci * state table when someone issues a shutdown while in COOKIE_WAIT state. 51468c2ecf20Sopenharmony_ci * 51478c2ecf20Sopenharmony_ci * Outputs 51488c2ecf20Sopenharmony_ci * (timers) 51498c2ecf20Sopenharmony_ci */ 51508c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_prm_shutdown( 51518c2ecf20Sopenharmony_ci struct net *net, 51528c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 51538c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 51548c2ecf20Sopenharmony_ci const union sctp_subtype type, 51558c2ecf20Sopenharmony_ci void *arg, 51568c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 51578c2ecf20Sopenharmony_ci{ 51588c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 51598c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 51608c2ecf20Sopenharmony_ci 51618c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 51628c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 51638c2ecf20Sopenharmony_ci 51648c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); 51658c2ecf20Sopenharmony_ci 51668c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 51678c2ecf20Sopenharmony_ci 51688c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 51698c2ecf20Sopenharmony_ci} 51708c2ecf20Sopenharmony_ci 51718c2ecf20Sopenharmony_ci/* 51728c2ecf20Sopenharmony_ci * sctp_cookie_echoed_prm_shutdown 51738c2ecf20Sopenharmony_ci * 51748c2ecf20Sopenharmony_ci * Section: 4 Note: 2 51758c2ecf20Sopenharmony_ci * Verification Tag: 51768c2ecf20Sopenharmony_ci * Inputs 51778c2ecf20Sopenharmony_ci * (endpoint, asoc) 51788c2ecf20Sopenharmony_ci * 51798c2ecf20Sopenharmony_ci * The RFC does not explcitly address this issue, but is the route through the 51808c2ecf20Sopenharmony_ci * state table when someone issues a shutdown while in COOKIE_ECHOED state. 51818c2ecf20Sopenharmony_ci * 51828c2ecf20Sopenharmony_ci * Outputs 51838c2ecf20Sopenharmony_ci * (timers) 51848c2ecf20Sopenharmony_ci */ 51858c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_prm_shutdown( 51868c2ecf20Sopenharmony_ci struct net *net, 51878c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 51888c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 51898c2ecf20Sopenharmony_ci const union sctp_subtype type, 51908c2ecf20Sopenharmony_ci void *arg, 51918c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 51928c2ecf20Sopenharmony_ci{ 51938c2ecf20Sopenharmony_ci /* There is a single T1 timer, so we should be able to use 51948c2ecf20Sopenharmony_ci * common function with the COOKIE-WAIT state. 51958c2ecf20Sopenharmony_ci */ 51968c2ecf20Sopenharmony_ci return sctp_sf_cookie_wait_prm_shutdown(net, ep, asoc, type, arg, commands); 51978c2ecf20Sopenharmony_ci} 51988c2ecf20Sopenharmony_ci 51998c2ecf20Sopenharmony_ci/* 52008c2ecf20Sopenharmony_ci * sctp_sf_cookie_wait_prm_abort 52018c2ecf20Sopenharmony_ci * 52028c2ecf20Sopenharmony_ci * Section: 4 Note: 2 52038c2ecf20Sopenharmony_ci * Verification Tag: 52048c2ecf20Sopenharmony_ci * Inputs 52058c2ecf20Sopenharmony_ci * (endpoint, asoc) 52068c2ecf20Sopenharmony_ci * 52078c2ecf20Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 52088c2ecf20Sopenharmony_ci * state table when someone issues an abort while in COOKIE_WAIT state. 52098c2ecf20Sopenharmony_ci * 52108c2ecf20Sopenharmony_ci * Outputs 52118c2ecf20Sopenharmony_ci * (timers) 52128c2ecf20Sopenharmony_ci */ 52138c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_prm_abort( 52148c2ecf20Sopenharmony_ci struct net *net, 52158c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 52168c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 52178c2ecf20Sopenharmony_ci const union sctp_subtype type, 52188c2ecf20Sopenharmony_ci void *arg, 52198c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 52208c2ecf20Sopenharmony_ci{ 52218c2ecf20Sopenharmony_ci struct sctp_chunk *abort = arg; 52228c2ecf20Sopenharmony_ci 52238c2ecf20Sopenharmony_ci /* Stop T1-init timer */ 52248c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 52258c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 52268c2ecf20Sopenharmony_ci 52278c2ecf20Sopenharmony_ci if (abort) 52288c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 52298c2ecf20Sopenharmony_ci 52308c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 52318c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 52328c2ecf20Sopenharmony_ci 52338c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 52348c2ecf20Sopenharmony_ci 52358c2ecf20Sopenharmony_ci /* Even if we can't send the ABORT due to low memory delete the 52368c2ecf20Sopenharmony_ci * TCB. This is a departure from our typical NOMEM handling. 52378c2ecf20Sopenharmony_ci */ 52388c2ecf20Sopenharmony_ci 52398c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 52408c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNREFUSED)); 52418c2ecf20Sopenharmony_ci /* Delete the established association. */ 52428c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 52438c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_USER_ABORT)); 52448c2ecf20Sopenharmony_ci 52458c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 52468c2ecf20Sopenharmony_ci} 52478c2ecf20Sopenharmony_ci 52488c2ecf20Sopenharmony_ci/* 52498c2ecf20Sopenharmony_ci * sctp_sf_cookie_echoed_prm_abort 52508c2ecf20Sopenharmony_ci * 52518c2ecf20Sopenharmony_ci * Section: 4 Note: 3 52528c2ecf20Sopenharmony_ci * Verification Tag: 52538c2ecf20Sopenharmony_ci * Inputs 52548c2ecf20Sopenharmony_ci * (endpoint, asoc) 52558c2ecf20Sopenharmony_ci * 52568c2ecf20Sopenharmony_ci * The RFC does not explcitly address this issue, but is the route through the 52578c2ecf20Sopenharmony_ci * state table when someone issues an abort while in COOKIE_ECHOED state. 52588c2ecf20Sopenharmony_ci * 52598c2ecf20Sopenharmony_ci * Outputs 52608c2ecf20Sopenharmony_ci * (timers) 52618c2ecf20Sopenharmony_ci */ 52628c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_prm_abort( 52638c2ecf20Sopenharmony_ci struct net *net, 52648c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 52658c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 52668c2ecf20Sopenharmony_ci const union sctp_subtype type, 52678c2ecf20Sopenharmony_ci void *arg, 52688c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 52698c2ecf20Sopenharmony_ci{ 52708c2ecf20Sopenharmony_ci /* There is a single T1 timer, so we should be able to use 52718c2ecf20Sopenharmony_ci * common function with the COOKIE-WAIT state. 52728c2ecf20Sopenharmony_ci */ 52738c2ecf20Sopenharmony_ci return sctp_sf_cookie_wait_prm_abort(net, ep, asoc, type, arg, commands); 52748c2ecf20Sopenharmony_ci} 52758c2ecf20Sopenharmony_ci 52768c2ecf20Sopenharmony_ci/* 52778c2ecf20Sopenharmony_ci * sctp_sf_shutdown_pending_prm_abort 52788c2ecf20Sopenharmony_ci * 52798c2ecf20Sopenharmony_ci * Inputs 52808c2ecf20Sopenharmony_ci * (endpoint, asoc) 52818c2ecf20Sopenharmony_ci * 52828c2ecf20Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 52838c2ecf20Sopenharmony_ci * state table when someone issues an abort while in SHUTDOWN-PENDING state. 52848c2ecf20Sopenharmony_ci * 52858c2ecf20Sopenharmony_ci * Outputs 52868c2ecf20Sopenharmony_ci * (timers) 52878c2ecf20Sopenharmony_ci */ 52888c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_pending_prm_abort( 52898c2ecf20Sopenharmony_ci struct net *net, 52908c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 52918c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 52928c2ecf20Sopenharmony_ci const union sctp_subtype type, 52938c2ecf20Sopenharmony_ci void *arg, 52948c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 52958c2ecf20Sopenharmony_ci{ 52968c2ecf20Sopenharmony_ci /* Stop the T5-shutdown guard timer. */ 52978c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 52988c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 52998c2ecf20Sopenharmony_ci 53008c2ecf20Sopenharmony_ci return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands); 53018c2ecf20Sopenharmony_ci} 53028c2ecf20Sopenharmony_ci 53038c2ecf20Sopenharmony_ci/* 53048c2ecf20Sopenharmony_ci * sctp_sf_shutdown_sent_prm_abort 53058c2ecf20Sopenharmony_ci * 53068c2ecf20Sopenharmony_ci * Inputs 53078c2ecf20Sopenharmony_ci * (endpoint, asoc) 53088c2ecf20Sopenharmony_ci * 53098c2ecf20Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 53108c2ecf20Sopenharmony_ci * state table when someone issues an abort while in SHUTDOWN-SENT state. 53118c2ecf20Sopenharmony_ci * 53128c2ecf20Sopenharmony_ci * Outputs 53138c2ecf20Sopenharmony_ci * (timers) 53148c2ecf20Sopenharmony_ci */ 53158c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_sent_prm_abort( 53168c2ecf20Sopenharmony_ci struct net *net, 53178c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 53188c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 53198c2ecf20Sopenharmony_ci const union sctp_subtype type, 53208c2ecf20Sopenharmony_ci void *arg, 53218c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 53228c2ecf20Sopenharmony_ci{ 53238c2ecf20Sopenharmony_ci /* Stop the T2-shutdown timer. */ 53248c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 53258c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 53268c2ecf20Sopenharmony_ci 53278c2ecf20Sopenharmony_ci /* Stop the T5-shutdown guard timer. */ 53288c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 53298c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 53308c2ecf20Sopenharmony_ci 53318c2ecf20Sopenharmony_ci return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands); 53328c2ecf20Sopenharmony_ci} 53338c2ecf20Sopenharmony_ci 53348c2ecf20Sopenharmony_ci/* 53358c2ecf20Sopenharmony_ci * sctp_sf_cookie_echoed_prm_abort 53368c2ecf20Sopenharmony_ci * 53378c2ecf20Sopenharmony_ci * Inputs 53388c2ecf20Sopenharmony_ci * (endpoint, asoc) 53398c2ecf20Sopenharmony_ci * 53408c2ecf20Sopenharmony_ci * The RFC does not explcitly address this issue, but is the route through the 53418c2ecf20Sopenharmony_ci * state table when someone issues an abort while in COOKIE_ECHOED state. 53428c2ecf20Sopenharmony_ci * 53438c2ecf20Sopenharmony_ci * Outputs 53448c2ecf20Sopenharmony_ci * (timers) 53458c2ecf20Sopenharmony_ci */ 53468c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_ack_sent_prm_abort( 53478c2ecf20Sopenharmony_ci struct net *net, 53488c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 53498c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 53508c2ecf20Sopenharmony_ci const union sctp_subtype type, 53518c2ecf20Sopenharmony_ci void *arg, 53528c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 53538c2ecf20Sopenharmony_ci{ 53548c2ecf20Sopenharmony_ci /* The same T2 timer, so we should be able to use 53558c2ecf20Sopenharmony_ci * common function with the SHUTDOWN-SENT state. 53568c2ecf20Sopenharmony_ci */ 53578c2ecf20Sopenharmony_ci return sctp_sf_shutdown_sent_prm_abort(net, ep, asoc, type, arg, commands); 53588c2ecf20Sopenharmony_ci} 53598c2ecf20Sopenharmony_ci 53608c2ecf20Sopenharmony_ci/* 53618c2ecf20Sopenharmony_ci * Process the REQUESTHEARTBEAT primitive 53628c2ecf20Sopenharmony_ci * 53638c2ecf20Sopenharmony_ci * 10.1 ULP-to-SCTP 53648c2ecf20Sopenharmony_ci * J) Request Heartbeat 53658c2ecf20Sopenharmony_ci * 53668c2ecf20Sopenharmony_ci * Format: REQUESTHEARTBEAT(association id, destination transport address) 53678c2ecf20Sopenharmony_ci * 53688c2ecf20Sopenharmony_ci * -> result 53698c2ecf20Sopenharmony_ci * 53708c2ecf20Sopenharmony_ci * Instructs the local endpoint to perform a HeartBeat on the specified 53718c2ecf20Sopenharmony_ci * destination transport address of the given association. The returned 53728c2ecf20Sopenharmony_ci * result should indicate whether the transmission of the HEARTBEAT 53738c2ecf20Sopenharmony_ci * chunk to the destination address is successful. 53748c2ecf20Sopenharmony_ci * 53758c2ecf20Sopenharmony_ci * Mandatory attributes: 53768c2ecf20Sopenharmony_ci * 53778c2ecf20Sopenharmony_ci * o association id - local handle to the SCTP association 53788c2ecf20Sopenharmony_ci * 53798c2ecf20Sopenharmony_ci * o destination transport address - the transport address of the 53808c2ecf20Sopenharmony_ci * association on which a heartbeat should be issued. 53818c2ecf20Sopenharmony_ci */ 53828c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_requestheartbeat( 53838c2ecf20Sopenharmony_ci struct net *net, 53848c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 53858c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 53868c2ecf20Sopenharmony_ci const union sctp_subtype type, 53878c2ecf20Sopenharmony_ci void *arg, 53888c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 53898c2ecf20Sopenharmony_ci{ 53908c2ecf20Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == sctp_sf_heartbeat(ep, asoc, type, 53918c2ecf20Sopenharmony_ci (struct sctp_transport *)arg, commands)) 53928c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 53938c2ecf20Sopenharmony_ci 53948c2ecf20Sopenharmony_ci /* 53958c2ecf20Sopenharmony_ci * RFC 2960 (bis), section 8.3 53968c2ecf20Sopenharmony_ci * 53978c2ecf20Sopenharmony_ci * D) Request an on-demand HEARTBEAT on a specific destination 53988c2ecf20Sopenharmony_ci * transport address of a given association. 53998c2ecf20Sopenharmony_ci * 54008c2ecf20Sopenharmony_ci * The endpoint should increment the respective error counter of 54018c2ecf20Sopenharmony_ci * the destination transport address each time a HEARTBEAT is sent 54028c2ecf20Sopenharmony_ci * to that address and not acknowledged within one RTO. 54038c2ecf20Sopenharmony_ci * 54048c2ecf20Sopenharmony_ci */ 54058c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, 54068c2ecf20Sopenharmony_ci SCTP_TRANSPORT(arg)); 54078c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 54088c2ecf20Sopenharmony_ci} 54098c2ecf20Sopenharmony_ci 54108c2ecf20Sopenharmony_ci/* 54118c2ecf20Sopenharmony_ci * ADDIP Section 4.1 ASCONF Chunk Procedures 54128c2ecf20Sopenharmony_ci * When an endpoint has an ASCONF signaled change to be sent to the 54138c2ecf20Sopenharmony_ci * remote endpoint it should do A1 to A9 54148c2ecf20Sopenharmony_ci */ 54158c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_asconf(struct net *net, 54168c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 54178c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 54188c2ecf20Sopenharmony_ci const union sctp_subtype type, 54198c2ecf20Sopenharmony_ci void *arg, 54208c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 54218c2ecf20Sopenharmony_ci{ 54228c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 54238c2ecf20Sopenharmony_ci 54248c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); 54258c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 54268c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 54278c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); 54288c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 54298c2ecf20Sopenharmony_ci} 54308c2ecf20Sopenharmony_ci 54318c2ecf20Sopenharmony_ci/* RE-CONFIG Section 5.1 RECONF Chunk Procedures */ 54328c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_reconf(struct net *net, 54338c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 54348c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 54358c2ecf20Sopenharmony_ci const union sctp_subtype type, 54368c2ecf20Sopenharmony_ci void *arg, 54378c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 54388c2ecf20Sopenharmony_ci{ 54398c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 54408c2ecf20Sopenharmony_ci 54418c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); 54428c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 54438c2ecf20Sopenharmony_ci} 54448c2ecf20Sopenharmony_ci 54458c2ecf20Sopenharmony_ci/* 54468c2ecf20Sopenharmony_ci * Ignore the primitive event 54478c2ecf20Sopenharmony_ci * 54488c2ecf20Sopenharmony_ci * The return value is the disposition of the primitive. 54498c2ecf20Sopenharmony_ci */ 54508c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_ignore_primitive( 54518c2ecf20Sopenharmony_ci struct net *net, 54528c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 54538c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 54548c2ecf20Sopenharmony_ci const union sctp_subtype type, 54558c2ecf20Sopenharmony_ci void *arg, 54568c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 54578c2ecf20Sopenharmony_ci{ 54588c2ecf20Sopenharmony_ci pr_debug("%s: primitive type:%d is ignored\n", __func__, 54598c2ecf20Sopenharmony_ci type.primitive); 54608c2ecf20Sopenharmony_ci 54618c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 54628c2ecf20Sopenharmony_ci} 54638c2ecf20Sopenharmony_ci 54648c2ecf20Sopenharmony_ci/*************************************************************************** 54658c2ecf20Sopenharmony_ci * These are the state functions for the OTHER events. 54668c2ecf20Sopenharmony_ci ***************************************************************************/ 54678c2ecf20Sopenharmony_ci 54688c2ecf20Sopenharmony_ci/* 54698c2ecf20Sopenharmony_ci * When the SCTP stack has no more user data to send or retransmit, this 54708c2ecf20Sopenharmony_ci * notification is given to the user. Also, at the time when a user app 54718c2ecf20Sopenharmony_ci * subscribes to this event, if there is no data to be sent or 54728c2ecf20Sopenharmony_ci * retransmit, the stack will immediately send up this notification. 54738c2ecf20Sopenharmony_ci */ 54748c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_no_pending_tsn( 54758c2ecf20Sopenharmony_ci struct net *net, 54768c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 54778c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 54788c2ecf20Sopenharmony_ci const union sctp_subtype type, 54798c2ecf20Sopenharmony_ci void *arg, 54808c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 54818c2ecf20Sopenharmony_ci{ 54828c2ecf20Sopenharmony_ci struct sctp_ulpevent *event; 54838c2ecf20Sopenharmony_ci 54848c2ecf20Sopenharmony_ci event = sctp_ulpevent_make_sender_dry_event(asoc, GFP_ATOMIC); 54858c2ecf20Sopenharmony_ci if (!event) 54868c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 54878c2ecf20Sopenharmony_ci 54888c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(event)); 54898c2ecf20Sopenharmony_ci 54908c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 54918c2ecf20Sopenharmony_ci} 54928c2ecf20Sopenharmony_ci 54938c2ecf20Sopenharmony_ci/* 54948c2ecf20Sopenharmony_ci * Start the shutdown negotiation. 54958c2ecf20Sopenharmony_ci * 54968c2ecf20Sopenharmony_ci * From Section 9.2: 54978c2ecf20Sopenharmony_ci * Once all its outstanding data has been acknowledged, the endpoint 54988c2ecf20Sopenharmony_ci * shall send a SHUTDOWN chunk to its peer including in the Cumulative 54998c2ecf20Sopenharmony_ci * TSN Ack field the last sequential TSN it has received from the peer. 55008c2ecf20Sopenharmony_ci * It shall then start the T2-shutdown timer and enter the SHUTDOWN-SENT 55018c2ecf20Sopenharmony_ci * state. If the timer expires, the endpoint must re-send the SHUTDOWN 55028c2ecf20Sopenharmony_ci * with the updated last sequential TSN received from its peer. 55038c2ecf20Sopenharmony_ci * 55048c2ecf20Sopenharmony_ci * The return value is the disposition. 55058c2ecf20Sopenharmony_ci */ 55068c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_start_shutdown( 55078c2ecf20Sopenharmony_ci struct net *net, 55088c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 55098c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 55108c2ecf20Sopenharmony_ci const union sctp_subtype type, 55118c2ecf20Sopenharmony_ci void *arg, 55128c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 55138c2ecf20Sopenharmony_ci{ 55148c2ecf20Sopenharmony_ci struct sctp_chunk *reply; 55158c2ecf20Sopenharmony_ci 55168c2ecf20Sopenharmony_ci /* Once all its outstanding data has been acknowledged, the 55178c2ecf20Sopenharmony_ci * endpoint shall send a SHUTDOWN chunk to its peer including 55188c2ecf20Sopenharmony_ci * in the Cumulative TSN Ack field the last sequential TSN it 55198c2ecf20Sopenharmony_ci * has received from the peer. 55208c2ecf20Sopenharmony_ci */ 55218c2ecf20Sopenharmony_ci reply = sctp_make_shutdown(asoc, arg); 55228c2ecf20Sopenharmony_ci if (!reply) 55238c2ecf20Sopenharmony_ci goto nomem; 55248c2ecf20Sopenharmony_ci 55258c2ecf20Sopenharmony_ci /* Set the transport for the SHUTDOWN chunk and the timeout for the 55268c2ecf20Sopenharmony_ci * T2-shutdown timer. 55278c2ecf20Sopenharmony_ci */ 55288c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 55298c2ecf20Sopenharmony_ci 55308c2ecf20Sopenharmony_ci /* It shall then start the T2-shutdown timer */ 55318c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 55328c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 55338c2ecf20Sopenharmony_ci 55348c2ecf20Sopenharmony_ci /* RFC 4960 Section 9.2 55358c2ecf20Sopenharmony_ci * The sender of the SHUTDOWN MAY also start an overall guard timer 55368c2ecf20Sopenharmony_ci * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. 55378c2ecf20Sopenharmony_ci */ 55388c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 55398c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 55408c2ecf20Sopenharmony_ci 55418c2ecf20Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 55428c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 55438c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 55448c2ecf20Sopenharmony_ci 55458c2ecf20Sopenharmony_ci /* and enter the SHUTDOWN-SENT state. */ 55468c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 55478c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_SENT)); 55488c2ecf20Sopenharmony_ci 55498c2ecf20Sopenharmony_ci /* sctp-implguide 2.10 Issues with Heartbeating and failover 55508c2ecf20Sopenharmony_ci * 55518c2ecf20Sopenharmony_ci * HEARTBEAT ... is discontinued after sending either SHUTDOWN 55528c2ecf20Sopenharmony_ci * or SHUTDOWN-ACK. 55538c2ecf20Sopenharmony_ci */ 55548c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); 55558c2ecf20Sopenharmony_ci 55568c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 55578c2ecf20Sopenharmony_ci 55588c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 55598c2ecf20Sopenharmony_ci 55608c2ecf20Sopenharmony_cinomem: 55618c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 55628c2ecf20Sopenharmony_ci} 55638c2ecf20Sopenharmony_ci 55648c2ecf20Sopenharmony_ci/* 55658c2ecf20Sopenharmony_ci * Generate a SHUTDOWN ACK now that everything is SACK'd. 55668c2ecf20Sopenharmony_ci * 55678c2ecf20Sopenharmony_ci * From Section 9.2: 55688c2ecf20Sopenharmony_ci * 55698c2ecf20Sopenharmony_ci * If it has no more outstanding DATA chunks, the SHUTDOWN receiver 55708c2ecf20Sopenharmony_ci * shall send a SHUTDOWN ACK and start a T2-shutdown timer of its own, 55718c2ecf20Sopenharmony_ci * entering the SHUTDOWN-ACK-SENT state. If the timer expires, the 55728c2ecf20Sopenharmony_ci * endpoint must re-send the SHUTDOWN ACK. 55738c2ecf20Sopenharmony_ci * 55748c2ecf20Sopenharmony_ci * The return value is the disposition. 55758c2ecf20Sopenharmony_ci */ 55768c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_shutdown_ack( 55778c2ecf20Sopenharmony_ci struct net *net, 55788c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 55798c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 55808c2ecf20Sopenharmony_ci const union sctp_subtype type, 55818c2ecf20Sopenharmony_ci void *arg, 55828c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 55838c2ecf20Sopenharmony_ci{ 55848c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = arg; 55858c2ecf20Sopenharmony_ci struct sctp_chunk *reply; 55868c2ecf20Sopenharmony_ci 55878c2ecf20Sopenharmony_ci /* There are 2 ways of getting here: 55888c2ecf20Sopenharmony_ci * 1) called in response to a SHUTDOWN chunk 55898c2ecf20Sopenharmony_ci * 2) called when SCTP_EVENT_NO_PENDING_TSN event is issued. 55908c2ecf20Sopenharmony_ci * 55918c2ecf20Sopenharmony_ci * For the case (2), the arg parameter is set to NULL. We need 55928c2ecf20Sopenharmony_ci * to check that we have a chunk before accessing it's fields. 55938c2ecf20Sopenharmony_ci */ 55948c2ecf20Sopenharmony_ci if (chunk) { 55958c2ecf20Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 55968c2ecf20Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, 55978c2ecf20Sopenharmony_ci commands); 55988c2ecf20Sopenharmony_ci 55998c2ecf20Sopenharmony_ci /* Make sure that the SHUTDOWN chunk has a valid length. */ 56008c2ecf20Sopenharmony_ci if (!sctp_chunk_length_valid( 56018c2ecf20Sopenharmony_ci chunk, sizeof(struct sctp_shutdown_chunk))) 56028c2ecf20Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, 56038c2ecf20Sopenharmony_ci arg, commands); 56048c2ecf20Sopenharmony_ci } 56058c2ecf20Sopenharmony_ci 56068c2ecf20Sopenharmony_ci /* If it has no more outstanding DATA chunks, the SHUTDOWN receiver 56078c2ecf20Sopenharmony_ci * shall send a SHUTDOWN ACK ... 56088c2ecf20Sopenharmony_ci */ 56098c2ecf20Sopenharmony_ci reply = sctp_make_shutdown_ack(asoc, chunk); 56108c2ecf20Sopenharmony_ci if (!reply) 56118c2ecf20Sopenharmony_ci goto nomem; 56128c2ecf20Sopenharmony_ci 56138c2ecf20Sopenharmony_ci /* Set the transport for the SHUTDOWN ACK chunk and the timeout for 56148c2ecf20Sopenharmony_ci * the T2-shutdown timer. 56158c2ecf20Sopenharmony_ci */ 56168c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 56178c2ecf20Sopenharmony_ci 56188c2ecf20Sopenharmony_ci /* and start/restart a T2-shutdown timer of its own, */ 56198c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 56208c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 56218c2ecf20Sopenharmony_ci 56228c2ecf20Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 56238c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 56248c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 56258c2ecf20Sopenharmony_ci 56268c2ecf20Sopenharmony_ci /* Enter the SHUTDOWN-ACK-SENT state. */ 56278c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 56288c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_ACK_SENT)); 56298c2ecf20Sopenharmony_ci 56308c2ecf20Sopenharmony_ci /* sctp-implguide 2.10 Issues with Heartbeating and failover 56318c2ecf20Sopenharmony_ci * 56328c2ecf20Sopenharmony_ci * HEARTBEAT ... is discontinued after sending either SHUTDOWN 56338c2ecf20Sopenharmony_ci * or SHUTDOWN-ACK. 56348c2ecf20Sopenharmony_ci */ 56358c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); 56368c2ecf20Sopenharmony_ci 56378c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 56388c2ecf20Sopenharmony_ci 56398c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 56408c2ecf20Sopenharmony_ci 56418c2ecf20Sopenharmony_cinomem: 56428c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 56438c2ecf20Sopenharmony_ci} 56448c2ecf20Sopenharmony_ci 56458c2ecf20Sopenharmony_ci/* 56468c2ecf20Sopenharmony_ci * Ignore the event defined as other 56478c2ecf20Sopenharmony_ci * 56488c2ecf20Sopenharmony_ci * The return value is the disposition of the event. 56498c2ecf20Sopenharmony_ci */ 56508c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_ignore_other(struct net *net, 56518c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 56528c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 56538c2ecf20Sopenharmony_ci const union sctp_subtype type, 56548c2ecf20Sopenharmony_ci void *arg, 56558c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 56568c2ecf20Sopenharmony_ci{ 56578c2ecf20Sopenharmony_ci pr_debug("%s: the event other type:%d is ignored\n", 56588c2ecf20Sopenharmony_ci __func__, type.other); 56598c2ecf20Sopenharmony_ci 56608c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 56618c2ecf20Sopenharmony_ci} 56628c2ecf20Sopenharmony_ci 56638c2ecf20Sopenharmony_ci/************************************************************ 56648c2ecf20Sopenharmony_ci * These are the state functions for handling timeout events. 56658c2ecf20Sopenharmony_ci ************************************************************/ 56668c2ecf20Sopenharmony_ci 56678c2ecf20Sopenharmony_ci/* 56688c2ecf20Sopenharmony_ci * RTX Timeout 56698c2ecf20Sopenharmony_ci * 56708c2ecf20Sopenharmony_ci * Section: 6.3.3 Handle T3-rtx Expiration 56718c2ecf20Sopenharmony_ci * 56728c2ecf20Sopenharmony_ci * Whenever the retransmission timer T3-rtx expires for a destination 56738c2ecf20Sopenharmony_ci * address, do the following: 56748c2ecf20Sopenharmony_ci * [See below] 56758c2ecf20Sopenharmony_ci * 56768c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 56778c2ecf20Sopenharmony_ci */ 56788c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_6_3_3_rtx(struct net *net, 56798c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 56808c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 56818c2ecf20Sopenharmony_ci const union sctp_subtype type, 56828c2ecf20Sopenharmony_ci void *arg, 56838c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 56848c2ecf20Sopenharmony_ci{ 56858c2ecf20Sopenharmony_ci struct sctp_transport *transport = arg; 56868c2ecf20Sopenharmony_ci 56878c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS); 56888c2ecf20Sopenharmony_ci 56898c2ecf20Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 56908c2ecf20Sopenharmony_ci if (asoc->peer.zero_window_announced && 56918c2ecf20Sopenharmony_ci asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { 56928c2ecf20Sopenharmony_ci /* 56938c2ecf20Sopenharmony_ci * We are here likely because the receiver had its rwnd 56948c2ecf20Sopenharmony_ci * closed for a while and we have not been able to 56958c2ecf20Sopenharmony_ci * transmit the locally queued data within the maximum 56968c2ecf20Sopenharmony_ci * retransmission attempts limit. Start the T5 56978c2ecf20Sopenharmony_ci * shutdown guard timer to give the receiver one last 56988c2ecf20Sopenharmony_ci * chance and some additional time to recover before 56998c2ecf20Sopenharmony_ci * aborting. 57008c2ecf20Sopenharmony_ci */ 57018c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START_ONCE, 57028c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 57038c2ecf20Sopenharmony_ci } else { 57048c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 57058c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 57068c2ecf20Sopenharmony_ci /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 57078c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 57088c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 57098c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 57108c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 57118c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 57128c2ecf20Sopenharmony_ci } 57138c2ecf20Sopenharmony_ci } 57148c2ecf20Sopenharmony_ci 57158c2ecf20Sopenharmony_ci /* E1) For the destination address for which the timer 57168c2ecf20Sopenharmony_ci * expires, adjust its ssthresh with rules defined in Section 57178c2ecf20Sopenharmony_ci * 7.2.3 and set the cwnd <- MTU. 57188c2ecf20Sopenharmony_ci */ 57198c2ecf20Sopenharmony_ci 57208c2ecf20Sopenharmony_ci /* E2) For the destination address for which the timer 57218c2ecf20Sopenharmony_ci * expires, set RTO <- RTO * 2 ("back off the timer"). The 57228c2ecf20Sopenharmony_ci * maximum value discussed in rule C7 above (RTO.max) may be 57238c2ecf20Sopenharmony_ci * used to provide an upper bound to this doubling operation. 57248c2ecf20Sopenharmony_ci */ 57258c2ecf20Sopenharmony_ci 57268c2ecf20Sopenharmony_ci /* E3) Determine how many of the earliest (i.e., lowest TSN) 57278c2ecf20Sopenharmony_ci * outstanding DATA chunks for the address for which the 57288c2ecf20Sopenharmony_ci * T3-rtx has expired will fit into a single packet, subject 57298c2ecf20Sopenharmony_ci * to the MTU constraint for the path corresponding to the 57308c2ecf20Sopenharmony_ci * destination transport address to which the retransmission 57318c2ecf20Sopenharmony_ci * is being sent (this may be different from the address for 57328c2ecf20Sopenharmony_ci * which the timer expires [see Section 6.4]). Call this 57338c2ecf20Sopenharmony_ci * value K. Bundle and retransmit those K DATA chunks in a 57348c2ecf20Sopenharmony_ci * single packet to the destination endpoint. 57358c2ecf20Sopenharmony_ci * 57368c2ecf20Sopenharmony_ci * Note: Any DATA chunks that were sent to the address for 57378c2ecf20Sopenharmony_ci * which the T3-rtx timer expired but did not fit in one MTU 57388c2ecf20Sopenharmony_ci * (rule E3 above), should be marked for retransmission and 57398c2ecf20Sopenharmony_ci * sent as soon as cwnd allows (normally when a SACK arrives). 57408c2ecf20Sopenharmony_ci */ 57418c2ecf20Sopenharmony_ci 57428c2ecf20Sopenharmony_ci /* Do some failure management (Section 8.2). */ 57438c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); 57448c2ecf20Sopenharmony_ci 57458c2ecf20Sopenharmony_ci /* NB: Rules E4 and F1 are implicit in R1. */ 57468c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(transport)); 57478c2ecf20Sopenharmony_ci 57488c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 57498c2ecf20Sopenharmony_ci} 57508c2ecf20Sopenharmony_ci 57518c2ecf20Sopenharmony_ci/* 57528c2ecf20Sopenharmony_ci * Generate delayed SACK on timeout 57538c2ecf20Sopenharmony_ci * 57548c2ecf20Sopenharmony_ci * Section: 6.2 Acknowledgement on Reception of DATA Chunks 57558c2ecf20Sopenharmony_ci * 57568c2ecf20Sopenharmony_ci * The guidelines on delayed acknowledgement algorithm specified in 57578c2ecf20Sopenharmony_ci * Section 4.2 of [RFC2581] SHOULD be followed. Specifically, an 57588c2ecf20Sopenharmony_ci * acknowledgement SHOULD be generated for at least every second packet 57598c2ecf20Sopenharmony_ci * (not every second DATA chunk) received, and SHOULD be generated 57608c2ecf20Sopenharmony_ci * within 200 ms of the arrival of any unacknowledged DATA chunk. In 57618c2ecf20Sopenharmony_ci * some situations it may be beneficial for an SCTP transmitter to be 57628c2ecf20Sopenharmony_ci * more conservative than the algorithms detailed in this document 57638c2ecf20Sopenharmony_ci * allow. However, an SCTP transmitter MUST NOT be more aggressive than 57648c2ecf20Sopenharmony_ci * the following algorithms allow. 57658c2ecf20Sopenharmony_ci */ 57668c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_do_6_2_sack(struct net *net, 57678c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 57688c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 57698c2ecf20Sopenharmony_ci const union sctp_subtype type, 57708c2ecf20Sopenharmony_ci void *arg, 57718c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 57728c2ecf20Sopenharmony_ci{ 57738c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS); 57748c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 57758c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 57768c2ecf20Sopenharmony_ci} 57778c2ecf20Sopenharmony_ci 57788c2ecf20Sopenharmony_ci/* 57798c2ecf20Sopenharmony_ci * sctp_sf_t1_init_timer_expire 57808c2ecf20Sopenharmony_ci * 57818c2ecf20Sopenharmony_ci * Section: 4 Note: 2 57828c2ecf20Sopenharmony_ci * Verification Tag: 57838c2ecf20Sopenharmony_ci * Inputs 57848c2ecf20Sopenharmony_ci * (endpoint, asoc) 57858c2ecf20Sopenharmony_ci * 57868c2ecf20Sopenharmony_ci * RFC 2960 Section 4 Notes 57878c2ecf20Sopenharmony_ci * 2) If the T1-init timer expires, the endpoint MUST retransmit INIT 57888c2ecf20Sopenharmony_ci * and re-start the T1-init timer without changing state. This MUST 57898c2ecf20Sopenharmony_ci * be repeated up to 'Max.Init.Retransmits' times. After that, the 57908c2ecf20Sopenharmony_ci * endpoint MUST abort the initialization process and report the 57918c2ecf20Sopenharmony_ci * error to SCTP user. 57928c2ecf20Sopenharmony_ci * 57938c2ecf20Sopenharmony_ci * Outputs 57948c2ecf20Sopenharmony_ci * (timers, events) 57958c2ecf20Sopenharmony_ci * 57968c2ecf20Sopenharmony_ci */ 57978c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_t1_init_timer_expire( 57988c2ecf20Sopenharmony_ci struct net *net, 57998c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 58008c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 58018c2ecf20Sopenharmony_ci const union sctp_subtype type, 58028c2ecf20Sopenharmony_ci void *arg, 58038c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 58048c2ecf20Sopenharmony_ci{ 58058c2ecf20Sopenharmony_ci int attempts = asoc->init_err_counter + 1; 58068c2ecf20Sopenharmony_ci struct sctp_chunk *repl = NULL; 58078c2ecf20Sopenharmony_ci struct sctp_bind_addr *bp; 58088c2ecf20Sopenharmony_ci 58098c2ecf20Sopenharmony_ci pr_debug("%s: timer T1 expired (INIT)\n", __func__); 58108c2ecf20Sopenharmony_ci 58118c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS); 58128c2ecf20Sopenharmony_ci 58138c2ecf20Sopenharmony_ci if (attempts <= asoc->max_init_attempts) { 58148c2ecf20Sopenharmony_ci bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; 58158c2ecf20Sopenharmony_ci repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); 58168c2ecf20Sopenharmony_ci if (!repl) 58178c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 58188c2ecf20Sopenharmony_ci 58198c2ecf20Sopenharmony_ci /* Choose transport for INIT. */ 58208c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, 58218c2ecf20Sopenharmony_ci SCTP_CHUNK(repl)); 58228c2ecf20Sopenharmony_ci 58238c2ecf20Sopenharmony_ci /* Issue a sideeffect to do the needed accounting. */ 58248c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, 58258c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 58268c2ecf20Sopenharmony_ci 58278c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 58288c2ecf20Sopenharmony_ci } else { 58298c2ecf20Sopenharmony_ci pr_debug("%s: giving up on INIT, attempts:%d " 58308c2ecf20Sopenharmony_ci "max_init_attempts:%d\n", __func__, attempts, 58318c2ecf20Sopenharmony_ci asoc->max_init_attempts); 58328c2ecf20Sopenharmony_ci 58338c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 58348c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 58358c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 58368c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 58378c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 58388c2ecf20Sopenharmony_ci } 58398c2ecf20Sopenharmony_ci 58408c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 58418c2ecf20Sopenharmony_ci} 58428c2ecf20Sopenharmony_ci 58438c2ecf20Sopenharmony_ci/* 58448c2ecf20Sopenharmony_ci * sctp_sf_t1_cookie_timer_expire 58458c2ecf20Sopenharmony_ci * 58468c2ecf20Sopenharmony_ci * Section: 4 Note: 2 58478c2ecf20Sopenharmony_ci * Verification Tag: 58488c2ecf20Sopenharmony_ci * Inputs 58498c2ecf20Sopenharmony_ci * (endpoint, asoc) 58508c2ecf20Sopenharmony_ci * 58518c2ecf20Sopenharmony_ci * RFC 2960 Section 4 Notes 58528c2ecf20Sopenharmony_ci * 3) If the T1-cookie timer expires, the endpoint MUST retransmit 58538c2ecf20Sopenharmony_ci * COOKIE ECHO and re-start the T1-cookie timer without changing 58548c2ecf20Sopenharmony_ci * state. This MUST be repeated up to 'Max.Init.Retransmits' times. 58558c2ecf20Sopenharmony_ci * After that, the endpoint MUST abort the initialization process and 58568c2ecf20Sopenharmony_ci * report the error to SCTP user. 58578c2ecf20Sopenharmony_ci * 58588c2ecf20Sopenharmony_ci * Outputs 58598c2ecf20Sopenharmony_ci * (timers, events) 58608c2ecf20Sopenharmony_ci * 58618c2ecf20Sopenharmony_ci */ 58628c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_t1_cookie_timer_expire( 58638c2ecf20Sopenharmony_ci struct net *net, 58648c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 58658c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 58668c2ecf20Sopenharmony_ci const union sctp_subtype type, 58678c2ecf20Sopenharmony_ci void *arg, 58688c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 58698c2ecf20Sopenharmony_ci{ 58708c2ecf20Sopenharmony_ci int attempts = asoc->init_err_counter + 1; 58718c2ecf20Sopenharmony_ci struct sctp_chunk *repl = NULL; 58728c2ecf20Sopenharmony_ci 58738c2ecf20Sopenharmony_ci pr_debug("%s: timer T1 expired (COOKIE-ECHO)\n", __func__); 58748c2ecf20Sopenharmony_ci 58758c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS); 58768c2ecf20Sopenharmony_ci 58778c2ecf20Sopenharmony_ci if (attempts <= asoc->max_init_attempts) { 58788c2ecf20Sopenharmony_ci repl = sctp_make_cookie_echo(asoc, NULL); 58798c2ecf20Sopenharmony_ci if (!repl) 58808c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 58818c2ecf20Sopenharmony_ci 58828c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, 58838c2ecf20Sopenharmony_ci SCTP_CHUNK(repl)); 58848c2ecf20Sopenharmony_ci /* Issue a sideeffect to do the needed accounting. */ 58858c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, 58868c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 58878c2ecf20Sopenharmony_ci 58888c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 58898c2ecf20Sopenharmony_ci } else { 58908c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 58918c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 58928c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 58938c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 58948c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 58958c2ecf20Sopenharmony_ci } 58968c2ecf20Sopenharmony_ci 58978c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 58988c2ecf20Sopenharmony_ci} 58998c2ecf20Sopenharmony_ci 59008c2ecf20Sopenharmony_ci/* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN 59018c2ecf20Sopenharmony_ci * with the updated last sequential TSN received from its peer. 59028c2ecf20Sopenharmony_ci * 59038c2ecf20Sopenharmony_ci * An endpoint should limit the number of retransmissions of the 59048c2ecf20Sopenharmony_ci * SHUTDOWN chunk to the protocol parameter 'Association.Max.Retrans'. 59058c2ecf20Sopenharmony_ci * If this threshold is exceeded the endpoint should destroy the TCB and 59068c2ecf20Sopenharmony_ci * MUST report the peer endpoint unreachable to the upper layer (and 59078c2ecf20Sopenharmony_ci * thus the association enters the CLOSED state). The reception of any 59088c2ecf20Sopenharmony_ci * packet from its peer (i.e. as the peer sends all of its queued DATA 59098c2ecf20Sopenharmony_ci * chunks) should clear the endpoint's retransmission count and restart 59108c2ecf20Sopenharmony_ci * the T2-Shutdown timer, giving its peer ample opportunity to transmit 59118c2ecf20Sopenharmony_ci * all of its queued DATA chunks that have not yet been sent. 59128c2ecf20Sopenharmony_ci */ 59138c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_t2_timer_expire( 59148c2ecf20Sopenharmony_ci struct net *net, 59158c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 59168c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 59178c2ecf20Sopenharmony_ci const union sctp_subtype type, 59188c2ecf20Sopenharmony_ci void *arg, 59198c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 59208c2ecf20Sopenharmony_ci{ 59218c2ecf20Sopenharmony_ci struct sctp_chunk *reply = NULL; 59228c2ecf20Sopenharmony_ci 59238c2ecf20Sopenharmony_ci pr_debug("%s: timer T2 expired\n", __func__); 59248c2ecf20Sopenharmony_ci 59258c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS); 59268c2ecf20Sopenharmony_ci 59278c2ecf20Sopenharmony_ci ((struct sctp_association *)asoc)->shutdown_retries++; 59288c2ecf20Sopenharmony_ci 59298c2ecf20Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 59308c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 59318c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 59328c2ecf20Sopenharmony_ci /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 59338c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 59348c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 59358c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 59368c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 59378c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 59388c2ecf20Sopenharmony_ci } 59398c2ecf20Sopenharmony_ci 59408c2ecf20Sopenharmony_ci switch (asoc->state) { 59418c2ecf20Sopenharmony_ci case SCTP_STATE_SHUTDOWN_SENT: 59428c2ecf20Sopenharmony_ci reply = sctp_make_shutdown(asoc, NULL); 59438c2ecf20Sopenharmony_ci break; 59448c2ecf20Sopenharmony_ci 59458c2ecf20Sopenharmony_ci case SCTP_STATE_SHUTDOWN_ACK_SENT: 59468c2ecf20Sopenharmony_ci reply = sctp_make_shutdown_ack(asoc, NULL); 59478c2ecf20Sopenharmony_ci break; 59488c2ecf20Sopenharmony_ci 59498c2ecf20Sopenharmony_ci default: 59508c2ecf20Sopenharmony_ci BUG(); 59518c2ecf20Sopenharmony_ci break; 59528c2ecf20Sopenharmony_ci } 59538c2ecf20Sopenharmony_ci 59548c2ecf20Sopenharmony_ci if (!reply) 59558c2ecf20Sopenharmony_ci goto nomem; 59568c2ecf20Sopenharmony_ci 59578c2ecf20Sopenharmony_ci /* Do some failure management (Section 8.2). 59588c2ecf20Sopenharmony_ci * If we remove the transport an SHUTDOWN was last sent to, don't 59598c2ecf20Sopenharmony_ci * do failure management. 59608c2ecf20Sopenharmony_ci */ 59618c2ecf20Sopenharmony_ci if (asoc->shutdown_last_sent_to) 59628c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, 59638c2ecf20Sopenharmony_ci SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); 59648c2ecf20Sopenharmony_ci 59658c2ecf20Sopenharmony_ci /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for 59668c2ecf20Sopenharmony_ci * the T2-shutdown timer. 59678c2ecf20Sopenharmony_ci */ 59688c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 59698c2ecf20Sopenharmony_ci 59708c2ecf20Sopenharmony_ci /* Restart the T2-shutdown timer. */ 59718c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 59728c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 59738c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 59748c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 59758c2ecf20Sopenharmony_ci 59768c2ecf20Sopenharmony_cinomem: 59778c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 59788c2ecf20Sopenharmony_ci} 59798c2ecf20Sopenharmony_ci 59808c2ecf20Sopenharmony_ci/* 59818c2ecf20Sopenharmony_ci * ADDIP Section 4.1 ASCONF CHunk Procedures 59828c2ecf20Sopenharmony_ci * If the T4 RTO timer expires the endpoint should do B1 to B5 59838c2ecf20Sopenharmony_ci */ 59848c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_t4_timer_expire( 59858c2ecf20Sopenharmony_ci struct net *net, 59868c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 59878c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 59888c2ecf20Sopenharmony_ci const union sctp_subtype type, 59898c2ecf20Sopenharmony_ci void *arg, 59908c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 59918c2ecf20Sopenharmony_ci{ 59928c2ecf20Sopenharmony_ci struct sctp_chunk *chunk = asoc->addip_last_asconf; 59938c2ecf20Sopenharmony_ci struct sctp_transport *transport = chunk->transport; 59948c2ecf20Sopenharmony_ci 59958c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS); 59968c2ecf20Sopenharmony_ci 59978c2ecf20Sopenharmony_ci /* ADDIP 4.1 B1) Increment the error counters and perform path failure 59988c2ecf20Sopenharmony_ci * detection on the appropriate destination address as defined in 59998c2ecf20Sopenharmony_ci * RFC2960 [5] section 8.1 and 8.2. 60008c2ecf20Sopenharmony_ci */ 60018c2ecf20Sopenharmony_ci if (transport) 60028c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, 60038c2ecf20Sopenharmony_ci SCTP_TRANSPORT(transport)); 60048c2ecf20Sopenharmony_ci 60058c2ecf20Sopenharmony_ci /* Reconfig T4 timer and transport. */ 60068c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); 60078c2ecf20Sopenharmony_ci 60088c2ecf20Sopenharmony_ci /* ADDIP 4.1 B2) Increment the association error counters and perform 60098c2ecf20Sopenharmony_ci * endpoint failure detection on the association as defined in 60108c2ecf20Sopenharmony_ci * RFC2960 [5] section 8.1 and 8.2. 60118c2ecf20Sopenharmony_ci * association error counter is incremented in SCTP_CMD_STRIKE. 60128c2ecf20Sopenharmony_ci */ 60138c2ecf20Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 60148c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 60158c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 60168c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 60178c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 60188c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 60198c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 60208c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 60218c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 60228c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 60238c2ecf20Sopenharmony_ci } 60248c2ecf20Sopenharmony_ci 60258c2ecf20Sopenharmony_ci /* ADDIP 4.1 B3) Back-off the destination address RTO value to which 60268c2ecf20Sopenharmony_ci * the ASCONF chunk was sent by doubling the RTO timer value. 60278c2ecf20Sopenharmony_ci * This is done in SCTP_CMD_STRIKE. 60288c2ecf20Sopenharmony_ci */ 60298c2ecf20Sopenharmony_ci 60308c2ecf20Sopenharmony_ci /* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible 60318c2ecf20Sopenharmony_ci * choose an alternate destination address (please refer to RFC2960 60328c2ecf20Sopenharmony_ci * [5] section 6.4.1). An endpoint MUST NOT add new parameters to this 60338c2ecf20Sopenharmony_ci * chunk, it MUST be the same (including its serial number) as the last 60348c2ecf20Sopenharmony_ci * ASCONF sent. 60358c2ecf20Sopenharmony_ci */ 60368c2ecf20Sopenharmony_ci sctp_chunk_hold(asoc->addip_last_asconf); 60378c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 60388c2ecf20Sopenharmony_ci SCTP_CHUNK(asoc->addip_last_asconf)); 60398c2ecf20Sopenharmony_ci 60408c2ecf20Sopenharmony_ci /* ADDIP 4.1 B5) Restart the T-4 RTO timer. Note that if a different 60418c2ecf20Sopenharmony_ci * destination is selected, then the RTO used will be that of the new 60428c2ecf20Sopenharmony_ci * destination address. 60438c2ecf20Sopenharmony_ci */ 60448c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 60458c2ecf20Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 60468c2ecf20Sopenharmony_ci 60478c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 60488c2ecf20Sopenharmony_ci} 60498c2ecf20Sopenharmony_ci 60508c2ecf20Sopenharmony_ci/* sctpimpguide-05 Section 2.12.2 60518c2ecf20Sopenharmony_ci * The sender of the SHUTDOWN MAY also start an overall guard timer 60528c2ecf20Sopenharmony_ci * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. 60538c2ecf20Sopenharmony_ci * At the expiration of this timer the sender SHOULD abort the association 60548c2ecf20Sopenharmony_ci * by sending an ABORT chunk. 60558c2ecf20Sopenharmony_ci */ 60568c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_t5_timer_expire( 60578c2ecf20Sopenharmony_ci struct net *net, 60588c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 60598c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 60608c2ecf20Sopenharmony_ci const union sctp_subtype type, 60618c2ecf20Sopenharmony_ci void *arg, 60628c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 60638c2ecf20Sopenharmony_ci{ 60648c2ecf20Sopenharmony_ci struct sctp_chunk *reply = NULL; 60658c2ecf20Sopenharmony_ci 60668c2ecf20Sopenharmony_ci pr_debug("%s: timer T5 expired\n", __func__); 60678c2ecf20Sopenharmony_ci 60688c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); 60698c2ecf20Sopenharmony_ci 60708c2ecf20Sopenharmony_ci reply = sctp_make_abort(asoc, NULL, 0); 60718c2ecf20Sopenharmony_ci if (!reply) 60728c2ecf20Sopenharmony_ci goto nomem; 60738c2ecf20Sopenharmony_ci 60748c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 60758c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 60768c2ecf20Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 60778c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 60788c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 60798c2ecf20Sopenharmony_ci 60808c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 60818c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 60828c2ecf20Sopenharmony_ci 60838c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 60848c2ecf20Sopenharmony_cinomem: 60858c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 60868c2ecf20Sopenharmony_ci} 60878c2ecf20Sopenharmony_ci 60888c2ecf20Sopenharmony_ci/* Handle expiration of AUTOCLOSE timer. When the autoclose timer expires, 60898c2ecf20Sopenharmony_ci * the association is automatically closed by starting the shutdown process. 60908c2ecf20Sopenharmony_ci * The work that needs to be done is same as when SHUTDOWN is initiated by 60918c2ecf20Sopenharmony_ci * the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown(). 60928c2ecf20Sopenharmony_ci */ 60938c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_autoclose_timer_expire( 60948c2ecf20Sopenharmony_ci struct net *net, 60958c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 60968c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 60978c2ecf20Sopenharmony_ci const union sctp_subtype type, 60988c2ecf20Sopenharmony_ci void *arg, 60998c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 61008c2ecf20Sopenharmony_ci{ 61018c2ecf20Sopenharmony_ci enum sctp_disposition disposition; 61028c2ecf20Sopenharmony_ci 61038c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS); 61048c2ecf20Sopenharmony_ci 61058c2ecf20Sopenharmony_ci /* From 9.2 Shutdown of an Association 61068c2ecf20Sopenharmony_ci * Upon receipt of the SHUTDOWN primitive from its upper 61078c2ecf20Sopenharmony_ci * layer, the endpoint enters SHUTDOWN-PENDING state and 61088c2ecf20Sopenharmony_ci * remains there until all outstanding data has been 61098c2ecf20Sopenharmony_ci * acknowledged by its peer. The endpoint accepts no new data 61108c2ecf20Sopenharmony_ci * from its upper layer, but retransmits data to the far end 61118c2ecf20Sopenharmony_ci * if necessary to fill gaps. 61128c2ecf20Sopenharmony_ci */ 61138c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 61148c2ecf20Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); 61158c2ecf20Sopenharmony_ci 61168c2ecf20Sopenharmony_ci disposition = SCTP_DISPOSITION_CONSUME; 61178c2ecf20Sopenharmony_ci if (sctp_outq_is_empty(&asoc->outqueue)) { 61188c2ecf20Sopenharmony_ci disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type, 61198c2ecf20Sopenharmony_ci NULL, commands); 61208c2ecf20Sopenharmony_ci } 61218c2ecf20Sopenharmony_ci 61228c2ecf20Sopenharmony_ci return disposition; 61238c2ecf20Sopenharmony_ci} 61248c2ecf20Sopenharmony_ci 61258c2ecf20Sopenharmony_ci/***************************************************************************** 61268c2ecf20Sopenharmony_ci * These are sa state functions which could apply to all types of events. 61278c2ecf20Sopenharmony_ci ****************************************************************************/ 61288c2ecf20Sopenharmony_ci 61298c2ecf20Sopenharmony_ci/* 61308c2ecf20Sopenharmony_ci * This table entry is not implemented. 61318c2ecf20Sopenharmony_ci * 61328c2ecf20Sopenharmony_ci * Inputs 61338c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 61348c2ecf20Sopenharmony_ci * 61358c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 61368c2ecf20Sopenharmony_ci */ 61378c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_not_impl(struct net *net, 61388c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 61398c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 61408c2ecf20Sopenharmony_ci const union sctp_subtype type, 61418c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 61428c2ecf20Sopenharmony_ci{ 61438c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_NOT_IMPL; 61448c2ecf20Sopenharmony_ci} 61458c2ecf20Sopenharmony_ci 61468c2ecf20Sopenharmony_ci/* 61478c2ecf20Sopenharmony_ci * This table entry represents a bug. 61488c2ecf20Sopenharmony_ci * 61498c2ecf20Sopenharmony_ci * Inputs 61508c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 61518c2ecf20Sopenharmony_ci * 61528c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 61538c2ecf20Sopenharmony_ci */ 61548c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_bug(struct net *net, 61558c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 61568c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 61578c2ecf20Sopenharmony_ci const union sctp_subtype type, 61588c2ecf20Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 61598c2ecf20Sopenharmony_ci{ 61608c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_BUG; 61618c2ecf20Sopenharmony_ci} 61628c2ecf20Sopenharmony_ci 61638c2ecf20Sopenharmony_ci/* 61648c2ecf20Sopenharmony_ci * This table entry represents the firing of a timer in the wrong state. 61658c2ecf20Sopenharmony_ci * Since timer deletion cannot be guaranteed a timer 'may' end up firing 61668c2ecf20Sopenharmony_ci * when the association is in the wrong state. This event should 61678c2ecf20Sopenharmony_ci * be ignored, so as to prevent any rearming of the timer. 61688c2ecf20Sopenharmony_ci * 61698c2ecf20Sopenharmony_ci * Inputs 61708c2ecf20Sopenharmony_ci * (endpoint, asoc, chunk) 61718c2ecf20Sopenharmony_ci * 61728c2ecf20Sopenharmony_ci * The return value is the disposition of the chunk. 61738c2ecf20Sopenharmony_ci */ 61748c2ecf20Sopenharmony_cienum sctp_disposition sctp_sf_timer_ignore(struct net *net, 61758c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 61768c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 61778c2ecf20Sopenharmony_ci const union sctp_subtype type, 61788c2ecf20Sopenharmony_ci void *arg, 61798c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 61808c2ecf20Sopenharmony_ci{ 61818c2ecf20Sopenharmony_ci pr_debug("%s: timer %d ignored\n", __func__, type.chunk); 61828c2ecf20Sopenharmony_ci 61838c2ecf20Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 61848c2ecf20Sopenharmony_ci} 61858c2ecf20Sopenharmony_ci 61868c2ecf20Sopenharmony_ci/******************************************************************** 61878c2ecf20Sopenharmony_ci * 2nd Level Abstractions 61888c2ecf20Sopenharmony_ci ********************************************************************/ 61898c2ecf20Sopenharmony_ci 61908c2ecf20Sopenharmony_ci/* Pull the SACK chunk based on the SACK header. */ 61918c2ecf20Sopenharmony_cistatic struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk) 61928c2ecf20Sopenharmony_ci{ 61938c2ecf20Sopenharmony_ci struct sctp_sackhdr *sack; 61948c2ecf20Sopenharmony_ci __u16 num_dup_tsns; 61958c2ecf20Sopenharmony_ci unsigned int len; 61968c2ecf20Sopenharmony_ci __u16 num_blocks; 61978c2ecf20Sopenharmony_ci 61988c2ecf20Sopenharmony_ci /* Protect ourselves from reading too far into 61998c2ecf20Sopenharmony_ci * the skb from a bogus sender. 62008c2ecf20Sopenharmony_ci */ 62018c2ecf20Sopenharmony_ci sack = (struct sctp_sackhdr *) chunk->skb->data; 62028c2ecf20Sopenharmony_ci 62038c2ecf20Sopenharmony_ci num_blocks = ntohs(sack->num_gap_ack_blocks); 62048c2ecf20Sopenharmony_ci num_dup_tsns = ntohs(sack->num_dup_tsns); 62058c2ecf20Sopenharmony_ci len = sizeof(struct sctp_sackhdr); 62068c2ecf20Sopenharmony_ci len += (num_blocks + num_dup_tsns) * sizeof(__u32); 62078c2ecf20Sopenharmony_ci if (len > chunk->skb->len) 62088c2ecf20Sopenharmony_ci return NULL; 62098c2ecf20Sopenharmony_ci 62108c2ecf20Sopenharmony_ci skb_pull(chunk->skb, len); 62118c2ecf20Sopenharmony_ci 62128c2ecf20Sopenharmony_ci return sack; 62138c2ecf20Sopenharmony_ci} 62148c2ecf20Sopenharmony_ci 62158c2ecf20Sopenharmony_ci/* Create an ABORT packet to be sent as a response, with the specified 62168c2ecf20Sopenharmony_ci * error causes. 62178c2ecf20Sopenharmony_ci */ 62188c2ecf20Sopenharmony_cistatic struct sctp_packet *sctp_abort_pkt_new( 62198c2ecf20Sopenharmony_ci struct net *net, 62208c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 62218c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 62228c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 62238c2ecf20Sopenharmony_ci const void *payload, size_t paylen) 62248c2ecf20Sopenharmony_ci{ 62258c2ecf20Sopenharmony_ci struct sctp_packet *packet; 62268c2ecf20Sopenharmony_ci struct sctp_chunk *abort; 62278c2ecf20Sopenharmony_ci 62288c2ecf20Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 62298c2ecf20Sopenharmony_ci 62308c2ecf20Sopenharmony_ci if (packet) { 62318c2ecf20Sopenharmony_ci /* Make an ABORT. 62328c2ecf20Sopenharmony_ci * The T bit will be set if the asoc is NULL. 62338c2ecf20Sopenharmony_ci */ 62348c2ecf20Sopenharmony_ci abort = sctp_make_abort(asoc, chunk, paylen); 62358c2ecf20Sopenharmony_ci if (!abort) { 62368c2ecf20Sopenharmony_ci sctp_ootb_pkt_free(packet); 62378c2ecf20Sopenharmony_ci return NULL; 62388c2ecf20Sopenharmony_ci } 62398c2ecf20Sopenharmony_ci 62408c2ecf20Sopenharmony_ci /* Reflect vtag if T-Bit is set */ 62418c2ecf20Sopenharmony_ci if (sctp_test_T_bit(abort)) 62428c2ecf20Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 62438c2ecf20Sopenharmony_ci 62448c2ecf20Sopenharmony_ci /* Add specified error causes, i.e., payload, to the 62458c2ecf20Sopenharmony_ci * end of the chunk. 62468c2ecf20Sopenharmony_ci */ 62478c2ecf20Sopenharmony_ci sctp_addto_chunk(abort, paylen, payload); 62488c2ecf20Sopenharmony_ci 62498c2ecf20Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 62508c2ecf20Sopenharmony_ci abort->skb->sk = ep->base.sk; 62518c2ecf20Sopenharmony_ci 62528c2ecf20Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 62538c2ecf20Sopenharmony_ci 62548c2ecf20Sopenharmony_ci } 62558c2ecf20Sopenharmony_ci 62568c2ecf20Sopenharmony_ci return packet; 62578c2ecf20Sopenharmony_ci} 62588c2ecf20Sopenharmony_ci 62598c2ecf20Sopenharmony_ci/* Allocate a packet for responding in the OOTB conditions. */ 62608c2ecf20Sopenharmony_cistatic struct sctp_packet *sctp_ootb_pkt_new( 62618c2ecf20Sopenharmony_ci struct net *net, 62628c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 62638c2ecf20Sopenharmony_ci const struct sctp_chunk *chunk) 62648c2ecf20Sopenharmony_ci{ 62658c2ecf20Sopenharmony_ci struct sctp_transport *transport; 62668c2ecf20Sopenharmony_ci struct sctp_packet *packet; 62678c2ecf20Sopenharmony_ci __u16 sport, dport; 62688c2ecf20Sopenharmony_ci __u32 vtag; 62698c2ecf20Sopenharmony_ci 62708c2ecf20Sopenharmony_ci /* Get the source and destination port from the inbound packet. */ 62718c2ecf20Sopenharmony_ci sport = ntohs(chunk->sctp_hdr->dest); 62728c2ecf20Sopenharmony_ci dport = ntohs(chunk->sctp_hdr->source); 62738c2ecf20Sopenharmony_ci 62748c2ecf20Sopenharmony_ci /* The V-tag is going to be the same as the inbound packet if no 62758c2ecf20Sopenharmony_ci * association exists, otherwise, use the peer's vtag. 62768c2ecf20Sopenharmony_ci */ 62778c2ecf20Sopenharmony_ci if (asoc) { 62788c2ecf20Sopenharmony_ci /* Special case the INIT-ACK as there is no peer's vtag 62798c2ecf20Sopenharmony_ci * yet. 62808c2ecf20Sopenharmony_ci */ 62818c2ecf20Sopenharmony_ci switch (chunk->chunk_hdr->type) { 62828c2ecf20Sopenharmony_ci case SCTP_CID_INIT: 62838c2ecf20Sopenharmony_ci case SCTP_CID_INIT_ACK: 62848c2ecf20Sopenharmony_ci { 62858c2ecf20Sopenharmony_ci struct sctp_initack_chunk *initack; 62868c2ecf20Sopenharmony_ci 62878c2ecf20Sopenharmony_ci initack = (struct sctp_initack_chunk *)chunk->chunk_hdr; 62888c2ecf20Sopenharmony_ci vtag = ntohl(initack->init_hdr.init_tag); 62898c2ecf20Sopenharmony_ci break; 62908c2ecf20Sopenharmony_ci } 62918c2ecf20Sopenharmony_ci default: 62928c2ecf20Sopenharmony_ci vtag = asoc->peer.i.init_tag; 62938c2ecf20Sopenharmony_ci break; 62948c2ecf20Sopenharmony_ci } 62958c2ecf20Sopenharmony_ci } else { 62968c2ecf20Sopenharmony_ci /* Special case the INIT and stale COOKIE_ECHO as there is no 62978c2ecf20Sopenharmony_ci * vtag yet. 62988c2ecf20Sopenharmony_ci */ 62998c2ecf20Sopenharmony_ci switch (chunk->chunk_hdr->type) { 63008c2ecf20Sopenharmony_ci case SCTP_CID_INIT: 63018c2ecf20Sopenharmony_ci { 63028c2ecf20Sopenharmony_ci struct sctp_init_chunk *init; 63038c2ecf20Sopenharmony_ci 63048c2ecf20Sopenharmony_ci init = (struct sctp_init_chunk *)chunk->chunk_hdr; 63058c2ecf20Sopenharmony_ci vtag = ntohl(init->init_hdr.init_tag); 63068c2ecf20Sopenharmony_ci break; 63078c2ecf20Sopenharmony_ci } 63088c2ecf20Sopenharmony_ci default: 63098c2ecf20Sopenharmony_ci vtag = ntohl(chunk->sctp_hdr->vtag); 63108c2ecf20Sopenharmony_ci break; 63118c2ecf20Sopenharmony_ci } 63128c2ecf20Sopenharmony_ci } 63138c2ecf20Sopenharmony_ci 63148c2ecf20Sopenharmony_ci /* Make a transport for the bucket, Eliza... */ 63158c2ecf20Sopenharmony_ci transport = sctp_transport_new(net, sctp_source(chunk), GFP_ATOMIC); 63168c2ecf20Sopenharmony_ci if (!transport) 63178c2ecf20Sopenharmony_ci goto nomem; 63188c2ecf20Sopenharmony_ci 63198c2ecf20Sopenharmony_ci /* Cache a route for the transport with the chunk's destination as 63208c2ecf20Sopenharmony_ci * the source address. 63218c2ecf20Sopenharmony_ci */ 63228c2ecf20Sopenharmony_ci sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, 63238c2ecf20Sopenharmony_ci sctp_sk(net->sctp.ctl_sock)); 63248c2ecf20Sopenharmony_ci 63258c2ecf20Sopenharmony_ci packet = &transport->packet; 63268c2ecf20Sopenharmony_ci sctp_packet_init(packet, transport, sport, dport); 63278c2ecf20Sopenharmony_ci sctp_packet_config(packet, vtag, 0); 63288c2ecf20Sopenharmony_ci 63298c2ecf20Sopenharmony_ci return packet; 63308c2ecf20Sopenharmony_ci 63318c2ecf20Sopenharmony_cinomem: 63328c2ecf20Sopenharmony_ci return NULL; 63338c2ecf20Sopenharmony_ci} 63348c2ecf20Sopenharmony_ci 63358c2ecf20Sopenharmony_ci/* Free the packet allocated earlier for responding in the OOTB condition. */ 63368c2ecf20Sopenharmony_civoid sctp_ootb_pkt_free(struct sctp_packet *packet) 63378c2ecf20Sopenharmony_ci{ 63388c2ecf20Sopenharmony_ci sctp_transport_free(packet->transport); 63398c2ecf20Sopenharmony_ci} 63408c2ecf20Sopenharmony_ci 63418c2ecf20Sopenharmony_ci/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */ 63428c2ecf20Sopenharmony_cistatic void sctp_send_stale_cookie_err(struct net *net, 63438c2ecf20Sopenharmony_ci const struct sctp_endpoint *ep, 63448c2ecf20Sopenharmony_ci const struct sctp_association *asoc, 63458c2ecf20Sopenharmony_ci const struct sctp_chunk *chunk, 63468c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands, 63478c2ecf20Sopenharmony_ci struct sctp_chunk *err_chunk) 63488c2ecf20Sopenharmony_ci{ 63498c2ecf20Sopenharmony_ci struct sctp_packet *packet; 63508c2ecf20Sopenharmony_ci 63518c2ecf20Sopenharmony_ci if (err_chunk) { 63528c2ecf20Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 63538c2ecf20Sopenharmony_ci if (packet) { 63548c2ecf20Sopenharmony_ci struct sctp_signed_cookie *cookie; 63558c2ecf20Sopenharmony_ci 63568c2ecf20Sopenharmony_ci /* Override the OOTB vtag from the cookie. */ 63578c2ecf20Sopenharmony_ci cookie = chunk->subh.cookie_hdr; 63588c2ecf20Sopenharmony_ci packet->vtag = cookie->c.peer_vtag; 63598c2ecf20Sopenharmony_ci 63608c2ecf20Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 63618c2ecf20Sopenharmony_ci err_chunk->skb->sk = ep->base.sk; 63628c2ecf20Sopenharmony_ci sctp_packet_append_chunk(packet, err_chunk); 63638c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 63648c2ecf20Sopenharmony_ci SCTP_PACKET(packet)); 63658c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 63668c2ecf20Sopenharmony_ci } else 63678c2ecf20Sopenharmony_ci sctp_chunk_free (err_chunk); 63688c2ecf20Sopenharmony_ci } 63698c2ecf20Sopenharmony_ci} 63708c2ecf20Sopenharmony_ci 63718c2ecf20Sopenharmony_ci 63728c2ecf20Sopenharmony_ci/* Process a data chunk */ 63738c2ecf20Sopenharmony_cistatic int sctp_eat_data(const struct sctp_association *asoc, 63748c2ecf20Sopenharmony_ci struct sctp_chunk *chunk, 63758c2ecf20Sopenharmony_ci struct sctp_cmd_seq *commands) 63768c2ecf20Sopenharmony_ci{ 63778c2ecf20Sopenharmony_ci struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; 63788c2ecf20Sopenharmony_ci struct sock *sk = asoc->base.sk; 63798c2ecf20Sopenharmony_ci struct net *net = sock_net(sk); 63808c2ecf20Sopenharmony_ci struct sctp_datahdr *data_hdr; 63818c2ecf20Sopenharmony_ci struct sctp_chunk *err; 63828c2ecf20Sopenharmony_ci enum sctp_verb deliver; 63838c2ecf20Sopenharmony_ci size_t datalen; 63848c2ecf20Sopenharmony_ci __u32 tsn; 63858c2ecf20Sopenharmony_ci int tmp; 63868c2ecf20Sopenharmony_ci 63878c2ecf20Sopenharmony_ci data_hdr = (struct sctp_datahdr *)chunk->skb->data; 63888c2ecf20Sopenharmony_ci chunk->subh.data_hdr = data_hdr; 63898c2ecf20Sopenharmony_ci skb_pull(chunk->skb, sctp_datahdr_len(&asoc->stream)); 63908c2ecf20Sopenharmony_ci 63918c2ecf20Sopenharmony_ci tsn = ntohl(data_hdr->tsn); 63928c2ecf20Sopenharmony_ci pr_debug("%s: TSN 0x%x\n", __func__, tsn); 63938c2ecf20Sopenharmony_ci 63948c2ecf20Sopenharmony_ci /* ASSERT: Now skb->data is really the user data. */ 63958c2ecf20Sopenharmony_ci 63968c2ecf20Sopenharmony_ci /* Process ECN based congestion. 63978c2ecf20Sopenharmony_ci * 63988c2ecf20Sopenharmony_ci * Since the chunk structure is reused for all chunks within 63998c2ecf20Sopenharmony_ci * a packet, we use ecn_ce_done to track if we've already 64008c2ecf20Sopenharmony_ci * done CE processing for this packet. 64018c2ecf20Sopenharmony_ci * 64028c2ecf20Sopenharmony_ci * We need to do ECN processing even if we plan to discard the 64038c2ecf20Sopenharmony_ci * chunk later. 64048c2ecf20Sopenharmony_ci */ 64058c2ecf20Sopenharmony_ci 64068c2ecf20Sopenharmony_ci if (asoc->peer.ecn_capable && !chunk->ecn_ce_done) { 64078c2ecf20Sopenharmony_ci struct sctp_af *af = SCTP_INPUT_CB(chunk->skb)->af; 64088c2ecf20Sopenharmony_ci chunk->ecn_ce_done = 1; 64098c2ecf20Sopenharmony_ci 64108c2ecf20Sopenharmony_ci if (af->is_ce(sctp_gso_headskb(chunk->skb))) { 64118c2ecf20Sopenharmony_ci /* Do real work as sideffect. */ 64128c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, 64138c2ecf20Sopenharmony_ci SCTP_U32(tsn)); 64148c2ecf20Sopenharmony_ci } 64158c2ecf20Sopenharmony_ci } 64168c2ecf20Sopenharmony_ci 64178c2ecf20Sopenharmony_ci tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn); 64188c2ecf20Sopenharmony_ci if (tmp < 0) { 64198c2ecf20Sopenharmony_ci /* The TSN is too high--silently discard the chunk and 64208c2ecf20Sopenharmony_ci * count on it getting retransmitted later. 64218c2ecf20Sopenharmony_ci */ 64228c2ecf20Sopenharmony_ci if (chunk->asoc) 64238c2ecf20Sopenharmony_ci chunk->asoc->stats.outofseqtsns++; 64248c2ecf20Sopenharmony_ci return SCTP_IERROR_HIGH_TSN; 64258c2ecf20Sopenharmony_ci } else if (tmp > 0) { 64268c2ecf20Sopenharmony_ci /* This is a duplicate. Record it. */ 64278c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn)); 64288c2ecf20Sopenharmony_ci return SCTP_IERROR_DUP_TSN; 64298c2ecf20Sopenharmony_ci } 64308c2ecf20Sopenharmony_ci 64318c2ecf20Sopenharmony_ci /* This is a new TSN. */ 64328c2ecf20Sopenharmony_ci 64338c2ecf20Sopenharmony_ci /* Discard if there is no room in the receive window. 64348c2ecf20Sopenharmony_ci * Actually, allow a little bit of overflow (up to a MTU). 64358c2ecf20Sopenharmony_ci */ 64368c2ecf20Sopenharmony_ci datalen = ntohs(chunk->chunk_hdr->length); 64378c2ecf20Sopenharmony_ci datalen -= sctp_datachk_len(&asoc->stream); 64388c2ecf20Sopenharmony_ci 64398c2ecf20Sopenharmony_ci deliver = SCTP_CMD_CHUNK_ULP; 64408c2ecf20Sopenharmony_ci 64418c2ecf20Sopenharmony_ci /* Think about partial delivery. */ 64428c2ecf20Sopenharmony_ci if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { 64438c2ecf20Sopenharmony_ci 64448c2ecf20Sopenharmony_ci /* Even if we don't accept this chunk there is 64458c2ecf20Sopenharmony_ci * memory pressure. 64468c2ecf20Sopenharmony_ci */ 64478c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL()); 64488c2ecf20Sopenharmony_ci } 64498c2ecf20Sopenharmony_ci 64508c2ecf20Sopenharmony_ci /* Spill over rwnd a little bit. Note: While allowed, this spill over 64518c2ecf20Sopenharmony_ci * seems a bit troublesome in that frag_point varies based on 64528c2ecf20Sopenharmony_ci * PMTU. In cases, such as loopback, this might be a rather 64538c2ecf20Sopenharmony_ci * large spill over. 64548c2ecf20Sopenharmony_ci */ 64558c2ecf20Sopenharmony_ci if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || 64568c2ecf20Sopenharmony_ci (datalen > asoc->rwnd + asoc->frag_point))) { 64578c2ecf20Sopenharmony_ci 64588c2ecf20Sopenharmony_ci /* If this is the next TSN, consider reneging to make 64598c2ecf20Sopenharmony_ci * room. Note: Playing nice with a confused sender. A 64608c2ecf20Sopenharmony_ci * malicious sender can still eat up all our buffer 64618c2ecf20Sopenharmony_ci * space and in the future we may want to detect and 64628c2ecf20Sopenharmony_ci * do more drastic reneging. 64638c2ecf20Sopenharmony_ci */ 64648c2ecf20Sopenharmony_ci if (sctp_tsnmap_has_gap(map) && 64658c2ecf20Sopenharmony_ci (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { 64668c2ecf20Sopenharmony_ci pr_debug("%s: reneging for tsn:%u\n", __func__, tsn); 64678c2ecf20Sopenharmony_ci deliver = SCTP_CMD_RENEGE; 64688c2ecf20Sopenharmony_ci } else { 64698c2ecf20Sopenharmony_ci pr_debug("%s: discard tsn:%u len:%zu, rwnd:%d\n", 64708c2ecf20Sopenharmony_ci __func__, tsn, datalen, asoc->rwnd); 64718c2ecf20Sopenharmony_ci 64728c2ecf20Sopenharmony_ci return SCTP_IERROR_IGNORE_TSN; 64738c2ecf20Sopenharmony_ci } 64748c2ecf20Sopenharmony_ci } 64758c2ecf20Sopenharmony_ci 64768c2ecf20Sopenharmony_ci /* 64778c2ecf20Sopenharmony_ci * Also try to renege to limit our memory usage in the event that 64788c2ecf20Sopenharmony_ci * we are under memory pressure 64798c2ecf20Sopenharmony_ci * If we can't renege, don't worry about it, the sk_rmem_schedule 64808c2ecf20Sopenharmony_ci * in sctp_ulpevent_make_rcvmsg will drop the frame if we grow our 64818c2ecf20Sopenharmony_ci * memory usage too much 64828c2ecf20Sopenharmony_ci */ 64838c2ecf20Sopenharmony_ci if (sk_under_memory_pressure(sk)) { 64848c2ecf20Sopenharmony_ci if (sctp_tsnmap_has_gap(map) && 64858c2ecf20Sopenharmony_ci (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { 64868c2ecf20Sopenharmony_ci pr_debug("%s: under pressure, reneging for tsn:%u\n", 64878c2ecf20Sopenharmony_ci __func__, tsn); 64888c2ecf20Sopenharmony_ci deliver = SCTP_CMD_RENEGE; 64898c2ecf20Sopenharmony_ci } else { 64908c2ecf20Sopenharmony_ci sk_mem_reclaim(sk); 64918c2ecf20Sopenharmony_ci } 64928c2ecf20Sopenharmony_ci } 64938c2ecf20Sopenharmony_ci 64948c2ecf20Sopenharmony_ci /* 64958c2ecf20Sopenharmony_ci * Section 3.3.10.9 No User Data (9) 64968c2ecf20Sopenharmony_ci * 64978c2ecf20Sopenharmony_ci * Cause of error 64988c2ecf20Sopenharmony_ci * --------------- 64998c2ecf20Sopenharmony_ci * No User Data: This error cause is returned to the originator of a 65008c2ecf20Sopenharmony_ci * DATA chunk if a received DATA chunk has no user data. 65018c2ecf20Sopenharmony_ci */ 65028c2ecf20Sopenharmony_ci if (unlikely(0 == datalen)) { 65038c2ecf20Sopenharmony_ci err = sctp_make_abort_no_data(asoc, chunk, tsn); 65048c2ecf20Sopenharmony_ci if (err) { 65058c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 65068c2ecf20Sopenharmony_ci SCTP_CHUNK(err)); 65078c2ecf20Sopenharmony_ci } 65088c2ecf20Sopenharmony_ci /* We are going to ABORT, so we might as well stop 65098c2ecf20Sopenharmony_ci * processing the rest of the chunks in the packet. 65108c2ecf20Sopenharmony_ci */ 65118c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 65128c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 65138c2ecf20Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 65148c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 65158c2ecf20Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_DATA)); 65168c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 65178c2ecf20Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 65188c2ecf20Sopenharmony_ci return SCTP_IERROR_NO_DATA; 65198c2ecf20Sopenharmony_ci } 65208c2ecf20Sopenharmony_ci 65218c2ecf20Sopenharmony_ci chunk->data_accepted = 1; 65228c2ecf20Sopenharmony_ci 65238c2ecf20Sopenharmony_ci /* Note: Some chunks may get overcounted (if we drop) or overcounted 65248c2ecf20Sopenharmony_ci * if we renege and the chunk arrives again. 65258c2ecf20Sopenharmony_ci */ 65268c2ecf20Sopenharmony_ci if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { 65278c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS); 65288c2ecf20Sopenharmony_ci if (chunk->asoc) 65298c2ecf20Sopenharmony_ci chunk->asoc->stats.iuodchunks++; 65308c2ecf20Sopenharmony_ci } else { 65318c2ecf20Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS); 65328c2ecf20Sopenharmony_ci if (chunk->asoc) 65338c2ecf20Sopenharmony_ci chunk->asoc->stats.iodchunks++; 65348c2ecf20Sopenharmony_ci } 65358c2ecf20Sopenharmony_ci 65368c2ecf20Sopenharmony_ci /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number 65378c2ecf20Sopenharmony_ci * 65388c2ecf20Sopenharmony_ci * If an endpoint receive a DATA chunk with an invalid stream 65398c2ecf20Sopenharmony_ci * identifier, it shall acknowledge the reception of the DATA chunk 65408c2ecf20Sopenharmony_ci * following the normal procedure, immediately send an ERROR chunk 65418c2ecf20Sopenharmony_ci * with cause set to "Invalid Stream Identifier" (See Section 3.3.10) 65428c2ecf20Sopenharmony_ci * and discard the DATA chunk. 65438c2ecf20Sopenharmony_ci */ 65448c2ecf20Sopenharmony_ci if (ntohs(data_hdr->stream) >= asoc->stream.incnt) { 65458c2ecf20Sopenharmony_ci /* Mark tsn as received even though we drop it */ 65468c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); 65478c2ecf20Sopenharmony_ci 65488c2ecf20Sopenharmony_ci err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, 65498c2ecf20Sopenharmony_ci &data_hdr->stream, 65508c2ecf20Sopenharmony_ci sizeof(data_hdr->stream), 65518c2ecf20Sopenharmony_ci sizeof(u16)); 65528c2ecf20Sopenharmony_ci if (err) 65538c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 65548c2ecf20Sopenharmony_ci SCTP_CHUNK(err)); 65558c2ecf20Sopenharmony_ci return SCTP_IERROR_BAD_STREAM; 65568c2ecf20Sopenharmony_ci } 65578c2ecf20Sopenharmony_ci 65588c2ecf20Sopenharmony_ci /* Check to see if the SSN is possible for this TSN. 65598c2ecf20Sopenharmony_ci * The biggest gap we can record is 4K wide. Since SSNs wrap 65608c2ecf20Sopenharmony_ci * at an unsigned short, there is no way that an SSN can 65618c2ecf20Sopenharmony_ci * wrap and for a valid TSN. We can simply check if the current 65628c2ecf20Sopenharmony_ci * SSN is smaller then the next expected one. If it is, it wrapped 65638c2ecf20Sopenharmony_ci * and is invalid. 65648c2ecf20Sopenharmony_ci */ 65658c2ecf20Sopenharmony_ci if (!asoc->stream.si->validate_data(chunk)) 65668c2ecf20Sopenharmony_ci return SCTP_IERROR_PROTO_VIOLATION; 65678c2ecf20Sopenharmony_ci 65688c2ecf20Sopenharmony_ci /* Send the data up to the user. Note: Schedule the 65698c2ecf20Sopenharmony_ci * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK 65708c2ecf20Sopenharmony_ci * chunk needs the updated rwnd. 65718c2ecf20Sopenharmony_ci */ 65728c2ecf20Sopenharmony_ci sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk)); 65738c2ecf20Sopenharmony_ci 65748c2ecf20Sopenharmony_ci return SCTP_IERROR_NO_ERROR; 65758c2ecf20Sopenharmony_ci} 6576