xref: /onnv-gate/usr/src/uts/common/inet/sctp/sctp_error.c (revision 13009:29fc56bd19a6)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211735Skcpoon 
220Sstevel@tonic-gate /*
2312869SKacheong.Poon@Sun.COM  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/systm.h>
280Sstevel@tonic-gate #include <sys/stream.h>
290Sstevel@tonic-gate #include <sys/cmn_err.h>
300Sstevel@tonic-gate #include <sys/ddi.h>
310Sstevel@tonic-gate #include <sys/strsubr.h>
321676Sjpk #include <sys/tsol/tnet.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <netinet/in.h>
350Sstevel@tonic-gate #include <netinet/ip6.h>
360Sstevel@tonic-gate 
3711042SErik.Nordmark@Sun.COM #include <inet/ipsec_impl.h>
380Sstevel@tonic-gate #include <inet/common.h>
390Sstevel@tonic-gate #include <inet/ip.h>
400Sstevel@tonic-gate #include <inet/ip6.h>
4111042SErik.Nordmark@Sun.COM #include <inet/ipsec_impl.h>
420Sstevel@tonic-gate #include <inet/mib2.h>
430Sstevel@tonic-gate #include <inet/sctp_ip.h>
440Sstevel@tonic-gate #include <inet/ipclassifier.h>
450Sstevel@tonic-gate #include <inet/ip_ire.h>
460Sstevel@tonic-gate #include "sctp_impl.h"
470Sstevel@tonic-gate #include "sctp_asconf.h"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate ssize_t
sctp_link_abort(mblk_t * mp,uint16_t serror,char * details,size_t len,int iserror,boolean_t tbit)500Sstevel@tonic-gate sctp_link_abort(mblk_t *mp, uint16_t serror, char *details, size_t len,
510Sstevel@tonic-gate     int iserror, boolean_t tbit)
520Sstevel@tonic-gate {
530Sstevel@tonic-gate 	size_t alen;
540Sstevel@tonic-gate 	mblk_t *amp;
550Sstevel@tonic-gate 	sctp_chunk_hdr_t *acp;
560Sstevel@tonic-gate 	sctp_parm_hdr_t *eph;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	ASSERT(mp != NULL && mp->b_cont == NULL);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	alen = sizeof (*acp) + (serror != 0 ? (sizeof (*eph) + len) : 0);
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	amp = allocb(alen, BPRI_MED);
630Sstevel@tonic-gate 	if (amp == NULL) {
640Sstevel@tonic-gate 		return (-1);
650Sstevel@tonic-gate 	}
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	amp->b_wptr = amp->b_rptr + alen;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	/* Chunk header */
700Sstevel@tonic-gate 	acp = (sctp_chunk_hdr_t *)amp->b_rptr;
710Sstevel@tonic-gate 	acp->sch_id = iserror ? CHUNK_ERROR : CHUNK_ABORT;
720Sstevel@tonic-gate 	acp->sch_flags = 0;
730Sstevel@tonic-gate 	acp->sch_len = htons(alen);
740Sstevel@tonic-gate 	if (tbit)
750Sstevel@tonic-gate 		SCTP_SET_TBIT(acp);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	linkb(mp, amp);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if (serror == 0) {
800Sstevel@tonic-gate 		return (alen);
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	eph = (sctp_parm_hdr_t *)(acp + 1);
840Sstevel@tonic-gate 	eph->sph_type = htons(serror);
850Sstevel@tonic-gate 	eph->sph_len = htons(len + sizeof (*eph));
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	if (len > 0) {
880Sstevel@tonic-gate 		bcopy(details, eph + 1, len);
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	/* XXX pad */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	return (alen);
940Sstevel@tonic-gate }
950Sstevel@tonic-gate 
960Sstevel@tonic-gate void
sctp_user_abort(sctp_t * sctp,mblk_t * data)977480SKacheong.Poon@Sun.COM sctp_user_abort(sctp_t *sctp, mblk_t *data)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate 	mblk_t *mp;
1000Sstevel@tonic-gate 	int len, hdrlen;
1010Sstevel@tonic-gate 	char *cause;
1020Sstevel@tonic-gate 	sctp_faddr_t *fp = sctp->sctp_current;
103*13009SChandrasekar.Marimuthu@Sun.COM 	ip_xmit_attr_t	*ixa = fp->sf_ixa;
1043448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
1050Sstevel@tonic-gate 
1069509Sanil.udupa@sun.com 	/*
1079509Sanil.udupa@sun.com 	 * Don't need notification if connection is not yet setup,
1089509Sanil.udupa@sun.com 	 * call sctp_clean_death() to reclaim resources.
1099509Sanil.udupa@sun.com 	 * Any pending connect call(s) will error out.
1109509Sanil.udupa@sun.com 	 */
1119509Sanil.udupa@sun.com 	if (sctp->sctp_state < SCTPS_COOKIE_WAIT) {
1129509Sanil.udupa@sun.com 		sctp_clean_death(sctp, ECONNABORTED);
1139509Sanil.udupa@sun.com 		return;
1149509Sanil.udupa@sun.com 	}
1159509Sanil.udupa@sun.com 
1160Sstevel@tonic-gate 	mp = sctp_make_mp(sctp, fp, 0);
1171735Skcpoon 	if (mp == NULL) {
1183448Sdh155122 		SCTP_KSTAT(sctps, sctp_send_user_abort_failed);
1190Sstevel@tonic-gate 		return;
1201735Skcpoon 	}
1211735Skcpoon 
1220Sstevel@tonic-gate 	/*
1230Sstevel@tonic-gate 	 * Create abort chunk.
1240Sstevel@tonic-gate 	 */
1250Sstevel@tonic-gate 	if (data) {
126*13009SChandrasekar.Marimuthu@Sun.COM 		if (fp->sf_isv4) {
1270Sstevel@tonic-gate 			hdrlen = sctp->sctp_hdr_len;
1280Sstevel@tonic-gate 		} else {
1290Sstevel@tonic-gate 			hdrlen = sctp->sctp_hdr6_len;
1300Sstevel@tonic-gate 		}
1310Sstevel@tonic-gate 		hdrlen += sizeof (sctp_chunk_hdr_t) + sizeof (sctp_parm_hdr_t);
1320Sstevel@tonic-gate 		cause = (char *)data->b_rptr;
1330Sstevel@tonic-gate 		len = data->b_wptr - data->b_rptr;
1340Sstevel@tonic-gate 
135*13009SChandrasekar.Marimuthu@Sun.COM 		if (len + hdrlen > fp->sf_pmss) {
136*13009SChandrasekar.Marimuthu@Sun.COM 			len = fp->sf_pmss - hdrlen;
1370Sstevel@tonic-gate 		}
1380Sstevel@tonic-gate 	} else {
1390Sstevel@tonic-gate 		cause = NULL;
1400Sstevel@tonic-gate 		len = 0;
1410Sstevel@tonic-gate 	}
1427480SKacheong.Poon@Sun.COM 	/*
1437480SKacheong.Poon@Sun.COM 	 * Since it is a user abort, we should have the sctp_t and hence
1447480SKacheong.Poon@Sun.COM 	 * the correct verification tag.  So we should not set the T-bit
1457480SKacheong.Poon@Sun.COM 	 * in the ABORT.
1467480SKacheong.Poon@Sun.COM 	 */
1470Sstevel@tonic-gate 	if ((len = sctp_link_abort(mp, SCTP_ERR_USER_ABORT, cause, len, 0,
1487480SKacheong.Poon@Sun.COM 	    B_FALSE)) < 0) {
1490Sstevel@tonic-gate 		freemsg(mp);
1500Sstevel@tonic-gate 		return;
1510Sstevel@tonic-gate 	}
15212869SKacheong.Poon@Sun.COM 	SCTPS_BUMP_MIB(sctps, sctpAborted);
1530Sstevel@tonic-gate 	BUMP_LOCAL(sctp->sctp_opkts);
1540Sstevel@tonic-gate 	BUMP_LOCAL(sctp->sctp_obchunks);
1550Sstevel@tonic-gate 
15611042SErik.Nordmark@Sun.COM 	sctp_set_iplen(sctp, mp, ixa);
15711042SErik.Nordmark@Sun.COM 	ASSERT(ixa->ixa_ire != NULL);
15811042SErik.Nordmark@Sun.COM 	ASSERT(ixa->ixa_cred != NULL);
15911042SErik.Nordmark@Sun.COM 
16011042SErik.Nordmark@Sun.COM 	(void) conn_ip_output(mp, ixa);
1617480SKacheong.Poon@Sun.COM 
1627480SKacheong.Poon@Sun.COM 	sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
1637480SKacheong.Poon@Sun.COM 	sctp_clean_death(sctp, ECONNABORTED);
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate /*
1670Sstevel@tonic-gate  * If iserror == 0, sends an abort. If iserror != 0, sends an error.
1680Sstevel@tonic-gate  */
1690Sstevel@tonic-gate void
sctp_send_abort(sctp_t * sctp,uint32_t vtag,uint16_t serror,char * details,size_t len,mblk_t * inmp,int iserror,boolean_t tbit,ip_recv_attr_t * ira)1700Sstevel@tonic-gate sctp_send_abort(sctp_t *sctp, uint32_t vtag, uint16_t serror, char *details,
17111042SErik.Nordmark@Sun.COM     size_t len, mblk_t *inmp, int iserror, boolean_t tbit, ip_recv_attr_t *ira)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	mblk_t		*hmp;
1750Sstevel@tonic-gate 	uint32_t	ip_hdr_len;
1760Sstevel@tonic-gate 	ipha_t		*iniph;
17711042SErik.Nordmark@Sun.COM 	ipha_t		*ahiph = NULL;
1780Sstevel@tonic-gate 	ip6_t		*inip6h;
17911042SErik.Nordmark@Sun.COM 	ip6_t		*ahip6h = NULL;
1800Sstevel@tonic-gate 	sctp_hdr_t	*sh;
1810Sstevel@tonic-gate 	sctp_hdr_t	*insh;
1820Sstevel@tonic-gate 	size_t		ahlen;
1830Sstevel@tonic-gate 	uchar_t		*p;
1840Sstevel@tonic-gate 	ssize_t		alen;
1850Sstevel@tonic-gate 	int		isv4;
18611042SErik.Nordmark@Sun.COM 	conn_t		*connp = sctp->sctp_connp;
1873448Sdh155122 	sctp_stack_t	*sctps = sctp->sctp_sctps;
18811042SErik.Nordmark@Sun.COM 	ip_xmit_attr_t	*ixa;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
1910Sstevel@tonic-gate 	if (isv4) {
1920Sstevel@tonic-gate 		ahlen = sctp->sctp_hdr_len;
1930Sstevel@tonic-gate 	} else {
1940Sstevel@tonic-gate 		ahlen = sctp->sctp_hdr6_len;
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 
1971676Sjpk 	/*
1981676Sjpk 	 * If this is a labeled system, then check to see if we're allowed to
1991676Sjpk 	 * send a response to this particular sender.  If not, then just drop.
2001676Sjpk 	 */
20111042SErik.Nordmark@Sun.COM 	if (is_system_labeled() && !tsol_can_reply_error(inmp, ira))
2021676Sjpk 		return;
2031676Sjpk 
20411042SErik.Nordmark@Sun.COM 	hmp = allocb(sctps->sctps_wroff_xtra + ahlen, BPRI_MED);
2050Sstevel@tonic-gate 	if (hmp == NULL) {
2060Sstevel@tonic-gate 		/* XXX no resources */
2070Sstevel@tonic-gate 		return;
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	/* copy in the IP / SCTP header */
2113448Sdh155122 	p = hmp->b_rptr + sctps->sctps_wroff_xtra;
2120Sstevel@tonic-gate 	hmp->b_rptr = p;
2130Sstevel@tonic-gate 	hmp->b_wptr = p + ahlen;
2140Sstevel@tonic-gate 	if (isv4) {
2150Sstevel@tonic-gate 		bcopy(sctp->sctp_iphc, p, sctp->sctp_hdr_len);
2160Sstevel@tonic-gate 		/*
2170Sstevel@tonic-gate 		 * Composite is likely incomplete at this point, so pull
2180Sstevel@tonic-gate 		 * info from the incoming IP / SCTP headers.
2190Sstevel@tonic-gate 		 */
2200Sstevel@tonic-gate 		ahiph = (ipha_t *)p;
2210Sstevel@tonic-gate 		iniph = (ipha_t *)inmp->b_rptr;
2220Sstevel@tonic-gate 		ip_hdr_len = IPH_HDR_LENGTH(inmp->b_rptr);
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 		sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr_len);
2250Sstevel@tonic-gate 		ASSERT(OK_32PTR(sh));
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 		insh = (sctp_hdr_t *)((uchar_t *)iniph + ip_hdr_len);
2280Sstevel@tonic-gate 		ASSERT(OK_32PTR(insh));
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 		/* Copy in the peer's IP addr */
2310Sstevel@tonic-gate 		ahiph->ipha_dst = iniph->ipha_src;
2320Sstevel@tonic-gate 		ahiph->ipha_src = iniph->ipha_dst;
2330Sstevel@tonic-gate 	} else {
2340Sstevel@tonic-gate 		bcopy(sctp->sctp_iphc6, p, sctp->sctp_hdr6_len);
2350Sstevel@tonic-gate 		ahip6h = (ip6_t *)p;
2360Sstevel@tonic-gate 		inip6h = (ip6_t *)inmp->b_rptr;
2377480SKacheong.Poon@Sun.COM 		ip_hdr_len = ip_hdr_length_v6(inmp, inip6h);
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 		sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr6_len);
2400Sstevel@tonic-gate 		ASSERT(OK_32PTR(sh));
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 		insh = (sctp_hdr_t *)((uchar_t *)inip6h + ip_hdr_len);
2430Sstevel@tonic-gate 		ASSERT(OK_32PTR(insh));
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		/* Copy in the peer's IP addr */
2460Sstevel@tonic-gate 		ahip6h->ip6_dst = inip6h->ip6_src;
2470Sstevel@tonic-gate 		ahip6h->ip6_src = inip6h->ip6_dst;
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	/* Fill in the holes in the SCTP common header */
2510Sstevel@tonic-gate 	sh->sh_sport = insh->sh_dport;
2520Sstevel@tonic-gate 	sh->sh_dport = insh->sh_sport;
2530Sstevel@tonic-gate 	sh->sh_verf = vtag;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	/* Link in the abort chunk */
2560Sstevel@tonic-gate 	if ((alen = sctp_link_abort(hmp, serror, details, len, iserror, tbit))
2570Sstevel@tonic-gate 	    < 0) {
2580Sstevel@tonic-gate 		freemsg(hmp);
2590Sstevel@tonic-gate 		return;
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 
26211042SErik.Nordmark@Sun.COM 	/*
26311042SErik.Nordmark@Sun.COM 	 * Base the transmission on any routing-related socket options
26411042SErik.Nordmark@Sun.COM 	 * that have been set on the listener/connection.
26511042SErik.Nordmark@Sun.COM 	 */
26611042SErik.Nordmark@Sun.COM 	ixa = conn_get_ixa_exclusive(connp);
26711042SErik.Nordmark@Sun.COM 	if (ixa == NULL) {
26811042SErik.Nordmark@Sun.COM 		freemsg(hmp);
26911042SErik.Nordmark@Sun.COM 		return;
27011042SErik.Nordmark@Sun.COM 	}
27111042SErik.Nordmark@Sun.COM 	ixa->ixa_flags &= ~IXAF_VERIFY_PMTU;
27211042SErik.Nordmark@Sun.COM 
27311042SErik.Nordmark@Sun.COM 	ixa->ixa_pktlen = ahlen + alen;
2740Sstevel@tonic-gate 	if (isv4) {
27511042SErik.Nordmark@Sun.COM 		ixa->ixa_flags |= IXAF_IS_IPV4;
27611042SErik.Nordmark@Sun.COM 		ahiph->ipha_length = htons(ixa->ixa_pktlen);
27711042SErik.Nordmark@Sun.COM 		ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr_len;
2780Sstevel@tonic-gate 	} else {
27911042SErik.Nordmark@Sun.COM 		ixa->ixa_flags &= ~IXAF_IS_IPV4;
28011042SErik.Nordmark@Sun.COM 		ahip6h->ip6_plen = htons(ixa->ixa_pktlen - IPV6_HDR_LEN);
28111042SErik.Nordmark@Sun.COM 		ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr6_len;
2820Sstevel@tonic-gate 	}
2830Sstevel@tonic-gate 
28412869SKacheong.Poon@Sun.COM 	SCTPS_BUMP_MIB(sctps, sctpAborted);
2850Sstevel@tonic-gate 	BUMP_LOCAL(sctp->sctp_obchunks);
2860Sstevel@tonic-gate 
28711042SErik.Nordmark@Sun.COM 	if (is_system_labeled() && ixa->ixa_tsl != NULL) {
28811042SErik.Nordmark@Sun.COM 		ASSERT(ira->ira_tsl != NULL);
28911042SErik.Nordmark@Sun.COM 
29011042SErik.Nordmark@Sun.COM 		ixa->ixa_tsl = ira->ira_tsl;	/* A multi-level responder */
29111042SErik.Nordmark@Sun.COM 	}
2921676Sjpk 
29311042SErik.Nordmark@Sun.COM 	if (ira->ira_flags & IRAF_IPSEC_SECURE) {
29411042SErik.Nordmark@Sun.COM 		/*
29511042SErik.Nordmark@Sun.COM 		 * Apply IPsec based on how IPsec was applied to
29611042SErik.Nordmark@Sun.COM 		 * the packet that caused the abort.
29711042SErik.Nordmark@Sun.COM 		 */
29811042SErik.Nordmark@Sun.COM 		if (!ipsec_in_to_out(ira, ixa, hmp, ahiph, ahip6h)) {
29911042SErik.Nordmark@Sun.COM 			ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip;
30011042SErik.Nordmark@Sun.COM 
30111042SErik.Nordmark@Sun.COM 			BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
30211042SErik.Nordmark@Sun.COM 			/* Note: mp already consumed and ip_drop_packet done */
30311042SErik.Nordmark@Sun.COM 			ixa_refrele(ixa);
3041676Sjpk 			return;
3051676Sjpk 		}
30611042SErik.Nordmark@Sun.COM 	} else {
30711042SErik.Nordmark@Sun.COM 		ixa->ixa_flags |= IXAF_NO_IPSEC;
3081676Sjpk 	}
3091676Sjpk 
31011042SErik.Nordmark@Sun.COM 	BUMP_LOCAL(sctp->sctp_opkts);
31111042SErik.Nordmark@Sun.COM 	BUMP_LOCAL(sctp->sctp_obchunks);
31211042SErik.Nordmark@Sun.COM 
31311042SErik.Nordmark@Sun.COM 	(void) ip_output_simple(hmp, ixa);
31411042SErik.Nordmark@Sun.COM 	ixa_refrele(ixa);
31511042SErik.Nordmark@Sun.COM }
3161676Sjpk 
31711042SErik.Nordmark@Sun.COM /*
31811042SErik.Nordmark@Sun.COM  * OOTB version of the above.
31911042SErik.Nordmark@Sun.COM  * If iserror == 0, sends an abort. If iserror != 0, sends an error.
32011042SErik.Nordmark@Sun.COM  */
32111042SErik.Nordmark@Sun.COM void
sctp_ootb_send_abort(uint32_t vtag,uint16_t serror,char * details,size_t len,const mblk_t * inmp,int iserror,boolean_t tbit,ip_recv_attr_t * ira,ip_stack_t * ipst)32211042SErik.Nordmark@Sun.COM sctp_ootb_send_abort(uint32_t vtag, uint16_t serror, char *details,
32311042SErik.Nordmark@Sun.COM     size_t len, const mblk_t *inmp, int iserror, boolean_t tbit,
32411042SErik.Nordmark@Sun.COM     ip_recv_attr_t *ira, ip_stack_t *ipst)
32511042SErik.Nordmark@Sun.COM {
32611042SErik.Nordmark@Sun.COM 	uint32_t	ip_hdr_len;
32711042SErik.Nordmark@Sun.COM 	size_t		ahlen;
32811042SErik.Nordmark@Sun.COM 	ipha_t		*ipha = NULL;
32911042SErik.Nordmark@Sun.COM 	ip6_t		*ip6h = NULL;
33011042SErik.Nordmark@Sun.COM 	sctp_hdr_t	*insctph;
33111042SErik.Nordmark@Sun.COM 	int		i;
33211042SErik.Nordmark@Sun.COM 	uint16_t	port;
33311042SErik.Nordmark@Sun.COM 	ssize_t		alen;
33411042SErik.Nordmark@Sun.COM 	int		isv4;
33511042SErik.Nordmark@Sun.COM 	mblk_t		*mp;
33611042SErik.Nordmark@Sun.COM 	netstack_t	*ns = ipst->ips_netstack;
33711042SErik.Nordmark@Sun.COM 	sctp_stack_t	*sctps = ns->netstack_sctp;
33811042SErik.Nordmark@Sun.COM 	ip_xmit_attr_t	ixas;
33911042SErik.Nordmark@Sun.COM 
34011042SErik.Nordmark@Sun.COM 	bzero(&ixas, sizeof (ixas));
34111042SErik.Nordmark@Sun.COM 
34211042SErik.Nordmark@Sun.COM 	isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
34311042SErik.Nordmark@Sun.COM 	ip_hdr_len = ira->ira_ip_hdr_length;
34411042SErik.Nordmark@Sun.COM 	ahlen = ip_hdr_len + sizeof (sctp_hdr_t);
34511042SErik.Nordmark@Sun.COM 
3460Sstevel@tonic-gate 	/*
34711042SErik.Nordmark@Sun.COM 	 * If this is a labeled system, then check to see if we're allowed to
34811042SErik.Nordmark@Sun.COM 	 * send a response to this particular sender.  If not, then just drop.
3490Sstevel@tonic-gate 	 */
35011042SErik.Nordmark@Sun.COM 	if (is_system_labeled() && !tsol_can_reply_error(inmp, ira))
3510Sstevel@tonic-gate 		return;
35211042SErik.Nordmark@Sun.COM 
35311042SErik.Nordmark@Sun.COM 	mp = allocb(ahlen + sctps->sctps_wroff_xtra, BPRI_MED);
35411042SErik.Nordmark@Sun.COM 	if (mp == NULL) {
3550Sstevel@tonic-gate 		return;
3560Sstevel@tonic-gate 	}
35711042SErik.Nordmark@Sun.COM 	mp->b_rptr += sctps->sctps_wroff_xtra;
35811042SErik.Nordmark@Sun.COM 	mp->b_wptr = mp->b_rptr + ahlen;
35911042SErik.Nordmark@Sun.COM 	bcopy(inmp->b_rptr, mp->b_rptr, ahlen);
36011042SErik.Nordmark@Sun.COM 
3610Sstevel@tonic-gate 	/*
36211042SErik.Nordmark@Sun.COM 	 * We follow the logic in tcp_xmit_early_reset() in that we skip
36311042SErik.Nordmark@Sun.COM 	 * reversing source route (i.e. replace all IP options with EOL).
3640Sstevel@tonic-gate 	 */
36511042SErik.Nordmark@Sun.COM 	if (isv4) {
36611042SErik.Nordmark@Sun.COM 		ipaddr_t	v4addr;
36711042SErik.Nordmark@Sun.COM 
36811042SErik.Nordmark@Sun.COM 		ipha = (ipha_t *)mp->b_rptr;
36911042SErik.Nordmark@Sun.COM 		for (i = IP_SIMPLE_HDR_LENGTH; i < (int)ip_hdr_len; i++)
37011042SErik.Nordmark@Sun.COM 			mp->b_rptr[i] = IPOPT_EOL;
37111042SErik.Nordmark@Sun.COM 		/* Swap addresses */
37211042SErik.Nordmark@Sun.COM 		ipha->ipha_length = htons(ahlen);
37311042SErik.Nordmark@Sun.COM 		v4addr = ipha->ipha_src;
37411042SErik.Nordmark@Sun.COM 		ipha->ipha_src = ipha->ipha_dst;
37511042SErik.Nordmark@Sun.COM 		ipha->ipha_dst = v4addr;
37611042SErik.Nordmark@Sun.COM 		ipha->ipha_ident = 0;
37711042SErik.Nordmark@Sun.COM 		ipha->ipha_ttl = (uchar_t)sctps->sctps_ipv4_ttl;
37811042SErik.Nordmark@Sun.COM 
37911042SErik.Nordmark@Sun.COM 		ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4;
38011042SErik.Nordmark@Sun.COM 	} else {
38111042SErik.Nordmark@Sun.COM 		in6_addr_t	v6addr;
38211042SErik.Nordmark@Sun.COM 
38311042SErik.Nordmark@Sun.COM 		ip6h = (ip6_t *)mp->b_rptr;
38411042SErik.Nordmark@Sun.COM 		/* Remove any extension headers assuming partial overlay */
38511042SErik.Nordmark@Sun.COM 		if (ip_hdr_len > IPV6_HDR_LEN) {
38611042SErik.Nordmark@Sun.COM 			uint8_t	*to;
38711042SErik.Nordmark@Sun.COM 
38811042SErik.Nordmark@Sun.COM 			to = mp->b_rptr + ip_hdr_len - IPV6_HDR_LEN;
38911042SErik.Nordmark@Sun.COM 			ovbcopy(ip6h, to, IPV6_HDR_LEN);
39011042SErik.Nordmark@Sun.COM 			mp->b_rptr += ip_hdr_len - IPV6_HDR_LEN;
39111042SErik.Nordmark@Sun.COM 			ip_hdr_len = IPV6_HDR_LEN;
39211042SErik.Nordmark@Sun.COM 			ip6h = (ip6_t *)mp->b_rptr;
39311042SErik.Nordmark@Sun.COM 			ip6h->ip6_nxt = IPPROTO_SCTP;
39411042SErik.Nordmark@Sun.COM 			ahlen = ip_hdr_len + sizeof (sctp_hdr_t);
39511042SErik.Nordmark@Sun.COM 		}
39611042SErik.Nordmark@Sun.COM 		ip6h->ip6_plen = htons(ahlen - IPV6_HDR_LEN);
39711042SErik.Nordmark@Sun.COM 		v6addr = ip6h->ip6_src;
39811042SErik.Nordmark@Sun.COM 		ip6h->ip6_src = ip6h->ip6_dst;
39911042SErik.Nordmark@Sun.COM 		ip6h->ip6_dst = v6addr;
40011042SErik.Nordmark@Sun.COM 		ip6h->ip6_hops = (uchar_t)sctps->sctps_ipv6_hoplimit;
40111042SErik.Nordmark@Sun.COM 
40211042SErik.Nordmark@Sun.COM 		ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6;
40311042SErik.Nordmark@Sun.COM 		if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_dst)) {
40411042SErik.Nordmark@Sun.COM 			ixas.ixa_flags |= IXAF_SCOPEID_SET;
40511042SErik.Nordmark@Sun.COM 			ixas.ixa_scopeid = ira->ira_ruifindex;
40611042SErik.Nordmark@Sun.COM 		}
4070Sstevel@tonic-gate 	}
40811042SErik.Nordmark@Sun.COM 	insctph = (sctp_hdr_t *)(mp->b_rptr + ip_hdr_len);
40911042SErik.Nordmark@Sun.COM 
41011042SErik.Nordmark@Sun.COM 	/* Swap ports.  Verification tag is reused. */
41111042SErik.Nordmark@Sun.COM 	port = insctph->sh_sport;
41211042SErik.Nordmark@Sun.COM 	insctph->sh_sport = insctph->sh_dport;
41311042SErik.Nordmark@Sun.COM 	insctph->sh_dport = port;
41411042SErik.Nordmark@Sun.COM 	insctph->sh_verf = vtag;
41511042SErik.Nordmark@Sun.COM 
41611042SErik.Nordmark@Sun.COM 	/* Link in the abort chunk */
41711042SErik.Nordmark@Sun.COM 	if ((alen = sctp_link_abort(mp, serror, details, len, iserror, tbit))
41811042SErik.Nordmark@Sun.COM 	    < 0) {
41911042SErik.Nordmark@Sun.COM 		freemsg(mp);
42011042SErik.Nordmark@Sun.COM 		return;
42111042SErik.Nordmark@Sun.COM 	}
42211042SErik.Nordmark@Sun.COM 
42311042SErik.Nordmark@Sun.COM 	ixas.ixa_pktlen = ahlen + alen;
42411042SErik.Nordmark@Sun.COM 	ixas.ixa_ip_hdr_length = ip_hdr_len;
42511042SErik.Nordmark@Sun.COM 
42611042SErik.Nordmark@Sun.COM 	if (isv4) {
42711042SErik.Nordmark@Sun.COM 		ipha->ipha_length = htons(ixas.ixa_pktlen);
42811042SErik.Nordmark@Sun.COM 	} else {
42911042SErik.Nordmark@Sun.COM 		ip6h->ip6_plen = htons(ixas.ixa_pktlen - IPV6_HDR_LEN);
43011042SErik.Nordmark@Sun.COM 	}
43111042SErik.Nordmark@Sun.COM 
43211042SErik.Nordmark@Sun.COM 	ixas.ixa_protocol = IPPROTO_SCTP;
43311042SErik.Nordmark@Sun.COM 	ixas.ixa_zoneid = ira->ira_zoneid;
43411042SErik.Nordmark@Sun.COM 	ixas.ixa_ipst = ipst;
43511042SErik.Nordmark@Sun.COM 	ixas.ixa_ifindex = 0;
43611042SErik.Nordmark@Sun.COM 
43712869SKacheong.Poon@Sun.COM 	SCTPS_BUMP_MIB(sctps, sctpAborted);
43811042SErik.Nordmark@Sun.COM 
43911042SErik.Nordmark@Sun.COM 	if (is_system_labeled()) {
44011042SErik.Nordmark@Sun.COM 		ASSERT(ira->ira_tsl != NULL);
44111042SErik.Nordmark@Sun.COM 
44211042SErik.Nordmark@Sun.COM 		ixas.ixa_tsl = ira->ira_tsl;	/* A multi-level responder */
44311042SErik.Nordmark@Sun.COM 	}
44411042SErik.Nordmark@Sun.COM 
44511042SErik.Nordmark@Sun.COM 	if (ira->ira_flags & IRAF_IPSEC_SECURE) {
44611042SErik.Nordmark@Sun.COM 		/*
44711042SErik.Nordmark@Sun.COM 		 * Apply IPsec based on how IPsec was applied to
44811042SErik.Nordmark@Sun.COM 		 * the packet that was out of the blue.
44911042SErik.Nordmark@Sun.COM 		 */
45011042SErik.Nordmark@Sun.COM 		if (!ipsec_in_to_out(ira, &ixas, mp, ipha, ip6h)) {
45111042SErik.Nordmark@Sun.COM 			BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
45211042SErik.Nordmark@Sun.COM 			/* Note: mp already consumed and ip_drop_packet done */
45311042SErik.Nordmark@Sun.COM 			return;
45411042SErik.Nordmark@Sun.COM 		}
45511042SErik.Nordmark@Sun.COM 	} else {
45611042SErik.Nordmark@Sun.COM 		/*
45711042SErik.Nordmark@Sun.COM 		 * This is in clear. The abort message we are building
45811042SErik.Nordmark@Sun.COM 		 * here should go out in clear, independent of our policy.
45911042SErik.Nordmark@Sun.COM 		 */
46011042SErik.Nordmark@Sun.COM 		ixas.ixa_flags |= IXAF_NO_IPSEC;
46111042SErik.Nordmark@Sun.COM 	}
46211042SErik.Nordmark@Sun.COM 
46311042SErik.Nordmark@Sun.COM 	(void) ip_output_simple(mp, &ixas);
46411042SErik.Nordmark@Sun.COM 	ixa_cleanup(&ixas);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate /*ARGSUSED*/
4680Sstevel@tonic-gate mblk_t *
sctp_make_err(sctp_t * sctp,uint16_t serror,void * details,size_t len)4690Sstevel@tonic-gate sctp_make_err(sctp_t *sctp, uint16_t serror, void *details, size_t len)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	mblk_t *emp;
4730Sstevel@tonic-gate 	size_t elen;
4740Sstevel@tonic-gate 	sctp_chunk_hdr_t *ecp;
4750Sstevel@tonic-gate 	sctp_parm_hdr_t *eph;
4760Sstevel@tonic-gate 	int pad;
4770Sstevel@tonic-gate 
4784964Skcpoon 	if ((pad = len % SCTP_ALIGN) != 0) {
4794964Skcpoon 		pad = SCTP_ALIGN - pad;
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	elen = sizeof (*ecp) + sizeof (*eph) + len;
4830Sstevel@tonic-gate 	emp = allocb(elen + pad, BPRI_MED);
4840Sstevel@tonic-gate 	if (emp == NULL) {
4850Sstevel@tonic-gate 		return (NULL);
4860Sstevel@tonic-gate 	}
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	emp->b_wptr = emp->b_rptr + elen + pad;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	/* Chunk header */
4910Sstevel@tonic-gate 	ecp = (sctp_chunk_hdr_t *)emp->b_rptr;
4920Sstevel@tonic-gate 	ecp->sch_id = CHUNK_ERROR;
4930Sstevel@tonic-gate 	ecp->sch_flags = 0;
4940Sstevel@tonic-gate 	ecp->sch_len = htons(elen);
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	eph = (sctp_parm_hdr_t *)(ecp + 1);
4970Sstevel@tonic-gate 	eph->sph_type = htons(serror);
4980Sstevel@tonic-gate 	eph->sph_len = htons(len + sizeof (*eph));
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 	if (len > 0) {
5010Sstevel@tonic-gate 		bcopy(details, eph + 1, len);
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	if (pad != 0) {
5050Sstevel@tonic-gate 		bzero((uchar_t *)(eph + 1) + len, pad);
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	return (emp);
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate 
5114964Skcpoon /*
5124964Skcpoon  * Called from sctp_input_data() to add one error chunk to the error
5134964Skcpoon  * chunks list.  The error chunks list will be processed at the end
5144964Skcpoon  * of sctp_input_data() by calling sctp_process_err().
5154964Skcpoon  */
5160Sstevel@tonic-gate void
sctp_add_err(sctp_t * sctp,uint16_t serror,void * details,size_t len,sctp_faddr_t * dest)5174964Skcpoon sctp_add_err(sctp_t *sctp, uint16_t serror, void *details, size_t len,
5184964Skcpoon     sctp_faddr_t *dest)
5190Sstevel@tonic-gate {
5204964Skcpoon 	sctp_stack_t *sctps = sctp->sctp_sctps;
5214964Skcpoon 	mblk_t *emp;
5224964Skcpoon 	uint32_t emp_len;
5234964Skcpoon 	uint32_t mss;
5244964Skcpoon 	mblk_t *sendmp;
5254964Skcpoon 	sctp_faddr_t *fp;
5260Sstevel@tonic-gate 
5274964Skcpoon 	emp = sctp_make_err(sctp, serror, details, len);
5284964Skcpoon 	if (emp == NULL)
5294964Skcpoon 		return;
5304964Skcpoon 	emp_len = MBLKL(emp);
5314964Skcpoon 	if (sctp->sctp_err_chunks != NULL) {
5324964Skcpoon 		fp = SCTP_CHUNK_DEST(sctp->sctp_err_chunks);
5330Sstevel@tonic-gate 	} else {
5344964Skcpoon 		fp = dest;
5354964Skcpoon 		SCTP_SET_CHUNK_DEST(emp, dest);
5364964Skcpoon 	}
537*13009SChandrasekar.Marimuthu@Sun.COM 	mss = fp->sf_pmss;
5384964Skcpoon 
5394964Skcpoon 	/*
5404964Skcpoon 	 * If the current output packet cannot include the new error chunk,
5414964Skcpoon 	 * send out the current packet and then add the new error chunk
5424964Skcpoon 	 * to the new output packet.
5434964Skcpoon 	 */
5444964Skcpoon 	if (sctp->sctp_err_len + emp_len > mss) {
5454964Skcpoon 		if ((sendmp = sctp_make_mp(sctp, fp, 0)) == NULL) {
5463448Sdh155122 			SCTP_KSTAT(sctps, sctp_send_err_failed);
5474964Skcpoon 			/* Just free the latest error chunk. */
5484964Skcpoon 			freeb(emp);
5490Sstevel@tonic-gate 			return;
5500Sstevel@tonic-gate 		}
5514964Skcpoon 		sendmp->b_cont = sctp->sctp_err_chunks;
552*13009SChandrasekar.Marimuthu@Sun.COM 		sctp_set_iplen(sctp, sendmp, fp->sf_ixa);
553*13009SChandrasekar.Marimuthu@Sun.COM 		(void) conn_ip_output(sendmp, fp->sf_ixa);
55411042SErik.Nordmark@Sun.COM 		BUMP_LOCAL(sctp->sctp_opkts);
5554964Skcpoon 
5564964Skcpoon 		sctp->sctp_err_chunks = emp;
5574964Skcpoon 		sctp->sctp_err_len = emp_len;
5584964Skcpoon 		SCTP_SET_CHUNK_DEST(emp, dest);
5594964Skcpoon 	} else {
5604964Skcpoon 		if (sctp->sctp_err_chunks != NULL)
5614964Skcpoon 			linkb(sctp->sctp_err_chunks, emp);
5624964Skcpoon 		else
5634964Skcpoon 			sctp->sctp_err_chunks = emp;
5644964Skcpoon 		sctp->sctp_err_len += emp_len;
5650Sstevel@tonic-gate 	}
5664964Skcpoon 	/* Assume that we will send it out... */
5670Sstevel@tonic-gate 	BUMP_LOCAL(sctp->sctp_obchunks);
5684964Skcpoon }
5690Sstevel@tonic-gate 
5704964Skcpoon /*
5714964Skcpoon  * Called from sctp_input_data() to send out error chunks created during
5724964Skcpoon  * the processing of all the chunks in an incoming packet.
5734964Skcpoon  */
5744964Skcpoon void
sctp_process_err(sctp_t * sctp)5754964Skcpoon sctp_process_err(sctp_t *sctp)
5764964Skcpoon {
5774964Skcpoon 	sctp_stack_t *sctps = sctp->sctp_sctps;
5784964Skcpoon 	mblk_t *errmp;
5794964Skcpoon 	mblk_t *sendmp;
58011042SErik.Nordmark@Sun.COM 	sctp_faddr_t *fp;
5814964Skcpoon 
5824964Skcpoon 	ASSERT(sctp->sctp_err_chunks != NULL);
5834964Skcpoon 	errmp = sctp->sctp_err_chunks;
58411042SErik.Nordmark@Sun.COM 	fp = SCTP_CHUNK_DEST(errmp);
58511042SErik.Nordmark@Sun.COM 	if ((sendmp = sctp_make_mp(sctp, fp, 0)) == NULL) {
5864964Skcpoon 		SCTP_KSTAT(sctps, sctp_send_err_failed);
5874964Skcpoon 		freemsg(errmp);
5884964Skcpoon 		goto done;
5894964Skcpoon 	}
5904964Skcpoon 	sendmp->b_cont = errmp;
591*13009SChandrasekar.Marimuthu@Sun.COM 	sctp_set_iplen(sctp, sendmp, fp->sf_ixa);
592*13009SChandrasekar.Marimuthu@Sun.COM 	(void) conn_ip_output(sendmp, fp->sf_ixa);
59311042SErik.Nordmark@Sun.COM 	BUMP_LOCAL(sctp->sctp_opkts);
5944964Skcpoon done:
5954964Skcpoon 	sctp->sctp_err_chunks = NULL;
5964964Skcpoon 	sctp->sctp_err_len = 0;
5970Sstevel@tonic-gate }
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate /*
6000Sstevel@tonic-gate  * Returns 0 on non-fatal error, otherwise a system error on fatal
6010Sstevel@tonic-gate  * error.
6020Sstevel@tonic-gate  */
6030Sstevel@tonic-gate int
sctp_handle_error(sctp_t * sctp,sctp_hdr_t * sctph,sctp_chunk_hdr_t * ch,mblk_t * mp,ip_recv_attr_t * ira)6040Sstevel@tonic-gate sctp_handle_error(sctp_t *sctp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ch,
60511042SErik.Nordmark@Sun.COM     mblk_t *mp, ip_recv_attr_t *ira)
6060Sstevel@tonic-gate {
6070Sstevel@tonic-gate 	sctp_parm_hdr_t *errh;
6080Sstevel@tonic-gate 	sctp_chunk_hdr_t *uch;
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	if (ch->sch_len == htons(sizeof (*ch))) {
6110Sstevel@tonic-gate 		/* no error cause given */
6120Sstevel@tonic-gate 		return (0);
6130Sstevel@tonic-gate 	}
6140Sstevel@tonic-gate 	errh = (sctp_parm_hdr_t *)(ch + 1);
61511953Sanil.udupa@sun.com 	sctp_error_event(sctp, ch, B_FALSE);
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 	switch (errh->sph_type) {
6180Sstevel@tonic-gate 	/*
6190Sstevel@tonic-gate 	 * Both BAD_SID and NO_USR_DATA errors
6200Sstevel@tonic-gate 	 * indicate a serious bug in our stack,
6210Sstevel@tonic-gate 	 * so complain and abort the association.
6220Sstevel@tonic-gate 	 */
6230Sstevel@tonic-gate 	case SCTP_ERR_BAD_SID:
6240Sstevel@tonic-gate 		cmn_err(CE_WARN, "BUG! send to invalid SID");
62511042SErik.Nordmark@Sun.COM 		sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0,
62611042SErik.Nordmark@Sun.COM 		    ira);
6270Sstevel@tonic-gate 		return (ECONNABORTED);
6280Sstevel@tonic-gate 	case SCTP_ERR_NO_USR_DATA:
6290Sstevel@tonic-gate 		cmn_err(CE_WARN, "BUG! no usr data");
63011042SErik.Nordmark@Sun.COM 		sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0,
63111042SErik.Nordmark@Sun.COM 		    ira);
6320Sstevel@tonic-gate 		return (ECONNABORTED);
6330Sstevel@tonic-gate 	case SCTP_ERR_UNREC_CHUNK:
6340Sstevel@tonic-gate 		/* Pull out the unrecognized chunk type */
6350Sstevel@tonic-gate 		if (ntohs(errh->sph_len) < (sizeof (*errh) + sizeof (*uch))) {
6360Sstevel@tonic-gate 			/* Not enough to process */
6370Sstevel@tonic-gate 			return (0);
6380Sstevel@tonic-gate 		}
6390Sstevel@tonic-gate 		uch = (sctp_chunk_hdr_t *)(errh + 1);
6400Sstevel@tonic-gate 		if (uch->sch_id == CHUNK_ASCONF) {
6410Sstevel@tonic-gate 			/* Turn on ASCONF sending */
6420Sstevel@tonic-gate 			sctp->sctp_understands_asconf = B_FALSE;
6430Sstevel@tonic-gate 			/*
6440Sstevel@tonic-gate 			 * Hand off to asconf to clear out the unacked
6450Sstevel@tonic-gate 			 * asconf chunk.
6460Sstevel@tonic-gate 			 */
6470Sstevel@tonic-gate 			if (ntohs(uch->sch_len) !=
6480Sstevel@tonic-gate 			    (ntohs(errh->sph_len) - sizeof (*errh))) {
6490Sstevel@tonic-gate 				/* malformed */
6500Sstevel@tonic-gate 				dprint(0, ("Malformed Unrec Chunk error\n"));
6510Sstevel@tonic-gate 				return (0);
6520Sstevel@tonic-gate 			}
653852Svi117747 			sctp_asconf_free_cxmit(sctp, uch);
6540Sstevel@tonic-gate 			return (0);
6550Sstevel@tonic-gate 		}
6560Sstevel@tonic-gate 		/* Else drop it */
6570Sstevel@tonic-gate 		break;
6580Sstevel@tonic-gate 	default:
6590Sstevel@tonic-gate 		break;
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	return (0);
6630Sstevel@tonic-gate }
664