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