162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* SCTP kernel implementation 362306a36Sopenharmony_ci * (C) Copyright IBM Corp. 2001, 2004 462306a36Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 562306a36Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 662306a36Sopenharmony_ci * Copyright (c) 2001-2002 Intel Corp. 762306a36Sopenharmony_ci * Copyright (c) 2002 Nokia Corp. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This is part of the SCTP Linux Kernel Implementation. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * These are the state functions for the state machine. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the 1462306a36Sopenharmony_ci * email address(es): 1562306a36Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Written or modified by: 1862306a36Sopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 1962306a36Sopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 2062306a36Sopenharmony_ci * Mathew Kotowsky <kotowsky@sctp.org> 2162306a36Sopenharmony_ci * Sridhar Samudrala <samudrala@us.ibm.com> 2262306a36Sopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 2362306a36Sopenharmony_ci * Hui Huang <hui.huang@nokia.com> 2462306a36Sopenharmony_ci * Dajiang Zhang <dajiang.zhang@nokia.com> 2562306a36Sopenharmony_ci * Daisy Chang <daisyc@us.ibm.com> 2662306a36Sopenharmony_ci * Ardelle Fan <ardelle.fan@intel.com> 2762306a36Sopenharmony_ci * Ryan Layer <rmlayer@us.ibm.com> 2862306a36Sopenharmony_ci * Kevin Gao <kevin.gao@intel.com> 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <linux/types.h> 3462306a36Sopenharmony_ci#include <linux/kernel.h> 3562306a36Sopenharmony_ci#include <linux/ip.h> 3662306a36Sopenharmony_ci#include <linux/ipv6.h> 3762306a36Sopenharmony_ci#include <linux/net.h> 3862306a36Sopenharmony_ci#include <linux/inet.h> 3962306a36Sopenharmony_ci#include <linux/slab.h> 4062306a36Sopenharmony_ci#include <net/sock.h> 4162306a36Sopenharmony_ci#include <net/inet_ecn.h> 4262306a36Sopenharmony_ci#include <linux/skbuff.h> 4362306a36Sopenharmony_ci#include <net/sctp/sctp.h> 4462306a36Sopenharmony_ci#include <net/sctp/sm.h> 4562306a36Sopenharmony_ci#include <net/sctp/structs.h> 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 4862306a36Sopenharmony_ci#include <trace/events/sctp.h> 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic struct sctp_packet *sctp_abort_pkt_new( 5162306a36Sopenharmony_ci struct net *net, 5262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 5362306a36Sopenharmony_ci const struct sctp_association *asoc, 5462306a36Sopenharmony_ci struct sctp_chunk *chunk, 5562306a36Sopenharmony_ci const void *payload, size_t paylen); 5662306a36Sopenharmony_cistatic int sctp_eat_data(const struct sctp_association *asoc, 5762306a36Sopenharmony_ci struct sctp_chunk *chunk, 5862306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 5962306a36Sopenharmony_cistatic struct sctp_packet *sctp_ootb_pkt_new( 6062306a36Sopenharmony_ci struct net *net, 6162306a36Sopenharmony_ci const struct sctp_association *asoc, 6262306a36Sopenharmony_ci const struct sctp_chunk *chunk); 6362306a36Sopenharmony_cistatic void sctp_send_stale_cookie_err(struct net *net, 6462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 6562306a36Sopenharmony_ci const struct sctp_association *asoc, 6662306a36Sopenharmony_ci const struct sctp_chunk *chunk, 6762306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 6862306a36Sopenharmony_ci struct sctp_chunk *err_chunk); 6962306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_5_2_6_stale( 7062306a36Sopenharmony_ci struct net *net, 7162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 7262306a36Sopenharmony_ci const struct sctp_association *asoc, 7362306a36Sopenharmony_ci const union sctp_subtype type, 7462306a36Sopenharmony_ci void *arg, 7562306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 7662306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_shut_8_4_5( 7762306a36Sopenharmony_ci struct net *net, 7862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 7962306a36Sopenharmony_ci const struct sctp_association *asoc, 8062306a36Sopenharmony_ci const union sctp_subtype type, 8162306a36Sopenharmony_ci void *arg, 8262306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 8362306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_tabort_8_4_8( 8462306a36Sopenharmony_ci struct net *net, 8562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 8662306a36Sopenharmony_ci const struct sctp_association *asoc, 8762306a36Sopenharmony_ci const union sctp_subtype type, 8862306a36Sopenharmony_ci void *arg, 8962306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 9062306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_new_encap_port( 9162306a36Sopenharmony_ci struct net *net, 9262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 9362306a36Sopenharmony_ci const struct sctp_association *asoc, 9462306a36Sopenharmony_ci const union sctp_subtype type, 9562306a36Sopenharmony_ci void *arg, 9662306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 9762306a36Sopenharmony_cistatic struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic enum sctp_disposition sctp_stop_t1_and_abort( 10062306a36Sopenharmony_ci struct net *net, 10162306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 10262306a36Sopenharmony_ci __be16 error, int sk_err, 10362306a36Sopenharmony_ci const struct sctp_association *asoc, 10462306a36Sopenharmony_ci struct sctp_transport *transport); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_abort_violation( 10762306a36Sopenharmony_ci struct net *net, 10862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 10962306a36Sopenharmony_ci const struct sctp_association *asoc, 11062306a36Sopenharmony_ci void *arg, 11162306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 11262306a36Sopenharmony_ci const __u8 *payload, 11362306a36Sopenharmony_ci const size_t paylen); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunklen( 11662306a36Sopenharmony_ci struct net *net, 11762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 11862306a36Sopenharmony_ci const struct sctp_association *asoc, 11962306a36Sopenharmony_ci const union sctp_subtype type, 12062306a36Sopenharmony_ci void *arg, 12162306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_paramlen( 12462306a36Sopenharmony_ci struct net *net, 12562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 12662306a36Sopenharmony_ci const struct sctp_association *asoc, 12762306a36Sopenharmony_ci const union sctp_subtype type, 12862306a36Sopenharmony_ci void *arg, void *ext, 12962306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_ctsn( 13262306a36Sopenharmony_ci struct net *net, 13362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 13462306a36Sopenharmony_ci const struct sctp_association *asoc, 13562306a36Sopenharmony_ci const union sctp_subtype type, 13662306a36Sopenharmony_ci void *arg, 13762306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunk( 14062306a36Sopenharmony_ci struct net *net, 14162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 14262306a36Sopenharmony_ci const struct sctp_association *asoc, 14362306a36Sopenharmony_ci const union sctp_subtype type, 14462306a36Sopenharmony_ci void *arg, 14562306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic enum sctp_ierror sctp_sf_authenticate( 14862306a36Sopenharmony_ci const struct sctp_association *asoc, 14962306a36Sopenharmony_ci struct sctp_chunk *chunk); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic enum sctp_disposition __sctp_sf_do_9_1_abort( 15262306a36Sopenharmony_ci struct net *net, 15362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 15462306a36Sopenharmony_ci const struct sctp_association *asoc, 15562306a36Sopenharmony_ci const union sctp_subtype type, 15662306a36Sopenharmony_ci void *arg, 15762306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic enum sctp_disposition 16062306a36Sopenharmony_ci__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, 16162306a36Sopenharmony_ci const struct sctp_association *asoc, 16262306a36Sopenharmony_ci const union sctp_subtype type, void *arg, 16362306a36Sopenharmony_ci struct sctp_cmd_seq *commands); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* Small helper function that checks if the chunk length 16662306a36Sopenharmony_ci * is of the appropriate length. The 'required_length' argument 16762306a36Sopenharmony_ci * is set to be the size of a specific chunk we are testing. 16862306a36Sopenharmony_ci * Return Values: true = Valid length 16962306a36Sopenharmony_ci * false = Invalid length 17062306a36Sopenharmony_ci * 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_cistatic inline bool sctp_chunk_length_valid(struct sctp_chunk *chunk, 17362306a36Sopenharmony_ci __u16 required_length) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci __u16 chunk_length = ntohs(chunk->chunk_hdr->length); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* Previously already marked? */ 17862306a36Sopenharmony_ci if (unlikely(chunk->pdiscard)) 17962306a36Sopenharmony_ci return false; 18062306a36Sopenharmony_ci if (unlikely(chunk_length < required_length)) 18162306a36Sopenharmony_ci return false; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci return true; 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* Check for format error in an ABORT chunk */ 18762306a36Sopenharmony_cistatic inline bool sctp_err_chunk_valid(struct sctp_chunk *chunk) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci struct sctp_errhdr *err; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci sctp_walk_errors(err, chunk->chunk_hdr); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return (void *)err == (void *)chunk->chunk_end; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/********************************************************** 19762306a36Sopenharmony_ci * These are the state functions for handling chunk events. 19862306a36Sopenharmony_ci **********************************************************/ 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/* 20162306a36Sopenharmony_ci * Process the final SHUTDOWN COMPLETE. 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * Section: 4 (C) (diagram), 9.2 20462306a36Sopenharmony_ci * Upon reception of the SHUTDOWN COMPLETE chunk the endpoint will verify 20562306a36Sopenharmony_ci * that it is in SHUTDOWN-ACK-SENT state, if it is not the chunk should be 20662306a36Sopenharmony_ci * discarded. If the endpoint is in the SHUTDOWN-ACK-SENT state the endpoint 20762306a36Sopenharmony_ci * should stop the T2-shutdown timer and remove all knowledge of the 20862306a36Sopenharmony_ci * association (and thus the association enters the CLOSED state). 20962306a36Sopenharmony_ci * 21062306a36Sopenharmony_ci * Verification Tag: 8.5.1(C), sctpimpguide 2.41. 21162306a36Sopenharmony_ci * C) Rules for packet carrying SHUTDOWN COMPLETE: 21262306a36Sopenharmony_ci * ... 21362306a36Sopenharmony_ci * - The receiver of a SHUTDOWN COMPLETE shall accept the packet 21462306a36Sopenharmony_ci * if the Verification Tag field of the packet matches its own tag and 21562306a36Sopenharmony_ci * the T bit is not set 21662306a36Sopenharmony_ci * OR 21762306a36Sopenharmony_ci * it is set to its peer's tag and the T bit is set in the Chunk 21862306a36Sopenharmony_ci * Flags. 21962306a36Sopenharmony_ci * Otherwise, the receiver MUST silently discard the packet 22062306a36Sopenharmony_ci * and take no further action. An endpoint MUST ignore the 22162306a36Sopenharmony_ci * SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state. 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * Inputs 22462306a36Sopenharmony_ci * (endpoint, asoc, chunk) 22562306a36Sopenharmony_ci * 22662306a36Sopenharmony_ci * Outputs 22762306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 22862306a36Sopenharmony_ci * 22962306a36Sopenharmony_ci * The return value is the disposition of the chunk. 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_4_C(struct net *net, 23262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 23362306a36Sopenharmony_ci const struct sctp_association *asoc, 23462306a36Sopenharmony_ci const union sctp_subtype type, 23562306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 23862306a36Sopenharmony_ci struct sctp_ulpevent *ev; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 24162306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* RFC 2960 6.10 Bundling 24462306a36Sopenharmony_ci * 24562306a36Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 24662306a36Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 24762306a36Sopenharmony_ci */ 24862306a36Sopenharmony_ci if (!chunk->singleton) 24962306a36Sopenharmony_ci return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */ 25262306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 25362306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 25462306a36Sopenharmony_ci commands); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* RFC 2960 10.2 SCTP-to-ULP 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * H) SHUTDOWN COMPLETE notification 25962306a36Sopenharmony_ci * 26062306a36Sopenharmony_ci * When SCTP completes the shutdown procedures (section 9.2) this 26162306a36Sopenharmony_ci * notification is passed to the upper layer. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, 26462306a36Sopenharmony_ci 0, 0, 0, NULL, GFP_ATOMIC); 26562306a36Sopenharmony_ci if (ev) 26662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 26762306a36Sopenharmony_ci SCTP_ULPEVENT(ev)); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint 27062306a36Sopenharmony_ci * will verify that it is in SHUTDOWN-ACK-SENT state, if it is 27162306a36Sopenharmony_ci * not the chunk should be discarded. If the endpoint is in 27262306a36Sopenharmony_ci * the SHUTDOWN-ACK-SENT state the endpoint should stop the 27362306a36Sopenharmony_ci * T2-shutdown timer and remove all knowledge of the 27462306a36Sopenharmony_ci * association (and thus the association enters the CLOSED 27562306a36Sopenharmony_ci * state). 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 27862306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 28162306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 28462306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); 28762306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci/* 29562306a36Sopenharmony_ci * Respond to a normal INIT chunk. 29662306a36Sopenharmony_ci * We are the side that is being asked for an association. 29762306a36Sopenharmony_ci * 29862306a36Sopenharmony_ci * Section: 5.1 Normal Establishment of an Association, B 29962306a36Sopenharmony_ci * B) "Z" shall respond immediately with an INIT ACK chunk. The 30062306a36Sopenharmony_ci * destination IP address of the INIT ACK MUST be set to the source 30162306a36Sopenharmony_ci * IP address of the INIT to which this INIT ACK is responding. In 30262306a36Sopenharmony_ci * the response, besides filling in other parameters, "Z" must set the 30362306a36Sopenharmony_ci * Verification Tag field to Tag_A, and also provide its own 30462306a36Sopenharmony_ci * Verification Tag (Tag_Z) in the Initiate Tag field. 30562306a36Sopenharmony_ci * 30662306a36Sopenharmony_ci * Verification Tag: Must be 0. 30762306a36Sopenharmony_ci * 30862306a36Sopenharmony_ci * Inputs 30962306a36Sopenharmony_ci * (endpoint, asoc, chunk) 31062306a36Sopenharmony_ci * 31162306a36Sopenharmony_ci * Outputs 31262306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * The return value is the disposition of the chunk. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1B_init(struct net *net, 31762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 31862306a36Sopenharmony_ci const struct sctp_association *asoc, 31962306a36Sopenharmony_ci const union sctp_subtype type, 32062306a36Sopenharmony_ci void *arg, 32162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct sctp_chunk *chunk = arg, *repl, *err_chunk; 32462306a36Sopenharmony_ci struct sctp_unrecognized_param *unk_param; 32562306a36Sopenharmony_ci struct sctp_association *new_asoc; 32662306a36Sopenharmony_ci struct sctp_packet *packet; 32762306a36Sopenharmony_ci int len; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* 6.10 Bundling 33062306a36Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 33162306a36Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 33262306a36Sopenharmony_ci * 33362306a36Sopenharmony_ci * IG Section 2.11.2 33462306a36Sopenharmony_ci * Furthermore, we require that the receiver of an INIT chunk MUST 33562306a36Sopenharmony_ci * enforce these rules by silently discarding an arriving packet 33662306a36Sopenharmony_ci * with an INIT chunk that is bundled with other chunks. 33762306a36Sopenharmony_ci */ 33862306a36Sopenharmony_ci if (!chunk->singleton) 33962306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* Make sure that the INIT chunk has a valid length. 34262306a36Sopenharmony_ci * Normally, this would cause an ABORT with a Protocol Violation 34362306a36Sopenharmony_ci * error, but since we don't have an association, we'll 34462306a36Sopenharmony_ci * just discard the packet. 34562306a36Sopenharmony_ci */ 34662306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) 34762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* If the packet is an OOTB packet which is temporarily on the 35062306a36Sopenharmony_ci * control endpoint, respond with an ABORT. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci if (ep == sctp_sk(net->sctp.ctl_sock)->ep) { 35362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 35462306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* 3.1 A packet containing an INIT chunk MUST have a zero Verification 35862306a36Sopenharmony_ci * Tag. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci if (chunk->sctp_hdr->vtag != 0) 36162306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* If the INIT is coming toward a closing socket, we'll send back 36462306a36Sopenharmony_ci * and ABORT. Essentially, this catches the race of INIT being 36562306a36Sopenharmony_ci * backloged to the socket at the same time as the user issues close(). 36662306a36Sopenharmony_ci * Since the socket and all its associations are going away, we 36762306a36Sopenharmony_ci * can treat this OOTB 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_ci if (sctp_sstate(ep->base.sk, CLOSING)) 37062306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci /* Verify the INIT chunk before processing it. */ 37362306a36Sopenharmony_ci err_chunk = NULL; 37462306a36Sopenharmony_ci if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, 37562306a36Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, chunk, 37662306a36Sopenharmony_ci &err_chunk)) { 37762306a36Sopenharmony_ci /* This chunk contains fatal error. It is to be discarded. 37862306a36Sopenharmony_ci * Send an ABORT, with causes if there is any. 37962306a36Sopenharmony_ci */ 38062306a36Sopenharmony_ci if (err_chunk) { 38162306a36Sopenharmony_ci packet = sctp_abort_pkt_new(net, ep, asoc, arg, 38262306a36Sopenharmony_ci (__u8 *)(err_chunk->chunk_hdr) + 38362306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr), 38462306a36Sopenharmony_ci ntohs(err_chunk->chunk_hdr->length) - 38562306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci sctp_chunk_free(err_chunk); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (packet) { 39062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 39162306a36Sopenharmony_ci SCTP_PACKET(packet)); 39262306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 39362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 39462306a36Sopenharmony_ci } else { 39562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci } else { 39862306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, 39962306a36Sopenharmony_ci commands); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci /* Grab the INIT header. */ 40462306a36Sopenharmony_ci chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* Tag the variable length parameters. */ 40762306a36Sopenharmony_ci chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(struct sctp_inithdr)); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC); 41062306a36Sopenharmony_ci if (!new_asoc) 41162306a36Sopenharmony_ci goto nomem; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* Update socket peer label if first association. */ 41462306a36Sopenharmony_ci if (security_sctp_assoc_request(new_asoc, chunk->skb)) { 41562306a36Sopenharmony_ci sctp_association_free(new_asoc); 41662306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (sctp_assoc_set_bind_addr_from_ep(new_asoc, 42062306a36Sopenharmony_ci sctp_scope(sctp_source(chunk)), 42162306a36Sopenharmony_ci GFP_ATOMIC) < 0) 42262306a36Sopenharmony_ci goto nomem_init; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* The call, sctp_process_init(), can fail on memory allocation. */ 42562306a36Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), 42662306a36Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, 42762306a36Sopenharmony_ci GFP_ATOMIC)) 42862306a36Sopenharmony_ci goto nomem_init; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /* B) "Z" shall respond immediately with an INIT ACK chunk. */ 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 43362306a36Sopenharmony_ci * make sure to reserve enough room in the INIT ACK for them. 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_ci len = 0; 43662306a36Sopenharmony_ci if (err_chunk) 43762306a36Sopenharmony_ci len = ntohs(err_chunk->chunk_hdr->length) - 43862306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); 44162306a36Sopenharmony_ci if (!repl) 44262306a36Sopenharmony_ci goto nomem_init; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 44562306a36Sopenharmony_ci * include them in the outgoing INIT ACK as "Unrecognized parameter" 44662306a36Sopenharmony_ci * parameter. 44762306a36Sopenharmony_ci */ 44862306a36Sopenharmony_ci if (err_chunk) { 44962306a36Sopenharmony_ci /* Get the "Unrecognized parameter" parameter(s) out of the 45062306a36Sopenharmony_ci * ERROR chunk generated by sctp_verify_init(). Since the 45162306a36Sopenharmony_ci * error cause code for "unknown parameter" and the 45262306a36Sopenharmony_ci * "Unrecognized parameter" type is the same, we can 45362306a36Sopenharmony_ci * construct the parameters in INIT ACK by copying the 45462306a36Sopenharmony_ci * ERROR causes over. 45562306a36Sopenharmony_ci */ 45662306a36Sopenharmony_ci unk_param = (struct sctp_unrecognized_param *) 45762306a36Sopenharmony_ci ((__u8 *)(err_chunk->chunk_hdr) + 45862306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 45962306a36Sopenharmony_ci /* Replace the cause code with the "Unrecognized parameter" 46062306a36Sopenharmony_ci * parameter type. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci sctp_addto_chunk(repl, len, unk_param); 46362306a36Sopenharmony_ci sctp_chunk_free(err_chunk); 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* 47162306a36Sopenharmony_ci * Note: After sending out INIT ACK with the State Cookie parameter, 47262306a36Sopenharmony_ci * "Z" MUST NOT allocate any resources, nor keep any states for the 47362306a36Sopenharmony_ci * new association. Otherwise, "Z" will be vulnerable to resource 47462306a36Sopenharmony_ci * attacks. 47562306a36Sopenharmony_ci */ 47662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_cinomem_init: 48162306a36Sopenharmony_ci sctp_association_free(new_asoc); 48262306a36Sopenharmony_cinomem: 48362306a36Sopenharmony_ci if (err_chunk) 48462306a36Sopenharmony_ci sctp_chunk_free(err_chunk); 48562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci/* 48962306a36Sopenharmony_ci * Respond to a normal INIT ACK chunk. 49062306a36Sopenharmony_ci * We are the side that is initiating the association. 49162306a36Sopenharmony_ci * 49262306a36Sopenharmony_ci * Section: 5.1 Normal Establishment of an Association, C 49362306a36Sopenharmony_ci * C) Upon reception of the INIT ACK from "Z", "A" shall stop the T1-init 49462306a36Sopenharmony_ci * timer and leave COOKIE-WAIT state. "A" shall then send the State 49562306a36Sopenharmony_ci * Cookie received in the INIT ACK chunk in a COOKIE ECHO chunk, start 49662306a36Sopenharmony_ci * the T1-cookie timer, and enter the COOKIE-ECHOED state. 49762306a36Sopenharmony_ci * 49862306a36Sopenharmony_ci * Note: The COOKIE ECHO chunk can be bundled with any pending outbound 49962306a36Sopenharmony_ci * DATA chunks, but it MUST be the first chunk in the packet and 50062306a36Sopenharmony_ci * until the COOKIE ACK is returned the sender MUST NOT send any 50162306a36Sopenharmony_ci * other packets to the peer. 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci * Verification Tag: 3.3.3 50462306a36Sopenharmony_ci * If the value of the Initiate Tag in a received INIT ACK chunk is 50562306a36Sopenharmony_ci * found to be 0, the receiver MUST treat it as an error and close the 50662306a36Sopenharmony_ci * association by transmitting an ABORT. 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * Inputs 50962306a36Sopenharmony_ci * (endpoint, asoc, chunk) 51062306a36Sopenharmony_ci * 51162306a36Sopenharmony_ci * Outputs 51262306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 51362306a36Sopenharmony_ci * 51462306a36Sopenharmony_ci * The return value is the disposition of the chunk. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net, 51762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 51862306a36Sopenharmony_ci const struct sctp_association *asoc, 51962306a36Sopenharmony_ci const union sctp_subtype type, 52062306a36Sopenharmony_ci void *arg, 52162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci struct sctp_init_chunk *initchunk; 52462306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 52562306a36Sopenharmony_ci struct sctp_chunk *err_chunk; 52662306a36Sopenharmony_ci struct sctp_packet *packet; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 52962306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* 6.10 Bundling 53262306a36Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 53362306a36Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_ci if (!chunk->singleton) 53662306a36Sopenharmony_ci return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci /* Make sure that the INIT-ACK chunk has a valid length */ 53962306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_initack_chunk))) 54062306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 54162306a36Sopenharmony_ci commands); 54262306a36Sopenharmony_ci /* Grab the INIT header. */ 54362306a36Sopenharmony_ci chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci /* Verify the INIT chunk before processing it. */ 54662306a36Sopenharmony_ci err_chunk = NULL; 54762306a36Sopenharmony_ci if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, 54862306a36Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, chunk, 54962306a36Sopenharmony_ci &err_chunk)) { 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci enum sctp_error error = SCTP_ERROR_NO_RESOURCE; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci /* This chunk contains fatal error. It is to be discarded. 55462306a36Sopenharmony_ci * Send an ABORT, with causes. If there are no causes, 55562306a36Sopenharmony_ci * then there wasn't enough memory. Just terminate 55662306a36Sopenharmony_ci * the association. 55762306a36Sopenharmony_ci */ 55862306a36Sopenharmony_ci if (err_chunk) { 55962306a36Sopenharmony_ci packet = sctp_abort_pkt_new(net, ep, asoc, arg, 56062306a36Sopenharmony_ci (__u8 *)(err_chunk->chunk_hdr) + 56162306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr), 56262306a36Sopenharmony_ci ntohs(err_chunk->chunk_hdr->length) - 56362306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci sctp_chunk_free(err_chunk); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci if (packet) { 56862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 56962306a36Sopenharmony_ci SCTP_PACKET(packet)); 57062306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 57162306a36Sopenharmony_ci error = SCTP_ERROR_INV_PARAM; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci /* SCTP-AUTH, Section 6.3: 57662306a36Sopenharmony_ci * It should be noted that if the receiver wants to tear 57762306a36Sopenharmony_ci * down an association in an authenticated way only, the 57862306a36Sopenharmony_ci * handling of malformed packets should not result in 57962306a36Sopenharmony_ci * tearing down the association. 58062306a36Sopenharmony_ci * 58162306a36Sopenharmony_ci * This means that if we only want to abort associations 58262306a36Sopenharmony_ci * in an authenticated way (i.e AUTH+ABORT), then we 58362306a36Sopenharmony_ci * can't destroy this association just because the packet 58462306a36Sopenharmony_ci * was malformed. 58562306a36Sopenharmony_ci */ 58662306a36Sopenharmony_ci if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 58762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 59062306a36Sopenharmony_ci return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, 59162306a36Sopenharmony_ci asoc, chunk->transport); 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* Tag the variable length parameters. Note that we never 59562306a36Sopenharmony_ci * convert the parameters in an INIT chunk. 59662306a36Sopenharmony_ci */ 59762306a36Sopenharmony_ci chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(struct sctp_inithdr)); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci initchunk = (struct sctp_init_chunk *)chunk->chunk_hdr; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, 60262306a36Sopenharmony_ci SCTP_PEER_INIT(initchunk)); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* Reset init error count upon receipt of INIT-ACK. */ 60562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* 5.1 C) "A" shall stop the T1-init timer and leave 60862306a36Sopenharmony_ci * COOKIE-WAIT state. "A" shall then ... start the T1-cookie 60962306a36Sopenharmony_ci * timer, and enter the COOKIE-ECHOED state. 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 61262306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 61362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 61462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 61562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 61662306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_COOKIE_ECHOED)); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci /* SCTP-AUTH: generate the association shared keys so that 61962306a36Sopenharmony_ci * we can potentially sign the COOKIE-ECHO. 62062306a36Sopenharmony_ci */ 62162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_SHKEY, SCTP_NULL()); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* 5.1 C) "A" shall then send the State Cookie received in the 62462306a36Sopenharmony_ci * INIT ACK chunk in a COOKIE ECHO chunk, ... 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_ci /* If there is any errors to report, send the ERROR chunk generated 62762306a36Sopenharmony_ci * for unknown parameters as well. 62862306a36Sopenharmony_ci */ 62962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_COOKIE_ECHO, 63062306a36Sopenharmony_ci SCTP_CHUNK(err_chunk)); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistatic bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, 63662306a36Sopenharmony_ci const struct sctp_association *asoc) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci struct sctp_chunk auth; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (!chunk->auth_chunk) 64162306a36Sopenharmony_ci return true; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo 64462306a36Sopenharmony_ci * is supposed to be authenticated and we have to do delayed 64562306a36Sopenharmony_ci * authentication. We've just recreated the association using 64662306a36Sopenharmony_ci * the information in the cookie and now it's much easier to 64762306a36Sopenharmony_ci * do the authentication. 64862306a36Sopenharmony_ci */ 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci /* Make sure that we and the peer are AUTH capable */ 65162306a36Sopenharmony_ci if (!net->sctp.auth_enable || !asoc->peer.auth_capable) 65262306a36Sopenharmony_ci return false; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* set-up our fake chunk so that we can process it */ 65562306a36Sopenharmony_ci auth.skb = chunk->auth_chunk; 65662306a36Sopenharmony_ci auth.asoc = chunk->asoc; 65762306a36Sopenharmony_ci auth.sctp_hdr = chunk->sctp_hdr; 65862306a36Sopenharmony_ci auth.chunk_hdr = (struct sctp_chunkhdr *) 65962306a36Sopenharmony_ci skb_push(chunk->auth_chunk, 66062306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 66162306a36Sopenharmony_ci skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr)); 66262306a36Sopenharmony_ci auth.transport = chunk->transport; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR; 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci/* 66862306a36Sopenharmony_ci * Respond to a normal COOKIE ECHO chunk. 66962306a36Sopenharmony_ci * We are the side that is being asked for an association. 67062306a36Sopenharmony_ci * 67162306a36Sopenharmony_ci * Section: 5.1 Normal Establishment of an Association, D 67262306a36Sopenharmony_ci * D) Upon reception of the COOKIE ECHO chunk, Endpoint "Z" will reply 67362306a36Sopenharmony_ci * with a COOKIE ACK chunk after building a TCB and moving to 67462306a36Sopenharmony_ci * the ESTABLISHED state. A COOKIE ACK chunk may be bundled with 67562306a36Sopenharmony_ci * any pending DATA chunks (and/or SACK chunks), but the COOKIE ACK 67662306a36Sopenharmony_ci * chunk MUST be the first chunk in the packet. 67762306a36Sopenharmony_ci * 67862306a36Sopenharmony_ci * IMPLEMENTATION NOTE: An implementation may choose to send the 67962306a36Sopenharmony_ci * Communication Up notification to the SCTP user upon reception 68062306a36Sopenharmony_ci * of a valid COOKIE ECHO chunk. 68162306a36Sopenharmony_ci * 68262306a36Sopenharmony_ci * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules 68362306a36Sopenharmony_ci * D) Rules for packet carrying a COOKIE ECHO 68462306a36Sopenharmony_ci * 68562306a36Sopenharmony_ci * - When sending a COOKIE ECHO, the endpoint MUST use the value of the 68662306a36Sopenharmony_ci * Initial Tag received in the INIT ACK. 68762306a36Sopenharmony_ci * 68862306a36Sopenharmony_ci * - The receiver of a COOKIE ECHO follows the procedures in Section 5. 68962306a36Sopenharmony_ci * 69062306a36Sopenharmony_ci * Inputs 69162306a36Sopenharmony_ci * (endpoint, asoc, chunk) 69262306a36Sopenharmony_ci * 69362306a36Sopenharmony_ci * Outputs 69462306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 69562306a36Sopenharmony_ci * 69662306a36Sopenharmony_ci * The return value is the disposition of the chunk. 69762306a36Sopenharmony_ci */ 69862306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net, 69962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 70062306a36Sopenharmony_ci const struct sctp_association *asoc, 70162306a36Sopenharmony_ci const union sctp_subtype type, 70262306a36Sopenharmony_ci void *arg, 70362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci struct sctp_ulpevent *ev, *ai_ev = NULL, *auth_ev = NULL; 70662306a36Sopenharmony_ci struct sctp_association *new_asoc; 70762306a36Sopenharmony_ci struct sctp_init_chunk *peer_init; 70862306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 70962306a36Sopenharmony_ci struct sctp_chunk *err_chk_p; 71062306a36Sopenharmony_ci struct sctp_chunk *repl; 71162306a36Sopenharmony_ci struct sock *sk; 71262306a36Sopenharmony_ci int error = 0; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (asoc && !sctp_vtag_verify(chunk, asoc)) 71562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* If the packet is an OOTB packet which is temporarily on the 71862306a36Sopenharmony_ci * control endpoint, respond with an ABORT. 71962306a36Sopenharmony_ci */ 72062306a36Sopenharmony_ci if (ep == sctp_sk(net->sctp.ctl_sock)->ep) { 72162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 72262306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 72362306a36Sopenharmony_ci } 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci /* Make sure that the COOKIE_ECHO chunk has a valid length. 72662306a36Sopenharmony_ci * In this case, we check that we have enough for at least a 72762306a36Sopenharmony_ci * chunk header. More detailed verification is done 72862306a36Sopenharmony_ci * in sctp_unpack_cookie(). 72962306a36Sopenharmony_ci */ 73062306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 73162306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 73262306a36Sopenharmony_ci commands); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci /* If the endpoint is not listening or if the number of associations 73562306a36Sopenharmony_ci * on the TCP-style socket exceed the max backlog, respond with an 73662306a36Sopenharmony_ci * ABORT. 73762306a36Sopenharmony_ci */ 73862306a36Sopenharmony_ci sk = ep->base.sk; 73962306a36Sopenharmony_ci if (!sctp_sstate(sk, LISTENING) || 74062306a36Sopenharmony_ci (sctp_style(sk, TCP) && sk_acceptq_is_full(sk))) 74162306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci /* "Decode" the chunk. We have no optional parameters so we 74462306a36Sopenharmony_ci * are in good shape. 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_ci chunk->subh.cookie_hdr = 74762306a36Sopenharmony_ci (struct sctp_signed_cookie *)chunk->skb->data; 74862306a36Sopenharmony_ci if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - 74962306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr))) 75062306a36Sopenharmony_ci goto nomem; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci /* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint 75362306a36Sopenharmony_ci * "Z" will reply with a COOKIE ACK chunk after building a TCB 75462306a36Sopenharmony_ci * and moving to the ESTABLISHED state. 75562306a36Sopenharmony_ci */ 75662306a36Sopenharmony_ci new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error, 75762306a36Sopenharmony_ci &err_chk_p); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* FIXME: 76062306a36Sopenharmony_ci * If the re-build failed, what is the proper error path 76162306a36Sopenharmony_ci * from here? 76262306a36Sopenharmony_ci * 76362306a36Sopenharmony_ci * [We should abort the association. --piggy] 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_ci if (!new_asoc) { 76662306a36Sopenharmony_ci /* FIXME: Several errors are possible. A bad cookie should 76762306a36Sopenharmony_ci * be silently discarded, but think about logging it too. 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_ci switch (error) { 77062306a36Sopenharmony_ci case -SCTP_IERROR_NOMEM: 77162306a36Sopenharmony_ci goto nomem; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci case -SCTP_IERROR_STALE_COOKIE: 77462306a36Sopenharmony_ci sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands, 77562306a36Sopenharmony_ci err_chk_p); 77662306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci case -SCTP_IERROR_BAD_SIG: 77962306a36Sopenharmony_ci default: 78062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci if (security_sctp_assoc_request(new_asoc, chunk->head_skb ?: chunk->skb)) { 78562306a36Sopenharmony_ci sctp_association_free(new_asoc); 78662306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 78762306a36Sopenharmony_ci } 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci /* Delay state machine commands until later. 79062306a36Sopenharmony_ci * 79162306a36Sopenharmony_ci * Re-build the bind address for the association is done in 79262306a36Sopenharmony_ci * the sctp_unpack_cookie() already. 79362306a36Sopenharmony_ci */ 79462306a36Sopenharmony_ci /* This is a brand-new association, so these are not yet side 79562306a36Sopenharmony_ci * effects--it is safe to run them here. 79662306a36Sopenharmony_ci */ 79762306a36Sopenharmony_ci peer_init = (struct sctp_init_chunk *)(chunk->subh.cookie_hdr + 1); 79862306a36Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, 79962306a36Sopenharmony_ci &chunk->subh.cookie_hdr->c.peer_addr, 80062306a36Sopenharmony_ci peer_init, GFP_ATOMIC)) 80162306a36Sopenharmony_ci goto nomem_init; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci /* SCTP-AUTH: Now that we've populate required fields in 80462306a36Sopenharmony_ci * sctp_process_init, set up the association shared keys as 80562306a36Sopenharmony_ci * necessary so that we can potentially authenticate the ACK 80662306a36Sopenharmony_ci */ 80762306a36Sopenharmony_ci error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC); 80862306a36Sopenharmony_ci if (error) 80962306a36Sopenharmony_ci goto nomem_init; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) { 81262306a36Sopenharmony_ci sctp_association_free(new_asoc); 81362306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 81462306a36Sopenharmony_ci } 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci repl = sctp_make_cookie_ack(new_asoc, chunk); 81762306a36Sopenharmony_ci if (!repl) 81862306a36Sopenharmony_ci goto nomem_init; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 82162306a36Sopenharmony_ci * 82262306a36Sopenharmony_ci * D) IMPLEMENTATION NOTE: An implementation may choose to 82362306a36Sopenharmony_ci * send the Communication Up notification to the SCTP user 82462306a36Sopenharmony_ci * upon reception of a valid COOKIE ECHO chunk. 82562306a36Sopenharmony_ci */ 82662306a36Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, SCTP_COMM_UP, 0, 82762306a36Sopenharmony_ci new_asoc->c.sinit_num_ostreams, 82862306a36Sopenharmony_ci new_asoc->c.sinit_max_instreams, 82962306a36Sopenharmony_ci NULL, GFP_ATOMIC); 83062306a36Sopenharmony_ci if (!ev) 83162306a36Sopenharmony_ci goto nomem_ev; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 83462306a36Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter , SCTP 83562306a36Sopenharmony_ci * delivers this notification to inform the application that of the 83662306a36Sopenharmony_ci * peers requested adaptation layer. 83762306a36Sopenharmony_ci */ 83862306a36Sopenharmony_ci if (new_asoc->peer.adaptation_ind) { 83962306a36Sopenharmony_ci ai_ev = sctp_ulpevent_make_adaptation_indication(new_asoc, 84062306a36Sopenharmony_ci GFP_ATOMIC); 84162306a36Sopenharmony_ci if (!ai_ev) 84262306a36Sopenharmony_ci goto nomem_aiev; 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (!new_asoc->peer.auth_capable) { 84662306a36Sopenharmony_ci auth_ev = sctp_ulpevent_make_authkey(new_asoc, 0, 84762306a36Sopenharmony_ci SCTP_AUTH_NO_AUTH, 84862306a36Sopenharmony_ci GFP_ATOMIC); 84962306a36Sopenharmony_ci if (!auth_ev) 85062306a36Sopenharmony_ci goto nomem_authev; 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci /* Add all the state machine commands now since we've created 85462306a36Sopenharmony_ci * everything. This way we don't introduce memory corruptions 85562306a36Sopenharmony_ci * during side-effect processing and correctly count established 85662306a36Sopenharmony_ci * associations. 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 85962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 86062306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 86162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 86262306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); 86362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 86662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 86762306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* This will send the COOKIE ACK */ 87062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* Queue the ASSOC_CHANGE event */ 87362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci /* Send up the Adaptation Layer Indication event */ 87662306a36Sopenharmony_ci if (ai_ev) 87762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 87862306a36Sopenharmony_ci SCTP_ULPEVENT(ai_ev)); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (auth_ev) 88162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 88262306a36Sopenharmony_ci SCTP_ULPEVENT(auth_ev)); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cinomem_authev: 88762306a36Sopenharmony_ci sctp_ulpevent_free(ai_ev); 88862306a36Sopenharmony_cinomem_aiev: 88962306a36Sopenharmony_ci sctp_ulpevent_free(ev); 89062306a36Sopenharmony_cinomem_ev: 89162306a36Sopenharmony_ci sctp_chunk_free(repl); 89262306a36Sopenharmony_cinomem_init: 89362306a36Sopenharmony_ci sctp_association_free(new_asoc); 89462306a36Sopenharmony_cinomem: 89562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci/* 89962306a36Sopenharmony_ci * Respond to a normal COOKIE ACK chunk. 90062306a36Sopenharmony_ci * We are the side that is asking for an association. 90162306a36Sopenharmony_ci * 90262306a36Sopenharmony_ci * RFC 2960 5.1 Normal Establishment of an Association 90362306a36Sopenharmony_ci * 90462306a36Sopenharmony_ci * E) Upon reception of the COOKIE ACK, endpoint "A" will move from the 90562306a36Sopenharmony_ci * COOKIE-ECHOED state to the ESTABLISHED state, stopping the T1-cookie 90662306a36Sopenharmony_ci * timer. It may also notify its ULP about the successful 90762306a36Sopenharmony_ci * establishment of the association with a Communication Up 90862306a36Sopenharmony_ci * notification (see Section 10). 90962306a36Sopenharmony_ci * 91062306a36Sopenharmony_ci * Verification Tag: 91162306a36Sopenharmony_ci * Inputs 91262306a36Sopenharmony_ci * (endpoint, asoc, chunk) 91362306a36Sopenharmony_ci * 91462306a36Sopenharmony_ci * Outputs 91562306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 91662306a36Sopenharmony_ci * 91762306a36Sopenharmony_ci * The return value is the disposition of the chunk. 91862306a36Sopenharmony_ci */ 91962306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net, 92062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 92162306a36Sopenharmony_ci const struct sctp_association *asoc, 92262306a36Sopenharmony_ci const union sctp_subtype type, 92362306a36Sopenharmony_ci void *arg, 92462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 92562306a36Sopenharmony_ci{ 92662306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 92762306a36Sopenharmony_ci struct sctp_ulpevent *ev; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 93062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci /* Set peer label for connection. */ 93362306a36Sopenharmony_ci if (security_sctp_assoc_established((struct sctp_association *)asoc, 93462306a36Sopenharmony_ci chunk->head_skb ?: chunk->skb)) 93562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci /* Verify that the chunk length for the COOKIE-ACK is OK. 93862306a36Sopenharmony_ci * If we don't do this, any bundled chunks may be junked. 93962306a36Sopenharmony_ci */ 94062306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 94162306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 94262306a36Sopenharmony_ci commands); 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* Reset init error count upon receipt of COOKIE-ACK, 94562306a36Sopenharmony_ci * to avoid problems with the management of this 94662306a36Sopenharmony_ci * counter in stale cookie situations when a transition back 94762306a36Sopenharmony_ci * from the COOKIE-ECHOED state to the COOKIE-WAIT 94862306a36Sopenharmony_ci * state is performed. 94962306a36Sopenharmony_ci */ 95062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 95362306a36Sopenharmony_ci * 95462306a36Sopenharmony_ci * E) Upon reception of the COOKIE ACK, endpoint "A" will move 95562306a36Sopenharmony_ci * from the COOKIE-ECHOED state to the ESTABLISHED state, 95662306a36Sopenharmony_ci * stopping the T1-cookie timer. 95762306a36Sopenharmony_ci */ 95862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 95962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 96062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 96162306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 96262306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 96362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); 96462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); 96562306a36Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 96662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 96762306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* It may also notify its ULP about the successful 97062306a36Sopenharmony_ci * establishment of the association with a Communication Up 97162306a36Sopenharmony_ci * notification (see Section 10). 97262306a36Sopenharmony_ci */ 97362306a36Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 97462306a36Sopenharmony_ci 0, asoc->c.sinit_num_ostreams, 97562306a36Sopenharmony_ci asoc->c.sinit_max_instreams, 97662306a36Sopenharmony_ci NULL, GFP_ATOMIC); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci if (!ev) 97962306a36Sopenharmony_ci goto nomem; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 98462306a36Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter , SCTP 98562306a36Sopenharmony_ci * delivers this notification to inform the application that of the 98662306a36Sopenharmony_ci * peers requested adaptation layer. 98762306a36Sopenharmony_ci */ 98862306a36Sopenharmony_ci if (asoc->peer.adaptation_ind) { 98962306a36Sopenharmony_ci ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC); 99062306a36Sopenharmony_ci if (!ev) 99162306a36Sopenharmony_ci goto nomem; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 99462306a36Sopenharmony_ci SCTP_ULPEVENT(ev)); 99562306a36Sopenharmony_ci } 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci if (!asoc->peer.auth_capable) { 99862306a36Sopenharmony_ci ev = sctp_ulpevent_make_authkey(asoc, 0, SCTP_AUTH_NO_AUTH, 99962306a36Sopenharmony_ci GFP_ATOMIC); 100062306a36Sopenharmony_ci if (!ev) 100162306a36Sopenharmony_ci goto nomem; 100262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 100362306a36Sopenharmony_ci SCTP_ULPEVENT(ev)); 100462306a36Sopenharmony_ci } 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 100762306a36Sopenharmony_cinomem: 100862306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 100962306a36Sopenharmony_ci} 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci/* Generate and sendout a heartbeat packet. */ 101262306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_heartbeat( 101362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 101462306a36Sopenharmony_ci const struct sctp_association *asoc, 101562306a36Sopenharmony_ci const union sctp_subtype type, 101662306a36Sopenharmony_ci void *arg, 101762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 101862306a36Sopenharmony_ci{ 101962306a36Sopenharmony_ci struct sctp_transport *transport = (struct sctp_transport *) arg; 102062306a36Sopenharmony_ci struct sctp_chunk *reply; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci /* Send a heartbeat to our peer. */ 102362306a36Sopenharmony_ci reply = sctp_make_heartbeat(asoc, transport, 0); 102462306a36Sopenharmony_ci if (!reply) 102562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci /* Set rto_pending indicating that an RTT measurement 102862306a36Sopenharmony_ci * is started with this heartbeat chunk. 102962306a36Sopenharmony_ci */ 103062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_RTO_PENDING, 103162306a36Sopenharmony_ci SCTP_TRANSPORT(transport)); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 103462306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 103562306a36Sopenharmony_ci} 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci/* Generate a HEARTBEAT packet on the given transport. */ 103862306a36Sopenharmony_cienum sctp_disposition sctp_sf_sendbeat_8_3(struct net *net, 103962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 104062306a36Sopenharmony_ci const struct sctp_association *asoc, 104162306a36Sopenharmony_ci const union sctp_subtype type, 104262306a36Sopenharmony_ci void *arg, 104362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci struct sctp_transport *transport = (struct sctp_transport *) arg; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 104862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 104962306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 105062306a36Sopenharmony_ci /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 105162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 105262306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 105362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 105462306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 105562306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 105662306a36Sopenharmony_ci } 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci /* Section 3.3.5. 105962306a36Sopenharmony_ci * The Sender-specific Heartbeat Info field should normally include 106062306a36Sopenharmony_ci * information about the sender's current time when this HEARTBEAT 106162306a36Sopenharmony_ci * chunk is sent and the destination transport address to which this 106262306a36Sopenharmony_ci * HEARTBEAT is sent (see Section 8.3). 106362306a36Sopenharmony_ci */ 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (transport->param_flags & SPP_HB_ENABLE) { 106662306a36Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == 106762306a36Sopenharmony_ci sctp_sf_heartbeat(ep, asoc, type, arg, 106862306a36Sopenharmony_ci commands)) 106962306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci /* Set transport error counter and association error counter 107262306a36Sopenharmony_ci * when sending heartbeat. 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, 107562306a36Sopenharmony_ci SCTP_TRANSPORT(transport)); 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE, 107862306a36Sopenharmony_ci SCTP_TRANSPORT(transport)); 107962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE, 108062306a36Sopenharmony_ci SCTP_TRANSPORT(transport)); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 108362306a36Sopenharmony_ci} 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci/* resend asoc strreset_chunk. */ 108662306a36Sopenharmony_cienum sctp_disposition sctp_sf_send_reconf(struct net *net, 108762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 108862306a36Sopenharmony_ci const struct sctp_association *asoc, 108962306a36Sopenharmony_ci const union sctp_subtype type, 109062306a36Sopenharmony_ci void *arg, 109162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 109262306a36Sopenharmony_ci{ 109362306a36Sopenharmony_ci struct sctp_transport *transport = arg; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 109662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 109762306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 109862306a36Sopenharmony_ci /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 109962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 110062306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 110162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 110262306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 110362306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci sctp_chunk_hold(asoc->strreset_chunk); 110762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 110862306a36Sopenharmony_ci SCTP_CHUNK(asoc->strreset_chunk)); 110962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 111262306a36Sopenharmony_ci} 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci/* send hb chunk with padding for PLPMUTD. */ 111562306a36Sopenharmony_cienum sctp_disposition sctp_sf_send_probe(struct net *net, 111662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 111762306a36Sopenharmony_ci const struct sctp_association *asoc, 111862306a36Sopenharmony_ci const union sctp_subtype type, 111962306a36Sopenharmony_ci void *arg, 112062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 112162306a36Sopenharmony_ci{ 112262306a36Sopenharmony_ci struct sctp_transport *transport = (struct sctp_transport *)arg; 112362306a36Sopenharmony_ci struct sctp_chunk *reply; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci if (!sctp_transport_pl_enabled(transport)) 112662306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci sctp_transport_pl_send(transport); 112962306a36Sopenharmony_ci reply = sctp_make_heartbeat(asoc, transport, transport->pl.probe_size); 113062306a36Sopenharmony_ci if (!reply) 113162306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 113262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 113362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROBE_TIMER_UPDATE, 113462306a36Sopenharmony_ci SCTP_TRANSPORT(transport)); 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 113762306a36Sopenharmony_ci} 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci/* 114062306a36Sopenharmony_ci * Process an heartbeat request. 114162306a36Sopenharmony_ci * 114262306a36Sopenharmony_ci * Section: 8.3 Path Heartbeat 114362306a36Sopenharmony_ci * The receiver of the HEARTBEAT should immediately respond with a 114462306a36Sopenharmony_ci * HEARTBEAT ACK that contains the Heartbeat Information field copied 114562306a36Sopenharmony_ci * from the received HEARTBEAT chunk. 114662306a36Sopenharmony_ci * 114762306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 114862306a36Sopenharmony_ci * When receiving an SCTP packet, the endpoint MUST ensure that the 114962306a36Sopenharmony_ci * value in the Verification Tag field of the received SCTP packet 115062306a36Sopenharmony_ci * matches its own Tag. If the received Verification Tag value does not 115162306a36Sopenharmony_ci * match the receiver's own tag value, the receiver shall silently 115262306a36Sopenharmony_ci * discard the packet and shall not process it any further except for 115362306a36Sopenharmony_ci * those cases listed in Section 8.5.1 below. 115462306a36Sopenharmony_ci * 115562306a36Sopenharmony_ci * Inputs 115662306a36Sopenharmony_ci * (endpoint, asoc, chunk) 115762306a36Sopenharmony_ci * 115862306a36Sopenharmony_ci * Outputs 115962306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 116062306a36Sopenharmony_ci * 116162306a36Sopenharmony_ci * The return value is the disposition of the chunk. 116262306a36Sopenharmony_ci */ 116362306a36Sopenharmony_cienum sctp_disposition sctp_sf_beat_8_3(struct net *net, 116462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 116562306a36Sopenharmony_ci const struct sctp_association *asoc, 116662306a36Sopenharmony_ci const union sctp_subtype type, 116762306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 116862306a36Sopenharmony_ci{ 116962306a36Sopenharmony_ci struct sctp_paramhdr *param_hdr; 117062306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 117162306a36Sopenharmony_ci struct sctp_chunk *reply; 117262306a36Sopenharmony_ci size_t paylen = 0; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 117562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci /* Make sure that the HEARTBEAT chunk has a valid length. */ 117862306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, 117962306a36Sopenharmony_ci sizeof(struct sctp_heartbeat_chunk))) 118062306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 118162306a36Sopenharmony_ci commands); 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci /* 8.3 The receiver of the HEARTBEAT should immediately 118462306a36Sopenharmony_ci * respond with a HEARTBEAT ACK that contains the Heartbeat 118562306a36Sopenharmony_ci * Information field copied from the received HEARTBEAT chunk. 118662306a36Sopenharmony_ci */ 118762306a36Sopenharmony_ci chunk->subh.hb_hdr = (struct sctp_heartbeathdr *)chunk->skb->data; 118862306a36Sopenharmony_ci param_hdr = (struct sctp_paramhdr *)chunk->subh.hb_hdr; 118962306a36Sopenharmony_ci paylen = ntohs(chunk->chunk_hdr->length) - sizeof(struct sctp_chunkhdr); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (ntohs(param_hdr->length) > paylen) 119262306a36Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 119362306a36Sopenharmony_ci param_hdr, commands); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci if (!pskb_pull(chunk->skb, paylen)) 119662306a36Sopenharmony_ci goto nomem; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci reply = sctp_make_heartbeat_ack(asoc, chunk, param_hdr, paylen); 119962306a36Sopenharmony_ci if (!reply) 120062306a36Sopenharmony_ci goto nomem; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 120362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_cinomem: 120662306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 120762306a36Sopenharmony_ci} 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci/* 121062306a36Sopenharmony_ci * Process the returning HEARTBEAT ACK. 121162306a36Sopenharmony_ci * 121262306a36Sopenharmony_ci * Section: 8.3 Path Heartbeat 121362306a36Sopenharmony_ci * Upon the receipt of the HEARTBEAT ACK, the sender of the HEARTBEAT 121462306a36Sopenharmony_ci * should clear the error counter of the destination transport 121562306a36Sopenharmony_ci * address to which the HEARTBEAT was sent, and mark the destination 121662306a36Sopenharmony_ci * transport address as active if it is not so marked. The endpoint may 121762306a36Sopenharmony_ci * optionally report to the upper layer when an inactive destination 121862306a36Sopenharmony_ci * address is marked as active due to the reception of the latest 121962306a36Sopenharmony_ci * HEARTBEAT ACK. The receiver of the HEARTBEAT ACK must also 122062306a36Sopenharmony_ci * clear the association overall error count as well (as defined 122162306a36Sopenharmony_ci * in section 8.1). 122262306a36Sopenharmony_ci * 122362306a36Sopenharmony_ci * The receiver of the HEARTBEAT ACK should also perform an RTT 122462306a36Sopenharmony_ci * measurement for that destination transport address using the time 122562306a36Sopenharmony_ci * value carried in the HEARTBEAT ACK chunk. 122662306a36Sopenharmony_ci * 122762306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 122862306a36Sopenharmony_ci * 122962306a36Sopenharmony_ci * Inputs 123062306a36Sopenharmony_ci * (endpoint, asoc, chunk) 123162306a36Sopenharmony_ci * 123262306a36Sopenharmony_ci * Outputs 123362306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 123462306a36Sopenharmony_ci * 123562306a36Sopenharmony_ci * The return value is the disposition of the chunk. 123662306a36Sopenharmony_ci */ 123762306a36Sopenharmony_cienum sctp_disposition sctp_sf_backbeat_8_3(struct net *net, 123862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 123962306a36Sopenharmony_ci const struct sctp_association *asoc, 124062306a36Sopenharmony_ci const union sctp_subtype type, 124162306a36Sopenharmony_ci void *arg, 124262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 124362306a36Sopenharmony_ci{ 124462306a36Sopenharmony_ci struct sctp_sender_hb_info *hbinfo; 124562306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 124662306a36Sopenharmony_ci struct sctp_transport *link; 124762306a36Sopenharmony_ci unsigned long max_interval; 124862306a36Sopenharmony_ci union sctp_addr from_addr; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 125162306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci /* Make sure that the HEARTBEAT-ACK chunk has a valid length. */ 125462306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr) + 125562306a36Sopenharmony_ci sizeof(*hbinfo))) 125662306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 125762306a36Sopenharmony_ci commands); 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci hbinfo = (struct sctp_sender_hb_info *)chunk->skb->data; 126062306a36Sopenharmony_ci /* Make sure that the length of the parameter is what we expect */ 126162306a36Sopenharmony_ci if (ntohs(hbinfo->param_hdr.length) != sizeof(*hbinfo)) 126262306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci from_addr = hbinfo->daddr; 126562306a36Sopenharmony_ci link = sctp_assoc_lookup_paddr(asoc, &from_addr); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci /* This should never happen, but lets log it if so. */ 126862306a36Sopenharmony_ci if (unlikely(!link)) { 126962306a36Sopenharmony_ci if (from_addr.sa.sa_family == AF_INET6) { 127062306a36Sopenharmony_ci net_warn_ratelimited("%s association %p could not find address %pI6\n", 127162306a36Sopenharmony_ci __func__, 127262306a36Sopenharmony_ci asoc, 127362306a36Sopenharmony_ci &from_addr.v6.sin6_addr); 127462306a36Sopenharmony_ci } else { 127562306a36Sopenharmony_ci net_warn_ratelimited("%s association %p could not find address %pI4\n", 127662306a36Sopenharmony_ci __func__, 127762306a36Sopenharmony_ci asoc, 127862306a36Sopenharmony_ci &from_addr.v4.sin_addr.s_addr); 127962306a36Sopenharmony_ci } 128062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci /* Validate the 64-bit random nonce. */ 128462306a36Sopenharmony_ci if (hbinfo->hb_nonce != link->hb_nonce) 128562306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci if (hbinfo->probe_size) { 128862306a36Sopenharmony_ci if (hbinfo->probe_size != link->pl.probe_size || 128962306a36Sopenharmony_ci !sctp_transport_pl_enabled(link)) 129062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci if (sctp_transport_pl_recv(link)) 129362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci return sctp_sf_send_probe(net, ep, asoc, type, link, commands); 129662306a36Sopenharmony_ci } 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci max_interval = link->hbinterval + link->rto; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci /* Check if the timestamp looks valid. */ 130162306a36Sopenharmony_ci if (time_after(hbinfo->sent_at, jiffies) || 130262306a36Sopenharmony_ci time_after(jiffies, hbinfo->sent_at + max_interval)) { 130362306a36Sopenharmony_ci pr_debug("%s: HEARTBEAT ACK with invalid timestamp received " 130462306a36Sopenharmony_ci "for transport:%p\n", __func__, link); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of 131062306a36Sopenharmony_ci * the HEARTBEAT should clear the error counter of the 131162306a36Sopenharmony_ci * destination transport address to which the HEARTBEAT was 131262306a36Sopenharmony_ci * sent and mark the destination transport address as active if 131362306a36Sopenharmony_ci * it is not so marked. 131462306a36Sopenharmony_ci */ 131562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON, SCTP_TRANSPORT(link)); 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 131862306a36Sopenharmony_ci} 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci/* Helper function to send out an abort for the restart 132162306a36Sopenharmony_ci * condition. 132262306a36Sopenharmony_ci */ 132362306a36Sopenharmony_cistatic int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa, 132462306a36Sopenharmony_ci struct sctp_chunk *init, 132562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 132662306a36Sopenharmony_ci{ 132762306a36Sopenharmony_ci struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family); 132862306a36Sopenharmony_ci union sctp_addr_param *addrparm; 132962306a36Sopenharmony_ci struct sctp_errhdr *errhdr; 133062306a36Sopenharmony_ci char buffer[sizeof(*errhdr) + sizeof(*addrparm)]; 133162306a36Sopenharmony_ci struct sctp_endpoint *ep; 133262306a36Sopenharmony_ci struct sctp_packet *pkt; 133362306a36Sopenharmony_ci int len; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci /* Build the error on the stack. We are way to malloc crazy 133662306a36Sopenharmony_ci * throughout the code today. 133762306a36Sopenharmony_ci */ 133862306a36Sopenharmony_ci errhdr = (struct sctp_errhdr *)buffer; 133962306a36Sopenharmony_ci addrparm = (union sctp_addr_param *)(errhdr + 1); 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci /* Copy into a parm format. */ 134262306a36Sopenharmony_ci len = af->to_addr_param(ssa, addrparm); 134362306a36Sopenharmony_ci len += sizeof(*errhdr); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci errhdr->cause = SCTP_ERROR_RESTART; 134662306a36Sopenharmony_ci errhdr->length = htons(len); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci /* Assign to the control socket. */ 134962306a36Sopenharmony_ci ep = sctp_sk(net->sctp.ctl_sock)->ep; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci /* Association is NULL since this may be a restart attack and we 135262306a36Sopenharmony_ci * want to send back the attacker's vtag. 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_ci pkt = sctp_abort_pkt_new(net, ep, NULL, init, errhdr, len); 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci if (!pkt) 135762306a36Sopenharmony_ci goto out; 135862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt)); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci /* Discard the rest of the inbound packet. */ 136362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ciout: 136662306a36Sopenharmony_ci /* Even if there is no memory, treat as a failure so 136762306a36Sopenharmony_ci * the packet will get dropped. 136862306a36Sopenharmony_ci */ 136962306a36Sopenharmony_ci return 0; 137062306a36Sopenharmony_ci} 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_cistatic bool list_has_sctp_addr(const struct list_head *list, 137362306a36Sopenharmony_ci union sctp_addr *ipaddr) 137462306a36Sopenharmony_ci{ 137562306a36Sopenharmony_ci struct sctp_transport *addr; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci list_for_each_entry(addr, list, transports) { 137862306a36Sopenharmony_ci if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr)) 137962306a36Sopenharmony_ci return true; 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci return false; 138362306a36Sopenharmony_ci} 138462306a36Sopenharmony_ci/* A restart is occurring, check to make sure no new addresses 138562306a36Sopenharmony_ci * are being added as we may be under a takeover attack. 138662306a36Sopenharmony_ci */ 138762306a36Sopenharmony_cistatic int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, 138862306a36Sopenharmony_ci const struct sctp_association *asoc, 138962306a36Sopenharmony_ci struct sctp_chunk *init, 139062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 139162306a36Sopenharmony_ci{ 139262306a36Sopenharmony_ci struct net *net = new_asoc->base.net; 139362306a36Sopenharmony_ci struct sctp_transport *new_addr; 139462306a36Sopenharmony_ci int ret = 1; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci /* Implementor's Guide - Section 5.2.2 139762306a36Sopenharmony_ci * ... 139862306a36Sopenharmony_ci * Before responding the endpoint MUST check to see if the 139962306a36Sopenharmony_ci * unexpected INIT adds new addresses to the association. If new 140062306a36Sopenharmony_ci * addresses are added to the association, the endpoint MUST respond 140162306a36Sopenharmony_ci * with an ABORT.. 140262306a36Sopenharmony_ci */ 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci /* Search through all current addresses and make sure 140562306a36Sopenharmony_ci * we aren't adding any new ones. 140662306a36Sopenharmony_ci */ 140762306a36Sopenharmony_ci list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, 140862306a36Sopenharmony_ci transports) { 140962306a36Sopenharmony_ci if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, 141062306a36Sopenharmony_ci &new_addr->ipaddr)) { 141162306a36Sopenharmony_ci sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init, 141262306a36Sopenharmony_ci commands); 141362306a36Sopenharmony_ci ret = 0; 141462306a36Sopenharmony_ci break; 141562306a36Sopenharmony_ci } 141662306a36Sopenharmony_ci } 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci /* Return success if all addresses were found. */ 141962306a36Sopenharmony_ci return ret; 142062306a36Sopenharmony_ci} 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci/* Populate the verification/tie tags based on overlapping INIT 142362306a36Sopenharmony_ci * scenario. 142462306a36Sopenharmony_ci * 142562306a36Sopenharmony_ci * Note: Do not use in CLOSED or SHUTDOWN-ACK-SENT state. 142662306a36Sopenharmony_ci */ 142762306a36Sopenharmony_cistatic void sctp_tietags_populate(struct sctp_association *new_asoc, 142862306a36Sopenharmony_ci const struct sctp_association *asoc) 142962306a36Sopenharmony_ci{ 143062306a36Sopenharmony_ci switch (asoc->state) { 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci /* 5.2.1 INIT received in COOKIE-WAIT or COOKIE-ECHOED State */ 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci case SCTP_STATE_COOKIE_WAIT: 143562306a36Sopenharmony_ci new_asoc->c.my_vtag = asoc->c.my_vtag; 143662306a36Sopenharmony_ci new_asoc->c.my_ttag = asoc->c.my_vtag; 143762306a36Sopenharmony_ci new_asoc->c.peer_ttag = 0; 143862306a36Sopenharmony_ci break; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci case SCTP_STATE_COOKIE_ECHOED: 144162306a36Sopenharmony_ci new_asoc->c.my_vtag = asoc->c.my_vtag; 144262306a36Sopenharmony_ci new_asoc->c.my_ttag = asoc->c.my_vtag; 144362306a36Sopenharmony_ci new_asoc->c.peer_ttag = asoc->c.peer_vtag; 144462306a36Sopenharmony_ci break; 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci /* 5.2.2 Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED, 144762306a36Sopenharmony_ci * COOKIE-WAIT and SHUTDOWN-ACK-SENT 144862306a36Sopenharmony_ci */ 144962306a36Sopenharmony_ci default: 145062306a36Sopenharmony_ci new_asoc->c.my_ttag = asoc->c.my_vtag; 145162306a36Sopenharmony_ci new_asoc->c.peer_ttag = asoc->c.peer_vtag; 145262306a36Sopenharmony_ci break; 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci /* Other parameters for the endpoint SHOULD be copied from the 145662306a36Sopenharmony_ci * existing parameters of the association (e.g. number of 145762306a36Sopenharmony_ci * outbound streams) into the INIT ACK and cookie. 145862306a36Sopenharmony_ci */ 145962306a36Sopenharmony_ci new_asoc->rwnd = asoc->rwnd; 146062306a36Sopenharmony_ci new_asoc->c.sinit_num_ostreams = asoc->c.sinit_num_ostreams; 146162306a36Sopenharmony_ci new_asoc->c.sinit_max_instreams = asoc->c.sinit_max_instreams; 146262306a36Sopenharmony_ci new_asoc->c.initial_tsn = asoc->c.initial_tsn; 146362306a36Sopenharmony_ci} 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci/* 146662306a36Sopenharmony_ci * Compare vtag/tietag values to determine unexpected COOKIE-ECHO 146762306a36Sopenharmony_ci * handling action. 146862306a36Sopenharmony_ci * 146962306a36Sopenharmony_ci * RFC 2960 5.2.4 Handle a COOKIE ECHO when a TCB exists. 147062306a36Sopenharmony_ci * 147162306a36Sopenharmony_ci * Returns value representing action to be taken. These action values 147262306a36Sopenharmony_ci * correspond to Action/Description values in RFC 2960, Table 2. 147362306a36Sopenharmony_ci */ 147462306a36Sopenharmony_cistatic char sctp_tietags_compare(struct sctp_association *new_asoc, 147562306a36Sopenharmony_ci const struct sctp_association *asoc) 147662306a36Sopenharmony_ci{ 147762306a36Sopenharmony_ci /* In this case, the peer may have restarted. */ 147862306a36Sopenharmony_ci if ((asoc->c.my_vtag != new_asoc->c.my_vtag) && 147962306a36Sopenharmony_ci (asoc->c.peer_vtag != new_asoc->c.peer_vtag) && 148062306a36Sopenharmony_ci (asoc->c.my_vtag == new_asoc->c.my_ttag) && 148162306a36Sopenharmony_ci (asoc->c.peer_vtag == new_asoc->c.peer_ttag)) 148262306a36Sopenharmony_ci return 'A'; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci /* Collision case B. */ 148562306a36Sopenharmony_ci if ((asoc->c.my_vtag == new_asoc->c.my_vtag) && 148662306a36Sopenharmony_ci ((asoc->c.peer_vtag != new_asoc->c.peer_vtag) || 148762306a36Sopenharmony_ci (0 == asoc->c.peer_vtag))) { 148862306a36Sopenharmony_ci return 'B'; 148962306a36Sopenharmony_ci } 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci /* Collision case D. */ 149262306a36Sopenharmony_ci if ((asoc->c.my_vtag == new_asoc->c.my_vtag) && 149362306a36Sopenharmony_ci (asoc->c.peer_vtag == new_asoc->c.peer_vtag)) 149462306a36Sopenharmony_ci return 'D'; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci /* Collision case C. */ 149762306a36Sopenharmony_ci if ((asoc->c.my_vtag != new_asoc->c.my_vtag) && 149862306a36Sopenharmony_ci (asoc->c.peer_vtag == new_asoc->c.peer_vtag) && 149962306a36Sopenharmony_ci (0 == new_asoc->c.my_ttag) && 150062306a36Sopenharmony_ci (0 == new_asoc->c.peer_ttag)) 150162306a36Sopenharmony_ci return 'C'; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci /* No match to any of the special cases; discard this packet. */ 150462306a36Sopenharmony_ci return 'E'; 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci/* Common helper routine for both duplicate and simultaneous INIT 150862306a36Sopenharmony_ci * chunk handling. 150962306a36Sopenharmony_ci */ 151062306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_unexpected_init( 151162306a36Sopenharmony_ci struct net *net, 151262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 151362306a36Sopenharmony_ci const struct sctp_association *asoc, 151462306a36Sopenharmony_ci const union sctp_subtype type, 151562306a36Sopenharmony_ci void *arg, 151662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 151762306a36Sopenharmony_ci{ 151862306a36Sopenharmony_ci struct sctp_chunk *chunk = arg, *repl, *err_chunk; 151962306a36Sopenharmony_ci struct sctp_unrecognized_param *unk_param; 152062306a36Sopenharmony_ci struct sctp_association *new_asoc; 152162306a36Sopenharmony_ci enum sctp_disposition retval; 152262306a36Sopenharmony_ci struct sctp_packet *packet; 152362306a36Sopenharmony_ci int len; 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci /* 6.10 Bundling 152662306a36Sopenharmony_ci * An endpoint MUST NOT bundle INIT, INIT ACK or 152762306a36Sopenharmony_ci * SHUTDOWN COMPLETE with any other chunks. 152862306a36Sopenharmony_ci * 152962306a36Sopenharmony_ci * IG Section 2.11.2 153062306a36Sopenharmony_ci * Furthermore, we require that the receiver of an INIT chunk MUST 153162306a36Sopenharmony_ci * enforce these rules by silently discarding an arriving packet 153262306a36Sopenharmony_ci * with an INIT chunk that is bundled with other chunks. 153362306a36Sopenharmony_ci */ 153462306a36Sopenharmony_ci if (!chunk->singleton) 153562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci /* Make sure that the INIT chunk has a valid length. */ 153862306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) 153962306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci /* 3.1 A packet containing an INIT chunk MUST have a zero Verification 154262306a36Sopenharmony_ci * Tag. 154362306a36Sopenharmony_ci */ 154462306a36Sopenharmony_ci if (chunk->sctp_hdr->vtag != 0) 154562306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci if (SCTP_INPUT_CB(chunk->skb)->encap_port != chunk->transport->encap_port) 154862306a36Sopenharmony_ci return sctp_sf_new_encap_port(net, ep, asoc, type, arg, commands); 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci /* Grab the INIT header. */ 155162306a36Sopenharmony_ci chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci /* Tag the variable length parameters. */ 155462306a36Sopenharmony_ci chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(struct sctp_inithdr)); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci /* Verify the INIT chunk before processing it. */ 155762306a36Sopenharmony_ci err_chunk = NULL; 155862306a36Sopenharmony_ci if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, 155962306a36Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, chunk, 156062306a36Sopenharmony_ci &err_chunk)) { 156162306a36Sopenharmony_ci /* This chunk contains fatal error. It is to be discarded. 156262306a36Sopenharmony_ci * Send an ABORT, with causes if there is any. 156362306a36Sopenharmony_ci */ 156462306a36Sopenharmony_ci if (err_chunk) { 156562306a36Sopenharmony_ci packet = sctp_abort_pkt_new(net, ep, asoc, arg, 156662306a36Sopenharmony_ci (__u8 *)(err_chunk->chunk_hdr) + 156762306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr), 156862306a36Sopenharmony_ci ntohs(err_chunk->chunk_hdr->length) - 156962306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci if (packet) { 157262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 157362306a36Sopenharmony_ci SCTP_PACKET(packet)); 157462306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 157562306a36Sopenharmony_ci retval = SCTP_DISPOSITION_CONSUME; 157662306a36Sopenharmony_ci } else { 157762306a36Sopenharmony_ci retval = SCTP_DISPOSITION_NOMEM; 157862306a36Sopenharmony_ci } 157962306a36Sopenharmony_ci goto cleanup; 158062306a36Sopenharmony_ci } else { 158162306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, 158262306a36Sopenharmony_ci commands); 158362306a36Sopenharmony_ci } 158462306a36Sopenharmony_ci } 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci /* 158762306a36Sopenharmony_ci * Other parameters for the endpoint SHOULD be copied from the 158862306a36Sopenharmony_ci * existing parameters of the association (e.g. number of 158962306a36Sopenharmony_ci * outbound streams) into the INIT ACK and cookie. 159062306a36Sopenharmony_ci * FIXME: We are copying parameters from the endpoint not the 159162306a36Sopenharmony_ci * association. 159262306a36Sopenharmony_ci */ 159362306a36Sopenharmony_ci new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC); 159462306a36Sopenharmony_ci if (!new_asoc) 159562306a36Sopenharmony_ci goto nomem; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci /* Update socket peer label if first association. */ 159862306a36Sopenharmony_ci if (security_sctp_assoc_request(new_asoc, chunk->skb)) { 159962306a36Sopenharmony_ci sctp_association_free(new_asoc); 160062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 160162306a36Sopenharmony_ci } 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci if (sctp_assoc_set_bind_addr_from_ep(new_asoc, 160462306a36Sopenharmony_ci sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0) 160562306a36Sopenharmony_ci goto nomem; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci /* In the outbound INIT ACK the endpoint MUST copy its current 160862306a36Sopenharmony_ci * Verification Tag and Peers Verification tag into a reserved 160962306a36Sopenharmony_ci * place (local tie-tag and per tie-tag) within the state cookie. 161062306a36Sopenharmony_ci */ 161162306a36Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), 161262306a36Sopenharmony_ci (struct sctp_init_chunk *)chunk->chunk_hdr, 161362306a36Sopenharmony_ci GFP_ATOMIC)) 161462306a36Sopenharmony_ci goto nomem; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci /* Make sure no new addresses are being added during the 161762306a36Sopenharmony_ci * restart. Do not do this check for COOKIE-WAIT state, 161862306a36Sopenharmony_ci * since there are no peer addresses to check against. 161962306a36Sopenharmony_ci * Upon return an ABORT will have been sent if needed. 162062306a36Sopenharmony_ci */ 162162306a36Sopenharmony_ci if (!sctp_state(asoc, COOKIE_WAIT)) { 162262306a36Sopenharmony_ci if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, 162362306a36Sopenharmony_ci commands)) { 162462306a36Sopenharmony_ci retval = SCTP_DISPOSITION_CONSUME; 162562306a36Sopenharmony_ci goto nomem_retval; 162662306a36Sopenharmony_ci } 162762306a36Sopenharmony_ci } 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci sctp_tietags_populate(new_asoc, asoc); 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci /* B) "Z" shall respond immediately with an INIT ACK chunk. */ 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 163462306a36Sopenharmony_ci * make sure to reserve enough room in the INIT ACK for them. 163562306a36Sopenharmony_ci */ 163662306a36Sopenharmony_ci len = 0; 163762306a36Sopenharmony_ci if (err_chunk) { 163862306a36Sopenharmony_ci len = ntohs(err_chunk->chunk_hdr->length) - 163962306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr); 164062306a36Sopenharmony_ci } 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); 164362306a36Sopenharmony_ci if (!repl) 164462306a36Sopenharmony_ci goto nomem; 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci /* If there are errors need to be reported for unknown parameters, 164762306a36Sopenharmony_ci * include them in the outgoing INIT ACK as "Unrecognized parameter" 164862306a36Sopenharmony_ci * parameter. 164962306a36Sopenharmony_ci */ 165062306a36Sopenharmony_ci if (err_chunk) { 165162306a36Sopenharmony_ci /* Get the "Unrecognized parameter" parameter(s) out of the 165262306a36Sopenharmony_ci * ERROR chunk generated by sctp_verify_init(). Since the 165362306a36Sopenharmony_ci * error cause code for "unknown parameter" and the 165462306a36Sopenharmony_ci * "Unrecognized parameter" type is the same, we can 165562306a36Sopenharmony_ci * construct the parameters in INIT ACK by copying the 165662306a36Sopenharmony_ci * ERROR causes over. 165762306a36Sopenharmony_ci */ 165862306a36Sopenharmony_ci unk_param = (struct sctp_unrecognized_param *) 165962306a36Sopenharmony_ci ((__u8 *)(err_chunk->chunk_hdr) + 166062306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr)); 166162306a36Sopenharmony_ci /* Replace the cause code with the "Unrecognized parameter" 166262306a36Sopenharmony_ci * parameter type. 166362306a36Sopenharmony_ci */ 166462306a36Sopenharmony_ci sctp_addto_chunk(repl, len, unk_param); 166562306a36Sopenharmony_ci } 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 166862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci /* 167162306a36Sopenharmony_ci * Note: After sending out INIT ACK with the State Cookie parameter, 167262306a36Sopenharmony_ci * "Z" MUST NOT allocate any resources for this new association. 167362306a36Sopenharmony_ci * Otherwise, "Z" will be vulnerable to resource attacks. 167462306a36Sopenharmony_ci */ 167562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 167662306a36Sopenharmony_ci retval = SCTP_DISPOSITION_CONSUME; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci return retval; 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_cinomem: 168162306a36Sopenharmony_ci retval = SCTP_DISPOSITION_NOMEM; 168262306a36Sopenharmony_cinomem_retval: 168362306a36Sopenharmony_ci if (new_asoc) 168462306a36Sopenharmony_ci sctp_association_free(new_asoc); 168562306a36Sopenharmony_cicleanup: 168662306a36Sopenharmony_ci if (err_chunk) 168762306a36Sopenharmony_ci sctp_chunk_free(err_chunk); 168862306a36Sopenharmony_ci return retval; 168962306a36Sopenharmony_ci} 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci/* 169262306a36Sopenharmony_ci * Handle simultaneous INIT. 169362306a36Sopenharmony_ci * This means we started an INIT and then we got an INIT request from 169462306a36Sopenharmony_ci * our peer. 169562306a36Sopenharmony_ci * 169662306a36Sopenharmony_ci * Section: 5.2.1 INIT received in COOKIE-WAIT or COOKIE-ECHOED State (Item B) 169762306a36Sopenharmony_ci * This usually indicates an initialization collision, i.e., each 169862306a36Sopenharmony_ci * endpoint is attempting, at about the same time, to establish an 169962306a36Sopenharmony_ci * association with the other endpoint. 170062306a36Sopenharmony_ci * 170162306a36Sopenharmony_ci * Upon receipt of an INIT in the COOKIE-WAIT or COOKIE-ECHOED state, an 170262306a36Sopenharmony_ci * endpoint MUST respond with an INIT ACK using the same parameters it 170362306a36Sopenharmony_ci * sent in its original INIT chunk (including its Verification Tag, 170462306a36Sopenharmony_ci * unchanged). These original parameters are combined with those from the 170562306a36Sopenharmony_ci * newly received INIT chunk. The endpoint shall also generate a State 170662306a36Sopenharmony_ci * Cookie with the INIT ACK. The endpoint uses the parameters sent in its 170762306a36Sopenharmony_ci * INIT to calculate the State Cookie. 170862306a36Sopenharmony_ci * 170962306a36Sopenharmony_ci * After that, the endpoint MUST NOT change its state, the T1-init 171062306a36Sopenharmony_ci * timer shall be left running and the corresponding TCB MUST NOT be 171162306a36Sopenharmony_ci * destroyed. The normal procedures for handling State Cookies when 171262306a36Sopenharmony_ci * a TCB exists will resolve the duplicate INITs to a single association. 171362306a36Sopenharmony_ci * 171462306a36Sopenharmony_ci * For an endpoint that is in the COOKIE-ECHOED state it MUST populate 171562306a36Sopenharmony_ci * its Tie-Tags with the Tag information of itself and its peer (see 171662306a36Sopenharmony_ci * section 5.2.2 for a description of the Tie-Tags). 171762306a36Sopenharmony_ci * 171862306a36Sopenharmony_ci * Verification Tag: Not explicit, but an INIT can not have a valid 171962306a36Sopenharmony_ci * verification tag, so we skip the check. 172062306a36Sopenharmony_ci * 172162306a36Sopenharmony_ci * Inputs 172262306a36Sopenharmony_ci * (endpoint, asoc, chunk) 172362306a36Sopenharmony_ci * 172462306a36Sopenharmony_ci * Outputs 172562306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 172662306a36Sopenharmony_ci * 172762306a36Sopenharmony_ci * The return value is the disposition of the chunk. 172862306a36Sopenharmony_ci */ 172962306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_1_siminit( 173062306a36Sopenharmony_ci struct net *net, 173162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 173262306a36Sopenharmony_ci const struct sctp_association *asoc, 173362306a36Sopenharmony_ci const union sctp_subtype type, 173462306a36Sopenharmony_ci void *arg, 173562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 173662306a36Sopenharmony_ci{ 173762306a36Sopenharmony_ci /* Call helper to do the real work for both simultaneous and 173862306a36Sopenharmony_ci * duplicate INIT chunk handling. 173962306a36Sopenharmony_ci */ 174062306a36Sopenharmony_ci return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands); 174162306a36Sopenharmony_ci} 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci/* 174462306a36Sopenharmony_ci * Handle duplicated INIT messages. These are usually delayed 174562306a36Sopenharmony_ci * restransmissions. 174662306a36Sopenharmony_ci * 174762306a36Sopenharmony_ci * Section: 5.2.2 Unexpected INIT in States Other than CLOSED, 174862306a36Sopenharmony_ci * COOKIE-ECHOED and COOKIE-WAIT 174962306a36Sopenharmony_ci * 175062306a36Sopenharmony_ci * Unless otherwise stated, upon reception of an unexpected INIT for 175162306a36Sopenharmony_ci * this association, the endpoint shall generate an INIT ACK with a 175262306a36Sopenharmony_ci * State Cookie. In the outbound INIT ACK the endpoint MUST copy its 175362306a36Sopenharmony_ci * current Verification Tag and peer's Verification Tag into a reserved 175462306a36Sopenharmony_ci * place within the state cookie. We shall refer to these locations as 175562306a36Sopenharmony_ci * the Peer's-Tie-Tag and the Local-Tie-Tag. The outbound SCTP packet 175662306a36Sopenharmony_ci * containing this INIT ACK MUST carry a Verification Tag value equal to 175762306a36Sopenharmony_ci * the Initiation Tag found in the unexpected INIT. And the INIT ACK 175862306a36Sopenharmony_ci * MUST contain a new Initiation Tag (randomly generated see Section 175962306a36Sopenharmony_ci * 5.3.1). Other parameters for the endpoint SHOULD be copied from the 176062306a36Sopenharmony_ci * existing parameters of the association (e.g. number of outbound 176162306a36Sopenharmony_ci * streams) into the INIT ACK and cookie. 176262306a36Sopenharmony_ci * 176362306a36Sopenharmony_ci * After sending out the INIT ACK, the endpoint shall take no further 176462306a36Sopenharmony_ci * actions, i.e., the existing association, including its current state, 176562306a36Sopenharmony_ci * and the corresponding TCB MUST NOT be changed. 176662306a36Sopenharmony_ci * 176762306a36Sopenharmony_ci * Note: Only when a TCB exists and the association is not in a COOKIE- 176862306a36Sopenharmony_ci * WAIT state are the Tie-Tags populated. For a normal association INIT 176962306a36Sopenharmony_ci * (i.e. the endpoint is in a COOKIE-WAIT state), the Tie-Tags MUST be 177062306a36Sopenharmony_ci * set to 0 (indicating that no previous TCB existed). The INIT ACK and 177162306a36Sopenharmony_ci * State Cookie are populated as specified in section 5.2.1. 177262306a36Sopenharmony_ci * 177362306a36Sopenharmony_ci * Verification Tag: Not specified, but an INIT has no way of knowing 177462306a36Sopenharmony_ci * what the verification tag could be, so we ignore it. 177562306a36Sopenharmony_ci * 177662306a36Sopenharmony_ci * Inputs 177762306a36Sopenharmony_ci * (endpoint, asoc, chunk) 177862306a36Sopenharmony_ci * 177962306a36Sopenharmony_ci * Outputs 178062306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 178162306a36Sopenharmony_ci * 178262306a36Sopenharmony_ci * The return value is the disposition of the chunk. 178362306a36Sopenharmony_ci */ 178462306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_2_dupinit( 178562306a36Sopenharmony_ci struct net *net, 178662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 178762306a36Sopenharmony_ci const struct sctp_association *asoc, 178862306a36Sopenharmony_ci const union sctp_subtype type, 178962306a36Sopenharmony_ci void *arg, 179062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 179162306a36Sopenharmony_ci{ 179262306a36Sopenharmony_ci /* Call helper to do the real work for both simultaneous and 179362306a36Sopenharmony_ci * duplicate INIT chunk handling. 179462306a36Sopenharmony_ci */ 179562306a36Sopenharmony_ci return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands); 179662306a36Sopenharmony_ci} 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci/* 180062306a36Sopenharmony_ci * Unexpected INIT-ACK handler. 180162306a36Sopenharmony_ci * 180262306a36Sopenharmony_ci * Section 5.2.3 180362306a36Sopenharmony_ci * If an INIT ACK received by an endpoint in any state other than the 180462306a36Sopenharmony_ci * COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk. 180562306a36Sopenharmony_ci * An unexpected INIT ACK usually indicates the processing of an old or 180662306a36Sopenharmony_ci * duplicated INIT chunk. 180762306a36Sopenharmony_ci*/ 180862306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_3_initack( 180962306a36Sopenharmony_ci struct net *net, 181062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 181162306a36Sopenharmony_ci const struct sctp_association *asoc, 181262306a36Sopenharmony_ci const union sctp_subtype type, 181362306a36Sopenharmony_ci void *arg, 181462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 181562306a36Sopenharmony_ci{ 181662306a36Sopenharmony_ci /* Per the above section, we'll discard the chunk if we have an 181762306a36Sopenharmony_ci * endpoint. If this is an OOTB INIT-ACK, treat it as such. 181862306a36Sopenharmony_ci */ 181962306a36Sopenharmony_ci if (ep == sctp_sk(net->sctp.ctl_sock)->ep) 182062306a36Sopenharmony_ci return sctp_sf_ootb(net, ep, asoc, type, arg, commands); 182162306a36Sopenharmony_ci else 182262306a36Sopenharmony_ci return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); 182362306a36Sopenharmony_ci} 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_cistatic int sctp_sf_do_assoc_update(struct sctp_association *asoc, 182662306a36Sopenharmony_ci struct sctp_association *new, 182762306a36Sopenharmony_ci struct sctp_cmd_seq *cmds) 182862306a36Sopenharmony_ci{ 182962306a36Sopenharmony_ci struct net *net = asoc->base.net; 183062306a36Sopenharmony_ci struct sctp_chunk *abort; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci if (!sctp_assoc_update(asoc, new)) 183362306a36Sopenharmony_ci return 0; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci abort = sctp_make_abort(asoc, NULL, sizeof(struct sctp_errhdr)); 183662306a36Sopenharmony_ci if (abort) { 183762306a36Sopenharmony_ci sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); 183862306a36Sopenharmony_ci sctp_add_cmd_sf(cmds, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 183962306a36Sopenharmony_ci } 184062306a36Sopenharmony_ci sctp_add_cmd_sf(cmds, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED)); 184162306a36Sopenharmony_ci sctp_add_cmd_sf(cmds, SCTP_CMD_ASSOC_FAILED, 184262306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_RSRC_LOW)); 184362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 184462306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci return -ENOMEM; 184762306a36Sopenharmony_ci} 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci/* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A') 185062306a36Sopenharmony_ci * 185162306a36Sopenharmony_ci * Section 5.2.4 185262306a36Sopenharmony_ci * A) In this case, the peer may have restarted. 185362306a36Sopenharmony_ci */ 185462306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_a( 185562306a36Sopenharmony_ci struct net *net, 185662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 185762306a36Sopenharmony_ci const struct sctp_association *asoc, 185862306a36Sopenharmony_ci struct sctp_chunk *chunk, 185962306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 186062306a36Sopenharmony_ci struct sctp_association *new_asoc) 186162306a36Sopenharmony_ci{ 186262306a36Sopenharmony_ci struct sctp_init_chunk *peer_init; 186362306a36Sopenharmony_ci enum sctp_disposition disposition; 186462306a36Sopenharmony_ci struct sctp_ulpevent *ev; 186562306a36Sopenharmony_ci struct sctp_chunk *repl; 186662306a36Sopenharmony_ci struct sctp_chunk *err; 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci /* new_asoc is a brand-new association, so these are not yet 186962306a36Sopenharmony_ci * side effects--it is safe to run them here. 187062306a36Sopenharmony_ci */ 187162306a36Sopenharmony_ci peer_init = (struct sctp_init_chunk *)(chunk->subh.cookie_hdr + 1); 187262306a36Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, 187362306a36Sopenharmony_ci GFP_ATOMIC)) 187462306a36Sopenharmony_ci goto nomem; 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci if (sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC)) 187762306a36Sopenharmony_ci goto nomem; 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) 188062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci /* Make sure no new addresses are being added during the 188362306a36Sopenharmony_ci * restart. Though this is a pretty complicated attack 188462306a36Sopenharmony_ci * since you'd have to get inside the cookie. 188562306a36Sopenharmony_ci */ 188662306a36Sopenharmony_ci if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) 188762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci /* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes 189062306a36Sopenharmony_ci * the peer has restarted (Action A), it MUST NOT setup a new 189162306a36Sopenharmony_ci * association but instead resend the SHUTDOWN ACK and send an ERROR 189262306a36Sopenharmony_ci * chunk with a "Cookie Received while Shutting Down" error cause to 189362306a36Sopenharmony_ci * its peer. 189462306a36Sopenharmony_ci */ 189562306a36Sopenharmony_ci if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) { 189662306a36Sopenharmony_ci disposition = __sctp_sf_do_9_2_reshutack(net, ep, asoc, 189762306a36Sopenharmony_ci SCTP_ST_CHUNK(chunk->chunk_hdr->type), 189862306a36Sopenharmony_ci chunk, commands); 189962306a36Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == disposition) 190062306a36Sopenharmony_ci goto nomem; 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci err = sctp_make_op_error(asoc, chunk, 190362306a36Sopenharmony_ci SCTP_ERROR_COOKIE_IN_SHUTDOWN, 190462306a36Sopenharmony_ci NULL, 0, 0); 190562306a36Sopenharmony_ci if (err) 190662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 190762306a36Sopenharmony_ci SCTP_CHUNK(err)); 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 191062306a36Sopenharmony_ci } 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci /* For now, stop pending T3-rtx and SACK timers, fail any unsent/unacked 191362306a36Sopenharmony_ci * data. Consider the optional choice of resending of this data. 191462306a36Sopenharmony_ci */ 191562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL()); 191662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 191762306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); 191862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci /* Stop pending T4-rto timer, teardown ASCONF queue, ASCONF-ACK queue 192162306a36Sopenharmony_ci * and ASCONF-ACK cache. 192262306a36Sopenharmony_ci */ 192362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 192462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 192562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL()); 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci /* Update the content of current association. */ 192862306a36Sopenharmony_ci if (sctp_sf_do_assoc_update((struct sctp_association *)asoc, new_asoc, commands)) 192962306a36Sopenharmony_ci goto nomem; 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ci repl = sctp_make_cookie_ack(asoc, chunk); 193262306a36Sopenharmony_ci if (!repl) 193362306a36Sopenharmony_ci goto nomem; 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci /* Report association restart to upper layer. */ 193662306a36Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, 193762306a36Sopenharmony_ci asoc->c.sinit_num_ostreams, 193862306a36Sopenharmony_ci asoc->c.sinit_max_instreams, 193962306a36Sopenharmony_ci NULL, GFP_ATOMIC); 194062306a36Sopenharmony_ci if (!ev) 194162306a36Sopenharmony_ci goto nomem_ev; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 194462306a36Sopenharmony_ci if ((sctp_state(asoc, SHUTDOWN_PENDING) || 194562306a36Sopenharmony_ci sctp_state(asoc, SHUTDOWN_SENT)) && 194662306a36Sopenharmony_ci (sctp_sstate(asoc->base.sk, CLOSING) || 194762306a36Sopenharmony_ci sock_flag(asoc->base.sk, SOCK_DEAD))) { 194862306a36Sopenharmony_ci /* If the socket has been closed by user, don't 194962306a36Sopenharmony_ci * transition to ESTABLISHED. Instead trigger SHUTDOWN 195062306a36Sopenharmony_ci * bundled with COOKIE_ACK. 195162306a36Sopenharmony_ci */ 195262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 195362306a36Sopenharmony_ci return sctp_sf_do_9_2_start_shutdown(net, ep, asoc, 195462306a36Sopenharmony_ci SCTP_ST_CHUNK(0), repl, 195562306a36Sopenharmony_ci commands); 195662306a36Sopenharmony_ci } else { 195762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 195862306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 195962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 196062306a36Sopenharmony_ci } 196162306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_cinomem_ev: 196462306a36Sopenharmony_ci sctp_chunk_free(repl); 196562306a36Sopenharmony_cinomem: 196662306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 196762306a36Sopenharmony_ci} 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci/* Unexpected COOKIE-ECHO handler for setup collision (Table 2, action 'B') 197062306a36Sopenharmony_ci * 197162306a36Sopenharmony_ci * Section 5.2.4 197262306a36Sopenharmony_ci * B) In this case, both sides may be attempting to start an association 197362306a36Sopenharmony_ci * at about the same time but the peer endpoint started its INIT 197462306a36Sopenharmony_ci * after responding to the local endpoint's INIT 197562306a36Sopenharmony_ci */ 197662306a36Sopenharmony_ci/* This case represents an initialization collision. */ 197762306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_b( 197862306a36Sopenharmony_ci struct net *net, 197962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 198062306a36Sopenharmony_ci const struct sctp_association *asoc, 198162306a36Sopenharmony_ci struct sctp_chunk *chunk, 198262306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 198362306a36Sopenharmony_ci struct sctp_association *new_asoc) 198462306a36Sopenharmony_ci{ 198562306a36Sopenharmony_ci struct sctp_init_chunk *peer_init; 198662306a36Sopenharmony_ci struct sctp_chunk *repl; 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci /* new_asoc is a brand-new association, so these are not yet 198962306a36Sopenharmony_ci * side effects--it is safe to run them here. 199062306a36Sopenharmony_ci */ 199162306a36Sopenharmony_ci peer_init = (struct sctp_init_chunk *)(chunk->subh.cookie_hdr + 1); 199262306a36Sopenharmony_ci if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, 199362306a36Sopenharmony_ci GFP_ATOMIC)) 199462306a36Sopenharmony_ci goto nomem; 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci if (sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC)) 199762306a36Sopenharmony_ci goto nomem; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) 200062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 200362306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 200462306a36Sopenharmony_ci if (asoc->state < SCTP_STATE_ESTABLISHED) 200562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 200662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci /* Update the content of current association. */ 200962306a36Sopenharmony_ci if (sctp_sf_do_assoc_update((struct sctp_association *)asoc, new_asoc, commands)) 201062306a36Sopenharmony_ci goto nomem; 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci repl = sctp_make_cookie_ack(asoc, chunk); 201362306a36Sopenharmony_ci if (!repl) 201462306a36Sopenharmony_ci goto nomem; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 201962306a36Sopenharmony_ci * 202062306a36Sopenharmony_ci * D) IMPLEMENTATION NOTE: An implementation may choose to 202162306a36Sopenharmony_ci * send the Communication Up notification to the SCTP user 202262306a36Sopenharmony_ci * upon reception of a valid COOKIE ECHO chunk. 202362306a36Sopenharmony_ci * 202462306a36Sopenharmony_ci * Sadly, this needs to be implemented as a side-effect, because 202562306a36Sopenharmony_ci * we are not guaranteed to have set the association id of the real 202662306a36Sopenharmony_ci * association and so these notifications need to be delayed until 202762306a36Sopenharmony_ci * the association id is allocated. 202862306a36Sopenharmony_ci */ 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_CHANGE, SCTP_U8(SCTP_COMM_UP)); 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 203362306a36Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter , SCTP 203462306a36Sopenharmony_ci * delivers this notification to inform the application that of the 203562306a36Sopenharmony_ci * peers requested adaptation layer. 203662306a36Sopenharmony_ci * 203762306a36Sopenharmony_ci * This also needs to be done as a side effect for the same reason as 203862306a36Sopenharmony_ci * above. 203962306a36Sopenharmony_ci */ 204062306a36Sopenharmony_ci if (asoc->peer.adaptation_ind) 204162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL()); 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci if (!asoc->peer.auth_capable) 204462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PEER_NO_AUTH, SCTP_NULL()); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_cinomem: 204962306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 205062306a36Sopenharmony_ci} 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci/* Unexpected COOKIE-ECHO handler for setup collision (Table 2, action 'C') 205362306a36Sopenharmony_ci * 205462306a36Sopenharmony_ci * Section 5.2.4 205562306a36Sopenharmony_ci * C) In this case, the local endpoint's cookie has arrived late. 205662306a36Sopenharmony_ci * Before it arrived, the local endpoint sent an INIT and received an 205762306a36Sopenharmony_ci * INIT-ACK and finally sent a COOKIE ECHO with the peer's same tag 205862306a36Sopenharmony_ci * but a new tag of its own. 205962306a36Sopenharmony_ci */ 206062306a36Sopenharmony_ci/* This case represents an initialization collision. */ 206162306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_c( 206262306a36Sopenharmony_ci struct net *net, 206362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 206462306a36Sopenharmony_ci const struct sctp_association *asoc, 206562306a36Sopenharmony_ci struct sctp_chunk *chunk, 206662306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 206762306a36Sopenharmony_ci struct sctp_association *new_asoc) 206862306a36Sopenharmony_ci{ 206962306a36Sopenharmony_ci /* The cookie should be silently discarded. 207062306a36Sopenharmony_ci * The endpoint SHOULD NOT change states and should leave 207162306a36Sopenharmony_ci * any timers running. 207262306a36Sopenharmony_ci */ 207362306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 207462306a36Sopenharmony_ci} 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci/* Unexpected COOKIE-ECHO handler lost chunk (Table 2, action 'D') 207762306a36Sopenharmony_ci * 207862306a36Sopenharmony_ci * Section 5.2.4 207962306a36Sopenharmony_ci * 208062306a36Sopenharmony_ci * D) When both local and remote tags match the endpoint should always 208162306a36Sopenharmony_ci * enter the ESTABLISHED state, if it has not already done so. 208262306a36Sopenharmony_ci */ 208362306a36Sopenharmony_ci/* This case represents an initialization collision. */ 208462306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_dupcook_d( 208562306a36Sopenharmony_ci struct net *net, 208662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 208762306a36Sopenharmony_ci const struct sctp_association *asoc, 208862306a36Sopenharmony_ci struct sctp_chunk *chunk, 208962306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 209062306a36Sopenharmony_ci struct sctp_association *new_asoc) 209162306a36Sopenharmony_ci{ 209262306a36Sopenharmony_ci struct sctp_ulpevent *ev = NULL, *ai_ev = NULL, *auth_ev = NULL; 209362306a36Sopenharmony_ci struct sctp_chunk *repl; 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci /* Clarification from Implementor's Guide: 209662306a36Sopenharmony_ci * D) When both local and remote tags match the endpoint should 209762306a36Sopenharmony_ci * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state. 209862306a36Sopenharmony_ci * It should stop any cookie timer that may be running and send 209962306a36Sopenharmony_ci * a COOKIE ACK. 210062306a36Sopenharmony_ci */ 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci if (!sctp_auth_chunk_verify(net, chunk, asoc)) 210362306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci /* Don't accidentally move back into established state. */ 210662306a36Sopenharmony_ci if (asoc->state < SCTP_STATE_ESTABLISHED) { 210762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 210862306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 210962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 211062306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_ESTABLISHED)); 211162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); 211262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, 211362306a36Sopenharmony_ci SCTP_NULL()); 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 211662306a36Sopenharmony_ci * 211762306a36Sopenharmony_ci * D) IMPLEMENTATION NOTE: An implementation may choose 211862306a36Sopenharmony_ci * to send the Communication Up notification to the 211962306a36Sopenharmony_ci * SCTP user upon reception of a valid COOKIE 212062306a36Sopenharmony_ci * ECHO chunk. 212162306a36Sopenharmony_ci */ 212262306a36Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, 212362306a36Sopenharmony_ci SCTP_COMM_UP, 0, 212462306a36Sopenharmony_ci asoc->c.sinit_num_ostreams, 212562306a36Sopenharmony_ci asoc->c.sinit_max_instreams, 212662306a36Sopenharmony_ci NULL, GFP_ATOMIC); 212762306a36Sopenharmony_ci if (!ev) 212862306a36Sopenharmony_ci goto nomem; 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci /* Sockets API Draft Section 5.3.1.6 213162306a36Sopenharmony_ci * When a peer sends a Adaptation Layer Indication parameter, 213262306a36Sopenharmony_ci * SCTP delivers this notification to inform the application 213362306a36Sopenharmony_ci * that of the peers requested adaptation layer. 213462306a36Sopenharmony_ci */ 213562306a36Sopenharmony_ci if (asoc->peer.adaptation_ind) { 213662306a36Sopenharmony_ci ai_ev = sctp_ulpevent_make_adaptation_indication(asoc, 213762306a36Sopenharmony_ci GFP_ATOMIC); 213862306a36Sopenharmony_ci if (!ai_ev) 213962306a36Sopenharmony_ci goto nomem; 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci } 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci if (!asoc->peer.auth_capable) { 214462306a36Sopenharmony_ci auth_ev = sctp_ulpevent_make_authkey(asoc, 0, 214562306a36Sopenharmony_ci SCTP_AUTH_NO_AUTH, 214662306a36Sopenharmony_ci GFP_ATOMIC); 214762306a36Sopenharmony_ci if (!auth_ev) 214862306a36Sopenharmony_ci goto nomem; 214962306a36Sopenharmony_ci } 215062306a36Sopenharmony_ci } 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci repl = sctp_make_cookie_ack(asoc, chunk); 215362306a36Sopenharmony_ci if (!repl) 215462306a36Sopenharmony_ci goto nomem; 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci if (ev) 215962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 216062306a36Sopenharmony_ci SCTP_ULPEVENT(ev)); 216162306a36Sopenharmony_ci if (ai_ev) 216262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 216362306a36Sopenharmony_ci SCTP_ULPEVENT(ai_ev)); 216462306a36Sopenharmony_ci if (auth_ev) 216562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 216662306a36Sopenharmony_ci SCTP_ULPEVENT(auth_ev)); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_cinomem: 217162306a36Sopenharmony_ci if (auth_ev) 217262306a36Sopenharmony_ci sctp_ulpevent_free(auth_ev); 217362306a36Sopenharmony_ci if (ai_ev) 217462306a36Sopenharmony_ci sctp_ulpevent_free(ai_ev); 217562306a36Sopenharmony_ci if (ev) 217662306a36Sopenharmony_ci sctp_ulpevent_free(ev); 217762306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 217862306a36Sopenharmony_ci} 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci/* 218162306a36Sopenharmony_ci * Handle a duplicate COOKIE-ECHO. This usually means a cookie-carrying 218262306a36Sopenharmony_ci * chunk was retransmitted and then delayed in the network. 218362306a36Sopenharmony_ci * 218462306a36Sopenharmony_ci * Section: 5.2.4 Handle a COOKIE ECHO when a TCB exists 218562306a36Sopenharmony_ci * 218662306a36Sopenharmony_ci * Verification Tag: None. Do cookie validation. 218762306a36Sopenharmony_ci * 218862306a36Sopenharmony_ci * Inputs 218962306a36Sopenharmony_ci * (endpoint, asoc, chunk) 219062306a36Sopenharmony_ci * 219162306a36Sopenharmony_ci * Outputs 219262306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 219362306a36Sopenharmony_ci * 219462306a36Sopenharmony_ci * The return value is the disposition of the chunk. 219562306a36Sopenharmony_ci */ 219662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_5_2_4_dupcook( 219762306a36Sopenharmony_ci struct net *net, 219862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 219962306a36Sopenharmony_ci const struct sctp_association *asoc, 220062306a36Sopenharmony_ci const union sctp_subtype type, 220162306a36Sopenharmony_ci void *arg, 220262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 220362306a36Sopenharmony_ci{ 220462306a36Sopenharmony_ci struct sctp_association *new_asoc; 220562306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 220662306a36Sopenharmony_ci enum sctp_disposition retval; 220762306a36Sopenharmony_ci struct sctp_chunk *err_chk_p; 220862306a36Sopenharmony_ci int error = 0; 220962306a36Sopenharmony_ci char action; 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci /* Make sure that the chunk has a valid length from the protocol 221262306a36Sopenharmony_ci * perspective. In this case check to make sure we have at least 221362306a36Sopenharmony_ci * enough for the chunk header. Cookie length verification is 221462306a36Sopenharmony_ci * done later. 221562306a36Sopenharmony_ci */ 221662306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) { 221762306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 221862306a36Sopenharmony_ci asoc = NULL; 221962306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, commands); 222062306a36Sopenharmony_ci } 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci /* "Decode" the chunk. We have no optional parameters so we 222362306a36Sopenharmony_ci * are in good shape. 222462306a36Sopenharmony_ci */ 222562306a36Sopenharmony_ci chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; 222662306a36Sopenharmony_ci if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - 222762306a36Sopenharmony_ci sizeof(struct sctp_chunkhdr))) 222862306a36Sopenharmony_ci goto nomem; 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci /* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie 223162306a36Sopenharmony_ci * of a duplicate COOKIE ECHO match the Verification Tags of the 223262306a36Sopenharmony_ci * current association, consider the State Cookie valid even if 223362306a36Sopenharmony_ci * the lifespan is exceeded. 223462306a36Sopenharmony_ci */ 223562306a36Sopenharmony_ci new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error, 223662306a36Sopenharmony_ci &err_chk_p); 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci /* FIXME: 223962306a36Sopenharmony_ci * If the re-build failed, what is the proper error path 224062306a36Sopenharmony_ci * from here? 224162306a36Sopenharmony_ci * 224262306a36Sopenharmony_ci * [We should abort the association. --piggy] 224362306a36Sopenharmony_ci */ 224462306a36Sopenharmony_ci if (!new_asoc) { 224562306a36Sopenharmony_ci /* FIXME: Several errors are possible. A bad cookie should 224662306a36Sopenharmony_ci * be silently discarded, but think about logging it too. 224762306a36Sopenharmony_ci */ 224862306a36Sopenharmony_ci switch (error) { 224962306a36Sopenharmony_ci case -SCTP_IERROR_NOMEM: 225062306a36Sopenharmony_ci goto nomem; 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci case -SCTP_IERROR_STALE_COOKIE: 225362306a36Sopenharmony_ci sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands, 225462306a36Sopenharmony_ci err_chk_p); 225562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 225662306a36Sopenharmony_ci case -SCTP_IERROR_BAD_SIG: 225762306a36Sopenharmony_ci default: 225862306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 225962306a36Sopenharmony_ci } 226062306a36Sopenharmony_ci } 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci /* Update socket peer label if first association. */ 226362306a36Sopenharmony_ci if (security_sctp_assoc_request(new_asoc, chunk->head_skb ?: chunk->skb)) { 226462306a36Sopenharmony_ci sctp_association_free(new_asoc); 226562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 226662306a36Sopenharmony_ci } 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_ci /* Set temp so that it won't be added into hashtable */ 226962306a36Sopenharmony_ci new_asoc->temp = 1; 227062306a36Sopenharmony_ci 227162306a36Sopenharmony_ci /* Compare the tie_tag in cookie with the verification tag of 227262306a36Sopenharmony_ci * current association. 227362306a36Sopenharmony_ci */ 227462306a36Sopenharmony_ci action = sctp_tietags_compare(new_asoc, asoc); 227562306a36Sopenharmony_ci 227662306a36Sopenharmony_ci switch (action) { 227762306a36Sopenharmony_ci case 'A': /* Association restart. */ 227862306a36Sopenharmony_ci retval = sctp_sf_do_dupcook_a(net, ep, asoc, chunk, commands, 227962306a36Sopenharmony_ci new_asoc); 228062306a36Sopenharmony_ci break; 228162306a36Sopenharmony_ci 228262306a36Sopenharmony_ci case 'B': /* Collision case B. */ 228362306a36Sopenharmony_ci retval = sctp_sf_do_dupcook_b(net, ep, asoc, chunk, commands, 228462306a36Sopenharmony_ci new_asoc); 228562306a36Sopenharmony_ci break; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci case 'C': /* Collision case C. */ 228862306a36Sopenharmony_ci retval = sctp_sf_do_dupcook_c(net, ep, asoc, chunk, commands, 228962306a36Sopenharmony_ci new_asoc); 229062306a36Sopenharmony_ci break; 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_ci case 'D': /* Collision case D. */ 229362306a36Sopenharmony_ci retval = sctp_sf_do_dupcook_d(net, ep, asoc, chunk, commands, 229462306a36Sopenharmony_ci new_asoc); 229562306a36Sopenharmony_ci break; 229662306a36Sopenharmony_ci 229762306a36Sopenharmony_ci default: /* Discard packet for all others. */ 229862306a36Sopenharmony_ci retval = sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 229962306a36Sopenharmony_ci break; 230062306a36Sopenharmony_ci } 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci /* Delete the temporary new association. */ 230362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc)); 230462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_ci /* Restore association pointer to provide SCTP command interpreter 230762306a36Sopenharmony_ci * with a valid context in case it needs to manipulate 230862306a36Sopenharmony_ci * the queues */ 230962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, 231062306a36Sopenharmony_ci SCTP_ASOC((struct sctp_association *)asoc)); 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci return retval; 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_cinomem: 231562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 231662306a36Sopenharmony_ci} 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_ci/* 231962306a36Sopenharmony_ci * Process an ABORT. (SHUTDOWN-PENDING state) 232062306a36Sopenharmony_ci * 232162306a36Sopenharmony_ci * See sctp_sf_do_9_1_abort(). 232262306a36Sopenharmony_ci */ 232362306a36Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_pending_abort( 232462306a36Sopenharmony_ci struct net *net, 232562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 232662306a36Sopenharmony_ci const struct sctp_association *asoc, 232762306a36Sopenharmony_ci const union sctp_subtype type, 232862306a36Sopenharmony_ci void *arg, 232962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 233062306a36Sopenharmony_ci{ 233162306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 233262306a36Sopenharmony_ci 233362306a36Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 233462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 233762306a36Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 233862306a36Sopenharmony_ci * because of the following text: 233962306a36Sopenharmony_ci * RFC 2960, Section 3.3.7 234062306a36Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 234162306a36Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 234262306a36Sopenharmony_ci * Because the length is "invalid", we can't really discard just 234362306a36Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 234462306a36Sopenharmony_ci * packet. 234562306a36Sopenharmony_ci */ 234662306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 234762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 234862306a36Sopenharmony_ci 234962306a36Sopenharmony_ci /* ADD-IP: Special case for ABORT chunks 235062306a36Sopenharmony_ci * F4) One special consideration is that ABORT Chunks arriving 235162306a36Sopenharmony_ci * destined to the IP address being deleted MUST be 235262306a36Sopenharmony_ci * ignored (see Section 5.3.1 for further details). 235362306a36Sopenharmony_ci */ 235462306a36Sopenharmony_ci if (SCTP_ADDR_DEL == 235562306a36Sopenharmony_ci sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) 235662306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci if (!sctp_err_chunk_valid(chunk)) 235962306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); 236262306a36Sopenharmony_ci} 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci/* 236562306a36Sopenharmony_ci * Process an ABORT. (SHUTDOWN-SENT state) 236662306a36Sopenharmony_ci * 236762306a36Sopenharmony_ci * See sctp_sf_do_9_1_abort(). 236862306a36Sopenharmony_ci */ 236962306a36Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_sent_abort( 237062306a36Sopenharmony_ci struct net *net, 237162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 237262306a36Sopenharmony_ci const struct sctp_association *asoc, 237362306a36Sopenharmony_ci const union sctp_subtype type, 237462306a36Sopenharmony_ci void *arg, 237562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 237662306a36Sopenharmony_ci{ 237762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 238062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 238362306a36Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 238462306a36Sopenharmony_ci * because of the following text: 238562306a36Sopenharmony_ci * RFC 2960, Section 3.3.7 238662306a36Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 238762306a36Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 238862306a36Sopenharmony_ci * Because the length is "invalid", we can't really discard just 238962306a36Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 239062306a36Sopenharmony_ci * packet. 239162306a36Sopenharmony_ci */ 239262306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 239362306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 239462306a36Sopenharmony_ci 239562306a36Sopenharmony_ci /* ADD-IP: Special case for ABORT chunks 239662306a36Sopenharmony_ci * F4) One special consideration is that ABORT Chunks arriving 239762306a36Sopenharmony_ci * destined to the IP address being deleted MUST be 239862306a36Sopenharmony_ci * ignored (see Section 5.3.1 for further details). 239962306a36Sopenharmony_ci */ 240062306a36Sopenharmony_ci if (SCTP_ADDR_DEL == 240162306a36Sopenharmony_ci sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) 240262306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_ci if (!sctp_err_chunk_valid(chunk)) 240562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci /* Stop the T2-shutdown timer. */ 240862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 240962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci /* Stop the T5-shutdown guard timer. */ 241262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 241362306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 241462306a36Sopenharmony_ci 241562306a36Sopenharmony_ci return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); 241662306a36Sopenharmony_ci} 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci/* 241962306a36Sopenharmony_ci * Process an ABORT. (SHUTDOWN-ACK-SENT state) 242062306a36Sopenharmony_ci * 242162306a36Sopenharmony_ci * See sctp_sf_do_9_1_abort(). 242262306a36Sopenharmony_ci */ 242362306a36Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_ack_sent_abort( 242462306a36Sopenharmony_ci struct net *net, 242562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 242662306a36Sopenharmony_ci const struct sctp_association *asoc, 242762306a36Sopenharmony_ci const union sctp_subtype type, 242862306a36Sopenharmony_ci void *arg, 242962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 243062306a36Sopenharmony_ci{ 243162306a36Sopenharmony_ci /* The same T2 timer, so we should be able to use 243262306a36Sopenharmony_ci * common function with the SHUTDOWN-SENT state. 243362306a36Sopenharmony_ci */ 243462306a36Sopenharmony_ci return sctp_sf_shutdown_sent_abort(net, ep, asoc, type, arg, commands); 243562306a36Sopenharmony_ci} 243662306a36Sopenharmony_ci 243762306a36Sopenharmony_ci/* 243862306a36Sopenharmony_ci * Handle an Error received in COOKIE_ECHOED state. 243962306a36Sopenharmony_ci * 244062306a36Sopenharmony_ci * Only handle the error type of stale COOKIE Error, the other errors will 244162306a36Sopenharmony_ci * be ignored. 244262306a36Sopenharmony_ci * 244362306a36Sopenharmony_ci * Inputs 244462306a36Sopenharmony_ci * (endpoint, asoc, chunk) 244562306a36Sopenharmony_ci * 244662306a36Sopenharmony_ci * Outputs 244762306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 244862306a36Sopenharmony_ci * 244962306a36Sopenharmony_ci * The return value is the disposition of the chunk. 245062306a36Sopenharmony_ci */ 245162306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_err( 245262306a36Sopenharmony_ci struct net *net, 245362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 245462306a36Sopenharmony_ci const struct sctp_association *asoc, 245562306a36Sopenharmony_ci const union sctp_subtype type, 245662306a36Sopenharmony_ci void *arg, 245762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 245862306a36Sopenharmony_ci{ 245962306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 246062306a36Sopenharmony_ci struct sctp_errhdr *err; 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 246362306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci /* Make sure that the ERROR chunk has a valid length. 246662306a36Sopenharmony_ci * The parameter walking depends on this as well. 246762306a36Sopenharmony_ci */ 246862306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_operr_chunk))) 246962306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 247062306a36Sopenharmony_ci commands); 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci /* Process the error here */ 247362306a36Sopenharmony_ci /* FUTURE FIXME: When PR-SCTP related and other optional 247462306a36Sopenharmony_ci * parms are emitted, this will have to change to handle multiple 247562306a36Sopenharmony_ci * errors. 247662306a36Sopenharmony_ci */ 247762306a36Sopenharmony_ci sctp_walk_errors(err, chunk->chunk_hdr) { 247862306a36Sopenharmony_ci if (SCTP_ERROR_STALE_COOKIE == err->cause) 247962306a36Sopenharmony_ci return sctp_sf_do_5_2_6_stale(net, ep, asoc, type, 248062306a36Sopenharmony_ci arg, commands); 248162306a36Sopenharmony_ci } 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci /* It is possible to have malformed error causes, and that 248462306a36Sopenharmony_ci * will cause us to end the walk early. However, since 248562306a36Sopenharmony_ci * we are discarding the packet, there should be no adverse 248662306a36Sopenharmony_ci * affects. 248762306a36Sopenharmony_ci */ 248862306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 248962306a36Sopenharmony_ci} 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci/* 249262306a36Sopenharmony_ci * Handle a Stale COOKIE Error 249362306a36Sopenharmony_ci * 249462306a36Sopenharmony_ci * Section: 5.2.6 Handle Stale COOKIE Error 249562306a36Sopenharmony_ci * If the association is in the COOKIE-ECHOED state, the endpoint may elect 249662306a36Sopenharmony_ci * one of the following three alternatives. 249762306a36Sopenharmony_ci * ... 249862306a36Sopenharmony_ci * 3) Send a new INIT chunk to the endpoint, adding a Cookie 249962306a36Sopenharmony_ci * Preservative parameter requesting an extension to the lifetime of 250062306a36Sopenharmony_ci * the State Cookie. When calculating the time extension, an 250162306a36Sopenharmony_ci * implementation SHOULD use the RTT information measured based on the 250262306a36Sopenharmony_ci * previous COOKIE ECHO / ERROR exchange, and should add no more 250362306a36Sopenharmony_ci * than 1 second beyond the measured RTT, due to long State Cookie 250462306a36Sopenharmony_ci * lifetimes making the endpoint more subject to a replay attack. 250562306a36Sopenharmony_ci * 250662306a36Sopenharmony_ci * Verification Tag: Not explicit, but safe to ignore. 250762306a36Sopenharmony_ci * 250862306a36Sopenharmony_ci * Inputs 250962306a36Sopenharmony_ci * (endpoint, asoc, chunk) 251062306a36Sopenharmony_ci * 251162306a36Sopenharmony_ci * Outputs 251262306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 251362306a36Sopenharmony_ci * 251462306a36Sopenharmony_ci * The return value is the disposition of the chunk. 251562306a36Sopenharmony_ci */ 251662306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_do_5_2_6_stale( 251762306a36Sopenharmony_ci struct net *net, 251862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 251962306a36Sopenharmony_ci const struct sctp_association *asoc, 252062306a36Sopenharmony_ci const union sctp_subtype type, 252162306a36Sopenharmony_ci void *arg, 252262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 252362306a36Sopenharmony_ci{ 252462306a36Sopenharmony_ci int attempts = asoc->init_err_counter + 1; 252562306a36Sopenharmony_ci struct sctp_chunk *chunk = arg, *reply; 252662306a36Sopenharmony_ci struct sctp_cookie_preserve_param bht; 252762306a36Sopenharmony_ci struct sctp_bind_addr *bp; 252862306a36Sopenharmony_ci struct sctp_errhdr *err; 252962306a36Sopenharmony_ci u32 stale; 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_ci if (attempts > asoc->max_init_attempts) { 253262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 253362306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 253462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 253562306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_STALE_COOKIE)); 253662306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 253762306a36Sopenharmony_ci } 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci err = (struct sctp_errhdr *)(chunk->skb->data); 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci /* When calculating the time extension, an implementation 254262306a36Sopenharmony_ci * SHOULD use the RTT information measured based on the 254362306a36Sopenharmony_ci * previous COOKIE ECHO / ERROR exchange, and should add no 254462306a36Sopenharmony_ci * more than 1 second beyond the measured RTT, due to long 254562306a36Sopenharmony_ci * State Cookie lifetimes making the endpoint more subject to 254662306a36Sopenharmony_ci * a replay attack. 254762306a36Sopenharmony_ci * Measure of Staleness's unit is usec. (1/1000000 sec) 254862306a36Sopenharmony_ci * Suggested Cookie Life-span Increment's unit is msec. 254962306a36Sopenharmony_ci * (1/1000 sec) 255062306a36Sopenharmony_ci * In general, if you use the suggested cookie life, the value 255162306a36Sopenharmony_ci * found in the field of measure of staleness should be doubled 255262306a36Sopenharmony_ci * to give ample time to retransmit the new cookie and thus 255362306a36Sopenharmony_ci * yield a higher probability of success on the reattempt. 255462306a36Sopenharmony_ci */ 255562306a36Sopenharmony_ci stale = ntohl(*(__be32 *)((u8 *)err + sizeof(*err))); 255662306a36Sopenharmony_ci stale = (stale * 2) / 1000; 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE; 255962306a36Sopenharmony_ci bht.param_hdr.length = htons(sizeof(bht)); 256062306a36Sopenharmony_ci bht.lifespan_increment = htonl(stale); 256162306a36Sopenharmony_ci 256262306a36Sopenharmony_ci /* Build that new INIT chunk. */ 256362306a36Sopenharmony_ci bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; 256462306a36Sopenharmony_ci reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht)); 256562306a36Sopenharmony_ci if (!reply) 256662306a36Sopenharmony_ci goto nomem; 256762306a36Sopenharmony_ci 256862306a36Sopenharmony_ci sctp_addto_chunk(reply, sizeof(bht), &bht); 256962306a36Sopenharmony_ci 257062306a36Sopenharmony_ci /* Clear peer's init_tag cached in assoc as we are sending a new INIT */ 257162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL()); 257262306a36Sopenharmony_ci 257362306a36Sopenharmony_ci /* Stop pending T3-rtx and heartbeat timers */ 257462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL()); 257562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); 257662306a36Sopenharmony_ci 257762306a36Sopenharmony_ci /* Delete non-primary peer ip addresses since we are transitioning 257862306a36Sopenharmony_ci * back to the COOKIE-WAIT state 257962306a36Sopenharmony_ci */ 258062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL()); 258162306a36Sopenharmony_ci 258262306a36Sopenharmony_ci /* If we've sent any data bundled with COOKIE-ECHO we will need to 258362306a36Sopenharmony_ci * resend 258462306a36Sopenharmony_ci */ 258562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN, 258662306a36Sopenharmony_ci SCTP_TRANSPORT(asoc->peer.primary_path)); 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci /* Cast away the const modifier, as we want to just 258962306a36Sopenharmony_ci * rerun it through as a sideffect. 259062306a36Sopenharmony_ci */ 259162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL()); 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 259462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 259562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 259662306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_COOKIE_WAIT)); 259762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 259862306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 260162306a36Sopenharmony_ci 260262306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_cinomem: 260562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 260662306a36Sopenharmony_ci} 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci/* 260962306a36Sopenharmony_ci * Process an ABORT. 261062306a36Sopenharmony_ci * 261162306a36Sopenharmony_ci * Section: 9.1 261262306a36Sopenharmony_ci * After checking the Verification Tag, the receiving endpoint shall 261362306a36Sopenharmony_ci * remove the association from its record, and shall report the 261462306a36Sopenharmony_ci * termination to its upper layer. 261562306a36Sopenharmony_ci * 261662306a36Sopenharmony_ci * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules 261762306a36Sopenharmony_ci * B) Rules for packet carrying ABORT: 261862306a36Sopenharmony_ci * 261962306a36Sopenharmony_ci * - The endpoint shall always fill in the Verification Tag field of the 262062306a36Sopenharmony_ci * outbound packet with the destination endpoint's tag value if it 262162306a36Sopenharmony_ci * is known. 262262306a36Sopenharmony_ci * 262362306a36Sopenharmony_ci * - If the ABORT is sent in response to an OOTB packet, the endpoint 262462306a36Sopenharmony_ci * MUST follow the procedure described in Section 8.4. 262562306a36Sopenharmony_ci * 262662306a36Sopenharmony_ci * - The receiver MUST accept the packet if the Verification Tag 262762306a36Sopenharmony_ci * matches either its own tag, OR the tag of its peer. Otherwise, the 262862306a36Sopenharmony_ci * receiver MUST silently discard the packet and take no further 262962306a36Sopenharmony_ci * action. 263062306a36Sopenharmony_ci * 263162306a36Sopenharmony_ci * Inputs 263262306a36Sopenharmony_ci * (endpoint, asoc, chunk) 263362306a36Sopenharmony_ci * 263462306a36Sopenharmony_ci * Outputs 263562306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 263662306a36Sopenharmony_ci * 263762306a36Sopenharmony_ci * The return value is the disposition of the chunk. 263862306a36Sopenharmony_ci */ 263962306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_1_abort( 264062306a36Sopenharmony_ci struct net *net, 264162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 264262306a36Sopenharmony_ci const struct sctp_association *asoc, 264362306a36Sopenharmony_ci const union sctp_subtype type, 264462306a36Sopenharmony_ci void *arg, 264562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 264662306a36Sopenharmony_ci{ 264762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 264862306a36Sopenharmony_ci 264962306a36Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 265062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 265162306a36Sopenharmony_ci 265262306a36Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 265362306a36Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 265462306a36Sopenharmony_ci * because of the following text: 265562306a36Sopenharmony_ci * RFC 2960, Section 3.3.7 265662306a36Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 265762306a36Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 265862306a36Sopenharmony_ci * Because the length is "invalid", we can't really discard just 265962306a36Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 266062306a36Sopenharmony_ci * packet. 266162306a36Sopenharmony_ci */ 266262306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 266362306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_ci /* ADD-IP: Special case for ABORT chunks 266662306a36Sopenharmony_ci * F4) One special consideration is that ABORT Chunks arriving 266762306a36Sopenharmony_ci * destined to the IP address being deleted MUST be 266862306a36Sopenharmony_ci * ignored (see Section 5.3.1 for further details). 266962306a36Sopenharmony_ci */ 267062306a36Sopenharmony_ci if (SCTP_ADDR_DEL == 267162306a36Sopenharmony_ci sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) 267262306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci if (!sctp_err_chunk_valid(chunk)) 267562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); 267862306a36Sopenharmony_ci} 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_cistatic enum sctp_disposition __sctp_sf_do_9_1_abort( 268162306a36Sopenharmony_ci struct net *net, 268262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 268362306a36Sopenharmony_ci const struct sctp_association *asoc, 268462306a36Sopenharmony_ci const union sctp_subtype type, 268562306a36Sopenharmony_ci void *arg, 268662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 268762306a36Sopenharmony_ci{ 268862306a36Sopenharmony_ci __be16 error = SCTP_ERROR_NO_ERROR; 268962306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 269062306a36Sopenharmony_ci unsigned int len; 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci /* See if we have an error cause code in the chunk. */ 269362306a36Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 269462306a36Sopenharmony_ci if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) 269562306a36Sopenharmony_ci error = ((struct sctp_errhdr *)chunk->skb->data)->cause; 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); 269862306a36Sopenharmony_ci /* ASSOC_FAILED will DELETE_TCB. */ 269962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error)); 270062306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 270162306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 270262306a36Sopenharmony_ci 270362306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 270462306a36Sopenharmony_ci} 270562306a36Sopenharmony_ci 270662306a36Sopenharmony_ci/* 270762306a36Sopenharmony_ci * Process an ABORT. (COOKIE-WAIT state) 270862306a36Sopenharmony_ci * 270962306a36Sopenharmony_ci * See sctp_sf_do_9_1_abort() above. 271062306a36Sopenharmony_ci */ 271162306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_abort( 271262306a36Sopenharmony_ci struct net *net, 271362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 271462306a36Sopenharmony_ci const struct sctp_association *asoc, 271562306a36Sopenharmony_ci const union sctp_subtype type, 271662306a36Sopenharmony_ci void *arg, 271762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 271862306a36Sopenharmony_ci{ 271962306a36Sopenharmony_ci __be16 error = SCTP_ERROR_NO_ERROR; 272062306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 272162306a36Sopenharmony_ci unsigned int len; 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_ci if (!sctp_vtag_verify_either(chunk, asoc)) 272462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci /* Make sure that the ABORT chunk has a valid length. 272762306a36Sopenharmony_ci * Since this is an ABORT chunk, we have to discard it 272862306a36Sopenharmony_ci * because of the following text: 272962306a36Sopenharmony_ci * RFC 2960, Section 3.3.7 273062306a36Sopenharmony_ci * If an endpoint receives an ABORT with a format error or for an 273162306a36Sopenharmony_ci * association that doesn't exist, it MUST silently discard it. 273262306a36Sopenharmony_ci * Because the length is "invalid", we can't really discard just 273362306a36Sopenharmony_ci * as we do not know its true length. So, to be safe, discard the 273462306a36Sopenharmony_ci * packet. 273562306a36Sopenharmony_ci */ 273662306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_abort_chunk))) 273762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 273862306a36Sopenharmony_ci 273962306a36Sopenharmony_ci /* See if we have an error cause code in the chunk. */ 274062306a36Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 274162306a36Sopenharmony_ci if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) 274262306a36Sopenharmony_ci error = ((struct sctp_errhdr *)chunk->skb->data)->cause; 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_ci return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, asoc, 274562306a36Sopenharmony_ci chunk->transport); 274662306a36Sopenharmony_ci} 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci/* 274962306a36Sopenharmony_ci * Process an incoming ICMP as an ABORT. (COOKIE-WAIT state) 275062306a36Sopenharmony_ci */ 275162306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_icmp_abort( 275262306a36Sopenharmony_ci struct net *net, 275362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 275462306a36Sopenharmony_ci const struct sctp_association *asoc, 275562306a36Sopenharmony_ci const union sctp_subtype type, 275662306a36Sopenharmony_ci void *arg, 275762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 275862306a36Sopenharmony_ci{ 275962306a36Sopenharmony_ci return sctp_stop_t1_and_abort(net, commands, SCTP_ERROR_NO_ERROR, 276062306a36Sopenharmony_ci ENOPROTOOPT, asoc, 276162306a36Sopenharmony_ci (struct sctp_transport *)arg); 276262306a36Sopenharmony_ci} 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci/* 276562306a36Sopenharmony_ci * Process an ABORT. (COOKIE-ECHOED state) 276662306a36Sopenharmony_ci */ 276762306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_abort( 276862306a36Sopenharmony_ci struct net *net, 276962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 277062306a36Sopenharmony_ci const struct sctp_association *asoc, 277162306a36Sopenharmony_ci const union sctp_subtype type, 277262306a36Sopenharmony_ci void *arg, 277362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 277462306a36Sopenharmony_ci{ 277562306a36Sopenharmony_ci /* There is a single T1 timer, so we should be able to use 277662306a36Sopenharmony_ci * common function with the COOKIE-WAIT state. 277762306a36Sopenharmony_ci */ 277862306a36Sopenharmony_ci return sctp_sf_cookie_wait_abort(net, ep, asoc, type, arg, commands); 277962306a36Sopenharmony_ci} 278062306a36Sopenharmony_ci 278162306a36Sopenharmony_ci/* 278262306a36Sopenharmony_ci * Stop T1 timer and abort association with "INIT failed". 278362306a36Sopenharmony_ci * 278462306a36Sopenharmony_ci * This is common code called by several sctp_sf_*_abort() functions above. 278562306a36Sopenharmony_ci */ 278662306a36Sopenharmony_cistatic enum sctp_disposition sctp_stop_t1_and_abort( 278762306a36Sopenharmony_ci struct net *net, 278862306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 278962306a36Sopenharmony_ci __be16 error, int sk_err, 279062306a36Sopenharmony_ci const struct sctp_association *asoc, 279162306a36Sopenharmony_ci struct sctp_transport *transport) 279262306a36Sopenharmony_ci{ 279362306a36Sopenharmony_ci pr_debug("%s: ABORT received (INIT)\n", __func__); 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 279662306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 279762306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 279862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 279962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 280062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); 280162306a36Sopenharmony_ci /* CMD_INIT_FAILED will DELETE_TCB. */ 280262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 280362306a36Sopenharmony_ci SCTP_PERR(error)); 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 280662306a36Sopenharmony_ci} 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci/* 280962306a36Sopenharmony_ci * sctp_sf_do_9_2_shut 281062306a36Sopenharmony_ci * 281162306a36Sopenharmony_ci * Section: 9.2 281262306a36Sopenharmony_ci * Upon the reception of the SHUTDOWN, the peer endpoint shall 281362306a36Sopenharmony_ci * - enter the SHUTDOWN-RECEIVED state, 281462306a36Sopenharmony_ci * 281562306a36Sopenharmony_ci * - stop accepting new data from its SCTP user 281662306a36Sopenharmony_ci * 281762306a36Sopenharmony_ci * - verify, by checking the Cumulative TSN Ack field of the chunk, 281862306a36Sopenharmony_ci * that all its outstanding DATA chunks have been received by the 281962306a36Sopenharmony_ci * SHUTDOWN sender. 282062306a36Sopenharmony_ci * 282162306a36Sopenharmony_ci * Once an endpoint as reached the SHUTDOWN-RECEIVED state it MUST NOT 282262306a36Sopenharmony_ci * send a SHUTDOWN in response to a ULP request. And should discard 282362306a36Sopenharmony_ci * subsequent SHUTDOWN chunks. 282462306a36Sopenharmony_ci * 282562306a36Sopenharmony_ci * If there are still outstanding DATA chunks left, the SHUTDOWN 282662306a36Sopenharmony_ci * receiver shall continue to follow normal data transmission 282762306a36Sopenharmony_ci * procedures defined in Section 6 until all outstanding DATA chunks 282862306a36Sopenharmony_ci * are acknowledged; however, the SHUTDOWN receiver MUST NOT accept 282962306a36Sopenharmony_ci * new data from its SCTP user. 283062306a36Sopenharmony_ci * 283162306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 283262306a36Sopenharmony_ci * 283362306a36Sopenharmony_ci * Inputs 283462306a36Sopenharmony_ci * (endpoint, asoc, chunk) 283562306a36Sopenharmony_ci * 283662306a36Sopenharmony_ci * Outputs 283762306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 283862306a36Sopenharmony_ci * 283962306a36Sopenharmony_ci * The return value is the disposition of the chunk. 284062306a36Sopenharmony_ci */ 284162306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_shutdown( 284262306a36Sopenharmony_ci struct net *net, 284362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 284462306a36Sopenharmony_ci const struct sctp_association *asoc, 284562306a36Sopenharmony_ci const union sctp_subtype type, 284662306a36Sopenharmony_ci void *arg, 284762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 284862306a36Sopenharmony_ci{ 284962306a36Sopenharmony_ci enum sctp_disposition disposition; 285062306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 285162306a36Sopenharmony_ci struct sctp_shutdownhdr *sdh; 285262306a36Sopenharmony_ci struct sctp_ulpevent *ev; 285362306a36Sopenharmony_ci __u32 ctsn; 285462306a36Sopenharmony_ci 285562306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 285662306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci /* Make sure that the SHUTDOWN chunk has a valid length. */ 285962306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk))) 286062306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 286162306a36Sopenharmony_ci commands); 286262306a36Sopenharmony_ci 286362306a36Sopenharmony_ci /* Convert the elaborate header. */ 286462306a36Sopenharmony_ci sdh = (struct sctp_shutdownhdr *)chunk->skb->data; 286562306a36Sopenharmony_ci skb_pull(chunk->skb, sizeof(*sdh)); 286662306a36Sopenharmony_ci chunk->subh.shutdown_hdr = sdh; 286762306a36Sopenharmony_ci ctsn = ntohl(sdh->cum_tsn_ack); 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_ci if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { 287062306a36Sopenharmony_ci pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, 287162306a36Sopenharmony_ci asoc->ctsn_ack_point); 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 287462306a36Sopenharmony_ci } 287562306a36Sopenharmony_ci 287662306a36Sopenharmony_ci /* If Cumulative TSN Ack beyond the max tsn currently 287762306a36Sopenharmony_ci * send, terminating the association and respond to the 287862306a36Sopenharmony_ci * sender with an ABORT. 287962306a36Sopenharmony_ci */ 288062306a36Sopenharmony_ci if (!TSN_lt(ctsn, asoc->next_tsn)) 288162306a36Sopenharmony_ci return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 288262306a36Sopenharmony_ci 288362306a36Sopenharmony_ci /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT 288462306a36Sopenharmony_ci * When a peer sends a SHUTDOWN, SCTP delivers this notification to 288562306a36Sopenharmony_ci * inform the application that it should cease sending data. 288662306a36Sopenharmony_ci */ 288762306a36Sopenharmony_ci ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC); 288862306a36Sopenharmony_ci if (!ev) { 288962306a36Sopenharmony_ci disposition = SCTP_DISPOSITION_NOMEM; 289062306a36Sopenharmony_ci goto out; 289162306a36Sopenharmony_ci } 289262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 289362306a36Sopenharmony_ci 289462306a36Sopenharmony_ci /* Upon the reception of the SHUTDOWN, the peer endpoint shall 289562306a36Sopenharmony_ci * - enter the SHUTDOWN-RECEIVED state, 289662306a36Sopenharmony_ci * - stop accepting new data from its SCTP user 289762306a36Sopenharmony_ci * 289862306a36Sopenharmony_ci * [This is implicit in the new state.] 289962306a36Sopenharmony_ci */ 290062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 290162306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_RECEIVED)); 290262306a36Sopenharmony_ci disposition = SCTP_DISPOSITION_CONSUME; 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_ci if (sctp_outq_is_empty(&asoc->outqueue)) { 290562306a36Sopenharmony_ci disposition = sctp_sf_do_9_2_shutdown_ack(net, ep, asoc, type, 290662306a36Sopenharmony_ci arg, commands); 290762306a36Sopenharmony_ci } 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == disposition) 291062306a36Sopenharmony_ci goto out; 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci /* - verify, by checking the Cumulative TSN Ack field of the 291362306a36Sopenharmony_ci * chunk, that all its outstanding DATA chunks have been 291462306a36Sopenharmony_ci * received by the SHUTDOWN sender. 291562306a36Sopenharmony_ci */ 291662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, 291762306a36Sopenharmony_ci SCTP_BE32(chunk->subh.shutdown_hdr->cum_tsn_ack)); 291862306a36Sopenharmony_ci 291962306a36Sopenharmony_ciout: 292062306a36Sopenharmony_ci return disposition; 292162306a36Sopenharmony_ci} 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci/* 292462306a36Sopenharmony_ci * sctp_sf_do_9_2_shut_ctsn 292562306a36Sopenharmony_ci * 292662306a36Sopenharmony_ci * Once an endpoint has reached the SHUTDOWN-RECEIVED state, 292762306a36Sopenharmony_ci * it MUST NOT send a SHUTDOWN in response to a ULP request. 292862306a36Sopenharmony_ci * The Cumulative TSN Ack of the received SHUTDOWN chunk 292962306a36Sopenharmony_ci * MUST be processed. 293062306a36Sopenharmony_ci */ 293162306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_shut_ctsn( 293262306a36Sopenharmony_ci struct net *net, 293362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 293462306a36Sopenharmony_ci const struct sctp_association *asoc, 293562306a36Sopenharmony_ci const union sctp_subtype type, 293662306a36Sopenharmony_ci void *arg, 293762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 293862306a36Sopenharmony_ci{ 293962306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 294062306a36Sopenharmony_ci struct sctp_shutdownhdr *sdh; 294162306a36Sopenharmony_ci __u32 ctsn; 294262306a36Sopenharmony_ci 294362306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 294462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci /* Make sure that the SHUTDOWN chunk has a valid length. */ 294762306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk))) 294862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 294962306a36Sopenharmony_ci commands); 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_ci sdh = (struct sctp_shutdownhdr *)chunk->skb->data; 295262306a36Sopenharmony_ci ctsn = ntohl(sdh->cum_tsn_ack); 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_ci if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { 295562306a36Sopenharmony_ci pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, 295662306a36Sopenharmony_ci asoc->ctsn_ack_point); 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 295962306a36Sopenharmony_ci } 296062306a36Sopenharmony_ci 296162306a36Sopenharmony_ci /* If Cumulative TSN Ack beyond the max tsn currently 296262306a36Sopenharmony_ci * send, terminating the association and respond to the 296362306a36Sopenharmony_ci * sender with an ABORT. 296462306a36Sopenharmony_ci */ 296562306a36Sopenharmony_ci if (!TSN_lt(ctsn, asoc->next_tsn)) 296662306a36Sopenharmony_ci return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 296762306a36Sopenharmony_ci 296862306a36Sopenharmony_ci /* verify, by checking the Cumulative TSN Ack field of the 296962306a36Sopenharmony_ci * chunk, that all its outstanding DATA chunks have been 297062306a36Sopenharmony_ci * received by the SHUTDOWN sender. 297162306a36Sopenharmony_ci */ 297262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, 297362306a36Sopenharmony_ci SCTP_BE32(sdh->cum_tsn_ack)); 297462306a36Sopenharmony_ci 297562306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 297662306a36Sopenharmony_ci} 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_ci/* RFC 2960 9.2 297962306a36Sopenharmony_ci * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk 298062306a36Sopenharmony_ci * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination 298162306a36Sopenharmony_ci * transport addresses (either in the IP addresses or in the INIT chunk) 298262306a36Sopenharmony_ci * that belong to this association, it should discard the INIT chunk and 298362306a36Sopenharmony_ci * retransmit the SHUTDOWN ACK chunk. 298462306a36Sopenharmony_ci */ 298562306a36Sopenharmony_cistatic enum sctp_disposition 298662306a36Sopenharmony_ci__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, 298762306a36Sopenharmony_ci const struct sctp_association *asoc, 298862306a36Sopenharmony_ci const union sctp_subtype type, void *arg, 298962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 299062306a36Sopenharmony_ci{ 299162306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 299262306a36Sopenharmony_ci struct sctp_chunk *reply; 299362306a36Sopenharmony_ci 299462306a36Sopenharmony_ci /* Make sure that the chunk has a valid length */ 299562306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 299662306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 299762306a36Sopenharmony_ci commands); 299862306a36Sopenharmony_ci 299962306a36Sopenharmony_ci /* Since we are not going to really process this INIT, there 300062306a36Sopenharmony_ci * is no point in verifying chunk boundaries. Just generate 300162306a36Sopenharmony_ci * the SHUTDOWN ACK. 300262306a36Sopenharmony_ci */ 300362306a36Sopenharmony_ci reply = sctp_make_shutdown_ack(asoc, chunk); 300462306a36Sopenharmony_ci if (NULL == reply) 300562306a36Sopenharmony_ci goto nomem; 300662306a36Sopenharmony_ci 300762306a36Sopenharmony_ci /* Set the transport for the SHUTDOWN ACK chunk and the timeout for 300862306a36Sopenharmony_ci * the T2-SHUTDOWN timer. 300962306a36Sopenharmony_ci */ 301062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 301162306a36Sopenharmony_ci 301262306a36Sopenharmony_ci /* and restart the T2-shutdown timer. */ 301362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 301462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 301562306a36Sopenharmony_ci 301662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 301962306a36Sopenharmony_cinomem: 302062306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 302162306a36Sopenharmony_ci} 302262306a36Sopenharmony_ci 302362306a36Sopenharmony_cienum sctp_disposition 302462306a36Sopenharmony_cisctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, 302562306a36Sopenharmony_ci const struct sctp_association *asoc, 302662306a36Sopenharmony_ci const union sctp_subtype type, void *arg, 302762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 302862306a36Sopenharmony_ci{ 302962306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 303062306a36Sopenharmony_ci 303162306a36Sopenharmony_ci if (!chunk->singleton) 303262306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) 303562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 303662306a36Sopenharmony_ci 303762306a36Sopenharmony_ci if (chunk->sctp_hdr->vtag != 0) 303862306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 303962306a36Sopenharmony_ci 304062306a36Sopenharmony_ci return __sctp_sf_do_9_2_reshutack(net, ep, asoc, type, arg, commands); 304162306a36Sopenharmony_ci} 304262306a36Sopenharmony_ci 304362306a36Sopenharmony_ci/* 304462306a36Sopenharmony_ci * sctp_sf_do_ecn_cwr 304562306a36Sopenharmony_ci * 304662306a36Sopenharmony_ci * Section: Appendix A: Explicit Congestion Notification 304762306a36Sopenharmony_ci * 304862306a36Sopenharmony_ci * CWR: 304962306a36Sopenharmony_ci * 305062306a36Sopenharmony_ci * RFC 2481 details a specific bit for a sender to send in the header of 305162306a36Sopenharmony_ci * its next outbound TCP segment to indicate to its peer that it has 305262306a36Sopenharmony_ci * reduced its congestion window. This is termed the CWR bit. For 305362306a36Sopenharmony_ci * SCTP the same indication is made by including the CWR chunk. 305462306a36Sopenharmony_ci * This chunk contains one data element, i.e. the TSN number that 305562306a36Sopenharmony_ci * was sent in the ECNE chunk. This element represents the lowest 305662306a36Sopenharmony_ci * TSN number in the datagram that was originally marked with the 305762306a36Sopenharmony_ci * CE bit. 305862306a36Sopenharmony_ci * 305962306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 306062306a36Sopenharmony_ci * Inputs 306162306a36Sopenharmony_ci * (endpoint, asoc, chunk) 306262306a36Sopenharmony_ci * 306362306a36Sopenharmony_ci * Outputs 306462306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 306562306a36Sopenharmony_ci * 306662306a36Sopenharmony_ci * The return value is the disposition of the chunk. 306762306a36Sopenharmony_ci */ 306862306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_ecn_cwr(struct net *net, 306962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 307062306a36Sopenharmony_ci const struct sctp_association *asoc, 307162306a36Sopenharmony_ci const union sctp_subtype type, 307262306a36Sopenharmony_ci void *arg, 307362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 307462306a36Sopenharmony_ci{ 307562306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 307662306a36Sopenharmony_ci struct sctp_cwrhdr *cwr; 307762306a36Sopenharmony_ci u32 lowest_tsn; 307862306a36Sopenharmony_ci 307962306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 308062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 308162306a36Sopenharmony_ci 308262306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_ecne_chunk))) 308362306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 308462306a36Sopenharmony_ci commands); 308562306a36Sopenharmony_ci 308662306a36Sopenharmony_ci cwr = (struct sctp_cwrhdr *)chunk->skb->data; 308762306a36Sopenharmony_ci skb_pull(chunk->skb, sizeof(*cwr)); 308862306a36Sopenharmony_ci 308962306a36Sopenharmony_ci lowest_tsn = ntohl(cwr->lowest_tsn); 309062306a36Sopenharmony_ci 309162306a36Sopenharmony_ci /* Does this CWR ack the last sent congestion notification? */ 309262306a36Sopenharmony_ci if (TSN_lte(asoc->last_ecne_tsn, lowest_tsn)) { 309362306a36Sopenharmony_ci /* Stop sending ECNE. */ 309462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, 309562306a36Sopenharmony_ci SCTP_CMD_ECN_CWR, 309662306a36Sopenharmony_ci SCTP_U32(lowest_tsn)); 309762306a36Sopenharmony_ci } 309862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 309962306a36Sopenharmony_ci} 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_ci/* 310262306a36Sopenharmony_ci * sctp_sf_do_ecne 310362306a36Sopenharmony_ci * 310462306a36Sopenharmony_ci * Section: Appendix A: Explicit Congestion Notification 310562306a36Sopenharmony_ci * 310662306a36Sopenharmony_ci * ECN-Echo 310762306a36Sopenharmony_ci * 310862306a36Sopenharmony_ci * RFC 2481 details a specific bit for a receiver to send back in its 310962306a36Sopenharmony_ci * TCP acknowledgements to notify the sender of the Congestion 311062306a36Sopenharmony_ci * Experienced (CE) bit having arrived from the network. For SCTP this 311162306a36Sopenharmony_ci * same indication is made by including the ECNE chunk. This chunk 311262306a36Sopenharmony_ci * contains one data element, i.e. the lowest TSN associated with the IP 311362306a36Sopenharmony_ci * datagram marked with the CE bit..... 311462306a36Sopenharmony_ci * 311562306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 311662306a36Sopenharmony_ci * Inputs 311762306a36Sopenharmony_ci * (endpoint, asoc, chunk) 311862306a36Sopenharmony_ci * 311962306a36Sopenharmony_ci * Outputs 312062306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 312162306a36Sopenharmony_ci * 312262306a36Sopenharmony_ci * The return value is the disposition of the chunk. 312362306a36Sopenharmony_ci */ 312462306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_ecne(struct net *net, 312562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 312662306a36Sopenharmony_ci const struct sctp_association *asoc, 312762306a36Sopenharmony_ci const union sctp_subtype type, 312862306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 312962306a36Sopenharmony_ci{ 313062306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 313162306a36Sopenharmony_ci struct sctp_ecnehdr *ecne; 313262306a36Sopenharmony_ci 313362306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 313462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 313562306a36Sopenharmony_ci 313662306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_ecne_chunk))) 313762306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 313862306a36Sopenharmony_ci commands); 313962306a36Sopenharmony_ci 314062306a36Sopenharmony_ci ecne = (struct sctp_ecnehdr *)chunk->skb->data; 314162306a36Sopenharmony_ci skb_pull(chunk->skb, sizeof(*ecne)); 314262306a36Sopenharmony_ci 314362306a36Sopenharmony_ci /* If this is a newer ECNE than the last CWR packet we sent out */ 314462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ECN_ECNE, 314562306a36Sopenharmony_ci SCTP_U32(ntohl(ecne->lowest_tsn))); 314662306a36Sopenharmony_ci 314762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 314862306a36Sopenharmony_ci} 314962306a36Sopenharmony_ci 315062306a36Sopenharmony_ci/* 315162306a36Sopenharmony_ci * Section: 6.2 Acknowledgement on Reception of DATA Chunks 315262306a36Sopenharmony_ci * 315362306a36Sopenharmony_ci * The SCTP endpoint MUST always acknowledge the reception of each valid 315462306a36Sopenharmony_ci * DATA chunk. 315562306a36Sopenharmony_ci * 315662306a36Sopenharmony_ci * The guidelines on delayed acknowledgement algorithm specified in 315762306a36Sopenharmony_ci * Section 4.2 of [RFC2581] SHOULD be followed. Specifically, an 315862306a36Sopenharmony_ci * acknowledgement SHOULD be generated for at least every second packet 315962306a36Sopenharmony_ci * (not every second DATA chunk) received, and SHOULD be generated within 316062306a36Sopenharmony_ci * 200 ms of the arrival of any unacknowledged DATA chunk. In some 316162306a36Sopenharmony_ci * situations it may be beneficial for an SCTP transmitter to be more 316262306a36Sopenharmony_ci * conservative than the algorithms detailed in this document allow. 316362306a36Sopenharmony_ci * However, an SCTP transmitter MUST NOT be more aggressive than the 316462306a36Sopenharmony_ci * following algorithms allow. 316562306a36Sopenharmony_ci * 316662306a36Sopenharmony_ci * A SCTP receiver MUST NOT generate more than one SACK for every 316762306a36Sopenharmony_ci * incoming packet, other than to update the offered window as the 316862306a36Sopenharmony_ci * receiving application consumes new data. 316962306a36Sopenharmony_ci * 317062306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 317162306a36Sopenharmony_ci * 317262306a36Sopenharmony_ci * Inputs 317362306a36Sopenharmony_ci * (endpoint, asoc, chunk) 317462306a36Sopenharmony_ci * 317562306a36Sopenharmony_ci * Outputs 317662306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 317762306a36Sopenharmony_ci * 317862306a36Sopenharmony_ci * The return value is the disposition of the chunk. 317962306a36Sopenharmony_ci */ 318062306a36Sopenharmony_cienum sctp_disposition sctp_sf_eat_data_6_2(struct net *net, 318162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 318262306a36Sopenharmony_ci const struct sctp_association *asoc, 318362306a36Sopenharmony_ci const union sctp_subtype type, 318462306a36Sopenharmony_ci void *arg, 318562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 318662306a36Sopenharmony_ci{ 318762306a36Sopenharmony_ci union sctp_arg force = SCTP_NOFORCE(); 318862306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 318962306a36Sopenharmony_ci int error; 319062306a36Sopenharmony_ci 319162306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 319262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 319362306a36Sopenharmony_ci SCTP_NULL()); 319462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 319562306a36Sopenharmony_ci } 319662306a36Sopenharmony_ci 319762306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_datachk_len(&asoc->stream))) 319862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 319962306a36Sopenharmony_ci commands); 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci error = sctp_eat_data(asoc, chunk, commands); 320262306a36Sopenharmony_ci switch (error) { 320362306a36Sopenharmony_ci case SCTP_IERROR_NO_ERROR: 320462306a36Sopenharmony_ci break; 320562306a36Sopenharmony_ci case SCTP_IERROR_HIGH_TSN: 320662306a36Sopenharmony_ci case SCTP_IERROR_BAD_STREAM: 320762306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); 320862306a36Sopenharmony_ci goto discard_noforce; 320962306a36Sopenharmony_ci case SCTP_IERROR_DUP_TSN: 321062306a36Sopenharmony_ci case SCTP_IERROR_IGNORE_TSN: 321162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); 321262306a36Sopenharmony_ci goto discard_force; 321362306a36Sopenharmony_ci case SCTP_IERROR_NO_DATA: 321462306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 321562306a36Sopenharmony_ci case SCTP_IERROR_PROTO_VIOLATION: 321662306a36Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, 321762306a36Sopenharmony_ci (u8 *)chunk->subh.data_hdr, 321862306a36Sopenharmony_ci sctp_datahdr_len(&asoc->stream)); 321962306a36Sopenharmony_ci default: 322062306a36Sopenharmony_ci BUG(); 322162306a36Sopenharmony_ci } 322262306a36Sopenharmony_ci 322362306a36Sopenharmony_ci if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) 322462306a36Sopenharmony_ci force = SCTP_FORCE(); 322562306a36Sopenharmony_ci 322662306a36Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { 322762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 322862306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 322962306a36Sopenharmony_ci } 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci /* If this is the last chunk in a packet, we need to count it 323262306a36Sopenharmony_ci * toward sack generation. Note that we need to SACK every 323362306a36Sopenharmony_ci * OTHER packet containing data chunks, EVEN IF WE DISCARD 323462306a36Sopenharmony_ci * THEM. We elect to NOT generate SACK's if the chunk fails 323562306a36Sopenharmony_ci * the verification tag test. 323662306a36Sopenharmony_ci * 323762306a36Sopenharmony_ci * RFC 2960 6.2 Acknowledgement on Reception of DATA Chunks 323862306a36Sopenharmony_ci * 323962306a36Sopenharmony_ci * The SCTP endpoint MUST always acknowledge the reception of 324062306a36Sopenharmony_ci * each valid DATA chunk. 324162306a36Sopenharmony_ci * 324262306a36Sopenharmony_ci * The guidelines on delayed acknowledgement algorithm 324362306a36Sopenharmony_ci * specified in Section 4.2 of [RFC2581] SHOULD be followed. 324462306a36Sopenharmony_ci * Specifically, an acknowledgement SHOULD be generated for at 324562306a36Sopenharmony_ci * least every second packet (not every second DATA chunk) 324662306a36Sopenharmony_ci * received, and SHOULD be generated within 200 ms of the 324762306a36Sopenharmony_ci * arrival of any unacknowledged DATA chunk. In some 324862306a36Sopenharmony_ci * situations it may be beneficial for an SCTP transmitter to 324962306a36Sopenharmony_ci * be more conservative than the algorithms detailed in this 325062306a36Sopenharmony_ci * document allow. However, an SCTP transmitter MUST NOT be 325162306a36Sopenharmony_ci * more aggressive than the following algorithms allow. 325262306a36Sopenharmony_ci */ 325362306a36Sopenharmony_ci if (chunk->end_of_packet) 325462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); 325562306a36Sopenharmony_ci 325662306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_cidiscard_force: 325962306a36Sopenharmony_ci /* RFC 2960 6.2 Acknowledgement on Reception of DATA Chunks 326062306a36Sopenharmony_ci * 326162306a36Sopenharmony_ci * When a packet arrives with duplicate DATA chunk(s) and with 326262306a36Sopenharmony_ci * no new DATA chunk(s), the endpoint MUST immediately send a 326362306a36Sopenharmony_ci * SACK with no delay. If a packet arrives with duplicate 326462306a36Sopenharmony_ci * DATA chunk(s) bundled with new DATA chunks, the endpoint 326562306a36Sopenharmony_ci * MAY immediately send a SACK. Normally receipt of duplicate 326662306a36Sopenharmony_ci * DATA chunks will occur when the original SACK chunk was lost 326762306a36Sopenharmony_ci * and the peer's RTO has expired. The duplicate TSN number(s) 326862306a36Sopenharmony_ci * SHOULD be reported in the SACK as duplicate. 326962306a36Sopenharmony_ci */ 327062306a36Sopenharmony_ci /* In our case, we split the MAY SACK advice up whether or not 327162306a36Sopenharmony_ci * the last chunk is a duplicate.' 327262306a36Sopenharmony_ci */ 327362306a36Sopenharmony_ci if (chunk->end_of_packet) 327462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 327562306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 327662306a36Sopenharmony_ci 327762306a36Sopenharmony_cidiscard_noforce: 327862306a36Sopenharmony_ci if (chunk->end_of_packet) 327962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); 328062306a36Sopenharmony_ci 328162306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 328262306a36Sopenharmony_ci} 328362306a36Sopenharmony_ci 328462306a36Sopenharmony_ci/* 328562306a36Sopenharmony_ci * sctp_sf_eat_data_fast_4_4 328662306a36Sopenharmony_ci * 328762306a36Sopenharmony_ci * Section: 4 (4) 328862306a36Sopenharmony_ci * (4) In SHUTDOWN-SENT state the endpoint MUST acknowledge any received 328962306a36Sopenharmony_ci * DATA chunks without delay. 329062306a36Sopenharmony_ci * 329162306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 329262306a36Sopenharmony_ci * Inputs 329362306a36Sopenharmony_ci * (endpoint, asoc, chunk) 329462306a36Sopenharmony_ci * 329562306a36Sopenharmony_ci * Outputs 329662306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 329762306a36Sopenharmony_ci * 329862306a36Sopenharmony_ci * The return value is the disposition of the chunk. 329962306a36Sopenharmony_ci */ 330062306a36Sopenharmony_cienum sctp_disposition sctp_sf_eat_data_fast_4_4( 330162306a36Sopenharmony_ci struct net *net, 330262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 330362306a36Sopenharmony_ci const struct sctp_association *asoc, 330462306a36Sopenharmony_ci const union sctp_subtype type, 330562306a36Sopenharmony_ci void *arg, 330662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 330762306a36Sopenharmony_ci{ 330862306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 330962306a36Sopenharmony_ci int error; 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 331262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 331362306a36Sopenharmony_ci SCTP_NULL()); 331462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 331562306a36Sopenharmony_ci } 331662306a36Sopenharmony_ci 331762306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_datachk_len(&asoc->stream))) 331862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 331962306a36Sopenharmony_ci commands); 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_ci error = sctp_eat_data(asoc, chunk, commands); 332262306a36Sopenharmony_ci switch (error) { 332362306a36Sopenharmony_ci case SCTP_IERROR_NO_ERROR: 332462306a36Sopenharmony_ci case SCTP_IERROR_HIGH_TSN: 332562306a36Sopenharmony_ci case SCTP_IERROR_DUP_TSN: 332662306a36Sopenharmony_ci case SCTP_IERROR_IGNORE_TSN: 332762306a36Sopenharmony_ci case SCTP_IERROR_BAD_STREAM: 332862306a36Sopenharmony_ci break; 332962306a36Sopenharmony_ci case SCTP_IERROR_NO_DATA: 333062306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 333162306a36Sopenharmony_ci case SCTP_IERROR_PROTO_VIOLATION: 333262306a36Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, 333362306a36Sopenharmony_ci (u8 *)chunk->subh.data_hdr, 333462306a36Sopenharmony_ci sctp_datahdr_len(&asoc->stream)); 333562306a36Sopenharmony_ci default: 333662306a36Sopenharmony_ci BUG(); 333762306a36Sopenharmony_ci } 333862306a36Sopenharmony_ci 333962306a36Sopenharmony_ci /* Go a head and force a SACK, since we are shutting down. */ 334062306a36Sopenharmony_ci 334162306a36Sopenharmony_ci /* Implementor's Guide. 334262306a36Sopenharmony_ci * 334362306a36Sopenharmony_ci * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately 334462306a36Sopenharmony_ci * respond to each received packet containing one or more DATA chunk(s) 334562306a36Sopenharmony_ci * with a SACK, a SHUTDOWN chunk, and restart the T2-shutdown timer 334662306a36Sopenharmony_ci */ 334762306a36Sopenharmony_ci if (chunk->end_of_packet) { 334862306a36Sopenharmony_ci /* We must delay the chunk creation since the cumulative 334962306a36Sopenharmony_ci * TSN has not been updated yet. 335062306a36Sopenharmony_ci */ 335162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SHUTDOWN, SCTP_NULL()); 335262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 335362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 335462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 335562306a36Sopenharmony_ci } 335662306a36Sopenharmony_ci 335762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 335862306a36Sopenharmony_ci} 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci/* 336162306a36Sopenharmony_ci * Section: 6.2 Processing a Received SACK 336262306a36Sopenharmony_ci * D) Any time a SACK arrives, the endpoint performs the following: 336362306a36Sopenharmony_ci * 336462306a36Sopenharmony_ci * i) If Cumulative TSN Ack is less than the Cumulative TSN Ack Point, 336562306a36Sopenharmony_ci * then drop the SACK. Since Cumulative TSN Ack is monotonically 336662306a36Sopenharmony_ci * increasing, a SACK whose Cumulative TSN Ack is less than the 336762306a36Sopenharmony_ci * Cumulative TSN Ack Point indicates an out-of-order SACK. 336862306a36Sopenharmony_ci * 336962306a36Sopenharmony_ci * ii) Set rwnd equal to the newly received a_rwnd minus the number 337062306a36Sopenharmony_ci * of bytes still outstanding after processing the Cumulative TSN Ack 337162306a36Sopenharmony_ci * and the Gap Ack Blocks. 337262306a36Sopenharmony_ci * 337362306a36Sopenharmony_ci * iii) If the SACK is missing a TSN that was previously 337462306a36Sopenharmony_ci * acknowledged via a Gap Ack Block (e.g., the data receiver 337562306a36Sopenharmony_ci * reneged on the data), then mark the corresponding DATA chunk 337662306a36Sopenharmony_ci * as available for retransmit: Mark it as missing for fast 337762306a36Sopenharmony_ci * retransmit as described in Section 7.2.4 and if no retransmit 337862306a36Sopenharmony_ci * timer is running for the destination address to which the DATA 337962306a36Sopenharmony_ci * chunk was originally transmitted, then T3-rtx is started for 338062306a36Sopenharmony_ci * that destination address. 338162306a36Sopenharmony_ci * 338262306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 338362306a36Sopenharmony_ci * 338462306a36Sopenharmony_ci * Inputs 338562306a36Sopenharmony_ci * (endpoint, asoc, chunk) 338662306a36Sopenharmony_ci * 338762306a36Sopenharmony_ci * Outputs 338862306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 338962306a36Sopenharmony_ci * 339062306a36Sopenharmony_ci * The return value is the disposition of the chunk. 339162306a36Sopenharmony_ci */ 339262306a36Sopenharmony_cienum sctp_disposition sctp_sf_eat_sack_6_2(struct net *net, 339362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 339462306a36Sopenharmony_ci const struct sctp_association *asoc, 339562306a36Sopenharmony_ci const union sctp_subtype type, 339662306a36Sopenharmony_ci void *arg, 339762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 339862306a36Sopenharmony_ci{ 339962306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 340062306a36Sopenharmony_ci struct sctp_sackhdr *sackh; 340162306a36Sopenharmony_ci __u32 ctsn; 340262306a36Sopenharmony_ci 340362306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 340462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 340562306a36Sopenharmony_ci 340662306a36Sopenharmony_ci /* Make sure that the SACK chunk has a valid length. */ 340762306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_sack_chunk))) 340862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 340962306a36Sopenharmony_ci commands); 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ci /* Pull the SACK chunk from the data buffer */ 341262306a36Sopenharmony_ci sackh = sctp_sm_pull_sack(chunk); 341362306a36Sopenharmony_ci /* Was this a bogus SACK? */ 341462306a36Sopenharmony_ci if (!sackh) 341562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 341662306a36Sopenharmony_ci chunk->subh.sack_hdr = sackh; 341762306a36Sopenharmony_ci ctsn = ntohl(sackh->cum_tsn_ack); 341862306a36Sopenharmony_ci 341962306a36Sopenharmony_ci /* If Cumulative TSN Ack beyond the max tsn currently 342062306a36Sopenharmony_ci * send, terminating the association and respond to the 342162306a36Sopenharmony_ci * sender with an ABORT. 342262306a36Sopenharmony_ci */ 342362306a36Sopenharmony_ci if (TSN_lte(asoc->next_tsn, ctsn)) 342462306a36Sopenharmony_ci return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 342562306a36Sopenharmony_ci 342662306a36Sopenharmony_ci trace_sctp_probe(ep, asoc, chunk); 342762306a36Sopenharmony_ci 342862306a36Sopenharmony_ci /* i) If Cumulative TSN Ack is less than the Cumulative TSN 342962306a36Sopenharmony_ci * Ack Point, then drop the SACK. Since Cumulative TSN 343062306a36Sopenharmony_ci * Ack is monotonically increasing, a SACK whose 343162306a36Sopenharmony_ci * Cumulative TSN Ack is less than the Cumulative TSN Ack 343262306a36Sopenharmony_ci * Point indicates an out-of-order SACK. 343362306a36Sopenharmony_ci */ 343462306a36Sopenharmony_ci if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { 343562306a36Sopenharmony_ci pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, 343662306a36Sopenharmony_ci asoc->ctsn_ack_point); 343762306a36Sopenharmony_ci 343862306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 343962306a36Sopenharmony_ci } 344062306a36Sopenharmony_ci 344162306a36Sopenharmony_ci /* Return this SACK for further processing. */ 344262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk)); 344362306a36Sopenharmony_ci 344462306a36Sopenharmony_ci /* Note: We do the rest of the work on the PROCESS_SACK 344562306a36Sopenharmony_ci * sideeffect. 344662306a36Sopenharmony_ci */ 344762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 344862306a36Sopenharmony_ci} 344962306a36Sopenharmony_ci 345062306a36Sopenharmony_ci/* 345162306a36Sopenharmony_ci * Generate an ABORT in response to a packet. 345262306a36Sopenharmony_ci * 345362306a36Sopenharmony_ci * Section: 8.4 Handle "Out of the blue" Packets, sctpimpguide 2.41 345462306a36Sopenharmony_ci * 345562306a36Sopenharmony_ci * 8) The receiver should respond to the sender of the OOTB packet with 345662306a36Sopenharmony_ci * an ABORT. When sending the ABORT, the receiver of the OOTB packet 345762306a36Sopenharmony_ci * MUST fill in the Verification Tag field of the outbound packet 345862306a36Sopenharmony_ci * with the value found in the Verification Tag field of the OOTB 345962306a36Sopenharmony_ci * packet and set the T-bit in the Chunk Flags to indicate that the 346062306a36Sopenharmony_ci * Verification Tag is reflected. After sending this ABORT, the 346162306a36Sopenharmony_ci * receiver of the OOTB packet shall discard the OOTB packet and take 346262306a36Sopenharmony_ci * no further action. 346362306a36Sopenharmony_ci * 346462306a36Sopenharmony_ci * Verification Tag: 346562306a36Sopenharmony_ci * 346662306a36Sopenharmony_ci * The return value is the disposition of the chunk. 346762306a36Sopenharmony_ci*/ 346862306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_tabort_8_4_8( 346962306a36Sopenharmony_ci struct net *net, 347062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 347162306a36Sopenharmony_ci const struct sctp_association *asoc, 347262306a36Sopenharmony_ci const union sctp_subtype type, 347362306a36Sopenharmony_ci void *arg, 347462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 347562306a36Sopenharmony_ci{ 347662306a36Sopenharmony_ci struct sctp_packet *packet = NULL; 347762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 347862306a36Sopenharmony_ci struct sctp_chunk *abort; 347962306a36Sopenharmony_ci 348062306a36Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 348162306a36Sopenharmony_ci if (!packet) 348262306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 348362306a36Sopenharmony_ci 348462306a36Sopenharmony_ci /* Make an ABORT. The T bit will be set if the asoc 348562306a36Sopenharmony_ci * is NULL. 348662306a36Sopenharmony_ci */ 348762306a36Sopenharmony_ci abort = sctp_make_abort(asoc, chunk, 0); 348862306a36Sopenharmony_ci if (!abort) { 348962306a36Sopenharmony_ci sctp_ootb_pkt_free(packet); 349062306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 349162306a36Sopenharmony_ci } 349262306a36Sopenharmony_ci 349362306a36Sopenharmony_ci /* Reflect vtag if T-Bit is set */ 349462306a36Sopenharmony_ci if (sctp_test_T_bit(abort)) 349562306a36Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 349662306a36Sopenharmony_ci 349762306a36Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 349862306a36Sopenharmony_ci abort->skb->sk = ep->base.sk; 349962306a36Sopenharmony_ci 350062306a36Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 350162306a36Sopenharmony_ci 350262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(packet)); 350362306a36Sopenharmony_ci 350462306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 350562306a36Sopenharmony_ci 350662306a36Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 350762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 350862306a36Sopenharmony_ci} 350962306a36Sopenharmony_ci 351062306a36Sopenharmony_ci/* Handling of SCTP Packets Containing an INIT Chunk Matching an 351162306a36Sopenharmony_ci * Existing Associations when the UDP encap port is incorrect. 351262306a36Sopenharmony_ci * 351362306a36Sopenharmony_ci * From Section 4 at draft-tuexen-tsvwg-sctp-udp-encaps-cons-03. 351462306a36Sopenharmony_ci */ 351562306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_new_encap_port( 351662306a36Sopenharmony_ci struct net *net, 351762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 351862306a36Sopenharmony_ci const struct sctp_association *asoc, 351962306a36Sopenharmony_ci const union sctp_subtype type, 352062306a36Sopenharmony_ci void *arg, 352162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 352262306a36Sopenharmony_ci{ 352362306a36Sopenharmony_ci struct sctp_packet *packet = NULL; 352462306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 352562306a36Sopenharmony_ci struct sctp_chunk *abort; 352662306a36Sopenharmony_ci 352762306a36Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 352862306a36Sopenharmony_ci if (!packet) 352962306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 353062306a36Sopenharmony_ci 353162306a36Sopenharmony_ci abort = sctp_make_new_encap_port(asoc, chunk); 353262306a36Sopenharmony_ci if (!abort) { 353362306a36Sopenharmony_ci sctp_ootb_pkt_free(packet); 353462306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 353562306a36Sopenharmony_ci } 353662306a36Sopenharmony_ci 353762306a36Sopenharmony_ci abort->skb->sk = ep->base.sk; 353862306a36Sopenharmony_ci 353962306a36Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 354062306a36Sopenharmony_ci 354162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 354262306a36Sopenharmony_ci SCTP_PACKET(packet)); 354362306a36Sopenharmony_ci 354462306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 354562306a36Sopenharmony_ci 354662306a36Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 354762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 354862306a36Sopenharmony_ci} 354962306a36Sopenharmony_ci 355062306a36Sopenharmony_ci/* 355162306a36Sopenharmony_ci * Received an ERROR chunk from peer. Generate SCTP_REMOTE_ERROR 355262306a36Sopenharmony_ci * event as ULP notification for each cause included in the chunk. 355362306a36Sopenharmony_ci * 355462306a36Sopenharmony_ci * API 5.3.1.3 - SCTP_REMOTE_ERROR 355562306a36Sopenharmony_ci * 355662306a36Sopenharmony_ci * The return value is the disposition of the chunk. 355762306a36Sopenharmony_ci*/ 355862306a36Sopenharmony_cienum sctp_disposition sctp_sf_operr_notify(struct net *net, 355962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 356062306a36Sopenharmony_ci const struct sctp_association *asoc, 356162306a36Sopenharmony_ci const union sctp_subtype type, 356262306a36Sopenharmony_ci void *arg, 356362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 356462306a36Sopenharmony_ci{ 356562306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 356662306a36Sopenharmony_ci struct sctp_errhdr *err; 356762306a36Sopenharmony_ci 356862306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 356962306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 357062306a36Sopenharmony_ci 357162306a36Sopenharmony_ci /* Make sure that the ERROR chunk has a valid length. */ 357262306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_operr_chunk))) 357362306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 357462306a36Sopenharmony_ci commands); 357562306a36Sopenharmony_ci sctp_walk_errors(err, chunk->chunk_hdr); 357662306a36Sopenharmony_ci if ((void *)err != (void *)chunk->chunk_end) 357762306a36Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 357862306a36Sopenharmony_ci (void *)err, commands); 357962306a36Sopenharmony_ci 358062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, 358162306a36Sopenharmony_ci SCTP_CHUNK(chunk)); 358262306a36Sopenharmony_ci 358362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 358462306a36Sopenharmony_ci} 358562306a36Sopenharmony_ci 358662306a36Sopenharmony_ci/* 358762306a36Sopenharmony_ci * Process an inbound SHUTDOWN ACK. 358862306a36Sopenharmony_ci * 358962306a36Sopenharmony_ci * From Section 9.2: 359062306a36Sopenharmony_ci * Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall 359162306a36Sopenharmony_ci * stop the T2-shutdown timer, send a SHUTDOWN COMPLETE chunk to its 359262306a36Sopenharmony_ci * peer, and remove all record of the association. 359362306a36Sopenharmony_ci * 359462306a36Sopenharmony_ci * The return value is the disposition. 359562306a36Sopenharmony_ci */ 359662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_final(struct net *net, 359762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 359862306a36Sopenharmony_ci const struct sctp_association *asoc, 359962306a36Sopenharmony_ci const union sctp_subtype type, 360062306a36Sopenharmony_ci void *arg, 360162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 360262306a36Sopenharmony_ci{ 360362306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 360462306a36Sopenharmony_ci struct sctp_chunk *reply; 360562306a36Sopenharmony_ci struct sctp_ulpevent *ev; 360662306a36Sopenharmony_ci 360762306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 360862306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 360962306a36Sopenharmony_ci 361062306a36Sopenharmony_ci /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ 361162306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 361262306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 361362306a36Sopenharmony_ci commands); 361462306a36Sopenharmony_ci /* 10.2 H) SHUTDOWN COMPLETE notification 361562306a36Sopenharmony_ci * 361662306a36Sopenharmony_ci * When SCTP completes the shutdown procedures (section 9.2) this 361762306a36Sopenharmony_ci * notification is passed to the upper layer. 361862306a36Sopenharmony_ci */ 361962306a36Sopenharmony_ci ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, 362062306a36Sopenharmony_ci 0, 0, 0, NULL, GFP_ATOMIC); 362162306a36Sopenharmony_ci if (!ev) 362262306a36Sopenharmony_ci goto nomem; 362362306a36Sopenharmony_ci 362462306a36Sopenharmony_ci /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ 362562306a36Sopenharmony_ci reply = sctp_make_shutdown_complete(asoc, chunk); 362662306a36Sopenharmony_ci if (!reply) 362762306a36Sopenharmony_ci goto nomem_chunk; 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_ci /* Do all the commands now (after allocation), so that we 363062306a36Sopenharmony_ci * have consistent state if memory allocation fails 363162306a36Sopenharmony_ci */ 363262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_ci /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall 363562306a36Sopenharmony_ci * stop the T2-shutdown timer, 363662306a36Sopenharmony_ci */ 363762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 363862306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 363962306a36Sopenharmony_ci 364062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 364162306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 364262306a36Sopenharmony_ci 364362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 364462306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 364562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); 364662306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 364762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 364862306a36Sopenharmony_ci 364962306a36Sopenharmony_ci /* ...and remove all record of the association. */ 365062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 365162306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 365262306a36Sopenharmony_ci 365362306a36Sopenharmony_cinomem_chunk: 365462306a36Sopenharmony_ci sctp_ulpevent_free(ev); 365562306a36Sopenharmony_cinomem: 365662306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 365762306a36Sopenharmony_ci} 365862306a36Sopenharmony_ci 365962306a36Sopenharmony_ci/* 366062306a36Sopenharmony_ci * RFC 2960, 8.4 - Handle "Out of the blue" Packets, sctpimpguide 2.41. 366162306a36Sopenharmony_ci * 366262306a36Sopenharmony_ci * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should 366362306a36Sopenharmony_ci * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. 366462306a36Sopenharmony_ci * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB 366562306a36Sopenharmony_ci * packet must fill in the Verification Tag field of the outbound 366662306a36Sopenharmony_ci * packet with the Verification Tag received in the SHUTDOWN ACK and 366762306a36Sopenharmony_ci * set the T-bit in the Chunk Flags to indicate that the Verification 366862306a36Sopenharmony_ci * Tag is reflected. 366962306a36Sopenharmony_ci * 367062306a36Sopenharmony_ci * 8) The receiver should respond to the sender of the OOTB packet with 367162306a36Sopenharmony_ci * an ABORT. When sending the ABORT, the receiver of the OOTB packet 367262306a36Sopenharmony_ci * MUST fill in the Verification Tag field of the outbound packet 367362306a36Sopenharmony_ci * with the value found in the Verification Tag field of the OOTB 367462306a36Sopenharmony_ci * packet and set the T-bit in the Chunk Flags to indicate that the 367562306a36Sopenharmony_ci * Verification Tag is reflected. After sending this ABORT, the 367662306a36Sopenharmony_ci * receiver of the OOTB packet shall discard the OOTB packet and take 367762306a36Sopenharmony_ci * no further action. 367862306a36Sopenharmony_ci */ 367962306a36Sopenharmony_cienum sctp_disposition sctp_sf_ootb(struct net *net, 368062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 368162306a36Sopenharmony_ci const struct sctp_association *asoc, 368262306a36Sopenharmony_ci const union sctp_subtype type, 368362306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 368462306a36Sopenharmony_ci{ 368562306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 368662306a36Sopenharmony_ci struct sk_buff *skb = chunk->skb; 368762306a36Sopenharmony_ci struct sctp_chunkhdr *ch; 368862306a36Sopenharmony_ci struct sctp_errhdr *err; 368962306a36Sopenharmony_ci int ootb_cookie_ack = 0; 369062306a36Sopenharmony_ci int ootb_shut_ack = 0; 369162306a36Sopenharmony_ci __u8 *ch_end; 369262306a36Sopenharmony_ci 369362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 369462306a36Sopenharmony_ci 369562306a36Sopenharmony_ci if (asoc && !sctp_vtag_verify(chunk, asoc)) 369662306a36Sopenharmony_ci asoc = NULL; 369762306a36Sopenharmony_ci 369862306a36Sopenharmony_ci ch = (struct sctp_chunkhdr *)chunk->chunk_hdr; 369962306a36Sopenharmony_ci do { 370062306a36Sopenharmony_ci /* Report violation if the chunk is less then minimal */ 370162306a36Sopenharmony_ci if (ntohs(ch->length) < sizeof(*ch)) 370262306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 370362306a36Sopenharmony_ci commands); 370462306a36Sopenharmony_ci 370562306a36Sopenharmony_ci /* Report violation if chunk len overflows */ 370662306a36Sopenharmony_ci ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length)); 370762306a36Sopenharmony_ci if (ch_end > skb_tail_pointer(skb)) 370862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 370962306a36Sopenharmony_ci commands); 371062306a36Sopenharmony_ci 371162306a36Sopenharmony_ci /* Now that we know we at least have a chunk header, 371262306a36Sopenharmony_ci * do things that are type appropriate. 371362306a36Sopenharmony_ci */ 371462306a36Sopenharmony_ci if (SCTP_CID_SHUTDOWN_ACK == ch->type) 371562306a36Sopenharmony_ci ootb_shut_ack = 1; 371662306a36Sopenharmony_ci 371762306a36Sopenharmony_ci /* RFC 2960, Section 3.3.7 371862306a36Sopenharmony_ci * Moreover, under any circumstances, an endpoint that 371962306a36Sopenharmony_ci * receives an ABORT MUST NOT respond to that ABORT by 372062306a36Sopenharmony_ci * sending an ABORT of its own. 372162306a36Sopenharmony_ci */ 372262306a36Sopenharmony_ci if (SCTP_CID_ABORT == ch->type) 372362306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 372462306a36Sopenharmony_ci 372562306a36Sopenharmony_ci /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR 372662306a36Sopenharmony_ci * or a COOKIE ACK the SCTP Packet should be silently 372762306a36Sopenharmony_ci * discarded. 372862306a36Sopenharmony_ci */ 372962306a36Sopenharmony_ci 373062306a36Sopenharmony_ci if (SCTP_CID_COOKIE_ACK == ch->type) 373162306a36Sopenharmony_ci ootb_cookie_ack = 1; 373262306a36Sopenharmony_ci 373362306a36Sopenharmony_ci if (SCTP_CID_ERROR == ch->type) { 373462306a36Sopenharmony_ci sctp_walk_errors(err, ch) { 373562306a36Sopenharmony_ci if (SCTP_ERROR_STALE_COOKIE == err->cause) { 373662306a36Sopenharmony_ci ootb_cookie_ack = 1; 373762306a36Sopenharmony_ci break; 373862306a36Sopenharmony_ci } 373962306a36Sopenharmony_ci } 374062306a36Sopenharmony_ci } 374162306a36Sopenharmony_ci 374262306a36Sopenharmony_ci ch = (struct sctp_chunkhdr *)ch_end; 374362306a36Sopenharmony_ci } while (ch_end < skb_tail_pointer(skb)); 374462306a36Sopenharmony_ci 374562306a36Sopenharmony_ci if (ootb_shut_ack) 374662306a36Sopenharmony_ci return sctp_sf_shut_8_4_5(net, ep, asoc, type, arg, commands); 374762306a36Sopenharmony_ci else if (ootb_cookie_ack) 374862306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 374962306a36Sopenharmony_ci else 375062306a36Sopenharmony_ci return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); 375162306a36Sopenharmony_ci} 375262306a36Sopenharmony_ci 375362306a36Sopenharmony_ci/* 375462306a36Sopenharmony_ci * Handle an "Out of the blue" SHUTDOWN ACK. 375562306a36Sopenharmony_ci * 375662306a36Sopenharmony_ci * Section: 8.4 5, sctpimpguide 2.41. 375762306a36Sopenharmony_ci * 375862306a36Sopenharmony_ci * 5) If the packet contains a SHUTDOWN ACK chunk, the receiver should 375962306a36Sopenharmony_ci * respond to the sender of the OOTB packet with a SHUTDOWN COMPLETE. 376062306a36Sopenharmony_ci * When sending the SHUTDOWN COMPLETE, the receiver of the OOTB 376162306a36Sopenharmony_ci * packet must fill in the Verification Tag field of the outbound 376262306a36Sopenharmony_ci * packet with the Verification Tag received in the SHUTDOWN ACK and 376362306a36Sopenharmony_ci * set the T-bit in the Chunk Flags to indicate that the Verification 376462306a36Sopenharmony_ci * Tag is reflected. 376562306a36Sopenharmony_ci * 376662306a36Sopenharmony_ci * Inputs 376762306a36Sopenharmony_ci * (endpoint, asoc, type, arg, commands) 376862306a36Sopenharmony_ci * 376962306a36Sopenharmony_ci * Outputs 377062306a36Sopenharmony_ci * (enum sctp_disposition) 377162306a36Sopenharmony_ci * 377262306a36Sopenharmony_ci * The return value is the disposition of the chunk. 377362306a36Sopenharmony_ci */ 377462306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_shut_8_4_5( 377562306a36Sopenharmony_ci struct net *net, 377662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 377762306a36Sopenharmony_ci const struct sctp_association *asoc, 377862306a36Sopenharmony_ci const union sctp_subtype type, 377962306a36Sopenharmony_ci void *arg, 378062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 378162306a36Sopenharmony_ci{ 378262306a36Sopenharmony_ci struct sctp_packet *packet = NULL; 378362306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 378462306a36Sopenharmony_ci struct sctp_chunk *shut; 378562306a36Sopenharmony_ci 378662306a36Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 378762306a36Sopenharmony_ci if (!packet) 378862306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 378962306a36Sopenharmony_ci 379062306a36Sopenharmony_ci /* Make an SHUTDOWN_COMPLETE. 379162306a36Sopenharmony_ci * The T bit will be set if the asoc is NULL. 379262306a36Sopenharmony_ci */ 379362306a36Sopenharmony_ci shut = sctp_make_shutdown_complete(asoc, chunk); 379462306a36Sopenharmony_ci if (!shut) { 379562306a36Sopenharmony_ci sctp_ootb_pkt_free(packet); 379662306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 379762306a36Sopenharmony_ci } 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci /* Reflect vtag if T-Bit is set */ 380062306a36Sopenharmony_ci if (sctp_test_T_bit(shut)) 380162306a36Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 380262306a36Sopenharmony_ci 380362306a36Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 380462306a36Sopenharmony_ci shut->skb->sk = ep->base.sk; 380562306a36Sopenharmony_ci 380662306a36Sopenharmony_ci sctp_packet_append_chunk(packet, shut); 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 380962306a36Sopenharmony_ci SCTP_PACKET(packet)); 381062306a36Sopenharmony_ci 381162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 381262306a36Sopenharmony_ci 381362306a36Sopenharmony_ci /* We need to discard the rest of the packet to prevent 381462306a36Sopenharmony_ci * potential boomming attacks from additional bundled chunks. 381562306a36Sopenharmony_ci * This is documented in SCTP Threats ID. 381662306a36Sopenharmony_ci */ 381762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 381862306a36Sopenharmony_ci} 381962306a36Sopenharmony_ci 382062306a36Sopenharmony_ci/* 382162306a36Sopenharmony_ci * Handle SHUTDOWN ACK in COOKIE_ECHOED or COOKIE_WAIT state. 382262306a36Sopenharmony_ci * 382362306a36Sopenharmony_ci * Verification Tag: 8.5.1 E) Rules for packet carrying a SHUTDOWN ACK 382462306a36Sopenharmony_ci * If the receiver is in COOKIE-ECHOED or COOKIE-WAIT state the 382562306a36Sopenharmony_ci * procedures in section 8.4 SHOULD be followed, in other words it 382662306a36Sopenharmony_ci * should be treated as an Out Of The Blue packet. 382762306a36Sopenharmony_ci * [This means that we do NOT check the Verification Tag on these 382862306a36Sopenharmony_ci * chunks. --piggy ] 382962306a36Sopenharmony_ci * 383062306a36Sopenharmony_ci */ 383162306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_8_5_1_E_sa(struct net *net, 383262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 383362306a36Sopenharmony_ci const struct sctp_association *asoc, 383462306a36Sopenharmony_ci const union sctp_subtype type, 383562306a36Sopenharmony_ci void *arg, 383662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 383762306a36Sopenharmony_ci{ 383862306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 383962306a36Sopenharmony_ci 384062306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 384162306a36Sopenharmony_ci asoc = NULL; 384262306a36Sopenharmony_ci 384362306a36Sopenharmony_ci /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ 384462306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 384562306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 384662306a36Sopenharmony_ci commands); 384762306a36Sopenharmony_ci 384862306a36Sopenharmony_ci /* Although we do have an association in this case, it corresponds 384962306a36Sopenharmony_ci * to a restarted association. So the packet is treated as an OOTB 385062306a36Sopenharmony_ci * packet and the state function that handles OOTB SHUTDOWN_ACK is 385162306a36Sopenharmony_ci * called with a NULL association. 385262306a36Sopenharmony_ci */ 385362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); 385462306a36Sopenharmony_ci 385562306a36Sopenharmony_ci return sctp_sf_shut_8_4_5(net, ep, NULL, type, arg, commands); 385662306a36Sopenharmony_ci} 385762306a36Sopenharmony_ci 385862306a36Sopenharmony_ci/* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */ 385962306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_asconf(struct net *net, 386062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 386162306a36Sopenharmony_ci const struct sctp_association *asoc, 386262306a36Sopenharmony_ci const union sctp_subtype type, 386362306a36Sopenharmony_ci void *arg, 386462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 386562306a36Sopenharmony_ci{ 386662306a36Sopenharmony_ci struct sctp_paramhdr *err_param = NULL; 386762306a36Sopenharmony_ci struct sctp_chunk *asconf_ack = NULL; 386862306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 386962306a36Sopenharmony_ci struct sctp_addiphdr *hdr; 387062306a36Sopenharmony_ci __u32 serial; 387162306a36Sopenharmony_ci 387262306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 387362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 387462306a36Sopenharmony_ci SCTP_NULL()); 387562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 387662306a36Sopenharmony_ci } 387762306a36Sopenharmony_ci 387862306a36Sopenharmony_ci /* Make sure that the ASCONF ADDIP chunk has a valid length. */ 387962306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk))) 388062306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 388162306a36Sopenharmony_ci commands); 388262306a36Sopenharmony_ci 388362306a36Sopenharmony_ci /* ADD-IP: Section 4.1.1 388462306a36Sopenharmony_ci * This chunk MUST be sent in an authenticated way by using 388562306a36Sopenharmony_ci * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk 388662306a36Sopenharmony_ci * is received unauthenticated it MUST be silently discarded as 388762306a36Sopenharmony_ci * described in [I-D.ietf-tsvwg-sctp-auth]. 388862306a36Sopenharmony_ci */ 388962306a36Sopenharmony_ci if (!asoc->peer.asconf_capable || 389062306a36Sopenharmony_ci (!net->sctp.addip_noauth && !chunk->auth)) 389162306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 389262306a36Sopenharmony_ci 389362306a36Sopenharmony_ci hdr = (struct sctp_addiphdr *)chunk->skb->data; 389462306a36Sopenharmony_ci serial = ntohl(hdr->serial); 389562306a36Sopenharmony_ci 389662306a36Sopenharmony_ci /* Verify the ASCONF chunk before processing it. */ 389762306a36Sopenharmony_ci if (!sctp_verify_asconf(asoc, chunk, true, &err_param)) 389862306a36Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 389962306a36Sopenharmony_ci (void *)err_param, commands); 390062306a36Sopenharmony_ci 390162306a36Sopenharmony_ci /* ADDIP 5.2 E1) Compare the value of the serial number to the value 390262306a36Sopenharmony_ci * the endpoint stored in a new association variable 390362306a36Sopenharmony_ci * 'Peer-Serial-Number'. 390462306a36Sopenharmony_ci */ 390562306a36Sopenharmony_ci if (serial == asoc->peer.addip_serial + 1) { 390662306a36Sopenharmony_ci /* If this is the first instance of ASCONF in the packet, 390762306a36Sopenharmony_ci * we can clean our old ASCONF-ACKs. 390862306a36Sopenharmony_ci */ 390962306a36Sopenharmony_ci if (!chunk->has_asconf) 391062306a36Sopenharmony_ci sctp_assoc_clean_asconf_ack_cache(asoc); 391162306a36Sopenharmony_ci 391262306a36Sopenharmony_ci /* ADDIP 5.2 E4) When the Sequence Number matches the next one 391362306a36Sopenharmony_ci * expected, process the ASCONF as described below and after 391462306a36Sopenharmony_ci * processing the ASCONF Chunk, append an ASCONF-ACK Chunk to 391562306a36Sopenharmony_ci * the response packet and cache a copy of it (in the event it 391662306a36Sopenharmony_ci * later needs to be retransmitted). 391762306a36Sopenharmony_ci * 391862306a36Sopenharmony_ci * Essentially, do V1-V5. 391962306a36Sopenharmony_ci */ 392062306a36Sopenharmony_ci asconf_ack = sctp_process_asconf((struct sctp_association *) 392162306a36Sopenharmony_ci asoc, chunk); 392262306a36Sopenharmony_ci if (!asconf_ack) 392362306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 392462306a36Sopenharmony_ci } else if (serial < asoc->peer.addip_serial + 1) { 392562306a36Sopenharmony_ci /* ADDIP 5.2 E2) 392662306a36Sopenharmony_ci * If the value found in the Sequence Number is less than the 392762306a36Sopenharmony_ci * ('Peer- Sequence-Number' + 1), simply skip to the next 392862306a36Sopenharmony_ci * ASCONF, and include in the outbound response packet 392962306a36Sopenharmony_ci * any previously cached ASCONF-ACK response that was 393062306a36Sopenharmony_ci * sent and saved that matches the Sequence Number of the 393162306a36Sopenharmony_ci * ASCONF. Note: It is possible that no cached ASCONF-ACK 393262306a36Sopenharmony_ci * Chunk exists. This will occur when an older ASCONF 393362306a36Sopenharmony_ci * arrives out of order. In such a case, the receiver 393462306a36Sopenharmony_ci * should skip the ASCONF Chunk and not include ASCONF-ACK 393562306a36Sopenharmony_ci * Chunk for that chunk. 393662306a36Sopenharmony_ci */ 393762306a36Sopenharmony_ci asconf_ack = sctp_assoc_lookup_asconf_ack(asoc, hdr->serial); 393862306a36Sopenharmony_ci if (!asconf_ack) 393962306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 394062306a36Sopenharmony_ci 394162306a36Sopenharmony_ci /* Reset the transport so that we select the correct one 394262306a36Sopenharmony_ci * this time around. This is to make sure that we don't 394362306a36Sopenharmony_ci * accidentally use a stale transport that's been removed. 394462306a36Sopenharmony_ci */ 394562306a36Sopenharmony_ci asconf_ack->transport = NULL; 394662306a36Sopenharmony_ci } else { 394762306a36Sopenharmony_ci /* ADDIP 5.2 E5) Otherwise, the ASCONF Chunk is discarded since 394862306a36Sopenharmony_ci * it must be either a stale packet or from an attacker. 394962306a36Sopenharmony_ci */ 395062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 395162306a36Sopenharmony_ci } 395262306a36Sopenharmony_ci 395362306a36Sopenharmony_ci /* ADDIP 5.2 E6) The destination address of the SCTP packet 395462306a36Sopenharmony_ci * containing the ASCONF-ACK Chunks MUST be the source address of 395562306a36Sopenharmony_ci * the SCTP packet that held the ASCONF Chunks. 395662306a36Sopenharmony_ci * 395762306a36Sopenharmony_ci * To do this properly, we'll set the destination address of the chunk 395862306a36Sopenharmony_ci * and at the transmit time, will try look up the transport to use. 395962306a36Sopenharmony_ci * Since ASCONFs may be bundled, the correct transport may not be 396062306a36Sopenharmony_ci * created until we process the entire packet, thus this workaround. 396162306a36Sopenharmony_ci */ 396262306a36Sopenharmony_ci asconf_ack->dest = chunk->source; 396362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack)); 396462306a36Sopenharmony_ci if (asoc->new_transport) { 396562306a36Sopenharmony_ci sctp_sf_heartbeat(ep, asoc, type, asoc->new_transport, commands); 396662306a36Sopenharmony_ci ((struct sctp_association *)asoc)->new_transport = NULL; 396762306a36Sopenharmony_ci } 396862306a36Sopenharmony_ci 396962306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 397062306a36Sopenharmony_ci} 397162306a36Sopenharmony_ci 397262306a36Sopenharmony_cistatic enum sctp_disposition sctp_send_next_asconf( 397362306a36Sopenharmony_ci struct net *net, 397462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 397562306a36Sopenharmony_ci struct sctp_association *asoc, 397662306a36Sopenharmony_ci const union sctp_subtype type, 397762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 397862306a36Sopenharmony_ci{ 397962306a36Sopenharmony_ci struct sctp_chunk *asconf; 398062306a36Sopenharmony_ci struct list_head *entry; 398162306a36Sopenharmony_ci 398262306a36Sopenharmony_ci if (list_empty(&asoc->addip_chunk_list)) 398362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci entry = asoc->addip_chunk_list.next; 398662306a36Sopenharmony_ci asconf = list_entry(entry, struct sctp_chunk, list); 398762306a36Sopenharmony_ci 398862306a36Sopenharmony_ci list_del_init(entry); 398962306a36Sopenharmony_ci sctp_chunk_hold(asconf); 399062306a36Sopenharmony_ci asoc->addip_last_asconf = asconf; 399162306a36Sopenharmony_ci 399262306a36Sopenharmony_ci return sctp_sf_do_prm_asconf(net, ep, asoc, type, asconf, commands); 399362306a36Sopenharmony_ci} 399462306a36Sopenharmony_ci 399562306a36Sopenharmony_ci/* 399662306a36Sopenharmony_ci * ADDIP Section 4.3 General rules for address manipulation 399762306a36Sopenharmony_ci * When building TLV parameters for the ASCONF Chunk that will add or 399862306a36Sopenharmony_ci * delete IP addresses the D0 to D13 rules should be applied: 399962306a36Sopenharmony_ci */ 400062306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_asconf_ack(struct net *net, 400162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 400262306a36Sopenharmony_ci const struct sctp_association *asoc, 400362306a36Sopenharmony_ci const union sctp_subtype type, 400462306a36Sopenharmony_ci void *arg, 400562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 400662306a36Sopenharmony_ci{ 400762306a36Sopenharmony_ci struct sctp_chunk *last_asconf = asoc->addip_last_asconf; 400862306a36Sopenharmony_ci struct sctp_paramhdr *err_param = NULL; 400962306a36Sopenharmony_ci struct sctp_chunk *asconf_ack = arg; 401062306a36Sopenharmony_ci struct sctp_addiphdr *addip_hdr; 401162306a36Sopenharmony_ci __u32 sent_serial, rcvd_serial; 401262306a36Sopenharmony_ci struct sctp_chunk *abort; 401362306a36Sopenharmony_ci 401462306a36Sopenharmony_ci if (!sctp_vtag_verify(asconf_ack, asoc)) { 401562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 401662306a36Sopenharmony_ci SCTP_NULL()); 401762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 401862306a36Sopenharmony_ci } 401962306a36Sopenharmony_ci 402062306a36Sopenharmony_ci /* Make sure that the ADDIP chunk has a valid length. */ 402162306a36Sopenharmony_ci if (!sctp_chunk_length_valid(asconf_ack, 402262306a36Sopenharmony_ci sizeof(struct sctp_addip_chunk))) 402362306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 402462306a36Sopenharmony_ci commands); 402562306a36Sopenharmony_ci 402662306a36Sopenharmony_ci /* ADD-IP, Section 4.1.2: 402762306a36Sopenharmony_ci * This chunk MUST be sent in an authenticated way by using 402862306a36Sopenharmony_ci * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk 402962306a36Sopenharmony_ci * is received unauthenticated it MUST be silently discarded as 403062306a36Sopenharmony_ci * described in [I-D.ietf-tsvwg-sctp-auth]. 403162306a36Sopenharmony_ci */ 403262306a36Sopenharmony_ci if (!asoc->peer.asconf_capable || 403362306a36Sopenharmony_ci (!net->sctp.addip_noauth && !asconf_ack->auth)) 403462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 403562306a36Sopenharmony_ci 403662306a36Sopenharmony_ci addip_hdr = (struct sctp_addiphdr *)asconf_ack->skb->data; 403762306a36Sopenharmony_ci rcvd_serial = ntohl(addip_hdr->serial); 403862306a36Sopenharmony_ci 403962306a36Sopenharmony_ci /* Verify the ASCONF-ACK chunk before processing it. */ 404062306a36Sopenharmony_ci if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param)) 404162306a36Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 404262306a36Sopenharmony_ci (void *)err_param, commands); 404362306a36Sopenharmony_ci 404462306a36Sopenharmony_ci if (last_asconf) { 404562306a36Sopenharmony_ci addip_hdr = last_asconf->subh.addip_hdr; 404662306a36Sopenharmony_ci sent_serial = ntohl(addip_hdr->serial); 404762306a36Sopenharmony_ci } else { 404862306a36Sopenharmony_ci sent_serial = asoc->addip_serial - 1; 404962306a36Sopenharmony_ci } 405062306a36Sopenharmony_ci 405162306a36Sopenharmony_ci /* D0) If an endpoint receives an ASCONF-ACK that is greater than or 405262306a36Sopenharmony_ci * equal to the next serial number to be used but no ASCONF chunk is 405362306a36Sopenharmony_ci * outstanding the endpoint MUST ABORT the association. Note that a 405462306a36Sopenharmony_ci * sequence number is greater than if it is no more than 2^^31-1 405562306a36Sopenharmony_ci * larger than the current sequence number (using serial arithmetic). 405662306a36Sopenharmony_ci */ 405762306a36Sopenharmony_ci if (ADDIP_SERIAL_gte(rcvd_serial, sent_serial + 1) && 405862306a36Sopenharmony_ci !(asoc->addip_last_asconf)) { 405962306a36Sopenharmony_ci abort = sctp_make_abort(asoc, asconf_ack, 406062306a36Sopenharmony_ci sizeof(struct sctp_errhdr)); 406162306a36Sopenharmony_ci if (abort) { 406262306a36Sopenharmony_ci sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0); 406362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 406462306a36Sopenharmony_ci SCTP_CHUNK(abort)); 406562306a36Sopenharmony_ci } 406662306a36Sopenharmony_ci /* We are going to ABORT, so we might as well stop 406762306a36Sopenharmony_ci * processing the rest of the chunks in the packet. 406862306a36Sopenharmony_ci */ 406962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 407062306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 407162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 407262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 407362306a36Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 407462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 407562306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); 407662306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 407762306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 407862306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 407962306a36Sopenharmony_ci } 408062306a36Sopenharmony_ci 408162306a36Sopenharmony_ci if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) { 408262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 408362306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 408462306a36Sopenharmony_ci 408562306a36Sopenharmony_ci if (!sctp_process_asconf_ack((struct sctp_association *)asoc, 408662306a36Sopenharmony_ci asconf_ack)) 408762306a36Sopenharmony_ci return sctp_send_next_asconf(net, ep, 408862306a36Sopenharmony_ci (struct sctp_association *)asoc, 408962306a36Sopenharmony_ci type, commands); 409062306a36Sopenharmony_ci 409162306a36Sopenharmony_ci abort = sctp_make_abort(asoc, asconf_ack, 409262306a36Sopenharmony_ci sizeof(struct sctp_errhdr)); 409362306a36Sopenharmony_ci if (abort) { 409462306a36Sopenharmony_ci sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); 409562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 409662306a36Sopenharmony_ci SCTP_CHUNK(abort)); 409762306a36Sopenharmony_ci } 409862306a36Sopenharmony_ci /* We are going to ABORT, so we might as well stop 409962306a36Sopenharmony_ci * processing the rest of the chunks in the packet. 410062306a36Sopenharmony_ci */ 410162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 410262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 410362306a36Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 410462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 410562306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); 410662306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 410762306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 410862306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 410962306a36Sopenharmony_ci } 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 411262306a36Sopenharmony_ci} 411362306a36Sopenharmony_ci 411462306a36Sopenharmony_ci/* RE-CONFIG Section 5.2 Upon reception of an RECONF Chunk. */ 411562306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_reconf(struct net *net, 411662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 411762306a36Sopenharmony_ci const struct sctp_association *asoc, 411862306a36Sopenharmony_ci const union sctp_subtype type, 411962306a36Sopenharmony_ci void *arg, 412062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 412162306a36Sopenharmony_ci{ 412262306a36Sopenharmony_ci struct sctp_paramhdr *err_param = NULL; 412362306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 412462306a36Sopenharmony_ci struct sctp_reconf_chunk *hdr; 412562306a36Sopenharmony_ci union sctp_params param; 412662306a36Sopenharmony_ci 412762306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 412862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 412962306a36Sopenharmony_ci SCTP_NULL()); 413062306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 413162306a36Sopenharmony_ci } 413262306a36Sopenharmony_ci 413362306a36Sopenharmony_ci /* Make sure that the RECONF chunk has a valid length. */ 413462306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(*hdr))) 413562306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 413662306a36Sopenharmony_ci commands); 413762306a36Sopenharmony_ci 413862306a36Sopenharmony_ci if (!sctp_verify_reconf(asoc, chunk, &err_param)) 413962306a36Sopenharmony_ci return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 414062306a36Sopenharmony_ci (void *)err_param, commands); 414162306a36Sopenharmony_ci 414262306a36Sopenharmony_ci hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; 414362306a36Sopenharmony_ci sctp_walk_params(param, hdr) { 414462306a36Sopenharmony_ci struct sctp_chunk *reply = NULL; 414562306a36Sopenharmony_ci struct sctp_ulpevent *ev = NULL; 414662306a36Sopenharmony_ci 414762306a36Sopenharmony_ci if (param.p->type == SCTP_PARAM_RESET_OUT_REQUEST) 414862306a36Sopenharmony_ci reply = sctp_process_strreset_outreq( 414962306a36Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 415062306a36Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST) 415162306a36Sopenharmony_ci reply = sctp_process_strreset_inreq( 415262306a36Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 415362306a36Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_TSN_REQUEST) 415462306a36Sopenharmony_ci reply = sctp_process_strreset_tsnreq( 415562306a36Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 415662306a36Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) 415762306a36Sopenharmony_ci reply = sctp_process_strreset_addstrm_out( 415862306a36Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 415962306a36Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) 416062306a36Sopenharmony_ci reply = sctp_process_strreset_addstrm_in( 416162306a36Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 416262306a36Sopenharmony_ci else if (param.p->type == SCTP_PARAM_RESET_RESPONSE) 416362306a36Sopenharmony_ci reply = sctp_process_strreset_resp( 416462306a36Sopenharmony_ci (struct sctp_association *)asoc, param, &ev); 416562306a36Sopenharmony_ci 416662306a36Sopenharmony_ci if (ev) 416762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 416862306a36Sopenharmony_ci SCTP_ULPEVENT(ev)); 416962306a36Sopenharmony_ci 417062306a36Sopenharmony_ci if (reply) 417162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 417262306a36Sopenharmony_ci SCTP_CHUNK(reply)); 417362306a36Sopenharmony_ci } 417462306a36Sopenharmony_ci 417562306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 417662306a36Sopenharmony_ci} 417762306a36Sopenharmony_ci 417862306a36Sopenharmony_ci/* 417962306a36Sopenharmony_ci * PR-SCTP Section 3.6 Receiver Side Implementation of PR-SCTP 418062306a36Sopenharmony_ci * 418162306a36Sopenharmony_ci * When a FORWARD TSN chunk arrives, the data receiver MUST first update 418262306a36Sopenharmony_ci * its cumulative TSN point to the value carried in the FORWARD TSN 418362306a36Sopenharmony_ci * chunk, and then MUST further advance its cumulative TSN point locally 418462306a36Sopenharmony_ci * if possible. 418562306a36Sopenharmony_ci * After the above processing, the data receiver MUST stop reporting any 418662306a36Sopenharmony_ci * missing TSNs earlier than or equal to the new cumulative TSN point. 418762306a36Sopenharmony_ci * 418862306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 418962306a36Sopenharmony_ci * 419062306a36Sopenharmony_ci * The return value is the disposition of the chunk. 419162306a36Sopenharmony_ci */ 419262306a36Sopenharmony_cienum sctp_disposition sctp_sf_eat_fwd_tsn(struct net *net, 419362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 419462306a36Sopenharmony_ci const struct sctp_association *asoc, 419562306a36Sopenharmony_ci const union sctp_subtype type, 419662306a36Sopenharmony_ci void *arg, 419762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 419862306a36Sopenharmony_ci{ 419962306a36Sopenharmony_ci struct sctp_fwdtsn_hdr *fwdtsn_hdr; 420062306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 420162306a36Sopenharmony_ci __u16 len; 420262306a36Sopenharmony_ci __u32 tsn; 420362306a36Sopenharmony_ci 420462306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 420562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 420662306a36Sopenharmony_ci SCTP_NULL()); 420762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 420862306a36Sopenharmony_ci } 420962306a36Sopenharmony_ci 421062306a36Sopenharmony_ci if (!asoc->peer.prsctp_capable) 421162306a36Sopenharmony_ci return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); 421262306a36Sopenharmony_ci 421362306a36Sopenharmony_ci /* Make sure that the FORWARD_TSN chunk has valid length. */ 421462306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_ftsnchk_len(&asoc->stream))) 421562306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 421662306a36Sopenharmony_ci commands); 421762306a36Sopenharmony_ci 421862306a36Sopenharmony_ci fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; 421962306a36Sopenharmony_ci chunk->subh.fwdtsn_hdr = fwdtsn_hdr; 422062306a36Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 422162306a36Sopenharmony_ci len -= sizeof(struct sctp_chunkhdr); 422262306a36Sopenharmony_ci skb_pull(chunk->skb, len); 422362306a36Sopenharmony_ci 422462306a36Sopenharmony_ci tsn = ntohl(fwdtsn_hdr->new_cum_tsn); 422562306a36Sopenharmony_ci pr_debug("%s: TSN 0x%x\n", __func__, tsn); 422662306a36Sopenharmony_ci 422762306a36Sopenharmony_ci /* The TSN is too high--silently discard the chunk and count on it 422862306a36Sopenharmony_ci * getting retransmitted later. 422962306a36Sopenharmony_ci */ 423062306a36Sopenharmony_ci if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) 423162306a36Sopenharmony_ci goto discard_noforce; 423262306a36Sopenharmony_ci 423362306a36Sopenharmony_ci if (!asoc->stream.si->validate_ftsn(chunk)) 423462306a36Sopenharmony_ci goto discard_noforce; 423562306a36Sopenharmony_ci 423662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); 423762306a36Sopenharmony_ci if (len > sctp_ftsnhdr_len(&asoc->stream)) 423862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 423962306a36Sopenharmony_ci SCTP_CHUNK(chunk)); 424062306a36Sopenharmony_ci 424162306a36Sopenharmony_ci /* Count this as receiving DATA. */ 424262306a36Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { 424362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 424462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 424562306a36Sopenharmony_ci } 424662306a36Sopenharmony_ci 424762306a36Sopenharmony_ci /* FIXME: For now send a SACK, but DATA processing may 424862306a36Sopenharmony_ci * send another. 424962306a36Sopenharmony_ci */ 425062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE()); 425162306a36Sopenharmony_ci 425262306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 425362306a36Sopenharmony_ci 425462306a36Sopenharmony_cidiscard_noforce: 425562306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 425662306a36Sopenharmony_ci} 425762306a36Sopenharmony_ci 425862306a36Sopenharmony_cienum sctp_disposition sctp_sf_eat_fwd_tsn_fast( 425962306a36Sopenharmony_ci struct net *net, 426062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 426162306a36Sopenharmony_ci const struct sctp_association *asoc, 426262306a36Sopenharmony_ci const union sctp_subtype type, 426362306a36Sopenharmony_ci void *arg, 426462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 426562306a36Sopenharmony_ci{ 426662306a36Sopenharmony_ci struct sctp_fwdtsn_hdr *fwdtsn_hdr; 426762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 426862306a36Sopenharmony_ci __u16 len; 426962306a36Sopenharmony_ci __u32 tsn; 427062306a36Sopenharmony_ci 427162306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 427262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 427362306a36Sopenharmony_ci SCTP_NULL()); 427462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 427562306a36Sopenharmony_ci } 427662306a36Sopenharmony_ci 427762306a36Sopenharmony_ci if (!asoc->peer.prsctp_capable) 427862306a36Sopenharmony_ci return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); 427962306a36Sopenharmony_ci 428062306a36Sopenharmony_ci /* Make sure that the FORWARD_TSN chunk has a valid length. */ 428162306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sctp_ftsnchk_len(&asoc->stream))) 428262306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 428362306a36Sopenharmony_ci commands); 428462306a36Sopenharmony_ci 428562306a36Sopenharmony_ci fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; 428662306a36Sopenharmony_ci chunk->subh.fwdtsn_hdr = fwdtsn_hdr; 428762306a36Sopenharmony_ci len = ntohs(chunk->chunk_hdr->length); 428862306a36Sopenharmony_ci len -= sizeof(struct sctp_chunkhdr); 428962306a36Sopenharmony_ci skb_pull(chunk->skb, len); 429062306a36Sopenharmony_ci 429162306a36Sopenharmony_ci tsn = ntohl(fwdtsn_hdr->new_cum_tsn); 429262306a36Sopenharmony_ci pr_debug("%s: TSN 0x%x\n", __func__, tsn); 429362306a36Sopenharmony_ci 429462306a36Sopenharmony_ci /* The TSN is too high--silently discard the chunk and count on it 429562306a36Sopenharmony_ci * getting retransmitted later. 429662306a36Sopenharmony_ci */ 429762306a36Sopenharmony_ci if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) 429862306a36Sopenharmony_ci goto gen_shutdown; 429962306a36Sopenharmony_ci 430062306a36Sopenharmony_ci if (!asoc->stream.si->validate_ftsn(chunk)) 430162306a36Sopenharmony_ci goto gen_shutdown; 430262306a36Sopenharmony_ci 430362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); 430462306a36Sopenharmony_ci if (len > sctp_ftsnhdr_len(&asoc->stream)) 430562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 430662306a36Sopenharmony_ci SCTP_CHUNK(chunk)); 430762306a36Sopenharmony_ci 430862306a36Sopenharmony_ci /* Go a head and force a SACK, since we are shutting down. */ 430962306a36Sopenharmony_cigen_shutdown: 431062306a36Sopenharmony_ci /* Implementor's Guide. 431162306a36Sopenharmony_ci * 431262306a36Sopenharmony_ci * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately 431362306a36Sopenharmony_ci * respond to each received packet containing one or more DATA chunk(s) 431462306a36Sopenharmony_ci * with a SACK, a SHUTDOWN chunk, and restart the T2-shutdown timer 431562306a36Sopenharmony_ci */ 431662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SHUTDOWN, SCTP_NULL()); 431762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 431862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 431962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 432062306a36Sopenharmony_ci 432162306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 432262306a36Sopenharmony_ci} 432362306a36Sopenharmony_ci 432462306a36Sopenharmony_ci/* 432562306a36Sopenharmony_ci * SCTP-AUTH Section 6.3 Receiving authenticated chunks 432662306a36Sopenharmony_ci * 432762306a36Sopenharmony_ci * The receiver MUST use the HMAC algorithm indicated in the HMAC 432862306a36Sopenharmony_ci * Identifier field. If this algorithm was not specified by the 432962306a36Sopenharmony_ci * receiver in the HMAC-ALGO parameter in the INIT or INIT-ACK chunk 433062306a36Sopenharmony_ci * during association setup, the AUTH chunk and all chunks after it MUST 433162306a36Sopenharmony_ci * be discarded and an ERROR chunk SHOULD be sent with the error cause 433262306a36Sopenharmony_ci * defined in Section 4.1. 433362306a36Sopenharmony_ci * 433462306a36Sopenharmony_ci * If an endpoint with no shared key receives a Shared Key Identifier 433562306a36Sopenharmony_ci * other than 0, it MUST silently discard all authenticated chunks. If 433662306a36Sopenharmony_ci * the endpoint has at least one endpoint pair shared key for the peer, 433762306a36Sopenharmony_ci * it MUST use the key specified by the Shared Key Identifier if a 433862306a36Sopenharmony_ci * key has been configured for that Shared Key Identifier. If no 433962306a36Sopenharmony_ci * endpoint pair shared key has been configured for that Shared Key 434062306a36Sopenharmony_ci * Identifier, all authenticated chunks MUST be silently discarded. 434162306a36Sopenharmony_ci * 434262306a36Sopenharmony_ci * Verification Tag: 8.5 Verification Tag [Normal verification] 434362306a36Sopenharmony_ci * 434462306a36Sopenharmony_ci * The return value is the disposition of the chunk. 434562306a36Sopenharmony_ci */ 434662306a36Sopenharmony_cistatic enum sctp_ierror sctp_sf_authenticate( 434762306a36Sopenharmony_ci const struct sctp_association *asoc, 434862306a36Sopenharmony_ci struct sctp_chunk *chunk) 434962306a36Sopenharmony_ci{ 435062306a36Sopenharmony_ci struct sctp_shared_key *sh_key = NULL; 435162306a36Sopenharmony_ci struct sctp_authhdr *auth_hdr; 435262306a36Sopenharmony_ci __u8 *save_digest, *digest; 435362306a36Sopenharmony_ci struct sctp_hmac *hmac; 435462306a36Sopenharmony_ci unsigned int sig_len; 435562306a36Sopenharmony_ci __u16 key_id; 435662306a36Sopenharmony_ci 435762306a36Sopenharmony_ci /* Pull in the auth header, so we can do some more verification */ 435862306a36Sopenharmony_ci auth_hdr = (struct sctp_authhdr *)chunk->skb->data; 435962306a36Sopenharmony_ci chunk->subh.auth_hdr = auth_hdr; 436062306a36Sopenharmony_ci skb_pull(chunk->skb, sizeof(*auth_hdr)); 436162306a36Sopenharmony_ci 436262306a36Sopenharmony_ci /* Make sure that we support the HMAC algorithm from the auth 436362306a36Sopenharmony_ci * chunk. 436462306a36Sopenharmony_ci */ 436562306a36Sopenharmony_ci if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id)) 436662306a36Sopenharmony_ci return SCTP_IERROR_AUTH_BAD_HMAC; 436762306a36Sopenharmony_ci 436862306a36Sopenharmony_ci /* Make sure that the provided shared key identifier has been 436962306a36Sopenharmony_ci * configured 437062306a36Sopenharmony_ci */ 437162306a36Sopenharmony_ci key_id = ntohs(auth_hdr->shkey_id); 437262306a36Sopenharmony_ci if (key_id != asoc->active_key_id) { 437362306a36Sopenharmony_ci sh_key = sctp_auth_get_shkey(asoc, key_id); 437462306a36Sopenharmony_ci if (!sh_key) 437562306a36Sopenharmony_ci return SCTP_IERROR_AUTH_BAD_KEYID; 437662306a36Sopenharmony_ci } 437762306a36Sopenharmony_ci 437862306a36Sopenharmony_ci /* Make sure that the length of the signature matches what 437962306a36Sopenharmony_ci * we expect. 438062306a36Sopenharmony_ci */ 438162306a36Sopenharmony_ci sig_len = ntohs(chunk->chunk_hdr->length) - 438262306a36Sopenharmony_ci sizeof(struct sctp_auth_chunk); 438362306a36Sopenharmony_ci hmac = sctp_auth_get_hmac(ntohs(auth_hdr->hmac_id)); 438462306a36Sopenharmony_ci if (sig_len != hmac->hmac_len) 438562306a36Sopenharmony_ci return SCTP_IERROR_PROTO_VIOLATION; 438662306a36Sopenharmony_ci 438762306a36Sopenharmony_ci /* Now that we've done validation checks, we can compute and 438862306a36Sopenharmony_ci * verify the hmac. The steps involved are: 438962306a36Sopenharmony_ci * 1. Save the digest from the chunk. 439062306a36Sopenharmony_ci * 2. Zero out the digest in the chunk. 439162306a36Sopenharmony_ci * 3. Compute the new digest 439262306a36Sopenharmony_ci * 4. Compare saved and new digests. 439362306a36Sopenharmony_ci */ 439462306a36Sopenharmony_ci digest = (u8 *)(auth_hdr + 1); 439562306a36Sopenharmony_ci skb_pull(chunk->skb, sig_len); 439662306a36Sopenharmony_ci 439762306a36Sopenharmony_ci save_digest = kmemdup(digest, sig_len, GFP_ATOMIC); 439862306a36Sopenharmony_ci if (!save_digest) 439962306a36Sopenharmony_ci goto nomem; 440062306a36Sopenharmony_ci 440162306a36Sopenharmony_ci memset(digest, 0, sig_len); 440262306a36Sopenharmony_ci 440362306a36Sopenharmony_ci sctp_auth_calculate_hmac(asoc, chunk->skb, 440462306a36Sopenharmony_ci (struct sctp_auth_chunk *)chunk->chunk_hdr, 440562306a36Sopenharmony_ci sh_key, GFP_ATOMIC); 440662306a36Sopenharmony_ci 440762306a36Sopenharmony_ci /* Discard the packet if the digests do not match */ 440862306a36Sopenharmony_ci if (memcmp(save_digest, digest, sig_len)) { 440962306a36Sopenharmony_ci kfree(save_digest); 441062306a36Sopenharmony_ci return SCTP_IERROR_BAD_SIG; 441162306a36Sopenharmony_ci } 441262306a36Sopenharmony_ci 441362306a36Sopenharmony_ci kfree(save_digest); 441462306a36Sopenharmony_ci chunk->auth = 1; 441562306a36Sopenharmony_ci 441662306a36Sopenharmony_ci return SCTP_IERROR_NO_ERROR; 441762306a36Sopenharmony_cinomem: 441862306a36Sopenharmony_ci return SCTP_IERROR_NOMEM; 441962306a36Sopenharmony_ci} 442062306a36Sopenharmony_ci 442162306a36Sopenharmony_cienum sctp_disposition sctp_sf_eat_auth(struct net *net, 442262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 442362306a36Sopenharmony_ci const struct sctp_association *asoc, 442462306a36Sopenharmony_ci const union sctp_subtype type, 442562306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 442662306a36Sopenharmony_ci{ 442762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 442862306a36Sopenharmony_ci struct sctp_authhdr *auth_hdr; 442962306a36Sopenharmony_ci struct sctp_chunk *err_chunk; 443062306a36Sopenharmony_ci enum sctp_ierror error; 443162306a36Sopenharmony_ci 443262306a36Sopenharmony_ci /* Make sure that the peer has AUTH capable */ 443362306a36Sopenharmony_ci if (!asoc->peer.auth_capable) 443462306a36Sopenharmony_ci return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); 443562306a36Sopenharmony_ci 443662306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) { 443762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 443862306a36Sopenharmony_ci SCTP_NULL()); 443962306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 444062306a36Sopenharmony_ci } 444162306a36Sopenharmony_ci 444262306a36Sopenharmony_ci /* Make sure that the AUTH chunk has valid length. */ 444362306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk))) 444462306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 444562306a36Sopenharmony_ci commands); 444662306a36Sopenharmony_ci 444762306a36Sopenharmony_ci auth_hdr = (struct sctp_authhdr *)chunk->skb->data; 444862306a36Sopenharmony_ci error = sctp_sf_authenticate(asoc, chunk); 444962306a36Sopenharmony_ci switch (error) { 445062306a36Sopenharmony_ci case SCTP_IERROR_AUTH_BAD_HMAC: 445162306a36Sopenharmony_ci /* Generate the ERROR chunk and discard the rest 445262306a36Sopenharmony_ci * of the packet 445362306a36Sopenharmony_ci */ 445462306a36Sopenharmony_ci err_chunk = sctp_make_op_error(asoc, chunk, 445562306a36Sopenharmony_ci SCTP_ERROR_UNSUP_HMAC, 445662306a36Sopenharmony_ci &auth_hdr->hmac_id, 445762306a36Sopenharmony_ci sizeof(__u16), 0); 445862306a36Sopenharmony_ci if (err_chunk) { 445962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 446062306a36Sopenharmony_ci SCTP_CHUNK(err_chunk)); 446162306a36Sopenharmony_ci } 446262306a36Sopenharmony_ci fallthrough; 446362306a36Sopenharmony_ci case SCTP_IERROR_AUTH_BAD_KEYID: 446462306a36Sopenharmony_ci case SCTP_IERROR_BAD_SIG: 446562306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 446662306a36Sopenharmony_ci 446762306a36Sopenharmony_ci case SCTP_IERROR_PROTO_VIOLATION: 446862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 446962306a36Sopenharmony_ci commands); 447062306a36Sopenharmony_ci 447162306a36Sopenharmony_ci case SCTP_IERROR_NOMEM: 447262306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 447362306a36Sopenharmony_ci 447462306a36Sopenharmony_ci default: /* Prevent gcc warnings */ 447562306a36Sopenharmony_ci break; 447662306a36Sopenharmony_ci } 447762306a36Sopenharmony_ci 447862306a36Sopenharmony_ci if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) { 447962306a36Sopenharmony_ci struct sctp_ulpevent *ev; 448062306a36Sopenharmony_ci 448162306a36Sopenharmony_ci ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id), 448262306a36Sopenharmony_ci SCTP_AUTH_NEW_KEY, GFP_ATOMIC); 448362306a36Sopenharmony_ci 448462306a36Sopenharmony_ci if (!ev) 448562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 448662306a36Sopenharmony_ci 448762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, 448862306a36Sopenharmony_ci SCTP_ULPEVENT(ev)); 448962306a36Sopenharmony_ci } 449062306a36Sopenharmony_ci 449162306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 449262306a36Sopenharmony_ci} 449362306a36Sopenharmony_ci 449462306a36Sopenharmony_ci/* 449562306a36Sopenharmony_ci * Process an unknown chunk. 449662306a36Sopenharmony_ci * 449762306a36Sopenharmony_ci * Section: 3.2. Also, 2.1 in the implementor's guide. 449862306a36Sopenharmony_ci * 449962306a36Sopenharmony_ci * Chunk Types are encoded such that the highest-order two bits specify 450062306a36Sopenharmony_ci * the action that must be taken if the processing endpoint does not 450162306a36Sopenharmony_ci * recognize the Chunk Type. 450262306a36Sopenharmony_ci * 450362306a36Sopenharmony_ci * 00 - Stop processing this SCTP packet and discard it, do not process 450462306a36Sopenharmony_ci * any further chunks within it. 450562306a36Sopenharmony_ci * 450662306a36Sopenharmony_ci * 01 - Stop processing this SCTP packet and discard it, do not process 450762306a36Sopenharmony_ci * any further chunks within it, and report the unrecognized 450862306a36Sopenharmony_ci * chunk in an 'Unrecognized Chunk Type'. 450962306a36Sopenharmony_ci * 451062306a36Sopenharmony_ci * 10 - Skip this chunk and continue processing. 451162306a36Sopenharmony_ci * 451262306a36Sopenharmony_ci * 11 - Skip this chunk and continue processing, but report in an ERROR 451362306a36Sopenharmony_ci * Chunk using the 'Unrecognized Chunk Type' cause of error. 451462306a36Sopenharmony_ci * 451562306a36Sopenharmony_ci * The return value is the disposition of the chunk. 451662306a36Sopenharmony_ci */ 451762306a36Sopenharmony_cienum sctp_disposition sctp_sf_unk_chunk(struct net *net, 451862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 451962306a36Sopenharmony_ci const struct sctp_association *asoc, 452062306a36Sopenharmony_ci const union sctp_subtype type, 452162306a36Sopenharmony_ci void *arg, 452262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 452362306a36Sopenharmony_ci{ 452462306a36Sopenharmony_ci struct sctp_chunk *unk_chunk = arg; 452562306a36Sopenharmony_ci struct sctp_chunk *err_chunk; 452662306a36Sopenharmony_ci struct sctp_chunkhdr *hdr; 452762306a36Sopenharmony_ci 452862306a36Sopenharmony_ci pr_debug("%s: processing unknown chunk id:%d\n", __func__, type.chunk); 452962306a36Sopenharmony_ci 453062306a36Sopenharmony_ci if (!sctp_vtag_verify(unk_chunk, asoc)) 453162306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 453262306a36Sopenharmony_ci 453362306a36Sopenharmony_ci /* Make sure that the chunk has a valid length. 453462306a36Sopenharmony_ci * Since we don't know the chunk type, we use a general 453562306a36Sopenharmony_ci * chunkhdr structure to make a comparison. 453662306a36Sopenharmony_ci */ 453762306a36Sopenharmony_ci if (!sctp_chunk_length_valid(unk_chunk, sizeof(*hdr))) 453862306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 453962306a36Sopenharmony_ci commands); 454062306a36Sopenharmony_ci 454162306a36Sopenharmony_ci switch (type.chunk & SCTP_CID_ACTION_MASK) { 454262306a36Sopenharmony_ci case SCTP_CID_ACTION_DISCARD: 454362306a36Sopenharmony_ci /* Discard the packet. */ 454462306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 454562306a36Sopenharmony_ci case SCTP_CID_ACTION_DISCARD_ERR: 454662306a36Sopenharmony_ci /* Generate an ERROR chunk as response. */ 454762306a36Sopenharmony_ci hdr = unk_chunk->chunk_hdr; 454862306a36Sopenharmony_ci err_chunk = sctp_make_op_error(asoc, unk_chunk, 454962306a36Sopenharmony_ci SCTP_ERROR_UNKNOWN_CHUNK, hdr, 455062306a36Sopenharmony_ci SCTP_PAD4(ntohs(hdr->length)), 455162306a36Sopenharmony_ci 0); 455262306a36Sopenharmony_ci if (err_chunk) { 455362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 455462306a36Sopenharmony_ci SCTP_CHUNK(err_chunk)); 455562306a36Sopenharmony_ci } 455662306a36Sopenharmony_ci 455762306a36Sopenharmony_ci /* Discard the packet. */ 455862306a36Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 455962306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 456062306a36Sopenharmony_ci case SCTP_CID_ACTION_SKIP: 456162306a36Sopenharmony_ci /* Skip the chunk. */ 456262306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 456362306a36Sopenharmony_ci case SCTP_CID_ACTION_SKIP_ERR: 456462306a36Sopenharmony_ci /* Generate an ERROR chunk as response. */ 456562306a36Sopenharmony_ci hdr = unk_chunk->chunk_hdr; 456662306a36Sopenharmony_ci err_chunk = sctp_make_op_error(asoc, unk_chunk, 456762306a36Sopenharmony_ci SCTP_ERROR_UNKNOWN_CHUNK, hdr, 456862306a36Sopenharmony_ci SCTP_PAD4(ntohs(hdr->length)), 456962306a36Sopenharmony_ci 0); 457062306a36Sopenharmony_ci if (err_chunk) { 457162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 457262306a36Sopenharmony_ci SCTP_CHUNK(err_chunk)); 457362306a36Sopenharmony_ci } 457462306a36Sopenharmony_ci /* Skip the chunk. */ 457562306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 457662306a36Sopenharmony_ci default: 457762306a36Sopenharmony_ci break; 457862306a36Sopenharmony_ci } 457962306a36Sopenharmony_ci 458062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 458162306a36Sopenharmony_ci} 458262306a36Sopenharmony_ci 458362306a36Sopenharmony_ci/* 458462306a36Sopenharmony_ci * Discard the chunk. 458562306a36Sopenharmony_ci * 458662306a36Sopenharmony_ci * Section: 0.2, 5.2.3, 5.2.5, 5.2.6, 6.0, 8.4.6, 8.5.1c, 9.2 458762306a36Sopenharmony_ci * [Too numerous to mention...] 458862306a36Sopenharmony_ci * Verification Tag: No verification needed. 458962306a36Sopenharmony_ci * Inputs 459062306a36Sopenharmony_ci * (endpoint, asoc, chunk) 459162306a36Sopenharmony_ci * 459262306a36Sopenharmony_ci * Outputs 459362306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 459462306a36Sopenharmony_ci * 459562306a36Sopenharmony_ci * The return value is the disposition of the chunk. 459662306a36Sopenharmony_ci */ 459762306a36Sopenharmony_cienum sctp_disposition sctp_sf_discard_chunk(struct net *net, 459862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 459962306a36Sopenharmony_ci const struct sctp_association *asoc, 460062306a36Sopenharmony_ci const union sctp_subtype type, 460162306a36Sopenharmony_ci void *arg, 460262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 460362306a36Sopenharmony_ci{ 460462306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 460562306a36Sopenharmony_ci 460662306a36Sopenharmony_ci if (asoc && !sctp_vtag_verify(chunk, asoc)) 460762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 460862306a36Sopenharmony_ci 460962306a36Sopenharmony_ci /* Make sure that the chunk has a valid length. 461062306a36Sopenharmony_ci * Since we don't know the chunk type, we use a general 461162306a36Sopenharmony_ci * chunkhdr structure to make a comparison. 461262306a36Sopenharmony_ci */ 461362306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 461462306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 461562306a36Sopenharmony_ci commands); 461662306a36Sopenharmony_ci 461762306a36Sopenharmony_ci pr_debug("%s: chunk:%d is discarded\n", __func__, type.chunk); 461862306a36Sopenharmony_ci 461962306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 462062306a36Sopenharmony_ci} 462162306a36Sopenharmony_ci 462262306a36Sopenharmony_ci/* 462362306a36Sopenharmony_ci * Discard the whole packet. 462462306a36Sopenharmony_ci * 462562306a36Sopenharmony_ci * Section: 8.4 2) 462662306a36Sopenharmony_ci * 462762306a36Sopenharmony_ci * 2) If the OOTB packet contains an ABORT chunk, the receiver MUST 462862306a36Sopenharmony_ci * silently discard the OOTB packet and take no further action. 462962306a36Sopenharmony_ci * 463062306a36Sopenharmony_ci * Verification Tag: No verification necessary 463162306a36Sopenharmony_ci * 463262306a36Sopenharmony_ci * Inputs 463362306a36Sopenharmony_ci * (endpoint, asoc, chunk) 463462306a36Sopenharmony_ci * 463562306a36Sopenharmony_ci * Outputs 463662306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 463762306a36Sopenharmony_ci * 463862306a36Sopenharmony_ci * The return value is the disposition of the chunk. 463962306a36Sopenharmony_ci */ 464062306a36Sopenharmony_cienum sctp_disposition sctp_sf_pdiscard(struct net *net, 464162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 464262306a36Sopenharmony_ci const struct sctp_association *asoc, 464362306a36Sopenharmony_ci const union sctp_subtype type, 464462306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 464562306a36Sopenharmony_ci{ 464662306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS); 464762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 464862306a36Sopenharmony_ci 464962306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 465062306a36Sopenharmony_ci} 465162306a36Sopenharmony_ci 465262306a36Sopenharmony_ci 465362306a36Sopenharmony_ci/* 465462306a36Sopenharmony_ci * The other end is violating protocol. 465562306a36Sopenharmony_ci * 465662306a36Sopenharmony_ci * Section: Not specified 465762306a36Sopenharmony_ci * Verification Tag: Not specified 465862306a36Sopenharmony_ci * Inputs 465962306a36Sopenharmony_ci * (endpoint, asoc, chunk) 466062306a36Sopenharmony_ci * 466162306a36Sopenharmony_ci * Outputs 466262306a36Sopenharmony_ci * (asoc, reply_msg, msg_up, timers, counters) 466362306a36Sopenharmony_ci * 466462306a36Sopenharmony_ci * We simply tag the chunk as a violation. The state machine will log 466562306a36Sopenharmony_ci * the violation and continue. 466662306a36Sopenharmony_ci */ 466762306a36Sopenharmony_cienum sctp_disposition sctp_sf_violation(struct net *net, 466862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 466962306a36Sopenharmony_ci const struct sctp_association *asoc, 467062306a36Sopenharmony_ci const union sctp_subtype type, 467162306a36Sopenharmony_ci void *arg, 467262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 467362306a36Sopenharmony_ci{ 467462306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 467562306a36Sopenharmony_ci 467662306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 467762306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); 467862306a36Sopenharmony_ci 467962306a36Sopenharmony_ci /* Make sure that the chunk has a valid length. */ 468062306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) 468162306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, 468262306a36Sopenharmony_ci commands); 468362306a36Sopenharmony_ci 468462306a36Sopenharmony_ci return SCTP_DISPOSITION_VIOLATION; 468562306a36Sopenharmony_ci} 468662306a36Sopenharmony_ci 468762306a36Sopenharmony_ci/* 468862306a36Sopenharmony_ci * Common function to handle a protocol violation. 468962306a36Sopenharmony_ci */ 469062306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_abort_violation( 469162306a36Sopenharmony_ci struct net *net, 469262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 469362306a36Sopenharmony_ci const struct sctp_association *asoc, 469462306a36Sopenharmony_ci void *arg, 469562306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 469662306a36Sopenharmony_ci const __u8 *payload, 469762306a36Sopenharmony_ci const size_t paylen) 469862306a36Sopenharmony_ci{ 469962306a36Sopenharmony_ci struct sctp_packet *packet = NULL; 470062306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 470162306a36Sopenharmony_ci struct sctp_chunk *abort = NULL; 470262306a36Sopenharmony_ci 470362306a36Sopenharmony_ci /* SCTP-AUTH, Section 6.3: 470462306a36Sopenharmony_ci * It should be noted that if the receiver wants to tear 470562306a36Sopenharmony_ci * down an association in an authenticated way only, the 470662306a36Sopenharmony_ci * handling of malformed packets should not result in 470762306a36Sopenharmony_ci * tearing down the association. 470862306a36Sopenharmony_ci * 470962306a36Sopenharmony_ci * This means that if we only want to abort associations 471062306a36Sopenharmony_ci * in an authenticated way (i.e AUTH+ABORT), then we 471162306a36Sopenharmony_ci * can't destroy this association just because the packet 471262306a36Sopenharmony_ci * was malformed. 471362306a36Sopenharmony_ci */ 471462306a36Sopenharmony_ci if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 471562306a36Sopenharmony_ci goto discard; 471662306a36Sopenharmony_ci 471762306a36Sopenharmony_ci /* Make the abort chunk. */ 471862306a36Sopenharmony_ci abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); 471962306a36Sopenharmony_ci if (!abort) 472062306a36Sopenharmony_ci goto nomem; 472162306a36Sopenharmony_ci 472262306a36Sopenharmony_ci if (asoc) { 472362306a36Sopenharmony_ci /* Treat INIT-ACK as a special case during COOKIE-WAIT. */ 472462306a36Sopenharmony_ci if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK && 472562306a36Sopenharmony_ci !asoc->peer.i.init_tag) { 472662306a36Sopenharmony_ci struct sctp_initack_chunk *initack; 472762306a36Sopenharmony_ci 472862306a36Sopenharmony_ci initack = (struct sctp_initack_chunk *)chunk->chunk_hdr; 472962306a36Sopenharmony_ci if (!sctp_chunk_length_valid(chunk, sizeof(*initack))) 473062306a36Sopenharmony_ci abort->chunk_hdr->flags |= SCTP_CHUNK_FLAG_T; 473162306a36Sopenharmony_ci else { 473262306a36Sopenharmony_ci unsigned int inittag; 473362306a36Sopenharmony_ci 473462306a36Sopenharmony_ci inittag = ntohl(initack->init_hdr.init_tag); 473562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_INITTAG, 473662306a36Sopenharmony_ci SCTP_U32(inittag)); 473762306a36Sopenharmony_ci } 473862306a36Sopenharmony_ci } 473962306a36Sopenharmony_ci 474062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 474162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 474262306a36Sopenharmony_ci 474362306a36Sopenharmony_ci if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { 474462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 474562306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 474662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 474762306a36Sopenharmony_ci SCTP_ERROR(ECONNREFUSED)); 474862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 474962306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); 475062306a36Sopenharmony_ci } else { 475162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 475262306a36Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 475362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 475462306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); 475562306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 475662306a36Sopenharmony_ci } 475762306a36Sopenharmony_ci } else { 475862306a36Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 475962306a36Sopenharmony_ci 476062306a36Sopenharmony_ci if (!packet) 476162306a36Sopenharmony_ci goto nomem_pkt; 476262306a36Sopenharmony_ci 476362306a36Sopenharmony_ci if (sctp_test_T_bit(abort)) 476462306a36Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 476562306a36Sopenharmony_ci 476662306a36Sopenharmony_ci abort->skb->sk = ep->base.sk; 476762306a36Sopenharmony_ci 476862306a36Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 476962306a36Sopenharmony_ci 477062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 477162306a36Sopenharmony_ci SCTP_PACKET(packet)); 477262306a36Sopenharmony_ci 477362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 477462306a36Sopenharmony_ci } 477562306a36Sopenharmony_ci 477662306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 477762306a36Sopenharmony_ci 477862306a36Sopenharmony_cidiscard: 477962306a36Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands); 478062306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 478162306a36Sopenharmony_ci 478262306a36Sopenharmony_cinomem_pkt: 478362306a36Sopenharmony_ci sctp_chunk_free(abort); 478462306a36Sopenharmony_cinomem: 478562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 478662306a36Sopenharmony_ci} 478762306a36Sopenharmony_ci 478862306a36Sopenharmony_ci/* 478962306a36Sopenharmony_ci * Handle a protocol violation when the chunk length is invalid. 479062306a36Sopenharmony_ci * "Invalid" length is identified as smaller than the minimal length a 479162306a36Sopenharmony_ci * given chunk can be. For example, a SACK chunk has invalid length 479262306a36Sopenharmony_ci * if its length is set to be smaller than the size of struct sctp_sack_chunk. 479362306a36Sopenharmony_ci * 479462306a36Sopenharmony_ci * We inform the other end by sending an ABORT with a Protocol Violation 479562306a36Sopenharmony_ci * error code. 479662306a36Sopenharmony_ci * 479762306a36Sopenharmony_ci * Section: Not specified 479862306a36Sopenharmony_ci * Verification Tag: Nothing to do 479962306a36Sopenharmony_ci * Inputs 480062306a36Sopenharmony_ci * (endpoint, asoc, chunk) 480162306a36Sopenharmony_ci * 480262306a36Sopenharmony_ci * Outputs 480362306a36Sopenharmony_ci * (reply_msg, msg_up, counters) 480462306a36Sopenharmony_ci * 480562306a36Sopenharmony_ci * Generate an ABORT chunk and terminate the association. 480662306a36Sopenharmony_ci */ 480762306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunklen( 480862306a36Sopenharmony_ci struct net *net, 480962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 481062306a36Sopenharmony_ci const struct sctp_association *asoc, 481162306a36Sopenharmony_ci const union sctp_subtype type, 481262306a36Sopenharmony_ci void *arg, 481362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 481462306a36Sopenharmony_ci{ 481562306a36Sopenharmony_ci static const char err_str[] = "The following chunk had invalid length:"; 481662306a36Sopenharmony_ci 481762306a36Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, 481862306a36Sopenharmony_ci sizeof(err_str)); 481962306a36Sopenharmony_ci} 482062306a36Sopenharmony_ci 482162306a36Sopenharmony_ci/* 482262306a36Sopenharmony_ci * Handle a protocol violation when the parameter length is invalid. 482362306a36Sopenharmony_ci * If the length is smaller than the minimum length of a given parameter, 482462306a36Sopenharmony_ci * or accumulated length in multi parameters exceeds the end of the chunk, 482562306a36Sopenharmony_ci * the length is considered as invalid. 482662306a36Sopenharmony_ci */ 482762306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_paramlen( 482862306a36Sopenharmony_ci struct net *net, 482962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 483062306a36Sopenharmony_ci const struct sctp_association *asoc, 483162306a36Sopenharmony_ci const union sctp_subtype type, 483262306a36Sopenharmony_ci void *arg, void *ext, 483362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 483462306a36Sopenharmony_ci{ 483562306a36Sopenharmony_ci struct sctp_paramhdr *param = ext; 483662306a36Sopenharmony_ci struct sctp_chunk *abort = NULL; 483762306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 483862306a36Sopenharmony_ci 483962306a36Sopenharmony_ci if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 484062306a36Sopenharmony_ci goto discard; 484162306a36Sopenharmony_ci 484262306a36Sopenharmony_ci /* Make the abort chunk. */ 484362306a36Sopenharmony_ci abort = sctp_make_violation_paramlen(asoc, chunk, param); 484462306a36Sopenharmony_ci if (!abort) 484562306a36Sopenharmony_ci goto nomem; 484662306a36Sopenharmony_ci 484762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 484862306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 484962306a36Sopenharmony_ci 485062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 485162306a36Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 485262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 485362306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); 485462306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 485562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 485662306a36Sopenharmony_ci 485762306a36Sopenharmony_cidiscard: 485862306a36Sopenharmony_ci sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands); 485962306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 486062306a36Sopenharmony_cinomem: 486162306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 486262306a36Sopenharmony_ci} 486362306a36Sopenharmony_ci 486462306a36Sopenharmony_ci/* Handle a protocol violation when the peer trying to advance the 486562306a36Sopenharmony_ci * cumulative tsn ack to a point beyond the max tsn currently sent. 486662306a36Sopenharmony_ci * 486762306a36Sopenharmony_ci * We inform the other end by sending an ABORT with a Protocol Violation 486862306a36Sopenharmony_ci * error code. 486962306a36Sopenharmony_ci */ 487062306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_ctsn( 487162306a36Sopenharmony_ci struct net *net, 487262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 487362306a36Sopenharmony_ci const struct sctp_association *asoc, 487462306a36Sopenharmony_ci const union sctp_subtype type, 487562306a36Sopenharmony_ci void *arg, 487662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 487762306a36Sopenharmony_ci{ 487862306a36Sopenharmony_ci static const char err_str[] = "The cumulative tsn ack beyond the max tsn currently sent:"; 487962306a36Sopenharmony_ci 488062306a36Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, 488162306a36Sopenharmony_ci sizeof(err_str)); 488262306a36Sopenharmony_ci} 488362306a36Sopenharmony_ci 488462306a36Sopenharmony_ci/* Handle protocol violation of an invalid chunk bundling. For example, 488562306a36Sopenharmony_ci * when we have an association and we receive bundled INIT-ACK, or 488662306a36Sopenharmony_ci * SHUTDOWN-COMPLETE, our peer is clearly violating the "MUST NOT bundle" 488762306a36Sopenharmony_ci * statement from the specs. Additionally, there might be an attacker 488862306a36Sopenharmony_ci * on the path and we may not want to continue this communication. 488962306a36Sopenharmony_ci */ 489062306a36Sopenharmony_cistatic enum sctp_disposition sctp_sf_violation_chunk( 489162306a36Sopenharmony_ci struct net *net, 489262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 489362306a36Sopenharmony_ci const struct sctp_association *asoc, 489462306a36Sopenharmony_ci const union sctp_subtype type, 489562306a36Sopenharmony_ci void *arg, 489662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 489762306a36Sopenharmony_ci{ 489862306a36Sopenharmony_ci static const char err_str[] = "The following chunk violates protocol:"; 489962306a36Sopenharmony_ci 490062306a36Sopenharmony_ci return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, 490162306a36Sopenharmony_ci sizeof(err_str)); 490262306a36Sopenharmony_ci} 490362306a36Sopenharmony_ci/*************************************************************************** 490462306a36Sopenharmony_ci * These are the state functions for handling primitive (Section 10) events. 490562306a36Sopenharmony_ci ***************************************************************************/ 490662306a36Sopenharmony_ci/* 490762306a36Sopenharmony_ci * sctp_sf_do_prm_asoc 490862306a36Sopenharmony_ci * 490962306a36Sopenharmony_ci * Section: 10.1 ULP-to-SCTP 491062306a36Sopenharmony_ci * B) Associate 491162306a36Sopenharmony_ci * 491262306a36Sopenharmony_ci * Format: ASSOCIATE(local SCTP instance name, destination transport addr, 491362306a36Sopenharmony_ci * outbound stream count) 491462306a36Sopenharmony_ci * -> association id [,destination transport addr list] [,outbound stream 491562306a36Sopenharmony_ci * count] 491662306a36Sopenharmony_ci * 491762306a36Sopenharmony_ci * This primitive allows the upper layer to initiate an association to a 491862306a36Sopenharmony_ci * specific peer endpoint. 491962306a36Sopenharmony_ci * 492062306a36Sopenharmony_ci * The peer endpoint shall be specified by one of the transport addresses 492162306a36Sopenharmony_ci * which defines the endpoint (see Section 1.4). If the local SCTP 492262306a36Sopenharmony_ci * instance has not been initialized, the ASSOCIATE is considered an 492362306a36Sopenharmony_ci * error. 492462306a36Sopenharmony_ci * [This is not relevant for the kernel implementation since we do all 492562306a36Sopenharmony_ci * initialization at boot time. It we hadn't initialized we wouldn't 492662306a36Sopenharmony_ci * get anywhere near this code.] 492762306a36Sopenharmony_ci * 492862306a36Sopenharmony_ci * An association id, which is a local handle to the SCTP association, 492962306a36Sopenharmony_ci * will be returned on successful establishment of the association. If 493062306a36Sopenharmony_ci * SCTP is not able to open an SCTP association with the peer endpoint, 493162306a36Sopenharmony_ci * an error is returned. 493262306a36Sopenharmony_ci * [In the kernel implementation, the struct sctp_association needs to 493362306a36Sopenharmony_ci * be created BEFORE causing this primitive to run.] 493462306a36Sopenharmony_ci * 493562306a36Sopenharmony_ci * Other association parameters may be returned, including the 493662306a36Sopenharmony_ci * complete destination transport addresses of the peer as well as the 493762306a36Sopenharmony_ci * outbound stream count of the local endpoint. One of the transport 493862306a36Sopenharmony_ci * address from the returned destination addresses will be selected by 493962306a36Sopenharmony_ci * the local endpoint as default primary path for sending SCTP packets 494062306a36Sopenharmony_ci * to this peer. The returned "destination transport addr list" can 494162306a36Sopenharmony_ci * be used by the ULP to change the default primary path or to force 494262306a36Sopenharmony_ci * sending a packet to a specific transport address. [All of this 494362306a36Sopenharmony_ci * stuff happens when the INIT ACK arrives. This is a NON-BLOCKING 494462306a36Sopenharmony_ci * function.] 494562306a36Sopenharmony_ci * 494662306a36Sopenharmony_ci * Mandatory attributes: 494762306a36Sopenharmony_ci * 494862306a36Sopenharmony_ci * o local SCTP instance name - obtained from the INITIALIZE operation. 494962306a36Sopenharmony_ci * [This is the argument asoc.] 495062306a36Sopenharmony_ci * o destination transport addr - specified as one of the transport 495162306a36Sopenharmony_ci * addresses of the peer endpoint with which the association is to be 495262306a36Sopenharmony_ci * established. 495362306a36Sopenharmony_ci * [This is asoc->peer.active_path.] 495462306a36Sopenharmony_ci * o outbound stream count - the number of outbound streams the ULP 495562306a36Sopenharmony_ci * would like to open towards this peer endpoint. 495662306a36Sopenharmony_ci * [BUG: This is not currently implemented.] 495762306a36Sopenharmony_ci * Optional attributes: 495862306a36Sopenharmony_ci * 495962306a36Sopenharmony_ci * None. 496062306a36Sopenharmony_ci * 496162306a36Sopenharmony_ci * The return value is a disposition. 496262306a36Sopenharmony_ci */ 496362306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_asoc(struct net *net, 496462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 496562306a36Sopenharmony_ci const struct sctp_association *asoc, 496662306a36Sopenharmony_ci const union sctp_subtype type, 496762306a36Sopenharmony_ci void *arg, 496862306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 496962306a36Sopenharmony_ci{ 497062306a36Sopenharmony_ci struct sctp_association *my_asoc; 497162306a36Sopenharmony_ci struct sctp_chunk *repl; 497262306a36Sopenharmony_ci 497362306a36Sopenharmony_ci /* The comment below says that we enter COOKIE-WAIT AFTER 497462306a36Sopenharmony_ci * sending the INIT, but that doesn't actually work in our 497562306a36Sopenharmony_ci * implementation... 497662306a36Sopenharmony_ci */ 497762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 497862306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_COOKIE_WAIT)); 497962306a36Sopenharmony_ci 498062306a36Sopenharmony_ci /* RFC 2960 5.1 Normal Establishment of an Association 498162306a36Sopenharmony_ci * 498262306a36Sopenharmony_ci * A) "A" first sends an INIT chunk to "Z". In the INIT, "A" 498362306a36Sopenharmony_ci * must provide its Verification Tag (Tag_A) in the Initiate 498462306a36Sopenharmony_ci * Tag field. Tag_A SHOULD be a random number in the range of 498562306a36Sopenharmony_ci * 1 to 4294967295 (see 5.3.1 for Tag value selection). ... 498662306a36Sopenharmony_ci */ 498762306a36Sopenharmony_ci 498862306a36Sopenharmony_ci repl = sctp_make_init(asoc, &asoc->base.bind_addr, GFP_ATOMIC, 0); 498962306a36Sopenharmony_ci if (!repl) 499062306a36Sopenharmony_ci goto nomem; 499162306a36Sopenharmony_ci 499262306a36Sopenharmony_ci /* Choose transport for INIT. */ 499362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, 499462306a36Sopenharmony_ci SCTP_CHUNK(repl)); 499562306a36Sopenharmony_ci 499662306a36Sopenharmony_ci /* Cast away the const modifier, as we want to just 499762306a36Sopenharmony_ci * rerun it through as a sideffect. 499862306a36Sopenharmony_ci */ 499962306a36Sopenharmony_ci my_asoc = (struct sctp_association *)asoc; 500062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(my_asoc)); 500162306a36Sopenharmony_ci 500262306a36Sopenharmony_ci /* After sending the INIT, "A" starts the T1-init timer and 500362306a36Sopenharmony_ci * enters the COOKIE-WAIT state. 500462306a36Sopenharmony_ci */ 500562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 500662306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 500762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 500862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 500962306a36Sopenharmony_ci 501062306a36Sopenharmony_cinomem: 501162306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 501262306a36Sopenharmony_ci} 501362306a36Sopenharmony_ci 501462306a36Sopenharmony_ci/* 501562306a36Sopenharmony_ci * Process the SEND primitive. 501662306a36Sopenharmony_ci * 501762306a36Sopenharmony_ci * Section: 10.1 ULP-to-SCTP 501862306a36Sopenharmony_ci * E) Send 501962306a36Sopenharmony_ci * 502062306a36Sopenharmony_ci * Format: SEND(association id, buffer address, byte count [,context] 502162306a36Sopenharmony_ci * [,stream id] [,life time] [,destination transport address] 502262306a36Sopenharmony_ci * [,unorder flag] [,no-bundle flag] [,payload protocol-id] ) 502362306a36Sopenharmony_ci * -> result 502462306a36Sopenharmony_ci * 502562306a36Sopenharmony_ci * This is the main method to send user data via SCTP. 502662306a36Sopenharmony_ci * 502762306a36Sopenharmony_ci * Mandatory attributes: 502862306a36Sopenharmony_ci * 502962306a36Sopenharmony_ci * o association id - local handle to the SCTP association 503062306a36Sopenharmony_ci * 503162306a36Sopenharmony_ci * o buffer address - the location where the user message to be 503262306a36Sopenharmony_ci * transmitted is stored; 503362306a36Sopenharmony_ci * 503462306a36Sopenharmony_ci * o byte count - The size of the user data in number of bytes; 503562306a36Sopenharmony_ci * 503662306a36Sopenharmony_ci * Optional attributes: 503762306a36Sopenharmony_ci * 503862306a36Sopenharmony_ci * o context - an optional 32 bit integer that will be carried in the 503962306a36Sopenharmony_ci * sending failure notification to the ULP if the transportation of 504062306a36Sopenharmony_ci * this User Message fails. 504162306a36Sopenharmony_ci * 504262306a36Sopenharmony_ci * o stream id - to indicate which stream to send the data on. If not 504362306a36Sopenharmony_ci * specified, stream 0 will be used. 504462306a36Sopenharmony_ci * 504562306a36Sopenharmony_ci * o life time - specifies the life time of the user data. The user data 504662306a36Sopenharmony_ci * will not be sent by SCTP after the life time expires. This 504762306a36Sopenharmony_ci * parameter can be used to avoid efforts to transmit stale 504862306a36Sopenharmony_ci * user messages. SCTP notifies the ULP if the data cannot be 504962306a36Sopenharmony_ci * initiated to transport (i.e. sent to the destination via SCTP's 505062306a36Sopenharmony_ci * send primitive) within the life time variable. However, the 505162306a36Sopenharmony_ci * user data will be transmitted if SCTP has attempted to transmit a 505262306a36Sopenharmony_ci * chunk before the life time expired. 505362306a36Sopenharmony_ci * 505462306a36Sopenharmony_ci * o destination transport address - specified as one of the destination 505562306a36Sopenharmony_ci * transport addresses of the peer endpoint to which this packet 505662306a36Sopenharmony_ci * should be sent. Whenever possible, SCTP should use this destination 505762306a36Sopenharmony_ci * transport address for sending the packets, instead of the current 505862306a36Sopenharmony_ci * primary path. 505962306a36Sopenharmony_ci * 506062306a36Sopenharmony_ci * o unorder flag - this flag, if present, indicates that the user 506162306a36Sopenharmony_ci * would like the data delivered in an unordered fashion to the peer 506262306a36Sopenharmony_ci * (i.e., the U flag is set to 1 on all DATA chunks carrying this 506362306a36Sopenharmony_ci * message). 506462306a36Sopenharmony_ci * 506562306a36Sopenharmony_ci * o no-bundle flag - instructs SCTP not to bundle this user data with 506662306a36Sopenharmony_ci * other outbound DATA chunks. SCTP MAY still bundle even when 506762306a36Sopenharmony_ci * this flag is present, when faced with network congestion. 506862306a36Sopenharmony_ci * 506962306a36Sopenharmony_ci * o payload protocol-id - A 32 bit unsigned integer that is to be 507062306a36Sopenharmony_ci * passed to the peer indicating the type of payload protocol data 507162306a36Sopenharmony_ci * being transmitted. This value is passed as opaque data by SCTP. 507262306a36Sopenharmony_ci * 507362306a36Sopenharmony_ci * The return value is the disposition. 507462306a36Sopenharmony_ci */ 507562306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_send(struct net *net, 507662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 507762306a36Sopenharmony_ci const struct sctp_association *asoc, 507862306a36Sopenharmony_ci const union sctp_subtype type, 507962306a36Sopenharmony_ci void *arg, 508062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 508162306a36Sopenharmony_ci{ 508262306a36Sopenharmony_ci struct sctp_datamsg *msg = arg; 508362306a36Sopenharmony_ci 508462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_MSG, SCTP_DATAMSG(msg)); 508562306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 508662306a36Sopenharmony_ci} 508762306a36Sopenharmony_ci 508862306a36Sopenharmony_ci/* 508962306a36Sopenharmony_ci * Process the SHUTDOWN primitive. 509062306a36Sopenharmony_ci * 509162306a36Sopenharmony_ci * Section: 10.1: 509262306a36Sopenharmony_ci * C) Shutdown 509362306a36Sopenharmony_ci * 509462306a36Sopenharmony_ci * Format: SHUTDOWN(association id) 509562306a36Sopenharmony_ci * -> result 509662306a36Sopenharmony_ci * 509762306a36Sopenharmony_ci * Gracefully closes an association. Any locally queued user data 509862306a36Sopenharmony_ci * will be delivered to the peer. The association will be terminated only 509962306a36Sopenharmony_ci * after the peer acknowledges all the SCTP packets sent. A success code 510062306a36Sopenharmony_ci * will be returned on successful termination of the association. If 510162306a36Sopenharmony_ci * attempting to terminate the association results in a failure, an error 510262306a36Sopenharmony_ci * code shall be returned. 510362306a36Sopenharmony_ci * 510462306a36Sopenharmony_ci * Mandatory attributes: 510562306a36Sopenharmony_ci * 510662306a36Sopenharmony_ci * o association id - local handle to the SCTP association 510762306a36Sopenharmony_ci * 510862306a36Sopenharmony_ci * Optional attributes: 510962306a36Sopenharmony_ci * 511062306a36Sopenharmony_ci * None. 511162306a36Sopenharmony_ci * 511262306a36Sopenharmony_ci * The return value is the disposition. 511362306a36Sopenharmony_ci */ 511462306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_prm_shutdown( 511562306a36Sopenharmony_ci struct net *net, 511662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 511762306a36Sopenharmony_ci const struct sctp_association *asoc, 511862306a36Sopenharmony_ci const union sctp_subtype type, 511962306a36Sopenharmony_ci void *arg, 512062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 512162306a36Sopenharmony_ci{ 512262306a36Sopenharmony_ci enum sctp_disposition disposition; 512362306a36Sopenharmony_ci 512462306a36Sopenharmony_ci /* From 9.2 Shutdown of an Association 512562306a36Sopenharmony_ci * Upon receipt of the SHUTDOWN primitive from its upper 512662306a36Sopenharmony_ci * layer, the endpoint enters SHUTDOWN-PENDING state and 512762306a36Sopenharmony_ci * remains there until all outstanding data has been 512862306a36Sopenharmony_ci * acknowledged by its peer. The endpoint accepts no new data 512962306a36Sopenharmony_ci * from its upper layer, but retransmits data to the far end 513062306a36Sopenharmony_ci * if necessary to fill gaps. 513162306a36Sopenharmony_ci */ 513262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 513362306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); 513462306a36Sopenharmony_ci 513562306a36Sopenharmony_ci disposition = SCTP_DISPOSITION_CONSUME; 513662306a36Sopenharmony_ci if (sctp_outq_is_empty(&asoc->outqueue)) { 513762306a36Sopenharmony_ci disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type, 513862306a36Sopenharmony_ci arg, commands); 513962306a36Sopenharmony_ci } 514062306a36Sopenharmony_ci 514162306a36Sopenharmony_ci return disposition; 514262306a36Sopenharmony_ci} 514362306a36Sopenharmony_ci 514462306a36Sopenharmony_ci/* 514562306a36Sopenharmony_ci * Process the ABORT primitive. 514662306a36Sopenharmony_ci * 514762306a36Sopenharmony_ci * Section: 10.1: 514862306a36Sopenharmony_ci * C) Abort 514962306a36Sopenharmony_ci * 515062306a36Sopenharmony_ci * Format: Abort(association id [, cause code]) 515162306a36Sopenharmony_ci * -> result 515262306a36Sopenharmony_ci * 515362306a36Sopenharmony_ci * Ungracefully closes an association. Any locally queued user data 515462306a36Sopenharmony_ci * will be discarded and an ABORT chunk is sent to the peer. A success code 515562306a36Sopenharmony_ci * will be returned on successful abortion of the association. If 515662306a36Sopenharmony_ci * attempting to abort the association results in a failure, an error 515762306a36Sopenharmony_ci * code shall be returned. 515862306a36Sopenharmony_ci * 515962306a36Sopenharmony_ci * Mandatory attributes: 516062306a36Sopenharmony_ci * 516162306a36Sopenharmony_ci * o association id - local handle to the SCTP association 516262306a36Sopenharmony_ci * 516362306a36Sopenharmony_ci * Optional attributes: 516462306a36Sopenharmony_ci * 516562306a36Sopenharmony_ci * o cause code - reason of the abort to be passed to the peer 516662306a36Sopenharmony_ci * 516762306a36Sopenharmony_ci * None. 516862306a36Sopenharmony_ci * 516962306a36Sopenharmony_ci * The return value is the disposition. 517062306a36Sopenharmony_ci */ 517162306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_1_prm_abort( 517262306a36Sopenharmony_ci struct net *net, 517362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 517462306a36Sopenharmony_ci const struct sctp_association *asoc, 517562306a36Sopenharmony_ci const union sctp_subtype type, 517662306a36Sopenharmony_ci void *arg, 517762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 517862306a36Sopenharmony_ci{ 517962306a36Sopenharmony_ci /* From 9.1 Abort of an Association 518062306a36Sopenharmony_ci * Upon receipt of the ABORT primitive from its upper 518162306a36Sopenharmony_ci * layer, the endpoint enters CLOSED state and 518262306a36Sopenharmony_ci * discard all outstanding data has been 518362306a36Sopenharmony_ci * acknowledged by its peer. The endpoint accepts no new data 518462306a36Sopenharmony_ci * from its upper layer, but retransmits data to the far end 518562306a36Sopenharmony_ci * if necessary to fill gaps. 518662306a36Sopenharmony_ci */ 518762306a36Sopenharmony_ci struct sctp_chunk *abort = arg; 518862306a36Sopenharmony_ci 518962306a36Sopenharmony_ci if (abort) 519062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 519162306a36Sopenharmony_ci 519262306a36Sopenharmony_ci /* Even if we can't send the ABORT due to low memory delete the 519362306a36Sopenharmony_ci * TCB. This is a departure from our typical NOMEM handling. 519462306a36Sopenharmony_ci */ 519562306a36Sopenharmony_ci 519662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 519762306a36Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 519862306a36Sopenharmony_ci /* Delete the established association. */ 519962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 520062306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_USER_ABORT)); 520162306a36Sopenharmony_ci 520262306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 520362306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 520462306a36Sopenharmony_ci 520562306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 520662306a36Sopenharmony_ci} 520762306a36Sopenharmony_ci 520862306a36Sopenharmony_ci/* We tried an illegal operation on an association which is closed. */ 520962306a36Sopenharmony_cienum sctp_disposition sctp_sf_error_closed(struct net *net, 521062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 521162306a36Sopenharmony_ci const struct sctp_association *asoc, 521262306a36Sopenharmony_ci const union sctp_subtype type, 521362306a36Sopenharmony_ci void *arg, 521462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 521562306a36Sopenharmony_ci{ 521662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_ERROR, SCTP_ERROR(-EINVAL)); 521762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 521862306a36Sopenharmony_ci} 521962306a36Sopenharmony_ci 522062306a36Sopenharmony_ci/* We tried an illegal operation on an association which is shutting 522162306a36Sopenharmony_ci * down. 522262306a36Sopenharmony_ci */ 522362306a36Sopenharmony_cienum sctp_disposition sctp_sf_error_shutdown( 522462306a36Sopenharmony_ci struct net *net, 522562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 522662306a36Sopenharmony_ci const struct sctp_association *asoc, 522762306a36Sopenharmony_ci const union sctp_subtype type, 522862306a36Sopenharmony_ci void *arg, 522962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 523062306a36Sopenharmony_ci{ 523162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_ERROR, 523262306a36Sopenharmony_ci SCTP_ERROR(-ESHUTDOWN)); 523362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 523462306a36Sopenharmony_ci} 523562306a36Sopenharmony_ci 523662306a36Sopenharmony_ci/* 523762306a36Sopenharmony_ci * sctp_cookie_wait_prm_shutdown 523862306a36Sopenharmony_ci * 523962306a36Sopenharmony_ci * Section: 4 Note: 2 524062306a36Sopenharmony_ci * Verification Tag: 524162306a36Sopenharmony_ci * Inputs 524262306a36Sopenharmony_ci * (endpoint, asoc) 524362306a36Sopenharmony_ci * 524462306a36Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 524562306a36Sopenharmony_ci * state table when someone issues a shutdown while in COOKIE_WAIT state. 524662306a36Sopenharmony_ci * 524762306a36Sopenharmony_ci * Outputs 524862306a36Sopenharmony_ci * (timers) 524962306a36Sopenharmony_ci */ 525062306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_prm_shutdown( 525162306a36Sopenharmony_ci struct net *net, 525262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 525362306a36Sopenharmony_ci const struct sctp_association *asoc, 525462306a36Sopenharmony_ci const union sctp_subtype type, 525562306a36Sopenharmony_ci void *arg, 525662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 525762306a36Sopenharmony_ci{ 525862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 525962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 526062306a36Sopenharmony_ci 526162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 526262306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 526362306a36Sopenharmony_ci 526462306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); 526562306a36Sopenharmony_ci 526662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 526762306a36Sopenharmony_ci 526862306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 526962306a36Sopenharmony_ci} 527062306a36Sopenharmony_ci 527162306a36Sopenharmony_ci/* 527262306a36Sopenharmony_ci * sctp_cookie_echoed_prm_shutdown 527362306a36Sopenharmony_ci * 527462306a36Sopenharmony_ci * Section: 4 Note: 2 527562306a36Sopenharmony_ci * Verification Tag: 527662306a36Sopenharmony_ci * Inputs 527762306a36Sopenharmony_ci * (endpoint, asoc) 527862306a36Sopenharmony_ci * 527962306a36Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 528062306a36Sopenharmony_ci * state table when someone issues a shutdown while in COOKIE_ECHOED state. 528162306a36Sopenharmony_ci * 528262306a36Sopenharmony_ci * Outputs 528362306a36Sopenharmony_ci * (timers) 528462306a36Sopenharmony_ci */ 528562306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_prm_shutdown( 528662306a36Sopenharmony_ci struct net *net, 528762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 528862306a36Sopenharmony_ci const struct sctp_association *asoc, 528962306a36Sopenharmony_ci const union sctp_subtype type, 529062306a36Sopenharmony_ci void *arg, 529162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 529262306a36Sopenharmony_ci{ 529362306a36Sopenharmony_ci /* There is a single T1 timer, so we should be able to use 529462306a36Sopenharmony_ci * common function with the COOKIE-WAIT state. 529562306a36Sopenharmony_ci */ 529662306a36Sopenharmony_ci return sctp_sf_cookie_wait_prm_shutdown(net, ep, asoc, type, arg, commands); 529762306a36Sopenharmony_ci} 529862306a36Sopenharmony_ci 529962306a36Sopenharmony_ci/* 530062306a36Sopenharmony_ci * sctp_sf_cookie_wait_prm_abort 530162306a36Sopenharmony_ci * 530262306a36Sopenharmony_ci * Section: 4 Note: 2 530362306a36Sopenharmony_ci * Verification Tag: 530462306a36Sopenharmony_ci * Inputs 530562306a36Sopenharmony_ci * (endpoint, asoc) 530662306a36Sopenharmony_ci * 530762306a36Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 530862306a36Sopenharmony_ci * state table when someone issues an abort while in COOKIE_WAIT state. 530962306a36Sopenharmony_ci * 531062306a36Sopenharmony_ci * Outputs 531162306a36Sopenharmony_ci * (timers) 531262306a36Sopenharmony_ci */ 531362306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_wait_prm_abort( 531462306a36Sopenharmony_ci struct net *net, 531562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 531662306a36Sopenharmony_ci const struct sctp_association *asoc, 531762306a36Sopenharmony_ci const union sctp_subtype type, 531862306a36Sopenharmony_ci void *arg, 531962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 532062306a36Sopenharmony_ci{ 532162306a36Sopenharmony_ci struct sctp_chunk *abort = arg; 532262306a36Sopenharmony_ci 532362306a36Sopenharmony_ci /* Stop T1-init timer */ 532462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 532562306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 532662306a36Sopenharmony_ci 532762306a36Sopenharmony_ci if (abort) 532862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 532962306a36Sopenharmony_ci 533062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 533162306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_CLOSED)); 533262306a36Sopenharmony_ci 533362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 533462306a36Sopenharmony_ci 533562306a36Sopenharmony_ci /* Even if we can't send the ABORT due to low memory delete the 533662306a36Sopenharmony_ci * TCB. This is a departure from our typical NOMEM handling. 533762306a36Sopenharmony_ci */ 533862306a36Sopenharmony_ci 533962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 534062306a36Sopenharmony_ci SCTP_ERROR(ECONNREFUSED)); 534162306a36Sopenharmony_ci /* Delete the established association. */ 534262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 534362306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_USER_ABORT)); 534462306a36Sopenharmony_ci 534562306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 534662306a36Sopenharmony_ci} 534762306a36Sopenharmony_ci 534862306a36Sopenharmony_ci/* 534962306a36Sopenharmony_ci * sctp_sf_cookie_echoed_prm_abort 535062306a36Sopenharmony_ci * 535162306a36Sopenharmony_ci * Section: 4 Note: 3 535262306a36Sopenharmony_ci * Verification Tag: 535362306a36Sopenharmony_ci * Inputs 535462306a36Sopenharmony_ci * (endpoint, asoc) 535562306a36Sopenharmony_ci * 535662306a36Sopenharmony_ci * The RFC does not explcitly address this issue, but is the route through the 535762306a36Sopenharmony_ci * state table when someone issues an abort while in COOKIE_ECHOED state. 535862306a36Sopenharmony_ci * 535962306a36Sopenharmony_ci * Outputs 536062306a36Sopenharmony_ci * (timers) 536162306a36Sopenharmony_ci */ 536262306a36Sopenharmony_cienum sctp_disposition sctp_sf_cookie_echoed_prm_abort( 536362306a36Sopenharmony_ci struct net *net, 536462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 536562306a36Sopenharmony_ci const struct sctp_association *asoc, 536662306a36Sopenharmony_ci const union sctp_subtype type, 536762306a36Sopenharmony_ci void *arg, 536862306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 536962306a36Sopenharmony_ci{ 537062306a36Sopenharmony_ci /* There is a single T1 timer, so we should be able to use 537162306a36Sopenharmony_ci * common function with the COOKIE-WAIT state. 537262306a36Sopenharmony_ci */ 537362306a36Sopenharmony_ci return sctp_sf_cookie_wait_prm_abort(net, ep, asoc, type, arg, commands); 537462306a36Sopenharmony_ci} 537562306a36Sopenharmony_ci 537662306a36Sopenharmony_ci/* 537762306a36Sopenharmony_ci * sctp_sf_shutdown_pending_prm_abort 537862306a36Sopenharmony_ci * 537962306a36Sopenharmony_ci * Inputs 538062306a36Sopenharmony_ci * (endpoint, asoc) 538162306a36Sopenharmony_ci * 538262306a36Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 538362306a36Sopenharmony_ci * state table when someone issues an abort while in SHUTDOWN-PENDING state. 538462306a36Sopenharmony_ci * 538562306a36Sopenharmony_ci * Outputs 538662306a36Sopenharmony_ci * (timers) 538762306a36Sopenharmony_ci */ 538862306a36Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_pending_prm_abort( 538962306a36Sopenharmony_ci struct net *net, 539062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 539162306a36Sopenharmony_ci const struct sctp_association *asoc, 539262306a36Sopenharmony_ci const union sctp_subtype type, 539362306a36Sopenharmony_ci void *arg, 539462306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 539562306a36Sopenharmony_ci{ 539662306a36Sopenharmony_ci /* Stop the T5-shutdown guard timer. */ 539762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 539862306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 539962306a36Sopenharmony_ci 540062306a36Sopenharmony_ci return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands); 540162306a36Sopenharmony_ci} 540262306a36Sopenharmony_ci 540362306a36Sopenharmony_ci/* 540462306a36Sopenharmony_ci * sctp_sf_shutdown_sent_prm_abort 540562306a36Sopenharmony_ci * 540662306a36Sopenharmony_ci * Inputs 540762306a36Sopenharmony_ci * (endpoint, asoc) 540862306a36Sopenharmony_ci * 540962306a36Sopenharmony_ci * The RFC does not explicitly address this issue, but is the route through the 541062306a36Sopenharmony_ci * state table when someone issues an abort while in SHUTDOWN-SENT state. 541162306a36Sopenharmony_ci * 541262306a36Sopenharmony_ci * Outputs 541362306a36Sopenharmony_ci * (timers) 541462306a36Sopenharmony_ci */ 541562306a36Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_sent_prm_abort( 541662306a36Sopenharmony_ci struct net *net, 541762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 541862306a36Sopenharmony_ci const struct sctp_association *asoc, 541962306a36Sopenharmony_ci const union sctp_subtype type, 542062306a36Sopenharmony_ci void *arg, 542162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 542262306a36Sopenharmony_ci{ 542362306a36Sopenharmony_ci /* Stop the T2-shutdown timer. */ 542462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 542562306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 542662306a36Sopenharmony_ci 542762306a36Sopenharmony_ci /* Stop the T5-shutdown guard timer. */ 542862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 542962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 543062306a36Sopenharmony_ci 543162306a36Sopenharmony_ci return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands); 543262306a36Sopenharmony_ci} 543362306a36Sopenharmony_ci 543462306a36Sopenharmony_ci/* 543562306a36Sopenharmony_ci * sctp_sf_cookie_echoed_prm_abort 543662306a36Sopenharmony_ci * 543762306a36Sopenharmony_ci * Inputs 543862306a36Sopenharmony_ci * (endpoint, asoc) 543962306a36Sopenharmony_ci * 544062306a36Sopenharmony_ci * The RFC does not explcitly address this issue, but is the route through the 544162306a36Sopenharmony_ci * state table when someone issues an abort while in COOKIE_ECHOED state. 544262306a36Sopenharmony_ci * 544362306a36Sopenharmony_ci * Outputs 544462306a36Sopenharmony_ci * (timers) 544562306a36Sopenharmony_ci */ 544662306a36Sopenharmony_cienum sctp_disposition sctp_sf_shutdown_ack_sent_prm_abort( 544762306a36Sopenharmony_ci struct net *net, 544862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 544962306a36Sopenharmony_ci const struct sctp_association *asoc, 545062306a36Sopenharmony_ci const union sctp_subtype type, 545162306a36Sopenharmony_ci void *arg, 545262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 545362306a36Sopenharmony_ci{ 545462306a36Sopenharmony_ci /* The same T2 timer, so we should be able to use 545562306a36Sopenharmony_ci * common function with the SHUTDOWN-SENT state. 545662306a36Sopenharmony_ci */ 545762306a36Sopenharmony_ci return sctp_sf_shutdown_sent_prm_abort(net, ep, asoc, type, arg, commands); 545862306a36Sopenharmony_ci} 545962306a36Sopenharmony_ci 546062306a36Sopenharmony_ci/* 546162306a36Sopenharmony_ci * Process the REQUESTHEARTBEAT primitive 546262306a36Sopenharmony_ci * 546362306a36Sopenharmony_ci * 10.1 ULP-to-SCTP 546462306a36Sopenharmony_ci * J) Request Heartbeat 546562306a36Sopenharmony_ci * 546662306a36Sopenharmony_ci * Format: REQUESTHEARTBEAT(association id, destination transport address) 546762306a36Sopenharmony_ci * 546862306a36Sopenharmony_ci * -> result 546962306a36Sopenharmony_ci * 547062306a36Sopenharmony_ci * Instructs the local endpoint to perform a HeartBeat on the specified 547162306a36Sopenharmony_ci * destination transport address of the given association. The returned 547262306a36Sopenharmony_ci * result should indicate whether the transmission of the HEARTBEAT 547362306a36Sopenharmony_ci * chunk to the destination address is successful. 547462306a36Sopenharmony_ci * 547562306a36Sopenharmony_ci * Mandatory attributes: 547662306a36Sopenharmony_ci * 547762306a36Sopenharmony_ci * o association id - local handle to the SCTP association 547862306a36Sopenharmony_ci * 547962306a36Sopenharmony_ci * o destination transport address - the transport address of the 548062306a36Sopenharmony_ci * association on which a heartbeat should be issued. 548162306a36Sopenharmony_ci */ 548262306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_requestheartbeat( 548362306a36Sopenharmony_ci struct net *net, 548462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 548562306a36Sopenharmony_ci const struct sctp_association *asoc, 548662306a36Sopenharmony_ci const union sctp_subtype type, 548762306a36Sopenharmony_ci void *arg, 548862306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 548962306a36Sopenharmony_ci{ 549062306a36Sopenharmony_ci if (SCTP_DISPOSITION_NOMEM == sctp_sf_heartbeat(ep, asoc, type, 549162306a36Sopenharmony_ci (struct sctp_transport *)arg, commands)) 549262306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 549362306a36Sopenharmony_ci 549462306a36Sopenharmony_ci /* 549562306a36Sopenharmony_ci * RFC 2960 (bis), section 8.3 549662306a36Sopenharmony_ci * 549762306a36Sopenharmony_ci * D) Request an on-demand HEARTBEAT on a specific destination 549862306a36Sopenharmony_ci * transport address of a given association. 549962306a36Sopenharmony_ci * 550062306a36Sopenharmony_ci * The endpoint should increment the respective error counter of 550162306a36Sopenharmony_ci * the destination transport address each time a HEARTBEAT is sent 550262306a36Sopenharmony_ci * to that address and not acknowledged within one RTO. 550362306a36Sopenharmony_ci * 550462306a36Sopenharmony_ci */ 550562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, 550662306a36Sopenharmony_ci SCTP_TRANSPORT(arg)); 550762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 550862306a36Sopenharmony_ci} 550962306a36Sopenharmony_ci 551062306a36Sopenharmony_ci/* 551162306a36Sopenharmony_ci * ADDIP Section 4.1 ASCONF Chunk Procedures 551262306a36Sopenharmony_ci * When an endpoint has an ASCONF signaled change to be sent to the 551362306a36Sopenharmony_ci * remote endpoint it should do A1 to A9 551462306a36Sopenharmony_ci */ 551562306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_asconf(struct net *net, 551662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 551762306a36Sopenharmony_ci const struct sctp_association *asoc, 551862306a36Sopenharmony_ci const union sctp_subtype type, 551962306a36Sopenharmony_ci void *arg, 552062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 552162306a36Sopenharmony_ci{ 552262306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 552362306a36Sopenharmony_ci 552462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); 552562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 552662306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 552762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); 552862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 552962306a36Sopenharmony_ci} 553062306a36Sopenharmony_ci 553162306a36Sopenharmony_ci/* RE-CONFIG Section 5.1 RECONF Chunk Procedures */ 553262306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_prm_reconf(struct net *net, 553362306a36Sopenharmony_ci const struct sctp_endpoint *ep, 553462306a36Sopenharmony_ci const struct sctp_association *asoc, 553562306a36Sopenharmony_ci const union sctp_subtype type, 553662306a36Sopenharmony_ci void *arg, 553762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 553862306a36Sopenharmony_ci{ 553962306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 554062306a36Sopenharmony_ci 554162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); 554262306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 554362306a36Sopenharmony_ci} 554462306a36Sopenharmony_ci 554562306a36Sopenharmony_ci/* 554662306a36Sopenharmony_ci * Ignore the primitive event 554762306a36Sopenharmony_ci * 554862306a36Sopenharmony_ci * The return value is the disposition of the primitive. 554962306a36Sopenharmony_ci */ 555062306a36Sopenharmony_cienum sctp_disposition sctp_sf_ignore_primitive( 555162306a36Sopenharmony_ci struct net *net, 555262306a36Sopenharmony_ci const struct sctp_endpoint *ep, 555362306a36Sopenharmony_ci const struct sctp_association *asoc, 555462306a36Sopenharmony_ci const union sctp_subtype type, 555562306a36Sopenharmony_ci void *arg, 555662306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 555762306a36Sopenharmony_ci{ 555862306a36Sopenharmony_ci pr_debug("%s: primitive type:%d is ignored\n", __func__, 555962306a36Sopenharmony_ci type.primitive); 556062306a36Sopenharmony_ci 556162306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 556262306a36Sopenharmony_ci} 556362306a36Sopenharmony_ci 556462306a36Sopenharmony_ci/*************************************************************************** 556562306a36Sopenharmony_ci * These are the state functions for the OTHER events. 556662306a36Sopenharmony_ci ***************************************************************************/ 556762306a36Sopenharmony_ci 556862306a36Sopenharmony_ci/* 556962306a36Sopenharmony_ci * When the SCTP stack has no more user data to send or retransmit, this 557062306a36Sopenharmony_ci * notification is given to the user. Also, at the time when a user app 557162306a36Sopenharmony_ci * subscribes to this event, if there is no data to be sent or 557262306a36Sopenharmony_ci * retransmit, the stack will immediately send up this notification. 557362306a36Sopenharmony_ci */ 557462306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_no_pending_tsn( 557562306a36Sopenharmony_ci struct net *net, 557662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 557762306a36Sopenharmony_ci const struct sctp_association *asoc, 557862306a36Sopenharmony_ci const union sctp_subtype type, 557962306a36Sopenharmony_ci void *arg, 558062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 558162306a36Sopenharmony_ci{ 558262306a36Sopenharmony_ci struct sctp_ulpevent *event; 558362306a36Sopenharmony_ci 558462306a36Sopenharmony_ci event = sctp_ulpevent_make_sender_dry_event(asoc, GFP_ATOMIC); 558562306a36Sopenharmony_ci if (!event) 558662306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 558762306a36Sopenharmony_ci 558862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(event)); 558962306a36Sopenharmony_ci 559062306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 559162306a36Sopenharmony_ci} 559262306a36Sopenharmony_ci 559362306a36Sopenharmony_ci/* 559462306a36Sopenharmony_ci * Start the shutdown negotiation. 559562306a36Sopenharmony_ci * 559662306a36Sopenharmony_ci * From Section 9.2: 559762306a36Sopenharmony_ci * Once all its outstanding data has been acknowledged, the endpoint 559862306a36Sopenharmony_ci * shall send a SHUTDOWN chunk to its peer including in the Cumulative 559962306a36Sopenharmony_ci * TSN Ack field the last sequential TSN it has received from the peer. 560062306a36Sopenharmony_ci * It shall then start the T2-shutdown timer and enter the SHUTDOWN-SENT 560162306a36Sopenharmony_ci * state. If the timer expires, the endpoint must re-send the SHUTDOWN 560262306a36Sopenharmony_ci * with the updated last sequential TSN received from its peer. 560362306a36Sopenharmony_ci * 560462306a36Sopenharmony_ci * The return value is the disposition. 560562306a36Sopenharmony_ci */ 560662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_start_shutdown( 560762306a36Sopenharmony_ci struct net *net, 560862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 560962306a36Sopenharmony_ci const struct sctp_association *asoc, 561062306a36Sopenharmony_ci const union sctp_subtype type, 561162306a36Sopenharmony_ci void *arg, 561262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 561362306a36Sopenharmony_ci{ 561462306a36Sopenharmony_ci struct sctp_chunk *reply; 561562306a36Sopenharmony_ci 561662306a36Sopenharmony_ci /* Once all its outstanding data has been acknowledged, the 561762306a36Sopenharmony_ci * endpoint shall send a SHUTDOWN chunk to its peer including 561862306a36Sopenharmony_ci * in the Cumulative TSN Ack field the last sequential TSN it 561962306a36Sopenharmony_ci * has received from the peer. 562062306a36Sopenharmony_ci */ 562162306a36Sopenharmony_ci reply = sctp_make_shutdown(asoc, arg); 562262306a36Sopenharmony_ci if (!reply) 562362306a36Sopenharmony_ci goto nomem; 562462306a36Sopenharmony_ci 562562306a36Sopenharmony_ci /* Set the transport for the SHUTDOWN chunk and the timeout for the 562662306a36Sopenharmony_ci * T2-shutdown timer. 562762306a36Sopenharmony_ci */ 562862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 562962306a36Sopenharmony_ci 563062306a36Sopenharmony_ci /* It shall then start the T2-shutdown timer */ 563162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, 563262306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 563362306a36Sopenharmony_ci 563462306a36Sopenharmony_ci /* RFC 4960 Section 9.2 563562306a36Sopenharmony_ci * The sender of the SHUTDOWN MAY also start an overall guard timer 563662306a36Sopenharmony_ci * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. 563762306a36Sopenharmony_ci */ 563862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 563962306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 564062306a36Sopenharmony_ci 564162306a36Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 564262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 564362306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 564462306a36Sopenharmony_ci 564562306a36Sopenharmony_ci /* and enter the SHUTDOWN-SENT state. */ 564662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 564762306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_SENT)); 564862306a36Sopenharmony_ci 564962306a36Sopenharmony_ci /* sctp-implguide 2.10 Issues with Heartbeating and failover 565062306a36Sopenharmony_ci * 565162306a36Sopenharmony_ci * HEARTBEAT ... is discontinued after sending either SHUTDOWN 565262306a36Sopenharmony_ci * or SHUTDOWN-ACK. 565362306a36Sopenharmony_ci */ 565462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); 565562306a36Sopenharmony_ci 565662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 565762306a36Sopenharmony_ci 565862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 565962306a36Sopenharmony_ci 566062306a36Sopenharmony_cinomem: 566162306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 566262306a36Sopenharmony_ci} 566362306a36Sopenharmony_ci 566462306a36Sopenharmony_ci/* 566562306a36Sopenharmony_ci * Generate a SHUTDOWN ACK now that everything is SACK'd. 566662306a36Sopenharmony_ci * 566762306a36Sopenharmony_ci * From Section 9.2: 566862306a36Sopenharmony_ci * 566962306a36Sopenharmony_ci * If it has no more outstanding DATA chunks, the SHUTDOWN receiver 567062306a36Sopenharmony_ci * shall send a SHUTDOWN ACK and start a T2-shutdown timer of its own, 567162306a36Sopenharmony_ci * entering the SHUTDOWN-ACK-SENT state. If the timer expires, the 567262306a36Sopenharmony_ci * endpoint must re-send the SHUTDOWN ACK. 567362306a36Sopenharmony_ci * 567462306a36Sopenharmony_ci * The return value is the disposition. 567562306a36Sopenharmony_ci */ 567662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_9_2_shutdown_ack( 567762306a36Sopenharmony_ci struct net *net, 567862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 567962306a36Sopenharmony_ci const struct sctp_association *asoc, 568062306a36Sopenharmony_ci const union sctp_subtype type, 568162306a36Sopenharmony_ci void *arg, 568262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 568362306a36Sopenharmony_ci{ 568462306a36Sopenharmony_ci struct sctp_chunk *chunk = arg; 568562306a36Sopenharmony_ci struct sctp_chunk *reply; 568662306a36Sopenharmony_ci 568762306a36Sopenharmony_ci /* There are 2 ways of getting here: 568862306a36Sopenharmony_ci * 1) called in response to a SHUTDOWN chunk 568962306a36Sopenharmony_ci * 2) called when SCTP_EVENT_NO_PENDING_TSN event is issued. 569062306a36Sopenharmony_ci * 569162306a36Sopenharmony_ci * For the case (2), the arg parameter is set to NULL. We need 569262306a36Sopenharmony_ci * to check that we have a chunk before accessing it's fields. 569362306a36Sopenharmony_ci */ 569462306a36Sopenharmony_ci if (chunk) { 569562306a36Sopenharmony_ci if (!sctp_vtag_verify(chunk, asoc)) 569662306a36Sopenharmony_ci return sctp_sf_pdiscard(net, ep, asoc, type, arg, 569762306a36Sopenharmony_ci commands); 569862306a36Sopenharmony_ci 569962306a36Sopenharmony_ci /* Make sure that the SHUTDOWN chunk has a valid length. */ 570062306a36Sopenharmony_ci if (!sctp_chunk_length_valid( 570162306a36Sopenharmony_ci chunk, sizeof(struct sctp_shutdown_chunk))) 570262306a36Sopenharmony_ci return sctp_sf_violation_chunklen(net, ep, asoc, type, 570362306a36Sopenharmony_ci arg, commands); 570462306a36Sopenharmony_ci } 570562306a36Sopenharmony_ci 570662306a36Sopenharmony_ci /* If it has no more outstanding DATA chunks, the SHUTDOWN receiver 570762306a36Sopenharmony_ci * shall send a SHUTDOWN ACK ... 570862306a36Sopenharmony_ci */ 570962306a36Sopenharmony_ci reply = sctp_make_shutdown_ack(asoc, chunk); 571062306a36Sopenharmony_ci if (!reply) 571162306a36Sopenharmony_ci goto nomem; 571262306a36Sopenharmony_ci 571362306a36Sopenharmony_ci /* Set the transport for the SHUTDOWN ACK chunk and the timeout for 571462306a36Sopenharmony_ci * the T2-shutdown timer. 571562306a36Sopenharmony_ci */ 571662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 571762306a36Sopenharmony_ci 571862306a36Sopenharmony_ci /* and start/restart a T2-shutdown timer of its own, */ 571962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 572062306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 572162306a36Sopenharmony_ci 572262306a36Sopenharmony_ci if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) 572362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 572462306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); 572562306a36Sopenharmony_ci 572662306a36Sopenharmony_ci /* Enter the SHUTDOWN-ACK-SENT state. */ 572762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 572862306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_ACK_SENT)); 572962306a36Sopenharmony_ci 573062306a36Sopenharmony_ci /* sctp-implguide 2.10 Issues with Heartbeating and failover 573162306a36Sopenharmony_ci * 573262306a36Sopenharmony_ci * HEARTBEAT ... is discontinued after sending either SHUTDOWN 573362306a36Sopenharmony_ci * or SHUTDOWN-ACK. 573462306a36Sopenharmony_ci */ 573562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL()); 573662306a36Sopenharmony_ci 573762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 573862306a36Sopenharmony_ci 573962306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 574062306a36Sopenharmony_ci 574162306a36Sopenharmony_cinomem: 574262306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 574362306a36Sopenharmony_ci} 574462306a36Sopenharmony_ci 574562306a36Sopenharmony_ci/* 574662306a36Sopenharmony_ci * Ignore the event defined as other 574762306a36Sopenharmony_ci * 574862306a36Sopenharmony_ci * The return value is the disposition of the event. 574962306a36Sopenharmony_ci */ 575062306a36Sopenharmony_cienum sctp_disposition sctp_sf_ignore_other(struct net *net, 575162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 575262306a36Sopenharmony_ci const struct sctp_association *asoc, 575362306a36Sopenharmony_ci const union sctp_subtype type, 575462306a36Sopenharmony_ci void *arg, 575562306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 575662306a36Sopenharmony_ci{ 575762306a36Sopenharmony_ci pr_debug("%s: the event other type:%d is ignored\n", 575862306a36Sopenharmony_ci __func__, type.other); 575962306a36Sopenharmony_ci 576062306a36Sopenharmony_ci return SCTP_DISPOSITION_DISCARD; 576162306a36Sopenharmony_ci} 576262306a36Sopenharmony_ci 576362306a36Sopenharmony_ci/************************************************************ 576462306a36Sopenharmony_ci * These are the state functions for handling timeout events. 576562306a36Sopenharmony_ci ************************************************************/ 576662306a36Sopenharmony_ci 576762306a36Sopenharmony_ci/* 576862306a36Sopenharmony_ci * RTX Timeout 576962306a36Sopenharmony_ci * 577062306a36Sopenharmony_ci * Section: 6.3.3 Handle T3-rtx Expiration 577162306a36Sopenharmony_ci * 577262306a36Sopenharmony_ci * Whenever the retransmission timer T3-rtx expires for a destination 577362306a36Sopenharmony_ci * address, do the following: 577462306a36Sopenharmony_ci * [See below] 577562306a36Sopenharmony_ci * 577662306a36Sopenharmony_ci * The return value is the disposition of the chunk. 577762306a36Sopenharmony_ci */ 577862306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_6_3_3_rtx(struct net *net, 577962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 578062306a36Sopenharmony_ci const struct sctp_association *asoc, 578162306a36Sopenharmony_ci const union sctp_subtype type, 578262306a36Sopenharmony_ci void *arg, 578362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 578462306a36Sopenharmony_ci{ 578562306a36Sopenharmony_ci struct sctp_transport *transport = arg; 578662306a36Sopenharmony_ci 578762306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS); 578862306a36Sopenharmony_ci 578962306a36Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 579062306a36Sopenharmony_ci if (asoc->peer.zero_window_announced && 579162306a36Sopenharmony_ci asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { 579262306a36Sopenharmony_ci /* 579362306a36Sopenharmony_ci * We are here likely because the receiver had its rwnd 579462306a36Sopenharmony_ci * closed for a while and we have not been able to 579562306a36Sopenharmony_ci * transmit the locally queued data within the maximum 579662306a36Sopenharmony_ci * retransmission attempts limit. Start the T5 579762306a36Sopenharmony_ci * shutdown guard timer to give the receiver one last 579862306a36Sopenharmony_ci * chance and some additional time to recover before 579962306a36Sopenharmony_ci * aborting. 580062306a36Sopenharmony_ci */ 580162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START_ONCE, 580262306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); 580362306a36Sopenharmony_ci } else { 580462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 580562306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 580662306a36Sopenharmony_ci /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 580762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 580862306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 580962306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 581062306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 581162306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 581262306a36Sopenharmony_ci } 581362306a36Sopenharmony_ci } 581462306a36Sopenharmony_ci 581562306a36Sopenharmony_ci /* E1) For the destination address for which the timer 581662306a36Sopenharmony_ci * expires, adjust its ssthresh with rules defined in Section 581762306a36Sopenharmony_ci * 7.2.3 and set the cwnd <- MTU. 581862306a36Sopenharmony_ci */ 581962306a36Sopenharmony_ci 582062306a36Sopenharmony_ci /* E2) For the destination address for which the timer 582162306a36Sopenharmony_ci * expires, set RTO <- RTO * 2 ("back off the timer"). The 582262306a36Sopenharmony_ci * maximum value discussed in rule C7 above (RTO.max) may be 582362306a36Sopenharmony_ci * used to provide an upper bound to this doubling operation. 582462306a36Sopenharmony_ci */ 582562306a36Sopenharmony_ci 582662306a36Sopenharmony_ci /* E3) Determine how many of the earliest (i.e., lowest TSN) 582762306a36Sopenharmony_ci * outstanding DATA chunks for the address for which the 582862306a36Sopenharmony_ci * T3-rtx has expired will fit into a single packet, subject 582962306a36Sopenharmony_ci * to the MTU constraint for the path corresponding to the 583062306a36Sopenharmony_ci * destination transport address to which the retransmission 583162306a36Sopenharmony_ci * is being sent (this may be different from the address for 583262306a36Sopenharmony_ci * which the timer expires [see Section 6.4]). Call this 583362306a36Sopenharmony_ci * value K. Bundle and retransmit those K DATA chunks in a 583462306a36Sopenharmony_ci * single packet to the destination endpoint. 583562306a36Sopenharmony_ci * 583662306a36Sopenharmony_ci * Note: Any DATA chunks that were sent to the address for 583762306a36Sopenharmony_ci * which the T3-rtx timer expired but did not fit in one MTU 583862306a36Sopenharmony_ci * (rule E3 above), should be marked for retransmission and 583962306a36Sopenharmony_ci * sent as soon as cwnd allows (normally when a SACK arrives). 584062306a36Sopenharmony_ci */ 584162306a36Sopenharmony_ci 584262306a36Sopenharmony_ci /* Do some failure management (Section 8.2). */ 584362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); 584462306a36Sopenharmony_ci 584562306a36Sopenharmony_ci /* NB: Rules E4 and F1 are implicit in R1. */ 584662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(transport)); 584762306a36Sopenharmony_ci 584862306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 584962306a36Sopenharmony_ci} 585062306a36Sopenharmony_ci 585162306a36Sopenharmony_ci/* 585262306a36Sopenharmony_ci * Generate delayed SACK on timeout 585362306a36Sopenharmony_ci * 585462306a36Sopenharmony_ci * Section: 6.2 Acknowledgement on Reception of DATA Chunks 585562306a36Sopenharmony_ci * 585662306a36Sopenharmony_ci * The guidelines on delayed acknowledgement algorithm specified in 585762306a36Sopenharmony_ci * Section 4.2 of [RFC2581] SHOULD be followed. Specifically, an 585862306a36Sopenharmony_ci * acknowledgement SHOULD be generated for at least every second packet 585962306a36Sopenharmony_ci * (not every second DATA chunk) received, and SHOULD be generated 586062306a36Sopenharmony_ci * within 200 ms of the arrival of any unacknowledged DATA chunk. In 586162306a36Sopenharmony_ci * some situations it may be beneficial for an SCTP transmitter to be 586262306a36Sopenharmony_ci * more conservative than the algorithms detailed in this document 586362306a36Sopenharmony_ci * allow. However, an SCTP transmitter MUST NOT be more aggressive than 586462306a36Sopenharmony_ci * the following algorithms allow. 586562306a36Sopenharmony_ci */ 586662306a36Sopenharmony_cienum sctp_disposition sctp_sf_do_6_2_sack(struct net *net, 586762306a36Sopenharmony_ci const struct sctp_endpoint *ep, 586862306a36Sopenharmony_ci const struct sctp_association *asoc, 586962306a36Sopenharmony_ci const union sctp_subtype type, 587062306a36Sopenharmony_ci void *arg, 587162306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 587262306a36Sopenharmony_ci{ 587362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS); 587462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); 587562306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 587662306a36Sopenharmony_ci} 587762306a36Sopenharmony_ci 587862306a36Sopenharmony_ci/* 587962306a36Sopenharmony_ci * sctp_sf_t1_init_timer_expire 588062306a36Sopenharmony_ci * 588162306a36Sopenharmony_ci * Section: 4 Note: 2 588262306a36Sopenharmony_ci * Verification Tag: 588362306a36Sopenharmony_ci * Inputs 588462306a36Sopenharmony_ci * (endpoint, asoc) 588562306a36Sopenharmony_ci * 588662306a36Sopenharmony_ci * RFC 2960 Section 4 Notes 588762306a36Sopenharmony_ci * 2) If the T1-init timer expires, the endpoint MUST retransmit INIT 588862306a36Sopenharmony_ci * and re-start the T1-init timer without changing state. This MUST 588962306a36Sopenharmony_ci * be repeated up to 'Max.Init.Retransmits' times. After that, the 589062306a36Sopenharmony_ci * endpoint MUST abort the initialization process and report the 589162306a36Sopenharmony_ci * error to SCTP user. 589262306a36Sopenharmony_ci * 589362306a36Sopenharmony_ci * Outputs 589462306a36Sopenharmony_ci * (timers, events) 589562306a36Sopenharmony_ci * 589662306a36Sopenharmony_ci */ 589762306a36Sopenharmony_cienum sctp_disposition sctp_sf_t1_init_timer_expire( 589862306a36Sopenharmony_ci struct net *net, 589962306a36Sopenharmony_ci const struct sctp_endpoint *ep, 590062306a36Sopenharmony_ci const struct sctp_association *asoc, 590162306a36Sopenharmony_ci const union sctp_subtype type, 590262306a36Sopenharmony_ci void *arg, 590362306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 590462306a36Sopenharmony_ci{ 590562306a36Sopenharmony_ci int attempts = asoc->init_err_counter + 1; 590662306a36Sopenharmony_ci struct sctp_chunk *repl = NULL; 590762306a36Sopenharmony_ci struct sctp_bind_addr *bp; 590862306a36Sopenharmony_ci 590962306a36Sopenharmony_ci pr_debug("%s: timer T1 expired (INIT)\n", __func__); 591062306a36Sopenharmony_ci 591162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS); 591262306a36Sopenharmony_ci 591362306a36Sopenharmony_ci if (attempts <= asoc->max_init_attempts) { 591462306a36Sopenharmony_ci bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; 591562306a36Sopenharmony_ci repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); 591662306a36Sopenharmony_ci if (!repl) 591762306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 591862306a36Sopenharmony_ci 591962306a36Sopenharmony_ci /* Choose transport for INIT. */ 592062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, 592162306a36Sopenharmony_ci SCTP_CHUNK(repl)); 592262306a36Sopenharmony_ci 592362306a36Sopenharmony_ci /* Issue a sideeffect to do the needed accounting. */ 592462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, 592562306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 592662306a36Sopenharmony_ci 592762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 592862306a36Sopenharmony_ci } else { 592962306a36Sopenharmony_ci pr_debug("%s: giving up on INIT, attempts:%d " 593062306a36Sopenharmony_ci "max_init_attempts:%d\n", __func__, attempts, 593162306a36Sopenharmony_ci asoc->max_init_attempts); 593262306a36Sopenharmony_ci 593362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 593462306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 593562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 593662306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 593762306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 593862306a36Sopenharmony_ci } 593962306a36Sopenharmony_ci 594062306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 594162306a36Sopenharmony_ci} 594262306a36Sopenharmony_ci 594362306a36Sopenharmony_ci/* 594462306a36Sopenharmony_ci * sctp_sf_t1_cookie_timer_expire 594562306a36Sopenharmony_ci * 594662306a36Sopenharmony_ci * Section: 4 Note: 2 594762306a36Sopenharmony_ci * Verification Tag: 594862306a36Sopenharmony_ci * Inputs 594962306a36Sopenharmony_ci * (endpoint, asoc) 595062306a36Sopenharmony_ci * 595162306a36Sopenharmony_ci * RFC 2960 Section 4 Notes 595262306a36Sopenharmony_ci * 3) If the T1-cookie timer expires, the endpoint MUST retransmit 595362306a36Sopenharmony_ci * COOKIE ECHO and re-start the T1-cookie timer without changing 595462306a36Sopenharmony_ci * state. This MUST be repeated up to 'Max.Init.Retransmits' times. 595562306a36Sopenharmony_ci * After that, the endpoint MUST abort the initialization process and 595662306a36Sopenharmony_ci * report the error to SCTP user. 595762306a36Sopenharmony_ci * 595862306a36Sopenharmony_ci * Outputs 595962306a36Sopenharmony_ci * (timers, events) 596062306a36Sopenharmony_ci * 596162306a36Sopenharmony_ci */ 596262306a36Sopenharmony_cienum sctp_disposition sctp_sf_t1_cookie_timer_expire( 596362306a36Sopenharmony_ci struct net *net, 596462306a36Sopenharmony_ci const struct sctp_endpoint *ep, 596562306a36Sopenharmony_ci const struct sctp_association *asoc, 596662306a36Sopenharmony_ci const union sctp_subtype type, 596762306a36Sopenharmony_ci void *arg, 596862306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 596962306a36Sopenharmony_ci{ 597062306a36Sopenharmony_ci int attempts = asoc->init_err_counter + 1; 597162306a36Sopenharmony_ci struct sctp_chunk *repl = NULL; 597262306a36Sopenharmony_ci 597362306a36Sopenharmony_ci pr_debug("%s: timer T1 expired (COOKIE-ECHO)\n", __func__); 597462306a36Sopenharmony_ci 597562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS); 597662306a36Sopenharmony_ci 597762306a36Sopenharmony_ci if (attempts <= asoc->max_init_attempts) { 597862306a36Sopenharmony_ci repl = sctp_make_cookie_echo(asoc, NULL); 597962306a36Sopenharmony_ci if (!repl) 598062306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 598162306a36Sopenharmony_ci 598262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, 598362306a36Sopenharmony_ci SCTP_CHUNK(repl)); 598462306a36Sopenharmony_ci /* Issue a sideeffect to do the needed accounting. */ 598562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, 598662306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); 598762306a36Sopenharmony_ci 598862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); 598962306a36Sopenharmony_ci } else { 599062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 599162306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 599262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, 599362306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 599462306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 599562306a36Sopenharmony_ci } 599662306a36Sopenharmony_ci 599762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 599862306a36Sopenharmony_ci} 599962306a36Sopenharmony_ci 600062306a36Sopenharmony_ci/* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN 600162306a36Sopenharmony_ci * with the updated last sequential TSN received from its peer. 600262306a36Sopenharmony_ci * 600362306a36Sopenharmony_ci * An endpoint should limit the number of retransmission of the 600462306a36Sopenharmony_ci * SHUTDOWN chunk to the protocol parameter 'Association.Max.Retrans'. 600562306a36Sopenharmony_ci * If this threshold is exceeded the endpoint should destroy the TCB and 600662306a36Sopenharmony_ci * MUST report the peer endpoint unreachable to the upper layer (and 600762306a36Sopenharmony_ci * thus the association enters the CLOSED state). The reception of any 600862306a36Sopenharmony_ci * packet from its peer (i.e. as the peer sends all of its queued DATA 600962306a36Sopenharmony_ci * chunks) should clear the endpoint's retransmission count and restart 601062306a36Sopenharmony_ci * the T2-Shutdown timer, giving its peer ample opportunity to transmit 601162306a36Sopenharmony_ci * all of its queued DATA chunks that have not yet been sent. 601262306a36Sopenharmony_ci */ 601362306a36Sopenharmony_cienum sctp_disposition sctp_sf_t2_timer_expire( 601462306a36Sopenharmony_ci struct net *net, 601562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 601662306a36Sopenharmony_ci const struct sctp_association *asoc, 601762306a36Sopenharmony_ci const union sctp_subtype type, 601862306a36Sopenharmony_ci void *arg, 601962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 602062306a36Sopenharmony_ci{ 602162306a36Sopenharmony_ci struct sctp_chunk *reply = NULL; 602262306a36Sopenharmony_ci 602362306a36Sopenharmony_ci pr_debug("%s: timer T2 expired\n", __func__); 602462306a36Sopenharmony_ci 602562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS); 602662306a36Sopenharmony_ci 602762306a36Sopenharmony_ci ((struct sctp_association *)asoc)->shutdown_retries++; 602862306a36Sopenharmony_ci 602962306a36Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 603062306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 603162306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 603262306a36Sopenharmony_ci /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ 603362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 603462306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 603562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 603662306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 603762306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 603862306a36Sopenharmony_ci } 603962306a36Sopenharmony_ci 604062306a36Sopenharmony_ci switch (asoc->state) { 604162306a36Sopenharmony_ci case SCTP_STATE_SHUTDOWN_SENT: 604262306a36Sopenharmony_ci reply = sctp_make_shutdown(asoc, NULL); 604362306a36Sopenharmony_ci break; 604462306a36Sopenharmony_ci 604562306a36Sopenharmony_ci case SCTP_STATE_SHUTDOWN_ACK_SENT: 604662306a36Sopenharmony_ci reply = sctp_make_shutdown_ack(asoc, NULL); 604762306a36Sopenharmony_ci break; 604862306a36Sopenharmony_ci 604962306a36Sopenharmony_ci default: 605062306a36Sopenharmony_ci BUG(); 605162306a36Sopenharmony_ci break; 605262306a36Sopenharmony_ci } 605362306a36Sopenharmony_ci 605462306a36Sopenharmony_ci if (!reply) 605562306a36Sopenharmony_ci goto nomem; 605662306a36Sopenharmony_ci 605762306a36Sopenharmony_ci /* Do some failure management (Section 8.2). 605862306a36Sopenharmony_ci * If we remove the transport an SHUTDOWN was last sent to, don't 605962306a36Sopenharmony_ci * do failure management. 606062306a36Sopenharmony_ci */ 606162306a36Sopenharmony_ci if (asoc->shutdown_last_sent_to) 606262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, 606362306a36Sopenharmony_ci SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); 606462306a36Sopenharmony_ci 606562306a36Sopenharmony_ci /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for 606662306a36Sopenharmony_ci * the T2-shutdown timer. 606762306a36Sopenharmony_ci */ 606862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T2, SCTP_CHUNK(reply)); 606962306a36Sopenharmony_ci 607062306a36Sopenharmony_ci /* Restart the T2-shutdown timer. */ 607162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 607262306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); 607362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 607462306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 607562306a36Sopenharmony_ci 607662306a36Sopenharmony_cinomem: 607762306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 607862306a36Sopenharmony_ci} 607962306a36Sopenharmony_ci 608062306a36Sopenharmony_ci/* 608162306a36Sopenharmony_ci * ADDIP Section 4.1 ASCONF Chunk Procedures 608262306a36Sopenharmony_ci * If the T4 RTO timer expires the endpoint should do B1 to B5 608362306a36Sopenharmony_ci */ 608462306a36Sopenharmony_cienum sctp_disposition sctp_sf_t4_timer_expire( 608562306a36Sopenharmony_ci struct net *net, 608662306a36Sopenharmony_ci const struct sctp_endpoint *ep, 608762306a36Sopenharmony_ci const struct sctp_association *asoc, 608862306a36Sopenharmony_ci const union sctp_subtype type, 608962306a36Sopenharmony_ci void *arg, 609062306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 609162306a36Sopenharmony_ci{ 609262306a36Sopenharmony_ci struct sctp_chunk *chunk = asoc->addip_last_asconf; 609362306a36Sopenharmony_ci struct sctp_transport *transport = chunk->transport; 609462306a36Sopenharmony_ci 609562306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS); 609662306a36Sopenharmony_ci 609762306a36Sopenharmony_ci /* ADDIP 4.1 B1) Increment the error counters and perform path failure 609862306a36Sopenharmony_ci * detection on the appropriate destination address as defined in 609962306a36Sopenharmony_ci * RFC2960 [5] section 8.1 and 8.2. 610062306a36Sopenharmony_ci */ 610162306a36Sopenharmony_ci if (transport) 610262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, 610362306a36Sopenharmony_ci SCTP_TRANSPORT(transport)); 610462306a36Sopenharmony_ci 610562306a36Sopenharmony_ci /* Reconfig T4 timer and transport. */ 610662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); 610762306a36Sopenharmony_ci 610862306a36Sopenharmony_ci /* ADDIP 4.1 B2) Increment the association error counters and perform 610962306a36Sopenharmony_ci * endpoint failure detection on the association as defined in 611062306a36Sopenharmony_ci * RFC2960 [5] section 8.1 and 8.2. 611162306a36Sopenharmony_ci * association error counter is incremented in SCTP_CMD_STRIKE. 611262306a36Sopenharmony_ci */ 611362306a36Sopenharmony_ci if (asoc->overall_error_count >= asoc->max_retrans) { 611462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, 611562306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 611662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 611762306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 611862306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 611962306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 612062306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 612162306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 612262306a36Sopenharmony_ci return SCTP_DISPOSITION_ABORT; 612362306a36Sopenharmony_ci } 612462306a36Sopenharmony_ci 612562306a36Sopenharmony_ci /* ADDIP 4.1 B3) Back-off the destination address RTO value to which 612662306a36Sopenharmony_ci * the ASCONF chunk was sent by doubling the RTO timer value. 612762306a36Sopenharmony_ci * This is done in SCTP_CMD_STRIKE. 612862306a36Sopenharmony_ci */ 612962306a36Sopenharmony_ci 613062306a36Sopenharmony_ci /* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible 613162306a36Sopenharmony_ci * choose an alternate destination address (please refer to RFC2960 613262306a36Sopenharmony_ci * [5] section 6.4.1). An endpoint MUST NOT add new parameters to this 613362306a36Sopenharmony_ci * chunk, it MUST be the same (including its serial number) as the last 613462306a36Sopenharmony_ci * ASCONF sent. 613562306a36Sopenharmony_ci */ 613662306a36Sopenharmony_ci sctp_chunk_hold(asoc->addip_last_asconf); 613762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 613862306a36Sopenharmony_ci SCTP_CHUNK(asoc->addip_last_asconf)); 613962306a36Sopenharmony_ci 614062306a36Sopenharmony_ci /* ADDIP 4.1 B5) Restart the T-4 RTO timer. Note that if a different 614162306a36Sopenharmony_ci * destination is selected, then the RTO used will be that of the new 614262306a36Sopenharmony_ci * destination address. 614362306a36Sopenharmony_ci */ 614462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, 614562306a36Sopenharmony_ci SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); 614662306a36Sopenharmony_ci 614762306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 614862306a36Sopenharmony_ci} 614962306a36Sopenharmony_ci 615062306a36Sopenharmony_ci/* sctpimpguide-05 Section 2.12.2 615162306a36Sopenharmony_ci * The sender of the SHUTDOWN MAY also start an overall guard timer 615262306a36Sopenharmony_ci * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. 615362306a36Sopenharmony_ci * At the expiration of this timer the sender SHOULD abort the association 615462306a36Sopenharmony_ci * by sending an ABORT chunk. 615562306a36Sopenharmony_ci */ 615662306a36Sopenharmony_cienum sctp_disposition sctp_sf_t5_timer_expire( 615762306a36Sopenharmony_ci struct net *net, 615862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 615962306a36Sopenharmony_ci const struct sctp_association *asoc, 616062306a36Sopenharmony_ci const union sctp_subtype type, 616162306a36Sopenharmony_ci void *arg, 616262306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 616362306a36Sopenharmony_ci{ 616462306a36Sopenharmony_ci struct sctp_chunk *reply = NULL; 616562306a36Sopenharmony_ci 616662306a36Sopenharmony_ci pr_debug("%s: timer T5 expired\n", __func__); 616762306a36Sopenharmony_ci 616862306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); 616962306a36Sopenharmony_ci 617062306a36Sopenharmony_ci reply = sctp_make_abort(asoc, NULL, 0); 617162306a36Sopenharmony_ci if (!reply) 617262306a36Sopenharmony_ci goto nomem; 617362306a36Sopenharmony_ci 617462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); 617562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 617662306a36Sopenharmony_ci SCTP_ERROR(ETIMEDOUT)); 617762306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 617862306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_ERROR)); 617962306a36Sopenharmony_ci 618062306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 618162306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 618262306a36Sopenharmony_ci 618362306a36Sopenharmony_ci return SCTP_DISPOSITION_DELETE_TCB; 618462306a36Sopenharmony_cinomem: 618562306a36Sopenharmony_ci return SCTP_DISPOSITION_NOMEM; 618662306a36Sopenharmony_ci} 618762306a36Sopenharmony_ci 618862306a36Sopenharmony_ci/* Handle expiration of AUTOCLOSE timer. When the autoclose timer expires, 618962306a36Sopenharmony_ci * the association is automatically closed by starting the shutdown process. 619062306a36Sopenharmony_ci * The work that needs to be done is same as when SHUTDOWN is initiated by 619162306a36Sopenharmony_ci * the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown(). 619262306a36Sopenharmony_ci */ 619362306a36Sopenharmony_cienum sctp_disposition sctp_sf_autoclose_timer_expire( 619462306a36Sopenharmony_ci struct net *net, 619562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 619662306a36Sopenharmony_ci const struct sctp_association *asoc, 619762306a36Sopenharmony_ci const union sctp_subtype type, 619862306a36Sopenharmony_ci void *arg, 619962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 620062306a36Sopenharmony_ci{ 620162306a36Sopenharmony_ci enum sctp_disposition disposition; 620262306a36Sopenharmony_ci 620362306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS); 620462306a36Sopenharmony_ci 620562306a36Sopenharmony_ci /* From 9.2 Shutdown of an Association 620662306a36Sopenharmony_ci * Upon receipt of the SHUTDOWN primitive from its upper 620762306a36Sopenharmony_ci * layer, the endpoint enters SHUTDOWN-PENDING state and 620862306a36Sopenharmony_ci * remains there until all outstanding data has been 620962306a36Sopenharmony_ci * acknowledged by its peer. The endpoint accepts no new data 621062306a36Sopenharmony_ci * from its upper layer, but retransmits data to the far end 621162306a36Sopenharmony_ci * if necessary to fill gaps. 621262306a36Sopenharmony_ci */ 621362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 621462306a36Sopenharmony_ci SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); 621562306a36Sopenharmony_ci 621662306a36Sopenharmony_ci disposition = SCTP_DISPOSITION_CONSUME; 621762306a36Sopenharmony_ci if (sctp_outq_is_empty(&asoc->outqueue)) { 621862306a36Sopenharmony_ci disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type, 621962306a36Sopenharmony_ci NULL, commands); 622062306a36Sopenharmony_ci } 622162306a36Sopenharmony_ci 622262306a36Sopenharmony_ci return disposition; 622362306a36Sopenharmony_ci} 622462306a36Sopenharmony_ci 622562306a36Sopenharmony_ci/***************************************************************************** 622662306a36Sopenharmony_ci * These are sa state functions which could apply to all types of events. 622762306a36Sopenharmony_ci ****************************************************************************/ 622862306a36Sopenharmony_ci 622962306a36Sopenharmony_ci/* 623062306a36Sopenharmony_ci * This table entry is not implemented. 623162306a36Sopenharmony_ci * 623262306a36Sopenharmony_ci * Inputs 623362306a36Sopenharmony_ci * (endpoint, asoc, chunk) 623462306a36Sopenharmony_ci * 623562306a36Sopenharmony_ci * The return value is the disposition of the chunk. 623662306a36Sopenharmony_ci */ 623762306a36Sopenharmony_cienum sctp_disposition sctp_sf_not_impl(struct net *net, 623862306a36Sopenharmony_ci const struct sctp_endpoint *ep, 623962306a36Sopenharmony_ci const struct sctp_association *asoc, 624062306a36Sopenharmony_ci const union sctp_subtype type, 624162306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 624262306a36Sopenharmony_ci{ 624362306a36Sopenharmony_ci return SCTP_DISPOSITION_NOT_IMPL; 624462306a36Sopenharmony_ci} 624562306a36Sopenharmony_ci 624662306a36Sopenharmony_ci/* 624762306a36Sopenharmony_ci * This table entry represents a bug. 624862306a36Sopenharmony_ci * 624962306a36Sopenharmony_ci * Inputs 625062306a36Sopenharmony_ci * (endpoint, asoc, chunk) 625162306a36Sopenharmony_ci * 625262306a36Sopenharmony_ci * The return value is the disposition of the chunk. 625362306a36Sopenharmony_ci */ 625462306a36Sopenharmony_cienum sctp_disposition sctp_sf_bug(struct net *net, 625562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 625662306a36Sopenharmony_ci const struct sctp_association *asoc, 625762306a36Sopenharmony_ci const union sctp_subtype type, 625862306a36Sopenharmony_ci void *arg, struct sctp_cmd_seq *commands) 625962306a36Sopenharmony_ci{ 626062306a36Sopenharmony_ci return SCTP_DISPOSITION_BUG; 626162306a36Sopenharmony_ci} 626262306a36Sopenharmony_ci 626362306a36Sopenharmony_ci/* 626462306a36Sopenharmony_ci * This table entry represents the firing of a timer in the wrong state. 626562306a36Sopenharmony_ci * Since timer deletion cannot be guaranteed a timer 'may' end up firing 626662306a36Sopenharmony_ci * when the association is in the wrong state. This event should 626762306a36Sopenharmony_ci * be ignored, so as to prevent any rearming of the timer. 626862306a36Sopenharmony_ci * 626962306a36Sopenharmony_ci * Inputs 627062306a36Sopenharmony_ci * (endpoint, asoc, chunk) 627162306a36Sopenharmony_ci * 627262306a36Sopenharmony_ci * The return value is the disposition of the chunk. 627362306a36Sopenharmony_ci */ 627462306a36Sopenharmony_cienum sctp_disposition sctp_sf_timer_ignore(struct net *net, 627562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 627662306a36Sopenharmony_ci const struct sctp_association *asoc, 627762306a36Sopenharmony_ci const union sctp_subtype type, 627862306a36Sopenharmony_ci void *arg, 627962306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 628062306a36Sopenharmony_ci{ 628162306a36Sopenharmony_ci pr_debug("%s: timer %d ignored\n", __func__, type.chunk); 628262306a36Sopenharmony_ci 628362306a36Sopenharmony_ci return SCTP_DISPOSITION_CONSUME; 628462306a36Sopenharmony_ci} 628562306a36Sopenharmony_ci 628662306a36Sopenharmony_ci/******************************************************************** 628762306a36Sopenharmony_ci * 2nd Level Abstractions 628862306a36Sopenharmony_ci ********************************************************************/ 628962306a36Sopenharmony_ci 629062306a36Sopenharmony_ci/* Pull the SACK chunk based on the SACK header. */ 629162306a36Sopenharmony_cistatic struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk) 629262306a36Sopenharmony_ci{ 629362306a36Sopenharmony_ci struct sctp_sackhdr *sack; 629462306a36Sopenharmony_ci __u16 num_dup_tsns; 629562306a36Sopenharmony_ci unsigned int len; 629662306a36Sopenharmony_ci __u16 num_blocks; 629762306a36Sopenharmony_ci 629862306a36Sopenharmony_ci /* Protect ourselves from reading too far into 629962306a36Sopenharmony_ci * the skb from a bogus sender. 630062306a36Sopenharmony_ci */ 630162306a36Sopenharmony_ci sack = (struct sctp_sackhdr *) chunk->skb->data; 630262306a36Sopenharmony_ci 630362306a36Sopenharmony_ci num_blocks = ntohs(sack->num_gap_ack_blocks); 630462306a36Sopenharmony_ci num_dup_tsns = ntohs(sack->num_dup_tsns); 630562306a36Sopenharmony_ci len = sizeof(struct sctp_sackhdr); 630662306a36Sopenharmony_ci len += (num_blocks + num_dup_tsns) * sizeof(__u32); 630762306a36Sopenharmony_ci if (len > chunk->skb->len) 630862306a36Sopenharmony_ci return NULL; 630962306a36Sopenharmony_ci 631062306a36Sopenharmony_ci skb_pull(chunk->skb, len); 631162306a36Sopenharmony_ci 631262306a36Sopenharmony_ci return sack; 631362306a36Sopenharmony_ci} 631462306a36Sopenharmony_ci 631562306a36Sopenharmony_ci/* Create an ABORT packet to be sent as a response, with the specified 631662306a36Sopenharmony_ci * error causes. 631762306a36Sopenharmony_ci */ 631862306a36Sopenharmony_cistatic struct sctp_packet *sctp_abort_pkt_new( 631962306a36Sopenharmony_ci struct net *net, 632062306a36Sopenharmony_ci const struct sctp_endpoint *ep, 632162306a36Sopenharmony_ci const struct sctp_association *asoc, 632262306a36Sopenharmony_ci struct sctp_chunk *chunk, 632362306a36Sopenharmony_ci const void *payload, size_t paylen) 632462306a36Sopenharmony_ci{ 632562306a36Sopenharmony_ci struct sctp_packet *packet; 632662306a36Sopenharmony_ci struct sctp_chunk *abort; 632762306a36Sopenharmony_ci 632862306a36Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 632962306a36Sopenharmony_ci 633062306a36Sopenharmony_ci if (packet) { 633162306a36Sopenharmony_ci /* Make an ABORT. 633262306a36Sopenharmony_ci * The T bit will be set if the asoc is NULL. 633362306a36Sopenharmony_ci */ 633462306a36Sopenharmony_ci abort = sctp_make_abort(asoc, chunk, paylen); 633562306a36Sopenharmony_ci if (!abort) { 633662306a36Sopenharmony_ci sctp_ootb_pkt_free(packet); 633762306a36Sopenharmony_ci return NULL; 633862306a36Sopenharmony_ci } 633962306a36Sopenharmony_ci 634062306a36Sopenharmony_ci /* Reflect vtag if T-Bit is set */ 634162306a36Sopenharmony_ci if (sctp_test_T_bit(abort)) 634262306a36Sopenharmony_ci packet->vtag = ntohl(chunk->sctp_hdr->vtag); 634362306a36Sopenharmony_ci 634462306a36Sopenharmony_ci /* Add specified error causes, i.e., payload, to the 634562306a36Sopenharmony_ci * end of the chunk. 634662306a36Sopenharmony_ci */ 634762306a36Sopenharmony_ci sctp_addto_chunk(abort, paylen, payload); 634862306a36Sopenharmony_ci 634962306a36Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 635062306a36Sopenharmony_ci abort->skb->sk = ep->base.sk; 635162306a36Sopenharmony_ci 635262306a36Sopenharmony_ci sctp_packet_append_chunk(packet, abort); 635362306a36Sopenharmony_ci 635462306a36Sopenharmony_ci } 635562306a36Sopenharmony_ci 635662306a36Sopenharmony_ci return packet; 635762306a36Sopenharmony_ci} 635862306a36Sopenharmony_ci 635962306a36Sopenharmony_ci/* Allocate a packet for responding in the OOTB conditions. */ 636062306a36Sopenharmony_cistatic struct sctp_packet *sctp_ootb_pkt_new( 636162306a36Sopenharmony_ci struct net *net, 636262306a36Sopenharmony_ci const struct sctp_association *asoc, 636362306a36Sopenharmony_ci const struct sctp_chunk *chunk) 636462306a36Sopenharmony_ci{ 636562306a36Sopenharmony_ci struct sctp_transport *transport; 636662306a36Sopenharmony_ci struct sctp_packet *packet; 636762306a36Sopenharmony_ci __u16 sport, dport; 636862306a36Sopenharmony_ci __u32 vtag; 636962306a36Sopenharmony_ci 637062306a36Sopenharmony_ci /* Get the source and destination port from the inbound packet. */ 637162306a36Sopenharmony_ci sport = ntohs(chunk->sctp_hdr->dest); 637262306a36Sopenharmony_ci dport = ntohs(chunk->sctp_hdr->source); 637362306a36Sopenharmony_ci 637462306a36Sopenharmony_ci /* The V-tag is going to be the same as the inbound packet if no 637562306a36Sopenharmony_ci * association exists, otherwise, use the peer's vtag. 637662306a36Sopenharmony_ci */ 637762306a36Sopenharmony_ci if (asoc) { 637862306a36Sopenharmony_ci /* Special case the INIT-ACK as there is no peer's vtag 637962306a36Sopenharmony_ci * yet. 638062306a36Sopenharmony_ci */ 638162306a36Sopenharmony_ci switch (chunk->chunk_hdr->type) { 638262306a36Sopenharmony_ci case SCTP_CID_INIT: 638362306a36Sopenharmony_ci case SCTP_CID_INIT_ACK: 638462306a36Sopenharmony_ci { 638562306a36Sopenharmony_ci struct sctp_initack_chunk *initack; 638662306a36Sopenharmony_ci 638762306a36Sopenharmony_ci initack = (struct sctp_initack_chunk *)chunk->chunk_hdr; 638862306a36Sopenharmony_ci vtag = ntohl(initack->init_hdr.init_tag); 638962306a36Sopenharmony_ci break; 639062306a36Sopenharmony_ci } 639162306a36Sopenharmony_ci default: 639262306a36Sopenharmony_ci vtag = asoc->peer.i.init_tag; 639362306a36Sopenharmony_ci break; 639462306a36Sopenharmony_ci } 639562306a36Sopenharmony_ci } else { 639662306a36Sopenharmony_ci /* Special case the INIT and stale COOKIE_ECHO as there is no 639762306a36Sopenharmony_ci * vtag yet. 639862306a36Sopenharmony_ci */ 639962306a36Sopenharmony_ci switch (chunk->chunk_hdr->type) { 640062306a36Sopenharmony_ci case SCTP_CID_INIT: 640162306a36Sopenharmony_ci { 640262306a36Sopenharmony_ci struct sctp_init_chunk *init; 640362306a36Sopenharmony_ci 640462306a36Sopenharmony_ci init = (struct sctp_init_chunk *)chunk->chunk_hdr; 640562306a36Sopenharmony_ci vtag = ntohl(init->init_hdr.init_tag); 640662306a36Sopenharmony_ci break; 640762306a36Sopenharmony_ci } 640862306a36Sopenharmony_ci default: 640962306a36Sopenharmony_ci vtag = ntohl(chunk->sctp_hdr->vtag); 641062306a36Sopenharmony_ci break; 641162306a36Sopenharmony_ci } 641262306a36Sopenharmony_ci } 641362306a36Sopenharmony_ci 641462306a36Sopenharmony_ci /* Make a transport for the bucket, Eliza... */ 641562306a36Sopenharmony_ci transport = sctp_transport_new(net, sctp_source(chunk), GFP_ATOMIC); 641662306a36Sopenharmony_ci if (!transport) 641762306a36Sopenharmony_ci goto nomem; 641862306a36Sopenharmony_ci 641962306a36Sopenharmony_ci transport->encap_port = SCTP_INPUT_CB(chunk->skb)->encap_port; 642062306a36Sopenharmony_ci 642162306a36Sopenharmony_ci /* Cache a route for the transport with the chunk's destination as 642262306a36Sopenharmony_ci * the source address. 642362306a36Sopenharmony_ci */ 642462306a36Sopenharmony_ci sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, 642562306a36Sopenharmony_ci sctp_sk(net->sctp.ctl_sock)); 642662306a36Sopenharmony_ci 642762306a36Sopenharmony_ci packet = &transport->packet; 642862306a36Sopenharmony_ci sctp_packet_init(packet, transport, sport, dport); 642962306a36Sopenharmony_ci sctp_packet_config(packet, vtag, 0); 643062306a36Sopenharmony_ci 643162306a36Sopenharmony_ci return packet; 643262306a36Sopenharmony_ci 643362306a36Sopenharmony_cinomem: 643462306a36Sopenharmony_ci return NULL; 643562306a36Sopenharmony_ci} 643662306a36Sopenharmony_ci 643762306a36Sopenharmony_ci/* Free the packet allocated earlier for responding in the OOTB condition. */ 643862306a36Sopenharmony_civoid sctp_ootb_pkt_free(struct sctp_packet *packet) 643962306a36Sopenharmony_ci{ 644062306a36Sopenharmony_ci sctp_transport_free(packet->transport); 644162306a36Sopenharmony_ci} 644262306a36Sopenharmony_ci 644362306a36Sopenharmony_ci/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */ 644462306a36Sopenharmony_cistatic void sctp_send_stale_cookie_err(struct net *net, 644562306a36Sopenharmony_ci const struct sctp_endpoint *ep, 644662306a36Sopenharmony_ci const struct sctp_association *asoc, 644762306a36Sopenharmony_ci const struct sctp_chunk *chunk, 644862306a36Sopenharmony_ci struct sctp_cmd_seq *commands, 644962306a36Sopenharmony_ci struct sctp_chunk *err_chunk) 645062306a36Sopenharmony_ci{ 645162306a36Sopenharmony_ci struct sctp_packet *packet; 645262306a36Sopenharmony_ci 645362306a36Sopenharmony_ci if (err_chunk) { 645462306a36Sopenharmony_ci packet = sctp_ootb_pkt_new(net, asoc, chunk); 645562306a36Sopenharmony_ci if (packet) { 645662306a36Sopenharmony_ci struct sctp_signed_cookie *cookie; 645762306a36Sopenharmony_ci 645862306a36Sopenharmony_ci /* Override the OOTB vtag from the cookie. */ 645962306a36Sopenharmony_ci cookie = chunk->subh.cookie_hdr; 646062306a36Sopenharmony_ci packet->vtag = cookie->c.peer_vtag; 646162306a36Sopenharmony_ci 646262306a36Sopenharmony_ci /* Set the skb to the belonging sock for accounting. */ 646362306a36Sopenharmony_ci err_chunk->skb->sk = ep->base.sk; 646462306a36Sopenharmony_ci sctp_packet_append_chunk(packet, err_chunk); 646562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, 646662306a36Sopenharmony_ci SCTP_PACKET(packet)); 646762306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); 646862306a36Sopenharmony_ci } else 646962306a36Sopenharmony_ci sctp_chunk_free (err_chunk); 647062306a36Sopenharmony_ci } 647162306a36Sopenharmony_ci} 647262306a36Sopenharmony_ci 647362306a36Sopenharmony_ci 647462306a36Sopenharmony_ci/* Process a data chunk */ 647562306a36Sopenharmony_cistatic int sctp_eat_data(const struct sctp_association *asoc, 647662306a36Sopenharmony_ci struct sctp_chunk *chunk, 647762306a36Sopenharmony_ci struct sctp_cmd_seq *commands) 647862306a36Sopenharmony_ci{ 647962306a36Sopenharmony_ci struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; 648062306a36Sopenharmony_ci struct sock *sk = asoc->base.sk; 648162306a36Sopenharmony_ci struct net *net = sock_net(sk); 648262306a36Sopenharmony_ci struct sctp_datahdr *data_hdr; 648362306a36Sopenharmony_ci struct sctp_chunk *err; 648462306a36Sopenharmony_ci enum sctp_verb deliver; 648562306a36Sopenharmony_ci size_t datalen; 648662306a36Sopenharmony_ci __u32 tsn; 648762306a36Sopenharmony_ci int tmp; 648862306a36Sopenharmony_ci 648962306a36Sopenharmony_ci data_hdr = (struct sctp_datahdr *)chunk->skb->data; 649062306a36Sopenharmony_ci chunk->subh.data_hdr = data_hdr; 649162306a36Sopenharmony_ci skb_pull(chunk->skb, sctp_datahdr_len(&asoc->stream)); 649262306a36Sopenharmony_ci 649362306a36Sopenharmony_ci tsn = ntohl(data_hdr->tsn); 649462306a36Sopenharmony_ci pr_debug("%s: TSN 0x%x\n", __func__, tsn); 649562306a36Sopenharmony_ci 649662306a36Sopenharmony_ci /* ASSERT: Now skb->data is really the user data. */ 649762306a36Sopenharmony_ci 649862306a36Sopenharmony_ci /* Process ECN based congestion. 649962306a36Sopenharmony_ci * 650062306a36Sopenharmony_ci * Since the chunk structure is reused for all chunks within 650162306a36Sopenharmony_ci * a packet, we use ecn_ce_done to track if we've already 650262306a36Sopenharmony_ci * done CE processing for this packet. 650362306a36Sopenharmony_ci * 650462306a36Sopenharmony_ci * We need to do ECN processing even if we plan to discard the 650562306a36Sopenharmony_ci * chunk later. 650662306a36Sopenharmony_ci */ 650762306a36Sopenharmony_ci 650862306a36Sopenharmony_ci if (asoc->peer.ecn_capable && !chunk->ecn_ce_done) { 650962306a36Sopenharmony_ci struct sctp_af *af = SCTP_INPUT_CB(chunk->skb)->af; 651062306a36Sopenharmony_ci chunk->ecn_ce_done = 1; 651162306a36Sopenharmony_ci 651262306a36Sopenharmony_ci if (af->is_ce(sctp_gso_headskb(chunk->skb))) { 651362306a36Sopenharmony_ci /* Do real work as side effect. */ 651462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, 651562306a36Sopenharmony_ci SCTP_U32(tsn)); 651662306a36Sopenharmony_ci } 651762306a36Sopenharmony_ci } 651862306a36Sopenharmony_ci 651962306a36Sopenharmony_ci tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn); 652062306a36Sopenharmony_ci if (tmp < 0) { 652162306a36Sopenharmony_ci /* The TSN is too high--silently discard the chunk and 652262306a36Sopenharmony_ci * count on it getting retransmitted later. 652362306a36Sopenharmony_ci */ 652462306a36Sopenharmony_ci if (chunk->asoc) 652562306a36Sopenharmony_ci chunk->asoc->stats.outofseqtsns++; 652662306a36Sopenharmony_ci return SCTP_IERROR_HIGH_TSN; 652762306a36Sopenharmony_ci } else if (tmp > 0) { 652862306a36Sopenharmony_ci /* This is a duplicate. Record it. */ 652962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn)); 653062306a36Sopenharmony_ci return SCTP_IERROR_DUP_TSN; 653162306a36Sopenharmony_ci } 653262306a36Sopenharmony_ci 653362306a36Sopenharmony_ci /* This is a new TSN. */ 653462306a36Sopenharmony_ci 653562306a36Sopenharmony_ci /* Discard if there is no room in the receive window. 653662306a36Sopenharmony_ci * Actually, allow a little bit of overflow (up to a MTU). 653762306a36Sopenharmony_ci */ 653862306a36Sopenharmony_ci datalen = ntohs(chunk->chunk_hdr->length); 653962306a36Sopenharmony_ci datalen -= sctp_datachk_len(&asoc->stream); 654062306a36Sopenharmony_ci 654162306a36Sopenharmony_ci deliver = SCTP_CMD_CHUNK_ULP; 654262306a36Sopenharmony_ci 654362306a36Sopenharmony_ci /* Think about partial delivery. */ 654462306a36Sopenharmony_ci if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { 654562306a36Sopenharmony_ci 654662306a36Sopenharmony_ci /* Even if we don't accept this chunk there is 654762306a36Sopenharmony_ci * memory pressure. 654862306a36Sopenharmony_ci */ 654962306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL()); 655062306a36Sopenharmony_ci } 655162306a36Sopenharmony_ci 655262306a36Sopenharmony_ci /* Spill over rwnd a little bit. Note: While allowed, this spill over 655362306a36Sopenharmony_ci * seems a bit troublesome in that frag_point varies based on 655462306a36Sopenharmony_ci * PMTU. In cases, such as loopback, this might be a rather 655562306a36Sopenharmony_ci * large spill over. 655662306a36Sopenharmony_ci */ 655762306a36Sopenharmony_ci if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || 655862306a36Sopenharmony_ci (datalen > asoc->rwnd + asoc->frag_point))) { 655962306a36Sopenharmony_ci 656062306a36Sopenharmony_ci /* If this is the next TSN, consider reneging to make 656162306a36Sopenharmony_ci * room. Note: Playing nice with a confused sender. A 656262306a36Sopenharmony_ci * malicious sender can still eat up all our buffer 656362306a36Sopenharmony_ci * space and in the future we may want to detect and 656462306a36Sopenharmony_ci * do more drastic reneging. 656562306a36Sopenharmony_ci */ 656662306a36Sopenharmony_ci if (sctp_tsnmap_has_gap(map) && 656762306a36Sopenharmony_ci (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { 656862306a36Sopenharmony_ci pr_debug("%s: reneging for tsn:%u\n", __func__, tsn); 656962306a36Sopenharmony_ci deliver = SCTP_CMD_RENEGE; 657062306a36Sopenharmony_ci } else { 657162306a36Sopenharmony_ci pr_debug("%s: discard tsn:%u len:%zu, rwnd:%d\n", 657262306a36Sopenharmony_ci __func__, tsn, datalen, asoc->rwnd); 657362306a36Sopenharmony_ci 657462306a36Sopenharmony_ci return SCTP_IERROR_IGNORE_TSN; 657562306a36Sopenharmony_ci } 657662306a36Sopenharmony_ci } 657762306a36Sopenharmony_ci 657862306a36Sopenharmony_ci /* 657962306a36Sopenharmony_ci * Also try to renege to limit our memory usage in the event that 658062306a36Sopenharmony_ci * we are under memory pressure 658162306a36Sopenharmony_ci * If we can't renege, don't worry about it, the sk_rmem_schedule 658262306a36Sopenharmony_ci * in sctp_ulpevent_make_rcvmsg will drop the frame if we grow our 658362306a36Sopenharmony_ci * memory usage too much 658462306a36Sopenharmony_ci */ 658562306a36Sopenharmony_ci if (sk_under_memory_pressure(sk)) { 658662306a36Sopenharmony_ci if (sctp_tsnmap_has_gap(map) && 658762306a36Sopenharmony_ci (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { 658862306a36Sopenharmony_ci pr_debug("%s: under pressure, reneging for tsn:%u\n", 658962306a36Sopenharmony_ci __func__, tsn); 659062306a36Sopenharmony_ci deliver = SCTP_CMD_RENEGE; 659162306a36Sopenharmony_ci } 659262306a36Sopenharmony_ci } 659362306a36Sopenharmony_ci 659462306a36Sopenharmony_ci /* 659562306a36Sopenharmony_ci * Section 3.3.10.9 No User Data (9) 659662306a36Sopenharmony_ci * 659762306a36Sopenharmony_ci * Cause of error 659862306a36Sopenharmony_ci * --------------- 659962306a36Sopenharmony_ci * No User Data: This error cause is returned to the originator of a 660062306a36Sopenharmony_ci * DATA chunk if a received DATA chunk has no user data. 660162306a36Sopenharmony_ci */ 660262306a36Sopenharmony_ci if (unlikely(0 == datalen)) { 660362306a36Sopenharmony_ci err = sctp_make_abort_no_data(asoc, chunk, tsn); 660462306a36Sopenharmony_ci if (err) { 660562306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 660662306a36Sopenharmony_ci SCTP_CHUNK(err)); 660762306a36Sopenharmony_ci } 660862306a36Sopenharmony_ci /* We are going to ABORT, so we might as well stop 660962306a36Sopenharmony_ci * processing the rest of the chunks in the packet. 661062306a36Sopenharmony_ci */ 661162306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); 661262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, 661362306a36Sopenharmony_ci SCTP_ERROR(ECONNABORTED)); 661462306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, 661562306a36Sopenharmony_ci SCTP_PERR(SCTP_ERROR_NO_DATA)); 661662306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); 661762306a36Sopenharmony_ci SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); 661862306a36Sopenharmony_ci return SCTP_IERROR_NO_DATA; 661962306a36Sopenharmony_ci } 662062306a36Sopenharmony_ci 662162306a36Sopenharmony_ci chunk->data_accepted = 1; 662262306a36Sopenharmony_ci 662362306a36Sopenharmony_ci /* Note: Some chunks may get overcounted (if we drop) or overcounted 662462306a36Sopenharmony_ci * if we renege and the chunk arrives again. 662562306a36Sopenharmony_ci */ 662662306a36Sopenharmony_ci if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { 662762306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS); 662862306a36Sopenharmony_ci if (chunk->asoc) 662962306a36Sopenharmony_ci chunk->asoc->stats.iuodchunks++; 663062306a36Sopenharmony_ci } else { 663162306a36Sopenharmony_ci SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS); 663262306a36Sopenharmony_ci if (chunk->asoc) 663362306a36Sopenharmony_ci chunk->asoc->stats.iodchunks++; 663462306a36Sopenharmony_ci } 663562306a36Sopenharmony_ci 663662306a36Sopenharmony_ci /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number 663762306a36Sopenharmony_ci * 663862306a36Sopenharmony_ci * If an endpoint receive a DATA chunk with an invalid stream 663962306a36Sopenharmony_ci * identifier, it shall acknowledge the reception of the DATA chunk 664062306a36Sopenharmony_ci * following the normal procedure, immediately send an ERROR chunk 664162306a36Sopenharmony_ci * with cause set to "Invalid Stream Identifier" (See Section 3.3.10) 664262306a36Sopenharmony_ci * and discard the DATA chunk. 664362306a36Sopenharmony_ci */ 664462306a36Sopenharmony_ci if (ntohs(data_hdr->stream) >= asoc->stream.incnt) { 664562306a36Sopenharmony_ci /* Mark tsn as received even though we drop it */ 664662306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); 664762306a36Sopenharmony_ci 664862306a36Sopenharmony_ci err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, 664962306a36Sopenharmony_ci &data_hdr->stream, 665062306a36Sopenharmony_ci sizeof(data_hdr->stream), 665162306a36Sopenharmony_ci sizeof(u16)); 665262306a36Sopenharmony_ci if (err) 665362306a36Sopenharmony_ci sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 665462306a36Sopenharmony_ci SCTP_CHUNK(err)); 665562306a36Sopenharmony_ci return SCTP_IERROR_BAD_STREAM; 665662306a36Sopenharmony_ci } 665762306a36Sopenharmony_ci 665862306a36Sopenharmony_ci /* Check to see if the SSN is possible for this TSN. 665962306a36Sopenharmony_ci * The biggest gap we can record is 4K wide. Since SSNs wrap 666062306a36Sopenharmony_ci * at an unsigned short, there is no way that an SSN can 666162306a36Sopenharmony_ci * wrap and for a valid TSN. We can simply check if the current 666262306a36Sopenharmony_ci * SSN is smaller then the next expected one. If it is, it wrapped 666362306a36Sopenharmony_ci * and is invalid. 666462306a36Sopenharmony_ci */ 666562306a36Sopenharmony_ci if (!asoc->stream.si->validate_data(chunk)) 666662306a36Sopenharmony_ci return SCTP_IERROR_PROTO_VIOLATION; 666762306a36Sopenharmony_ci 666862306a36Sopenharmony_ci /* Send the data up to the user. Note: Schedule the 666962306a36Sopenharmony_ci * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK 667062306a36Sopenharmony_ci * chunk needs the updated rwnd. 667162306a36Sopenharmony_ci */ 667262306a36Sopenharmony_ci sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk)); 667362306a36Sopenharmony_ci 667462306a36Sopenharmony_ci return SCTP_IERROR_NO_ERROR; 667562306a36Sopenharmony_ci} 6676