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.
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.
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]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <sys/systm.h>
28 #include <sys/stream.h>
29 #include <sys/cmn_err.h>
31 #include <sys/strsubr.h>
33 #include <netinet/in.h>
34 #include <netinet/ip6.h>
36 #include <inet/ipsec_impl.h>
37 #include <inet/common.h>
40 #include <inet/ipsec_impl.h>
41 #include <inet/mib2.h>
42 #include <inet/sctp_ip.h>
43 #include <inet/ipclassifier.h>
44 #include <inet/ip_ire.h>
45 #include <inet/sctp/sctp_impl.h>
46 #include <inet/sctp/sctp_asconf.h>
49 sctp_link_abort(mblk_t
*mp
, uint16_t serror
, char *details
, size_t len
,
50 int iserror
, boolean_t tbit
)
54 sctp_chunk_hdr_t
*acp
;
57 ASSERT(mp
!= NULL
&& mp
->b_cont
== NULL
);
59 alen
= sizeof (*acp
) + (serror
!= 0 ? (sizeof (*eph
) + len
) : 0);
61 amp
= allocb(alen
, BPRI_MED
);
66 amp
->b_wptr
= amp
->b_rptr
+ alen
;
69 acp
= (sctp_chunk_hdr_t
*)amp
->b_rptr
;
70 acp
->sch_id
= iserror
? CHUNK_ERROR
: CHUNK_ABORT
;
72 acp
->sch_len
= htons(alen
);
82 eph
= (sctp_parm_hdr_t
*)(acp
+ 1);
83 eph
->sph_type
= htons(serror
);
84 eph
->sph_len
= htons(len
+ sizeof (*eph
));
87 bcopy(details
, eph
+ 1, len
);
96 sctp_user_abort(sctp_t
*sctp
, mblk_t
*data
)
101 sctp_faddr_t
*fp
= sctp
->sctp_current
;
102 ip_xmit_attr_t
*ixa
= fp
->sf_ixa
;
103 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
106 * Don't need notification if connection is not yet setup,
107 * call sctp_clean_death() to reclaim resources.
108 * Any pending connect call(s) will error out.
110 if (sctp
->sctp_state
< SCTPS_COOKIE_WAIT
) {
111 sctp_clean_death(sctp
, ECONNABORTED
);
115 mp
= sctp_make_mp(sctp
, fp
, 0);
117 SCTP_KSTAT(sctps
, sctp_send_user_abort_failed
);
122 * Create abort chunk.
126 hdrlen
= sctp
->sctp_hdr_len
;
128 hdrlen
= sctp
->sctp_hdr6_len
;
130 hdrlen
+= sizeof (sctp_chunk_hdr_t
) + sizeof (sctp_parm_hdr_t
);
131 cause
= (char *)data
->b_rptr
;
132 len
= data
->b_wptr
- data
->b_rptr
;
134 if (len
+ hdrlen
> fp
->sf_pmss
) {
135 len
= fp
->sf_pmss
- hdrlen
;
142 * Since it is a user abort, we should have the sctp_t and hence
143 * the correct verification tag. So we should not set the T-bit
146 if ((len
= sctp_link_abort(mp
, SCTP_ERR_USER_ABORT
, cause
, len
, 0,
151 SCTPS_BUMP_MIB(sctps
, sctpAborted
);
152 BUMP_LOCAL(sctp
->sctp_opkts
);
153 BUMP_LOCAL(sctp
->sctp_obchunks
);
155 sctp_set_iplen(sctp
, mp
, ixa
);
156 ASSERT(ixa
->ixa_ire
!= NULL
);
157 ASSERT(ixa
->ixa_cred
!= NULL
);
159 (void) conn_ip_output(mp
, ixa
);
161 sctp_assoc_event(sctp
, SCTP_COMM_LOST
, 0, NULL
);
162 sctp_clean_death(sctp
, ECONNABORTED
);
166 * If iserror == 0, sends an abort. If iserror != 0, sends an error.
169 sctp_send_abort(sctp_t
*sctp
, uint32_t vtag
, uint16_t serror
, char *details
,
170 size_t len
, mblk_t
*inmp
, int iserror
, boolean_t tbit
, ip_recv_attr_t
*ira
)
176 ipha_t
*ahiph
= NULL
;
178 ip6_t
*ahip6h
= NULL
;
185 conn_t
*connp
= sctp
->sctp_connp
;
186 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
189 isv4
= (IPH_HDR_VERSION(inmp
->b_rptr
) == IPV4_VERSION
);
191 ahlen
= sctp
->sctp_hdr_len
;
193 ahlen
= sctp
->sctp_hdr6_len
;
196 hmp
= allocb(sctps
->sctps_wroff_xtra
+ ahlen
, BPRI_MED
);
198 /* XXX no resources */
202 /* copy in the IP / SCTP header */
203 p
= hmp
->b_rptr
+ sctps
->sctps_wroff_xtra
;
205 hmp
->b_wptr
= p
+ ahlen
;
207 bcopy(sctp
->sctp_iphc
, p
, sctp
->sctp_hdr_len
);
209 * Composite is likely incomplete at this point, so pull
210 * info from the incoming IP / SCTP headers.
213 iniph
= (ipha_t
*)inmp
->b_rptr
;
214 ip_hdr_len
= IPH_HDR_LENGTH(inmp
->b_rptr
);
216 sh
= (sctp_hdr_t
*)(p
+ sctp
->sctp_ip_hdr_len
);
217 ASSERT(OK_32PTR(sh
));
219 insh
= (sctp_hdr_t
*)((uchar_t
*)iniph
+ ip_hdr_len
);
220 ASSERT(OK_32PTR(insh
));
222 /* Copy in the peer's IP addr */
223 ahiph
->ipha_dst
= iniph
->ipha_src
;
224 ahiph
->ipha_src
= iniph
->ipha_dst
;
226 bcopy(sctp
->sctp_iphc6
, p
, sctp
->sctp_hdr6_len
);
228 inip6h
= (ip6_t
*)inmp
->b_rptr
;
229 ip_hdr_len
= ip_hdr_length_v6(inmp
, inip6h
);
231 sh
= (sctp_hdr_t
*)(p
+ sctp
->sctp_ip_hdr6_len
);
232 ASSERT(OK_32PTR(sh
));
234 insh
= (sctp_hdr_t
*)((uchar_t
*)inip6h
+ ip_hdr_len
);
235 ASSERT(OK_32PTR(insh
));
237 /* Copy in the peer's IP addr */
238 ahip6h
->ip6_dst
= inip6h
->ip6_src
;
239 ahip6h
->ip6_src
= inip6h
->ip6_dst
;
242 /* Fill in the holes in the SCTP common header */
243 sh
->sh_sport
= insh
->sh_dport
;
244 sh
->sh_dport
= insh
->sh_sport
;
247 /* Link in the abort chunk */
248 if ((alen
= sctp_link_abort(hmp
, serror
, details
, len
, iserror
, tbit
))
255 * Base the transmission on any routing-related socket options
256 * that have been set on the listener/connection.
258 ixa
= conn_get_ixa_exclusive(connp
);
263 ixa
->ixa_flags
&= ~IXAF_VERIFY_PMTU
;
265 ixa
->ixa_pktlen
= ahlen
+ alen
;
267 ixa
->ixa_flags
|= IXAF_IS_IPV4
;
268 ahiph
->ipha_length
= htons(ixa
->ixa_pktlen
);
269 ixa
->ixa_ip_hdr_length
= sctp
->sctp_ip_hdr_len
;
271 ixa
->ixa_flags
&= ~IXAF_IS_IPV4
;
272 ahip6h
->ip6_plen
= htons(ixa
->ixa_pktlen
- IPV6_HDR_LEN
);
273 ixa
->ixa_ip_hdr_length
= sctp
->sctp_ip_hdr6_len
;
276 SCTPS_BUMP_MIB(sctps
, sctpAborted
);
277 BUMP_LOCAL(sctp
->sctp_obchunks
);
279 if (ira
->ira_flags
& IRAF_IPSEC_SECURE
) {
281 * Apply IPsec based on how IPsec was applied to
282 * the packet that caused the abort.
284 if (!ipsec_in_to_out(ira
, ixa
, hmp
, ahiph
, ahip6h
)) {
285 ip_stack_t
*ipst
= sctps
->sctps_netstack
->netstack_ip
;
287 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutDiscards
);
288 /* Note: mp already consumed and ip_drop_packet done */
293 ixa
->ixa_flags
|= IXAF_NO_IPSEC
;
296 BUMP_LOCAL(sctp
->sctp_opkts
);
297 BUMP_LOCAL(sctp
->sctp_obchunks
);
299 (void) ip_output_simple(hmp
, ixa
);
304 * OOTB version of the above.
305 * If iserror == 0, sends an abort. If iserror != 0, sends an error.
308 sctp_ootb_send_abort(uint32_t vtag
, uint16_t serror
, char *details
,
309 size_t len
, const mblk_t
*inmp
, int iserror
, boolean_t tbit
,
310 ip_recv_attr_t
*ira
, ip_stack_t
*ipst
)
322 netstack_t
*ns
= ipst
->ips_netstack
;
323 sctp_stack_t
*sctps
= ns
->netstack_sctp
;
326 bzero(&ixas
, sizeof (ixas
));
328 isv4
= (IPH_HDR_VERSION(inmp
->b_rptr
) == IPV4_VERSION
);
329 ip_hdr_len
= ira
->ira_ip_hdr_length
;
330 ahlen
= ip_hdr_len
+ sizeof (sctp_hdr_t
);
332 mp
= allocb(ahlen
+ sctps
->sctps_wroff_xtra
, BPRI_MED
);
336 mp
->b_rptr
+= sctps
->sctps_wroff_xtra
;
337 mp
->b_wptr
= mp
->b_rptr
+ ahlen
;
338 bcopy(inmp
->b_rptr
, mp
->b_rptr
, ahlen
);
341 * We follow the logic in tcp_xmit_early_reset() in that we skip
342 * reversing source route (i.e. replace all IP options with EOL).
347 ipha
= (ipha_t
*)mp
->b_rptr
;
348 for (i
= IP_SIMPLE_HDR_LENGTH
; i
< (int)ip_hdr_len
; i
++)
349 mp
->b_rptr
[i
] = IPOPT_EOL
;
351 ipha
->ipha_length
= htons(ahlen
);
352 v4addr
= ipha
->ipha_src
;
353 ipha
->ipha_src
= ipha
->ipha_dst
;
354 ipha
->ipha_dst
= v4addr
;
355 ipha
->ipha_ident
= 0;
356 ipha
->ipha_ttl
= (uchar_t
)sctps
->sctps_ipv4_ttl
;
358 ixas
.ixa_flags
= IXAF_BASIC_SIMPLE_V4
;
362 ip6h
= (ip6_t
*)mp
->b_rptr
;
363 /* Remove any extension headers assuming partial overlay */
364 if (ip_hdr_len
> IPV6_HDR_LEN
) {
367 to
= mp
->b_rptr
+ ip_hdr_len
- IPV6_HDR_LEN
;
368 ovbcopy(ip6h
, to
, IPV6_HDR_LEN
);
369 mp
->b_rptr
+= ip_hdr_len
- IPV6_HDR_LEN
;
370 ip_hdr_len
= IPV6_HDR_LEN
;
371 ip6h
= (ip6_t
*)mp
->b_rptr
;
372 ip6h
->ip6_nxt
= IPPROTO_SCTP
;
373 ahlen
= ip_hdr_len
+ sizeof (sctp_hdr_t
);
375 ip6h
->ip6_plen
= htons(ahlen
- IPV6_HDR_LEN
);
376 v6addr
= ip6h
->ip6_src
;
377 ip6h
->ip6_src
= ip6h
->ip6_dst
;
378 ip6h
->ip6_dst
= v6addr
;
379 ip6h
->ip6_hops
= (uchar_t
)sctps
->sctps_ipv6_hoplimit
;
381 ixas
.ixa_flags
= IXAF_BASIC_SIMPLE_V6
;
382 if (IN6_IS_ADDR_LINKSCOPE(&ip6h
->ip6_dst
)) {
383 ixas
.ixa_flags
|= IXAF_SCOPEID_SET
;
384 ixas
.ixa_scopeid
= ira
->ira_ruifindex
;
387 insctph
= (sctp_hdr_t
*)(mp
->b_rptr
+ ip_hdr_len
);
389 /* Swap ports. Verification tag is reused. */
390 port
= insctph
->sh_sport
;
391 insctph
->sh_sport
= insctph
->sh_dport
;
392 insctph
->sh_dport
= port
;
393 insctph
->sh_verf
= vtag
;
395 /* Link in the abort chunk */
396 if ((alen
= sctp_link_abort(mp
, serror
, details
, len
, iserror
, tbit
))
402 ixas
.ixa_pktlen
= ahlen
+ alen
;
403 ixas
.ixa_ip_hdr_length
= ip_hdr_len
;
406 ipha
->ipha_length
= htons(ixas
.ixa_pktlen
);
408 ip6h
->ip6_plen
= htons(ixas
.ixa_pktlen
- IPV6_HDR_LEN
);
411 ixas
.ixa_protocol
= IPPROTO_SCTP
;
412 ixas
.ixa_zoneid
= ira
->ira_zoneid
;
413 ixas
.ixa_ipst
= ipst
;
414 ixas
.ixa_ifindex
= 0;
416 SCTPS_BUMP_MIB(sctps
, sctpAborted
);
418 if (ira
->ira_flags
& IRAF_IPSEC_SECURE
) {
420 * Apply IPsec based on how IPsec was applied to
421 * the packet that was out of the blue.
423 if (!ipsec_in_to_out(ira
, &ixas
, mp
, ipha
, ip6h
)) {
424 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutDiscards
);
425 /* Note: mp already consumed and ip_drop_packet done */
430 * This is in clear. The abort message we are building
431 * here should go out in clear, independent of our policy.
433 ixas
.ixa_flags
|= IXAF_NO_IPSEC
;
436 (void) ip_output_simple(mp
, &ixas
);
442 sctp_make_err(sctp_t
*sctp
, uint16_t serror
, void *details
, size_t len
)
447 sctp_chunk_hdr_t
*ecp
;
448 sctp_parm_hdr_t
*eph
;
451 if ((pad
= len
% SCTP_ALIGN
) != 0) {
452 pad
= SCTP_ALIGN
- pad
;
455 elen
= sizeof (*ecp
) + sizeof (*eph
) + len
;
456 emp
= allocb(elen
+ pad
, BPRI_MED
);
461 emp
->b_wptr
= emp
->b_rptr
+ elen
+ pad
;
464 ecp
= (sctp_chunk_hdr_t
*)emp
->b_rptr
;
465 ecp
->sch_id
= CHUNK_ERROR
;
467 ecp
->sch_len
= htons(elen
);
469 eph
= (sctp_parm_hdr_t
*)(ecp
+ 1);
470 eph
->sph_type
= htons(serror
);
471 eph
->sph_len
= htons(len
+ sizeof (*eph
));
474 bcopy(details
, eph
+ 1, len
);
478 bzero((uchar_t
*)(eph
+ 1) + len
, pad
);
485 * Called from sctp_input_data() to add one error chunk to the error
486 * chunks list. The error chunks list will be processed at the end
487 * of sctp_input_data() by calling sctp_process_err().
490 sctp_add_err(sctp_t
*sctp
, uint16_t serror
, void *details
, size_t len
,
493 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
500 emp
= sctp_make_err(sctp
, serror
, details
, len
);
503 emp_len
= MBLKL(emp
);
504 if (sctp
->sctp_err_chunks
!= NULL
) {
505 fp
= SCTP_CHUNK_DEST(sctp
->sctp_err_chunks
);
508 SCTP_SET_CHUNK_DEST(emp
, dest
);
513 * If the current output packet cannot include the new error chunk,
514 * send out the current packet and then add the new error chunk
515 * to the new output packet.
517 if (sctp
->sctp_err_len
+ emp_len
> mss
) {
518 if ((sendmp
= sctp_make_mp(sctp
, fp
, 0)) == NULL
) {
519 SCTP_KSTAT(sctps
, sctp_send_err_failed
);
520 /* Just free the latest error chunk. */
524 sendmp
->b_cont
= sctp
->sctp_err_chunks
;
525 sctp_set_iplen(sctp
, sendmp
, fp
->sf_ixa
);
526 (void) conn_ip_output(sendmp
, fp
->sf_ixa
);
527 BUMP_LOCAL(sctp
->sctp_opkts
);
529 sctp
->sctp_err_chunks
= emp
;
530 sctp
->sctp_err_len
= emp_len
;
531 SCTP_SET_CHUNK_DEST(emp
, dest
);
533 if (sctp
->sctp_err_chunks
!= NULL
)
534 linkb(sctp
->sctp_err_chunks
, emp
);
536 sctp
->sctp_err_chunks
= emp
;
537 sctp
->sctp_err_len
+= emp_len
;
539 /* Assume that we will send it out... */
540 BUMP_LOCAL(sctp
->sctp_obchunks
);
544 * Called from sctp_input_data() to send out error chunks created during
545 * the processing of all the chunks in an incoming packet.
548 sctp_process_err(sctp_t
*sctp
)
550 sctp_stack_t
*sctps
= sctp
->sctp_sctps
;
555 ASSERT(sctp
->sctp_err_chunks
!= NULL
);
556 errmp
= sctp
->sctp_err_chunks
;
557 fp
= SCTP_CHUNK_DEST(errmp
);
558 if ((sendmp
= sctp_make_mp(sctp
, fp
, 0)) == NULL
) {
559 SCTP_KSTAT(sctps
, sctp_send_err_failed
);
563 sendmp
->b_cont
= errmp
;
564 sctp_set_iplen(sctp
, sendmp
, fp
->sf_ixa
);
565 (void) conn_ip_output(sendmp
, fp
->sf_ixa
);
566 BUMP_LOCAL(sctp
->sctp_opkts
);
568 sctp
->sctp_err_chunks
= NULL
;
569 sctp
->sctp_err_len
= 0;
573 * Returns 0 on non-fatal error, otherwise a system error on fatal
577 sctp_handle_error(sctp_t
*sctp
, sctp_hdr_t
*sctph
, sctp_chunk_hdr_t
*ch
,
578 mblk_t
*mp
, ip_recv_attr_t
*ira
)
580 sctp_parm_hdr_t
*errh
;
581 sctp_chunk_hdr_t
*uch
;
583 if (ch
->sch_len
== htons(sizeof (*ch
))) {
584 /* no error cause given */
587 errh
= (sctp_parm_hdr_t
*)(ch
+ 1);
588 sctp_error_event(sctp
, ch
, B_FALSE
);
590 switch (errh
->sph_type
) {
592 * Both BAD_SID and NO_USR_DATA errors
593 * indicate a serious bug in our stack,
594 * so complain and abort the association.
596 case SCTP_ERR_BAD_SID
:
597 cmn_err(CE_WARN
, "BUG! send to invalid SID");
598 sctp_send_abort(sctp
, sctph
->sh_verf
, 0, NULL
, 0, mp
, 0, 0,
600 return (ECONNABORTED
);
601 case SCTP_ERR_NO_USR_DATA
:
602 cmn_err(CE_WARN
, "BUG! no usr data");
603 sctp_send_abort(sctp
, sctph
->sh_verf
, 0, NULL
, 0, mp
, 0, 0,
605 return (ECONNABORTED
);
606 case SCTP_ERR_UNREC_CHUNK
:
607 /* Pull out the unrecognized chunk type */
608 if (ntohs(errh
->sph_len
) < (sizeof (*errh
) + sizeof (*uch
))) {
609 /* Not enough to process */
612 uch
= (sctp_chunk_hdr_t
*)(errh
+ 1);
613 if (uch
->sch_id
== CHUNK_ASCONF
) {
614 /* Turn on ASCONF sending */
615 sctp
->sctp_understands_asconf
= B_FALSE
;
617 * Hand off to asconf to clear out the unacked
620 if (ntohs(uch
->sch_len
) !=
621 (ntohs(errh
->sph_len
) - sizeof (*errh
))) {
623 dprint(0, ("Malformed Unrec Chunk error\n"));
626 sctp_asconf_free_cxmit(sctp
, uch
);