1 /* $KAME: sctputil.c,v 1.36 2005/03/06 16:04:19 itojun Exp $ */
4 * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Cisco Systems, Inc.
18 * 4. Neither the name of the project nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #if !(defined(__OpenBSD__) || defined(__APPLE__))
36 #include "opt_ipsec.h"
38 #if defined(__FreeBSD__) || defined(__DragonFly__)
39 #include "opt_compat.h"
40 #include "opt_inet6.h"
42 #if !(defined(SCTP_BASE_FREEBSD) || defined(__DragonFly__))
43 #include "opt_mpath.h"
44 #endif /* SCTP_BASE_FREEBSD || __DragonFly__ */
46 #if defined(__NetBSD__)
51 #elif !defined(__OpenBSD__)
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/malloc.h>
59 #include <sys/domain.h>
60 #include <sys/protosw.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
64 #include <sys/kernel.h>
65 #include <sys/sysctl.h>
66 #include <sys/thread2.h>
68 #if defined(__FreeBSD__) || defined(__DragonFly__)
69 #include <sys/callout.h>
71 #include <netinet/sctp_callout.h> /* for callout_active() */
74 #include <net/radix.h>
75 #include <net/route.h>
79 #include <sys/domain.h>
83 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000)
84 #include <sys/limits.h>
86 #include <machine/limits.h>
90 #include <net/if_types.h>
91 #include <net/route.h>
93 #include <netinet/in.h>
94 #include <netinet/in_systm.h>
95 #include <netinet/ip.h>
96 #include <netinet/in_pcb.h>
97 #include <netinet/in_var.h>
98 #include <netinet/ip_var.h>
101 #include <netinet/ip6.h>
102 #include <netinet6/ip6_var.h>
104 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__DragonFly_)
105 #include <netinet6/in6_pcb.h>
106 #elif defined(__OpenBSD__)
107 #include <netinet/in_pcb.h>
112 #include <netinet/sctp_pcb.h>
116 #include <netinet6/ipsec.h>
117 #include <netproto/key/key.h>
123 #include <netinet/sctputil.h>
124 #include <netinet/sctp_var.h>
126 #include <netinet6/sctp6_var.h>
128 #include <netinet/sctp_header.h>
129 #include <netinet/sctp_output.h>
130 #include <netinet/sctp_hashdriver.h>
131 #include <netinet/sctp_uio.h>
132 #include <netinet/sctp_timer.h>
133 #include <netinet/sctp_crc32.h>
134 #include <netinet/sctp_indata.h> /* for sctp_deliver_data() */
135 #define NUMBER_OF_MTU_SIZES 18
138 extern u_int32_t sctp_debug_on;
141 #ifdef SCTP_STAT_LOGGING
142 int sctp_cwnd_log_at=0;
143 int sctp_cwnd_log_rolled=0;
144 struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
147 sctp_clr_stat_log(void)
150 sctp_cwnd_log_rolled=0;
154 sctp_log_strm_del_alt(u_int32_t tsn, u_int16_t sseq, int from)
157 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
158 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_STRM;
159 sctp_clog[sctp_cwnd_log_at].x.strlog.n_tsn = tsn;
160 sctp_clog[sctp_cwnd_log_at].x.strlog.n_sseq = sseq;
161 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn = 0;
162 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq = 0;
164 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
165 sctp_cwnd_log_at = 0;
166 sctp_cwnd_log_rolled = 1;
173 sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
176 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
177 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAP;
178 sctp_clog[sctp_cwnd_log_at].x.map.base = map;
179 sctp_clog[sctp_cwnd_log_at].x.map.cum = cum;
180 sctp_clog[sctp_cwnd_log_at].x.map.high = high;
182 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
183 sctp_cwnd_log_at = 0;
184 sctp_cwnd_log_rolled = 1;
189 sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
193 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
194 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_FR;
195 sctp_clog[sctp_cwnd_log_at].x.fr.largest_tsn = biggest_tsn;
196 sctp_clog[sctp_cwnd_log_at].x.fr.largest_new_tsn = biggest_new_tsn;
197 sctp_clog[sctp_cwnd_log_at].x.fr.tsn = tsn;
199 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
200 sctp_cwnd_log_at = 0;
201 sctp_cwnd_log_rolled = 1;
206 sctp_log_strm_del(struct sctp_tmit_chunk *chk, struct sctp_tmit_chunk *poschk,
211 kprintf("Gak log of NULL?\n");
214 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
215 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_STRM;
216 sctp_clog[sctp_cwnd_log_at].x.strlog.n_tsn = chk->rec.data.TSN_seq;
217 sctp_clog[sctp_cwnd_log_at].x.strlog.n_sseq = chk->rec.data.stream_seq;
218 if (poschk != NULL) {
219 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn =
220 poschk->rec.data.TSN_seq;
221 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq =
222 poschk->rec.data.stream_seq;
224 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn = 0;
225 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq = 0;
228 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
229 sctp_cwnd_log_at = 0;
230 sctp_cwnd_log_rolled = 1;
235 sctp_log_cwnd(struct sctp_nets *net, int augment, uint8_t from)
238 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
239 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_CWND;
240 sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
241 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = net->cwnd;
242 sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
243 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = augment;
245 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
246 sctp_cwnd_log_at = 0;
247 sctp_cwnd_log_rolled = 1;
252 sctp_log_maxburst(struct sctp_nets *net, int error, int burst, uint8_t from)
254 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
255 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAXBURST;
256 sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
257 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = error;
258 sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
259 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = burst;
261 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
262 sctp_cwnd_log_at = 0;
263 sctp_cwnd_log_rolled = 1;
268 sctp_log_rwnd(uint8_t from, u_int32_t peers_rwnd , u_int32_t snd_size, u_int32_t overhead)
270 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
271 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
272 sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
273 sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = snd_size;
274 sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
275 sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = 0;
277 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
278 sctp_cwnd_log_at = 0;
279 sctp_cwnd_log_rolled = 1;
284 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)
286 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
287 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
288 sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
289 sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = flight_size;
290 sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
291 sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = a_rwndval;
293 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
294 sctp_cwnd_log_at = 0;
295 sctp_cwnd_log_rolled = 1;
300 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)
302 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
303 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MBCNT;
304 sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_size = total_oq;
305 sctp_clog[sctp_cwnd_log_at].x.mbcnt.size_change = book;
306 sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_mb_size = total_mbcnt_q;
307 sctp_clog[sctp_cwnd_log_at].x.mbcnt.mbcnt_change = mbcnt;
309 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
310 sctp_cwnd_log_at = 0;
311 sctp_cwnd_log_rolled = 1;
316 sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc)
319 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
320 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_BLOCK;
321 sctp_clog[sctp_cwnd_log_at].x.blk.maxmb = (u_int16_t)(so->so_snd.ssb_mbmax/1024);
322 sctp_clog[sctp_cwnd_log_at].x.blk.onmb = asoc->total_output_mbuf_queue_size;
323 sctp_clog[sctp_cwnd_log_at].x.blk.maxsb = (u_int16_t)(so->so_snd.ssb_hiwat/1024);
324 sctp_clog[sctp_cwnd_log_at].x.blk.onsb = asoc->total_output_queue_size;
325 sctp_clog[sctp_cwnd_log_at].x.blk.send_sent_qcnt = (u_int16_t)(asoc->send_queue_cnt + asoc->sent_queue_cnt);
326 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (u_int16_t)asoc->stream_queue_cnt;
328 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
329 sctp_cwnd_log_at = 0;
330 sctp_cwnd_log_rolled = 1;
335 sctp_fill_stat_log(struct mbuf *m)
337 struct sctp_cwnd_log_req *req;
338 int size_limit, num, i, at, cnt_out=0;
343 size_limit = (m->m_len - sizeof(struct sctp_cwnd_log_req));
344 if (size_limit < sizeof(struct sctp_cwnd_log)) {
347 req = mtod(m, struct sctp_cwnd_log_req *);
348 num = size_limit/sizeof(struct sctp_cwnd_log);
349 if (sctp_cwnd_log_rolled) {
350 req->num_in_log = SCTP_STAT_LOG_SIZE;
352 req->num_in_log = sctp_cwnd_log_at;
353 /* if the log has not rolled, we don't
354 * let you have old data.
356 if (req->end_at > sctp_cwnd_log_at) {
357 req->end_at = sctp_cwnd_log_at;
360 if ((num < SCTP_STAT_LOG_SIZE) &&
361 ((sctp_cwnd_log_rolled) || (sctp_cwnd_log_at > num))) {
362 /* we can't return all of it */
363 if (((req->start_at == 0) && (req->end_at == 0)) ||
364 (req->start_at >= SCTP_STAT_LOG_SIZE) ||
365 (req->end_at >= SCTP_STAT_LOG_SIZE)) {
366 /* No user request or user is wacked. */
368 req->end_at = sctp_cwnd_log_at - 1;
369 if ((sctp_cwnd_log_at - num) < 0) {
371 cc = num - sctp_cwnd_log_at;
372 req->start_at = SCTP_STAT_LOG_SIZE - cc;
374 req->start_at = sctp_cwnd_log_at - num;
379 if (req->start_at > req->end_at) {
380 cc = (SCTP_STAT_LOG_SIZE - req->start_at) +
384 cc = req->end_at - req->start_at;
392 /* We can return all of it */
394 req->end_at = sctp_cwnd_log_at - 1;
395 req->num_ret = sctp_cwnd_log_at;
397 for (i = 0, at = req->start_at; i < req->num_ret; i++) {
398 req->log[i] = sctp_clog[at];
401 if (at >= SCTP_STAT_LOG_SIZE)
404 m->m_len = (cnt_out * sizeof(struct sctp_cwnd_log_req)) + sizeof(struct sctp_cwnd_log_req);
410 #ifdef SCTP_AUDITING_ENABLED
411 u_int8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
412 static int sctp_audit_indx = 0;
415 sctp_print_audit_report(void)
420 for (i=sctp_audit_indx;i<SCTP_AUDIT_SIZE;i++) {
421 if ((sctp_audit_data[i][0] == 0xe0) &&
422 (sctp_audit_data[i][1] == 0x01)) {
425 } else if (sctp_audit_data[i][0] == 0xf0) {
428 } else if ((sctp_audit_data[i][0] == 0xc0) &&
429 (sctp_audit_data[i][1] == 0x01)) {
433 kprintf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
434 (uint32_t)sctp_audit_data[i][1]);
439 for (i=0;i<sctp_audit_indx;i++) {
440 if ((sctp_audit_data[i][0] == 0xe0) &&
441 (sctp_audit_data[i][1] == 0x01)) {
444 } else if (sctp_audit_data[i][0] == 0xf0) {
447 } else if ((sctp_audit_data[i][0] == 0xc0) &&
448 (sctp_audit_data[i][1] == 0x01)) {
452 kprintf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
453 (uint32_t)sctp_audit_data[i][1]);
462 sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
463 struct sctp_nets *net)
465 int resend_cnt, tot_out, rep, tot_book_cnt;
466 struct sctp_nets *lnet;
467 struct sctp_tmit_chunk *chk;
469 sctp_audit_data[sctp_audit_indx][0] = 0xAA;
470 sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
472 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
476 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
477 sctp_audit_data[sctp_audit_indx][1] = 0x01;
479 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
485 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
486 sctp_audit_data[sctp_audit_indx][1] = 0x02;
488 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
493 sctp_audit_data[sctp_audit_indx][0] = 0xA1;
494 sctp_audit_data[sctp_audit_indx][1] =
495 (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
497 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
502 resend_cnt = tot_out = 0;
503 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
504 if (chk->sent == SCTP_DATAGRAM_RESEND) {
506 } else if (chk->sent < SCTP_DATAGRAM_RESEND) {
507 tot_out += chk->book_size;
511 if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
512 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
513 sctp_audit_data[sctp_audit_indx][1] = 0xA1;
515 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
518 kprintf("resend_cnt:%d asoc-tot:%d\n",
519 resend_cnt, stcb->asoc.sent_queue_retran_cnt);
521 stcb->asoc.sent_queue_retran_cnt = resend_cnt;
522 sctp_audit_data[sctp_audit_indx][0] = 0xA2;
523 sctp_audit_data[sctp_audit_indx][1] =
524 (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
526 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
530 if (tot_out != stcb->asoc.total_flight) {
531 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
532 sctp_audit_data[sctp_audit_indx][1] = 0xA2;
534 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
538 kprintf("tot_flt:%d asoc_tot:%d\n", tot_out,
539 (int)stcb->asoc.total_flight);
540 stcb->asoc.total_flight = tot_out;
542 if (tot_book_cnt != stcb->asoc.total_flight_count) {
543 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
544 sctp_audit_data[sctp_audit_indx][1] = 0xA5;
546 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
550 kprintf("tot_flt_book:%d\n", tot_book);
552 stcb->asoc.total_flight_count = tot_book_cnt;
555 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
556 tot_out += lnet->flight_size;
558 if (tot_out != stcb->asoc.total_flight) {
559 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
560 sctp_audit_data[sctp_audit_indx][1] = 0xA3;
562 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
566 kprintf("real flight:%d net total was %d\n",
567 stcb->asoc.total_flight, tot_out);
568 /* now corrective action */
569 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
571 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
572 if ((chk->whoTo == lnet) &&
573 (chk->sent < SCTP_DATAGRAM_RESEND)) {
574 tot_out += chk->book_size;
577 if (lnet->flight_size != tot_out) {
578 kprintf("net:%x flight was %d corrected to %d\n",
579 (uint32_t)lnet, lnet->flight_size, tot_out);
580 lnet->flight_size = tot_out;
587 sctp_print_audit_report();
592 sctp_audit_log(u_int8_t ev, u_int8_t fd)
595 sctp_audit_data[sctp_audit_indx][0] = ev;
596 sctp_audit_data[sctp_audit_indx][1] = fd;
598 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
607 * a list of sizes based on typical mtu's, used only if next hop
610 static int sctp_mtu_sizes[] = {
632 find_next_best_mtu(int totsz)
636 * if we are in here we must find the next best fit based on the
637 * size of the dg that failed to be sent.
640 for (i = 0; i < NUMBER_OF_MTU_SIZES; i++) {
641 if (totsz < sctp_mtu_sizes[i]) {
648 return (sctp_mtu_sizes[perfer]);
652 sctp_fill_random_store(struct sctp_pcb *m)
655 * Here we use the MD5/SHA-1 to hash with our good randomNumbers
656 * and our counter. The result becomes our good random numbers and
657 * we then setup to give these out. Note that we do no lockig
658 * to protect this. This is ok, since if competing folks call
659 * this we will get more gobbled gook in the random store whic
660 * is what we want. There is a danger that two guys will use
661 * the same random numbers, but thats ok too since that
662 * is random as well :->
665 sctp_hash_digest((char *)m->random_numbers, sizeof(m->random_numbers),
666 (char *)&m->random_counter, sizeof(m->random_counter),
667 (char *)m->random_store);
672 sctp_select_initial_TSN(struct sctp_pcb *m)
675 * A true implementation should use random selection process to
676 * get the initial stream sequence number, using RFC1750 as a
682 if (m->initial_sequence_debug != 0) {
684 ret = m->initial_sequence_debug;
685 m->initial_sequence_debug++;
688 if ((m->store_at+sizeof(u_long)) > SCTP_SIGNATURE_SIZE) {
689 /* Refill the random store */
690 sctp_fill_random_store(m);
692 p = &m->random_store[(int)m->store_at];
695 m->store_at += sizeof(u_long);
700 sctp_select_a_tag(struct sctp_inpcb *m)
705 SCTP_GETTIME_TIMEVAL(&now);
708 x = sctp_select_initial_TSN(&m->sctp_ep);
713 if (sctp_is_vtag_good(m, x, &now)) {
722 sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
723 int for_a_init, uint32_t override_tag )
726 * Anything set to zero is taken care of by the allocation
731 * Up front select what scoping to apply on addresses I tell my peer
732 * Not sure what to do with these right now, we will need to come up
733 * with a way to set them. We may need to pass them through from the
734 * caller in the sctp_aloc_assoc() function.
737 /* init all variables to a known value.*/
738 asoc->state = SCTP_STATE_INUSE;
739 asoc->max_burst = m->sctp_ep.max_burst;
740 asoc->heart_beat_delay = m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT];
741 asoc->cookie_life = m->sctp_ep.def_cookie_life;
744 asoc->my_vtag = override_tag;
746 asoc->my_vtag = sctp_select_a_tag(m);
748 asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
749 sctp_select_initial_TSN(&m->sctp_ep);
750 asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
751 /* we are opptimisitic here */
752 asoc->peer_supports_asconf = 1;
753 asoc->peer_supports_asconf_setprim = 1;
754 asoc->peer_supports_pktdrop = 1;
756 asoc->sent_queue_retran_cnt = 0;
757 /* This will need to be adjusted */
758 asoc->last_cwr_tsn = asoc->init_seq_number - 1;
759 asoc->last_acked_seq = asoc->init_seq_number - 1;
760 asoc->advanced_peer_ack_point = asoc->last_acked_seq;
761 asoc->asconf_seq_in = asoc->last_acked_seq;
763 /* here we are different, we hold the next one we expect */
764 asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
766 asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max;
767 asoc->initial_rto = m->sctp_ep.initial_rto;
769 asoc->max_init_times = m->sctp_ep.max_init_times;
770 asoc->max_send_times = m->sctp_ep.max_send_times;
771 asoc->def_net_failure = m->sctp_ep.def_net_failure;
773 /* ECN Nonce initialization */
774 asoc->ecn_nonce_allowed = 0;
775 asoc->receiver_nonce_sum = 1;
776 asoc->nonce_sum_expect_base = 1;
777 asoc->nonce_sum_check = 1;
778 asoc->nonce_resync_tsn = 0;
779 asoc->nonce_wait_for_ecne = 0;
780 asoc->nonce_wait_tsn = 0;
782 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
786 /* Its a V6 socket */
787 inp6 = (struct in6pcb *)m;
788 asoc->ipv6_addr_legal = 1;
789 /* Now look at the binding flag to see if V4 will be legal */
791 #if defined(__OpenBSD__)
792 (0) /* we always do dual bind */
793 #elif defined (__NetBSD__)
794 (inp6->in6p_flags & IN6P_IPV6_V6ONLY)
796 (inp6->inp_flags & IN6P_IPV6_V6ONLY)
799 asoc->ipv4_addr_legal = 1;
801 /* V4 addresses are NOT legal on the association */
802 asoc->ipv4_addr_legal = 0;
805 /* Its a V4 socket, no - V6 */
806 asoc->ipv4_addr_legal = 1;
807 asoc->ipv6_addr_legal = 0;
811 asoc->my_rwnd = max(m->sctp_socket->so_rcv.ssb_hiwat, SCTP_MINIMAL_RWND);
812 asoc->peers_rwnd = m->sctp_socket->so_rcv.ssb_hiwat;
814 asoc->smallest_mtu = m->sctp_frag_point;
815 asoc->minrto = m->sctp_ep.sctp_minrto;
816 asoc->maxrto = m->sctp_ep.sctp_maxrto;
818 LIST_INIT(&asoc->sctp_local_addr_list);
819 TAILQ_INIT(&asoc->nets);
820 TAILQ_INIT(&asoc->pending_reply_queue);
821 asoc->last_asconf_ack_sent = NULL;
822 /* Setup to fill the hb random cache at first HB */
823 asoc->hb_random_idx = 4;
825 asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
828 * Now the stream parameters, here we allocate space for all
829 * streams that we request by default.
831 asoc->streamoutcnt = asoc->pre_open_streams =
832 m->sctp_ep.pre_open_stream_count;
833 asoc->strmout = kmalloc(asoc->streamoutcnt * sizeof(struct sctp_stream_out),
835 if (asoc->strmout == NULL) {
836 /* big trouble no memory */
839 for (i = 0; i < asoc->streamoutcnt; i++) {
841 * inbound side must be set to 0xffff,
842 * also NOTE when we get the INIT-ACK back (for INIT sender)
843 * we MUST reduce the count (streamoutcnt) but first check
844 * if we sent to any of the upper streams that were dropped
845 * (if some were). Those that were dropped must be notified
846 * to the upper layer as failed to send.
848 asoc->strmout[i].next_sequence_sent = 0x0;
849 TAILQ_INIT(&asoc->strmout[i].outqueue);
850 asoc->strmout[i].stream_no = i;
851 asoc->strmout[i].next_spoke.tqe_next = 0;
852 asoc->strmout[i].next_spoke.tqe_prev = 0;
854 /* Now the mapping array */
855 asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
857 asoc->mapping_array = kmalloc(SCTP_INITIAL_MAPPING_ARRAY, M_PCB,
860 asoc->mapping_array = kmalloc(asoc->mapping_array_size, M_PCB,
863 if (asoc->mapping_array == NULL) {
864 kfree(asoc->strmout, M_PCB);
867 memset(asoc->mapping_array, 0, asoc->mapping_array_size);
868 /* Now the init of the other outqueues */
869 TAILQ_INIT(&asoc->out_wheel);
870 TAILQ_INIT(&asoc->control_send_queue);
871 TAILQ_INIT(&asoc->send_queue);
872 TAILQ_INIT(&asoc->sent_queue);
873 TAILQ_INIT(&asoc->reasmqueue);
874 TAILQ_INIT(&asoc->delivery_queue);
875 asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome;
877 TAILQ_INIT(&asoc->asconf_queue);
882 sctp_expand_mapping_array(struct sctp_association *asoc)
884 /* mapping array needs to grow */
888 new_size = asoc->mapping_array_size + SCTP_MAPPING_ARRAY_INCR;
890 new_array = kmalloc(asoc->mapping_array_size + SCTP_MAPPING_ARRAY_INCR,
893 new_array = kmalloc(new_size, M_PCB, M_NOWAIT);
895 if (new_array == NULL) {
896 /* can't get more, forget it */
897 kprintf("No memory for expansion of SCTP mapping array %d\n",
901 memset(new_array, 0, new_size);
902 memcpy(new_array, asoc->mapping_array, asoc->mapping_array_size);
903 kfree(asoc->mapping_array, M_PCB);
904 asoc->mapping_array = new_array;
905 asoc->mapping_array_size = new_size;
910 sctp_timeout_handler(void *t)
912 struct sctp_inpcb *inp;
913 struct sctp_tcb *stcb;
914 struct sctp_nets *net;
915 struct sctp_timer *tmr;
917 #if defined(__APPLE__)
918 boolean_t funnel_state;
920 /* get BSD kernel funnel/mutex */
921 funnel_state = thread_funnel_set(network_flock, TRUE);
925 tmr = (struct sctp_timer *)t;
926 inp = (struct sctp_inpcb *)tmr->ep;
927 stcb = (struct sctp_tcb *)tmr->tcb;
928 net = (struct sctp_nets *)tmr->net;
932 #ifdef SCTP_AUDITING_ENABLED
933 sctp_audit_log(0xF0, (u_int8_t)tmr->type);
934 sctp_auditing(3, inp, stcb, net);
936 sctp_pegs[SCTP_TIMERS_EXP]++;
943 if (inp->sctp_socket == 0) {
945 #if defined(__APPLE__)
946 /* release BSD kernel funnel/mutex */
947 thread_funnel_set(network_flock, FALSE);
949 SCTP_INP_WUNLOCK(inp);
953 if (stcb->asoc.state == 0) {
955 #if defined(__APPLE__)
956 /* release BSD kernel funnel/mutex */
957 thread_funnel_set(network_flock, FALSE);
959 SCTP_INP_WUNLOCK(inp);
964 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
965 kprintf("Timer type %d goes off\n", tmr->type);
967 #endif /* SCTP_DEBUG */
969 if (!callout_active(&tmr->timer)) {
971 #if defined(__APPLE__)
972 /* release BSD kernel funnel/mutex */
973 thread_funnel_set(network_flock, FALSE);
975 SCTP_INP_WUNLOCK(inp);
979 #if defined(__APPLE__)
980 /* clear the callout pending status here */
981 callout_stop(&tmr->timer);
986 SCTP_INP_INCR_REF(inp);
987 SCTP_INP_WUNLOCK(inp);
991 case SCTP_TIMER_TYPE_ITERATOR:
993 struct sctp_iterator *it;
994 it = (struct sctp_iterator *)inp;
995 sctp_iterator_timer(it);
998 /* call the handler for the appropriate timer type */
999 case SCTP_TIMER_TYPE_SEND:
1000 sctp_pegs[SCTP_TMIT_TIMER]++;
1001 stcb->asoc.num_send_timers_up--;
1002 if (stcb->asoc.num_send_timers_up < 0) {
1003 stcb->asoc.num_send_timers_up = 0;
1005 if (sctp_t3rxt_timer(inp, stcb, net)) {
1006 /* no need to unlock on tcb its gone */
1010 #ifdef SCTP_AUDITING_ENABLED
1011 sctp_auditing(4, inp, stcb, net);
1013 sctp_chunk_output(inp, stcb, 1);
1014 if ((stcb->asoc.num_send_timers_up == 0) &&
1015 (stcb->asoc.sent_queue_cnt > 0)
1017 struct sctp_tmit_chunk *chk;
1019 * safeguard. If there on some on the sent queue
1020 * somewhere but no timers running something is
1021 * wrong... so we start a timer on the first chunk
1022 * on the send queue on whatever net it is sent to.
1024 sctp_pegs[SCTP_T3_SAFEGRD]++;
1025 chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
1026 sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
1030 case SCTP_TIMER_TYPE_INIT:
1031 if (sctp_t1init_timer(inp, stcb, net)) {
1032 /* no need to unlock on tcb its gone */
1035 /* We do output but not here */
1038 case SCTP_TIMER_TYPE_RECV:
1039 sctp_pegs[SCTP_RECV_TIMER]++;
1040 sctp_send_sack(stcb);
1041 #ifdef SCTP_AUDITING_ENABLED
1042 sctp_auditing(4, inp, stcb, net);
1044 sctp_chunk_output(inp, stcb, 4);
1046 case SCTP_TIMER_TYPE_SHUTDOWN:
1047 if (sctp_shutdown_timer(inp, stcb, net) ) {
1048 /* no need to unlock on tcb its gone */
1051 #ifdef SCTP_AUDITING_ENABLED
1052 sctp_auditing(4, inp, stcb, net);
1054 sctp_chunk_output(inp, stcb, 5);
1056 case SCTP_TIMER_TYPE_HEARTBEAT:
1057 if (sctp_heartbeat_timer(inp, stcb, net)) {
1058 /* no need to unlock on tcb its gone */
1061 #ifdef SCTP_AUDITING_ENABLED
1062 sctp_auditing(4, inp, stcb, net);
1064 sctp_chunk_output(inp, stcb, 6);
1066 case SCTP_TIMER_TYPE_COOKIE:
1067 if (sctp_cookie_timer(inp, stcb, net)) {
1068 /* no need to unlock on tcb its gone */
1071 #ifdef SCTP_AUDITING_ENABLED
1072 sctp_auditing(4, inp, stcb, net);
1074 sctp_chunk_output(inp, stcb, 1);
1076 case SCTP_TIMER_TYPE_NEWCOOKIE:
1080 SCTP_GETTIME_TIMEVAL(&tv);
1081 SCTP_INP_WLOCK(inp);
1082 inp->sctp_ep.time_of_secret_change = tv.tv_sec;
1083 inp->sctp_ep.last_secret_number =
1084 inp->sctp_ep.current_secret_number;
1085 inp->sctp_ep.current_secret_number++;
1086 if (inp->sctp_ep.current_secret_number >=
1087 SCTP_HOW_MANY_SECRETS) {
1088 inp->sctp_ep.current_secret_number = 0;
1090 secret = (int)inp->sctp_ep.current_secret_number;
1091 for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
1092 inp->sctp_ep.secret_key[secret][i] =
1093 sctp_select_initial_TSN(&inp->sctp_ep);
1095 SCTP_INP_WUNLOCK(inp);
1096 sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
1100 case SCTP_TIMER_TYPE_PATHMTURAISE:
1101 sctp_pathmtu_timer(inp, stcb, net);
1104 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1105 if (sctp_shutdownack_timer(inp, stcb, net)) {
1106 /* no need to unlock on tcb its gone */
1109 #ifdef SCTP_AUDITING_ENABLED
1110 sctp_auditing(4, inp, stcb, net);
1112 sctp_chunk_output(inp, stcb, 7);
1114 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1115 sctp_abort_an_association(inp, stcb,
1116 SCTP_SHUTDOWN_GUARD_EXPIRES, NULL);
1117 /* no need to unlock on tcb its gone */
1121 case SCTP_TIMER_TYPE_STRRESET:
1122 if (sctp_strreset_timer(inp, stcb, net)) {
1123 /* no need to unlock on tcb its gone */
1126 sctp_chunk_output(inp, stcb, 9);
1129 case SCTP_TIMER_TYPE_ASCONF:
1130 if (sctp_asconf_timer(inp, stcb, net)) {
1131 /* no need to unlock on tcb its gone */
1134 #ifdef SCTP_AUDITING_ENABLED
1135 sctp_auditing(4, inp, stcb, net);
1137 sctp_chunk_output(inp, stcb, 8);
1140 case SCTP_TIMER_TYPE_AUTOCLOSE:
1141 sctp_autoclose_timer(inp, stcb, net);
1142 sctp_chunk_output(inp, stcb, 10);
1145 case SCTP_TIMER_TYPE_INPKILL:
1146 /* special case, take away our
1147 * increment since WE are the killer
1149 SCTP_INP_WLOCK(inp);
1150 SCTP_INP_DECR_REF(inp);
1151 SCTP_INP_WUNLOCK(inp);
1152 sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL);
1153 sctp_inpcb_free(inp, 1);
1158 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1159 kprintf("sctp_timeout_handler:unknown timer %d\n",
1162 #endif /* SCTP_DEBUG */
1165 #ifdef SCTP_AUDITING_ENABLED
1166 sctp_audit_log(0xF1, (u_int8_t)tmr->type);
1167 sctp_auditing(5, inp, stcb, net);
1171 * Now we need to clean up the control chunk chain if an
1172 * ECNE is on it. It must be marked as UNSENT again so next
1173 * call will continue to send it until such time that we get
1174 * a CWR, to remove it. It is, however, less likely that we
1175 * will find a ecn echo on the chain though.
1177 sctp_fix_ecn_echo(&stcb->asoc);
1180 SCTP_TCB_UNLOCK(stcb);
1183 SCTP_INP_WLOCK(inp);
1184 SCTP_INP_DECR_REF(inp);
1185 SCTP_INP_WUNLOCK(inp);
1190 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1191 kprintf("Timer now complete (type %d)\n", typ);
1193 #endif /* SCTP_DEBUG */
1196 #if defined(__APPLE__)
1197 /* release BSD kernel funnel/mutex */
1198 thread_funnel_set(network_flock, FALSE);
1203 sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1204 struct sctp_nets *net)
1207 struct sctp_timer *tmr;
1216 case SCTP_TIMER_TYPE_ITERATOR:
1218 struct sctp_iterator *it;
1219 it = (struct sctp_iterator *)inp;
1221 to_ticks = SCTP_ITERATOR_TICKS;
1224 case SCTP_TIMER_TYPE_SEND:
1225 /* Here we use the RTO timer */
1228 if ((stcb == NULL) || (net == NULL)) {
1231 tmr = &net->rxt_timer;
1232 if (net->RTO == 0) {
1233 rto_val = stcb->asoc.initial_rto;
1237 to_ticks = MSEC_TO_TICKS(rto_val);
1240 case SCTP_TIMER_TYPE_INIT:
1242 * Here we use the INIT timer default
1243 * usually about 1 minute.
1245 if ((stcb == NULL) || (net == NULL)) {
1248 tmr = &net->rxt_timer;
1249 if (net->RTO == 0) {
1250 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1252 to_ticks = MSEC_TO_TICKS(net->RTO);
1255 case SCTP_TIMER_TYPE_RECV:
1257 * Here we use the Delayed-Ack timer value from the inp
1258 * ususually about 200ms.
1263 tmr = &stcb->asoc.dack_timer;
1264 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV];
1266 case SCTP_TIMER_TYPE_SHUTDOWN:
1267 /* Here we use the RTO of the destination. */
1268 if ((stcb == NULL) || (net == NULL)) {
1272 if (net->RTO == 0) {
1273 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1275 to_ticks = MSEC_TO_TICKS(net->RTO);
1277 tmr = &net->rxt_timer;
1279 case SCTP_TIMER_TYPE_HEARTBEAT:
1281 * the net is used here so that we can add in the RTO.
1282 * Even though we use a different timer. We also add the
1283 * HB timer PLUS a random jitter.
1290 uint8_t this_random;
1291 int cnt_of_unconf=0;
1292 struct sctp_nets *lnet;
1294 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1295 if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
1300 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1301 kprintf("HB timer to start unconfirmed:%d hb_delay:%d\n",
1302 cnt_of_unconf, stcb->asoc.heart_beat_delay);
1305 if (stcb->asoc.hb_random_idx > 3) {
1306 rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1307 memcpy(stcb->asoc.hb_random_values, &rndval,
1308 sizeof(stcb->asoc.hb_random_values));
1309 this_random = stcb->asoc.hb_random_values[0];
1310 stcb->asoc.hb_random_idx = 0;
1311 stcb->asoc.hb_ect_randombit = 0;
1313 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
1314 stcb->asoc.hb_random_idx++;
1315 stcb->asoc.hb_ect_randombit = 0;
1318 * this_random will be 0 - 256 ms
1321 if ((stcb->asoc.heart_beat_delay == 0) &&
1322 (cnt_of_unconf == 0)) {
1323 /* no HB on this inp after confirmations */
1327 struct sctp_nets *lnet;
1329 delay = stcb->asoc.heart_beat_delay;
1330 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1331 if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
1332 ((lnet->dest_state & SCTP_ADDR_OUT_OF_SCOPE) == 0) &&
1333 (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
1337 if (net->RTO == 0) {
1338 /* Never been checked */
1339 to_ticks = this_random + stcb->asoc.initial_rto + delay;
1341 /* set rto_val to the ms */
1342 to_ticks = delay + net->RTO + this_random;
1345 if (cnt_of_unconf) {
1346 to_ticks = this_random + stcb->asoc.initial_rto;
1348 to_ticks = stcb->asoc.heart_beat_delay + this_random + stcb->asoc.initial_rto;
1352 * Now we must convert the to_ticks that are now in
1358 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1359 kprintf("Timer to expire in %d ticks\n", to_ticks);
1362 tmr = &stcb->asoc.hb_timer;
1365 case SCTP_TIMER_TYPE_COOKIE:
1367 * Here we can use the RTO timer from the network since
1368 * one RTT was compelete. If a retran happened then we will
1369 * be using the RTO initial value.
1371 if ((stcb == NULL) || (net == NULL)) {
1374 if (net->RTO == 0) {
1375 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1377 to_ticks = MSEC_TO_TICKS(net->RTO);
1379 tmr = &net->rxt_timer;
1381 case SCTP_TIMER_TYPE_NEWCOOKIE:
1383 * nothing needed but the endpoint here
1384 * ususually about 60 minutes.
1386 tmr = &inp->sctp_ep.signature_change;
1387 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
1389 case SCTP_TIMER_TYPE_INPKILL:
1391 * The inp is setup to die. We re-use the
1392 * signature_chage timer since that has
1393 * stopped and we are in the GONE state.
1395 tmr = &inp->sctp_ep.signature_change;
1396 to_ticks = (SCTP_INP_KILL_TIMEOUT * hz) / 1000;
1398 case SCTP_TIMER_TYPE_PATHMTURAISE:
1400 * Here we use the value found in the EP for PMTU
1401 * ususually about 10 minutes.
1409 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
1410 tmr = &net->pmtu_timer;
1412 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1413 /* Here we use the RTO of the destination */
1414 if ((stcb == NULL) || (net == NULL)) {
1417 if (net->RTO == 0) {
1418 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1420 to_ticks = MSEC_TO_TICKS(net->RTO);
1422 tmr = &net->rxt_timer;
1424 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1426 * Here we use the endpoints shutdown guard timer
1427 * usually about 3 minutes.
1432 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
1433 tmr = &stcb->asoc.shut_guard_timer;
1435 case SCTP_TIMER_TYPE_STRRESET:
1437 * Here the timer comes from the inp
1438 * but its value is from the RTO.
1440 if ((stcb == NULL) || (net == NULL)) {
1443 if (net->RTO == 0) {
1444 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1446 to_ticks = MSEC_TO_TICKS(net->RTO);
1448 tmr = &stcb->asoc.strreset_timer;
1451 case SCTP_TIMER_TYPE_ASCONF:
1453 * Here the timer comes from the inp
1454 * but its value is from the RTO.
1456 if ((stcb == NULL) || (net == NULL)) {
1459 if (net->RTO == 0) {
1460 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1462 to_ticks = MSEC_TO_TICKS(net->RTO);
1464 tmr = &stcb->asoc.asconf_timer;
1466 case SCTP_TIMER_TYPE_AUTOCLOSE:
1470 if (stcb->asoc.sctp_autoclose_ticks == 0) {
1471 /* Really an error since stcb is NOT set to autoclose */
1474 to_ticks = stcb->asoc.sctp_autoclose_ticks;
1475 tmr = &stcb->asoc.autoclose_timer;
1479 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1480 kprintf("sctp_timer_start:Unknown timer type %d\n",
1483 #endif /* SCTP_DEBUG */
1487 if ((to_ticks <= 0) || (tmr == NULL)) {
1489 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1490 kprintf("sctp_timer_start:%d:software error to_ticks:%d tmr:%p not set ??\n",
1491 t_type, to_ticks, tmr);
1493 #endif /* SCTP_DEBUG */
1496 if (callout_pending(&tmr->timer)) {
1498 * we do NOT allow you to have it already running.
1499 * if it is we leave the current one up unchanged
1503 /* At this point we can proceed */
1504 if (t_type == SCTP_TIMER_TYPE_SEND) {
1505 stcb->asoc.num_send_timers_up++;
1508 tmr->ep = (void *)inp;
1509 tmr->tcb = (void *)stcb;
1510 tmr->net = (void *)net;
1511 callout_reset(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
1516 sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1517 struct sctp_nets *net)
1519 struct sctp_timer *tmr;
1526 case SCTP_TIMER_TYPE_ITERATOR:
1528 struct sctp_iterator *it;
1529 it = (struct sctp_iterator *)inp;
1533 case SCTP_TIMER_TYPE_SEND:
1534 if ((stcb == NULL) || (net == NULL)) {
1537 tmr = &net->rxt_timer;
1539 case SCTP_TIMER_TYPE_INIT:
1540 if ((stcb == NULL) || (net == NULL)) {
1543 tmr = &net->rxt_timer;
1545 case SCTP_TIMER_TYPE_RECV:
1549 tmr = &stcb->asoc.dack_timer;
1551 case SCTP_TIMER_TYPE_SHUTDOWN:
1552 if ((stcb == NULL) || (net == NULL)) {
1555 tmr = &net->rxt_timer;
1557 case SCTP_TIMER_TYPE_HEARTBEAT:
1561 tmr = &stcb->asoc.hb_timer;
1563 case SCTP_TIMER_TYPE_COOKIE:
1564 if ((stcb == NULL) || (net == NULL)) {
1567 tmr = &net->rxt_timer;
1569 case SCTP_TIMER_TYPE_NEWCOOKIE:
1570 /* nothing needed but the endpoint here */
1571 tmr = &inp->sctp_ep.signature_change;
1572 /* We re-use the newcookie timer for
1573 * the INP kill timer. We must assure
1574 * that we do not kill it by accident.
1577 case SCTP_TIMER_TYPE_INPKILL:
1579 * The inp is setup to die. We re-use the
1580 * signature_chage timer since that has
1581 * stopped and we are in the GONE state.
1583 tmr = &inp->sctp_ep.signature_change;
1585 case SCTP_TIMER_TYPE_PATHMTURAISE:
1592 tmr = &net->pmtu_timer;
1594 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1595 if ((stcb == NULL) || (net == NULL)) {
1598 tmr = &net->rxt_timer;
1600 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1604 tmr = &stcb->asoc.shut_guard_timer;
1606 case SCTP_TIMER_TYPE_STRRESET:
1610 tmr = &stcb->asoc.strreset_timer;
1612 case SCTP_TIMER_TYPE_ASCONF:
1616 tmr = &stcb->asoc.asconf_timer;
1618 case SCTP_TIMER_TYPE_AUTOCLOSE:
1622 tmr = &stcb->asoc.autoclose_timer;
1626 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1627 kprintf("sctp_timer_stop:Unknown timer type %d\n",
1630 #endif /* SCTP_DEBUG */
1636 if ((tmr->type != t_type) && tmr->type) {
1638 * Ok we have a timer that is under joint use. Cookie timer
1639 * per chance with the SEND timer. We therefore are NOT
1640 * running the timer that the caller wants stopped. So just
1645 if (t_type == SCTP_TIMER_TYPE_SEND) {
1646 stcb->asoc.num_send_timers_up--;
1647 if (stcb->asoc.num_send_timers_up < 0) {
1648 stcb->asoc.num_send_timers_up = 0;
1651 callout_stop(&tmr->timer);
1655 #ifdef SCTP_USE_ADLER32
1657 update_adler32(uint32_t adler, uint8_t *buf, int32_t len)
1659 u_int32_t s1 = adler & 0xffff;
1660 u_int32_t s2 = (adler >> 16) & 0xffff;
1663 for (n = 0; n < len; n++, buf++) {
1664 /* s1 = (s1 + buf[n]) % BASE */
1668 * now if we need to, we do a mod by subtracting. It seems
1669 * a bit faster since I really will only ever do one subtract
1670 * at the MOST, since buf[n] is a max of 255.
1672 if (s1 >= SCTP_ADLER32_BASE) {
1673 s1 -= SCTP_ADLER32_BASE;
1675 /* s2 = (s2 + s1) % BASE */
1679 * again, it is more efficent (it seems) to subtract since
1680 * the most s2 will ever be is (BASE-1 + BASE-1) in the worse
1681 * case. This would then be (2 * BASE) - 2, which will still
1682 * only do one subtract. On Intel this is much better to do
1683 * this way and avoid the divide. Have not -pg'd on sparc.
1685 if (s2 >= SCTP_ADLER32_BASE) {
1686 s2 -= SCTP_ADLER32_BASE;
1689 /* Return the adler32 of the bytes buf[0..len-1] */
1690 return ((s2 << 16) + s1);
1697 sctp_calculate_len(struct mbuf *m)
1709 #if defined(SCTP_WITH_NO_CSUM)
1712 sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1715 * given a mbuf chain with a packetheader offset by 'offset'
1716 * pointing at a sctphdr (with csum set to 0) go through
1717 * the chain of m_next's and calculate the SCTP checksum.
1718 * This is currently Adler32 but will change to CRC32x
1719 * soon. Also has a side bonus calculate the total length
1720 * of the mbuf chain.
1721 * Note: if offset is greater than the total mbuf length,
1722 * checksum=1, pktlen=0 is returned (ie. no real error code)
1726 *pktlen = sctp_calculate_len(m);
1730 #elif defined(SCTP_USE_INCHKSUM)
1732 #include <machine/in_cksum.h>
1735 sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1738 * given a mbuf chain with a packetheader offset by 'offset'
1739 * pointing at a sctphdr (with csum set to 0) go through
1740 * the chain of m_next's and calculate the SCTP checksum.
1741 * This is currently Adler32 but will change to CRC32x
1742 * soon. Also has a side bonus calculate the total length
1743 * of the mbuf chain.
1744 * Note: if offset is greater than the total mbuf length,
1745 * checksum=1, pktlen=0 is returned (ie. no real error code)
1749 uint32_t the_sum, retsum;
1756 the_sum = (uint32_t)(in_cksum_skip(m, tlen, offset));
1758 *pktlen = (tlen-offset);
1759 retsum = htons(the_sum);
1766 sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1769 * given a mbuf chain with a packetheader offset by 'offset'
1770 * pointing at a sctphdr (with csum set to 0) go through
1771 * the chain of m_next's and calculate the SCTP checksum.
1772 * This is currently Adler32 but will change to CRC32x
1773 * soon. Also has a side bonus calculate the total length
1774 * of the mbuf chain.
1775 * Note: if offset is greater than the total mbuf length,
1776 * checksum=1, pktlen=0 is returned (ie. no real error code)
1779 #ifdef SCTP_USE_ADLER32
1782 uint32_t base = 0xffffffff;
1783 #endif /* SCTP_USE_ADLER32 */
1786 /* find the correct mbuf and offset into mbuf */
1787 while ((at != NULL) && (offset > (uint32_t)at->m_len)) {
1788 offset -= at->m_len; /* update remaining offset left */
1792 while (at != NULL) {
1793 #ifdef SCTP_USE_ADLER32
1794 base = update_adler32(base, at->m_data + offset,
1795 at->m_len - offset);
1797 base = update_crc32(base, at->m_data + offset,
1798 at->m_len - offset);
1799 #endif /* SCTP_USE_ADLER32 */
1800 tlen += at->m_len - offset;
1801 /* we only offset once into the first mbuf */
1807 if (pktlen != NULL) {
1810 #ifdef SCTP_USE_ADLER32
1815 base = sctp_csum_finalize(base);
1824 sctp_mtu_size_reset(struct sctp_inpcb *inp,
1825 struct sctp_association *asoc, u_long mtu)
1828 * Reset the P-MTU size on this association, this involves changing
1829 * the asoc MTU, going through ANY chunk+overhead larger than mtu
1830 * to allow the DF flag to be cleared.
1832 struct sctp_tmit_chunk *chk;
1833 struct sctp_stream_out *strm;
1834 unsigned int eff_mtu, ovh;
1835 asoc->smallest_mtu = mtu;
1836 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1837 ovh = SCTP_MIN_OVERHEAD;
1839 ovh = SCTP_MIN_V4_OVERHEAD;
1841 eff_mtu = mtu - ovh;
1842 /* Now mark any chunks that need to let IP fragment */
1843 TAILQ_FOREACH(strm, &asoc->out_wheel, next_spoke) {
1844 TAILQ_FOREACH(chk, &strm->outqueue, sctp_next) {
1845 if (chk->send_size > eff_mtu) {
1846 chk->flags &= SCTP_DONT_FRAGMENT;
1847 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1851 TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
1852 if (chk->send_size > eff_mtu) {
1853 chk->flags &= SCTP_DONT_FRAGMENT;
1854 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1857 TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
1858 if (chk->send_size > eff_mtu) {
1859 chk->flags &= SCTP_DONT_FRAGMENT;
1860 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1867 * given an association and starting time of the current RTT period
1868 * return RTO in number of usecs
1869 * net should point to the current network
1872 sctp_calculate_rto(struct sctp_tcb *stcb,
1873 struct sctp_association *asoc,
1874 struct sctp_nets *net,
1875 struct timeval *old)
1878 * given an association and the starting time of the current RTT
1879 * period (in value1/value2) return RTO in number of usecs.
1883 unsigned int new_rto = 0;
1884 int first_measure = 0;
1887 /************************/
1888 /* 1. calculate new RTT */
1889 /************************/
1890 /* get the current time */
1891 SCTP_GETTIME_TIMEVAL(&now);
1892 /* compute the RTT value */
1893 if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
1894 calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
1895 if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
1896 calc_time += (((u_long)now.tv_usec -
1897 (u_long)old->tv_usec)/1000);
1898 } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
1899 /* Borrow 1,000ms from current calculation */
1901 /* Add in the slop over */
1902 calc_time += ((int)now.tv_usec/1000);
1903 /* Add in the pre-second ms's */
1904 calc_time += (((int)1000000 - (int)old->tv_usec)/1000);
1906 } else if ((u_long)now.tv_sec == (u_long)old->tv_sec) {
1907 if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
1908 calc_time = ((u_long)now.tv_usec -
1909 (u_long)old->tv_usec)/1000;
1910 } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
1911 /* impossible .. garbage in nothing out */
1912 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1914 /* impossible .. garbage in nothing out */
1915 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1918 /* Clock wrapped? */
1919 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1921 /***************************/
1922 /* 2. update RTTVAR & SRTT */
1923 /***************************/
1925 /* if (net->lastsv || net->lastsa) {*/
1926 /* per Section 5.3.1 C3 in SCTP */
1927 /* net->lastsv = (int) *//* RTTVAR */
1928 /* (((double)(1.0 - 0.25) * (double)net->lastsv) +
1929 (double)(0.25 * (double)abs(net->lastsa - calc_time)));
1930 net->lastsa = (int) */ /* SRTT */
1931 /*(((double)(1.0 - 0.125) * (double)net->lastsa) +
1932 (double)(0.125 * (double)calc_time));
1934 *//* the first RTT calculation, per C2 Section 5.3.1 */
1935 /* net->lastsa = calc_time; *//* SRTT */
1936 /* net->lastsv = calc_time / 2; *//* RTTVAR */
1938 /* if RTTVAR goes to 0 you set to clock grainularity */
1939 /* if (net->lastsv == 0) {
1940 net->lastsv = SCTP_CLOCK_GRANULARITY;
1942 new_rto = net->lastsa + 4 * net->lastsv;
1945 o_calctime = calc_time;
1946 /* this is Van Jacobson's integer version */
1948 calc_time -= (net->lastsa >> 3);
1949 net->lastsa += calc_time;
1950 if (calc_time < 0) {
1951 calc_time = -calc_time;
1953 calc_time -= (net->lastsv >> 2);
1954 net->lastsv += calc_time;
1955 if (net->lastsv == 0) {
1956 net->lastsv = SCTP_CLOCK_GRANULARITY;
1959 /* First RTO measurment */
1960 net->lastsa = calc_time;
1961 net->lastsv = calc_time >> 1;
1964 new_rto = ((net->lastsa >> 2) + net->lastsv) >> 1;
1965 if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
1966 (stcb->asoc.sat_network_lockout == 0)) {
1967 stcb->asoc.sat_network = 1;
1968 } else if ((!first_measure) && stcb->asoc.sat_network) {
1969 stcb->asoc.sat_network = 0;
1970 stcb->asoc.sat_network_lockout = 1;
1972 /* bound it, per C6/C7 in Section 5.3.1 */
1973 if (new_rto < stcb->asoc.minrto) {
1974 new_rto = stcb->asoc.minrto;
1976 if (new_rto > stcb->asoc.maxrto) {
1977 new_rto = stcb->asoc.maxrto;
1979 /* we are now returning the RTT Smoothed */
1980 return ((u_int32_t)new_rto);
1985 * return a pointer to a contiguous piece of data from the given
1986 * mbuf chain starting at 'off' for 'len' bytes. If the desired
1987 * piece spans more than one mbuf, a copy is made at 'ptr'.
1988 * caller must ensure that the buffer size is >= 'len'
1989 * returns NULL if there there isn't 'len' bytes in the chain.
1992 sctp_m_getptr(struct mbuf *m, int off, int len, u_int8_t *in_ptr)
1997 if ((off < 0) || (len <= 0))
2000 /* find the desired start location */
2001 while ((m != NULL) && (off > 0)) {
2010 /* is the current mbuf large enough (eg. contiguous)? */
2011 if ((m->m_len - off) >= len) {
2012 return (mtod(m, caddr_t) + off);
2014 /* else, it spans more than one mbuf, so save a temp copy... */
2015 while ((m != NULL) && (len > 0)) {
2016 count = min(m->m_len - off, len);
2017 bcopy(mtod(m, caddr_t) + off, ptr, count);
2023 if ((m == NULL) && (len > 0))
2026 return ((caddr_t)in_ptr);
2031 struct sctp_paramhdr *
2032 sctp_get_next_param(struct mbuf *m,
2034 struct sctp_paramhdr *pull,
2037 /* This just provides a typed signature to Peter's Pull routine */
2038 return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
2044 sctp_add_pad_tombuf(struct mbuf *m, int padlen)
2047 * add padlen bytes of 0 filled padding to the end of the mbuf.
2048 * If padlen is > 3 this routine will fail.
2055 if (M_TRAILINGSPACE(m)) {
2058 * We hope the majority of the time we hit here :)
2060 dp = (u_int8_t *)(mtod(m, caddr_t) + m->m_len);
2063 /* Hard way we must grow the mbuf */
2065 MGET(tmp, MB_DONTWAIT, MT_DATA);
2067 /* Out of space GAK! we are in big trouble. */
2070 /* setup and insert in middle */
2071 tmp->m_next = m->m_next;
2072 tmp->m_len = padlen;
2074 dp = mtod(tmp, u_int8_t *);
2076 /* zero out the pad */
2077 for (i= 0; i < padlen; i++) {
2085 sctp_pad_lastmbuf(struct mbuf *m, int padval)
2087 /* find the last mbuf in chain and pad it */
2091 if (m_at->m_next == NULL) {
2092 return (sctp_add_pad_tombuf(m_at, padval));
2094 m_at = m_at->m_next;
2100 sctp_notify_assoc_change(u_int32_t event, struct sctp_tcb *stcb,
2103 struct mbuf *m_notify;
2104 struct sctp_assoc_change *sac;
2105 struct sockaddr *to;
2106 struct sockaddr_in6 sin6, lsa6;
2109 * First if we are are going down dump everything we
2110 * can to the socket rcv queue.
2112 if ((event == SCTP_SHUTDOWN_COMP) || (event == SCTP_COMM_LOST)) {
2113 sctp_deliver_data(stcb, &stcb->asoc, NULL, 0);
2117 * For TCP model AND UDP connected sockets we will send
2118 * an error up when an ABORT comes in.
2120 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2121 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
2122 (event == SCTP_COMM_LOST)) {
2123 stcb->sctp_socket->so_error = ECONNRESET;
2124 /* Wake ANY sleepers */
2125 sowwakeup(stcb->sctp_socket);
2126 sorwakeup(stcb->sctp_socket);
2129 if ((event == SCTP_COMM_UP) &&
2130 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2131 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
2132 soisconnected(stcb->sctp_socket);
2135 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
2136 /* event not enabled */
2139 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2140 if (m_notify == NULL)
2143 m_notify->m_len = 0;
2145 sac = mtod(m_notify, struct sctp_assoc_change *);
2146 sac->sac_type = SCTP_ASSOC_CHANGE;
2148 sac->sac_length = sizeof(struct sctp_assoc_change);
2149 sac->sac_state = event;
2150 sac->sac_error = error;
2151 /* XXX verify these stream counts */
2152 sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
2153 sac->sac_inbound_streams = stcb->asoc.streamincnt;
2154 sac->sac_assoc_id = sctp_get_associd(stcb);
2156 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2157 m_notify->m_pkthdr.len = sizeof(struct sctp_assoc_change);
2158 m_notify->m_pkthdr.rcvif = 0;
2159 m_notify->m_len = sizeof(struct sctp_assoc_change);
2160 m_notify->m_next = NULL;
2162 /* append to socket */
2163 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2164 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2165 to->sa_family == AF_INET) {
2166 struct sockaddr_in *sin;
2168 sin = (struct sockaddr_in *)to;
2169 bzero(&sin6, sizeof(sin6));
2170 sin6.sin6_family = AF_INET6;
2171 sin6.sin6_len = sizeof(struct sockaddr_in6);
2172 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2173 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2174 sizeof(sin6.sin6_addr.s6_addr16[3]));
2175 sin6.sin6_port = sin->sin_port;
2176 to = (struct sockaddr *)&sin6;
2178 /* check and strip embedded scope junk */
2179 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2182 * We need to always notify comm changes.
2183 * if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2184 * sctp_m_freem(m_notify);
2188 SCTP_TCB_UNLOCK(stcb);
2189 SCTP_INP_WLOCK(stcb->sctp_ep);
2190 SCTP_TCB_LOCK(stcb);
2191 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
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);
2197 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2200 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2201 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2202 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2203 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2204 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2207 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2209 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2210 /* Wake up any sleeper */
2211 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2212 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
2216 sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
2217 struct sockaddr *sa, uint32_t error)
2219 struct mbuf *m_notify;
2220 struct sctp_paddr_change *spc;
2221 struct sockaddr *to;
2222 struct sockaddr_in6 sin6, lsa6;
2224 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVPADDREVNT))
2225 /* event not enabled */
2228 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2229 if (m_notify == NULL)
2231 m_notify->m_len = 0;
2233 MCLGET(m_notify, MB_DONTWAIT);
2234 if ((m_notify->m_flags & M_EXT) != M_EXT) {
2235 sctp_m_freem(m_notify);
2239 spc = mtod(m_notify, struct sctp_paddr_change *);
2240 spc->spc_type = SCTP_PEER_ADDR_CHANGE;
2242 spc->spc_length = sizeof(struct sctp_paddr_change);
2243 if (sa->sa_family == AF_INET) {
2244 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2246 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2248 spc->spc_state = state;
2249 spc->spc_error = error;
2250 spc->spc_assoc_id = sctp_get_associd(stcb);
2252 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2253 m_notify->m_pkthdr.len = sizeof(struct sctp_paddr_change);
2254 m_notify->m_pkthdr.rcvif = 0;
2255 m_notify->m_len = sizeof(struct sctp_paddr_change);
2256 m_notify->m_next = NULL;
2258 to = (struct sockaddr *)(struct sockaddr *)
2259 &stcb->asoc.primary_destination->ro._l_addr;
2260 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2261 to->sa_family == AF_INET) {
2262 struct sockaddr_in *sin;
2264 sin = (struct sockaddr_in *)to;
2265 bzero(&sin6, sizeof(sin6));
2266 sin6.sin6_family = AF_INET6;
2267 sin6.sin6_len = sizeof(struct sockaddr_in6);
2268 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2269 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2270 sizeof(sin6.sin6_addr.s6_addr16[3]));
2271 sin6.sin6_port = sin->sin_port;
2272 to = (struct sockaddr *)&sin6;
2274 /* check and strip embedded scope junk */
2275 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2278 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2279 sctp_m_freem(m_notify);
2282 /* append to socket */
2283 SCTP_TCB_UNLOCK(stcb);
2284 SCTP_INP_WLOCK(stcb->sctp_ep);
2285 SCTP_TCB_LOCK(stcb);
2286 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
2287 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2288 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2289 /* not enough room */
2290 sctp_m_freem(m_notify);
2291 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2292 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2295 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2296 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2297 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2298 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2299 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2302 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2304 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2305 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2310 sctp_notify_send_failed(struct sctp_tcb *stcb, u_int32_t error,
2311 struct sctp_tmit_chunk *chk)
2313 struct mbuf *m_notify;
2314 struct sctp_send_failed *ssf;
2315 struct sockaddr_in6 sin6, lsa6;
2316 struct sockaddr *to;
2319 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2320 /* event not enabled */
2323 length = sizeof(struct sctp_send_failed) + chk->send_size;
2324 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2325 if (m_notify == NULL)
2328 m_notify->m_len = 0;
2329 ssf = mtod(m_notify, struct sctp_send_failed *);
2330 ssf->ssf_type = SCTP_SEND_FAILED;
2331 if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
2332 ssf->ssf_flags = SCTP_DATA_UNSENT;
2334 ssf->ssf_flags = SCTP_DATA_SENT;
2335 ssf->ssf_length = length;
2336 ssf->ssf_error = error;
2337 /* not exactly what the user sent in, but should be close :) */
2338 ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
2339 ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
2340 ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
2341 ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
2342 ssf->ssf_info.sinfo_context = chk->rec.data.context;
2343 ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
2344 ssf->ssf_assoc_id = sctp_get_associd(stcb);
2345 m_notify->m_next = chk->data;
2346 if (m_notify->m_next == NULL)
2347 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2350 m_notify->m_flags |= M_NOTIFICATION;
2352 while (m->m_next != NULL)
2354 m->m_flags |= M_EOR;
2356 m_notify->m_pkthdr.len = length;
2357 m_notify->m_pkthdr.rcvif = 0;
2358 m_notify->m_len = sizeof(struct sctp_send_failed);
2360 /* Steal off the mbuf */
2362 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2363 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2364 to->sa_family == AF_INET) {
2365 struct sockaddr_in *sin;
2367 sin = (struct sockaddr_in *)to;
2368 bzero(&sin6, sizeof(sin6));
2369 sin6.sin6_family = AF_INET6;
2370 sin6.sin6_len = sizeof(struct sockaddr_in6);
2371 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2372 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2373 sizeof(sin6.sin6_addr.s6_addr16[3]));
2374 sin6.sin6_port = sin->sin_port;
2375 to = (struct sockaddr *)&sin6;
2377 /* check and strip embedded scope junk */
2378 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2381 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2382 sctp_m_freem(m_notify);
2386 /* append to socket */
2387 SCTP_TCB_UNLOCK(stcb);
2388 SCTP_INP_WLOCK(stcb->sctp_ep);
2389 SCTP_TCB_LOCK(stcb);
2390 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
2391 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2392 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2393 /* not enough room */
2394 sctp_m_freem(m_notify);
2395 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2396 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2399 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2400 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2401 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2402 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2403 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2406 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2408 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2409 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2413 sctp_notify_adaption_layer(struct sctp_tcb *stcb,
2416 struct mbuf *m_notify;
2417 struct sctp_adaption_event *sai;
2418 struct sockaddr_in6 sin6, lsa6;
2419 struct sockaddr *to;
2421 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ADAPTIONEVNT))
2422 /* event not enabled */
2425 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2426 if (m_notify == NULL)
2429 m_notify->m_len = 0;
2430 sai = mtod(m_notify, struct sctp_adaption_event *);
2431 sai->sai_type = SCTP_ADAPTION_INDICATION;
2433 sai->sai_length = sizeof(struct sctp_adaption_event);
2434 sai->sai_adaption_ind = error;
2435 sai->sai_assoc_id = sctp_get_associd(stcb);
2437 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2438 m_notify->m_pkthdr.len = sizeof(struct sctp_adaption_event);
2439 m_notify->m_pkthdr.rcvif = 0;
2440 m_notify->m_len = sizeof(struct sctp_adaption_event);
2441 m_notify->m_next = NULL;
2443 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2444 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2445 (to->sa_family == AF_INET)) {
2446 struct sockaddr_in *sin;
2448 sin = (struct sockaddr_in *)to;
2449 bzero(&sin6, sizeof(sin6));
2450 sin6.sin6_family = AF_INET6;
2451 sin6.sin6_len = sizeof(struct sockaddr_in6);
2452 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2453 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2454 sizeof(sin6.sin6_addr.s6_addr16[3]));
2455 sin6.sin6_port = sin->sin_port;
2456 to = (struct sockaddr *)&sin6;
2458 /* check and strip embedded scope junk */
2459 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2461 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2462 sctp_m_freem(m_notify);
2465 /* append to socket */
2466 SCTP_TCB_UNLOCK(stcb);
2467 SCTP_INP_WLOCK(stcb->sctp_ep);
2468 SCTP_TCB_LOCK(stcb);
2469 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
2470 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2471 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2472 /* not enough room */
2473 sctp_m_freem(m_notify);
2474 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2475 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2478 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2479 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2480 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2481 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2482 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2485 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2487 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2488 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2492 sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
2495 struct mbuf *m_notify;
2496 struct sctp_pdapi_event *pdapi;
2497 struct sockaddr_in6 sin6, lsa6;
2498 struct sockaddr *to;
2500 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_PDAPIEVNT))
2501 /* event not enabled */
2504 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2505 if (m_notify == NULL)
2508 m_notify->m_len = 0;
2509 pdapi = mtod(m_notify, struct sctp_pdapi_event *);
2510 pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
2511 pdapi->pdapi_flags = 0;
2512 pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
2513 pdapi->pdapi_indication = error;
2514 pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
2516 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2517 m_notify->m_pkthdr.len = sizeof(struct sctp_pdapi_event);
2518 m_notify->m_pkthdr.rcvif = 0;
2519 m_notify->m_len = sizeof(struct sctp_pdapi_event);
2520 m_notify->m_next = NULL;
2522 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2523 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2524 (to->sa_family == AF_INET)) {
2525 struct sockaddr_in *sin;
2527 sin = (struct sockaddr_in *)to;
2528 bzero(&sin6, sizeof(sin6));
2529 sin6.sin6_family = AF_INET6;
2530 sin6.sin6_len = sizeof(struct sockaddr_in6);
2531 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2532 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2533 sizeof(sin6.sin6_addr.s6_addr16[3]));
2534 sin6.sin6_port = sin->sin_port;
2535 to = (struct sockaddr *)&sin6;
2537 /* check and strip embedded scope junk */
2538 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2540 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2541 sctp_m_freem(m_notify);
2544 /* append to socket */
2545 SCTP_TCB_UNLOCK(stcb);
2546 SCTP_INP_WLOCK(stcb->sctp_ep);
2547 SCTP_TCB_LOCK(stcb);
2548 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
2549 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2550 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2551 /* not enough room */
2552 sctp_m_freem(m_notify);
2553 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2554 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2557 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2558 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2559 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2560 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2561 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2564 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2566 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2567 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2571 sctp_notify_shutdown_event(struct sctp_tcb *stcb)
2573 struct mbuf *m_notify;
2574 struct sctp_shutdown_event *sse;
2575 struct sockaddr_in6 sin6, lsa6;
2576 struct sockaddr *to;
2579 * For TCP model AND UDP connected sockets we will send
2580 * an error up when an SHUTDOWN completes
2582 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2583 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2584 /* mark socket closed for read/write and wakeup! */
2585 socantrcvmore(stcb->sctp_socket);
2586 socantsendmore(stcb->sctp_socket);
2589 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2590 /* event not enabled */
2593 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2594 if (m_notify == NULL)
2597 m_notify->m_len = 0;
2598 sse = mtod(m_notify, struct sctp_shutdown_event *);
2599 sse->sse_type = SCTP_SHUTDOWN_EVENT;
2601 sse->sse_length = sizeof(struct sctp_shutdown_event);
2602 sse->sse_assoc_id = sctp_get_associd(stcb);
2604 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2605 m_notify->m_pkthdr.len = sizeof(struct sctp_shutdown_event);
2606 m_notify->m_pkthdr.rcvif = 0;
2607 m_notify->m_len = sizeof(struct sctp_shutdown_event);
2608 m_notify->m_next = NULL;
2610 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2611 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2612 to->sa_family == AF_INET) {
2613 struct sockaddr_in *sin;
2615 sin = (struct sockaddr_in *)to;
2616 bzero(&sin6, sizeof(sin6));
2617 sin6.sin6_family = AF_INET6;
2618 sin6.sin6_len = sizeof(struct sockaddr_in6);
2619 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2620 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2621 sizeof(sin6.sin6_addr.s6_addr16[3]));
2622 sin6.sin6_port = sin->sin_port;
2623 to = (struct sockaddr *)&sin6;
2625 /* check and strip embedded scope junk */
2626 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2628 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2629 sctp_m_freem(m_notify);
2632 /* append to socket */
2633 SCTP_TCB_UNLOCK(stcb);
2634 SCTP_INP_WLOCK(stcb->sctp_ep);
2635 SCTP_TCB_LOCK(stcb);
2636 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
2637 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2638 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2639 /* not enough room */
2640 sctp_m_freem(m_notify);
2641 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2642 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2645 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2646 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2647 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2648 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2649 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2652 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2654 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2655 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2659 sctp_notify_stream_reset(struct sctp_tcb *stcb,
2660 int number_entries, uint16_t *list, int flag)
2662 struct mbuf *m_notify;
2663 struct sctp_stream_reset_event *strreset;
2664 struct sockaddr_in6 sin6, lsa6;
2665 struct sockaddr *to;
2668 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2669 /* event not enabled */
2672 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2673 if (m_notify == NULL)
2676 m_notify->m_len = 0;
2677 len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
2678 if (len > M_TRAILINGSPACE(m_notify)) {
2679 MCLGET(m_notify, MB_WAIT);
2681 if (m_notify == NULL)
2685 if (len > M_TRAILINGSPACE(m_notify)) {
2686 /* never enough room */
2690 strreset = mtod(m_notify, struct sctp_stream_reset_event *);
2691 strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
2692 if (number_entries == 0) {
2693 strreset->strreset_flags = flag | SCTP_STRRESET_ALL_STREAMS;
2695 strreset->strreset_flags = flag | SCTP_STRRESET_STREAM_LIST;
2697 strreset->strreset_length = len;
2698 strreset->strreset_assoc_id = sctp_get_associd(stcb);
2699 if (number_entries) {
2701 for (i=0; i<number_entries; i++) {
2702 strreset->strreset_list[i] = list[i];
2705 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2706 m_notify->m_pkthdr.len = len;
2707 m_notify->m_pkthdr.rcvif = 0;
2708 m_notify->m_len = len;
2709 m_notify->m_next = NULL;
2710 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2712 sctp_m_freem(m_notify);
2715 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2716 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2717 to->sa_family == AF_INET) {
2718 struct sockaddr_in *sin;
2720 sin = (struct sockaddr_in *)to;
2721 bzero(&sin6, sizeof(sin6));
2722 sin6.sin6_family = AF_INET6;
2723 sin6.sin6_len = sizeof(struct sockaddr_in6);
2724 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2725 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2726 sizeof(sin6.sin6_addr.s6_addr16[3]));
2727 sin6.sin6_port = sin->sin_port;
2728 to = (struct sockaddr *)&sin6;
2730 /* check and strip embedded scope junk */
2731 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2733 /* append to socket */
2734 SCTP_TCB_UNLOCK(stcb);
2735 SCTP_INP_WLOCK(stcb->sctp_ep);
2736 SCTP_TCB_LOCK(stcb);
2737 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
2738 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2739 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2740 /* not enough room */
2741 sctp_m_freem(m_notify);
2742 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2743 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2746 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
2747 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2748 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2749 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2750 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2753 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2755 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2756 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2761 sctp_ulp_notify(u_int32_t notification, struct sctp_tcb *stcb,
2762 u_int32_t error, void *data)
2764 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2765 /* No notifications up when we are in a no socket state */
2768 if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
2769 /* Can't send up to a closed socket any notifications */
2772 switch (notification) {
2773 case SCTP_NOTIFY_ASSOC_UP:
2774 sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error);
2776 case SCTP_NOTIFY_ASSOC_DOWN:
2777 sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error);
2779 case SCTP_NOTIFY_INTERFACE_DOWN:
2781 struct sctp_nets *net;
2782 net = (struct sctp_nets *)data;
2783 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
2784 (struct sockaddr *)&net->ro._l_addr, error);
2787 case SCTP_NOTIFY_INTERFACE_UP:
2789 struct sctp_nets *net;
2790 net = (struct sctp_nets *)data;
2791 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
2792 (struct sockaddr *)&net->ro._l_addr, error);
2795 case SCTP_NOTIFY_INTERFACE_CONFIRMED:
2797 struct sctp_nets *net;
2798 net = (struct sctp_nets *)data;
2799 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
2800 (struct sockaddr *)&net->ro._l_addr, error);
2803 case SCTP_NOTIFY_DG_FAIL:
2804 sctp_notify_send_failed(stcb, error,
2805 (struct sctp_tmit_chunk *)data);
2807 case SCTP_NOTIFY_ADAPTION_INDICATION:
2808 /* Here the error is the adaption indication */
2809 sctp_notify_adaption_layer(stcb, error);
2811 case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
2812 sctp_notify_partial_delivery_indication(stcb, error);
2814 case SCTP_NOTIFY_STRDATA_ERR:
2816 case SCTP_NOTIFY_ASSOC_ABORTED:
2817 sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error);
2819 case SCTP_NOTIFY_PEER_OPENED_STREAM:
2821 case SCTP_NOTIFY_STREAM_OPENED_OK:
2823 case SCTP_NOTIFY_ASSOC_RESTART:
2824 sctp_notify_assoc_change(SCTP_RESTART, stcb, error);
2826 case SCTP_NOTIFY_HB_RESP:
2828 case SCTP_NOTIFY_STR_RESET_SEND:
2829 sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_OUTBOUND_STR);
2831 case SCTP_NOTIFY_STR_RESET_RECV:
2832 sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_INBOUND_STR);
2834 case SCTP_NOTIFY_ASCONF_ADD_IP:
2835 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
2838 case SCTP_NOTIFY_ASCONF_DELETE_IP:
2839 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
2842 case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
2843 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
2846 case SCTP_NOTIFY_ASCONF_SUCCESS:
2848 case SCTP_NOTIFY_ASCONF_FAILED:
2850 case SCTP_NOTIFY_PEER_SHUTDOWN:
2851 sctp_notify_shutdown_event(stcb);
2855 if (sctp_debug_on & SCTP_DEBUG_UTIL1) {
2856 kprintf("NOTIFY: unknown notification %xh (%u)\n",
2857 notification, notification);
2859 #endif /* SCTP_DEBUG */
2865 sctp_report_all_outbound(struct sctp_tcb *stcb)
2867 struct sctp_association *asoc;
2868 struct sctp_stream_out *outs;
2869 struct sctp_tmit_chunk *chk;
2873 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2876 /* now through all the gunk freeing chunks */
2877 TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
2878 /* now clean up any chunks here */
2879 chk = TAILQ_FIRST(&outs->outqueue);
2881 stcb->asoc.stream_queue_cnt--;
2882 TAILQ_REMOVE(&outs->outqueue, chk, sctp_next);
2883 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2884 SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2886 sctp_m_freem(chk->data);
2890 sctp_free_remote_addr(chk->whoTo);
2893 /* Free the chunk */
2894 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2895 sctppcbinfo.ipi_count_chunk--;
2896 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2897 panic("Chunk count is negative");
2899 sctppcbinfo.ipi_gencnt_chunk++;
2900 chk = TAILQ_FIRST(&outs->outqueue);
2903 /* pending send queue SHOULD be empty */
2904 if (!TAILQ_EMPTY(&asoc->send_queue)) {
2905 chk = TAILQ_FIRST(&asoc->send_queue);
2907 TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
2908 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2910 sctp_m_freem(chk->data);
2914 sctp_free_remote_addr(chk->whoTo);
2916 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2917 sctppcbinfo.ipi_count_chunk--;
2918 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2919 panic("Chunk count is negative");
2921 sctppcbinfo.ipi_gencnt_chunk++;
2922 chk = TAILQ_FIRST(&asoc->send_queue);
2925 /* sent queue SHOULD be empty */
2926 if (!TAILQ_EMPTY(&asoc->sent_queue)) {
2927 chk = TAILQ_FIRST(&asoc->sent_queue);
2929 TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
2930 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2931 SCTP_NOTIFY_DATAGRAM_SENT, chk);
2933 sctp_m_freem(chk->data);
2937 sctp_free_remote_addr(chk->whoTo);
2939 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2940 sctppcbinfo.ipi_count_chunk--;
2941 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2942 panic("Chunk count is negative");
2944 sctppcbinfo.ipi_gencnt_chunk++;
2945 chk = TAILQ_FIRST(&asoc->sent_queue);
2951 sctp_abort_notification(struct sctp_tcb *stcb, int error)
2954 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2957 /* Tell them we lost the asoc */
2958 sctp_report_all_outbound(stcb);
2959 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL);
2963 sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2964 struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *op_err)
2970 /* We have a TCB to abort, send notification too */
2971 vtag = stcb->asoc.peer_vtag;
2972 sctp_abort_notification(stcb, 0);
2974 sctp_send_abort(m, iphlen, sh, vtag, op_err);
2976 /* Ok, now lets free it */
2977 sctp_free_assoc(inp, stcb);
2979 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2980 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2981 sctp_inpcb_free(inp, 1);
2988 sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2989 int error, struct mbuf *op_err)
2994 /* Got to have a TCB */
2995 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2996 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2997 sctp_inpcb_free(inp, 1);
3002 vtag = stcb->asoc.peer_vtag;
3003 /* notify the ulp */
3004 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
3005 sctp_abort_notification(stcb, error);
3006 /* notify the peer */
3007 sctp_send_abort_tcb(stcb, op_err);
3008 /* now free the asoc */
3009 sctp_free_assoc(inp, stcb);
3013 sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
3014 struct sctp_inpcb *inp, struct mbuf *op_err)
3016 struct sctp_chunkhdr *ch, chunk_buf;
3017 unsigned int chk_length;
3019 /* Generate a TO address for future reference */
3020 if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
3021 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
3022 sctp_inpcb_free(inp, 1);
3025 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3026 sizeof(*ch), (u_int8_t *)&chunk_buf);
3027 while (ch != NULL) {
3028 chk_length = ntohs(ch->chunk_length);
3029 if (chk_length < sizeof(*ch)) {
3030 /* break to abort land */
3033 switch (ch->chunk_type) {
3034 case SCTP_PACKET_DROPPED:
3035 /* we don't respond to pkt-dropped */
3037 case SCTP_ABORT_ASSOCIATION:
3038 /* we don't respond with an ABORT to an ABORT */
3040 case SCTP_SHUTDOWN_COMPLETE:
3042 * we ignore it since we are not waiting for it
3046 case SCTP_SHUTDOWN_ACK:
3047 sctp_send_shutdown_complete2(m, iphlen, sh);
3052 offset += SCTP_SIZE32(chk_length);
3053 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3054 sizeof(*ch), (u_int8_t *)&chunk_buf);
3056 sctp_send_abort(m, iphlen, sh, 0, op_err);
3060 * check the inbound datagram to make sure there is not an abort
3061 * inside it, if there is return 1, else return 0.
3064 sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, int *vtagfill)
3066 struct sctp_chunkhdr *ch;
3067 struct sctp_init_chunk *init_chk, chunk_buf;
3069 unsigned int chk_length;
3071 offset = iphlen + sizeof(struct sctphdr);
3072 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
3073 (u_int8_t *)&chunk_buf);
3074 while (ch != NULL) {
3075 chk_length = ntohs(ch->chunk_length);
3076 if (chk_length < sizeof(*ch)) {
3077 /* packet is probably corrupt */
3080 /* we seem to be ok, is it an abort? */
3081 if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
3082 /* yep, tell them */
3085 if (ch->chunk_type == SCTP_INITIATION) {
3086 /* need to update the Vtag */
3087 init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
3088 offset, sizeof(*init_chk), (u_int8_t *)&chunk_buf);
3089 if (init_chk != NULL) {
3090 *vtagfill = ntohl(init_chk->init.initiate_tag);
3093 /* Nope, move to the next chunk */
3094 offset += SCTP_SIZE32(chk_length);
3095 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3096 sizeof(*ch), (u_int8_t *)&chunk_buf);
3102 * currently (2/02), ifa_addr embeds scope_id's and don't
3103 * have sin6_scope_id set (i.e. it's 0)
3104 * so, create this function to compare link local scopes
3107 sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
3109 struct sockaddr_in6 a, b;
3115 if (a.sin6_scope_id == 0)
3116 if (in6_recoverscope(&a, &a.sin6_addr, NULL)) {
3117 /* can't get scope, so can't match */
3120 if (b.sin6_scope_id == 0)
3121 if (in6_recoverscope(&b, &b.sin6_addr, NULL)) {
3122 /* can't get scope, so can't match */
3125 if (a.sin6_scope_id != b.sin6_scope_id)
3132 * returns a sockaddr_in6 with embedded scope recovered and removed
3134 struct sockaddr_in6 *
3135 sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
3138 /* check and strip embedded scope junk */
3139 if (addr->sin6_family == AF_INET6) {
3140 if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
3141 if (addr->sin6_scope_id == 0) {
3143 if (!in6_recoverscope(store, &store->sin6_addr,
3145 /* use the recovered scope */
3148 /* else, return the original "to" addr */
3156 * are the two addresses the same? currently a "scopeless" check
3157 * returns: 1 if same, 0 if not
3160 sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
3164 if (sa1 == NULL || sa2 == NULL)
3167 /* must be the same family */
3168 if (sa1->sa_family != sa2->sa_family)
3171 if (sa1->sa_family == AF_INET6) {
3172 /* IPv6 addresses */
3173 struct sockaddr_in6 *sin6_1, *sin6_2;
3175 sin6_1 = (struct sockaddr_in6 *)sa1;
3176 sin6_2 = (struct sockaddr_in6 *)sa2;
3177 return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr,
3178 &sin6_2->sin6_addr));
3179 } else if (sa1->sa_family == AF_INET) {
3180 /* IPv4 addresses */
3181 struct sockaddr_in *sin_1, *sin_2;
3183 sin_1 = (struct sockaddr_in *)sa1;
3184 sin_2 = (struct sockaddr_in *)sa2;
3185 return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
3187 /* we don't do these... */
3193 sctp_print_address(struct sockaddr *sa)
3196 if (sa->sa_family == AF_INET6) {
3197 struct sockaddr_in6 *sin6;
3198 sin6 = (struct sockaddr_in6 *)sa;
3199 kprintf("IPv6 address: %s:%d scope:%u\n",
3200 ip6_sprintf(&sin6->sin6_addr), ntohs(sin6->sin6_port),
3201 sin6->sin6_scope_id);
3202 } else if (sa->sa_family == AF_INET) {
3203 struct sockaddr_in *sin;
3204 sin = (struct sockaddr_in *)sa;
3205 kprintf("IPv4 address: %s:%d\n", inet_ntoa(sin->sin_addr),
3206 ntohs(sin->sin_port));
3213 sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
3215 if (iph->ip_v == IPVERSION) {
3216 struct sockaddr_in lsa, fsa;
3218 bzero(&lsa, sizeof(lsa));
3219 lsa.sin_len = sizeof(lsa);
3220 lsa.sin_family = AF_INET;
3221 lsa.sin_addr = iph->ip_src;
3222 lsa.sin_port = sh->src_port;
3223 bzero(&fsa, sizeof(fsa));
3224 fsa.sin_len = sizeof(fsa);
3225 fsa.sin_family = AF_INET;
3226 fsa.sin_addr = iph->ip_dst;
3227 fsa.sin_port = sh->dest_port;
3229 sctp_print_address((struct sockaddr *)&lsa);
3231 sctp_print_address((struct sockaddr *)&fsa);
3232 } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
3233 struct ip6_hdr *ip6;
3234 struct sockaddr_in6 lsa6, fsa6;
3236 ip6 = (struct ip6_hdr *)iph;
3237 bzero(&lsa6, sizeof(lsa6));
3238 lsa6.sin6_len = sizeof(lsa6);
3239 lsa6.sin6_family = AF_INET6;
3240 lsa6.sin6_addr = ip6->ip6_src;
3241 lsa6.sin6_port = sh->src_port;
3242 bzero(&fsa6, sizeof(fsa6));
3243 fsa6.sin6_len = sizeof(fsa6);
3244 fsa6.sin6_family = AF_INET6;
3245 fsa6.sin6_addr = ip6->ip6_dst;
3246 fsa6.sin6_port = sh->dest_port;
3248 sctp_print_address((struct sockaddr *)&lsa6);
3250 sctp_print_address((struct sockaddr *)&fsa6);
3254 #if defined(__FreeBSD__) || defined(__APPLE__)
3256 /* cloned from uipc_socket.c */
3258 #define SCTP_SBLINKRECORD(sb, m0) do { \
3259 if ((sb)->sb_lastrecord != NULL) \
3260 (sb)->sb_lastrecord->m_nextpkt = (m0); \
3262 (sb)->sb_mb = (m0); \
3263 (sb)->sb_lastrecord = (m0); \
3264 } while (/*CONSTCOND*/0)
3269 sctp_sbappendaddr_nocheck(struct signalsockbuf *ssb, struct sockaddr *asa, struct mbuf *m0,
3270 struct mbuf *control, u_int32_t tag,
3271 struct sctp_inpcb *inp)
3273 struct mbuf *m, *n, *nlast;
3276 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
3277 panic("sctp_sbappendaddr_nocheck");
3279 for (n = control; n; n = n->m_next) {
3280 if (n->m_next == 0) /* get pointer to last control buf */
3283 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3284 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
3285 uint32_t len = asa->sa_len; /* workaround GCC stupidity */
3289 MGETHDR(m, MB_DONTWAIT, MT_SONAME);
3295 kprintf("Duplicate mbuf allocated %p in and mget returned %p?\n",
3298 panic("more than once");
3303 m->m_len = asa->sa_len;
3304 bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
3310 n->m_next = m0; /* concatenate data to control */
3314 m->m_next = control;
3317 m->m_pkthdr.csum_data = (int)tag;
3320 for (n = m; n; n = n->m_next)
3321 sballoc(&ssb->sb, n);
3323 if (ssb->ssb_mb == NULL) {
3324 inp->sctp_vtag_first = tag;
3326 if ((n = ssb->ssb_mb) != NULL) {
3327 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3328 inp->sb_last_mpkt = NULL;
3330 if (inp->sb_last_mpkt)
3331 inp->sb_last_mpkt->m_nextpkt = m;
3333 while (n->m_nextpkt) {
3338 inp->sb_last_mpkt = m;
3340 inp->sb_last_mpkt = ssb->ssb_mb = m;
3341 inp->sctp_vtag_first = tag;
3343 SOCKBUF_UNLOCK(ssb);
3347 /*************HOLD THIS COMMENT FOR PATCH FILE OF
3348 *************ALTERNATE ROUTING CODE
3351 /*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
3352 *************ALTERNATE ROUTING CODE
3356 sctp_generate_invmanparam(int err)
3358 /* Return a MBUF with a invalid mandatory parameter */
3361 MGET(m, MB_DONTWAIT, MT_DATA);
3363 struct sctp_paramhdr *ph;
3364 m->m_len = sizeof(struct sctp_paramhdr);
3365 ph = mtod(m, struct sctp_paramhdr *);
3366 ph->param_length = htons(sizeof(struct sctp_paramhdr));
3367 ph->param_type = htons(err);
3373 sctp_should_be_moved(struct mbuf *this, struct sctp_association *asoc)
3377 * given a mbuf chain, look through it finding
3378 * the M_PKTHDR and return 1 if it belongs to
3379 * the association given. We tell this by
3380 * a kludge where we stuff the my_vtag of the asoc
3381 * into the m->m_pkthdr.csum_data/csum field.
3385 if (m->m_flags & M_PKTHDR) {
3387 #if defined(__OpenBSD__)
3388 if ((u_int32_t)m->m_pkthdr.csum == asoc->my_vtag)
3390 if ((u_int32_t)m->m_pkthdr.csum_data == asoc->my_vtag)
3403 sctp_get_first_vtag_from_sb(struct socket *so)
3405 struct mbuf *this, *at;
3409 lwkt_gettoken(&so->so_rcv.ssb_token);
3410 if (so->so_rcv.ssb_mb) {
3412 this = so->so_rcv.ssb_mb;
3415 /* get to the m_pkthdr */
3417 if (at->m_flags & M_PKTHDR)
3423 /* now do we have a m_pkthdr */
3424 if (at && (at->m_flags & M_PKTHDR)) {
3426 #if defined(__OpenBSD__)
3427 if ((u_int32_t)at->m_pkthdr.csum != 0)
3429 if ((u_int32_t)at->m_pkthdr.csum_data != 0)
3433 #if defined(__OpenBSD__)
3434 retval = (u_int32_t)at->m_pkthdr.csum;
3437 (u_int32_t)at->m_pkthdr.csum_data;
3442 this = this->m_nextpkt;
3446 lwkt_reltoken(&so->so_rcv.ssb_token);
3451 sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
3452 struct socket *new, struct sctp_tcb *stcb)
3454 struct mbuf **put, **take, *next, *this;
3455 struct signalsockbuf *old_sb, *new_sb;
3456 struct sctp_association *asoc;
3460 old_sb = &old->so_rcv;
3461 new_sb = &new->so_rcv;
3462 if (old_sb->ssb_mb == NULL) {
3463 /* Nothing to move */
3466 SOCKBUF_LOCK(old_sb);
3467 SOCKBUF_LOCK(new_sb);
3468 lwkt_gettoken(&old_sb->ssb_token);
3469 lwkt_gettoken(&new_sb->ssb_token);
3471 if (inp->sctp_vtag_first == asoc->my_vtag) {
3472 /* First one must be moved */
3474 for (mm = old_sb->ssb_mb; mm; mm = mm->m_next) {
3476 * Go down the chain and fix
3477 * the space allocation of the
3480 sbfree(&old_sb->sb, mm);
3481 sballoc(&new_sb->sb, mm);
3483 new_sb->ssb_mb = old_sb->ssb_mb;
3484 old_sb->ssb_mb = new_sb->ssb_mb->m_nextpkt;
3485 new_sb->ssb_mb->m_nextpkt = NULL;
3486 put = &new_sb->ssb_mb->m_nextpkt;
3489 put = &new_sb->ssb_mb;
3492 take = &old_sb->ssb_mb;
3493 next = old_sb->ssb_mb;
3496 /* postion for next one */
3497 next = this->m_nextpkt;
3498 /* check the tag of this packet */
3499 if (sctp_should_be_moved(this, asoc)) {
3500 /* yes this needs to be moved */
3502 *take = this->m_nextpkt;
3503 this->m_nextpkt = NULL;
3505 for (mm = this; mm; mm = mm->m_next) {
3507 * Go down the chain and fix
3508 * the space allocation of the
3511 sbfree(&old_sb->sb, mm);
3512 sballoc(&new_sb->sb, mm);
3514 put = &this->m_nextpkt;
3517 /* no advance our take point. */
3518 take = &this->m_nextpkt;
3523 * Ok so now we must re-postion vtag_first to
3524 * match the new first one since we moved the
3527 inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
3529 lwkt_reltoken(&new_sb->ssb_token);
3530 lwkt_reltoken(&old_sb->ssb_token);
3531 SOCKBUF_UNLOCK(old_sb);
3532 SOCKBUF_UNLOCK(new_sb);
3536 sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
3537 struct sctp_tmit_chunk *tp1)
3539 if (tp1->data == NULL) {
3542 #ifdef SCTP_MBCNT_LOGGING
3543 sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
3544 asoc->total_output_queue_size,
3546 asoc->total_output_mbuf_queue_size,
3549 if (asoc->total_output_queue_size >= tp1->book_size) {
3550 asoc->total_output_queue_size -= tp1->book_size;
3552 asoc->total_output_queue_size = 0;
3555 /* Now free the mbuf */
3556 if (asoc->total_output_mbuf_queue_size >= tp1->mbcnt) {
3557 asoc->total_output_mbuf_queue_size -= tp1->mbcnt;
3559 asoc->total_output_mbuf_queue_size = 0;
3561 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3562 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3563 if (stcb->sctp_socket->so_snd.ssb_cc >= tp1->book_size) {
3564 stcb->sctp_socket->so_snd.ssb_cc -= tp1->book_size;
3566 stcb->sctp_socket->so_snd.ssb_cc = 0;
3569 if (stcb->sctp_socket->so_snd.ssb_mbcnt >= tp1->mbcnt) {
3570 stcb->sctp_socket->so_snd.ssb_mbcnt -= tp1->mbcnt;
3572 stcb->sctp_socket->so_snd.ssb_mbcnt = 0;
3578 sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
3579 int reason, struct sctpchunk_listhead *queue)
3583 uint8_t foundeom = 0;
3586 ret_sz += tp1->book_size;
3587 tp1->sent = SCTP_FORWARD_TSN_SKIP;
3589 sctp_free_bufspace(stcb, &stcb->asoc, tp1);
3590 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1);
3591 sctp_m_freem(tp1->data);
3593 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
3595 if (tp1->flags & SCTP_PR_SCTP_BUFFER) {
3596 stcb->asoc.sent_queue_cnt_removeable--;
3598 if (queue == &stcb->asoc.send_queue) {
3599 TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
3600 /* on to the sent queue */
3601 TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
3603 stcb->asoc.sent_queue_cnt++;
3605 if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
3606 SCTP_DATA_NOT_FRAG) {
3607 /* not frag'ed we ae done */
3610 } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
3611 /* end of frag, we are done */
3615 /* Its a begin or middle piece, we must mark all of it */
3617 tp1 = TAILQ_NEXT(tp1, sctp_next);
3619 } while (tp1 && notdone);
3620 if ((foundeom == 0) && (queue == &stcb->asoc.sent_queue)) {
3622 * The multi-part message was scattered
3623 * across the send and sent queue.
3625 tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
3627 * recurse throught the send_queue too, starting at the
3631 ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
3632 &stcb->asoc.send_queue);
3634 kprintf("hmm, nothing on the send queue and no EOM?\n");
3641 * checks to see if the given address, sa, is one that is currently
3642 * known by the kernel
3643 * note: can't distinguish the same address on multiple interfaces and
3644 * doesn't handle multiple addresses with different zone/scope id's
3645 * note: ifa_ifwithaddr() compares the entire sockaddr struct
3648 sctp_find_ifa_by_addr(struct sockaddr *sa)
3652 /* go through all our known interfaces */
3653 TAILQ_FOREACH(ifn, &ifnet, if_list) {
3654 struct ifaddr_container *ifac;
3656 /* go through each interface addresses */
3657 TAILQ_FOREACH(ifac, &ifn->if_addrheads[mycpuid], ifa_link) {
3658 struct ifaddr *ifa = ifac->ifa;
3660 /* correct family? */
3661 if (ifa->ifa_addr->sa_family != sa->sa_family)
3665 if (ifa->ifa_addr->sa_family == AF_INET6) {
3667 struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
3668 sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
3669 if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
3670 /* create a copy and clear scope */
3671 memcpy(&sin6_tmp, sin1,
3672 sizeof(struct sockaddr_in6));
3674 in6_clearscope(&sin1->sin6_addr);
3676 sin2 = (struct sockaddr_in6 *)sa;
3677 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
3678 sizeof(struct in6_addr)) == 0) {
3684 if (ifa->ifa_addr->sa_family == AF_INET) {
3686 struct sockaddr_in *sin1, *sin2;
3687 sin1 = (struct sockaddr_in *)ifa->ifa_addr;
3688 sin2 = (struct sockaddr_in *)sa;
3689 if (sin1->sin_addr.s_addr ==
3690 sin2->sin_addr.s_addr) {
3695 /* else, not AF_INET or AF_INET6, so skip */
3696 } /* end foreach ifa */
3697 } /* end foreach ifn */
3705 * here we hack in a fix for Apple's m_copym for the case where the first mbuf
3706 * in the chain is a M_PKTHDR and the length is zero
3709 sctp_pkthdr_fix(struct mbuf *m)
3713 if ((m->m_flags & M_PKTHDR) == 0) {
3718 if (m->m_len != 0) {
3719 /* not a zero length PKTHDR mbuf */
3723 /* let's move in a word into the first mbuf... yes, ugly! */
3725 if (m_nxt == NULL) {
3726 /* umm... not a very useful mbuf chain... */
3729 if ((size_t)m_nxt->m_len > sizeof(long)) {
3730 /* move over a long */
3731 bcopy(mtod(m_nxt, caddr_t), mtod(m, caddr_t), sizeof(long));
3732 /* update mbuf data pointers and lengths */
3733 m->m_len += sizeof(long);
3734 m_nxt->m_data += sizeof(long);
3735 m_nxt->m_len -= sizeof(long);
3739 inline struct mbuf *
3740 sctp_m_copym(struct mbuf *m, int off, int len, int wait)
3743 return (m_copym(m, off, len, wait));
3745 #endif /* __APPLE__ */