1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <sys/types.h>
27 #include <sys/systm.h>
28 #include <sys/stream.h>
29 #include <sys/cmn_err.h>
30 #include <sys/ddi.h>
31 #include <sys/strsubr.h>
32 #include <sys/tsol/tnet.h>
33
34 #include <netinet/in.h>
35 #include <netinet/ip6.h>
36
37 #include <inet/ipsec_impl.h>
38 #include <inet/common.h>
39 #include <inet/ip.h>
40 #include <inet/ip6.h>
41 #include <inet/ipsec_impl.h>
42 #include <inet/mib2.h>
43 #include <inet/sctp_ip.h>
44 #include <inet/ipclassifier.h>
45 #include <inet/ip_ire.h>
46 #include "sctp_impl.h"
47 #include "sctp_asconf.h"
48
49 ssize_t
sctp_link_abort(mblk_t * mp,uint16_t serror,char * details,size_t len,int iserror,boolean_t tbit)50 sctp_link_abort(mblk_t *mp, uint16_t serror, char *details, size_t len,
51 int iserror, boolean_t tbit)
52 {
53 size_t alen;
54 mblk_t *amp;
55 sctp_chunk_hdr_t *acp;
56 sctp_parm_hdr_t *eph;
57
58 ASSERT(mp != NULL && mp->b_cont == NULL);
59
60 alen = sizeof (*acp) + (serror != 0 ? (sizeof (*eph) + len) : 0);
61
62 amp = allocb(alen, BPRI_MED);
63 if (amp == NULL) {
64 return (-1);
65 }
66
67 amp->b_wptr = amp->b_rptr + alen;
68
69 /* Chunk header */
70 acp = (sctp_chunk_hdr_t *)amp->b_rptr;
71 acp->sch_id = iserror ? CHUNK_ERROR : CHUNK_ABORT;
72 acp->sch_flags = 0;
73 acp->sch_len = htons(alen);
74 if (tbit)
75 SCTP_SET_TBIT(acp);
76
77 linkb(mp, amp);
78
79 if (serror == 0) {
80 return (alen);
81 }
82
83 eph = (sctp_parm_hdr_t *)(acp + 1);
84 eph->sph_type = htons(serror);
85 eph->sph_len = htons(len + sizeof (*eph));
86
87 if (len > 0) {
88 bcopy(details, eph + 1, len);
89 }
90
91 /* XXX pad */
92
93 return (alen);
94 }
95
96 void
sctp_user_abort(sctp_t * sctp,mblk_t * data)97 sctp_user_abort(sctp_t *sctp, mblk_t *data)
98 {
99 mblk_t *mp;
100 int len, hdrlen;
101 char *cause;
102 sctp_faddr_t *fp = sctp->sctp_current;
103 ip_xmit_attr_t *ixa = fp->sf_ixa;
104 sctp_stack_t *sctps = sctp->sctp_sctps;
105
106 /*
107 * Don't need notification if connection is not yet setup,
108 * call sctp_clean_death() to reclaim resources.
109 * Any pending connect call(s) will error out.
110 */
111 if (sctp->sctp_state < SCTPS_COOKIE_WAIT) {
112 sctp_clean_death(sctp, ECONNABORTED);
113 return;
114 }
115
116 mp = sctp_make_mp(sctp, fp, 0);
117 if (mp == NULL) {
118 SCTP_KSTAT(sctps, sctp_send_user_abort_failed);
119 return;
120 }
121
122 /*
123 * Create abort chunk.
124 */
125 if (data) {
126 if (fp->sf_isv4) {
127 hdrlen = sctp->sctp_hdr_len;
128 } else {
129 hdrlen = sctp->sctp_hdr6_len;
130 }
131 hdrlen += sizeof (sctp_chunk_hdr_t) + sizeof (sctp_parm_hdr_t);
132 cause = (char *)data->b_rptr;
133 len = data->b_wptr - data->b_rptr;
134
135 if (len + hdrlen > fp->sf_pmss) {
136 len = fp->sf_pmss - hdrlen;
137 }
138 } else {
139 cause = NULL;
140 len = 0;
141 }
142 /*
143 * Since it is a user abort, we should have the sctp_t and hence
144 * the correct verification tag. So we should not set the T-bit
145 * in the ABORT.
146 */
147 if ((len = sctp_link_abort(mp, SCTP_ERR_USER_ABORT, cause, len, 0,
148 B_FALSE)) < 0) {
149 freemsg(mp);
150 return;
151 }
152 SCTPS_BUMP_MIB(sctps, sctpAborted);
153 BUMP_LOCAL(sctp->sctp_opkts);
154 BUMP_LOCAL(sctp->sctp_obchunks);
155
156 sctp_set_iplen(sctp, mp, ixa);
157 ASSERT(ixa->ixa_ire != NULL);
158 ASSERT(ixa->ixa_cred != NULL);
159
160 (void) conn_ip_output(mp, ixa);
161
162 sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
163 sctp_clean_death(sctp, ECONNABORTED);
164 }
165
166 /*
167 * If iserror == 0, sends an abort. If iserror != 0, sends an error.
168 */
169 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)170 sctp_send_abort(sctp_t *sctp, uint32_t vtag, uint16_t serror, char *details,
171 size_t len, mblk_t *inmp, int iserror, boolean_t tbit, ip_recv_attr_t *ira)
172 {
173
174 mblk_t *hmp;
175 uint32_t ip_hdr_len;
176 ipha_t *iniph;
177 ipha_t *ahiph = NULL;
178 ip6_t *inip6h;
179 ip6_t *ahip6h = NULL;
180 sctp_hdr_t *sh;
181 sctp_hdr_t *insh;
182 size_t ahlen;
183 uchar_t *p;
184 ssize_t alen;
185 int isv4;
186 conn_t *connp = sctp->sctp_connp;
187 sctp_stack_t *sctps = sctp->sctp_sctps;
188 ip_xmit_attr_t *ixa;
189
190 isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
191 if (isv4) {
192 ahlen = sctp->sctp_hdr_len;
193 } else {
194 ahlen = sctp->sctp_hdr6_len;
195 }
196
197 /*
198 * If this is a labeled system, then check to see if we're allowed to
199 * send a response to this particular sender. If not, then just drop.
200 */
201 if (is_system_labeled() && !tsol_can_reply_error(inmp, ira))
202 return;
203
204 hmp = allocb(sctps->sctps_wroff_xtra + ahlen, BPRI_MED);
205 if (hmp == NULL) {
206 /* XXX no resources */
207 return;
208 }
209
210 /* copy in the IP / SCTP header */
211 p = hmp->b_rptr + sctps->sctps_wroff_xtra;
212 hmp->b_rptr = p;
213 hmp->b_wptr = p + ahlen;
214 if (isv4) {
215 bcopy(sctp->sctp_iphc, p, sctp->sctp_hdr_len);
216 /*
217 * Composite is likely incomplete at this point, so pull
218 * info from the incoming IP / SCTP headers.
219 */
220 ahiph = (ipha_t *)p;
221 iniph = (ipha_t *)inmp->b_rptr;
222 ip_hdr_len = IPH_HDR_LENGTH(inmp->b_rptr);
223
224 sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr_len);
225 ASSERT(OK_32PTR(sh));
226
227 insh = (sctp_hdr_t *)((uchar_t *)iniph + ip_hdr_len);
228 ASSERT(OK_32PTR(insh));
229
230 /* Copy in the peer's IP addr */
231 ahiph->ipha_dst = iniph->ipha_src;
232 ahiph->ipha_src = iniph->ipha_dst;
233 } else {
234 bcopy(sctp->sctp_iphc6, p, sctp->sctp_hdr6_len);
235 ahip6h = (ip6_t *)p;
236 inip6h = (ip6_t *)inmp->b_rptr;
237 ip_hdr_len = ip_hdr_length_v6(inmp, inip6h);
238
239 sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr6_len);
240 ASSERT(OK_32PTR(sh));
241
242 insh = (sctp_hdr_t *)((uchar_t *)inip6h + ip_hdr_len);
243 ASSERT(OK_32PTR(insh));
244
245 /* Copy in the peer's IP addr */
246 ahip6h->ip6_dst = inip6h->ip6_src;
247 ahip6h->ip6_src = inip6h->ip6_dst;
248 }
249
250 /* Fill in the holes in the SCTP common header */
251 sh->sh_sport = insh->sh_dport;
252 sh->sh_dport = insh->sh_sport;
253 sh->sh_verf = vtag;
254
255 /* Link in the abort chunk */
256 if ((alen = sctp_link_abort(hmp, serror, details, len, iserror, tbit))
257 < 0) {
258 freemsg(hmp);
259 return;
260 }
261
262 /*
263 * Base the transmission on any routing-related socket options
264 * that have been set on the listener/connection.
265 */
266 ixa = conn_get_ixa_exclusive(connp);
267 if (ixa == NULL) {
268 freemsg(hmp);
269 return;
270 }
271 ixa->ixa_flags &= ~IXAF_VERIFY_PMTU;
272
273 ixa->ixa_pktlen = ahlen + alen;
274 if (isv4) {
275 ixa->ixa_flags |= IXAF_IS_IPV4;
276 ahiph->ipha_length = htons(ixa->ixa_pktlen);
277 ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr_len;
278 } else {
279 ixa->ixa_flags &= ~IXAF_IS_IPV4;
280 ahip6h->ip6_plen = htons(ixa->ixa_pktlen - IPV6_HDR_LEN);
281 ixa->ixa_ip_hdr_length = sctp->sctp_ip_hdr6_len;
282 }
283
284 SCTPS_BUMP_MIB(sctps, sctpAborted);
285 BUMP_LOCAL(sctp->sctp_obchunks);
286
287 if (is_system_labeled() && ixa->ixa_tsl != NULL) {
288 ASSERT(ira->ira_tsl != NULL);
289
290 ixa->ixa_tsl = ira->ira_tsl; /* A multi-level responder */
291 }
292
293 if (ira->ira_flags & IRAF_IPSEC_SECURE) {
294 /*
295 * Apply IPsec based on how IPsec was applied to
296 * the packet that caused the abort.
297 */
298 if (!ipsec_in_to_out(ira, ixa, hmp, ahiph, ahip6h)) {
299 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip;
300
301 BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
302 /* Note: mp already consumed and ip_drop_packet done */
303 ixa_refrele(ixa);
304 return;
305 }
306 } else {
307 ixa->ixa_flags |= IXAF_NO_IPSEC;
308 }
309
310 BUMP_LOCAL(sctp->sctp_opkts);
311 BUMP_LOCAL(sctp->sctp_obchunks);
312
313 (void) ip_output_simple(hmp, ixa);
314 ixa_refrele(ixa);
315 }
316
317 /*
318 * OOTB version of the above.
319 * If iserror == 0, sends an abort. If iserror != 0, sends an error.
320 */
321 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)322 sctp_ootb_send_abort(uint32_t vtag, uint16_t serror, char *details,
323 size_t len, const mblk_t *inmp, int iserror, boolean_t tbit,
324 ip_recv_attr_t *ira, ip_stack_t *ipst)
325 {
326 uint32_t ip_hdr_len;
327 size_t ahlen;
328 ipha_t *ipha = NULL;
329 ip6_t *ip6h = NULL;
330 sctp_hdr_t *insctph;
331 int i;
332 uint16_t port;
333 ssize_t alen;
334 int isv4;
335 mblk_t *mp;
336 netstack_t *ns = ipst->ips_netstack;
337 sctp_stack_t *sctps = ns->netstack_sctp;
338 ip_xmit_attr_t ixas;
339
340 bzero(&ixas, sizeof (ixas));
341
342 isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION);
343 ip_hdr_len = ira->ira_ip_hdr_length;
344 ahlen = ip_hdr_len + sizeof (sctp_hdr_t);
345
346 /*
347 * If this is a labeled system, then check to see if we're allowed to
348 * send a response to this particular sender. If not, then just drop.
349 */
350 if (is_system_labeled() && !tsol_can_reply_error(inmp, ira))
351 return;
352
353 mp = allocb(ahlen + sctps->sctps_wroff_xtra, BPRI_MED);
354 if (mp == NULL) {
355 return;
356 }
357 mp->b_rptr += sctps->sctps_wroff_xtra;
358 mp->b_wptr = mp->b_rptr + ahlen;
359 bcopy(inmp->b_rptr, mp->b_rptr, ahlen);
360
361 /*
362 * We follow the logic in tcp_xmit_early_reset() in that we skip
363 * reversing source route (i.e. replace all IP options with EOL).
364 */
365 if (isv4) {
366 ipaddr_t v4addr;
367
368 ipha = (ipha_t *)mp->b_rptr;
369 for (i = IP_SIMPLE_HDR_LENGTH; i < (int)ip_hdr_len; i++)
370 mp->b_rptr[i] = IPOPT_EOL;
371 /* Swap addresses */
372 ipha->ipha_length = htons(ahlen);
373 v4addr = ipha->ipha_src;
374 ipha->ipha_src = ipha->ipha_dst;
375 ipha->ipha_dst = v4addr;
376 ipha->ipha_ident = 0;
377 ipha->ipha_ttl = (uchar_t)sctps->sctps_ipv4_ttl;
378
379 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4;
380 } else {
381 in6_addr_t v6addr;
382
383 ip6h = (ip6_t *)mp->b_rptr;
384 /* Remove any extension headers assuming partial overlay */
385 if (ip_hdr_len > IPV6_HDR_LEN) {
386 uint8_t *to;
387
388 to = mp->b_rptr + ip_hdr_len - IPV6_HDR_LEN;
389 ovbcopy(ip6h, to, IPV6_HDR_LEN);
390 mp->b_rptr += ip_hdr_len - IPV6_HDR_LEN;
391 ip_hdr_len = IPV6_HDR_LEN;
392 ip6h = (ip6_t *)mp->b_rptr;
393 ip6h->ip6_nxt = IPPROTO_SCTP;
394 ahlen = ip_hdr_len + sizeof (sctp_hdr_t);
395 }
396 ip6h->ip6_plen = htons(ahlen - IPV6_HDR_LEN);
397 v6addr = ip6h->ip6_src;
398 ip6h->ip6_src = ip6h->ip6_dst;
399 ip6h->ip6_dst = v6addr;
400 ip6h->ip6_hops = (uchar_t)sctps->sctps_ipv6_hoplimit;
401
402 ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6;
403 if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_dst)) {
404 ixas.ixa_flags |= IXAF_SCOPEID_SET;
405 ixas.ixa_scopeid = ira->ira_ruifindex;
406 }
407 }
408 insctph = (sctp_hdr_t *)(mp->b_rptr + ip_hdr_len);
409
410 /* Swap ports. Verification tag is reused. */
411 port = insctph->sh_sport;
412 insctph->sh_sport = insctph->sh_dport;
413 insctph->sh_dport = port;
414 insctph->sh_verf = vtag;
415
416 /* Link in the abort chunk */
417 if ((alen = sctp_link_abort(mp, serror, details, len, iserror, tbit))
418 < 0) {
419 freemsg(mp);
420 return;
421 }
422
423 ixas.ixa_pktlen = ahlen + alen;
424 ixas.ixa_ip_hdr_length = ip_hdr_len;
425
426 if (isv4) {
427 ipha->ipha_length = htons(ixas.ixa_pktlen);
428 } else {
429 ip6h->ip6_plen = htons(ixas.ixa_pktlen - IPV6_HDR_LEN);
430 }
431
432 ixas.ixa_protocol = IPPROTO_SCTP;
433 ixas.ixa_zoneid = ira->ira_zoneid;
434 ixas.ixa_ipst = ipst;
435 ixas.ixa_ifindex = 0;
436
437 SCTPS_BUMP_MIB(sctps, sctpAborted);
438
439 if (is_system_labeled()) {
440 ASSERT(ira->ira_tsl != NULL);
441
442 ixas.ixa_tsl = ira->ira_tsl; /* A multi-level responder */
443 }
444
445 if (ira->ira_flags & IRAF_IPSEC_SECURE) {
446 /*
447 * Apply IPsec based on how IPsec was applied to
448 * the packet that was out of the blue.
449 */
450 if (!ipsec_in_to_out(ira, &ixas, mp, ipha, ip6h)) {
451 BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards);
452 /* Note: mp already consumed and ip_drop_packet done */
453 return;
454 }
455 } else {
456 /*
457 * This is in clear. The abort message we are building
458 * here should go out in clear, independent of our policy.
459 */
460 ixas.ixa_flags |= IXAF_NO_IPSEC;
461 }
462
463 (void) ip_output_simple(mp, &ixas);
464 ixa_cleanup(&ixas);
465 }
466
467 /*ARGSUSED*/
468 mblk_t *
sctp_make_err(sctp_t * sctp,uint16_t serror,void * details,size_t len)469 sctp_make_err(sctp_t *sctp, uint16_t serror, void *details, size_t len)
470 {
471
472 mblk_t *emp;
473 size_t elen;
474 sctp_chunk_hdr_t *ecp;
475 sctp_parm_hdr_t *eph;
476 int pad;
477
478 if ((pad = len % SCTP_ALIGN) != 0) {
479 pad = SCTP_ALIGN - pad;
480 }
481
482 elen = sizeof (*ecp) + sizeof (*eph) + len;
483 emp = allocb(elen + pad, BPRI_MED);
484 if (emp == NULL) {
485 return (NULL);
486 }
487
488 emp->b_wptr = emp->b_rptr + elen + pad;
489
490 /* Chunk header */
491 ecp = (sctp_chunk_hdr_t *)emp->b_rptr;
492 ecp->sch_id = CHUNK_ERROR;
493 ecp->sch_flags = 0;
494 ecp->sch_len = htons(elen);
495
496 eph = (sctp_parm_hdr_t *)(ecp + 1);
497 eph->sph_type = htons(serror);
498 eph->sph_len = htons(len + sizeof (*eph));
499
500 if (len > 0) {
501 bcopy(details, eph + 1, len);
502 }
503
504 if (pad != 0) {
505 bzero((uchar_t *)(eph + 1) + len, pad);
506 }
507
508 return (emp);
509 }
510
511 /*
512 * Called from sctp_input_data() to add one error chunk to the error
513 * chunks list. The error chunks list will be processed at the end
514 * of sctp_input_data() by calling sctp_process_err().
515 */
516 void
sctp_add_err(sctp_t * sctp,uint16_t serror,void * details,size_t len,sctp_faddr_t * dest)517 sctp_add_err(sctp_t *sctp, uint16_t serror, void *details, size_t len,
518 sctp_faddr_t *dest)
519 {
520 sctp_stack_t *sctps = sctp->sctp_sctps;
521 mblk_t *emp;
522 uint32_t emp_len;
523 uint32_t mss;
524 mblk_t *sendmp;
525 sctp_faddr_t *fp;
526
527 emp = sctp_make_err(sctp, serror, details, len);
528 if (emp == NULL)
529 return;
530 emp_len = MBLKL(emp);
531 if (sctp->sctp_err_chunks != NULL) {
532 fp = SCTP_CHUNK_DEST(sctp->sctp_err_chunks);
533 } else {
534 fp = dest;
535 SCTP_SET_CHUNK_DEST(emp, dest);
536 }
537 mss = fp->sf_pmss;
538
539 /*
540 * If the current output packet cannot include the new error chunk,
541 * send out the current packet and then add the new error chunk
542 * to the new output packet.
543 */
544 if (sctp->sctp_err_len + emp_len > mss) {
545 if ((sendmp = sctp_make_mp(sctp, fp, 0)) == NULL) {
546 SCTP_KSTAT(sctps, sctp_send_err_failed);
547 /* Just free the latest error chunk. */
548 freeb(emp);
549 return;
550 }
551 sendmp->b_cont = sctp->sctp_err_chunks;
552 sctp_set_iplen(sctp, sendmp, fp->sf_ixa);
553 (void) conn_ip_output(sendmp, fp->sf_ixa);
554 BUMP_LOCAL(sctp->sctp_opkts);
555
556 sctp->sctp_err_chunks = emp;
557 sctp->sctp_err_len = emp_len;
558 SCTP_SET_CHUNK_DEST(emp, dest);
559 } else {
560 if (sctp->sctp_err_chunks != NULL)
561 linkb(sctp->sctp_err_chunks, emp);
562 else
563 sctp->sctp_err_chunks = emp;
564 sctp->sctp_err_len += emp_len;
565 }
566 /* Assume that we will send it out... */
567 BUMP_LOCAL(sctp->sctp_obchunks);
568 }
569
570 /*
571 * Called from sctp_input_data() to send out error chunks created during
572 * the processing of all the chunks in an incoming packet.
573 */
574 void
sctp_process_err(sctp_t * sctp)575 sctp_process_err(sctp_t *sctp)
576 {
577 sctp_stack_t *sctps = sctp->sctp_sctps;
578 mblk_t *errmp;
579 mblk_t *sendmp;
580 sctp_faddr_t *fp;
581
582 ASSERT(sctp->sctp_err_chunks != NULL);
583 errmp = sctp->sctp_err_chunks;
584 fp = SCTP_CHUNK_DEST(errmp);
585 if ((sendmp = sctp_make_mp(sctp, fp, 0)) == NULL) {
586 SCTP_KSTAT(sctps, sctp_send_err_failed);
587 freemsg(errmp);
588 goto done;
589 }
590 sendmp->b_cont = errmp;
591 sctp_set_iplen(sctp, sendmp, fp->sf_ixa);
592 (void) conn_ip_output(sendmp, fp->sf_ixa);
593 BUMP_LOCAL(sctp->sctp_opkts);
594 done:
595 sctp->sctp_err_chunks = NULL;
596 sctp->sctp_err_len = 0;
597 }
598
599 /*
600 * Returns 0 on non-fatal error, otherwise a system error on fatal
601 * error.
602 */
603 int
sctp_handle_error(sctp_t * sctp,sctp_hdr_t * sctph,sctp_chunk_hdr_t * ch,mblk_t * mp,ip_recv_attr_t * ira)604 sctp_handle_error(sctp_t *sctp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ch,
605 mblk_t *mp, ip_recv_attr_t *ira)
606 {
607 sctp_parm_hdr_t *errh;
608 sctp_chunk_hdr_t *uch;
609
610 if (ch->sch_len == htons(sizeof (*ch))) {
611 /* no error cause given */
612 return (0);
613 }
614 errh = (sctp_parm_hdr_t *)(ch + 1);
615 sctp_error_event(sctp, ch, B_FALSE);
616
617 switch (errh->sph_type) {
618 /*
619 * Both BAD_SID and NO_USR_DATA errors
620 * indicate a serious bug in our stack,
621 * so complain and abort the association.
622 */
623 case SCTP_ERR_BAD_SID:
624 cmn_err(CE_WARN, "BUG! send to invalid SID");
625 sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0,
626 ira);
627 return (ECONNABORTED);
628 case SCTP_ERR_NO_USR_DATA:
629 cmn_err(CE_WARN, "BUG! no usr data");
630 sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0,
631 ira);
632 return (ECONNABORTED);
633 case SCTP_ERR_UNREC_CHUNK:
634 /* Pull out the unrecognized chunk type */
635 if (ntohs(errh->sph_len) < (sizeof (*errh) + sizeof (*uch))) {
636 /* Not enough to process */
637 return (0);
638 }
639 uch = (sctp_chunk_hdr_t *)(errh + 1);
640 if (uch->sch_id == CHUNK_ASCONF) {
641 /* Turn on ASCONF sending */
642 sctp->sctp_understands_asconf = B_FALSE;
643 /*
644 * Hand off to asconf to clear out the unacked
645 * asconf chunk.
646 */
647 if (ntohs(uch->sch_len) !=
648 (ntohs(errh->sph_len) - sizeof (*errh))) {
649 /* malformed */
650 dprint(0, ("Malformed Unrec Chunk error\n"));
651 return (0);
652 }
653 sctp_asconf_free_cxmit(sctp, uch);
654 return (0);
655 }
656 /* Else drop it */
657 break;
658 default:
659 break;
660 }
661
662 return (0);
663 }
664