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]
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
26 #include <sys/systm.h>
27 #include <sys/stream.h>
28 #include <sys/cmn_err.h>
29 #include <sys/tihdr.h>
31 #define _SUN_TPI_VERSION 2
32 #include <sys/tihdr.h>
33 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/sctp.h>
38 #include <inet/common.h>
39 #include <inet/ipclassifier.h>
42 #include <inet/sctp/sctp_impl.h>
46 sctp_notify(sctp_t
*sctp
, mblk_t
*emp
, size_t len
)
48 struct T_unitdata_ind
*tudi
;
53 conn_t
*connp
= sctp
->sctp_connp
;
55 if ((mp
= allocb(sizeof (*tudi
) + sizeof (void *) +
56 sizeof (struct sockaddr_in6
), BPRI_HI
)) == NULL
) {
57 /* XXX trouble: don't want to drop events. should queue it. */
61 dprint(3, ("sctp_notify: event %d\n", (*(uint16_t *)emp
->b_rptr
)));
63 mp
->b_datap
->db_type
= M_PROTO
;
64 mp
->b_flag
|= MSGMARK
;
65 mp
->b_rptr
+= sizeof (void *); /* pointer worth of padding */
67 tudi
= (struct T_unitdata_ind
*)mp
->b_rptr
;
68 tudi
->PRIM_type
= T_UNITDATA_IND
;
69 tudi
->SRC_offset
= sizeof (*tudi
);
73 fp
= sctp
->sctp_primary
;
77 * Fill in primary remote address.
79 if (IN6_IS_ADDR_V4MAPPED(&fp
->sf_faddr
)) {
80 struct sockaddr_in
*sin4
;
82 tudi
->SRC_length
= sizeof (*sin4
);
83 sin4
= (struct sockaddr_in
*)(tudi
+ 1);
84 sin4
->sin_family
= AF_INET
;
85 sin4
->sin_port
= connp
->conn_fport
;
86 IN6_V4MAPPED_TO_IPADDR(&fp
->sf_faddr
, sin4
->sin_addr
.s_addr
);
87 mp
->b_wptr
= (uchar_t
*)(sin4
+ 1);
89 struct sockaddr_in6
*sin6
;
91 tudi
->SRC_length
= sizeof (*sin6
);
92 sin6
= (struct sockaddr_in6
*)(tudi
+ 1);
93 sin6
->sin6_family
= AF_INET6
;
94 sin6
->sin6_port
= connp
->conn_fport
;
95 sin6
->sin6_addr
= fp
->sf_faddr
;
96 mp
->b_wptr
= (uchar_t
*)(sin6
+ 1);
102 * Notifications are queued regardless of socket rx space. So
103 * we do not decrement sctp_rwnd here as this will confuse the
107 for (emp
= mp
->b_cont
; emp
; emp
= emp
->b_cont
) {
108 rwnd
+= emp
->b_wptr
- emp
->b_rptr
;
114 * Override b_flag for SCTP sockfs internal use
116 mp
->b_flag
= (short)SCTP_NOTIFICATION
;
118 rwnd
= sctp
->sctp_ulp_recv(sctp
->sctp_ulpd
, mp
, msgdsize(mp
), 0,
120 if (rwnd
> sctp
->sctp_rwnd
) {
121 sctp
->sctp_rwnd
= rwnd
;
126 sctp_assoc_event(sctp_t
*sctp
, uint16_t state
, uint16_t error
,
127 sctp_chunk_hdr_t
*ch
)
129 struct sctp_assoc_change
*sacp
;
133 if (!sctp
->sctp_recvassocevnt
) {
137 ch_len
= (ch
!= NULL
) ? ntohs(ch
->sch_len
) : 0;
139 if ((mp
= allocb(sizeof (*sacp
) + ch_len
, BPRI_MED
)) == NULL
) {
143 sacp
= (struct sctp_assoc_change
*)mp
->b_rptr
;
144 sacp
->sac_type
= SCTP_ASSOC_CHANGE
;
145 sacp
->sac_flags
= sctp
->sctp_prsctp_aware
? SCTP_PRSCTP_CAPABLE
: 0;
146 sacp
->sac_length
= sizeof (*sacp
) + ch_len
;
147 sacp
->sac_state
= state
;
148 sacp
->sac_error
= error
;
149 sacp
->sac_outbound_streams
= sctp
->sctp_num_ostr
;
150 sacp
->sac_inbound_streams
= sctp
->sctp_num_istr
;
151 sacp
->sac_assoc_id
= 0;
154 bcopy(ch
, sacp
+ 1, ch_len
);
155 mp
->b_wptr
+= sacp
->sac_length
;
156 sctp_notify(sctp
, mp
, sacp
->sac_length
);
160 * Send failure event. Message is expected to have message header still
161 * in place, data follows in subsequent mblk's.
164 sctp_sendfail(sctp_t
*sctp
, mblk_t
*msghdr
, uint16_t flags
, int error
)
166 struct sctp_send_failed
*sfp
;
170 /* Allocate a mblk for the notification header */
171 if ((mp
= allocb(sizeof (*sfp
), BPRI_MED
)) == NULL
) {
177 smh
= (sctp_msg_hdr_t
*)msghdr
->b_rptr
;
178 sfp
= (struct sctp_send_failed
*)mp
->b_rptr
;
179 sfp
->ssf_type
= SCTP_SEND_FAILED
;
180 sfp
->ssf_flags
= flags
;
181 sfp
->ssf_length
= smh
->smh_msglen
+ sizeof (*sfp
);
182 sfp
->ssf_error
= error
;
183 sfp
->ssf_assoc_id
= 0;
185 bzero(&sfp
->ssf_info
, sizeof (sfp
->ssf_info
));
186 sfp
->ssf_info
.sinfo_stream
= smh
->smh_sid
;
187 sfp
->ssf_info
.sinfo_flags
= smh
->smh_flags
;
188 sfp
->ssf_info
.sinfo_ppid
= smh
->smh_ppid
;
189 sfp
->ssf_info
.sinfo_context
= smh
->smh_context
;
190 sfp
->ssf_info
.sinfo_timetolive
= TICK_TO_MSEC(smh
->smh_ttl
);
192 mp
->b_wptr
= (uchar_t
*)(sfp
+ 1);
193 mp
->b_cont
= msghdr
->b_cont
;
197 sctp_notify(sctp
, mp
, sfp
->ssf_length
);
202 * Send failure when the message has been fully chunkified.
205 sctp_sendfail_sent(sctp_t
*sctp
, mblk_t
*meta
, int error
)
210 uint16_t flags
= SCTP_DATA_SENT
;
212 if (!sctp
->sctp_recvsendfailevnt
) {
218 * We need to remove all data_hdr's.
227 * If one of the chunks hasn't been sent yet, say that
228 * the message hasn't been sent.
230 if (!SCTP_CHUNK_ISSENT(nmp
)) {
231 flags
= SCTP_DATA_UNSENT
;
233 nmp
->b_rptr
+= sizeof (sctp_data_hdr_t
);
234 if (nmp
->b_rptr
== nmp
->b_wptr
) {
235 tail
->b_cont
= nmp
->b_cont
;
240 while (tail
->b_cont
) {
243 } while ((nmp
= mp
) != NULL
);
245 sctp_sendfail(sctp
, meta
, flags
, error
);
249 * Send failure when the message hasn't been fully chunkified.
252 sctp_sendfail_event(sctp_t
*sctp
, mblk_t
*meta
, int error
, boolean_t chunkified
)
261 if (!sctp
->sctp_recvsendfailevnt
) {
266 /* If the message is fully chunkified */
268 sctp_sendfail_sent(sctp
, meta
, error
);
272 * Message might be partially chunkified, we need to remove
277 while ((nmp
= mp
->b_next
) != NULL
) {
278 mp
->b_next
= nmp
->b_next
;
280 nmp
->b_rptr
+= sizeof (sctp_data_hdr_t
);
281 if (nmp
->b_rptr
== nmp
->b_wptr
) {
282 tail
->b_cont
= nmp
->b_cont
;
287 while (tail
->b_cont
) {
293 sctp_sendfail(sctp
, meta
, SCTP_DATA_UNSENT
, error
);
297 sctp_regift_xmitlist(sctp_t
*sctp
)
301 if (!sctp
->sctp_recvsendfailevnt
) {
305 while ((mp
= sctp
->sctp_xmit_head
) != NULL
) {
306 sctp
->sctp_xmit_head
= mp
->b_next
;
308 if (sctp
->sctp_xmit_head
!= NULL
)
309 sctp
->sctp_xmit_head
->b_prev
= NULL
;
310 sctp_sendfail_event(sctp
, mp
, 0, B_TRUE
);
312 while ((mp
= sctp
->sctp_xmit_unsent
) != NULL
) {
313 sctp
->sctp_xmit_unsent
= mp
->b_next
;
315 sctp_sendfail_event(sctp
, mp
, 0, B_FALSE
);
317 sctp
->sctp_xmit_tail
= sctp
->sctp_xmit_unsent_tail
= NULL
;
318 sctp
->sctp_unacked
= sctp
->sctp_unsent
= 0;
322 sctp_intf_event(sctp_t
*sctp
, in6_addr_t addr
, int state
, int error
)
324 struct sctp_paddr_change
*spc
;
326 struct sockaddr_in
*sin
;
327 struct sockaddr_in6
*sin6
;
330 if (!sctp
->sctp_recvpathevnt
) {
334 if ((mp
= allocb(sizeof (*spc
), BPRI_MED
)) == NULL
) {
338 spc
= (struct sctp_paddr_change
*)mp
->b_rptr
;
339 spc
->spc_type
= SCTP_PEER_ADDR_CHANGE
;
341 spc
->spc_length
= sizeof (*spc
);
342 if (IN6_IS_ADDR_V4MAPPED(&addr
)) {
343 IN6_V4MAPPED_TO_IPADDR(&addr
, addr4
);
344 sin
= (struct sockaddr_in
*)&spc
->spc_aaddr
;
345 sin
->sin_family
= AF_INET
;
347 sin
->sin_addr
.s_addr
= addr4
;
349 sin6
= (struct sockaddr_in6
*)&spc
->spc_aaddr
;
350 sin6
->sin6_family
= AF_INET6
;
352 sin6
->sin6_addr
= addr
;
354 spc
->spc_state
= state
;
355 spc
->spc_error
= error
;
356 spc
->spc_assoc_id
= 0;
358 mp
->b_wptr
= (uchar_t
*)(spc
+ 1);
359 sctp_notify(sctp
, mp
, spc
->spc_length
);
363 sctp_error_event(sctp_t
*sctp
, sctp_chunk_hdr_t
*ch
, boolean_t is_asconf
)
365 struct sctp_remote_error
*sre
;
368 sctp_parm_hdr_t
*errh
= NULL
;
373 if (!sctp
->sctp_recvpeererr
) {
378 * ASCONF PARM error chunks :
379 * PARM_ERROR_IND parm type is always followed by correlation id.
380 * See sctp_asconf_adderr() and sctp_asconf_prepend_errwrap() as to
381 * how these error chunks are build.
382 * error cause wrapper (PARM_ERROR_IND) + correlation id +
383 * error cause + error cause details.
385 * Regular error chunks :
386 * See sctp_make_err() as to how these error chunks are build.
387 * error chunk header (CHUNK_ERROR) + error cause + error cause details.
390 if (ntohs(ch
->sch_len
) >
391 (sizeof (*ch
) + sizeof (uint32_t))) {
392 errh
= (sctp_parm_hdr_t
*)((char *)ch
+
393 sizeof (uint32_t) + sizeof (sctp_parm_hdr_t
));
396 if (ntohs(ch
->sch_len
) > sizeof (*ch
)) {
397 errh
= (sctp_parm_hdr_t
*)(ch
+ 1);
402 error
= ntohs(errh
->sph_type
);
403 dlen
= ntohs(errh
->sph_len
) - sizeof (*errh
);
409 len
= sizeof (*sre
) + dlen
;
410 if ((mp
= allocb(len
, BPRI_MED
)) == NULL
) {
414 sre
= (struct sctp_remote_error
*)mp
->b_rptr
;
415 sre
->sre_type
= SCTP_REMOTE_ERROR
;
417 sre
->sre_length
= len
;
418 sre
->sre_assoc_id
= 0;
419 sre
->sre_error
= error
;
421 bcopy(dtail
, sre
+ 1, dlen
);
424 mp
->b_wptr
= mp
->b_rptr
+ len
;
425 sctp_notify(sctp
, mp
, len
);
429 sctp_shutdown_event(sctp_t
*sctp
)
431 struct sctp_shutdown_event
*sse
;
434 if (!sctp
->sctp_recvshutdownevnt
) {
438 if ((mp
= allocb(sizeof (*sse
), BPRI_MED
)) == NULL
) {
442 sse
= (struct sctp_shutdown_event
*)mp
->b_rptr
;
443 sse
->sse_type
= SCTP_SHUTDOWN_EVENT
;
445 sse
->sse_length
= sizeof (*sse
);
446 sse
->sse_assoc_id
= 0;
448 mp
->b_wptr
= (uchar_t
*)(sse
+ 1);
449 sctp_notify(sctp
, mp
, sse
->sse_length
);
453 sctp_adaptation_event(sctp_t
*sctp
)
455 struct sctp_adaptation_event
*sai
;
458 if (!sctp
->sctp_recvalevnt
|| !sctp
->sctp_recv_adaptation
) {
461 if ((mp
= allocb(sizeof (*sai
), BPRI_MED
)) == NULL
) {
465 sai
= (struct sctp_adaptation_event
*)mp
->b_rptr
;
466 sai
->sai_type
= SCTP_ADAPTATION_INDICATION
;
468 sai
->sai_length
= sizeof (*sai
);
469 sai
->sai_assoc_id
= 0;
471 * Adaptation code delivered in network byte order.
473 sai
->sai_adaptation_ind
= sctp
->sctp_rx_adaptation_code
;
475 mp
->b_wptr
= (uchar_t
*)(sai
+ 1);
476 sctp_notify(sctp
, mp
, sai
->sai_length
);
478 sctp
->sctp_recv_adaptation
= 0; /* in case there's a restart later */
481 /* Send partial deliver event */
483 sctp_partial_delivery_event(sctp_t
*sctp
)
485 struct sctp_pdapi_event
*pdapi
;
488 if (!sctp
->sctp_recvpdevnt
)
491 if ((mp
= allocb(sizeof (*pdapi
), BPRI_MED
)) == NULL
)
494 pdapi
= (struct sctp_pdapi_event
*)mp
->b_rptr
;
495 pdapi
->pdapi_type
= SCTP_PARTIAL_DELIVERY_EVENT
;
496 pdapi
->pdapi_flags
= 0;
497 pdapi
->pdapi_length
= sizeof (*pdapi
);
498 pdapi
->pdapi_indication
= SCTP_PARTIAL_DELIVERY_ABORTED
;
499 pdapi
->pdapi_assoc_id
= 0;
500 mp
->b_wptr
= (uchar_t
*)(pdapi
+ 1);
501 sctp_notify(sctp
, mp
, pdapi
->pdapi_length
);