1 /* $KAME: sctputil.c,v 1.36 2005/03/06 16:04:19 itojun Exp $ */
2 /* $DragonFly: src/sys/netinet/sctputil.c,v 1.8 2007/04/22 01:13:14 dillon Exp $ */
5 * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Cisco Systems, Inc.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #if !(defined(__OpenBSD__) || defined(__APPLE__))
37 #include "opt_ipsec.h"
39 #if defined(__FreeBSD__) || defined(__DragonFly__)
40 #include "opt_compat.h"
41 #include "opt_inet6.h"
43 #if !(defined(SCTP_BASE_FREEBSD) || defined(__DragonFly__))
44 #include "opt_mpath.h"
45 #endif /* SCTP_BASE_FREEBSD || __DragonFly__ */
47 #if defined(__NetBSD__)
52 #elif !defined(__OpenBSD__)
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/malloc.h>
60 #include <sys/domain.h>
61 #include <sys/protosw.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
65 #include <sys/kernel.h>
66 #include <sys/sysctl.h>
67 #include <sys/thread2.h>
69 #if defined(__FreeBSD__) || defined(__DragonFly__)
70 #include <sys/callout.h>
72 #include <netinet/sctp_callout.h> /* for callout_active() */
75 #include <net/radix.h>
76 #include <net/route.h>
80 #include <sys/domain.h>
84 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000)
85 #include <sys/limits.h>
87 #include <machine/limits.h>
91 #include <net/if_types.h>
92 #include <net/route.h>
94 #include <netinet/in.h>
95 #include <netinet/in_systm.h>
96 #include <netinet/ip.h>
97 #include <netinet/in_pcb.h>
98 #include <netinet/in_var.h>
99 #include <netinet/ip_var.h>
102 #include <netinet/ip6.h>
103 #include <netinet6/ip6_var.h>
105 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__DragonFly_)
106 #include <netinet6/in6_pcb.h>
107 #elif defined(__OpenBSD__)
108 #include <netinet/in_pcb.h>
113 #include <netinet/sctp_pcb.h>
117 #include <netinet6/ipsec.h>
118 #include <netproto/key/key.h>
124 #include <netinet/sctputil.h>
125 #include <netinet/sctp_var.h>
127 #include <netinet6/sctp6_var.h>
129 #include <netinet/sctp_header.h>
130 #include <netinet/sctp_output.h>
131 #include <netinet/sctp_hashdriver.h>
132 #include <netinet/sctp_uio.h>
133 #include <netinet/sctp_timer.h>
134 #include <netinet/sctp_crc32.h>
135 #include <netinet/sctp_indata.h> /* for sctp_deliver_data() */
136 #define NUMBER_OF_MTU_SIZES 18
139 extern u_int32_t sctp_debug_on
;
142 #ifdef SCTP_STAT_LOGGING
143 int sctp_cwnd_log_at
=0;
144 int sctp_cwnd_log_rolled
=0;
145 struct sctp_cwnd_log sctp_clog
[SCTP_STAT_LOG_SIZE
];
148 sctp_clr_stat_log(void)
151 sctp_cwnd_log_rolled
=0;
155 sctp_log_strm_del_alt(u_int32_t tsn
, u_int16_t sseq
, int from
)
158 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
159 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_STRM
;
160 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.n_tsn
= tsn
;
161 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.n_sseq
= sseq
;
162 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.e_tsn
= 0;
163 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.e_sseq
= 0;
165 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
166 sctp_cwnd_log_at
= 0;
167 sctp_cwnd_log_rolled
= 1;
174 sctp_log_map(uint32_t map
, uint32_t cum
, uint32_t high
, int from
)
177 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
178 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_MAP
;
179 sctp_clog
[sctp_cwnd_log_at
].x
.map
.base
= map
;
180 sctp_clog
[sctp_cwnd_log_at
].x
.map
.cum
= cum
;
181 sctp_clog
[sctp_cwnd_log_at
].x
.map
.high
= high
;
183 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
184 sctp_cwnd_log_at
= 0;
185 sctp_cwnd_log_rolled
= 1;
190 sctp_log_fr(uint32_t biggest_tsn
, uint32_t biggest_new_tsn
, uint32_t tsn
,
194 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
195 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_FR
;
196 sctp_clog
[sctp_cwnd_log_at
].x
.fr
.largest_tsn
= biggest_tsn
;
197 sctp_clog
[sctp_cwnd_log_at
].x
.fr
.largest_new_tsn
= biggest_new_tsn
;
198 sctp_clog
[sctp_cwnd_log_at
].x
.fr
.tsn
= tsn
;
200 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
201 sctp_cwnd_log_at
= 0;
202 sctp_cwnd_log_rolled
= 1;
207 sctp_log_strm_del(struct sctp_tmit_chunk
*chk
, struct sctp_tmit_chunk
*poschk
,
212 kprintf("Gak log of NULL?\n");
215 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
216 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_STRM
;
217 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.n_tsn
= chk
->rec
.data
.TSN_seq
;
218 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.n_sseq
= chk
->rec
.data
.stream_seq
;
219 if (poschk
!= NULL
) {
220 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.e_tsn
=
221 poschk
->rec
.data
.TSN_seq
;
222 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.e_sseq
=
223 poschk
->rec
.data
.stream_seq
;
225 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.e_tsn
= 0;
226 sctp_clog
[sctp_cwnd_log_at
].x
.strlog
.e_sseq
= 0;
229 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
230 sctp_cwnd_log_at
= 0;
231 sctp_cwnd_log_rolled
= 1;
236 sctp_log_cwnd(struct sctp_nets
*net
, int augment
, uint8_t from
)
239 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
240 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_CWND
;
241 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.net
= net
;
242 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.cwnd_new_value
= net
->cwnd
;
243 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.inflight
= net
->flight_size
;
244 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.cwnd_augment
= augment
;
246 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
247 sctp_cwnd_log_at
= 0;
248 sctp_cwnd_log_rolled
= 1;
253 sctp_log_maxburst(struct sctp_nets
*net
, int error
, int burst
, uint8_t from
)
255 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
256 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_MAXBURST
;
257 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.net
= net
;
258 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.cwnd_new_value
= error
;
259 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.inflight
= net
->flight_size
;
260 sctp_clog
[sctp_cwnd_log_at
].x
.cwnd
.cwnd_augment
= burst
;
262 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
263 sctp_cwnd_log_at
= 0;
264 sctp_cwnd_log_rolled
= 1;
269 sctp_log_rwnd(uint8_t from
, u_int32_t peers_rwnd
, u_int32_t snd_size
, u_int32_t overhead
)
271 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
272 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_RWND
;
273 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.rwnd
= peers_rwnd
;
274 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.send_size
= snd_size
;
275 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.overhead
= overhead
;
276 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.new_rwnd
= 0;
278 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
279 sctp_cwnd_log_at
= 0;
280 sctp_cwnd_log_rolled
= 1;
285 sctp_log_rwnd_set(uint8_t from
, u_int32_t peers_rwnd
, u_int32_t flight_size
, u_int32_t overhead
, u_int32_t a_rwndval
)
287 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
288 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_RWND
;
289 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.rwnd
= peers_rwnd
;
290 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.send_size
= flight_size
;
291 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.overhead
= overhead
;
292 sctp_clog
[sctp_cwnd_log_at
].x
.rwnd
.new_rwnd
= a_rwndval
;
294 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
295 sctp_cwnd_log_at
= 0;
296 sctp_cwnd_log_rolled
= 1;
301 sctp_log_mbcnt(uint8_t from
, u_int32_t total_oq
, u_int32_t book
, u_int32_t total_mbcnt_q
, u_int32_t mbcnt
)
303 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
304 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_MBCNT
;
305 sctp_clog
[sctp_cwnd_log_at
].x
.mbcnt
.total_queue_size
= total_oq
;
306 sctp_clog
[sctp_cwnd_log_at
].x
.mbcnt
.size_change
= book
;
307 sctp_clog
[sctp_cwnd_log_at
].x
.mbcnt
.total_queue_mb_size
= total_mbcnt_q
;
308 sctp_clog
[sctp_cwnd_log_at
].x
.mbcnt
.mbcnt_change
= mbcnt
;
310 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
311 sctp_cwnd_log_at
= 0;
312 sctp_cwnd_log_rolled
= 1;
317 sctp_log_block(uint8_t from
, struct socket
*so
, struct sctp_association
*asoc
)
320 sctp_clog
[sctp_cwnd_log_at
].from
= (u_int8_t
)from
;
321 sctp_clog
[sctp_cwnd_log_at
].event_type
= (u_int8_t
)SCTP_LOG_EVENT_BLOCK
;
322 sctp_clog
[sctp_cwnd_log_at
].x
.blk
.maxmb
= (u_int16_t
)(so
->so_snd
.ssb_mbmax
/1024);
323 sctp_clog
[sctp_cwnd_log_at
].x
.blk
.onmb
= asoc
->total_output_mbuf_queue_size
;
324 sctp_clog
[sctp_cwnd_log_at
].x
.blk
.maxsb
= (u_int16_t
)(so
->so_snd
.ssb_hiwat
/1024);
325 sctp_clog
[sctp_cwnd_log_at
].x
.blk
.onsb
= asoc
->total_output_queue_size
;
326 sctp_clog
[sctp_cwnd_log_at
].x
.blk
.send_sent_qcnt
= (u_int16_t
)(asoc
->send_queue_cnt
+ asoc
->sent_queue_cnt
);
327 sctp_clog
[sctp_cwnd_log_at
].x
.blk
.stream_qcnt
= (u_int16_t
)asoc
->stream_queue_cnt
;
329 if (sctp_cwnd_log_at
>= SCTP_STAT_LOG_SIZE
) {
330 sctp_cwnd_log_at
= 0;
331 sctp_cwnd_log_rolled
= 1;
336 sctp_fill_stat_log(struct mbuf
*m
)
338 struct sctp_cwnd_log_req
*req
;
339 int size_limit
, num
, i
, at
, cnt_out
=0;
344 size_limit
= (m
->m_len
- sizeof(struct sctp_cwnd_log_req
));
345 if (size_limit
< sizeof(struct sctp_cwnd_log
)) {
348 req
= mtod(m
, struct sctp_cwnd_log_req
*);
349 num
= size_limit
/sizeof(struct sctp_cwnd_log
);
350 if (sctp_cwnd_log_rolled
) {
351 req
->num_in_log
= SCTP_STAT_LOG_SIZE
;
353 req
->num_in_log
= sctp_cwnd_log_at
;
354 /* if the log has not rolled, we don't
355 * let you have old data.
357 if (req
->end_at
> sctp_cwnd_log_at
) {
358 req
->end_at
= sctp_cwnd_log_at
;
361 if ((num
< SCTP_STAT_LOG_SIZE
) &&
362 ((sctp_cwnd_log_rolled
) || (sctp_cwnd_log_at
> num
))) {
363 /* we can't return all of it */
364 if (((req
->start_at
== 0) && (req
->end_at
== 0)) ||
365 (req
->start_at
>= SCTP_STAT_LOG_SIZE
) ||
366 (req
->end_at
>= SCTP_STAT_LOG_SIZE
)) {
367 /* No user request or user is wacked. */
369 req
->end_at
= sctp_cwnd_log_at
- 1;
370 if ((sctp_cwnd_log_at
- num
) < 0) {
372 cc
= num
- sctp_cwnd_log_at
;
373 req
->start_at
= SCTP_STAT_LOG_SIZE
- cc
;
375 req
->start_at
= sctp_cwnd_log_at
- num
;
380 if (req
->start_at
> req
->end_at
) {
381 cc
= (SCTP_STAT_LOG_SIZE
- req
->start_at
) +
385 cc
= req
->end_at
- req
->start_at
;
393 /* We can return all of it */
395 req
->end_at
= sctp_cwnd_log_at
- 1;
396 req
->num_ret
= sctp_cwnd_log_at
;
398 for (i
= 0, at
= req
->start_at
; i
< req
->num_ret
; i
++) {
399 req
->log
[i
] = sctp_clog
[at
];
402 if (at
>= SCTP_STAT_LOG_SIZE
)
405 m
->m_len
= (cnt_out
* sizeof(struct sctp_cwnd_log_req
)) + sizeof(struct sctp_cwnd_log_req
);
411 #ifdef SCTP_AUDITING_ENABLED
412 u_int8_t sctp_audit_data
[SCTP_AUDIT_SIZE
][2];
413 static int sctp_audit_indx
= 0;
416 sctp_print_audit_report(void)
421 for (i
=sctp_audit_indx
;i
<SCTP_AUDIT_SIZE
;i
++) {
422 if ((sctp_audit_data
[i
][0] == 0xe0) &&
423 (sctp_audit_data
[i
][1] == 0x01)) {
426 } else if (sctp_audit_data
[i
][0] == 0xf0) {
429 } else if ((sctp_audit_data
[i
][0] == 0xc0) &&
430 (sctp_audit_data
[i
][1] == 0x01)) {
434 kprintf("%2.2x%2.2x ", (uint32_t)sctp_audit_data
[i
][0],
435 (uint32_t)sctp_audit_data
[i
][1]);
440 for (i
=0;i
<sctp_audit_indx
;i
++) {
441 if ((sctp_audit_data
[i
][0] == 0xe0) &&
442 (sctp_audit_data
[i
][1] == 0x01)) {
445 } else if (sctp_audit_data
[i
][0] == 0xf0) {
448 } else if ((sctp_audit_data
[i
][0] == 0xc0) &&
449 (sctp_audit_data
[i
][1] == 0x01)) {
453 kprintf("%2.2x%2.2x ", (uint32_t)sctp_audit_data
[i
][0],
454 (uint32_t)sctp_audit_data
[i
][1]);
463 sctp_auditing(int from
, struct sctp_inpcb
*inp
, struct sctp_tcb
*stcb
,
464 struct sctp_nets
*net
)
466 int resend_cnt
, tot_out
, rep
, tot_book_cnt
;
467 struct sctp_nets
*lnet
;
468 struct sctp_tmit_chunk
*chk
;
470 sctp_audit_data
[sctp_audit_indx
][0] = 0xAA;
471 sctp_audit_data
[sctp_audit_indx
][1] = 0x000000ff & from
;
473 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
477 sctp_audit_data
[sctp_audit_indx
][0] = 0xAF;
478 sctp_audit_data
[sctp_audit_indx
][1] = 0x01;
480 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
486 sctp_audit_data
[sctp_audit_indx
][0] = 0xAF;
487 sctp_audit_data
[sctp_audit_indx
][1] = 0x02;
489 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
494 sctp_audit_data
[sctp_audit_indx
][0] = 0xA1;
495 sctp_audit_data
[sctp_audit_indx
][1] =
496 (0x000000ff & stcb
->asoc
.sent_queue_retran_cnt
);
498 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
503 resend_cnt
= tot_out
= 0;
504 TAILQ_FOREACH(chk
, &stcb
->asoc
.sent_queue
, sctp_next
) {
505 if (chk
->sent
== SCTP_DATAGRAM_RESEND
) {
507 } else if (chk
->sent
< SCTP_DATAGRAM_RESEND
) {
508 tot_out
+= chk
->book_size
;
512 if (resend_cnt
!= stcb
->asoc
.sent_queue_retran_cnt
) {
513 sctp_audit_data
[sctp_audit_indx
][0] = 0xAF;
514 sctp_audit_data
[sctp_audit_indx
][1] = 0xA1;
516 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
519 kprintf("resend_cnt:%d asoc-tot:%d\n",
520 resend_cnt
, stcb
->asoc
.sent_queue_retran_cnt
);
522 stcb
->asoc
.sent_queue_retran_cnt
= resend_cnt
;
523 sctp_audit_data
[sctp_audit_indx
][0] = 0xA2;
524 sctp_audit_data
[sctp_audit_indx
][1] =
525 (0x000000ff & stcb
->asoc
.sent_queue_retran_cnt
);
527 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
531 if (tot_out
!= stcb
->asoc
.total_flight
) {
532 sctp_audit_data
[sctp_audit_indx
][0] = 0xAF;
533 sctp_audit_data
[sctp_audit_indx
][1] = 0xA2;
535 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
539 kprintf("tot_flt:%d asoc_tot:%d\n", tot_out
,
540 (int)stcb
->asoc
.total_flight
);
541 stcb
->asoc
.total_flight
= tot_out
;
543 if (tot_book_cnt
!= stcb
->asoc
.total_flight_count
) {
544 sctp_audit_data
[sctp_audit_indx
][0] = 0xAF;
545 sctp_audit_data
[sctp_audit_indx
][1] = 0xA5;
547 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
551 kprintf("tot_flt_book:%d\n", tot_book
);
553 stcb
->asoc
.total_flight_count
= tot_book_cnt
;
556 TAILQ_FOREACH(lnet
, &stcb
->asoc
.nets
, sctp_next
) {
557 tot_out
+= lnet
->flight_size
;
559 if (tot_out
!= stcb
->asoc
.total_flight
) {
560 sctp_audit_data
[sctp_audit_indx
][0] = 0xAF;
561 sctp_audit_data
[sctp_audit_indx
][1] = 0xA3;
563 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
567 kprintf("real flight:%d net total was %d\n",
568 stcb
->asoc
.total_flight
, tot_out
);
569 /* now corrective action */
570 TAILQ_FOREACH(lnet
, &stcb
->asoc
.nets
, sctp_next
) {
572 TAILQ_FOREACH(chk
, &stcb
->asoc
.sent_queue
, sctp_next
) {
573 if ((chk
->whoTo
== lnet
) &&
574 (chk
->sent
< SCTP_DATAGRAM_RESEND
)) {
575 tot_out
+= chk
->book_size
;
578 if (lnet
->flight_size
!= tot_out
) {
579 kprintf("net:%x flight was %d corrected to %d\n",
580 (uint32_t)lnet
, lnet
->flight_size
, tot_out
);
581 lnet
->flight_size
= tot_out
;
588 sctp_print_audit_report();
593 sctp_audit_log(u_int8_t ev
, u_int8_t fd
)
596 sctp_audit_data
[sctp_audit_indx
][0] = ev
;
597 sctp_audit_data
[sctp_audit_indx
][1] = fd
;
599 if (sctp_audit_indx
>= SCTP_AUDIT_SIZE
) {
608 * a list of sizes based on typical mtu's, used only if next hop
611 static int sctp_mtu_sizes
[] = {
633 find_next_best_mtu(int totsz
)
637 * if we are in here we must find the next best fit based on the
638 * size of the dg that failed to be sent.
641 for (i
= 0; i
< NUMBER_OF_MTU_SIZES
; i
++) {
642 if (totsz
< sctp_mtu_sizes
[i
]) {
649 return (sctp_mtu_sizes
[perfer
]);
653 sctp_fill_random_store(struct sctp_pcb
*m
)
656 * Here we use the MD5/SHA-1 to hash with our good randomNumbers
657 * and our counter. The result becomes our good random numbers and
658 * we then setup to give these out. Note that we do no lockig
659 * to protect this. This is ok, since if competing folks call
660 * this we will get more gobbled gook in the random store whic
661 * is what we want. There is a danger that two guys will use
662 * the same random numbers, but thats ok too since that
663 * is random as well :->
666 sctp_hash_digest((char *)m
->random_numbers
, sizeof(m
->random_numbers
),
667 (char *)&m
->random_counter
, sizeof(m
->random_counter
),
668 (char *)m
->random_store
);
673 sctp_select_initial_TSN(struct sctp_pcb
*m
)
676 * A true implementation should use random selection process to
677 * get the initial stream sequence number, using RFC1750 as a
683 if (m
->initial_sequence_debug
!= 0) {
685 ret
= m
->initial_sequence_debug
;
686 m
->initial_sequence_debug
++;
689 if ((m
->store_at
+sizeof(u_long
)) > SCTP_SIGNATURE_SIZE
) {
690 /* Refill the random store */
691 sctp_fill_random_store(m
);
693 p
= &m
->random_store
[(int)m
->store_at
];
696 m
->store_at
+= sizeof(u_long
);
701 sctp_select_a_tag(struct sctp_inpcb
*m
)
706 SCTP_GETTIME_TIMEVAL(&now
);
709 x
= sctp_select_initial_TSN(&m
->sctp_ep
);
714 if (sctp_is_vtag_good(m
, x
, &now
)) {
723 sctp_init_asoc(struct sctp_inpcb
*m
, struct sctp_association
*asoc
,
724 int for_a_init
, uint32_t override_tag
)
727 * Anything set to zero is taken care of by the allocation
732 * Up front select what scoping to apply on addresses I tell my peer
733 * Not sure what to do with these right now, we will need to come up
734 * with a way to set them. We may need to pass them through from the
735 * caller in the sctp_aloc_assoc() function.
738 /* init all variables to a known value.*/
739 asoc
->state
= SCTP_STATE_INUSE
;
740 asoc
->max_burst
= m
->sctp_ep
.max_burst
;
741 asoc
->heart_beat_delay
= m
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_HEARTBEAT
];
742 asoc
->cookie_life
= m
->sctp_ep
.def_cookie_life
;
745 asoc
->my_vtag
= override_tag
;
747 asoc
->my_vtag
= sctp_select_a_tag(m
);
749 asoc
->asconf_seq_out
= asoc
->str_reset_seq_out
= asoc
->init_seq_number
= asoc
->sending_seq
=
750 sctp_select_initial_TSN(&m
->sctp_ep
);
751 asoc
->t3timeout_highest_marked
= asoc
->asconf_seq_out
;
752 /* we are opptimisitic here */
753 asoc
->peer_supports_asconf
= 1;
754 asoc
->peer_supports_asconf_setprim
= 1;
755 asoc
->peer_supports_pktdrop
= 1;
757 asoc
->sent_queue_retran_cnt
= 0;
758 /* This will need to be adjusted */
759 asoc
->last_cwr_tsn
= asoc
->init_seq_number
- 1;
760 asoc
->last_acked_seq
= asoc
->init_seq_number
- 1;
761 asoc
->advanced_peer_ack_point
= asoc
->last_acked_seq
;
762 asoc
->asconf_seq_in
= asoc
->last_acked_seq
;
764 /* here we are different, we hold the next one we expect */
765 asoc
->str_reset_seq_in
= asoc
->last_acked_seq
+ 1;
767 asoc
->initial_init_rto_max
= m
->sctp_ep
.initial_init_rto_max
;
768 asoc
->initial_rto
= m
->sctp_ep
.initial_rto
;
770 asoc
->max_init_times
= m
->sctp_ep
.max_init_times
;
771 asoc
->max_send_times
= m
->sctp_ep
.max_send_times
;
772 asoc
->def_net_failure
= m
->sctp_ep
.def_net_failure
;
774 /* ECN Nonce initialization */
775 asoc
->ecn_nonce_allowed
= 0;
776 asoc
->receiver_nonce_sum
= 1;
777 asoc
->nonce_sum_expect_base
= 1;
778 asoc
->nonce_sum_check
= 1;
779 asoc
->nonce_resync_tsn
= 0;
780 asoc
->nonce_wait_for_ecne
= 0;
781 asoc
->nonce_wait_tsn
= 0;
783 if (m
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
787 /* Its a V6 socket */
788 inp6
= (struct in6pcb
*)m
;
789 asoc
->ipv6_addr_legal
= 1;
790 /* Now look at the binding flag to see if V4 will be legal */
792 #if defined(__OpenBSD__)
793 (0) /* we always do dual bind */
794 #elif defined (__NetBSD__)
795 (inp6
->in6p_flags
& IN6P_IPV6_V6ONLY
)
797 (inp6
->inp_flags
& IN6P_IPV6_V6ONLY
)
800 asoc
->ipv4_addr_legal
= 1;
802 /* V4 addresses are NOT legal on the association */
803 asoc
->ipv4_addr_legal
= 0;
806 /* Its a V4 socket, no - V6 */
807 asoc
->ipv4_addr_legal
= 1;
808 asoc
->ipv6_addr_legal
= 0;
812 asoc
->my_rwnd
= max(m
->sctp_socket
->so_rcv
.ssb_hiwat
, SCTP_MINIMAL_RWND
);
813 asoc
->peers_rwnd
= m
->sctp_socket
->so_rcv
.ssb_hiwat
;
815 asoc
->smallest_mtu
= m
->sctp_frag_point
;
816 asoc
->minrto
= m
->sctp_ep
.sctp_minrto
;
817 asoc
->maxrto
= m
->sctp_ep
.sctp_maxrto
;
819 LIST_INIT(&asoc
->sctp_local_addr_list
);
820 TAILQ_INIT(&asoc
->nets
);
821 TAILQ_INIT(&asoc
->pending_reply_queue
);
822 asoc
->last_asconf_ack_sent
= NULL
;
823 /* Setup to fill the hb random cache at first HB */
824 asoc
->hb_random_idx
= 4;
826 asoc
->sctp_autoclose_ticks
= m
->sctp_ep
.auto_close_time
;
829 * Now the stream parameters, here we allocate space for all
830 * streams that we request by default.
832 asoc
->streamoutcnt
= asoc
->pre_open_streams
=
833 m
->sctp_ep
.pre_open_stream_count
;
834 MALLOC(asoc
->strmout
, struct sctp_stream_out
*, asoc
->streamoutcnt
*
835 sizeof(struct sctp_stream_out
), M_PCB
, M_NOWAIT
);
836 if (asoc
->strmout
== NULL
) {
837 /* big trouble no memory */
840 for (i
= 0; i
< asoc
->streamoutcnt
; i
++) {
842 * inbound side must be set to 0xffff,
843 * also NOTE when we get the INIT-ACK back (for INIT sender)
844 * we MUST reduce the count (streamoutcnt) but first check
845 * if we sent to any of the upper streams that were dropped
846 * (if some were). Those that were dropped must be notified
847 * to the upper layer as failed to send.
849 asoc
->strmout
[i
].next_sequence_sent
= 0x0;
850 TAILQ_INIT(&asoc
->strmout
[i
].outqueue
);
851 asoc
->strmout
[i
].stream_no
= i
;
852 asoc
->strmout
[i
].next_spoke
.tqe_next
= 0;
853 asoc
->strmout
[i
].next_spoke
.tqe_prev
= 0;
855 /* Now the mapping array */
856 asoc
->mapping_array_size
= SCTP_INITIAL_MAPPING_ARRAY
;
858 MALLOC(asoc
->mapping_array
, u_int8_t
*, SCTP_INITIAL_MAPPING_ARRAY
,
861 MALLOC(asoc
->mapping_array
, u_int8_t
*, asoc
->mapping_array_size
,
864 if (asoc
->mapping_array
== NULL
) {
865 FREE(asoc
->strmout
, M_PCB
);
868 memset(asoc
->mapping_array
, 0, asoc
->mapping_array_size
);
869 /* Now the init of the other outqueues */
870 TAILQ_INIT(&asoc
->out_wheel
);
871 TAILQ_INIT(&asoc
->control_send_queue
);
872 TAILQ_INIT(&asoc
->send_queue
);
873 TAILQ_INIT(&asoc
->sent_queue
);
874 TAILQ_INIT(&asoc
->reasmqueue
);
875 TAILQ_INIT(&asoc
->delivery_queue
);
876 asoc
->max_inbound_streams
= m
->sctp_ep
.max_open_streams_intome
;
878 TAILQ_INIT(&asoc
->asconf_queue
);
883 sctp_expand_mapping_array(struct sctp_association
*asoc
)
885 /* mapping array needs to grow */
889 new_size
= asoc
->mapping_array_size
+ SCTP_MAPPING_ARRAY_INCR
;
891 MALLOC(new_array
, u_int8_t
*, asoc
->mapping_array_size
892 + SCTP_MAPPING_ARRAY_INCR
, M_PCB
, M_NOWAIT
);
894 MALLOC(new_array
, u_int8_t
*, new_size
, M_PCB
, M_NOWAIT
);
896 if (new_array
== NULL
) {
897 /* can't get more, forget it */
898 kprintf("No memory for expansion of SCTP mapping array %d\n",
902 memset(new_array
, 0, new_size
);
903 memcpy(new_array
, asoc
->mapping_array
, asoc
->mapping_array_size
);
904 FREE(asoc
->mapping_array
, M_PCB
);
905 asoc
->mapping_array
= new_array
;
906 asoc
->mapping_array_size
= new_size
;
911 sctp_timeout_handler(void *t
)
913 struct sctp_inpcb
*inp
;
914 struct sctp_tcb
*stcb
;
915 struct sctp_nets
*net
;
916 struct sctp_timer
*tmr
;
918 #if defined(__APPLE__)
919 boolean_t funnel_state
;
921 /* get BSD kernel funnel/mutex */
922 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
926 tmr
= (struct sctp_timer
*)t
;
927 inp
= (struct sctp_inpcb
*)tmr
->ep
;
928 stcb
= (struct sctp_tcb
*)tmr
->tcb
;
929 net
= (struct sctp_nets
*)tmr
->net
;
933 #ifdef SCTP_AUDITING_ENABLED
934 sctp_audit_log(0xF0, (u_int8_t
)tmr
->type
);
935 sctp_auditing(3, inp
, stcb
, net
);
937 sctp_pegs
[SCTP_TIMERS_EXP
]++;
944 if (inp
->sctp_socket
== 0) {
946 #if defined(__APPLE__)
947 /* release BSD kernel funnel/mutex */
948 thread_funnel_set(network_flock
, FALSE
);
950 SCTP_INP_WUNLOCK(inp
);
954 if (stcb
->asoc
.state
== 0) {
956 #if defined(__APPLE__)
957 /* release BSD kernel funnel/mutex */
958 thread_funnel_set(network_flock
, FALSE
);
960 SCTP_INP_WUNLOCK(inp
);
965 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
966 kprintf("Timer type %d goes off\n", tmr
->type
);
968 #endif /* SCTP_DEBUG */
970 if (!callout_active(&tmr
->timer
)) {
972 #if defined(__APPLE__)
973 /* release BSD kernel funnel/mutex */
974 thread_funnel_set(network_flock
, FALSE
);
976 SCTP_INP_WUNLOCK(inp
);
980 #if defined(__APPLE__)
981 /* clear the callout pending status here */
982 callout_stop(&tmr
->timer
);
987 SCTP_INP_INCR_REF(inp
);
988 SCTP_INP_WUNLOCK(inp
);
992 case SCTP_TIMER_TYPE_ITERATOR
:
994 struct sctp_iterator
*it
;
995 it
= (struct sctp_iterator
*)inp
;
996 sctp_iterator_timer(it
);
999 /* call the handler for the appropriate timer type */
1000 case SCTP_TIMER_TYPE_SEND
:
1001 sctp_pegs
[SCTP_TMIT_TIMER
]++;
1002 stcb
->asoc
.num_send_timers_up
--;
1003 if (stcb
->asoc
.num_send_timers_up
< 0) {
1004 stcb
->asoc
.num_send_timers_up
= 0;
1006 if (sctp_t3rxt_timer(inp
, stcb
, net
)) {
1007 /* no need to unlock on tcb its gone */
1011 #ifdef SCTP_AUDITING_ENABLED
1012 sctp_auditing(4, inp
, stcb
, net
);
1014 sctp_chunk_output(inp
, stcb
, 1);
1015 if ((stcb
->asoc
.num_send_timers_up
== 0) &&
1016 (stcb
->asoc
.sent_queue_cnt
> 0)
1018 struct sctp_tmit_chunk
*chk
;
1020 * safeguard. If there on some on the sent queue
1021 * somewhere but no timers running something is
1022 * wrong... so we start a timer on the first chunk
1023 * on the send queue on whatever net it is sent to.
1025 sctp_pegs
[SCTP_T3_SAFEGRD
]++;
1026 chk
= TAILQ_FIRST(&stcb
->asoc
.sent_queue
);
1027 sctp_timer_start(SCTP_TIMER_TYPE_SEND
, inp
, stcb
,
1031 case SCTP_TIMER_TYPE_INIT
:
1032 if (sctp_t1init_timer(inp
, stcb
, net
)) {
1033 /* no need to unlock on tcb its gone */
1036 /* We do output but not here */
1039 case SCTP_TIMER_TYPE_RECV
:
1040 sctp_pegs
[SCTP_RECV_TIMER
]++;
1041 sctp_send_sack(stcb
);
1042 #ifdef SCTP_AUDITING_ENABLED
1043 sctp_auditing(4, inp
, stcb
, net
);
1045 sctp_chunk_output(inp
, stcb
, 4);
1047 case SCTP_TIMER_TYPE_SHUTDOWN
:
1048 if (sctp_shutdown_timer(inp
, stcb
, net
) ) {
1049 /* no need to unlock on tcb its gone */
1052 #ifdef SCTP_AUDITING_ENABLED
1053 sctp_auditing(4, inp
, stcb
, net
);
1055 sctp_chunk_output(inp
, stcb
, 5);
1057 case SCTP_TIMER_TYPE_HEARTBEAT
:
1058 if (sctp_heartbeat_timer(inp
, stcb
, net
)) {
1059 /* no need to unlock on tcb its gone */
1062 #ifdef SCTP_AUDITING_ENABLED
1063 sctp_auditing(4, inp
, stcb
, net
);
1065 sctp_chunk_output(inp
, stcb
, 6);
1067 case SCTP_TIMER_TYPE_COOKIE
:
1068 if (sctp_cookie_timer(inp
, stcb
, net
)) {
1069 /* no need to unlock on tcb its gone */
1072 #ifdef SCTP_AUDITING_ENABLED
1073 sctp_auditing(4, inp
, stcb
, net
);
1075 sctp_chunk_output(inp
, stcb
, 1);
1077 case SCTP_TIMER_TYPE_NEWCOOKIE
:
1081 SCTP_GETTIME_TIMEVAL(&tv
);
1082 SCTP_INP_WLOCK(inp
);
1083 inp
->sctp_ep
.time_of_secret_change
= tv
.tv_sec
;
1084 inp
->sctp_ep
.last_secret_number
=
1085 inp
->sctp_ep
.current_secret_number
;
1086 inp
->sctp_ep
.current_secret_number
++;
1087 if (inp
->sctp_ep
.current_secret_number
>=
1088 SCTP_HOW_MANY_SECRETS
) {
1089 inp
->sctp_ep
.current_secret_number
= 0;
1091 secret
= (int)inp
->sctp_ep
.current_secret_number
;
1092 for (i
= 0; i
< SCTP_NUMBER_OF_SECRETS
; i
++) {
1093 inp
->sctp_ep
.secret_key
[secret
][i
] =
1094 sctp_select_initial_TSN(&inp
->sctp_ep
);
1096 SCTP_INP_WUNLOCK(inp
);
1097 sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE
, inp
, stcb
, net
);
1101 case SCTP_TIMER_TYPE_PATHMTURAISE
:
1102 sctp_pathmtu_timer(inp
, stcb
, net
);
1105 case SCTP_TIMER_TYPE_SHUTDOWNACK
:
1106 if (sctp_shutdownack_timer(inp
, stcb
, net
)) {
1107 /* no need to unlock on tcb its gone */
1110 #ifdef SCTP_AUDITING_ENABLED
1111 sctp_auditing(4, inp
, stcb
, net
);
1113 sctp_chunk_output(inp
, stcb
, 7);
1115 case SCTP_TIMER_TYPE_SHUTDOWNGUARD
:
1116 sctp_abort_an_association(inp
, stcb
,
1117 SCTP_SHUTDOWN_GUARD_EXPIRES
, NULL
);
1118 /* no need to unlock on tcb its gone */
1122 case SCTP_TIMER_TYPE_STRRESET
:
1123 if (sctp_strreset_timer(inp
, stcb
, net
)) {
1124 /* no need to unlock on tcb its gone */
1127 sctp_chunk_output(inp
, stcb
, 9);
1130 case SCTP_TIMER_TYPE_ASCONF
:
1131 if (sctp_asconf_timer(inp
, stcb
, net
)) {
1132 /* no need to unlock on tcb its gone */
1135 #ifdef SCTP_AUDITING_ENABLED
1136 sctp_auditing(4, inp
, stcb
, net
);
1138 sctp_chunk_output(inp
, stcb
, 8);
1141 case SCTP_TIMER_TYPE_AUTOCLOSE
:
1142 sctp_autoclose_timer(inp
, stcb
, net
);
1143 sctp_chunk_output(inp
, stcb
, 10);
1146 case SCTP_TIMER_TYPE_INPKILL
:
1147 /* special case, take away our
1148 * increment since WE are the killer
1150 SCTP_INP_WLOCK(inp
);
1151 SCTP_INP_DECR_REF(inp
);
1152 SCTP_INP_WUNLOCK(inp
);
1153 sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL
, inp
, NULL
, NULL
);
1154 sctp_inpcb_free(inp
, 1);
1159 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1160 kprintf("sctp_timeout_handler:unknown timer %d\n",
1163 #endif /* SCTP_DEBUG */
1166 #ifdef SCTP_AUDITING_ENABLED
1167 sctp_audit_log(0xF1, (u_int8_t
)tmr
->type
);
1168 sctp_auditing(5, inp
, stcb
, net
);
1172 * Now we need to clean up the control chunk chain if an
1173 * ECNE is on it. It must be marked as UNSENT again so next
1174 * call will continue to send it until such time that we get
1175 * a CWR, to remove it. It is, however, less likely that we
1176 * will find a ecn echo on the chain though.
1178 sctp_fix_ecn_echo(&stcb
->asoc
);
1181 SCTP_TCB_UNLOCK(stcb
);
1184 SCTP_INP_WLOCK(inp
);
1185 SCTP_INP_DECR_REF(inp
);
1186 SCTP_INP_WUNLOCK(inp
);
1191 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1192 kprintf("Timer now complete (type %d)\n", typ
);
1194 #endif /* SCTP_DEBUG */
1197 #if defined(__APPLE__)
1198 /* release BSD kernel funnel/mutex */
1199 thread_funnel_set(network_flock
, FALSE
);
1204 sctp_timer_start(int t_type
, struct sctp_inpcb
*inp
, struct sctp_tcb
*stcb
,
1205 struct sctp_nets
*net
)
1208 struct sctp_timer
*tmr
;
1217 case SCTP_TIMER_TYPE_ITERATOR
:
1219 struct sctp_iterator
*it
;
1220 it
= (struct sctp_iterator
*)inp
;
1222 to_ticks
= SCTP_ITERATOR_TICKS
;
1225 case SCTP_TIMER_TYPE_SEND
:
1226 /* Here we use the RTO timer */
1229 if ((stcb
== NULL
) || (net
== NULL
)) {
1232 tmr
= &net
->rxt_timer
;
1233 if (net
->RTO
== 0) {
1234 rto_val
= stcb
->asoc
.initial_rto
;
1238 to_ticks
= MSEC_TO_TICKS(rto_val
);
1241 case SCTP_TIMER_TYPE_INIT
:
1243 * Here we use the INIT timer default
1244 * usually about 1 minute.
1246 if ((stcb
== NULL
) || (net
== NULL
)) {
1249 tmr
= &net
->rxt_timer
;
1250 if (net
->RTO
== 0) {
1251 to_ticks
= MSEC_TO_TICKS(stcb
->asoc
.initial_rto
);
1253 to_ticks
= MSEC_TO_TICKS(net
->RTO
);
1256 case SCTP_TIMER_TYPE_RECV
:
1258 * Here we use the Delayed-Ack timer value from the inp
1259 * ususually about 200ms.
1264 tmr
= &stcb
->asoc
.dack_timer
;
1265 to_ticks
= inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_RECV
];
1267 case SCTP_TIMER_TYPE_SHUTDOWN
:
1268 /* Here we use the RTO of the destination. */
1269 if ((stcb
== NULL
) || (net
== NULL
)) {
1273 if (net
->RTO
== 0) {
1274 to_ticks
= MSEC_TO_TICKS(stcb
->asoc
.initial_rto
);
1276 to_ticks
= MSEC_TO_TICKS(net
->RTO
);
1278 tmr
= &net
->rxt_timer
;
1280 case SCTP_TIMER_TYPE_HEARTBEAT
:
1282 * the net is used here so that we can add in the RTO.
1283 * Even though we use a different timer. We also add the
1284 * HB timer PLUS a random jitter.
1291 uint8_t this_random
;
1292 int cnt_of_unconf
=0;
1293 struct sctp_nets
*lnet
;
1295 TAILQ_FOREACH(lnet
, &stcb
->asoc
.nets
, sctp_next
) {
1296 if (lnet
->dest_state
& SCTP_ADDR_UNCONFIRMED
) {
1301 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1302 kprintf("HB timer to start unconfirmed:%d hb_delay:%d\n",
1303 cnt_of_unconf
, stcb
->asoc
.heart_beat_delay
);
1306 if (stcb
->asoc
.hb_random_idx
> 3) {
1307 rndval
= sctp_select_initial_TSN(&inp
->sctp_ep
);
1308 memcpy(stcb
->asoc
.hb_random_values
, &rndval
,
1309 sizeof(stcb
->asoc
.hb_random_values
));
1310 this_random
= stcb
->asoc
.hb_random_values
[0];
1311 stcb
->asoc
.hb_random_idx
= 0;
1312 stcb
->asoc
.hb_ect_randombit
= 0;
1314 this_random
= stcb
->asoc
.hb_random_values
[stcb
->asoc
.hb_random_idx
];
1315 stcb
->asoc
.hb_random_idx
++;
1316 stcb
->asoc
.hb_ect_randombit
= 0;
1319 * this_random will be 0 - 256 ms
1322 if ((stcb
->asoc
.heart_beat_delay
== 0) &&
1323 (cnt_of_unconf
== 0)) {
1324 /* no HB on this inp after confirmations */
1328 struct sctp_nets
*lnet
;
1330 delay
= stcb
->asoc
.heart_beat_delay
;
1331 TAILQ_FOREACH(lnet
, &stcb
->asoc
.nets
, sctp_next
) {
1332 if ((lnet
->dest_state
& SCTP_ADDR_UNCONFIRMED
) &&
1333 ((lnet
->dest_state
& SCTP_ADDR_OUT_OF_SCOPE
) == 0) &&
1334 (lnet
->dest_state
& SCTP_ADDR_REACHABLE
)) {
1338 if (net
->RTO
== 0) {
1339 /* Never been checked */
1340 to_ticks
= this_random
+ stcb
->asoc
.initial_rto
+ delay
;
1342 /* set rto_val to the ms */
1343 to_ticks
= delay
+ net
->RTO
+ this_random
;
1346 if (cnt_of_unconf
) {
1347 to_ticks
= this_random
+ stcb
->asoc
.initial_rto
;
1349 to_ticks
= stcb
->asoc
.heart_beat_delay
+ this_random
+ stcb
->asoc
.initial_rto
;
1353 * Now we must convert the to_ticks that are now in
1359 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1360 kprintf("Timer to expire in %d ticks\n", to_ticks
);
1363 tmr
= &stcb
->asoc
.hb_timer
;
1366 case SCTP_TIMER_TYPE_COOKIE
:
1368 * Here we can use the RTO timer from the network since
1369 * one RTT was compelete. If a retran happened then we will
1370 * be using the RTO initial value.
1372 if ((stcb
== NULL
) || (net
== NULL
)) {
1375 if (net
->RTO
== 0) {
1376 to_ticks
= MSEC_TO_TICKS(stcb
->asoc
.initial_rto
);
1378 to_ticks
= MSEC_TO_TICKS(net
->RTO
);
1380 tmr
= &net
->rxt_timer
;
1382 case SCTP_TIMER_TYPE_NEWCOOKIE
:
1384 * nothing needed but the endpoint here
1385 * ususually about 60 minutes.
1387 tmr
= &inp
->sctp_ep
.signature_change
;
1388 to_ticks
= inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_SIGNATURE
];
1390 case SCTP_TIMER_TYPE_INPKILL
:
1392 * The inp is setup to die. We re-use the
1393 * signature_chage timer since that has
1394 * stopped and we are in the GONE state.
1396 tmr
= &inp
->sctp_ep
.signature_change
;
1397 to_ticks
= (SCTP_INP_KILL_TIMEOUT
* hz
) / 1000;
1399 case SCTP_TIMER_TYPE_PATHMTURAISE
:
1401 * Here we use the value found in the EP for PMTU
1402 * ususually about 10 minutes.
1410 to_ticks
= inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_PMTU
];
1411 tmr
= &net
->pmtu_timer
;
1413 case SCTP_TIMER_TYPE_SHUTDOWNACK
:
1414 /* Here we use the RTO of the destination */
1415 if ((stcb
== NULL
) || (net
== NULL
)) {
1418 if (net
->RTO
== 0) {
1419 to_ticks
= MSEC_TO_TICKS(stcb
->asoc
.initial_rto
);
1421 to_ticks
= MSEC_TO_TICKS(net
->RTO
);
1423 tmr
= &net
->rxt_timer
;
1425 case SCTP_TIMER_TYPE_SHUTDOWNGUARD
:
1427 * Here we use the endpoints shutdown guard timer
1428 * usually about 3 minutes.
1433 to_ticks
= inp
->sctp_ep
.sctp_timeoutticks
[SCTP_TIMER_MAXSHUTDOWN
];
1434 tmr
= &stcb
->asoc
.shut_guard_timer
;
1436 case SCTP_TIMER_TYPE_STRRESET
:
1438 * Here the timer comes from the inp
1439 * but its value is from the RTO.
1441 if ((stcb
== NULL
) || (net
== NULL
)) {
1444 if (net
->RTO
== 0) {
1445 to_ticks
= MSEC_TO_TICKS(stcb
->asoc
.initial_rto
);
1447 to_ticks
= MSEC_TO_TICKS(net
->RTO
);
1449 tmr
= &stcb
->asoc
.strreset_timer
;
1452 case SCTP_TIMER_TYPE_ASCONF
:
1454 * Here the timer comes from the inp
1455 * but its value is from the RTO.
1457 if ((stcb
== NULL
) || (net
== NULL
)) {
1460 if (net
->RTO
== 0) {
1461 to_ticks
= MSEC_TO_TICKS(stcb
->asoc
.initial_rto
);
1463 to_ticks
= MSEC_TO_TICKS(net
->RTO
);
1465 tmr
= &stcb
->asoc
.asconf_timer
;
1467 case SCTP_TIMER_TYPE_AUTOCLOSE
:
1471 if (stcb
->asoc
.sctp_autoclose_ticks
== 0) {
1472 /* Really an error since stcb is NOT set to autoclose */
1475 to_ticks
= stcb
->asoc
.sctp_autoclose_ticks
;
1476 tmr
= &stcb
->asoc
.autoclose_timer
;
1480 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1481 kprintf("sctp_timer_start:Unknown timer type %d\n",
1484 #endif /* SCTP_DEBUG */
1488 if ((to_ticks
<= 0) || (tmr
== NULL
)) {
1490 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1491 kprintf("sctp_timer_start:%d:software error to_ticks:%d tmr:%p not set ??\n",
1492 t_type
, to_ticks
, tmr
);
1494 #endif /* SCTP_DEBUG */
1497 if (callout_pending(&tmr
->timer
)) {
1499 * we do NOT allow you to have it already running.
1500 * if it is we leave the current one up unchanged
1504 /* At this point we can proceed */
1505 if (t_type
== SCTP_TIMER_TYPE_SEND
) {
1506 stcb
->asoc
.num_send_timers_up
++;
1509 tmr
->ep
= (void *)inp
;
1510 tmr
->tcb
= (void *)stcb
;
1511 tmr
->net
= (void *)net
;
1512 callout_reset(&tmr
->timer
, to_ticks
, sctp_timeout_handler
, tmr
);
1517 sctp_timer_stop(int t_type
, struct sctp_inpcb
*inp
, struct sctp_tcb
*stcb
,
1518 struct sctp_nets
*net
)
1520 struct sctp_timer
*tmr
;
1527 case SCTP_TIMER_TYPE_ITERATOR
:
1529 struct sctp_iterator
*it
;
1530 it
= (struct sctp_iterator
*)inp
;
1534 case SCTP_TIMER_TYPE_SEND
:
1535 if ((stcb
== NULL
) || (net
== NULL
)) {
1538 tmr
= &net
->rxt_timer
;
1540 case SCTP_TIMER_TYPE_INIT
:
1541 if ((stcb
== NULL
) || (net
== NULL
)) {
1544 tmr
= &net
->rxt_timer
;
1546 case SCTP_TIMER_TYPE_RECV
:
1550 tmr
= &stcb
->asoc
.dack_timer
;
1552 case SCTP_TIMER_TYPE_SHUTDOWN
:
1553 if ((stcb
== NULL
) || (net
== NULL
)) {
1556 tmr
= &net
->rxt_timer
;
1558 case SCTP_TIMER_TYPE_HEARTBEAT
:
1562 tmr
= &stcb
->asoc
.hb_timer
;
1564 case SCTP_TIMER_TYPE_COOKIE
:
1565 if ((stcb
== NULL
) || (net
== NULL
)) {
1568 tmr
= &net
->rxt_timer
;
1570 case SCTP_TIMER_TYPE_NEWCOOKIE
:
1571 /* nothing needed but the endpoint here */
1572 tmr
= &inp
->sctp_ep
.signature_change
;
1573 /* We re-use the newcookie timer for
1574 * the INP kill timer. We must assure
1575 * that we do not kill it by accident.
1578 case SCTP_TIMER_TYPE_INPKILL
:
1580 * The inp is setup to die. We re-use the
1581 * signature_chage timer since that has
1582 * stopped and we are in the GONE state.
1584 tmr
= &inp
->sctp_ep
.signature_change
;
1586 case SCTP_TIMER_TYPE_PATHMTURAISE
:
1593 tmr
= &net
->pmtu_timer
;
1595 case SCTP_TIMER_TYPE_SHUTDOWNACK
:
1596 if ((stcb
== NULL
) || (net
== NULL
)) {
1599 tmr
= &net
->rxt_timer
;
1601 case SCTP_TIMER_TYPE_SHUTDOWNGUARD
:
1605 tmr
= &stcb
->asoc
.shut_guard_timer
;
1607 case SCTP_TIMER_TYPE_STRRESET
:
1611 tmr
= &stcb
->asoc
.strreset_timer
;
1613 case SCTP_TIMER_TYPE_ASCONF
:
1617 tmr
= &stcb
->asoc
.asconf_timer
;
1619 case SCTP_TIMER_TYPE_AUTOCLOSE
:
1623 tmr
= &stcb
->asoc
.autoclose_timer
;
1627 if (sctp_debug_on
& SCTP_DEBUG_TIMER1
) {
1628 kprintf("sctp_timer_stop:Unknown timer type %d\n",
1631 #endif /* SCTP_DEBUG */
1637 if ((tmr
->type
!= t_type
) && tmr
->type
) {
1639 * Ok we have a timer that is under joint use. Cookie timer
1640 * per chance with the SEND timer. We therefore are NOT
1641 * running the timer that the caller wants stopped. So just
1646 if (t_type
== SCTP_TIMER_TYPE_SEND
) {
1647 stcb
->asoc
.num_send_timers_up
--;
1648 if (stcb
->asoc
.num_send_timers_up
< 0) {
1649 stcb
->asoc
.num_send_timers_up
= 0;
1652 callout_stop(&tmr
->timer
);
1656 #ifdef SCTP_USE_ADLER32
1658 update_adler32(uint32_t adler
, uint8_t *buf
, int32_t len
)
1660 u_int32_t s1
= adler
& 0xffff;
1661 u_int32_t s2
= (adler
>> 16) & 0xffff;
1664 for (n
= 0; n
< len
; n
++, buf
++) {
1665 /* s1 = (s1 + buf[n]) % BASE */
1669 * now if we need to, we do a mod by subtracting. It seems
1670 * a bit faster since I really will only ever do one subtract
1671 * at the MOST, since buf[n] is a max of 255.
1673 if (s1
>= SCTP_ADLER32_BASE
) {
1674 s1
-= SCTP_ADLER32_BASE
;
1676 /* s2 = (s2 + s1) % BASE */
1680 * again, it is more efficent (it seems) to subtract since
1681 * the most s2 will ever be is (BASE-1 + BASE-1) in the worse
1682 * case. This would then be (2 * BASE) - 2, which will still
1683 * only do one subtract. On Intel this is much better to do
1684 * this way and avoid the divide. Have not -pg'd on sparc.
1686 if (s2
>= SCTP_ADLER32_BASE
) {
1687 s2
-= SCTP_ADLER32_BASE
;
1690 /* Return the adler32 of the bytes buf[0..len-1] */
1691 return ((s2
<< 16) + s1
);
1698 sctp_calculate_len(struct mbuf
*m
)
1710 #if defined(SCTP_WITH_NO_CSUM)
1713 sctp_calculate_sum(struct mbuf
*m
, int32_t *pktlen
, uint32_t offset
)
1716 * given a mbuf chain with a packetheader offset by 'offset'
1717 * pointing at a sctphdr (with csum set to 0) go through
1718 * the chain of m_next's and calculate the SCTP checksum.
1719 * This is currently Adler32 but will change to CRC32x
1720 * soon. Also has a side bonus calculate the total length
1721 * of the mbuf chain.
1722 * Note: if offset is greater than the total mbuf length,
1723 * checksum=1, pktlen=0 is returned (ie. no real error code)
1727 *pktlen
= sctp_calculate_len(m
);
1731 #elif defined(SCTP_USE_INCHKSUM)
1733 #include <machine/in_cksum.h>
1736 sctp_calculate_sum(struct mbuf
*m
, int32_t *pktlen
, uint32_t offset
)
1739 * given a mbuf chain with a packetheader offset by 'offset'
1740 * pointing at a sctphdr (with csum set to 0) go through
1741 * the chain of m_next's and calculate the SCTP checksum.
1742 * This is currently Adler32 but will change to CRC32x
1743 * soon. Also has a side bonus calculate the total length
1744 * of the mbuf chain.
1745 * Note: if offset is greater than the total mbuf length,
1746 * checksum=1, pktlen=0 is returned (ie. no real error code)
1750 uint32_t the_sum
, retsum
;
1757 the_sum
= (uint32_t)(in_cksum_skip(m
, tlen
, offset
));
1759 *pktlen
= (tlen
-offset
);
1760 retsum
= htons(the_sum
);
1767 sctp_calculate_sum(struct mbuf
*m
, int32_t *pktlen
, uint32_t offset
)
1770 * given a mbuf chain with a packetheader offset by 'offset'
1771 * pointing at a sctphdr (with csum set to 0) go through
1772 * the chain of m_next's and calculate the SCTP checksum.
1773 * This is currently Adler32 but will change to CRC32x
1774 * soon. Also has a side bonus calculate the total length
1775 * of the mbuf chain.
1776 * Note: if offset is greater than the total mbuf length,
1777 * checksum=1, pktlen=0 is returned (ie. no real error code)
1780 #ifdef SCTP_USE_ADLER32
1783 uint32_t base
= 0xffffffff;
1784 #endif /* SCTP_USE_ADLER32 */
1787 /* find the correct mbuf and offset into mbuf */
1788 while ((at
!= NULL
) && (offset
> (uint32_t)at
->m_len
)) {
1789 offset
-= at
->m_len
; /* update remaining offset left */
1793 while (at
!= NULL
) {
1794 #ifdef SCTP_USE_ADLER32
1795 base
= update_adler32(base
, at
->m_data
+ offset
,
1796 at
->m_len
- offset
);
1798 base
= update_crc32(base
, at
->m_data
+ offset
,
1799 at
->m_len
- offset
);
1800 #endif /* SCTP_USE_ADLER32 */
1801 tlen
+= at
->m_len
- offset
;
1802 /* we only offset once into the first mbuf */
1808 if (pktlen
!= NULL
) {
1811 #ifdef SCTP_USE_ADLER32
1816 base
= sctp_csum_finalize(base
);
1825 sctp_mtu_size_reset(struct sctp_inpcb
*inp
,
1826 struct sctp_association
*asoc
, u_long mtu
)
1829 * Reset the P-MTU size on this association, this involves changing
1830 * the asoc MTU, going through ANY chunk+overhead larger than mtu
1831 * to allow the DF flag to be cleared.
1833 struct sctp_tmit_chunk
*chk
;
1834 struct sctp_stream_out
*strm
;
1835 unsigned int eff_mtu
, ovh
;
1836 asoc
->smallest_mtu
= mtu
;
1837 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_BOUND_V6
) {
1838 ovh
= SCTP_MIN_OVERHEAD
;
1840 ovh
= SCTP_MIN_V4_OVERHEAD
;
1842 eff_mtu
= mtu
- ovh
;
1843 /* Now mark any chunks that need to let IP fragment */
1844 TAILQ_FOREACH(strm
, &asoc
->out_wheel
, next_spoke
) {
1845 TAILQ_FOREACH(chk
, &strm
->outqueue
, sctp_next
) {
1846 if (chk
->send_size
> eff_mtu
) {
1847 chk
->flags
&= SCTP_DONT_FRAGMENT
;
1848 chk
->flags
|= CHUNK_FLAGS_FRAGMENT_OK
;
1852 TAILQ_FOREACH(chk
, &asoc
->send_queue
, sctp_next
) {
1853 if (chk
->send_size
> eff_mtu
) {
1854 chk
->flags
&= SCTP_DONT_FRAGMENT
;
1855 chk
->flags
|= CHUNK_FLAGS_FRAGMENT_OK
;
1858 TAILQ_FOREACH(chk
, &asoc
->sent_queue
, sctp_next
) {
1859 if (chk
->send_size
> eff_mtu
) {
1860 chk
->flags
&= SCTP_DONT_FRAGMENT
;
1861 chk
->flags
|= CHUNK_FLAGS_FRAGMENT_OK
;
1868 * given an association and starting time of the current RTT period
1869 * return RTO in number of usecs
1870 * net should point to the current network
1873 sctp_calculate_rto(struct sctp_tcb
*stcb
,
1874 struct sctp_association
*asoc
,
1875 struct sctp_nets
*net
,
1876 struct timeval
*old
)
1879 * given an association and the starting time of the current RTT
1880 * period (in value1/value2) return RTO in number of usecs.
1884 unsigned int new_rto
= 0;
1885 int first_measure
= 0;
1888 /************************/
1889 /* 1. calculate new RTT */
1890 /************************/
1891 /* get the current time */
1892 SCTP_GETTIME_TIMEVAL(&now
);
1893 /* compute the RTT value */
1894 if ((u_long
)now
.tv_sec
> (u_long
)old
->tv_sec
) {
1895 calc_time
= ((u_long
)now
.tv_sec
- (u_long
)old
->tv_sec
) * 1000;
1896 if ((u_long
)now
.tv_usec
> (u_long
)old
->tv_usec
) {
1897 calc_time
+= (((u_long
)now
.tv_usec
-
1898 (u_long
)old
->tv_usec
)/1000);
1899 } else if ((u_long
)now
.tv_usec
< (u_long
)old
->tv_usec
) {
1900 /* Borrow 1,000ms from current calculation */
1902 /* Add in the slop over */
1903 calc_time
+= ((int)now
.tv_usec
/1000);
1904 /* Add in the pre-second ms's */
1905 calc_time
+= (((int)1000000 - (int)old
->tv_usec
)/1000);
1907 } else if ((u_long
)now
.tv_sec
== (u_long
)old
->tv_sec
) {
1908 if ((u_long
)now
.tv_usec
> (u_long
)old
->tv_usec
) {
1909 calc_time
= ((u_long
)now
.tv_usec
-
1910 (u_long
)old
->tv_usec
)/1000;
1911 } else if ((u_long
)now
.tv_usec
< (u_long
)old
->tv_usec
) {
1912 /* impossible .. garbage in nothing out */
1913 return (((net
->lastsa
>> 2) + net
->lastsv
) >> 1);
1915 /* impossible .. garbage in nothing out */
1916 return (((net
->lastsa
>> 2) + net
->lastsv
) >> 1);
1919 /* Clock wrapped? */
1920 return (((net
->lastsa
>> 2) + net
->lastsv
) >> 1);
1922 /***************************/
1923 /* 2. update RTTVAR & SRTT */
1924 /***************************/
1926 /* if (net->lastsv || net->lastsa) {*/
1927 /* per Section 5.3.1 C3 in SCTP */
1928 /* net->lastsv = (int) *//* RTTVAR */
1929 /* (((double)(1.0 - 0.25) * (double)net->lastsv) +
1930 (double)(0.25 * (double)abs(net->lastsa - calc_time)));
1931 net->lastsa = (int) */ /* SRTT */
1932 /*(((double)(1.0 - 0.125) * (double)net->lastsa) +
1933 (double)(0.125 * (double)calc_time));
1935 *//* the first RTT calculation, per C2 Section 5.3.1 */
1936 /* net->lastsa = calc_time; *//* SRTT */
1937 /* net->lastsv = calc_time / 2; *//* RTTVAR */
1939 /* if RTTVAR goes to 0 you set to clock grainularity */
1940 /* if (net->lastsv == 0) {
1941 net->lastsv = SCTP_CLOCK_GRANULARITY;
1943 new_rto = net->lastsa + 4 * net->lastsv;
1946 o_calctime
= calc_time
;
1947 /* this is Van Jacobson's integer version */
1949 calc_time
-= (net
->lastsa
>> 3);
1950 net
->lastsa
+= calc_time
;
1951 if (calc_time
< 0) {
1952 calc_time
= -calc_time
;
1954 calc_time
-= (net
->lastsv
>> 2);
1955 net
->lastsv
+= calc_time
;
1956 if (net
->lastsv
== 0) {
1957 net
->lastsv
= SCTP_CLOCK_GRANULARITY
;
1960 /* First RTO measurment */
1961 net
->lastsa
= calc_time
;
1962 net
->lastsv
= calc_time
>> 1;
1965 new_rto
= ((net
->lastsa
>> 2) + net
->lastsv
) >> 1;
1966 if ((new_rto
> SCTP_SAT_NETWORK_MIN
) &&
1967 (stcb
->asoc
.sat_network_lockout
== 0)) {
1968 stcb
->asoc
.sat_network
= 1;
1969 } else if ((!first_measure
) && stcb
->asoc
.sat_network
) {
1970 stcb
->asoc
.sat_network
= 0;
1971 stcb
->asoc
.sat_network_lockout
= 1;
1973 /* bound it, per C6/C7 in Section 5.3.1 */
1974 if (new_rto
< stcb
->asoc
.minrto
) {
1975 new_rto
= stcb
->asoc
.minrto
;
1977 if (new_rto
> stcb
->asoc
.maxrto
) {
1978 new_rto
= stcb
->asoc
.maxrto
;
1980 /* we are now returning the RTT Smoothed */
1981 return ((u_int32_t
)new_rto
);
1986 * return a pointer to a contiguous piece of data from the given
1987 * mbuf chain starting at 'off' for 'len' bytes. If the desired
1988 * piece spans more than one mbuf, a copy is made at 'ptr'.
1989 * caller must ensure that the buffer size is >= 'len'
1990 * returns NULL if there there isn't 'len' bytes in the chain.
1993 sctp_m_getptr(struct mbuf
*m
, int off
, int len
, u_int8_t
*in_ptr
)
1998 if ((off
< 0) || (len
<= 0))
2001 /* find the desired start location */
2002 while ((m
!= NULL
) && (off
> 0)) {
2011 /* is the current mbuf large enough (eg. contiguous)? */
2012 if ((m
->m_len
- off
) >= len
) {
2013 return (mtod(m
, caddr_t
) + off
);
2015 /* else, it spans more than one mbuf, so save a temp copy... */
2016 while ((m
!= NULL
) && (len
> 0)) {
2017 count
= min(m
->m_len
- off
, len
);
2018 bcopy(mtod(m
, caddr_t
) + off
, ptr
, count
);
2024 if ((m
== NULL
) && (len
> 0))
2027 return ((caddr_t
)in_ptr
);
2032 struct sctp_paramhdr
*
2033 sctp_get_next_param(struct mbuf
*m
,
2035 struct sctp_paramhdr
*pull
,
2038 /* This just provides a typed signature to Peter's Pull routine */
2039 return ((struct sctp_paramhdr
*)sctp_m_getptr(m
, offset
, pull_limit
,
2045 sctp_add_pad_tombuf(struct mbuf
*m
, int padlen
)
2048 * add padlen bytes of 0 filled padding to the end of the mbuf.
2049 * If padlen is > 3 this routine will fail.
2056 if (M_TRAILINGSPACE(m
)) {
2059 * We hope the majority of the time we hit here :)
2061 dp
= (u_int8_t
*)(mtod(m
, caddr_t
) + m
->m_len
);
2064 /* Hard way we must grow the mbuf */
2066 MGET(tmp
, MB_DONTWAIT
, MT_DATA
);
2068 /* Out of space GAK! we are in big trouble. */
2071 /* setup and insert in middle */
2072 tmp
->m_next
= m
->m_next
;
2073 tmp
->m_len
= padlen
;
2075 dp
= mtod(tmp
, u_int8_t
*);
2077 /* zero out the pad */
2078 for (i
= 0; i
< padlen
; i
++) {
2086 sctp_pad_lastmbuf(struct mbuf
*m
, int padval
)
2088 /* find the last mbuf in chain and pad it */
2092 if (m_at
->m_next
== NULL
) {
2093 return (sctp_add_pad_tombuf(m_at
, padval
));
2095 m_at
= m_at
->m_next
;
2101 sctp_notify_assoc_change(u_int32_t event
, struct sctp_tcb
*stcb
,
2104 struct mbuf
*m_notify
;
2105 struct sctp_assoc_change
*sac
;
2106 struct sockaddr
*to
;
2107 struct sockaddr_in6 sin6
, lsa6
;
2110 * First if we are are going down dump everything we
2111 * can to the socket rcv queue.
2113 if ((event
== SCTP_SHUTDOWN_COMP
) || (event
== SCTP_COMM_LOST
)) {
2114 sctp_deliver_data(stcb
, &stcb
->asoc
, NULL
, 0);
2118 * For TCP model AND UDP connected sockets we will send
2119 * an error up when an ABORT comes in.
2121 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) ||
2122 (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)) &&
2123 (event
== SCTP_COMM_LOST
)) {
2124 stcb
->sctp_socket
->so_error
= ECONNRESET
;
2125 /* Wake ANY sleepers */
2126 sowwakeup(stcb
->sctp_socket
);
2127 sorwakeup(stcb
->sctp_socket
);
2130 if ((event
== SCTP_COMM_UP
) &&
2131 (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) &&
2132 (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
)) {
2133 soisconnected(stcb
->sctp_socket
);
2136 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_RECVASSOCEVNT
)) {
2137 /* event not enabled */
2140 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2141 if (m_notify
== NULL
)
2144 m_notify
->m_len
= 0;
2146 sac
= mtod(m_notify
, struct sctp_assoc_change
*);
2147 sac
->sac_type
= SCTP_ASSOC_CHANGE
;
2149 sac
->sac_length
= sizeof(struct sctp_assoc_change
);
2150 sac
->sac_state
= event
;
2151 sac
->sac_error
= error
;
2152 /* XXX verify these stream counts */
2153 sac
->sac_outbound_streams
= stcb
->asoc
.streamoutcnt
;
2154 sac
->sac_inbound_streams
= stcb
->asoc
.streamincnt
;
2155 sac
->sac_assoc_id
= sctp_get_associd(stcb
);
2157 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2158 m_notify
->m_pkthdr
.len
= sizeof(struct sctp_assoc_change
);
2159 m_notify
->m_pkthdr
.rcvif
= 0;
2160 m_notify
->m_len
= sizeof(struct sctp_assoc_change
);
2161 m_notify
->m_next
= NULL
;
2163 /* append to socket */
2164 to
= (struct sockaddr
*)&stcb
->asoc
.primary_destination
->ro
._l_addr
;
2165 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2166 to
->sa_family
== AF_INET
) {
2167 struct sockaddr_in
*sin
;
2169 sin
= (struct sockaddr_in
*)to
;
2170 bzero(&sin6
, sizeof(sin6
));
2171 sin6
.sin6_family
= AF_INET6
;
2172 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2173 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2174 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2175 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2176 sin6
.sin6_port
= sin
->sin_port
;
2177 to
= (struct sockaddr
*)&sin6
;
2179 /* check and strip embedded scope junk */
2180 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2183 * We need to always notify comm changes.
2184 * if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2185 * sctp_m_freem(m_notify);
2189 SCTP_TCB_UNLOCK(stcb
);
2190 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2191 SCTP_TCB_LOCK(stcb
);
2192 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
,
2193 to
, m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2194 /* not enough room */
2195 sctp_m_freem(m_notify
);
2196 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2199 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2200 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2201 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2202 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2205 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2207 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2208 /* Wake up any sleeper */
2209 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2210 sctp_sowwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2214 sctp_notify_peer_addr_change(struct sctp_tcb
*stcb
, uint32_t state
,
2215 struct sockaddr
*sa
, uint32_t error
)
2217 struct mbuf
*m_notify
;
2218 struct sctp_paddr_change
*spc
;
2219 struct sockaddr
*to
;
2220 struct sockaddr_in6 sin6
, lsa6
;
2222 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_RECVPADDREVNT
))
2223 /* event not enabled */
2226 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2227 if (m_notify
== NULL
)
2229 m_notify
->m_len
= 0;
2231 MCLGET(m_notify
, MB_DONTWAIT
);
2232 if ((m_notify
->m_flags
& M_EXT
) != M_EXT
) {
2233 sctp_m_freem(m_notify
);
2237 spc
= mtod(m_notify
, struct sctp_paddr_change
*);
2238 spc
->spc_type
= SCTP_PEER_ADDR_CHANGE
;
2240 spc
->spc_length
= sizeof(struct sctp_paddr_change
);
2241 if (sa
->sa_family
== AF_INET
) {
2242 memcpy(&spc
->spc_aaddr
, sa
, sizeof(struct sockaddr_in
));
2244 memcpy(&spc
->spc_aaddr
, sa
, sizeof(struct sockaddr_in6
));
2246 spc
->spc_state
= state
;
2247 spc
->spc_error
= error
;
2248 spc
->spc_assoc_id
= sctp_get_associd(stcb
);
2250 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2251 m_notify
->m_pkthdr
.len
= sizeof(struct sctp_paddr_change
);
2252 m_notify
->m_pkthdr
.rcvif
= 0;
2253 m_notify
->m_len
= sizeof(struct sctp_paddr_change
);
2254 m_notify
->m_next
= NULL
;
2256 to
= (struct sockaddr
*)(struct sockaddr
*)
2257 &stcb
->asoc
.primary_destination
->ro
._l_addr
;
2258 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2259 to
->sa_family
== AF_INET
) {
2260 struct sockaddr_in
*sin
;
2262 sin
= (struct sockaddr_in
*)to
;
2263 bzero(&sin6
, sizeof(sin6
));
2264 sin6
.sin6_family
= AF_INET6
;
2265 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2266 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2267 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2268 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2269 sin6
.sin6_port
= sin
->sin_port
;
2270 to
= (struct sockaddr
*)&sin6
;
2272 /* check and strip embedded scope junk */
2273 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2276 if (sctp_sbspace(&stcb
->sctp_socket
->so_rcv
) < m_notify
->m_len
) {
2277 sctp_m_freem(m_notify
);
2280 /* append to socket */
2281 SCTP_TCB_UNLOCK(stcb
);
2282 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2283 SCTP_TCB_LOCK(stcb
);
2284 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
, to
,
2285 m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2286 /* not enough room */
2287 sctp_m_freem(m_notify
);
2288 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2291 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2292 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2293 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2294 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2297 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2299 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2300 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2305 sctp_notify_send_failed(struct sctp_tcb
*stcb
, u_int32_t error
,
2306 struct sctp_tmit_chunk
*chk
)
2308 struct mbuf
*m_notify
;
2309 struct sctp_send_failed
*ssf
;
2310 struct sockaddr_in6 sin6
, lsa6
;
2311 struct sockaddr
*to
;
2314 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_RECVSENDFAILEVNT
))
2315 /* event not enabled */
2318 length
= sizeof(struct sctp_send_failed
) + chk
->send_size
;
2319 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2320 if (m_notify
== NULL
)
2323 m_notify
->m_len
= 0;
2324 ssf
= mtod(m_notify
, struct sctp_send_failed
*);
2325 ssf
->ssf_type
= SCTP_SEND_FAILED
;
2326 if (error
== SCTP_NOTIFY_DATAGRAM_UNSENT
)
2327 ssf
->ssf_flags
= SCTP_DATA_UNSENT
;
2329 ssf
->ssf_flags
= SCTP_DATA_SENT
;
2330 ssf
->ssf_length
= length
;
2331 ssf
->ssf_error
= error
;
2332 /* not exactly what the user sent in, but should be close :) */
2333 ssf
->ssf_info
.sinfo_stream
= chk
->rec
.data
.stream_number
;
2334 ssf
->ssf_info
.sinfo_ssn
= chk
->rec
.data
.stream_seq
;
2335 ssf
->ssf_info
.sinfo_flags
= chk
->rec
.data
.rcv_flags
;
2336 ssf
->ssf_info
.sinfo_ppid
= chk
->rec
.data
.payloadtype
;
2337 ssf
->ssf_info
.sinfo_context
= chk
->rec
.data
.context
;
2338 ssf
->ssf_info
.sinfo_assoc_id
= sctp_get_associd(stcb
);
2339 ssf
->ssf_assoc_id
= sctp_get_associd(stcb
);
2340 m_notify
->m_next
= chk
->data
;
2341 if (m_notify
->m_next
== NULL
)
2342 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2345 m_notify
->m_flags
|= M_NOTIFICATION
;
2347 while (m
->m_next
!= NULL
)
2349 m
->m_flags
|= M_EOR
;
2351 m_notify
->m_pkthdr
.len
= length
;
2352 m_notify
->m_pkthdr
.rcvif
= 0;
2353 m_notify
->m_len
= sizeof(struct sctp_send_failed
);
2355 /* Steal off the mbuf */
2357 to
= (struct sockaddr
*)(struct sockaddr
*)&stcb
->asoc
.primary_destination
->ro
._l_addr
;
2358 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2359 to
->sa_family
== AF_INET
) {
2360 struct sockaddr_in
*sin
;
2362 sin
= (struct sockaddr_in
*)to
;
2363 bzero(&sin6
, sizeof(sin6
));
2364 sin6
.sin6_family
= AF_INET6
;
2365 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2366 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2367 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2368 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2369 sin6
.sin6_port
= sin
->sin_port
;
2370 to
= (struct sockaddr
*)&sin6
;
2372 /* check and strip embedded scope junk */
2373 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2376 if (sctp_sbspace(&stcb
->sctp_socket
->so_rcv
) < m_notify
->m_len
) {
2377 sctp_m_freem(m_notify
);
2381 /* append to socket */
2382 SCTP_TCB_UNLOCK(stcb
);
2383 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2384 SCTP_TCB_LOCK(stcb
);
2385 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
, to
,
2386 m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2387 /* not enough room */
2388 sctp_m_freem(m_notify
);
2389 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2392 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2393 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2394 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2395 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2398 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2400 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2401 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2405 sctp_notify_adaption_layer(struct sctp_tcb
*stcb
,
2408 struct mbuf
*m_notify
;
2409 struct sctp_adaption_event
*sai
;
2410 struct sockaddr_in6 sin6
, lsa6
;
2411 struct sockaddr
*to
;
2413 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_ADAPTIONEVNT
))
2414 /* event not enabled */
2417 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2418 if (m_notify
== NULL
)
2421 m_notify
->m_len
= 0;
2422 sai
= mtod(m_notify
, struct sctp_adaption_event
*);
2423 sai
->sai_type
= SCTP_ADAPTION_INDICATION
;
2425 sai
->sai_length
= sizeof(struct sctp_adaption_event
);
2426 sai
->sai_adaption_ind
= error
;
2427 sai
->sai_assoc_id
= sctp_get_associd(stcb
);
2429 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2430 m_notify
->m_pkthdr
.len
= sizeof(struct sctp_adaption_event
);
2431 m_notify
->m_pkthdr
.rcvif
= 0;
2432 m_notify
->m_len
= sizeof(struct sctp_adaption_event
);
2433 m_notify
->m_next
= NULL
;
2435 to
= (struct sockaddr
*)(struct sockaddr
*)&stcb
->asoc
.primary_destination
->ro
._l_addr
;
2436 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2437 (to
->sa_family
== AF_INET
)) {
2438 struct sockaddr_in
*sin
;
2440 sin
= (struct sockaddr_in
*)to
;
2441 bzero(&sin6
, sizeof(sin6
));
2442 sin6
.sin6_family
= AF_INET6
;
2443 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2444 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2445 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2446 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2447 sin6
.sin6_port
= sin
->sin_port
;
2448 to
= (struct sockaddr
*)&sin6
;
2450 /* check and strip embedded scope junk */
2451 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2453 if (sctp_sbspace(&stcb
->sctp_socket
->so_rcv
) < m_notify
->m_len
) {
2454 sctp_m_freem(m_notify
);
2457 /* append to socket */
2458 SCTP_TCB_UNLOCK(stcb
);
2459 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2460 SCTP_TCB_LOCK(stcb
);
2461 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
, to
,
2462 m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2463 /* not enough room */
2464 sctp_m_freem(m_notify
);
2465 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2468 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2469 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2470 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2471 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2474 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2476 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2477 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2481 sctp_notify_partial_delivery_indication(struct sctp_tcb
*stcb
,
2484 struct mbuf
*m_notify
;
2485 struct sctp_pdapi_event
*pdapi
;
2486 struct sockaddr_in6 sin6
, lsa6
;
2487 struct sockaddr
*to
;
2489 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_PDAPIEVNT
))
2490 /* event not enabled */
2493 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2494 if (m_notify
== NULL
)
2497 m_notify
->m_len
= 0;
2498 pdapi
= mtod(m_notify
, struct sctp_pdapi_event
*);
2499 pdapi
->pdapi_type
= SCTP_PARTIAL_DELIVERY_EVENT
;
2500 pdapi
->pdapi_flags
= 0;
2501 pdapi
->pdapi_length
= sizeof(struct sctp_pdapi_event
);
2502 pdapi
->pdapi_indication
= error
;
2503 pdapi
->pdapi_assoc_id
= sctp_get_associd(stcb
);
2505 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2506 m_notify
->m_pkthdr
.len
= sizeof(struct sctp_pdapi_event
);
2507 m_notify
->m_pkthdr
.rcvif
= 0;
2508 m_notify
->m_len
= sizeof(struct sctp_pdapi_event
);
2509 m_notify
->m_next
= NULL
;
2511 to
= (struct sockaddr
*)(struct sockaddr
*)&stcb
->asoc
.primary_destination
->ro
._l_addr
;
2512 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2513 (to
->sa_family
== AF_INET
)) {
2514 struct sockaddr_in
*sin
;
2516 sin
= (struct sockaddr_in
*)to
;
2517 bzero(&sin6
, sizeof(sin6
));
2518 sin6
.sin6_family
= AF_INET6
;
2519 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2520 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2521 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2522 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2523 sin6
.sin6_port
= sin
->sin_port
;
2524 to
= (struct sockaddr
*)&sin6
;
2526 /* check and strip embedded scope junk */
2527 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2529 if (sctp_sbspace(&stcb
->sctp_socket
->so_rcv
) < m_notify
->m_len
) {
2530 sctp_m_freem(m_notify
);
2533 /* append to socket */
2534 SCTP_TCB_UNLOCK(stcb
);
2535 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2536 SCTP_TCB_LOCK(stcb
);
2537 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
, to
,
2538 m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2539 /* not enough room */
2540 sctp_m_freem(m_notify
);
2541 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2544 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2545 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2546 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2547 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2550 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2552 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2553 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2557 sctp_notify_shutdown_event(struct sctp_tcb
*stcb
)
2559 struct mbuf
*m_notify
;
2560 struct sctp_shutdown_event
*sse
;
2561 struct sockaddr_in6 sin6
, lsa6
;
2562 struct sockaddr
*to
;
2565 * For TCP model AND UDP connected sockets we will send
2566 * an error up when an SHUTDOWN completes
2568 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) ||
2569 (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)) {
2570 /* mark socket closed for read/write and wakeup! */
2571 socantrcvmore(stcb
->sctp_socket
);
2572 socantsendmore(stcb
->sctp_socket
);
2575 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT
))
2576 /* event not enabled */
2579 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2580 if (m_notify
== NULL
)
2583 m_notify
->m_len
= 0;
2584 sse
= mtod(m_notify
, struct sctp_shutdown_event
*);
2585 sse
->sse_type
= SCTP_SHUTDOWN_EVENT
;
2587 sse
->sse_length
= sizeof(struct sctp_shutdown_event
);
2588 sse
->sse_assoc_id
= sctp_get_associd(stcb
);
2590 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2591 m_notify
->m_pkthdr
.len
= sizeof(struct sctp_shutdown_event
);
2592 m_notify
->m_pkthdr
.rcvif
= 0;
2593 m_notify
->m_len
= sizeof(struct sctp_shutdown_event
);
2594 m_notify
->m_next
= NULL
;
2596 to
= (struct sockaddr
*)(struct sockaddr
*)&stcb
->asoc
.primary_destination
->ro
._l_addr
;
2597 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2598 to
->sa_family
== AF_INET
) {
2599 struct sockaddr_in
*sin
;
2601 sin
= (struct sockaddr_in
*)to
;
2602 bzero(&sin6
, sizeof(sin6
));
2603 sin6
.sin6_family
= AF_INET6
;
2604 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2605 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2606 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2607 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2608 sin6
.sin6_port
= sin
->sin_port
;
2609 to
= (struct sockaddr
*)&sin6
;
2611 /* check and strip embedded scope junk */
2612 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2614 if (sctp_sbspace(&stcb
->sctp_socket
->so_rcv
) < m_notify
->m_len
) {
2615 sctp_m_freem(m_notify
);
2618 /* append to socket */
2619 SCTP_TCB_UNLOCK(stcb
);
2620 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2621 SCTP_TCB_LOCK(stcb
);
2622 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
, to
,
2623 m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2624 /* not enough room */
2625 sctp_m_freem(m_notify
);
2626 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2629 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2630 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2631 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2632 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2635 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2637 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2638 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2642 sctp_notify_stream_reset(struct sctp_tcb
*stcb
,
2643 int number_entries
, uint16_t *list
, int flag
)
2645 struct mbuf
*m_notify
;
2646 struct sctp_stream_reset_event
*strreset
;
2647 struct sockaddr_in6 sin6
, lsa6
;
2648 struct sockaddr
*to
;
2651 if (!(stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_STREAM_RESETEVNT
))
2652 /* event not enabled */
2655 MGETHDR(m_notify
, MB_DONTWAIT
, MT_DATA
);
2656 if (m_notify
== NULL
)
2659 m_notify
->m_len
= 0;
2660 len
= sizeof(struct sctp_stream_reset_event
) + (number_entries
* sizeof(uint16_t));
2661 if (len
> M_TRAILINGSPACE(m_notify
)) {
2662 MCLGET(m_notify
, MB_WAIT
);
2664 if (m_notify
== NULL
)
2668 if (len
> M_TRAILINGSPACE(m_notify
)) {
2669 /* never enough room */
2673 strreset
= mtod(m_notify
, struct sctp_stream_reset_event
*);
2674 strreset
->strreset_type
= SCTP_STREAM_RESET_EVENT
;
2675 if (number_entries
== 0) {
2676 strreset
->strreset_flags
= flag
| SCTP_STRRESET_ALL_STREAMS
;
2678 strreset
->strreset_flags
= flag
| SCTP_STRRESET_STREAM_LIST
;
2680 strreset
->strreset_length
= len
;
2681 strreset
->strreset_assoc_id
= sctp_get_associd(stcb
);
2682 if (number_entries
) {
2684 for (i
=0; i
<number_entries
; i
++) {
2685 strreset
->strreset_list
[i
] = list
[i
];
2688 m_notify
->m_flags
|= M_EOR
| M_NOTIFICATION
;
2689 m_notify
->m_pkthdr
.len
= len
;
2690 m_notify
->m_pkthdr
.rcvif
= 0;
2691 m_notify
->m_len
= len
;
2692 m_notify
->m_next
= NULL
;
2693 if (sctp_sbspace(&stcb
->sctp_socket
->so_rcv
) < m_notify
->m_len
) {
2695 sctp_m_freem(m_notify
);
2698 to
= (struct sockaddr
*)(struct sockaddr
*)&stcb
->asoc
.primary_destination
->ro
._l_addr
;
2699 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_NEEDS_MAPPED_V4
) &&
2700 to
->sa_family
== AF_INET
) {
2701 struct sockaddr_in
*sin
;
2703 sin
= (struct sockaddr_in
*)to
;
2704 bzero(&sin6
, sizeof(sin6
));
2705 sin6
.sin6_family
= AF_INET6
;
2706 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
2707 sin6
.sin6_addr
.s6_addr16
[2] = 0xffff;
2708 bcopy(&sin
->sin_addr
, &sin6
.sin6_addr
.s6_addr16
[3],
2709 sizeof(sin6
.sin6_addr
.s6_addr16
[3]));
2710 sin6
.sin6_port
= sin
->sin_port
;
2711 to
= (struct sockaddr
*)&sin6
;
2713 /* check and strip embedded scope junk */
2714 to
= (struct sockaddr
*)sctp_recover_scope((struct sockaddr_in6
*)to
,
2716 /* append to socket */
2717 SCTP_TCB_UNLOCK(stcb
);
2718 SCTP_INP_WLOCK(stcb
->sctp_ep
);
2719 SCTP_TCB_LOCK(stcb
);
2720 if (!sctp_sbappendaddr_nocheck(&stcb
->sctp_socket
->so_rcv
, to
,
2721 m_notify
, NULL
, stcb
->asoc
.my_vtag
, stcb
->sctp_ep
)) {
2722 /* not enough room */
2723 sctp_m_freem(m_notify
);
2724 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2727 if (((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
) == 0) &&
2728 ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_CONNECTED
) == 0)){
2729 if (sctp_add_to_socket_q(stcb
->sctp_ep
, stcb
)) {
2730 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2733 stcb
->asoc
.my_rwnd_control_len
+= sizeof(struct mbuf
);
2735 SCTP_INP_WUNLOCK(stcb
->sctp_ep
);
2736 sctp_sorwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
2741 sctp_ulp_notify(u_int32_t notification
, struct sctp_tcb
*stcb
,
2742 u_int32_t error
, void *data
)
2744 if (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) {
2745 /* No notifications up when we are in a no socket state */
2748 if (stcb
->asoc
.state
& SCTP_STATE_CLOSED_SOCKET
) {
2749 /* Can't send up to a closed socket any notifications */
2752 switch (notification
) {
2753 case SCTP_NOTIFY_ASSOC_UP
:
2754 sctp_notify_assoc_change(SCTP_COMM_UP
, stcb
, error
);
2756 case SCTP_NOTIFY_ASSOC_DOWN
:
2757 sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP
, stcb
, error
);
2759 case SCTP_NOTIFY_INTERFACE_DOWN
:
2761 struct sctp_nets
*net
;
2762 net
= (struct sctp_nets
*)data
;
2763 sctp_notify_peer_addr_change(stcb
, SCTP_ADDR_UNREACHABLE
,
2764 (struct sockaddr
*)&net
->ro
._l_addr
, error
);
2767 case SCTP_NOTIFY_INTERFACE_UP
:
2769 struct sctp_nets
*net
;
2770 net
= (struct sctp_nets
*)data
;
2771 sctp_notify_peer_addr_change(stcb
, SCTP_ADDR_AVAILABLE
,
2772 (struct sockaddr
*)&net
->ro
._l_addr
, error
);
2775 case SCTP_NOTIFY_INTERFACE_CONFIRMED
:
2777 struct sctp_nets
*net
;
2778 net
= (struct sctp_nets
*)data
;
2779 sctp_notify_peer_addr_change(stcb
, SCTP_ADDR_CONFIRMED
,
2780 (struct sockaddr
*)&net
->ro
._l_addr
, error
);
2783 case SCTP_NOTIFY_DG_FAIL
:
2784 sctp_notify_send_failed(stcb
, error
,
2785 (struct sctp_tmit_chunk
*)data
);
2787 case SCTP_NOTIFY_ADAPTION_INDICATION
:
2788 /* Here the error is the adaption indication */
2789 sctp_notify_adaption_layer(stcb
, error
);
2791 case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION
:
2792 sctp_notify_partial_delivery_indication(stcb
, error
);
2794 case SCTP_NOTIFY_STRDATA_ERR
:
2796 case SCTP_NOTIFY_ASSOC_ABORTED
:
2797 sctp_notify_assoc_change(SCTP_COMM_LOST
, stcb
, error
);
2799 case SCTP_NOTIFY_PEER_OPENED_STREAM
:
2801 case SCTP_NOTIFY_STREAM_OPENED_OK
:
2803 case SCTP_NOTIFY_ASSOC_RESTART
:
2804 sctp_notify_assoc_change(SCTP_RESTART
, stcb
, error
);
2806 case SCTP_NOTIFY_HB_RESP
:
2808 case SCTP_NOTIFY_STR_RESET_SEND
:
2809 sctp_notify_stream_reset(stcb
, error
, ((uint16_t *)data
), SCTP_STRRESET_OUTBOUND_STR
);
2811 case SCTP_NOTIFY_STR_RESET_RECV
:
2812 sctp_notify_stream_reset(stcb
, error
, ((uint16_t *)data
), SCTP_STRRESET_INBOUND_STR
);
2814 case SCTP_NOTIFY_ASCONF_ADD_IP
:
2815 sctp_notify_peer_addr_change(stcb
, SCTP_ADDR_ADDED
, data
,
2818 case SCTP_NOTIFY_ASCONF_DELETE_IP
:
2819 sctp_notify_peer_addr_change(stcb
, SCTP_ADDR_REMOVED
, data
,
2822 case SCTP_NOTIFY_ASCONF_SET_PRIMARY
:
2823 sctp_notify_peer_addr_change(stcb
, SCTP_ADDR_MADE_PRIM
, data
,
2826 case SCTP_NOTIFY_ASCONF_SUCCESS
:
2828 case SCTP_NOTIFY_ASCONF_FAILED
:
2830 case SCTP_NOTIFY_PEER_SHUTDOWN
:
2831 sctp_notify_shutdown_event(stcb
);
2835 if (sctp_debug_on
& SCTP_DEBUG_UTIL1
) {
2836 kprintf("NOTIFY: unknown notification %xh (%u)\n",
2837 notification
, notification
);
2839 #endif /* SCTP_DEBUG */
2845 sctp_report_all_outbound(struct sctp_tcb
*stcb
)
2847 struct sctp_association
*asoc
;
2848 struct sctp_stream_out
*outs
;
2849 struct sctp_tmit_chunk
*chk
;
2853 if (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) {
2856 /* now through all the gunk freeing chunks */
2857 TAILQ_FOREACH(outs
, &asoc
->out_wheel
, next_spoke
) {
2858 /* now clean up any chunks here */
2859 chk
= TAILQ_FIRST(&outs
->outqueue
);
2861 stcb
->asoc
.stream_queue_cnt
--;
2862 TAILQ_REMOVE(&outs
->outqueue
, chk
, sctp_next
);
2863 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL
, stcb
,
2864 SCTP_NOTIFY_DATAGRAM_UNSENT
, chk
);
2866 sctp_m_freem(chk
->data
);
2870 sctp_free_remote_addr(chk
->whoTo
);
2873 /* Free the chunk */
2874 SCTP_ZONE_FREE(sctppcbinfo
.ipi_zone_chunk
, chk
);
2875 sctppcbinfo
.ipi_count_chunk
--;
2876 if ((int)sctppcbinfo
.ipi_count_chunk
< 0) {
2877 panic("Chunk count is negative");
2879 sctppcbinfo
.ipi_gencnt_chunk
++;
2880 chk
= TAILQ_FIRST(&outs
->outqueue
);
2883 /* pending send queue SHOULD be empty */
2884 if (!TAILQ_EMPTY(&asoc
->send_queue
)) {
2885 chk
= TAILQ_FIRST(&asoc
->send_queue
);
2887 TAILQ_REMOVE(&asoc
->send_queue
, chk
, sctp_next
);
2888 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL
, stcb
, SCTP_NOTIFY_DATAGRAM_UNSENT
, chk
);
2890 sctp_m_freem(chk
->data
);
2894 sctp_free_remote_addr(chk
->whoTo
);
2896 SCTP_ZONE_FREE(sctppcbinfo
.ipi_zone_chunk
, chk
);
2897 sctppcbinfo
.ipi_count_chunk
--;
2898 if ((int)sctppcbinfo
.ipi_count_chunk
< 0) {
2899 panic("Chunk count is negative");
2901 sctppcbinfo
.ipi_gencnt_chunk
++;
2902 chk
= TAILQ_FIRST(&asoc
->send_queue
);
2905 /* sent queue SHOULD be empty */
2906 if (!TAILQ_EMPTY(&asoc
->sent_queue
)) {
2907 chk
= TAILQ_FIRST(&asoc
->sent_queue
);
2909 TAILQ_REMOVE(&asoc
->sent_queue
, chk
, sctp_next
);
2910 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL
, stcb
,
2911 SCTP_NOTIFY_DATAGRAM_SENT
, chk
);
2913 sctp_m_freem(chk
->data
);
2917 sctp_free_remote_addr(chk
->whoTo
);
2919 SCTP_ZONE_FREE(sctppcbinfo
.ipi_zone_chunk
, chk
);
2920 sctppcbinfo
.ipi_count_chunk
--;
2921 if ((int)sctppcbinfo
.ipi_count_chunk
< 0) {
2922 panic("Chunk count is negative");
2924 sctppcbinfo
.ipi_gencnt_chunk
++;
2925 chk
= TAILQ_FIRST(&asoc
->sent_queue
);
2931 sctp_abort_notification(struct sctp_tcb
*stcb
, int error
)
2934 if (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) {
2937 /* Tell them we lost the asoc */
2938 sctp_report_all_outbound(stcb
);
2939 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED
, stcb
, error
, NULL
);
2943 sctp_abort_association(struct sctp_inpcb
*inp
, struct sctp_tcb
*stcb
,
2944 struct mbuf
*m
, int iphlen
, struct sctphdr
*sh
, struct mbuf
*op_err
)
2950 /* We have a TCB to abort, send notification too */
2951 vtag
= stcb
->asoc
.peer_vtag
;
2952 sctp_abort_notification(stcb
, 0);
2954 sctp_send_abort(m
, iphlen
, sh
, vtag
, op_err
);
2956 /* Ok, now lets free it */
2957 sctp_free_assoc(inp
, stcb
);
2959 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) {
2960 if (LIST_FIRST(&inp
->sctp_asoc_list
) == NULL
) {
2961 sctp_inpcb_free(inp
, 1);
2968 sctp_abort_an_association(struct sctp_inpcb
*inp
, struct sctp_tcb
*stcb
,
2969 int error
, struct mbuf
*op_err
)
2974 /* Got to have a TCB */
2975 if (inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) {
2976 if (LIST_FIRST(&inp
->sctp_asoc_list
) == NULL
) {
2977 sctp_inpcb_free(inp
, 1);
2982 vtag
= stcb
->asoc
.peer_vtag
;
2983 /* notify the ulp */
2984 if ((inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
) == 0)
2985 sctp_abort_notification(stcb
, error
);
2986 /* notify the peer */
2987 sctp_send_abort_tcb(stcb
, op_err
);
2988 /* now free the asoc */
2989 sctp_free_assoc(inp
, stcb
);
2993 sctp_handle_ootb(struct mbuf
*m
, int iphlen
, int offset
, struct sctphdr
*sh
,
2994 struct sctp_inpcb
*inp
, struct mbuf
*op_err
)
2996 struct sctp_chunkhdr
*ch
, chunk_buf
;
2997 unsigned int chk_length
;
2999 /* Generate a TO address for future reference */
3000 if (inp
&& (inp
->sctp_flags
& SCTP_PCB_FLAGS_SOCKET_GONE
)) {
3001 if (LIST_FIRST(&inp
->sctp_asoc_list
) == NULL
) {
3002 sctp_inpcb_free(inp
, 1);
3005 ch
= (struct sctp_chunkhdr
*)sctp_m_getptr(m
, offset
,
3006 sizeof(*ch
), (u_int8_t
*)&chunk_buf
);
3007 while (ch
!= NULL
) {
3008 chk_length
= ntohs(ch
->chunk_length
);
3009 if (chk_length
< sizeof(*ch
)) {
3010 /* break to abort land */
3013 switch (ch
->chunk_type
) {
3014 case SCTP_PACKET_DROPPED
:
3015 /* we don't respond to pkt-dropped */
3017 case SCTP_ABORT_ASSOCIATION
:
3018 /* we don't respond with an ABORT to an ABORT */
3020 case SCTP_SHUTDOWN_COMPLETE
:
3022 * we ignore it since we are not waiting for it
3026 case SCTP_SHUTDOWN_ACK
:
3027 sctp_send_shutdown_complete2(m
, iphlen
, sh
);
3032 offset
+= SCTP_SIZE32(chk_length
);
3033 ch
= (struct sctp_chunkhdr
*)sctp_m_getptr(m
, offset
,
3034 sizeof(*ch
), (u_int8_t
*)&chunk_buf
);
3036 sctp_send_abort(m
, iphlen
, sh
, 0, op_err
);
3040 * check the inbound datagram to make sure there is not an abort
3041 * inside it, if there is return 1, else return 0.
3044 sctp_is_there_an_abort_here(struct mbuf
*m
, int iphlen
, int *vtagfill
)
3046 struct sctp_chunkhdr
*ch
;
3047 struct sctp_init_chunk
*init_chk
, chunk_buf
;
3049 unsigned int chk_length
;
3051 offset
= iphlen
+ sizeof(struct sctphdr
);
3052 ch
= (struct sctp_chunkhdr
*)sctp_m_getptr(m
, offset
, sizeof(*ch
),
3053 (u_int8_t
*)&chunk_buf
);
3054 while (ch
!= NULL
) {
3055 chk_length
= ntohs(ch
->chunk_length
);
3056 if (chk_length
< sizeof(*ch
)) {
3057 /* packet is probably corrupt */
3060 /* we seem to be ok, is it an abort? */
3061 if (ch
->chunk_type
== SCTP_ABORT_ASSOCIATION
) {
3062 /* yep, tell them */
3065 if (ch
->chunk_type
== SCTP_INITIATION
) {
3066 /* need to update the Vtag */
3067 init_chk
= (struct sctp_init_chunk
*)sctp_m_getptr(m
,
3068 offset
, sizeof(*init_chk
), (u_int8_t
*)&chunk_buf
);
3069 if (init_chk
!= NULL
) {
3070 *vtagfill
= ntohl(init_chk
->init
.initiate_tag
);
3073 /* Nope, move to the next chunk */
3074 offset
+= SCTP_SIZE32(chk_length
);
3075 ch
= (struct sctp_chunkhdr
*)sctp_m_getptr(m
, offset
,
3076 sizeof(*ch
), (u_int8_t
*)&chunk_buf
);
3082 * currently (2/02), ifa_addr embeds scope_id's and don't
3083 * have sin6_scope_id set (i.e. it's 0)
3084 * so, create this function to compare link local scopes
3087 sctp_is_same_scope(struct sockaddr_in6
*addr1
, struct sockaddr_in6
*addr2
)
3089 struct sockaddr_in6 a
, b
;
3095 if (a
.sin6_scope_id
== 0)
3096 if (in6_recoverscope(&a
, &a
.sin6_addr
, NULL
)) {
3097 /* can't get scope, so can't match */
3100 if (b
.sin6_scope_id
== 0)
3101 if (in6_recoverscope(&b
, &b
.sin6_addr
, NULL
)) {
3102 /* can't get scope, so can't match */
3105 if (a
.sin6_scope_id
!= b
.sin6_scope_id
)
3112 * returns a sockaddr_in6 with embedded scope recovered and removed
3114 struct sockaddr_in6
*
3115 sctp_recover_scope(struct sockaddr_in6
*addr
, struct sockaddr_in6
*store
)
3118 /* check and strip embedded scope junk */
3119 if (addr
->sin6_family
== AF_INET6
) {
3120 if (IN6_IS_SCOPE_LINKLOCAL(&addr
->sin6_addr
)) {
3121 if (addr
->sin6_scope_id
== 0) {
3123 if (!in6_recoverscope(store
, &store
->sin6_addr
,
3125 /* use the recovered scope */
3128 /* else, return the original "to" addr */
3136 * are the two addresses the same? currently a "scopeless" check
3137 * returns: 1 if same, 0 if not
3140 sctp_cmpaddr(struct sockaddr
*sa1
, struct sockaddr
*sa2
)
3144 if (sa1
== NULL
|| sa2
== NULL
)
3147 /* must be the same family */
3148 if (sa1
->sa_family
!= sa2
->sa_family
)
3151 if (sa1
->sa_family
== AF_INET6
) {
3152 /* IPv6 addresses */
3153 struct sockaddr_in6
*sin6_1
, *sin6_2
;
3155 sin6_1
= (struct sockaddr_in6
*)sa1
;
3156 sin6_2
= (struct sockaddr_in6
*)sa2
;
3157 return (SCTP6_ARE_ADDR_EQUAL(&sin6_1
->sin6_addr
,
3158 &sin6_2
->sin6_addr
));
3159 } else if (sa1
->sa_family
== AF_INET
) {
3160 /* IPv4 addresses */
3161 struct sockaddr_in
*sin_1
, *sin_2
;
3163 sin_1
= (struct sockaddr_in
*)sa1
;
3164 sin_2
= (struct sockaddr_in
*)sa2
;
3165 return (sin_1
->sin_addr
.s_addr
== sin_2
->sin_addr
.s_addr
);
3167 /* we don't do these... */
3173 sctp_print_address(struct sockaddr
*sa
)
3176 if (sa
->sa_family
== AF_INET6
) {
3177 struct sockaddr_in6
*sin6
;
3178 sin6
= (struct sockaddr_in6
*)sa
;
3179 kprintf("IPv6 address: %s:%d scope:%u\n",
3180 ip6_sprintf(&sin6
->sin6_addr
), ntohs(sin6
->sin6_port
),
3181 sin6
->sin6_scope_id
);
3182 } else if (sa
->sa_family
== AF_INET
) {
3183 struct sockaddr_in
*sin
;
3184 sin
= (struct sockaddr_in
*)sa
;
3185 kprintf("IPv4 address: %s:%d\n", inet_ntoa(sin
->sin_addr
),
3186 ntohs(sin
->sin_port
));
3193 sctp_print_address_pkt(struct ip
*iph
, struct sctphdr
*sh
)
3195 if (iph
->ip_v
== IPVERSION
) {
3196 struct sockaddr_in lsa
, fsa
;
3198 bzero(&lsa
, sizeof(lsa
));
3199 lsa
.sin_len
= sizeof(lsa
);
3200 lsa
.sin_family
= AF_INET
;
3201 lsa
.sin_addr
= iph
->ip_src
;
3202 lsa
.sin_port
= sh
->src_port
;
3203 bzero(&fsa
, sizeof(fsa
));
3204 fsa
.sin_len
= sizeof(fsa
);
3205 fsa
.sin_family
= AF_INET
;
3206 fsa
.sin_addr
= iph
->ip_dst
;
3207 fsa
.sin_port
= sh
->dest_port
;
3209 sctp_print_address((struct sockaddr
*)&lsa
);
3211 sctp_print_address((struct sockaddr
*)&fsa
);
3212 } else if (iph
->ip_v
== (IPV6_VERSION
>> 4)) {
3213 struct ip6_hdr
*ip6
;
3214 struct sockaddr_in6 lsa6
, fsa6
;
3216 ip6
= (struct ip6_hdr
*)iph
;
3217 bzero(&lsa6
, sizeof(lsa6
));
3218 lsa6
.sin6_len
= sizeof(lsa6
);
3219 lsa6
.sin6_family
= AF_INET6
;
3220 lsa6
.sin6_addr
= ip6
->ip6_src
;
3221 lsa6
.sin6_port
= sh
->src_port
;
3222 bzero(&fsa6
, sizeof(fsa6
));
3223 fsa6
.sin6_len
= sizeof(fsa6
);
3224 fsa6
.sin6_family
= AF_INET6
;
3225 fsa6
.sin6_addr
= ip6
->ip6_dst
;
3226 fsa6
.sin6_port
= sh
->dest_port
;
3228 sctp_print_address((struct sockaddr
*)&lsa6
);
3230 sctp_print_address((struct sockaddr
*)&fsa6
);
3234 #if defined(__FreeBSD__) || defined(__APPLE__)
3236 /* cloned from uipc_socket.c */
3238 #define SCTP_SBLINKRECORD(sb, m0) do { \
3239 if ((sb)->sb_lastrecord != NULL) \
3240 (sb)->sb_lastrecord->m_nextpkt = (m0); \
3242 (sb)->sb_mb = (m0); \
3243 (sb)->sb_lastrecord = (m0); \
3244 } while (/*CONSTCOND*/0)
3249 sctp_sbappendaddr_nocheck(struct signalsockbuf
*ssb
, struct sockaddr
*asa
, struct mbuf
*m0
,
3250 struct mbuf
*control
, u_int32_t tag
,
3251 struct sctp_inpcb
*inp
)
3253 struct mbuf
*m
, *n
, *nlast
;
3256 if (m0
&& (m0
->m_flags
& M_PKTHDR
) == 0)
3257 panic("sctp_sbappendaddr_nocheck");
3259 for (n
= control
; n
; n
= n
->m_next
) {
3260 if (n
->m_next
== 0) /* get pointer to last control buf */
3263 if (((inp
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) == 0) ||
3264 ((inp
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)== 0)) {
3265 if (asa
->sa_len
> MHLEN
)
3268 MGETHDR(m
, MB_DONTWAIT
, MT_SONAME
);
3274 kprintf("Duplicate mbuf allocated %p in and mget returned %p?\n",
3277 panic("more than once");
3282 m
->m_len
= asa
->sa_len
;
3283 bcopy((caddr_t
)asa
, mtod(m
, caddr_t
), asa
->sa_len
);
3289 n
->m_next
= m0
; /* concatenate data to control */
3293 m
->m_next
= control
;
3296 m
->m_pkthdr
.csum_data
= (int)tag
;
3299 for (n
= m
; n
; n
= n
->m_next
)
3300 sballoc(&ssb
->sb
, n
);
3302 if (ssb
->ssb_mb
== NULL
) {
3303 inp
->sctp_vtag_first
= tag
;
3305 if ((n
= ssb
->ssb_mb
) != NULL
) {
3306 if ((n
->m_nextpkt
!= inp
->sb_last_mpkt
) && (n
->m_nextpkt
== NULL
)) {
3307 inp
->sb_last_mpkt
= NULL
;
3309 if (inp
->sb_last_mpkt
)
3310 inp
->sb_last_mpkt
->m_nextpkt
= m
;
3312 while (n
->m_nextpkt
) {
3317 inp
->sb_last_mpkt
= m
;
3319 inp
->sb_last_mpkt
= ssb
->ssb_mb
= m
;
3320 inp
->sctp_vtag_first
= tag
;
3322 SOCKBUF_UNLOCK(ssb
);
3326 /*************HOLD THIS COMMENT FOR PATCH FILE OF
3327 *************ALTERNATE ROUTING CODE
3330 /*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
3331 *************ALTERNATE ROUTING CODE
3335 sctp_generate_invmanparam(int err
)
3337 /* Return a MBUF with a invalid mandatory parameter */
3340 MGET(m
, MB_DONTWAIT
, MT_DATA
);
3342 struct sctp_paramhdr
*ph
;
3343 m
->m_len
= sizeof(struct sctp_paramhdr
);
3344 ph
= mtod(m
, struct sctp_paramhdr
*);
3345 ph
->param_length
= htons(sizeof(struct sctp_paramhdr
));
3346 ph
->param_type
= htons(err
);
3352 sctp_should_be_moved(struct mbuf
*this, struct sctp_association
*asoc
)
3356 * given a mbuf chain, look through it finding
3357 * the M_PKTHDR and return 1 if it belongs to
3358 * the association given. We tell this by
3359 * a kludge where we stuff the my_vtag of the asoc
3360 * into the m->m_pkthdr.csum_data/csum field.
3364 if (m
->m_flags
& M_PKTHDR
) {
3366 #if defined(__OpenBSD__)
3367 if ((u_int32_t
)m
->m_pkthdr
.csum
== asoc
->my_vtag
)
3369 if ((u_int32_t
)m
->m_pkthdr
.csum_data
== asoc
->my_vtag
)
3382 sctp_get_first_vtag_from_sb(struct socket
*so
)
3384 struct mbuf
*this, *at
;
3388 if (so
->so_rcv
.ssb_mb
) {
3390 this = so
->so_rcv
.ssb_mb
;
3393 /* get to the m_pkthdr */
3395 if (at
->m_flags
& M_PKTHDR
)
3401 /* now do we have a m_pkthdr */
3402 if (at
&& (at
->m_flags
& M_PKTHDR
)) {
3404 #if defined(__OpenBSD__)
3405 if ((u_int32_t
)at
->m_pkthdr
.csum
!= 0)
3407 if ((u_int32_t
)at
->m_pkthdr
.csum_data
!= 0)
3411 #if defined(__OpenBSD__)
3412 retval
= (u_int32_t
)at
->m_pkthdr
.csum
;
3415 (u_int32_t
)at
->m_pkthdr
.csum_data
;
3420 this = this->m_nextpkt
;
3428 sctp_grub_through_socket_buffer(struct sctp_inpcb
*inp
, struct socket
*old
,
3429 struct socket
*new, struct sctp_tcb
*stcb
)
3431 struct mbuf
**put
, **take
, *next
, *this;
3432 struct signalsockbuf
*old_sb
, *new_sb
;
3433 struct sctp_association
*asoc
;
3437 old_sb
= &old
->so_rcv
;
3438 new_sb
= &new->so_rcv
;
3439 if (old_sb
->ssb_mb
== NULL
) {
3440 /* Nothing to move */
3443 SOCKBUF_LOCK(old_sb
);
3444 SOCKBUF_LOCK(new_sb
);
3446 if (inp
->sctp_vtag_first
== asoc
->my_vtag
) {
3447 /* First one must be moved */
3449 for (mm
= old_sb
->ssb_mb
; mm
; mm
= mm
->m_next
) {
3451 * Go down the chain and fix
3452 * the space allocation of the
3455 sbfree(&old_sb
->sb
, mm
);
3456 sballoc(&new_sb
->sb
, mm
);
3458 new_sb
->ssb_mb
= old_sb
->ssb_mb
;
3459 old_sb
->ssb_mb
= new_sb
->ssb_mb
->m_nextpkt
;
3460 new_sb
->ssb_mb
->m_nextpkt
= NULL
;
3461 put
= &new_sb
->ssb_mb
->m_nextpkt
;
3464 put
= &new_sb
->ssb_mb
;
3467 take
= &old_sb
->ssb_mb
;
3468 next
= old_sb
->ssb_mb
;
3471 /* postion for next one */
3472 next
= this->m_nextpkt
;
3473 /* check the tag of this packet */
3474 if (sctp_should_be_moved(this, asoc
)) {
3475 /* yes this needs to be moved */
3477 *take
= this->m_nextpkt
;
3478 this->m_nextpkt
= NULL
;
3480 for (mm
= this; mm
; mm
= mm
->m_next
) {
3482 * Go down the chain and fix
3483 * the space allocation of the
3486 sbfree(&old_sb
->sb
, mm
);
3487 sballoc(&new_sb
->sb
, mm
);
3489 put
= &this->m_nextpkt
;
3492 /* no advance our take point. */
3493 take
= &this->m_nextpkt
;
3498 * Ok so now we must re-postion vtag_first to
3499 * match the new first one since we moved the
3502 inp
->sctp_vtag_first
= sctp_get_first_vtag_from_sb(old
);
3504 SOCKBUF_UNLOCK(old_sb
);
3505 SOCKBUF_UNLOCK(new_sb
);
3509 sctp_free_bufspace(struct sctp_tcb
*stcb
, struct sctp_association
*asoc
,
3510 struct sctp_tmit_chunk
*tp1
)
3512 if (tp1
->data
== NULL
) {
3515 #ifdef SCTP_MBCNT_LOGGING
3516 sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE
,
3517 asoc
->total_output_queue_size
,
3519 asoc
->total_output_mbuf_queue_size
,
3522 if (asoc
->total_output_queue_size
>= tp1
->book_size
) {
3523 asoc
->total_output_queue_size
-= tp1
->book_size
;
3525 asoc
->total_output_queue_size
= 0;
3528 /* Now free the mbuf */
3529 if (asoc
->total_output_mbuf_queue_size
>= tp1
->mbcnt
) {
3530 asoc
->total_output_mbuf_queue_size
-= tp1
->mbcnt
;
3532 asoc
->total_output_mbuf_queue_size
= 0;
3534 if ((stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_TCPTYPE
) ||
3535 (stcb
->sctp_ep
->sctp_flags
& SCTP_PCB_FLAGS_IN_TCPPOOL
)) {
3536 if (stcb
->sctp_socket
->so_snd
.ssb_cc
>= tp1
->book_size
) {
3537 stcb
->sctp_socket
->so_snd
.ssb_cc
-= tp1
->book_size
;
3539 stcb
->sctp_socket
->so_snd
.ssb_cc
= 0;
3542 if (stcb
->sctp_socket
->so_snd
.ssb_mbcnt
>= tp1
->mbcnt
) {
3543 stcb
->sctp_socket
->so_snd
.ssb_mbcnt
-= tp1
->mbcnt
;
3545 stcb
->sctp_socket
->so_snd
.ssb_mbcnt
= 0;
3551 sctp_release_pr_sctp_chunk(struct sctp_tcb
*stcb
, struct sctp_tmit_chunk
*tp1
,
3552 int reason
, struct sctpchunk_listhead
*queue
)
3556 uint8_t foundeom
= 0;
3559 ret_sz
+= tp1
->book_size
;
3560 tp1
->sent
= SCTP_FORWARD_TSN_SKIP
;
3562 sctp_free_bufspace(stcb
, &stcb
->asoc
, tp1
);
3563 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL
, stcb
, reason
, tp1
);
3564 sctp_m_freem(tp1
->data
);
3566 sctp_sowwakeup(stcb
->sctp_ep
, stcb
->sctp_socket
);
3568 if (tp1
->flags
& SCTP_PR_SCTP_BUFFER
) {
3569 stcb
->asoc
.sent_queue_cnt_removeable
--;
3571 if (queue
== &stcb
->asoc
.send_queue
) {
3572 TAILQ_REMOVE(&stcb
->asoc
.send_queue
, tp1
, sctp_next
);
3573 /* on to the sent queue */
3574 TAILQ_INSERT_TAIL(&stcb
->asoc
.sent_queue
, tp1
,
3576 stcb
->asoc
.sent_queue_cnt
++;
3578 if ((tp1
->rec
.data
.rcv_flags
& SCTP_DATA_NOT_FRAG
) ==
3579 SCTP_DATA_NOT_FRAG
) {
3580 /* not frag'ed we ae done */
3583 } else if (tp1
->rec
.data
.rcv_flags
& SCTP_DATA_LAST_FRAG
) {
3584 /* end of frag, we are done */
3588 /* Its a begin or middle piece, we must mark all of it */
3590 tp1
= TAILQ_NEXT(tp1
, sctp_next
);
3592 } while (tp1
&& notdone
);
3593 if ((foundeom
== 0) && (queue
== &stcb
->asoc
.sent_queue
)) {
3595 * The multi-part message was scattered
3596 * across the send and sent queue.
3598 tp1
= TAILQ_FIRST(&stcb
->asoc
.send_queue
);
3600 * recurse throught the send_queue too, starting at the
3604 ret_sz
+= sctp_release_pr_sctp_chunk(stcb
, tp1
, reason
,
3605 &stcb
->asoc
.send_queue
);
3607 kprintf("hmm, nothing on the send queue and no EOM?\n");
3614 * checks to see if the given address, sa, is one that is currently
3615 * known by the kernel
3616 * note: can't distinguish the same address on multiple interfaces and
3617 * doesn't handle multiple addresses with different zone/scope id's
3618 * note: ifa_ifwithaddr() compares the entire sockaddr struct
3621 sctp_find_ifa_by_addr(struct sockaddr
*sa
)
3626 /* go through all our known interfaces */
3627 TAILQ_FOREACH(ifn
, &ifnet
, if_list
) {
3628 /* go through each interface addresses */
3629 TAILQ_FOREACH(ifa
, &ifn
->if_addrlist
, ifa_list
) {
3630 /* correct family? */
3631 if (ifa
->ifa_addr
->sa_family
!= sa
->sa_family
)
3635 if (ifa
->ifa_addr
->sa_family
== AF_INET6
) {
3637 struct sockaddr_in6
*sin1
, *sin2
, sin6_tmp
;
3638 sin1
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
3639 if (IN6_IS_SCOPE_LINKLOCAL(&sin1
->sin6_addr
)) {
3640 /* create a copy and clear scope */
3641 memcpy(&sin6_tmp
, sin1
,
3642 sizeof(struct sockaddr_in6
));
3644 in6_clearscope(&sin1
->sin6_addr
);
3646 sin2
= (struct sockaddr_in6
*)sa
;
3647 if (memcmp(&sin1
->sin6_addr
, &sin2
->sin6_addr
,
3648 sizeof(struct in6_addr
)) == 0) {
3654 if (ifa
->ifa_addr
->sa_family
== AF_INET
) {
3656 struct sockaddr_in
*sin1
, *sin2
;
3657 sin1
= (struct sockaddr_in
*)ifa
->ifa_addr
;
3658 sin2
= (struct sockaddr_in
*)sa
;
3659 if (sin1
->sin_addr
.s_addr
==
3660 sin2
->sin_addr
.s_addr
) {
3665 /* else, not AF_INET or AF_INET6, so skip */
3666 } /* end foreach ifa */
3667 } /* end foreach ifn */
3675 * here we hack in a fix for Apple's m_copym for the case where the first mbuf
3676 * in the chain is a M_PKTHDR and the length is zero
3679 sctp_pkthdr_fix(struct mbuf
*m
)
3683 if ((m
->m_flags
& M_PKTHDR
) == 0) {
3688 if (m
->m_len
!= 0) {
3689 /* not a zero length PKTHDR mbuf */
3693 /* let's move in a word into the first mbuf... yes, ugly! */
3695 if (m_nxt
== NULL
) {
3696 /* umm... not a very useful mbuf chain... */
3699 if ((size_t)m_nxt
->m_len
> sizeof(long)) {
3700 /* move over a long */
3701 bcopy(mtod(m_nxt
, caddr_t
), mtod(m
, caddr_t
), sizeof(long));
3702 /* update mbuf data pointers and lengths */
3703 m
->m_len
+= sizeof(long);
3704 m_nxt
->m_data
+= sizeof(long);
3705 m_nxt
->m_len
-= sizeof(long);
3709 inline struct mbuf
*
3710 sctp_m_copym(struct mbuf
*m
, int off
, int len
, int wait
)
3713 return (m_copym(m
, off
, len
, wait
));
3715 #endif /* __APPLE__ */