This always must be called with the read-queue LOCKED in the INP */
| 3643 | |
| 3644 | /* This always must be called with the read-queue LOCKED in the INP */ |
| 3645 | static void |
| 3646 | sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error, |
| 3647 | uint32_t val, int so_locked) |
| 3648 | { |
| 3649 | struct mbuf *m_notify; |
| 3650 | struct sctp_pdapi_event *pdapi; |
| 3651 | struct sctp_queued_to_read *control; |
| 3652 | struct sockbuf *sb; |
| 3653 | |
| 3654 | if ((stcb == NULL) || |
| 3655 | sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) { |
| 3656 | /* event not enabled */ |
| 3657 | return; |
| 3658 | } |
| 3659 | if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { |
| 3660 | return; |
| 3661 | } |
| 3662 | |
| 3663 | m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA); |
| 3664 | if (m_notify == NULL) |
| 3665 | /* no space left */ |
| 3666 | return; |
| 3667 | SCTP_BUF_LEN(m_notify) = 0; |
| 3668 | pdapi = mtod(m_notify, struct sctp_pdapi_event *); |
| 3669 | memset(pdapi, 0, sizeof(struct sctp_pdapi_event)); |
| 3670 | pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; |
| 3671 | pdapi->pdapi_flags = 0; |
| 3672 | pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); |
| 3673 | pdapi->pdapi_indication = error; |
| 3674 | pdapi->pdapi_stream = (val >> 16); |
| 3675 | pdapi->pdapi_seq = (val & 0x0000ffff); |
| 3676 | pdapi->pdapi_assoc_id = sctp_get_associd(stcb); |
| 3677 | |
| 3678 | SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event); |
| 3679 | SCTP_BUF_NEXT(m_notify) = NULL; |
| 3680 | control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, |
| 3681 | 0, 0, stcb->asoc.context, 0, 0, 0, |
| 3682 | m_notify); |
| 3683 | if (control == NULL) { |
| 3684 | /* no memory */ |
| 3685 | sctp_m_freem(m_notify); |
| 3686 | return; |
| 3687 | } |
| 3688 | control->length = SCTP_BUF_LEN(m_notify); |
| 3689 | control->spec_flags = M_NOTIFICATION; |
| 3690 | /* not that we need this */ |
| 3691 | control->tail_mbuf = m_notify; |
| 3692 | sb = &stcb->sctp_socket->so_rcv; |
| 3693 | if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { |
| 3694 | sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify)); |
| 3695 | } |
| 3696 | sctp_sballoc(stcb, sb, m_notify); |
| 3697 | if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { |
| 3698 | sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); |
| 3699 | } |
| 3700 | control->end_added = 1; |
| 3701 | if (stcb->asoc.control_pdapi) |
| 3702 | TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next); |
no test coverage detected