.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* SCTP kernel implementation |
---|
2 | 3 | * (C) Copyright IBM Corp. 2001, 2004 |
---|
3 | 4 | * Copyright (c) 1999-2000 Cisco, Inc. |
---|
.. | .. |
---|
8 | 9 | * |
---|
9 | 10 | * These functions manipulate an sctp event. The struct ulpevent is used |
---|
10 | 11 | * 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/>. |
---|
27 | 12 | * |
---|
28 | 13 | * Please send any bug reports or fixes you make to the |
---|
29 | 14 | * email address(es): |
---|
.. | .. |
---|
253 | 238 | * When a destination address on a multi-homed peer encounters a change |
---|
254 | 239 | * an interface details event is sent. |
---|
255 | 240 | */ |
---|
256 | | -struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( |
---|
| 241 | +static struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( |
---|
257 | 242 | const struct sctp_association *asoc, |
---|
258 | 243 | const struct sockaddr_storage *aaddr, |
---|
259 | 244 | int flags, int state, int error, gfp_t gfp) |
---|
.. | .. |
---|
349 | 334 | |
---|
350 | 335 | fail: |
---|
351 | 336 | 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); |
---|
352 | 356 | } |
---|
353 | 357 | |
---|
354 | 358 | /* Create and initialize an SCTP_REMOTE_ERROR notification. |
---|
.. | .. |
---|
526 | 530 | return NULL; |
---|
527 | 531 | } |
---|
528 | 532 | |
---|
| 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 | + |
---|
529 | 572 | /* Create and initialize a SCTP_SHUTDOWN_EVENT notification. |
---|
530 | 573 | * |
---|
531 | 574 | * Socket Extensions for SCTP - draft-01 |
---|
.. | .. |
---|
634 | 677 | gfp_t gfp) |
---|
635 | 678 | { |
---|
636 | 679 | 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; |
---|
639 | 683 | int rx_count; |
---|
640 | 684 | |
---|
641 | 685 | /* |
---|
.. | .. |
---|
646 | 690 | if (asoc->ep->rcvbuf_policy) |
---|
647 | 691 | rx_count = atomic_read(&asoc->rmem_alloc); |
---|
648 | 692 | else |
---|
649 | | - rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); |
---|
| 693 | + rx_count = atomic_read(&sk->sk_rmem_alloc); |
---|
650 | 694 | |
---|
651 | | - if (rx_count >= asoc->base.sk->sk_rcvbuf) { |
---|
| 695 | + datalen = ntohs(chunk->chunk_hdr->length); |
---|
652 | 696 | |
---|
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; |
---|
658 | 699 | |
---|
659 | 700 | /* Clone the original skb, sharing the data. */ |
---|
660 | 701 | skb = skb_clone(chunk->skb, gfp); |
---|
.. | .. |
---|
681 | 722 | * The sender should never pad with more than 3 bytes. The receiver |
---|
682 | 723 | * MUST ignore the padding bytes. |
---|
683 | 724 | */ |
---|
684 | | - len = ntohs(chunk->chunk_hdr->length); |
---|
685 | | - padding = SCTP_PAD4(len) - len; |
---|
| 725 | + padding = SCTP_PAD4(datalen) - datalen; |
---|
686 | 726 | |
---|
687 | 727 | /* Fixup cloned skb with just this chunks data. */ |
---|
688 | 728 | skb_trim(skb, chunk->chunk_end - padding - skb->data); |
---|