hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/net/sctp/ulpevent.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* SCTP kernel implementation
23 * (C) Copyright IBM Corp. 2001, 2004
34 * Copyright (c) 1999-2000 Cisco, Inc.
....@@ -8,22 +9,6 @@
89 *
910 * These functions manipulate an sctp event. The struct ulpevent is used
1011 * to carry notifications and data to the ULP (sockets).
11
- *
12
- * This SCTP implementation is free software;
13
- * you can redistribute it and/or modify it under the terms of
14
- * the GNU General Public License as published by
15
- * the Free Software Foundation; either version 2, or (at your option)
16
- * any later version.
17
- *
18
- * This SCTP implementation is distributed in the hope that it
19
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20
- * ************************
21
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22
- * See the GNU General Public License for more details.
23
- *
24
- * You should have received a copy of the GNU General Public License
25
- * along with GNU CC; see the file COPYING. If not, see
26
- * <http://www.gnu.org/licenses/>.
2712 *
2813 * Please send any bug reports or fixes you make to the
2914 * email address(es):
....@@ -253,7 +238,7 @@
253238 * When a destination address on a multi-homed peer encounters a change
254239 * an interface details event is sent.
255240 */
256
-struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
241
+static struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
257242 const struct sctp_association *asoc,
258243 const struct sockaddr_storage *aaddr,
259244 int flags, int state, int error, gfp_t gfp)
....@@ -349,6 +334,25 @@
349334
350335 fail:
351336 return NULL;
337
+}
338
+
339
+void sctp_ulpevent_notify_peer_addr_change(struct sctp_transport *transport,
340
+ int state, int error)
341
+{
342
+ struct sctp_association *asoc = transport->asoc;
343
+ struct sockaddr_storage addr;
344
+ struct sctp_ulpevent *event;
345
+
346
+ if (asoc->state < SCTP_STATE_ESTABLISHED)
347
+ return;
348
+
349
+ memset(&addr, 0, sizeof(struct sockaddr_storage));
350
+ memcpy(&addr, &transport->ipaddr, transport->af_specific->sockaddr_len);
351
+
352
+ event = sctp_ulpevent_make_peer_addr_change(asoc, &addr, 0, state,
353
+ error, GFP_ATOMIC);
354
+ if (event)
355
+ asoc->stream.si->enqueue_event(&asoc->ulpq, event);
352356 }
353357
354358 /* Create and initialize an SCTP_REMOTE_ERROR notification.
....@@ -526,6 +530,45 @@
526530 return NULL;
527531 }
528532
533
+struct sctp_ulpevent *sctp_ulpevent_make_send_failed_event(
534
+ const struct sctp_association *asoc, struct sctp_chunk *chunk,
535
+ __u16 flags, __u32 error, gfp_t gfp)
536
+{
537
+ struct sctp_send_failed_event *ssf;
538
+ struct sctp_ulpevent *event;
539
+ struct sk_buff *skb;
540
+ int len;
541
+
542
+ skb = skb_copy_expand(chunk->skb, sizeof(*ssf), 0, gfp);
543
+ if (!skb)
544
+ return NULL;
545
+
546
+ len = ntohs(chunk->chunk_hdr->length);
547
+ len -= sctp_datachk_len(&asoc->stream);
548
+
549
+ skb_pull(skb, sctp_datachk_len(&asoc->stream));
550
+ event = sctp_skb2event(skb);
551
+ sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
552
+
553
+ ssf = skb_push(skb, sizeof(*ssf));
554
+ ssf->ssf_type = SCTP_SEND_FAILED_EVENT;
555
+ ssf->ssf_flags = flags;
556
+ ssf->ssf_length = sizeof(*ssf) + len;
557
+ skb_trim(skb, ssf->ssf_length);
558
+ ssf->ssf_error = error;
559
+
560
+ ssf->ssfe_info.snd_sid = chunk->sinfo.sinfo_stream;
561
+ ssf->ssfe_info.snd_ppid = chunk->sinfo.sinfo_ppid;
562
+ ssf->ssfe_info.snd_context = chunk->sinfo.sinfo_context;
563
+ ssf->ssfe_info.snd_assoc_id = chunk->sinfo.sinfo_assoc_id;
564
+ ssf->ssfe_info.snd_flags = chunk->chunk_hdr->flags;
565
+
566
+ sctp_ulpevent_set_owner(event, asoc);
567
+ ssf->ssf_assoc_id = sctp_assoc2id(asoc);
568
+
569
+ return event;
570
+}
571
+
529572 /* Create and initialize a SCTP_SHUTDOWN_EVENT notification.
530573 *
531574 * Socket Extensions for SCTP - draft-01
....@@ -634,8 +677,9 @@
634677 gfp_t gfp)
635678 {
636679 struct sctp_ulpevent *event = NULL;
637
- struct sk_buff *skb;
638
- size_t padding, len;
680
+ struct sk_buff *skb = chunk->skb;
681
+ struct sock *sk = asoc->base.sk;
682
+ size_t padding, datalen;
639683 int rx_count;
640684
641685 /*
....@@ -646,15 +690,12 @@
646690 if (asoc->ep->rcvbuf_policy)
647691 rx_count = atomic_read(&asoc->rmem_alloc);
648692 else
649
- rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
693
+ rx_count = atomic_read(&sk->sk_rmem_alloc);
650694
651
- if (rx_count >= asoc->base.sk->sk_rcvbuf) {
695
+ datalen = ntohs(chunk->chunk_hdr->length);
652696
653
- if ((asoc->base.sk->sk_userlocks & SOCK_RCVBUF_LOCK) ||
654
- (!sk_rmem_schedule(asoc->base.sk, chunk->skb,
655
- chunk->skb->truesize)))
656
- goto fail;
657
- }
697
+ if (rx_count >= sk->sk_rcvbuf || !sk_rmem_schedule(sk, skb, datalen))
698
+ goto fail;
658699
659700 /* Clone the original skb, sharing the data. */
660701 skb = skb_clone(chunk->skb, gfp);
....@@ -681,8 +722,7 @@
681722 * The sender should never pad with more than 3 bytes. The receiver
682723 * MUST ignore the padding bytes.
683724 */
684
- len = ntohs(chunk->chunk_hdr->length);
685
- padding = SCTP_PAD4(len) - len;
725
+ padding = SCTP_PAD4(datalen) - datalen;
686726
687727 /* Fixup cloned skb with just this chunks data. */
688728 skb_trim(skb, chunk->chunk_end - padding - skb->data);