Ejemplo n.º 1
0
/*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);
}
Ejemplo n.º 2
0
/*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 */
}
Ejemplo n.º 3
0
/*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);
	}
}
Ejemplo n.º 4
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);
}