| 8878 | } |
| 8879 | |
| 8880 | void |
| 8881 | sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) |
| 8882 | { |
| 8883 | /*- |
| 8884 | * Prepend a OPERATIONAL_ERROR chunk header and put on the end of |
| 8885 | * the control chunk queue. |
| 8886 | */ |
| 8887 | struct sctp_chunkhdr *hdr; |
| 8888 | struct sctp_tmit_chunk *chk; |
| 8889 | struct mbuf *mat, *last_mbuf; |
| 8890 | uint32_t chunk_length; |
| 8891 | uint16_t padding_length; |
| 8892 | |
| 8893 | SCTP_TCB_LOCK_ASSERT(stcb); |
| 8894 | SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT); |
| 8895 | if (op_err == NULL) { |
| 8896 | return; |
| 8897 | } |
| 8898 | last_mbuf = NULL; |
| 8899 | chunk_length = 0; |
| 8900 | for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) { |
| 8901 | chunk_length += SCTP_BUF_LEN(mat); |
| 8902 | if (SCTP_BUF_NEXT(mat) == NULL) { |
| 8903 | last_mbuf = mat; |
| 8904 | } |
| 8905 | } |
| 8906 | if (chunk_length > SCTP_MAX_CHUNK_LENGTH) { |
| 8907 | sctp_m_freem(op_err); |
| 8908 | return; |
| 8909 | } |
| 8910 | padding_length = chunk_length % 4; |
| 8911 | if (padding_length != 0) { |
| 8912 | padding_length = 4 - padding_length; |
| 8913 | } |
| 8914 | if (padding_length != 0) { |
| 8915 | if (sctp_add_pad_tombuf(last_mbuf, padding_length) == NULL) { |
| 8916 | sctp_m_freem(op_err); |
| 8917 | return; |
| 8918 | } |
| 8919 | } |
| 8920 | sctp_alloc_a_chunk(stcb, chk); |
| 8921 | if (chk == NULL) { |
| 8922 | /* no memory */ |
| 8923 | sctp_m_freem(op_err); |
| 8924 | return; |
| 8925 | } |
| 8926 | chk->copy_by_ref = 0; |
| 8927 | chk->rec.chunk_id.id = SCTP_OPERATION_ERROR; |
| 8928 | chk->rec.chunk_id.can_take_data = 0; |
| 8929 | chk->flags = 0; |
| 8930 | chk->send_size = (uint16_t)chunk_length; |
| 8931 | chk->sent = SCTP_DATAGRAM_UNSENT; |
| 8932 | chk->snd_count = 0; |
| 8933 | chk->asoc = &stcb->asoc; |
| 8934 | chk->data = op_err; |
| 8935 | chk->whoTo = NULL; |
| 8936 | hdr = mtod(op_err, struct sctp_chunkhdr *); |
| 8937 | hdr->chunk_type = SCTP_OPERATION_ERROR; |
no test coverage detected