/* * Reset any state related to transmitted chunks. */ void sctp_congest_reset(sctp_t *sctp) { sctp_faddr_t *fp; sctp_stack_t *sctps = sctp->sctp_sctps; mblk_t *mp; for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { fp->ssthresh = sctps->sctps_initial_mtu; SET_CWND(fp, fp->sfa_pmss, sctps->sctps_slow_start_initial); fp->suna = 0; fp->pba = 0; } /* * Clean up the transmit list as well since we have reset accounting * on all the fps. Send event upstream, if required. */ while ((mp = sctp->sctp_xmit_head) != NULL) { sctp->sctp_xmit_head = mp->b_next; mp->b_next = NULL; if (sctp->sctp_xmit_head != NULL) sctp->sctp_xmit_head->b_prev = NULL; sctp_sendfail_event(sctp, mp, 0, B_TRUE); } sctp->sctp_xmit_head = NULL; sctp->sctp_xmit_tail = NULL; sctp->sctp_xmit_unacked = NULL; sctp->sctp_unacked = 0; /* * Any control message as well. We will clean-up this list as well. * This contains any pending ASCONF request that we have queued/sent. * If we do get an ACK we will just drop it. However, given that * we are restarting chances are we aren't going to get any. */ if (sctp->sctp_cxmit_list != NULL) sctp_asconf_free_cxmit(sctp, NULL); sctp->sctp_cxmit_list = NULL; sctp->sctp_cchunk_pend = 0; sctp->sctp_rexmitting = B_FALSE; sctp->sctp_rxt_nxttsn = 0; sctp->sctp_rxt_maxtsn = 0; sctp->sctp_zero_win_probe = B_FALSE; }
/* * Returns 0 on non-fatal error, otherwise a system error on fatal * error. */ int sctp_handle_error(sctp_t *sctp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ch, mblk_t *mp, ip_recv_attr_t *ira) { sctp_parm_hdr_t *errh; sctp_chunk_hdr_t *uch; if (ch->sch_len == htons(sizeof (*ch))) { /* no error cause given */ return (0); } errh = (sctp_parm_hdr_t *)(ch + 1); sctp_error_event(sctp, ch, B_FALSE); switch (errh->sph_type) { /* * Both BAD_SID and NO_USR_DATA errors * indicate a serious bug in our stack, * so complain and abort the association. */ case SCTP_ERR_BAD_SID: cmn_err(CE_WARN, "BUG! send to invalid SID"); sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0, ira); return (ECONNABORTED); case SCTP_ERR_NO_USR_DATA: cmn_err(CE_WARN, "BUG! no usr data"); sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0, ira); return (ECONNABORTED); case SCTP_ERR_UNREC_CHUNK: /* Pull out the unrecognized chunk type */ if (ntohs(errh->sph_len) < (sizeof (*errh) + sizeof (*uch))) { /* Not enough to process */ return (0); } uch = (sctp_chunk_hdr_t *)(errh + 1); if (uch->sch_id == CHUNK_ASCONF) { /* Turn on ASCONF sending */ sctp->sctp_understands_asconf = B_FALSE; /* * Hand off to asconf to clear out the unacked * asconf chunk. */ if (ntohs(uch->sch_len) != (ntohs(errh->sph_len) - sizeof (*errh))) { /* malformed */ dprint(0, ("Malformed Unrec Chunk error\n")); return (0); } sctp_asconf_free_cxmit(sctp, uch); return (0); } /* Else drop it */ break; default: break; } return (0); }