| 9240 | } |
| 9241 | |
| 9242 | void |
| 9243 | sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net, int addr_locked) |
| 9244 | { |
| 9245 | /* |
| 9246 | * formulate and queue an ASCONF to the peer. ASCONF parameters |
| 9247 | * should be queued on the assoc queue. |
| 9248 | */ |
| 9249 | struct sctp_tmit_chunk *chk; |
| 9250 | struct mbuf *m_asconf; |
| 9251 | int len; |
| 9252 | |
| 9253 | SCTP_TCB_LOCK_ASSERT(stcb); |
| 9254 | |
| 9255 | if ((!TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) && |
| 9256 | (!sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_MULTIPLE_ASCONFS))) { |
| 9257 | /* can't send a new one if there is one in flight already */ |
| 9258 | return; |
| 9259 | } |
| 9260 | |
| 9261 | /* compose an ASCONF chunk, maximum length is PMTU */ |
| 9262 | m_asconf = sctp_compose_asconf(stcb, &len, addr_locked); |
| 9263 | if (m_asconf == NULL) { |
| 9264 | return; |
| 9265 | } |
| 9266 | |
| 9267 | sctp_alloc_a_chunk(stcb, chk); |
| 9268 | if (chk == NULL) { |
| 9269 | /* no memory */ |
| 9270 | sctp_m_freem(m_asconf); |
| 9271 | return; |
| 9272 | } |
| 9273 | |
| 9274 | chk->copy_by_ref = 0; |
| 9275 | chk->rec.chunk_id.id = SCTP_ASCONF; |
| 9276 | chk->rec.chunk_id.can_take_data = 0; |
| 9277 | chk->flags = CHUNK_FLAGS_FRAGMENT_OK; |
| 9278 | chk->data = m_asconf; |
| 9279 | chk->send_size = len; |
| 9280 | chk->sent = SCTP_DATAGRAM_UNSENT; |
| 9281 | chk->snd_count = 0; |
| 9282 | chk->asoc = &stcb->asoc; |
| 9283 | chk->whoTo = net; |
| 9284 | if (chk->whoTo) { |
| 9285 | atomic_add_int(&chk->whoTo->ref_count, 1); |
| 9286 | } |
| 9287 | TAILQ_INSERT_TAIL(&chk->asoc->asconf_send_queue, chk, sctp_next); |
| 9288 | chk->asoc->ctrl_queue_cnt++; |
| 9289 | return; |
| 9290 | } |
| 9291 | |
| 9292 | void |
| 9293 | sctp_send_asconf_ack(struct sctp_tcb *stcb) |
no test coverage detected