| 10840 | } |
| 10841 | |
| 10842 | void |
| 10843 | sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked) |
| 10844 | { |
| 10845 | struct mbuf *m_abort, *m, *m_last; |
| 10846 | struct mbuf *m_out, *m_end = NULL; |
| 10847 | struct sctp_abort_chunk *abort; |
| 10848 | struct sctp_auth_chunk *auth = NULL; |
| 10849 | struct sctp_nets *net; |
| 10850 | uint32_t vtag; |
| 10851 | uint32_t auth_offset = 0; |
| 10852 | int error; |
| 10853 | uint16_t cause_len, chunk_len, padding_len; |
| 10854 | |
| 10855 | SCTP_TCB_LOCK_ASSERT(stcb); |
| 10856 | /*- |
| 10857 | * Add an AUTH chunk, if chunk requires it and save the offset into |
| 10858 | * the chain for AUTH |
| 10859 | */ |
| 10860 | if (sctp_auth_is_required_chunk(SCTP_ABORT_ASSOCIATION, |
| 10861 | stcb->asoc.peer_auth_chunks)) { |
| 10862 | m_out = sctp_add_auth_chunk(NULL, &m_end, &auth, &auth_offset, |
| 10863 | stcb, SCTP_ABORT_ASSOCIATION); |
| 10864 | SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks); |
| 10865 | } else { |
| 10866 | m_out = NULL; |
| 10867 | } |
| 10868 | m_abort = sctp_get_mbuf_for_msg(sizeof(struct sctp_abort_chunk), 0, M_NOWAIT, 1, MT_HEADER); |
| 10869 | if (m_abort == NULL) { |
| 10870 | if (m_out) { |
| 10871 | sctp_m_freem(m_out); |
| 10872 | } |
| 10873 | if (operr) { |
| 10874 | sctp_m_freem(operr); |
| 10875 | } |
| 10876 | return; |
| 10877 | } |
| 10878 | /* link in any error */ |
| 10879 | SCTP_BUF_NEXT(m_abort) = operr; |
| 10880 | cause_len = 0; |
| 10881 | m_last = NULL; |
| 10882 | for (m = operr; m; m = SCTP_BUF_NEXT(m)) { |
| 10883 | cause_len += (uint16_t)SCTP_BUF_LEN(m); |
| 10884 | if (SCTP_BUF_NEXT(m) == NULL) { |
| 10885 | m_last = m; |
| 10886 | } |
| 10887 | } |
| 10888 | SCTP_BUF_LEN(m_abort) = sizeof(struct sctp_abort_chunk); |
| 10889 | chunk_len = (uint16_t)sizeof(struct sctp_abort_chunk) + cause_len; |
| 10890 | padding_len = SCTP_SIZE32(chunk_len) - chunk_len; |
| 10891 | if (m_out == NULL) { |
| 10892 | /* NO Auth chunk prepended, so reserve space in front */ |
| 10893 | SCTP_BUF_RESV_UF(m_abort, SCTP_MIN_OVERHEAD); |
| 10894 | m_out = m_abort; |
| 10895 | } else { |
| 10896 | /* Put AUTH chunk at the front of the chain */ |
| 10897 | SCTP_BUF_NEXT(m_end) = m_abort; |
| 10898 | } |
| 10899 | if (stcb->asoc.alternate) { |
no test coverage detected