162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* SCTP kernel implementation 362306a36Sopenharmony_ci * (C) Copyright IBM Corp. 2003, 2004 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This file is part of the SCTP kernel implementation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file contains the code relating the chunk abstraction. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the 1062306a36Sopenharmony_ci * email address(es): 1162306a36Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Written or modified by: 1462306a36Sopenharmony_ci * Jon Grimm <jgrimm@us.ibm.com> 1562306a36Sopenharmony_ci * Sridhar Samudrala <sri@us.ibm.com> 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/types.h> 2162306a36Sopenharmony_ci#include <linux/kernel.h> 2262306a36Sopenharmony_ci#include <linux/net.h> 2362306a36Sopenharmony_ci#include <linux/inet.h> 2462306a36Sopenharmony_ci#include <linux/skbuff.h> 2562306a36Sopenharmony_ci#include <linux/slab.h> 2662306a36Sopenharmony_ci#include <net/sock.h> 2762306a36Sopenharmony_ci#include <net/sctp/sctp.h> 2862306a36Sopenharmony_ci#include <net/sctp/sm.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* This file is mostly in anticipation of future work, but initially 3162306a36Sopenharmony_ci * populate with fragment tracking for an outbound message. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Initialize datamsg from memory. */ 3562306a36Sopenharmony_cistatic void sctp_datamsg_init(struct sctp_datamsg *msg) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci refcount_set(&msg->refcnt, 1); 3862306a36Sopenharmony_ci msg->send_failed = 0; 3962306a36Sopenharmony_ci msg->send_error = 0; 4062306a36Sopenharmony_ci msg->can_delay = 1; 4162306a36Sopenharmony_ci msg->abandoned = 0; 4262306a36Sopenharmony_ci msg->expires_at = 0; 4362306a36Sopenharmony_ci INIT_LIST_HEAD(&msg->chunks); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* Allocate and initialize datamsg. */ 4762306a36Sopenharmony_cistatic struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct sctp_datamsg *msg; 5062306a36Sopenharmony_ci msg = kmalloc(sizeof(struct sctp_datamsg), gfp); 5162306a36Sopenharmony_ci if (msg) { 5262306a36Sopenharmony_ci sctp_datamsg_init(msg); 5362306a36Sopenharmony_ci SCTP_DBG_OBJCNT_INC(datamsg); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci return msg; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_civoid sctp_datamsg_free(struct sctp_datamsg *msg) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct sctp_chunk *chunk; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* This doesn't have to be a _safe vairant because 6362306a36Sopenharmony_ci * sctp_chunk_free() only drops the refs. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci list_for_each_entry(chunk, &msg->chunks, frag_list) 6662306a36Sopenharmony_ci sctp_chunk_free(chunk); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci sctp_datamsg_put(msg); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* Final destructruction of datamsg memory. */ 7262306a36Sopenharmony_cistatic void sctp_datamsg_destroy(struct sctp_datamsg *msg) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct sctp_association *asoc = NULL; 7562306a36Sopenharmony_ci struct list_head *pos, *temp; 7662306a36Sopenharmony_ci struct sctp_chunk *chunk; 7762306a36Sopenharmony_ci struct sctp_ulpevent *ev; 7862306a36Sopenharmony_ci int error, sent; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* Release all references. */ 8162306a36Sopenharmony_ci list_for_each_safe(pos, temp, &msg->chunks) { 8262306a36Sopenharmony_ci list_del_init(pos); 8362306a36Sopenharmony_ci chunk = list_entry(pos, struct sctp_chunk, frag_list); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (!msg->send_failed) { 8662306a36Sopenharmony_ci sctp_chunk_put(chunk); 8762306a36Sopenharmony_ci continue; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci asoc = chunk->asoc; 9162306a36Sopenharmony_ci error = msg->send_error ?: asoc->outqueue.error; 9262306a36Sopenharmony_ci sent = chunk->has_tsn ? SCTP_DATA_SENT : SCTP_DATA_UNSENT; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (sctp_ulpevent_type_enabled(asoc->subscribe, 9562306a36Sopenharmony_ci SCTP_SEND_FAILED)) { 9662306a36Sopenharmony_ci ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent, 9762306a36Sopenharmony_ci error, GFP_ATOMIC); 9862306a36Sopenharmony_ci if (ev) 9962306a36Sopenharmony_ci asoc->stream.si->enqueue_event(&asoc->ulpq, ev); 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (sctp_ulpevent_type_enabled(asoc->subscribe, 10362306a36Sopenharmony_ci SCTP_SEND_FAILED_EVENT)) { 10462306a36Sopenharmony_ci ev = sctp_ulpevent_make_send_failed_event(asoc, chunk, 10562306a36Sopenharmony_ci sent, error, 10662306a36Sopenharmony_ci GFP_ATOMIC); 10762306a36Sopenharmony_ci if (ev) 10862306a36Sopenharmony_ci asoc->stream.si->enqueue_event(&asoc->ulpq, ev); 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci sctp_chunk_put(chunk); 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci SCTP_DBG_OBJCNT_DEC(datamsg); 11562306a36Sopenharmony_ci kfree(msg); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* Hold a reference. */ 11962306a36Sopenharmony_cistatic void sctp_datamsg_hold(struct sctp_datamsg *msg) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci refcount_inc(&msg->refcnt); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* Release a reference. */ 12562306a36Sopenharmony_civoid sctp_datamsg_put(struct sctp_datamsg *msg) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci if (refcount_dec_and_test(&msg->refcnt)) 12862306a36Sopenharmony_ci sctp_datamsg_destroy(msg); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* Assign a chunk to this datamsg. */ 13262306a36Sopenharmony_cistatic void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci sctp_datamsg_hold(msg); 13562306a36Sopenharmony_ci chunk->msg = msg; 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci/* A data chunk can have a maximum payload of (2^16 - 20). Break 14062306a36Sopenharmony_ci * down any such message into smaller chunks. Opportunistically, fragment 14162306a36Sopenharmony_ci * the chunks down to the current MTU constraints. We may get refragmented 14262306a36Sopenharmony_ci * later if the PMTU changes, but it is _much better_ to fragment immediately 14362306a36Sopenharmony_ci * with a reasonable guess than always doing our fragmentation on the 14462306a36Sopenharmony_ci * soft-interrupt. 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_cistruct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, 14762306a36Sopenharmony_ci struct sctp_sndrcvinfo *sinfo, 14862306a36Sopenharmony_ci struct iov_iter *from) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci size_t len, first_len, max_data, remaining; 15162306a36Sopenharmony_ci size_t msg_len = iov_iter_count(from); 15262306a36Sopenharmony_ci struct sctp_shared_key *shkey = NULL; 15362306a36Sopenharmony_ci struct list_head *pos, *temp; 15462306a36Sopenharmony_ci struct sctp_chunk *chunk; 15562306a36Sopenharmony_ci struct sctp_datamsg *msg; 15662306a36Sopenharmony_ci int err; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci msg = sctp_datamsg_new(GFP_KERNEL); 15962306a36Sopenharmony_ci if (!msg) 16062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* Note: Calculate this outside of the loop, so that all fragments 16362306a36Sopenharmony_ci * have the same expiration. 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ci if (asoc->peer.prsctp_capable && sinfo->sinfo_timetolive && 16662306a36Sopenharmony_ci (SCTP_PR_TTL_ENABLED(sinfo->sinfo_flags) || 16762306a36Sopenharmony_ci !SCTP_PR_POLICY(sinfo->sinfo_flags))) 16862306a36Sopenharmony_ci msg->expires_at = jiffies + 16962306a36Sopenharmony_ci msecs_to_jiffies(sinfo->sinfo_timetolive); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci /* This is the biggest possible DATA chunk that can fit into 17262306a36Sopenharmony_ci * the packet 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_ci max_data = asoc->frag_point; 17562306a36Sopenharmony_ci if (unlikely(!max_data)) { 17662306a36Sopenharmony_ci max_data = sctp_min_frag_point(sctp_sk(asoc->base.sk), 17762306a36Sopenharmony_ci sctp_datachk_len(&asoc->stream)); 17862306a36Sopenharmony_ci pr_warn_ratelimited("%s: asoc:%p frag_point is zero, forcing max_data to default minimum (%zu)", 17962306a36Sopenharmony_ci __func__, asoc, max_data); 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* If the peer requested that we authenticate DATA chunks 18362306a36Sopenharmony_ci * we need to account for bundling of the AUTH chunks along with 18462306a36Sopenharmony_ci * DATA. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) { 18762306a36Sopenharmony_ci struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (hmac_desc) 19062306a36Sopenharmony_ci max_data -= SCTP_PAD4(sizeof(struct sctp_auth_chunk) + 19162306a36Sopenharmony_ci hmac_desc->hmac_len); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (sinfo->sinfo_tsn && 19462306a36Sopenharmony_ci sinfo->sinfo_ssn != asoc->active_key_id) { 19562306a36Sopenharmony_ci shkey = sctp_auth_get_shkey(asoc, sinfo->sinfo_ssn); 19662306a36Sopenharmony_ci if (!shkey) { 19762306a36Sopenharmony_ci err = -EINVAL; 19862306a36Sopenharmony_ci goto errout; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci } else { 20162306a36Sopenharmony_ci shkey = asoc->shkey; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* Set first_len and then account for possible bundles on first frag */ 20662306a36Sopenharmony_ci first_len = max_data; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Check to see if we have a pending SACK and try to let it be bundled 20962306a36Sopenharmony_ci * with this message. Do this if we don't have any data queued already. 21062306a36Sopenharmony_ci * To check that, look at out_qlen and retransmit list. 21162306a36Sopenharmony_ci * NOTE: we will not reduce to account for SACK, if the message would 21262306a36Sopenharmony_ci * not have been fragmented. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci if (timer_pending(&asoc->timers[SCTP_EVENT_TIMEOUT_SACK]) && 21562306a36Sopenharmony_ci asoc->outqueue.out_qlen == 0 && 21662306a36Sopenharmony_ci list_empty(&asoc->outqueue.retransmit) && 21762306a36Sopenharmony_ci msg_len > max_data) 21862306a36Sopenharmony_ci first_len -= SCTP_PAD4(sizeof(struct sctp_sack_chunk)); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Encourage Cookie-ECHO bundling. */ 22162306a36Sopenharmony_ci if (asoc->state < SCTP_STATE_COOKIE_ECHOED) 22262306a36Sopenharmony_ci first_len -= SCTP_ARBITRARY_COOKIE_ECHO_LEN; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci /* Account for a different sized first fragment */ 22562306a36Sopenharmony_ci if (msg_len >= first_len) { 22662306a36Sopenharmony_ci msg->can_delay = 0; 22762306a36Sopenharmony_ci if (msg_len > first_len) 22862306a36Sopenharmony_ci SCTP_INC_STATS(asoc->base.net, 22962306a36Sopenharmony_ci SCTP_MIB_FRAGUSRMSGS); 23062306a36Sopenharmony_ci } else { 23162306a36Sopenharmony_ci /* Which may be the only one... */ 23262306a36Sopenharmony_ci first_len = msg_len; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* Create chunks for all DATA chunks. */ 23662306a36Sopenharmony_ci for (remaining = msg_len; remaining; remaining -= len) { 23762306a36Sopenharmony_ci u8 frag = SCTP_DATA_MIDDLE_FRAG; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (remaining == msg_len) { 24062306a36Sopenharmony_ci /* First frag, which may also be the last */ 24162306a36Sopenharmony_ci frag |= SCTP_DATA_FIRST_FRAG; 24262306a36Sopenharmony_ci len = first_len; 24362306a36Sopenharmony_ci } else { 24462306a36Sopenharmony_ci /* Middle frags */ 24562306a36Sopenharmony_ci len = max_data; 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (len >= remaining) { 24962306a36Sopenharmony_ci /* Last frag, which may also be the first */ 25062306a36Sopenharmony_ci len = remaining; 25162306a36Sopenharmony_ci frag |= SCTP_DATA_LAST_FRAG; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* The application requests to set the I-bit of the 25462306a36Sopenharmony_ci * last DATA chunk of a user message when providing 25562306a36Sopenharmony_ci * the user message to the SCTP implementation. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if ((sinfo->sinfo_flags & SCTP_EOF) || 25862306a36Sopenharmony_ci (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY)) 25962306a36Sopenharmony_ci frag |= SCTP_DATA_SACK_IMM; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci chunk = asoc->stream.si->make_datafrag(asoc, sinfo, len, frag, 26362306a36Sopenharmony_ci GFP_KERNEL); 26462306a36Sopenharmony_ci if (!chunk) { 26562306a36Sopenharmony_ci err = -ENOMEM; 26662306a36Sopenharmony_ci goto errout; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci err = sctp_user_addto_chunk(chunk, len, from); 27062306a36Sopenharmony_ci if (err < 0) 27162306a36Sopenharmony_ci goto errout_chunk_free; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci chunk->shkey = shkey; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Put the chunk->skb back into the form expected by send. */ 27662306a36Sopenharmony_ci __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr - 27762306a36Sopenharmony_ci chunk->skb->data); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci sctp_datamsg_assign(msg, chunk); 28062306a36Sopenharmony_ci list_add_tail(&chunk->frag_list, &msg->chunks); 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return msg; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cierrout_chunk_free: 28662306a36Sopenharmony_ci sctp_chunk_free(chunk); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cierrout: 28962306a36Sopenharmony_ci list_for_each_safe(pos, temp, &msg->chunks) { 29062306a36Sopenharmony_ci list_del_init(pos); 29162306a36Sopenharmony_ci chunk = list_entry(pos, struct sctp_chunk, frag_list); 29262306a36Sopenharmony_ci sctp_chunk_free(chunk); 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci sctp_datamsg_put(msg); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return ERR_PTR(err); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/* Check whether this message has expired. */ 30062306a36Sopenharmony_ciint sctp_chunk_abandoned(struct sctp_chunk *chunk) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci if (!chunk->asoc->peer.prsctp_capable) 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (chunk->msg->abandoned) 30662306a36Sopenharmony_ci return 1; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (!chunk->has_tsn && 30962306a36Sopenharmony_ci !(chunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)) 31062306a36Sopenharmony_ci return 0; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && 31362306a36Sopenharmony_ci time_after(jiffies, chunk->msg->expires_at)) { 31462306a36Sopenharmony_ci struct sctp_stream_out *streamout = 31562306a36Sopenharmony_ci SCTP_SO(&chunk->asoc->stream, 31662306a36Sopenharmony_ci chunk->sinfo.sinfo_stream); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (chunk->sent_count) { 31962306a36Sopenharmony_ci chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++; 32062306a36Sopenharmony_ci streamout->ext->abandoned_sent[SCTP_PR_INDEX(TTL)]++; 32162306a36Sopenharmony_ci } else { 32262306a36Sopenharmony_ci chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; 32362306a36Sopenharmony_ci streamout->ext->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci chunk->msg->abandoned = 1; 32662306a36Sopenharmony_ci return 1; 32762306a36Sopenharmony_ci } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && 32862306a36Sopenharmony_ci chunk->sent_count > chunk->sinfo.sinfo_timetolive) { 32962306a36Sopenharmony_ci struct sctp_stream_out *streamout = 33062306a36Sopenharmony_ci SCTP_SO(&chunk->asoc->stream, 33162306a36Sopenharmony_ci chunk->sinfo.sinfo_stream); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; 33462306a36Sopenharmony_ci streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++; 33562306a36Sopenharmony_ci chunk->msg->abandoned = 1; 33662306a36Sopenharmony_ci return 1; 33762306a36Sopenharmony_ci } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) && 33862306a36Sopenharmony_ci chunk->msg->expires_at && 33962306a36Sopenharmony_ci time_after(jiffies, chunk->msg->expires_at)) { 34062306a36Sopenharmony_ci chunk->msg->abandoned = 1; 34162306a36Sopenharmony_ci return 1; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci /* PRIO policy is processed by sendmsg, not here */ 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return 0; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci/* This chunk (and consequently entire message) has failed in its sending. */ 34962306a36Sopenharmony_civoid sctp_chunk_fail(struct sctp_chunk *chunk, int error) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci chunk->msg->send_failed = 1; 35262306a36Sopenharmony_ci chunk->msg->send_error = error; 35362306a36Sopenharmony_ci} 354