/*ARGSUSED*/ static void sctp_asconf_ack_unrec_parm(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph, sctp_faddr_t *fp, in6_addr_t *laddr) { ASSERT(ph); sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph); }
/*ARGSUSED*/ static void sctp_setprim_ack(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph, sctp_faddr_t *fp, in6_addr_t *laddr) { if (ph != NULL && ph->sph_type != htons(PARM_SUCCESS)) { /* If the peer doesn't understand Add-IP, remember it */ if (ph->sph_type == htons(PARM_UNRECOGNIZED)) { sctp->sctp_understands_addip = B_FALSE; } sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph); } /* On success we do nothing */ }
/*ARGSUSED*/ static void sctp_addip_ack(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph, sctp_faddr_t *fp, in6_addr_t *laddr) { in6_addr_t addr; sctp_saddr_ipif_t *sp; ipaddr_t *addr4; boolean_t backout = B_FALSE; uint16_t type; uint32_t *cid; /* could be an ASSERT */ if (laddr != NULL) IN6_IPADDR_TO_V4MAPPED(0, laddr); /* If the peer doesn't understand Add-IP, remember it */ if (ph != NULL && ph->sph_type == htons(PARM_UNRECOGNIZED)) { sctp->sctp_understands_addip = B_FALSE; backout = B_TRUE; } /* * If OK, continue with the add / delete action, otherwise * back out the action. */ if (ph != NULL && ph->sph_type != htons(PARM_SUCCESS)) { backout = B_TRUE; sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph); } type = ntohs(oph->sph_type); cid = (uint32_t *)(oph + 1); oph = (sctp_parm_hdr_t *)(cid + 1); if (oph->sph_type == htons(PARM_ADDR4)) { addr4 = (ipaddr_t *)(oph + 1); IN6_IPADDR_TO_V4MAPPED(*addr4, &addr); } else { bcopy(oph + 1, &addr, sizeof (addr)); } /* Signifies that the address was sucessfully processed */ if (!backout && laddr != NULL) *laddr = addr; sp = sctp_saddr_lookup(sctp, &addr, 0); ASSERT(sp != NULL); if (type == PARM_ADD_IP) { if (backout) { sctp_del_saddr(sctp, sp); } else { sp->saddr_ipif_dontsrc = 0; } } else if (type == PARM_DEL_IP) { if (backout) { sp->saddr_ipif_delete_pending = 0; sp->saddr_ipif_dontsrc = 0; } else { sctp_del_saddr(sctp, sp); } } else { /* Must be either PARM_ADD_IP or PARM_DEL_IP */ ASSERT(0); } }
/* * 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); }