1 /* $KAME: sctputil.c,v 1.36 2005/03/06 16:04:19 itojun Exp $ */
2 /* $DragonFly: src/sys/netinet/sctputil.c,v 1.4 2005/07/15 17:19:28 eirikn Exp $ */
5 * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Cisco Systems, Inc.
19 * 4. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #if !(defined(__OpenBSD__) || defined(__APPLE__))
37 #include "opt_ipsec.h"
39 #if defined(__FreeBSD__) || defined(__DragonFly__)
40 #include "opt_compat.h"
41 #include "opt_inet6.h"
43 #if !(defined(SCTP_BASE_FREEBSD) || defined(__DragonFly__))
44 #include "opt_mpath.h"
45 #endif /* SCTP_BASE_FREEBSD || __DragonFly__ */
47 #if defined(__NetBSD__)
52 #elif !defined(__OpenBSD__)
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/malloc.h>
60 #include <sys/domain.h>
61 #include <sys/protosw.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
65 #include <sys/kernel.h>
66 #include <sys/sysctl.h>
67 #include <sys/thread2.h>
69 #if defined(__FreeBSD__) || defined(__DragonFly__)
70 #include <sys/callout.h>
72 #include <netinet/sctp_callout.h> /* for callout_active() */
75 #include <net/radix.h>
76 #include <net/route.h>
80 #include <sys/domain.h>
84 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000)
85 #include <sys/limits.h>
87 #include <machine/limits.h>
91 #include <net/if_types.h>
92 #include <net/route.h>
94 #include <netinet/in.h>
95 #include <netinet/in_systm.h>
96 #include <netinet/ip.h>
97 #include <netinet/in_pcb.h>
98 #include <netinet/in_var.h>
99 #include <netinet/ip_var.h>
102 #include <netinet/ip6.h>
103 #include <netinet6/ip6_var.h>
105 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__DragonFly_)
106 #include <netinet6/in6_pcb.h>
107 #elif defined(__OpenBSD__)
108 #include <netinet/in_pcb.h>
113 #include <netinet/sctp_pcb.h>
117 #include <netinet6/ipsec.h>
118 #include <netkey/key.h>
124 #include <netinet/sctputil.h>
125 #include <netinet/sctp_var.h>
127 #include <netinet6/sctp6_var.h>
129 #include <netinet/sctp_header.h>
130 #include <netinet/sctp_output.h>
131 #include <netinet/sctp_hashdriver.h>
132 #include <netinet/sctp_uio.h>
133 #include <netinet/sctp_timer.h>
134 #include <netinet/sctp_crc32.h>
135 #include <netinet/sctp_indata.h> /* for sctp_deliver_data() */
136 #define NUMBER_OF_MTU_SIZES 18
139 extern u_int32_t sctp_debug_on;
142 #ifdef SCTP_STAT_LOGGING
143 int sctp_cwnd_log_at=0;
144 int sctp_cwnd_log_rolled=0;
145 struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
147 void 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;
172 sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
175 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
176 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAP;
177 sctp_clog[sctp_cwnd_log_at].x.map.base = map;
178 sctp_clog[sctp_cwnd_log_at].x.map.cum = cum;
179 sctp_clog[sctp_cwnd_log_at].x.map.high = high;
181 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
182 sctp_cwnd_log_at = 0;
183 sctp_cwnd_log_rolled = 1;
188 sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
192 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
193 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_FR;
194 sctp_clog[sctp_cwnd_log_at].x.fr.largest_tsn = biggest_tsn;
195 sctp_clog[sctp_cwnd_log_at].x.fr.largest_new_tsn = biggest_new_tsn;
196 sctp_clog[sctp_cwnd_log_at].x.fr.tsn = tsn;
198 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
199 sctp_cwnd_log_at = 0;
200 sctp_cwnd_log_rolled = 1;
205 sctp_log_strm_del(struct sctp_tmit_chunk *chk, struct sctp_tmit_chunk *poschk,
210 printf("Gak log of NULL?\n");
213 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
214 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_STRM;
215 sctp_clog[sctp_cwnd_log_at].x.strlog.n_tsn = chk->rec.data.TSN_seq;
216 sctp_clog[sctp_cwnd_log_at].x.strlog.n_sseq = chk->rec.data.stream_seq;
217 if (poschk != NULL) {
218 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn =
219 poschk->rec.data.TSN_seq;
220 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq =
221 poschk->rec.data.stream_seq;
223 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn = 0;
224 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq = 0;
227 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
228 sctp_cwnd_log_at = 0;
229 sctp_cwnd_log_rolled = 1;
234 sctp_log_cwnd(struct sctp_nets *net, int augment, uint8_t from)
237 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
238 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_CWND;
239 sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
240 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = net->cwnd;
241 sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
242 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = augment;
244 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
245 sctp_cwnd_log_at = 0;
246 sctp_cwnd_log_rolled = 1;
251 sctp_log_maxburst(struct sctp_nets *net, int error, int burst, uint8_t from)
253 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
254 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAXBURST;
255 sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
256 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = error;
257 sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
258 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = burst;
260 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
261 sctp_cwnd_log_at = 0;
262 sctp_cwnd_log_rolled = 1;
267 sctp_log_rwnd(uint8_t from, u_int32_t peers_rwnd , u_int32_t snd_size, u_int32_t overhead)
269 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
270 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
271 sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
272 sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = snd_size;
273 sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
274 sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = 0;
276 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
277 sctp_cwnd_log_at = 0;
278 sctp_cwnd_log_rolled = 1;
283 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)
285 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
286 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
287 sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
288 sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = flight_size;
289 sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
290 sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = a_rwndval;
292 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
293 sctp_cwnd_log_at = 0;
294 sctp_cwnd_log_rolled = 1;
299 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)
301 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
302 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MBCNT;
303 sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_size = total_oq;
304 sctp_clog[sctp_cwnd_log_at].x.mbcnt.size_change = book;
305 sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_mb_size = total_mbcnt_q;
306 sctp_clog[sctp_cwnd_log_at].x.mbcnt.mbcnt_change = mbcnt;
308 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
309 sctp_cwnd_log_at = 0;
310 sctp_cwnd_log_rolled = 1;
315 sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc)
318 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
319 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_BLOCK;
320 sctp_clog[sctp_cwnd_log_at].x.blk.maxmb = (u_int16_t)(so->so_snd.sb_mbmax/1024);
321 sctp_clog[sctp_cwnd_log_at].x.blk.onmb = asoc->total_output_mbuf_queue_size;
322 sctp_clog[sctp_cwnd_log_at].x.blk.maxsb = (u_int16_t)(so->so_snd.sb_hiwat/1024);
323 sctp_clog[sctp_cwnd_log_at].x.blk.onsb = asoc->total_output_queue_size;
324 sctp_clog[sctp_cwnd_log_at].x.blk.send_sent_qcnt = (u_int16_t)(asoc->send_queue_cnt + asoc->sent_queue_cnt);
325 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (u_int16_t)asoc->stream_queue_cnt;
327 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
328 sctp_cwnd_log_at = 0;
329 sctp_cwnd_log_rolled = 1;
334 sctp_fill_stat_log(struct mbuf *m)
336 struct sctp_cwnd_log_req *req;
337 int size_limit, num, i, at, cnt_out=0;
342 size_limit = (m->m_len - sizeof(struct sctp_cwnd_log_req));
343 if (size_limit < sizeof(struct sctp_cwnd_log)) {
346 req = mtod(m, struct sctp_cwnd_log_req *);
347 num = size_limit/sizeof(struct sctp_cwnd_log);
348 if (sctp_cwnd_log_rolled) {
349 req->num_in_log = SCTP_STAT_LOG_SIZE;
351 req->num_in_log = sctp_cwnd_log_at;
352 /* if the log has not rolled, we don't
353 * let you have old data.
355 if (req->end_at > sctp_cwnd_log_at) {
356 req->end_at = sctp_cwnd_log_at;
359 if ((num < SCTP_STAT_LOG_SIZE) &&
360 ((sctp_cwnd_log_rolled) || (sctp_cwnd_log_at > num))) {
361 /* we can't return all of it */
362 if (((req->start_at == 0) && (req->end_at == 0)) ||
363 (req->start_at >= SCTP_STAT_LOG_SIZE) ||
364 (req->end_at >= SCTP_STAT_LOG_SIZE)) {
365 /* No user request or user is wacked. */
367 req->end_at = sctp_cwnd_log_at - 1;
368 if ((sctp_cwnd_log_at - num) < 0) {
370 cc = num - sctp_cwnd_log_at;
371 req->start_at = SCTP_STAT_LOG_SIZE - cc;
373 req->start_at = sctp_cwnd_log_at - num;
378 if (req->start_at > req->end_at) {
379 cc = (SCTP_STAT_LOG_SIZE - req->start_at) +
383 cc = req->end_at - req->start_at;
391 /* We can return all of it */
393 req->end_at = sctp_cwnd_log_at - 1;
394 req->num_ret = sctp_cwnd_log_at;
396 for (i = 0, at = req->start_at; i < req->num_ret; i++) {
397 req->log[i] = sctp_clog[at];
400 if (at >= SCTP_STAT_LOG_SIZE)
403 m->m_len = (cnt_out * sizeof(struct sctp_cwnd_log_req)) + sizeof(struct sctp_cwnd_log_req);
409 #ifdef SCTP_AUDITING_ENABLED
410 u_int8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
411 static int sctp_audit_indx = 0;
414 void sctp_print_audit_report(void)
419 for (i=sctp_audit_indx;i<SCTP_AUDIT_SIZE;i++) {
420 if ((sctp_audit_data[i][0] == 0xe0) &&
421 (sctp_audit_data[i][1] == 0x01)) {
424 } else if (sctp_audit_data[i][0] == 0xf0) {
427 } else if ((sctp_audit_data[i][0] == 0xc0) &&
428 (sctp_audit_data[i][1] == 0x01)) {
432 printf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
433 (uint32_t)sctp_audit_data[i][1]);
438 for (i=0;i<sctp_audit_indx;i++) {
439 if ((sctp_audit_data[i][0] == 0xe0) &&
440 (sctp_audit_data[i][1] == 0x01)) {
443 } else if (sctp_audit_data[i][0] == 0xf0) {
446 } else if ((sctp_audit_data[i][0] == 0xc0) &&
447 (sctp_audit_data[i][1] == 0x01)) {
451 printf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
452 (uint32_t)sctp_audit_data[i][1]);
460 void sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
461 struct sctp_nets *net)
463 int resend_cnt, tot_out, rep, tot_book_cnt;
464 struct sctp_nets *lnet;
465 struct sctp_tmit_chunk *chk;
467 sctp_audit_data[sctp_audit_indx][0] = 0xAA;
468 sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
470 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
474 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
475 sctp_audit_data[sctp_audit_indx][1] = 0x01;
477 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
483 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
484 sctp_audit_data[sctp_audit_indx][1] = 0x02;
486 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
491 sctp_audit_data[sctp_audit_indx][0] = 0xA1;
492 sctp_audit_data[sctp_audit_indx][1] =
493 (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
495 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
500 resend_cnt = tot_out = 0;
501 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
502 if (chk->sent == SCTP_DATAGRAM_RESEND) {
504 } else if (chk->sent < SCTP_DATAGRAM_RESEND) {
505 tot_out += chk->book_size;
509 if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
510 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
511 sctp_audit_data[sctp_audit_indx][1] = 0xA1;
513 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
516 printf("resend_cnt:%d asoc-tot:%d\n",
517 resend_cnt, stcb->asoc.sent_queue_retran_cnt);
519 stcb->asoc.sent_queue_retran_cnt = resend_cnt;
520 sctp_audit_data[sctp_audit_indx][0] = 0xA2;
521 sctp_audit_data[sctp_audit_indx][1] =
522 (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
524 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
528 if (tot_out != stcb->asoc.total_flight) {
529 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
530 sctp_audit_data[sctp_audit_indx][1] = 0xA2;
532 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
536 printf("tot_flt:%d asoc_tot:%d\n", tot_out,
537 (int)stcb->asoc.total_flight);
538 stcb->asoc.total_flight = tot_out;
540 if (tot_book_cnt != stcb->asoc.total_flight_count) {
541 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
542 sctp_audit_data[sctp_audit_indx][1] = 0xA5;
544 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
548 printf("tot_flt_book:%d\n", tot_book);
550 stcb->asoc.total_flight_count = tot_book_cnt;
553 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
554 tot_out += lnet->flight_size;
556 if (tot_out != stcb->asoc.total_flight) {
557 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
558 sctp_audit_data[sctp_audit_indx][1] = 0xA3;
560 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
564 printf("real flight:%d net total was %d\n",
565 stcb->asoc.total_flight, tot_out);
566 /* now corrective action */
567 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
569 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
570 if ((chk->whoTo == lnet) &&
571 (chk->sent < SCTP_DATAGRAM_RESEND)) {
572 tot_out += chk->book_size;
575 if (lnet->flight_size != tot_out) {
576 printf("net:%x flight was %d corrected to %d\n",
577 (uint32_t)lnet, lnet->flight_size, tot_out);
578 lnet->flight_size = tot_out;
585 sctp_print_audit_report();
590 sctp_audit_log(u_int8_t ev, u_int8_t fd)
593 sctp_audit_data[sctp_audit_indx][0] = ev;
594 sctp_audit_data[sctp_audit_indx][1] = fd;
596 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
605 * a list of sizes based on typical mtu's, used only if next hop
608 static int sctp_mtu_sizes[] = {
630 find_next_best_mtu(int totsz)
634 * if we are in here we must find the next best fit based on the
635 * size of the dg that failed to be sent.
638 for (i = 0; i < NUMBER_OF_MTU_SIZES; i++) {
639 if (totsz < sctp_mtu_sizes[i]) {
646 return (sctp_mtu_sizes[perfer]);
650 sctp_fill_random_store(struct sctp_pcb *m)
653 * Here we use the MD5/SHA-1 to hash with our good randomNumbers
654 * and our counter. The result becomes our good random numbers and
655 * we then setup to give these out. Note that we do no lockig
656 * to protect this. This is ok, since if competing folks call
657 * this we will get more gobbled gook in the random store whic
658 * is what we want. There is a danger that two guys will use
659 * the same random numbers, but thats ok too since that
660 * is random as well :->
663 sctp_hash_digest((char *)m->random_numbers, sizeof(m->random_numbers),
664 (char *)&m->random_counter, sizeof(m->random_counter),
665 (char *)m->random_store);
670 sctp_select_initial_TSN(struct sctp_pcb *m)
673 * A true implementation should use random selection process to
674 * get the initial stream sequence number, using RFC1750 as a
680 if (m->initial_sequence_debug != 0) {
682 ret = m->initial_sequence_debug;
683 m->initial_sequence_debug++;
686 if ((m->store_at+sizeof(u_long)) > SCTP_SIGNATURE_SIZE) {
687 /* Refill the random store */
688 sctp_fill_random_store(m);
690 p = &m->random_store[(int)m->store_at];
693 m->store_at += sizeof(u_long);
697 u_int32_t sctp_select_a_tag(struct sctp_inpcb *m)
702 SCTP_GETTIME_TIMEVAL(&now);
705 x = sctp_select_initial_TSN(&m->sctp_ep);
710 if (sctp_is_vtag_good(m, x, &now)) {
719 sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
720 int for_a_init, uint32_t override_tag )
723 * Anything set to zero is taken care of by the allocation
728 * Up front select what scoping to apply on addresses I tell my peer
729 * Not sure what to do with these right now, we will need to come up
730 * with a way to set them. We may need to pass them through from the
731 * caller in the sctp_aloc_assoc() function.
734 /* init all variables to a known value.*/
735 asoc->state = SCTP_STATE_INUSE;
736 asoc->max_burst = m->sctp_ep.max_burst;
737 asoc->heart_beat_delay = m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT];
738 asoc->cookie_life = m->sctp_ep.def_cookie_life;
741 asoc->my_vtag = override_tag;
743 asoc->my_vtag = sctp_select_a_tag(m);
745 asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
746 sctp_select_initial_TSN(&m->sctp_ep);
747 asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
748 /* we are opptimisitic here */
749 asoc->peer_supports_asconf = 1;
750 asoc->peer_supports_asconf_setprim = 1;
751 asoc->peer_supports_pktdrop = 1;
753 asoc->sent_queue_retran_cnt = 0;
754 /* This will need to be adjusted */
755 asoc->last_cwr_tsn = asoc->init_seq_number - 1;
756 asoc->last_acked_seq = asoc->init_seq_number - 1;
757 asoc->advanced_peer_ack_point = asoc->last_acked_seq;
758 asoc->asconf_seq_in = asoc->last_acked_seq;
760 /* here we are different, we hold the next one we expect */
761 asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
763 asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max;
764 asoc->initial_rto = m->sctp_ep.initial_rto;
766 asoc->max_init_times = m->sctp_ep.max_init_times;
767 asoc->max_send_times = m->sctp_ep.max_send_times;
768 asoc->def_net_failure = m->sctp_ep.def_net_failure;
770 /* ECN Nonce initialization */
771 asoc->ecn_nonce_allowed = 0;
772 asoc->receiver_nonce_sum = 1;
773 asoc->nonce_sum_expect_base = 1;
774 asoc->nonce_sum_check = 1;
775 asoc->nonce_resync_tsn = 0;
776 asoc->nonce_wait_for_ecne = 0;
777 asoc->nonce_wait_tsn = 0;
779 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
783 /* Its a V6 socket */
784 inp6 = (struct in6pcb *)m;
785 asoc->ipv6_addr_legal = 1;
786 /* Now look at the binding flag to see if V4 will be legal */
788 #if defined(__OpenBSD__)
789 (0) /* we always do dual bind */
790 #elif defined (__NetBSD__)
791 (inp6->in6p_flags & IN6P_IPV6_V6ONLY)
793 (inp6->inp_flags & IN6P_IPV6_V6ONLY)
796 asoc->ipv4_addr_legal = 1;
798 /* V4 addresses are NOT legal on the association */
799 asoc->ipv4_addr_legal = 0;
802 /* Its a V4 socket, no - V6 */
803 asoc->ipv4_addr_legal = 1;
804 asoc->ipv6_addr_legal = 0;
808 asoc->my_rwnd = max(m->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND);
809 asoc->peers_rwnd = m->sctp_socket->so_rcv.sb_hiwat;
811 asoc->smallest_mtu = m->sctp_frag_point;
812 asoc->minrto = m->sctp_ep.sctp_minrto;
813 asoc->maxrto = m->sctp_ep.sctp_maxrto;
815 LIST_INIT(&asoc->sctp_local_addr_list);
816 TAILQ_INIT(&asoc->nets);
817 TAILQ_INIT(&asoc->pending_reply_queue);
818 asoc->last_asconf_ack_sent = NULL;
819 /* Setup to fill the hb random cache at first HB */
820 asoc->hb_random_idx = 4;
822 asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
825 * Now the stream parameters, here we allocate space for all
826 * streams that we request by default.
828 asoc->streamoutcnt = asoc->pre_open_streams =
829 m->sctp_ep.pre_open_stream_count;
830 MALLOC(asoc->strmout, struct sctp_stream_out *, asoc->streamoutcnt *
831 sizeof(struct sctp_stream_out), M_PCB, M_NOWAIT);
832 if (asoc->strmout == NULL) {
833 /* big trouble no memory */
836 for (i = 0; i < asoc->streamoutcnt; i++) {
838 * inbound side must be set to 0xffff,
839 * also NOTE when we get the INIT-ACK back (for INIT sender)
840 * we MUST reduce the count (streamoutcnt) but first check
841 * if we sent to any of the upper streams that were dropped
842 * (if some were). Those that were dropped must be notified
843 * to the upper layer as failed to send.
845 asoc->strmout[i].next_sequence_sent = 0x0;
846 TAILQ_INIT(&asoc->strmout[i].outqueue);
847 asoc->strmout[i].stream_no = i;
848 asoc->strmout[i].next_spoke.tqe_next = 0;
849 asoc->strmout[i].next_spoke.tqe_prev = 0;
851 /* Now the mapping array */
852 asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
854 MALLOC(asoc->mapping_array, u_int8_t *, SCTP_INITIAL_MAPPING_ARRAY,
857 MALLOC(asoc->mapping_array, u_int8_t *, asoc->mapping_array_size,
860 if (asoc->mapping_array == NULL) {
861 FREE(asoc->strmout, M_PCB);
864 memset(asoc->mapping_array, 0, asoc->mapping_array_size);
865 /* Now the init of the other outqueues */
866 TAILQ_INIT(&asoc->out_wheel);
867 TAILQ_INIT(&asoc->control_send_queue);
868 TAILQ_INIT(&asoc->send_queue);
869 TAILQ_INIT(&asoc->sent_queue);
870 TAILQ_INIT(&asoc->reasmqueue);
871 TAILQ_INIT(&asoc->delivery_queue);
872 asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome;
874 TAILQ_INIT(&asoc->asconf_queue);
879 sctp_expand_mapping_array(struct sctp_association *asoc)
881 /* mapping array needs to grow */
885 new_size = asoc->mapping_array_size + SCTP_MAPPING_ARRAY_INCR;
887 MALLOC(new_array, u_int8_t *, asoc->mapping_array_size
888 + SCTP_MAPPING_ARRAY_INCR, M_PCB, M_NOWAIT);
890 MALLOC(new_array, u_int8_t *, new_size, M_PCB, M_NOWAIT);
892 if (new_array == NULL) {
893 /* can't get more, forget it */
894 printf("No memory for expansion of SCTP mapping array %d\n",
898 memset(new_array, 0, new_size);
899 memcpy(new_array, asoc->mapping_array, asoc->mapping_array_size);
900 FREE(asoc->mapping_array, M_PCB);
901 asoc->mapping_array = new_array;
902 asoc->mapping_array_size = new_size;
907 sctp_timeout_handler(void *t)
909 struct sctp_inpcb *inp;
910 struct sctp_tcb *stcb;
911 struct sctp_nets *net;
912 struct sctp_timer *tmr;
914 #if defined(__APPLE__)
915 boolean_t funnel_state;
917 /* get BSD kernel funnel/mutex */
918 funnel_state = thread_funnel_set(network_flock, TRUE);
922 tmr = (struct sctp_timer *)t;
923 inp = (struct sctp_inpcb *)tmr->ep;
924 stcb = (struct sctp_tcb *)tmr->tcb;
925 net = (struct sctp_nets *)tmr->net;
929 #ifdef SCTP_AUDITING_ENABLED
930 sctp_audit_log(0xF0, (u_int8_t)tmr->type);
931 sctp_auditing(3, inp, stcb, net);
933 sctp_pegs[SCTP_TIMERS_EXP]++;
940 if (inp->sctp_socket == 0) {
942 #if defined(__APPLE__)
943 /* release BSD kernel funnel/mutex */
944 (void) thread_funnel_set(network_flock, FALSE);
946 SCTP_INP_WUNLOCK(inp);
950 if (stcb->asoc.state == 0) {
952 #if defined(__APPLE__)
953 /* release BSD kernel funnel/mutex */
954 (void) thread_funnel_set(network_flock, FALSE);
956 SCTP_INP_WUNLOCK(inp);
961 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
962 printf("Timer type %d goes off\n", tmr->type);
964 #endif /* SCTP_DEBUG */
966 if (!callout_active(&tmr->timer)) {
968 #if defined(__APPLE__)
969 /* release BSD kernel funnel/mutex */
970 (void) thread_funnel_set(network_flock, FALSE);
972 SCTP_INP_WUNLOCK(inp);
976 #if defined(__APPLE__)
977 /* clear the callout pending status here */
978 callout_stop(&tmr->timer);
983 SCTP_INP_INCR_REF(inp);
984 SCTP_INP_WUNLOCK(inp);
988 case SCTP_TIMER_TYPE_ITERATOR:
990 struct sctp_iterator *it;
991 it = (struct sctp_iterator *)inp;
992 sctp_iterator_timer(it);
995 /* call the handler for the appropriate timer type */
996 case SCTP_TIMER_TYPE_SEND:
997 sctp_pegs[SCTP_TMIT_TIMER]++;
998 stcb->asoc.num_send_timers_up--;
999 if (stcb->asoc.num_send_timers_up < 0) {
1000 stcb->asoc.num_send_timers_up = 0;
1002 if (sctp_t3rxt_timer(inp, stcb, net)) {
1003 /* no need to unlock on tcb its gone */
1007 #ifdef SCTP_AUDITING_ENABLED
1008 sctp_auditing(4, inp, stcb, net);
1010 sctp_chunk_output(inp, stcb, 1);
1011 if ((stcb->asoc.num_send_timers_up == 0) &&
1012 (stcb->asoc.sent_queue_cnt > 0)
1014 struct sctp_tmit_chunk *chk;
1016 * safeguard. If there on some on the sent queue
1017 * somewhere but no timers running something is
1018 * wrong... so we start a timer on the first chunk
1019 * on the send queue on whatever net it is sent to.
1021 sctp_pegs[SCTP_T3_SAFEGRD]++;
1022 chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
1023 sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
1027 case SCTP_TIMER_TYPE_INIT:
1028 if (sctp_t1init_timer(inp, stcb, net)) {
1029 /* no need to unlock on tcb its gone */
1032 /* We do output but not here */
1035 case SCTP_TIMER_TYPE_RECV:
1036 sctp_pegs[SCTP_RECV_TIMER]++;
1037 sctp_send_sack(stcb);
1038 #ifdef SCTP_AUDITING_ENABLED
1039 sctp_auditing(4, inp, stcb, net);
1041 sctp_chunk_output(inp, stcb, 4);
1043 case SCTP_TIMER_TYPE_SHUTDOWN:
1044 if (sctp_shutdown_timer(inp, stcb, net) ) {
1045 /* no need to unlock on tcb its gone */
1048 #ifdef SCTP_AUDITING_ENABLED
1049 sctp_auditing(4, inp, stcb, net);
1051 sctp_chunk_output(inp, stcb, 5);
1053 case SCTP_TIMER_TYPE_HEARTBEAT:
1054 if (sctp_heartbeat_timer(inp, stcb, net)) {
1055 /* no need to unlock on tcb its gone */
1058 #ifdef SCTP_AUDITING_ENABLED
1059 sctp_auditing(4, inp, stcb, net);
1061 sctp_chunk_output(inp, stcb, 6);
1063 case SCTP_TIMER_TYPE_COOKIE:
1064 if (sctp_cookie_timer(inp, stcb, net)) {
1065 /* no need to unlock on tcb its gone */
1068 #ifdef SCTP_AUDITING_ENABLED
1069 sctp_auditing(4, inp, stcb, net);
1071 sctp_chunk_output(inp, stcb, 1);
1073 case SCTP_TIMER_TYPE_NEWCOOKIE:
1077 SCTP_GETTIME_TIMEVAL(&tv);
1078 SCTP_INP_WLOCK(inp);
1079 inp->sctp_ep.time_of_secret_change = tv.tv_sec;
1080 inp->sctp_ep.last_secret_number =
1081 inp->sctp_ep.current_secret_number;
1082 inp->sctp_ep.current_secret_number++;
1083 if (inp->sctp_ep.current_secret_number >=
1084 SCTP_HOW_MANY_SECRETS) {
1085 inp->sctp_ep.current_secret_number = 0;
1087 secret = (int)inp->sctp_ep.current_secret_number;
1088 for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
1089 inp->sctp_ep.secret_key[secret][i] =
1090 sctp_select_initial_TSN(&inp->sctp_ep);
1092 SCTP_INP_WUNLOCK(inp);
1093 sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
1097 case SCTP_TIMER_TYPE_PATHMTURAISE:
1098 sctp_pathmtu_timer(inp, stcb, net);
1101 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1102 if (sctp_shutdownack_timer(inp, stcb, net)) {
1103 /* no need to unlock on tcb its gone */
1106 #ifdef SCTP_AUDITING_ENABLED
1107 sctp_auditing(4, inp, stcb, net);
1109 sctp_chunk_output(inp, stcb, 7);
1111 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1112 sctp_abort_an_association(inp, stcb,
1113 SCTP_SHUTDOWN_GUARD_EXPIRES, NULL);
1114 /* no need to unlock on tcb its gone */
1118 case SCTP_TIMER_TYPE_STRRESET:
1119 if (sctp_strreset_timer(inp, stcb, net)) {
1120 /* no need to unlock on tcb its gone */
1123 sctp_chunk_output(inp, stcb, 9);
1126 case SCTP_TIMER_TYPE_ASCONF:
1127 if (sctp_asconf_timer(inp, stcb, net)) {
1128 /* no need to unlock on tcb its gone */
1131 #ifdef SCTP_AUDITING_ENABLED
1132 sctp_auditing(4, inp, stcb, net);
1134 sctp_chunk_output(inp, stcb, 8);
1137 case SCTP_TIMER_TYPE_AUTOCLOSE:
1138 sctp_autoclose_timer(inp, stcb, net);
1139 sctp_chunk_output(inp, stcb, 10);
1142 case SCTP_TIMER_TYPE_INPKILL:
1143 /* special case, take away our
1144 * increment since WE are the killer
1146 SCTP_INP_WLOCK(inp);
1147 SCTP_INP_DECR_REF(inp);
1148 SCTP_INP_WUNLOCK(inp);
1149 sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL);
1150 sctp_inpcb_free(inp, 1);
1155 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1156 printf("sctp_timeout_handler:unknown timer %d\n",
1159 #endif /* SCTP_DEBUG */
1162 #ifdef SCTP_AUDITING_ENABLED
1163 sctp_audit_log(0xF1, (u_int8_t)tmr->type);
1164 sctp_auditing(5, inp, stcb, net);
1168 * Now we need to clean up the control chunk chain if an
1169 * ECNE is on it. It must be marked as UNSENT again so next
1170 * call will continue to send it until such time that we get
1171 * a CWR, to remove it. It is, however, less likely that we
1172 * will find a ecn echo on the chain though.
1174 sctp_fix_ecn_echo(&stcb->asoc);
1177 SCTP_TCB_UNLOCK(stcb);
1180 SCTP_INP_WLOCK(inp);
1181 SCTP_INP_DECR_REF(inp);
1182 SCTP_INP_WUNLOCK(inp);
1187 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1188 printf("Timer now complete (type %d)\n", typ);
1190 #endif /* SCTP_DEBUG */
1193 #if defined(__APPLE__)
1194 /* release BSD kernel funnel/mutex */
1195 (void) thread_funnel_set(network_flock, FALSE);
1200 sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1201 struct sctp_nets *net)
1204 struct sctp_timer *tmr;
1213 case SCTP_TIMER_TYPE_ITERATOR:
1215 struct sctp_iterator *it;
1216 it = (struct sctp_iterator *)inp;
1218 to_ticks = SCTP_ITERATOR_TICKS;
1221 case SCTP_TIMER_TYPE_SEND:
1222 /* Here we use the RTO timer */
1225 if ((stcb == NULL) || (net == NULL)) {
1228 tmr = &net->rxt_timer;
1229 if (net->RTO == 0) {
1230 rto_val = stcb->asoc.initial_rto;
1234 to_ticks = MSEC_TO_TICKS(rto_val);
1237 case SCTP_TIMER_TYPE_INIT:
1239 * Here we use the INIT timer default
1240 * usually about 1 minute.
1242 if ((stcb == NULL) || (net == NULL)) {
1245 tmr = &net->rxt_timer;
1246 if (net->RTO == 0) {
1247 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1249 to_ticks = MSEC_TO_TICKS(net->RTO);
1252 case SCTP_TIMER_TYPE_RECV:
1254 * Here we use the Delayed-Ack timer value from the inp
1255 * ususually about 200ms.
1260 tmr = &stcb->asoc.dack_timer;
1261 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV];
1263 case SCTP_TIMER_TYPE_SHUTDOWN:
1264 /* Here we use the RTO of the destination. */
1265 if ((stcb == NULL) || (net == NULL)) {
1269 if (net->RTO == 0) {
1270 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1272 to_ticks = MSEC_TO_TICKS(net->RTO);
1274 tmr = &net->rxt_timer;
1276 case SCTP_TIMER_TYPE_HEARTBEAT:
1278 * the net is used here so that we can add in the RTO.
1279 * Even though we use a different timer. We also add the
1280 * HB timer PLUS a random jitter.
1287 uint8_t this_random;
1288 int cnt_of_unconf=0;
1289 struct sctp_nets *lnet;
1291 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1292 if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
1297 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1298 printf("HB timer to start unconfirmed:%d hb_delay:%d\n",
1299 cnt_of_unconf, stcb->asoc.heart_beat_delay);
1302 if (stcb->asoc.hb_random_idx > 3) {
1303 rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1304 memcpy(stcb->asoc.hb_random_values, &rndval,
1305 sizeof(stcb->asoc.hb_random_values));
1306 this_random = stcb->asoc.hb_random_values[0];
1307 stcb->asoc.hb_random_idx = 0;
1308 stcb->asoc.hb_ect_randombit = 0;
1310 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
1311 stcb->asoc.hb_random_idx++;
1312 stcb->asoc.hb_ect_randombit = 0;
1315 * this_random will be 0 - 256 ms
1318 if ((stcb->asoc.heart_beat_delay == 0) &&
1319 (cnt_of_unconf == 0)) {
1320 /* no HB on this inp after confirmations */
1324 struct sctp_nets *lnet;
1326 delay = stcb->asoc.heart_beat_delay;
1327 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1328 if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
1329 ((lnet->dest_state & SCTP_ADDR_OUT_OF_SCOPE) == 0) &&
1330 (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
1334 if (net->RTO == 0) {
1335 /* Never been checked */
1336 to_ticks = this_random + stcb->asoc.initial_rto + delay;
1338 /* set rto_val to the ms */
1339 to_ticks = delay + net->RTO + this_random;
1342 if (cnt_of_unconf) {
1343 to_ticks = this_random + stcb->asoc.initial_rto;
1345 to_ticks = stcb->asoc.heart_beat_delay + this_random + stcb->asoc.initial_rto;
1349 * Now we must convert the to_ticks that are now in
1355 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1356 printf("Timer to expire in %d ticks\n", to_ticks);
1359 tmr = &stcb->asoc.hb_timer;
1362 case SCTP_TIMER_TYPE_COOKIE:
1364 * Here we can use the RTO timer from the network since
1365 * one RTT was compelete. If a retran happened then we will
1366 * be using the RTO initial value.
1368 if ((stcb == NULL) || (net == NULL)) {
1371 if (net->RTO == 0) {
1372 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1374 to_ticks = MSEC_TO_TICKS(net->RTO);
1376 tmr = &net->rxt_timer;
1378 case SCTP_TIMER_TYPE_NEWCOOKIE:
1380 * nothing needed but the endpoint here
1381 * ususually about 60 minutes.
1383 tmr = &inp->sctp_ep.signature_change;
1384 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
1386 case SCTP_TIMER_TYPE_INPKILL:
1388 * The inp is setup to die. We re-use the
1389 * signature_chage timer since that has
1390 * stopped and we are in the GONE state.
1392 tmr = &inp->sctp_ep.signature_change;
1393 to_ticks = (SCTP_INP_KILL_TIMEOUT * hz) / 1000;
1395 case SCTP_TIMER_TYPE_PATHMTURAISE:
1397 * Here we use the value found in the EP for PMTU
1398 * ususually about 10 minutes.
1406 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
1407 tmr = &net->pmtu_timer;
1409 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1410 /* Here we use the RTO of the destination */
1411 if ((stcb == NULL) || (net == NULL)) {
1414 if (net->RTO == 0) {
1415 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1417 to_ticks = MSEC_TO_TICKS(net->RTO);
1419 tmr = &net->rxt_timer;
1421 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1423 * Here we use the endpoints shutdown guard timer
1424 * usually about 3 minutes.
1429 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
1430 tmr = &stcb->asoc.shut_guard_timer;
1432 case SCTP_TIMER_TYPE_STRRESET:
1434 * Here the timer comes from the inp
1435 * but its value is from the RTO.
1437 if ((stcb == NULL) || (net == NULL)) {
1440 if (net->RTO == 0) {
1441 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1443 to_ticks = MSEC_TO_TICKS(net->RTO);
1445 tmr = &stcb->asoc.strreset_timer;
1448 case SCTP_TIMER_TYPE_ASCONF:
1450 * Here the timer comes from the inp
1451 * but its value is from the RTO.
1453 if ((stcb == NULL) || (net == NULL)) {
1456 if (net->RTO == 0) {
1457 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1459 to_ticks = MSEC_TO_TICKS(net->RTO);
1461 tmr = &stcb->asoc.asconf_timer;
1463 case SCTP_TIMER_TYPE_AUTOCLOSE:
1467 if (stcb->asoc.sctp_autoclose_ticks == 0) {
1468 /* Really an error since stcb is NOT set to autoclose */
1471 to_ticks = stcb->asoc.sctp_autoclose_ticks;
1472 tmr = &stcb->asoc.autoclose_timer;
1476 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1477 printf("sctp_timer_start:Unknown timer type %d\n",
1480 #endif /* SCTP_DEBUG */
1484 if ((to_ticks <= 0) || (tmr == NULL)) {
1486 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1487 printf("sctp_timer_start:%d:software error to_ticks:%d tmr:%p not set ??\n",
1488 t_type, to_ticks, tmr);
1490 #endif /* SCTP_DEBUG */
1493 if (callout_pending(&tmr->timer)) {
1495 * we do NOT allow you to have it already running.
1496 * if it is we leave the current one up unchanged
1500 /* At this point we can proceed */
1501 if (t_type == SCTP_TIMER_TYPE_SEND) {
1502 stcb->asoc.num_send_timers_up++;
1505 tmr->ep = (void *)inp;
1506 tmr->tcb = (void *)stcb;
1507 tmr->net = (void *)net;
1508 callout_reset(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
1513 sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1514 struct sctp_nets *net)
1516 struct sctp_timer *tmr;
1523 case SCTP_TIMER_TYPE_ITERATOR:
1525 struct sctp_iterator *it;
1526 it = (struct sctp_iterator *)inp;
1530 case SCTP_TIMER_TYPE_SEND:
1531 if ((stcb == NULL) || (net == NULL)) {
1534 tmr = &net->rxt_timer;
1536 case SCTP_TIMER_TYPE_INIT:
1537 if ((stcb == NULL) || (net == NULL)) {
1540 tmr = &net->rxt_timer;
1542 case SCTP_TIMER_TYPE_RECV:
1546 tmr = &stcb->asoc.dack_timer;
1548 case SCTP_TIMER_TYPE_SHUTDOWN:
1549 if ((stcb == NULL) || (net == NULL)) {
1552 tmr = &net->rxt_timer;
1554 case SCTP_TIMER_TYPE_HEARTBEAT:
1558 tmr = &stcb->asoc.hb_timer;
1560 case SCTP_TIMER_TYPE_COOKIE:
1561 if ((stcb == NULL) || (net == NULL)) {
1564 tmr = &net->rxt_timer;
1566 case SCTP_TIMER_TYPE_NEWCOOKIE:
1567 /* nothing needed but the endpoint here */
1568 tmr = &inp->sctp_ep.signature_change;
1569 /* We re-use the newcookie timer for
1570 * the INP kill timer. We must assure
1571 * that we do not kill it by accident.
1574 case SCTP_TIMER_TYPE_INPKILL:
1576 * The inp is setup to die. We re-use the
1577 * signature_chage timer since that has
1578 * stopped and we are in the GONE state.
1580 tmr = &inp->sctp_ep.signature_change;
1582 case SCTP_TIMER_TYPE_PATHMTURAISE:
1589 tmr = &net->pmtu_timer;
1591 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1592 if ((stcb == NULL) || (net == NULL)) {
1595 tmr = &net->rxt_timer;
1597 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1601 tmr = &stcb->asoc.shut_guard_timer;
1603 case SCTP_TIMER_TYPE_STRRESET:
1607 tmr = &stcb->asoc.strreset_timer;
1609 case SCTP_TIMER_TYPE_ASCONF:
1613 tmr = &stcb->asoc.asconf_timer;
1615 case SCTP_TIMER_TYPE_AUTOCLOSE:
1619 tmr = &stcb->asoc.autoclose_timer;
1623 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
1624 printf("sctp_timer_stop:Unknown timer type %d\n",
1627 #endif /* SCTP_DEBUG */
1633 if ((tmr->type != t_type) && tmr->type) {
1635 * Ok we have a timer that is under joint use. Cookie timer
1636 * per chance with the SEND timer. We therefore are NOT
1637 * running the timer that the caller wants stopped. So just
1642 if (t_type == SCTP_TIMER_TYPE_SEND) {
1643 stcb->asoc.num_send_timers_up--;
1644 if (stcb->asoc.num_send_timers_up < 0) {
1645 stcb->asoc.num_send_timers_up = 0;
1648 callout_stop(&tmr->timer);
1652 #ifdef SCTP_USE_ADLER32
1654 update_adler32(uint32_t adler, uint8_t *buf, int32_t len)
1656 u_int32_t s1 = adler & 0xffff;
1657 u_int32_t s2 = (adler >> 16) & 0xffff;
1660 for (n = 0; n < len; n++, buf++) {
1661 /* s1 = (s1 + buf[n]) % BASE */
1665 * now if we need to, we do a mod by subtracting. It seems
1666 * a bit faster since I really will only ever do one subtract
1667 * at the MOST, since buf[n] is a max of 255.
1669 if (s1 >= SCTP_ADLER32_BASE) {
1670 s1 -= SCTP_ADLER32_BASE;
1672 /* s2 = (s2 + s1) % BASE */
1676 * again, it is more efficent (it seems) to subtract since
1677 * the most s2 will ever be is (BASE-1 + BASE-1) in the worse
1678 * case. This would then be (2 * BASE) - 2, which will still
1679 * only do one subtract. On Intel this is much better to do
1680 * this way and avoid the divide. Have not -pg'd on sparc.
1682 if (s2 >= SCTP_ADLER32_BASE) {
1683 s2 -= SCTP_ADLER32_BASE;
1686 /* Return the adler32 of the bytes buf[0..len-1] */
1687 return ((s2 << 16) + s1);
1694 sctp_calculate_len(struct mbuf *m)
1706 #if defined(SCTP_WITH_NO_CSUM)
1709 sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1712 * given a mbuf chain with a packetheader offset by 'offset'
1713 * pointing at a sctphdr (with csum set to 0) go through
1714 * the chain of m_next's and calculate the SCTP checksum.
1715 * This is currently Adler32 but will change to CRC32x
1716 * soon. Also has a side bonus calculate the total length
1717 * of the mbuf chain.
1718 * Note: if offset is greater than the total mbuf length,
1719 * checksum=1, pktlen=0 is returned (ie. no real error code)
1723 *pktlen = sctp_calculate_len(m);
1727 #elif defined(SCTP_USE_INCHKSUM)
1729 #include <machine/in_cksum.h>
1732 sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1735 * given a mbuf chain with a packetheader offset by 'offset'
1736 * pointing at a sctphdr (with csum set to 0) go through
1737 * the chain of m_next's and calculate the SCTP checksum.
1738 * This is currently Adler32 but will change to CRC32x
1739 * soon. Also has a side bonus calculate the total length
1740 * of the mbuf chain.
1741 * Note: if offset is greater than the total mbuf length,
1742 * checksum=1, pktlen=0 is returned (ie. no real error code)
1746 uint32_t the_sum, retsum;
1753 the_sum = (uint32_t)(in_cksum_skip(m, tlen, offset));
1755 *pktlen = (tlen-offset);
1756 retsum = htons(the_sum);
1763 sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1766 * given a mbuf chain with a packetheader offset by 'offset'
1767 * pointing at a sctphdr (with csum set to 0) go through
1768 * the chain of m_next's and calculate the SCTP checksum.
1769 * This is currently Adler32 but will change to CRC32x
1770 * soon. Also has a side bonus calculate the total length
1771 * of the mbuf chain.
1772 * Note: if offset is greater than the total mbuf length,
1773 * checksum=1, pktlen=0 is returned (ie. no real error code)
1776 #ifdef SCTP_USE_ADLER32
1779 uint32_t base = 0xffffffff;
1780 #endif /* SCTP_USE_ADLER32 */
1783 /* find the correct mbuf and offset into mbuf */
1784 while ((at != NULL) && (offset > (uint32_t)at->m_len)) {
1785 offset -= at->m_len; /* update remaining offset left */
1789 while (at != NULL) {
1790 #ifdef SCTP_USE_ADLER32
1791 base = update_adler32(base, at->m_data + offset,
1792 at->m_len - offset);
1794 base = update_crc32(base, at->m_data + offset,
1795 at->m_len - offset);
1796 #endif /* SCTP_USE_ADLER32 */
1797 tlen += at->m_len - offset;
1798 /* we only offset once into the first mbuf */
1804 if (pktlen != NULL) {
1807 #ifdef SCTP_USE_ADLER32
1812 base = sctp_csum_finalize(base);
1821 sctp_mtu_size_reset(struct sctp_inpcb *inp,
1822 struct sctp_association *asoc, u_long mtu)
1825 * Reset the P-MTU size on this association, this involves changing
1826 * the asoc MTU, going through ANY chunk+overhead larger than mtu
1827 * to allow the DF flag to be cleared.
1829 struct sctp_tmit_chunk *chk;
1830 struct sctp_stream_out *strm;
1831 unsigned int eff_mtu, ovh;
1832 asoc->smallest_mtu = mtu;
1833 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1834 ovh = SCTP_MIN_OVERHEAD;
1836 ovh = SCTP_MIN_V4_OVERHEAD;
1838 eff_mtu = mtu - ovh;
1839 /* Now mark any chunks that need to let IP fragment */
1840 TAILQ_FOREACH(strm, &asoc->out_wheel, next_spoke) {
1841 TAILQ_FOREACH(chk, &strm->outqueue, sctp_next) {
1842 if (chk->send_size > eff_mtu) {
1843 chk->flags &= SCTP_DONT_FRAGMENT;
1844 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1848 TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
1849 if (chk->send_size > eff_mtu) {
1850 chk->flags &= SCTP_DONT_FRAGMENT;
1851 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1854 TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
1855 if (chk->send_size > eff_mtu) {
1856 chk->flags &= SCTP_DONT_FRAGMENT;
1857 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1864 * given an association and starting time of the current RTT period
1865 * return RTO in number of usecs
1866 * net should point to the current network
1869 sctp_calculate_rto(struct sctp_tcb *stcb,
1870 struct sctp_association *asoc,
1871 struct sctp_nets *net,
1872 struct timeval *old)
1875 * given an association and the starting time of the current RTT
1876 * period (in value1/value2) return RTO in number of usecs.
1880 unsigned int new_rto = 0;
1881 int first_measure = 0;
1884 /************************/
1885 /* 1. calculate new RTT */
1886 /************************/
1887 /* get the current time */
1888 SCTP_GETTIME_TIMEVAL(&now);
1889 /* compute the RTT value */
1890 if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
1891 calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
1892 if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
1893 calc_time += (((u_long)now.tv_usec -
1894 (u_long)old->tv_usec)/1000);
1895 } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
1896 /* Borrow 1,000ms from current calculation */
1898 /* Add in the slop over */
1899 calc_time += ((int)now.tv_usec/1000);
1900 /* Add in the pre-second ms's */
1901 calc_time += (((int)1000000 - (int)old->tv_usec)/1000);
1903 } else if ((u_long)now.tv_sec == (u_long)old->tv_sec) {
1904 if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
1905 calc_time = ((u_long)now.tv_usec -
1906 (u_long)old->tv_usec)/1000;
1907 } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
1908 /* impossible .. garbage in nothing out */
1909 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1911 /* impossible .. garbage in nothing out */
1912 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1915 /* Clock wrapped? */
1916 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1918 /***************************/
1919 /* 2. update RTTVAR & SRTT */
1920 /***************************/
1922 /* if (net->lastsv || net->lastsa) {*/
1923 /* per Section 5.3.1 C3 in SCTP */
1924 /* net->lastsv = (int) *//* RTTVAR */
1925 /* (((double)(1.0 - 0.25) * (double)net->lastsv) +
1926 (double)(0.25 * (double)abs(net->lastsa - calc_time)));
1927 net->lastsa = (int) */ /* SRTT */
1928 /*(((double)(1.0 - 0.125) * (double)net->lastsa) +
1929 (double)(0.125 * (double)calc_time));
1931 *//* the first RTT calculation, per C2 Section 5.3.1 */
1932 /* net->lastsa = calc_time; *//* SRTT */
1933 /* net->lastsv = calc_time / 2; *//* RTTVAR */
1935 /* if RTTVAR goes to 0 you set to clock grainularity */
1936 /* if (net->lastsv == 0) {
1937 net->lastsv = SCTP_CLOCK_GRANULARITY;
1939 new_rto = net->lastsa + 4 * net->lastsv;
1942 o_calctime = calc_time;
1943 /* this is Van Jacobson's integer version */
1945 calc_time -= (net->lastsa >> 3);
1946 net->lastsa += calc_time;
1947 if (calc_time < 0) {
1948 calc_time = -calc_time;
1950 calc_time -= (net->lastsv >> 2);
1951 net->lastsv += calc_time;
1952 if (net->lastsv == 0) {
1953 net->lastsv = SCTP_CLOCK_GRANULARITY;
1956 /* First RTO measurment */
1957 net->lastsa = calc_time;
1958 net->lastsv = calc_time >> 1;
1961 new_rto = ((net->lastsa >> 2) + net->lastsv) >> 1;
1962 if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
1963 (stcb->asoc.sat_network_lockout == 0)) {
1964 stcb->asoc.sat_network = 1;
1965 } else if ((!first_measure) && stcb->asoc.sat_network) {
1966 stcb->asoc.sat_network = 0;
1967 stcb->asoc.sat_network_lockout = 1;
1969 /* bound it, per C6/C7 in Section 5.3.1 */
1970 if (new_rto < stcb->asoc.minrto) {
1971 new_rto = stcb->asoc.minrto;
1973 if (new_rto > stcb->asoc.maxrto) {
1974 new_rto = stcb->asoc.maxrto;
1976 /* we are now returning the RTT Smoothed */
1977 return ((u_int32_t)new_rto);
1982 * return a pointer to a contiguous piece of data from the given
1983 * mbuf chain starting at 'off' for 'len' bytes. If the desired
1984 * piece spans more than one mbuf, a copy is made at 'ptr'.
1985 * caller must ensure that the buffer size is >= 'len'
1986 * returns NULL if there there isn't 'len' bytes in the chain.
1989 sctp_m_getptr(struct mbuf *m, int off, int len, u_int8_t *in_ptr)
1994 if ((off < 0) || (len <= 0))
1997 /* find the desired start location */
1998 while ((m != NULL) && (off > 0)) {
2007 /* is the current mbuf large enough (eg. contiguous)? */
2008 if ((m->m_len - off) >= len) {
2009 return (mtod(m, caddr_t) + off);
2011 /* else, it spans more than one mbuf, so save a temp copy... */
2012 while ((m != NULL) && (len > 0)) {
2013 count = min(m->m_len - off, len);
2014 bcopy(mtod(m, caddr_t) + off, ptr, count);
2020 if ((m == NULL) && (len > 0))
2023 return ((caddr_t)in_ptr);
2028 struct sctp_paramhdr *
2029 sctp_get_next_param(struct mbuf *m,
2031 struct sctp_paramhdr *pull,
2034 /* This just provides a typed signature to Peter's Pull routine */
2035 return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
2041 sctp_add_pad_tombuf(struct mbuf *m, int padlen)
2044 * add padlen bytes of 0 filled padding to the end of the mbuf.
2045 * If padlen is > 3 this routine will fail.
2052 if (M_TRAILINGSPACE(m)) {
2055 * We hope the majority of the time we hit here :)
2057 dp = (u_int8_t *)(mtod(m, caddr_t) + m->m_len);
2060 /* Hard way we must grow the mbuf */
2062 MGET(tmp, MB_DONTWAIT, MT_DATA);
2064 /* Out of space GAK! we are in big trouble. */
2067 /* setup and insert in middle */
2068 tmp->m_next = m->m_next;
2069 tmp->m_len = padlen;
2071 dp = mtod(tmp, u_int8_t *);
2073 /* zero out the pad */
2074 for (i= 0; i < padlen; i++) {
2082 sctp_pad_lastmbuf(struct mbuf *m, int padval)
2084 /* find the last mbuf in chain and pad it */
2088 if (m_at->m_next == NULL) {
2089 return (sctp_add_pad_tombuf(m_at, padval));
2091 m_at = m_at->m_next;
2097 sctp_notify_assoc_change(u_int32_t event, struct sctp_tcb *stcb,
2100 struct mbuf *m_notify;
2101 struct sctp_assoc_change *sac;
2102 struct sockaddr *to;
2103 struct sockaddr_in6 sin6, lsa6;
2106 * First if we are are going down dump everything we
2107 * can to the socket rcv queue.
2109 if ((event == SCTP_SHUTDOWN_COMP) || (event == SCTP_COMM_LOST)) {
2110 sctp_deliver_data(stcb, &stcb->asoc, NULL, 0);
2114 * For TCP model AND UDP connected sockets we will send
2115 * an error up when an ABORT comes in.
2117 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2118 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
2119 (event == SCTP_COMM_LOST)) {
2120 stcb->sctp_socket->so_error = ECONNRESET;
2121 /* Wake ANY sleepers */
2122 sowwakeup(stcb->sctp_socket);
2123 sorwakeup(stcb->sctp_socket);
2126 if ((event == SCTP_COMM_UP) &&
2127 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2128 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
2129 soisconnected(stcb->sctp_socket);
2132 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
2133 /* event not enabled */
2136 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2137 if (m_notify == NULL)
2140 m_notify->m_len = 0;
2142 sac = mtod(m_notify, struct sctp_assoc_change *);
2143 sac->sac_type = SCTP_ASSOC_CHANGE;
2145 sac->sac_length = sizeof(struct sctp_assoc_change);
2146 sac->sac_state = event;
2147 sac->sac_error = error;
2148 /* XXX verify these stream counts */
2149 sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
2150 sac->sac_inbound_streams = stcb->asoc.streamincnt;
2151 sac->sac_assoc_id = sctp_get_associd(stcb);
2153 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2154 m_notify->m_pkthdr.len = sizeof(struct sctp_assoc_change);
2155 m_notify->m_pkthdr.rcvif = 0;
2156 m_notify->m_len = sizeof(struct sctp_assoc_change);
2157 m_notify->m_next = NULL;
2159 /* append to socket */
2160 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2161 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2162 to->sa_family == AF_INET) {
2163 struct sockaddr_in *sin;
2165 sin = (struct sockaddr_in *)to;
2166 bzero(&sin6, sizeof(sin6));
2167 sin6.sin6_family = AF_INET6;
2168 sin6.sin6_len = sizeof(struct sockaddr_in6);
2169 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2170 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2171 sizeof(sin6.sin6_addr.s6_addr16[3]));
2172 sin6.sin6_port = sin->sin_port;
2173 to = (struct sockaddr *)&sin6;
2175 /* check and strip embedded scope junk */
2176 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2179 * We need to always notify comm changes.
2180 * if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2181 * sctp_m_freem(m_notify);
2185 SCTP_TCB_UNLOCK(stcb);
2186 SCTP_INP_WLOCK(stcb->sctp_ep);
2187 SCTP_TCB_LOCK(stcb);
2188 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
2189 to, m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2190 /* not enough room */
2191 sctp_m_freem(m_notify);
2192 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2195 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2196 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2197 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2198 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2201 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2203 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2204 /* Wake up any sleeper */
2205 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2206 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
2210 sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
2211 struct sockaddr *sa, uint32_t error)
2213 struct mbuf *m_notify;
2214 struct sctp_paddr_change *spc;
2215 struct sockaddr *to;
2216 struct sockaddr_in6 sin6, lsa6;
2218 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVPADDREVNT))
2219 /* event not enabled */
2222 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2223 if (m_notify == NULL)
2225 m_notify->m_len = 0;
2227 MCLGET(m_notify, MB_DONTWAIT);
2228 if ((m_notify->m_flags & M_EXT) != M_EXT) {
2229 sctp_m_freem(m_notify);
2233 spc = mtod(m_notify, struct sctp_paddr_change *);
2234 spc->spc_type = SCTP_PEER_ADDR_CHANGE;
2236 spc->spc_length = sizeof(struct sctp_paddr_change);
2237 if (sa->sa_family == AF_INET) {
2238 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2240 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2242 spc->spc_state = state;
2243 spc->spc_error = error;
2244 spc->spc_assoc_id = sctp_get_associd(stcb);
2246 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2247 m_notify->m_pkthdr.len = sizeof(struct sctp_paddr_change);
2248 m_notify->m_pkthdr.rcvif = 0;
2249 m_notify->m_len = sizeof(struct sctp_paddr_change);
2250 m_notify->m_next = NULL;
2252 to = (struct sockaddr *)(struct sockaddr *)
2253 &stcb->asoc.primary_destination->ro._l_addr;
2254 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2255 to->sa_family == AF_INET) {
2256 struct sockaddr_in *sin;
2258 sin = (struct sockaddr_in *)to;
2259 bzero(&sin6, sizeof(sin6));
2260 sin6.sin6_family = AF_INET6;
2261 sin6.sin6_len = sizeof(struct sockaddr_in6);
2262 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2263 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2264 sizeof(sin6.sin6_addr.s6_addr16[3]));
2265 sin6.sin6_port = sin->sin_port;
2266 to = (struct sockaddr *)&sin6;
2268 /* check and strip embedded scope junk */
2269 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2272 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2273 sctp_m_freem(m_notify);
2276 /* append to socket */
2277 SCTP_TCB_UNLOCK(stcb);
2278 SCTP_INP_WLOCK(stcb->sctp_ep);
2279 SCTP_TCB_LOCK(stcb);
2280 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2281 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2282 /* not enough room */
2283 sctp_m_freem(m_notify);
2284 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2287 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2288 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2289 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2290 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2293 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2295 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2296 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2301 sctp_notify_send_failed(struct sctp_tcb *stcb, u_int32_t error,
2302 struct sctp_tmit_chunk *chk)
2304 struct mbuf *m_notify;
2305 struct sctp_send_failed *ssf;
2306 struct sockaddr_in6 sin6, lsa6;
2307 struct sockaddr *to;
2310 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2311 /* event not enabled */
2314 length = sizeof(struct sctp_send_failed) + chk->send_size;
2315 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2316 if (m_notify == NULL)
2319 m_notify->m_len = 0;
2320 ssf = mtod(m_notify, struct sctp_send_failed *);
2321 ssf->ssf_type = SCTP_SEND_FAILED;
2322 if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
2323 ssf->ssf_flags = SCTP_DATA_UNSENT;
2325 ssf->ssf_flags = SCTP_DATA_SENT;
2326 ssf->ssf_length = length;
2327 ssf->ssf_error = error;
2328 /* not exactly what the user sent in, but should be close :) */
2329 ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
2330 ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
2331 ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
2332 ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
2333 ssf->ssf_info.sinfo_context = chk->rec.data.context;
2334 ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
2335 ssf->ssf_assoc_id = sctp_get_associd(stcb);
2336 m_notify->m_next = chk->data;
2337 if (m_notify->m_next == NULL)
2338 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2341 m_notify->m_flags |= M_NOTIFICATION;
2343 while (m->m_next != NULL)
2345 m->m_flags |= M_EOR;
2347 m_notify->m_pkthdr.len = length;
2348 m_notify->m_pkthdr.rcvif = 0;
2349 m_notify->m_len = sizeof(struct sctp_send_failed);
2351 /* Steal off the mbuf */
2353 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2354 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2355 to->sa_family == AF_INET) {
2356 struct sockaddr_in *sin;
2358 sin = (struct sockaddr_in *)to;
2359 bzero(&sin6, sizeof(sin6));
2360 sin6.sin6_family = AF_INET6;
2361 sin6.sin6_len = sizeof(struct sockaddr_in6);
2362 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2363 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2364 sizeof(sin6.sin6_addr.s6_addr16[3]));
2365 sin6.sin6_port = sin->sin_port;
2366 to = (struct sockaddr *)&sin6;
2368 /* check and strip embedded scope junk */
2369 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2372 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2373 sctp_m_freem(m_notify);
2377 /* append to socket */
2378 SCTP_TCB_UNLOCK(stcb);
2379 SCTP_INP_WLOCK(stcb->sctp_ep);
2380 SCTP_TCB_LOCK(stcb);
2381 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2382 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2383 /* not enough room */
2384 sctp_m_freem(m_notify);
2385 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2388 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2389 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2390 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2391 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2394 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2396 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2397 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2401 sctp_notify_adaption_layer(struct sctp_tcb *stcb,
2404 struct mbuf *m_notify;
2405 struct sctp_adaption_event *sai;
2406 struct sockaddr_in6 sin6, lsa6;
2407 struct sockaddr *to;
2409 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ADAPTIONEVNT))
2410 /* event not enabled */
2413 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2414 if (m_notify == NULL)
2417 m_notify->m_len = 0;
2418 sai = mtod(m_notify, struct sctp_adaption_event *);
2419 sai->sai_type = SCTP_ADAPTION_INDICATION;
2421 sai->sai_length = sizeof(struct sctp_adaption_event);
2422 sai->sai_adaption_ind = error;
2423 sai->sai_assoc_id = sctp_get_associd(stcb);
2425 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2426 m_notify->m_pkthdr.len = sizeof(struct sctp_adaption_event);
2427 m_notify->m_pkthdr.rcvif = 0;
2428 m_notify->m_len = sizeof(struct sctp_adaption_event);
2429 m_notify->m_next = NULL;
2431 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2432 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2433 (to->sa_family == AF_INET)) {
2434 struct sockaddr_in *sin;
2436 sin = (struct sockaddr_in *)to;
2437 bzero(&sin6, sizeof(sin6));
2438 sin6.sin6_family = AF_INET6;
2439 sin6.sin6_len = sizeof(struct sockaddr_in6);
2440 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2441 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2442 sizeof(sin6.sin6_addr.s6_addr16[3]));
2443 sin6.sin6_port = sin->sin_port;
2444 to = (struct sockaddr *)&sin6;
2446 /* check and strip embedded scope junk */
2447 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2449 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2450 sctp_m_freem(m_notify);
2453 /* append to socket */
2454 SCTP_TCB_UNLOCK(stcb);
2455 SCTP_INP_WLOCK(stcb->sctp_ep);
2456 SCTP_TCB_LOCK(stcb);
2457 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2458 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2459 /* not enough room */
2460 sctp_m_freem(m_notify);
2461 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2464 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2465 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2466 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2467 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2470 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2472 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2473 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2477 sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
2480 struct mbuf *m_notify;
2481 struct sctp_pdapi_event *pdapi;
2482 struct sockaddr_in6 sin6, lsa6;
2483 struct sockaddr *to;
2485 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_PDAPIEVNT))
2486 /* event not enabled */
2489 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2490 if (m_notify == NULL)
2493 m_notify->m_len = 0;
2494 pdapi = mtod(m_notify, struct sctp_pdapi_event *);
2495 pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
2496 pdapi->pdapi_flags = 0;
2497 pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
2498 pdapi->pdapi_indication = error;
2499 pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
2501 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2502 m_notify->m_pkthdr.len = sizeof(struct sctp_pdapi_event);
2503 m_notify->m_pkthdr.rcvif = 0;
2504 m_notify->m_len = sizeof(struct sctp_pdapi_event);
2505 m_notify->m_next = NULL;
2507 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2508 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2509 (to->sa_family == AF_INET)) {
2510 struct sockaddr_in *sin;
2512 sin = (struct sockaddr_in *)to;
2513 bzero(&sin6, sizeof(sin6));
2514 sin6.sin6_family = AF_INET6;
2515 sin6.sin6_len = sizeof(struct sockaddr_in6);
2516 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2517 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2518 sizeof(sin6.sin6_addr.s6_addr16[3]));
2519 sin6.sin6_port = sin->sin_port;
2520 to = (struct sockaddr *)&sin6;
2522 /* check and strip embedded scope junk */
2523 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2525 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2526 sctp_m_freem(m_notify);
2529 /* append to socket */
2530 SCTP_TCB_UNLOCK(stcb);
2531 SCTP_INP_WLOCK(stcb->sctp_ep);
2532 SCTP_TCB_LOCK(stcb);
2533 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2534 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2535 /* not enough room */
2536 sctp_m_freem(m_notify);
2537 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2540 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2541 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2542 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2543 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2546 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2548 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2549 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2553 sctp_notify_shutdown_event(struct sctp_tcb *stcb)
2555 struct mbuf *m_notify;
2556 struct sctp_shutdown_event *sse;
2557 struct sockaddr_in6 sin6, lsa6;
2558 struct sockaddr *to;
2561 * For TCP model AND UDP connected sockets we will send
2562 * an error up when an SHUTDOWN completes
2564 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2565 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2566 /* mark socket closed for read/write and wakeup! */
2567 socantrcvmore(stcb->sctp_socket);
2568 socantsendmore(stcb->sctp_socket);
2571 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2572 /* event not enabled */
2575 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2576 if (m_notify == NULL)
2579 m_notify->m_len = 0;
2580 sse = mtod(m_notify, struct sctp_shutdown_event *);
2581 sse->sse_type = SCTP_SHUTDOWN_EVENT;
2583 sse->sse_length = sizeof(struct sctp_shutdown_event);
2584 sse->sse_assoc_id = sctp_get_associd(stcb);
2586 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2587 m_notify->m_pkthdr.len = sizeof(struct sctp_shutdown_event);
2588 m_notify->m_pkthdr.rcvif = 0;
2589 m_notify->m_len = sizeof(struct sctp_shutdown_event);
2590 m_notify->m_next = NULL;
2592 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2593 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2594 to->sa_family == AF_INET) {
2595 struct sockaddr_in *sin;
2597 sin = (struct sockaddr_in *)to;
2598 bzero(&sin6, sizeof(sin6));
2599 sin6.sin6_family = AF_INET6;
2600 sin6.sin6_len = sizeof(struct sockaddr_in6);
2601 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2602 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2603 sizeof(sin6.sin6_addr.s6_addr16[3]));
2604 sin6.sin6_port = sin->sin_port;
2605 to = (struct sockaddr *)&sin6;
2607 /* check and strip embedded scope junk */
2608 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2610 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2611 sctp_m_freem(m_notify);
2614 /* append to socket */
2615 SCTP_TCB_UNLOCK(stcb);
2616 SCTP_INP_WLOCK(stcb->sctp_ep);
2617 SCTP_TCB_LOCK(stcb);
2618 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2619 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2620 /* not enough room */
2621 sctp_m_freem(m_notify);
2622 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2625 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2626 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2627 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2628 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2631 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2633 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2634 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2638 sctp_notify_stream_reset(struct sctp_tcb *stcb,
2639 int number_entries, uint16_t *list, int flag)
2641 struct mbuf *m_notify;
2642 struct sctp_stream_reset_event *strreset;
2643 struct sockaddr_in6 sin6, lsa6;
2644 struct sockaddr *to;
2647 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2648 /* event not enabled */
2651 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
2652 if (m_notify == NULL)
2655 m_notify->m_len = 0;
2656 len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
2657 if (len > M_TRAILINGSPACE(m_notify)) {
2658 MCLGET(m_notify, MB_WAIT);
2660 if (m_notify == NULL)
2664 if (len > M_TRAILINGSPACE(m_notify)) {
2665 /* never enough room */
2669 strreset = mtod(m_notify, struct sctp_stream_reset_event *);
2670 strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
2671 if (number_entries == 0) {
2672 strreset->strreset_flags = flag | SCTP_STRRESET_ALL_STREAMS;
2674 strreset->strreset_flags = flag | SCTP_STRRESET_STREAM_LIST;
2676 strreset->strreset_length = len;
2677 strreset->strreset_assoc_id = sctp_get_associd(stcb);
2678 if (number_entries) {
2680 for (i=0; i<number_entries; i++) {
2681 strreset->strreset_list[i] = list[i];
2684 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2685 m_notify->m_pkthdr.len = len;
2686 m_notify->m_pkthdr.rcvif = 0;
2687 m_notify->m_len = len;
2688 m_notify->m_next = NULL;
2689 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2691 sctp_m_freem(m_notify);
2694 to = (struct sockaddr *)(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2695 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2696 to->sa_family == AF_INET) {
2697 struct sockaddr_in *sin;
2699 sin = (struct sockaddr_in *)to;
2700 bzero(&sin6, sizeof(sin6));
2701 sin6.sin6_family = AF_INET6;
2702 sin6.sin6_len = sizeof(struct sockaddr_in6);
2703 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2704 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2705 sizeof(sin6.sin6_addr.s6_addr16[3]));
2706 sin6.sin6_port = sin->sin_port;
2707 to = (struct sockaddr *)&sin6;
2709 /* check and strip embedded scope junk */
2710 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2712 /* append to socket */
2713 SCTP_TCB_UNLOCK(stcb);
2714 SCTP_INP_WLOCK(stcb->sctp_ep);
2715 SCTP_TCB_LOCK(stcb);
2716 if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
2717 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2718 /* not enough room */
2719 sctp_m_freem(m_notify);
2720 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2723 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2724 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2725 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2726 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2729 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2731 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2732 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2737 sctp_ulp_notify(u_int32_t notification, struct sctp_tcb *stcb,
2738 u_int32_t error, void *data)
2740 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2741 /* No notifications up when we are in a no socket state */
2744 if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
2745 /* Can't send up to a closed socket any notifications */
2748 switch (notification) {
2749 case SCTP_NOTIFY_ASSOC_UP:
2750 sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error);
2752 case SCTP_NOTIFY_ASSOC_DOWN:
2753 sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error);
2755 case SCTP_NOTIFY_INTERFACE_DOWN:
2757 struct sctp_nets *net;
2758 net = (struct sctp_nets *)data;
2759 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
2760 (struct sockaddr *)&net->ro._l_addr, error);
2763 case SCTP_NOTIFY_INTERFACE_UP:
2765 struct sctp_nets *net;
2766 net = (struct sctp_nets *)data;
2767 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
2768 (struct sockaddr *)&net->ro._l_addr, error);
2771 case SCTP_NOTIFY_INTERFACE_CONFIRMED:
2773 struct sctp_nets *net;
2774 net = (struct sctp_nets *)data;
2775 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
2776 (struct sockaddr *)&net->ro._l_addr, error);
2779 case SCTP_NOTIFY_DG_FAIL:
2780 sctp_notify_send_failed(stcb, error,
2781 (struct sctp_tmit_chunk *)data);
2783 case SCTP_NOTIFY_ADAPTION_INDICATION:
2784 /* Here the error is the adaption indication */
2785 sctp_notify_adaption_layer(stcb, error);
2787 case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
2788 sctp_notify_partial_delivery_indication(stcb, error);
2790 case SCTP_NOTIFY_STRDATA_ERR:
2792 case SCTP_NOTIFY_ASSOC_ABORTED:
2793 sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error);
2795 case SCTP_NOTIFY_PEER_OPENED_STREAM:
2797 case SCTP_NOTIFY_STREAM_OPENED_OK:
2799 case SCTP_NOTIFY_ASSOC_RESTART:
2800 sctp_notify_assoc_change(SCTP_RESTART, stcb, error);
2802 case SCTP_NOTIFY_HB_RESP:
2804 case SCTP_NOTIFY_STR_RESET_SEND:
2805 sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_OUTBOUND_STR);
2807 case SCTP_NOTIFY_STR_RESET_RECV:
2808 sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_INBOUND_STR);
2810 case SCTP_NOTIFY_ASCONF_ADD_IP:
2811 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
2814 case SCTP_NOTIFY_ASCONF_DELETE_IP:
2815 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
2818 case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
2819 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
2822 case SCTP_NOTIFY_ASCONF_SUCCESS:
2824 case SCTP_NOTIFY_ASCONF_FAILED:
2826 case SCTP_NOTIFY_PEER_SHUTDOWN:
2827 sctp_notify_shutdown_event(stcb);
2831 if (sctp_debug_on & SCTP_DEBUG_UTIL1) {
2832 printf("NOTIFY: unknown notification %xh (%u)\n",
2833 notification, notification);
2835 #endif /* SCTP_DEBUG */
2841 sctp_report_all_outbound(struct sctp_tcb *stcb)
2843 struct sctp_association *asoc;
2844 struct sctp_stream_out *outs;
2845 struct sctp_tmit_chunk *chk;
2849 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2852 /* now through all the gunk freeing chunks */
2853 TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
2854 /* now clean up any chunks here */
2855 chk = TAILQ_FIRST(&outs->outqueue);
2857 stcb->asoc.stream_queue_cnt--;
2858 TAILQ_REMOVE(&outs->outqueue, chk, sctp_next);
2859 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2860 SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2862 sctp_m_freem(chk->data);
2866 sctp_free_remote_addr(chk->whoTo);
2869 /* Free the chunk */
2870 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2871 sctppcbinfo.ipi_count_chunk--;
2872 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2873 panic("Chunk count is negative");
2875 sctppcbinfo.ipi_gencnt_chunk++;
2876 chk = TAILQ_FIRST(&outs->outqueue);
2879 /* pending send queue SHOULD be empty */
2880 if (!TAILQ_EMPTY(&asoc->send_queue)) {
2881 chk = TAILQ_FIRST(&asoc->send_queue);
2883 TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
2884 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2886 sctp_m_freem(chk->data);
2890 sctp_free_remote_addr(chk->whoTo);
2892 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2893 sctppcbinfo.ipi_count_chunk--;
2894 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2895 panic("Chunk count is negative");
2897 sctppcbinfo.ipi_gencnt_chunk++;
2898 chk = TAILQ_FIRST(&asoc->send_queue);
2901 /* sent queue SHOULD be empty */
2902 if (!TAILQ_EMPTY(&asoc->sent_queue)) {
2903 chk = TAILQ_FIRST(&asoc->sent_queue);
2905 TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
2906 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2907 SCTP_NOTIFY_DATAGRAM_SENT, chk);
2909 sctp_m_freem(chk->data);
2913 sctp_free_remote_addr(chk->whoTo);
2915 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2916 sctppcbinfo.ipi_count_chunk--;
2917 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2918 panic("Chunk count is negative");
2920 sctppcbinfo.ipi_gencnt_chunk++;
2921 chk = TAILQ_FIRST(&asoc->sent_queue);
2927 sctp_abort_notification(struct sctp_tcb *stcb, int error)
2930 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2933 /* Tell them we lost the asoc */
2934 sctp_report_all_outbound(stcb);
2935 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL);
2939 sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2940 struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *op_err)
2946 /* We have a TCB to abort, send notification too */
2947 vtag = stcb->asoc.peer_vtag;
2948 sctp_abort_notification(stcb, 0);
2950 sctp_send_abort(m, iphlen, sh, vtag, op_err);
2952 /* Ok, now lets free it */
2953 sctp_free_assoc(inp, stcb);
2955 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2956 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2957 sctp_inpcb_free(inp, 1);
2964 sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2965 int error, struct mbuf *op_err)
2970 /* Got to have a TCB */
2971 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2972 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2973 sctp_inpcb_free(inp, 1);
2978 vtag = stcb->asoc.peer_vtag;
2979 /* notify the ulp */
2980 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
2981 sctp_abort_notification(stcb, error);
2982 /* notify the peer */
2983 sctp_send_abort_tcb(stcb, op_err);
2984 /* now free the asoc */
2985 sctp_free_assoc(inp, stcb);
2989 sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
2990 struct sctp_inpcb *inp, struct mbuf *op_err)
2992 struct sctp_chunkhdr *ch, chunk_buf;
2993 unsigned int chk_length;
2995 /* Generate a TO address for future reference */
2996 if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
2997 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2998 sctp_inpcb_free(inp, 1);
3001 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3002 sizeof(*ch), (u_int8_t *)&chunk_buf);
3003 while (ch != NULL) {
3004 chk_length = ntohs(ch->chunk_length);
3005 if (chk_length < sizeof(*ch)) {
3006 /* break to abort land */
3009 switch (ch->chunk_type) {
3010 case SCTP_PACKET_DROPPED:
3011 /* we don't respond to pkt-dropped */
3013 case SCTP_ABORT_ASSOCIATION:
3014 /* we don't respond with an ABORT to an ABORT */
3016 case SCTP_SHUTDOWN_COMPLETE:
3018 * we ignore it since we are not waiting for it
3022 case SCTP_SHUTDOWN_ACK:
3023 sctp_send_shutdown_complete2(m, iphlen, sh);
3028 offset += SCTP_SIZE32(chk_length);
3029 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3030 sizeof(*ch), (u_int8_t *)&chunk_buf);
3032 sctp_send_abort(m, iphlen, sh, 0, op_err);
3036 * check the inbound datagram to make sure there is not an abort
3037 * inside it, if there is return 1, else return 0.
3040 sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, int *vtagfill)
3042 struct sctp_chunkhdr *ch;
3043 struct sctp_init_chunk *init_chk, chunk_buf;
3045 unsigned int chk_length;
3047 offset = iphlen + sizeof(struct sctphdr);
3048 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
3049 (u_int8_t *)&chunk_buf);
3050 while (ch != NULL) {
3051 chk_length = ntohs(ch->chunk_length);
3052 if (chk_length < sizeof(*ch)) {
3053 /* packet is probably corrupt */
3056 /* we seem to be ok, is it an abort? */
3057 if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
3058 /* yep, tell them */
3061 if (ch->chunk_type == SCTP_INITIATION) {
3062 /* need to update the Vtag */
3063 init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
3064 offset, sizeof(*init_chk), (u_int8_t *)&chunk_buf);
3065 if (init_chk != NULL) {
3066 *vtagfill = ntohl(init_chk->init.initiate_tag);
3069 /* Nope, move to the next chunk */
3070 offset += SCTP_SIZE32(chk_length);
3071 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3072 sizeof(*ch), (u_int8_t *)&chunk_buf);
3078 * currently (2/02), ifa_addr embeds scope_id's and don't
3079 * have sin6_scope_id set (i.e. it's 0)
3080 * so, create this function to compare link local scopes
3083 sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
3085 struct sockaddr_in6 a, b;
3091 if (a.sin6_scope_id == 0)
3092 if (in6_recoverscope(&a, &a.sin6_addr, NULL)) {
3093 /* can't get scope, so can't match */
3096 if (b.sin6_scope_id == 0)
3097 if (in6_recoverscope(&b, &b.sin6_addr, NULL)) {
3098 /* can't get scope, so can't match */
3101 if (a.sin6_scope_id != b.sin6_scope_id)
3108 * returns a sockaddr_in6 with embedded scope recovered and removed
3110 struct sockaddr_in6 *
3111 sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
3114 /* check and strip embedded scope junk */
3115 if (addr->sin6_family == AF_INET6) {
3116 if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
3117 if (addr->sin6_scope_id == 0) {
3119 if (!in6_recoverscope(store, &store->sin6_addr,
3121 /* use the recovered scope */
3124 /* else, return the original "to" addr */
3132 * are the two addresses the same? currently a "scopeless" check
3133 * returns: 1 if same, 0 if not
3136 sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
3140 if (sa1 == NULL || sa2 == NULL)
3143 /* must be the same family */
3144 if (sa1->sa_family != sa2->sa_family)
3147 if (sa1->sa_family == AF_INET6) {
3148 /* IPv6 addresses */
3149 struct sockaddr_in6 *sin6_1, *sin6_2;
3151 sin6_1 = (struct sockaddr_in6 *)sa1;
3152 sin6_2 = (struct sockaddr_in6 *)sa2;
3153 return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr,
3154 &sin6_2->sin6_addr));
3155 } else if (sa1->sa_family == AF_INET) {
3156 /* IPv4 addresses */
3157 struct sockaddr_in *sin_1, *sin_2;
3159 sin_1 = (struct sockaddr_in *)sa1;
3160 sin_2 = (struct sockaddr_in *)sa2;
3161 return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
3163 /* we don't do these... */
3169 sctp_print_address(struct sockaddr *sa)
3172 if (sa->sa_family == AF_INET6) {
3173 struct sockaddr_in6 *sin6;
3174 sin6 = (struct sockaddr_in6 *)sa;
3175 printf("IPv6 address: %s:%d scope:%u\n",
3176 ip6_sprintf(&sin6->sin6_addr), ntohs(sin6->sin6_port),
3177 sin6->sin6_scope_id);
3178 } else if (sa->sa_family == AF_INET) {
3179 struct sockaddr_in *sin;
3180 sin = (struct sockaddr_in *)sa;
3181 printf("IPv4 address: %s:%d\n", inet_ntoa(sin->sin_addr),
3182 ntohs(sin->sin_port));
3189 sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
3191 if (iph->ip_v == IPVERSION) {
3192 struct sockaddr_in lsa, fsa;
3194 bzero(&lsa, sizeof(lsa));
3195 lsa.sin_len = sizeof(lsa);
3196 lsa.sin_family = AF_INET;
3197 lsa.sin_addr = iph->ip_src;
3198 lsa.sin_port = sh->src_port;
3199 bzero(&fsa, sizeof(fsa));
3200 fsa.sin_len = sizeof(fsa);
3201 fsa.sin_family = AF_INET;
3202 fsa.sin_addr = iph->ip_dst;
3203 fsa.sin_port = sh->dest_port;
3205 sctp_print_address((struct sockaddr *)&lsa);
3207 sctp_print_address((struct sockaddr *)&fsa);
3208 } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
3209 struct ip6_hdr *ip6;
3210 struct sockaddr_in6 lsa6, fsa6;
3212 ip6 = (struct ip6_hdr *)iph;
3213 bzero(&lsa6, sizeof(lsa6));
3214 lsa6.sin6_len = sizeof(lsa6);
3215 lsa6.sin6_family = AF_INET6;
3216 lsa6.sin6_addr = ip6->ip6_src;
3217 lsa6.sin6_port = sh->src_port;
3218 bzero(&fsa6, sizeof(fsa6));
3219 fsa6.sin6_len = sizeof(fsa6);
3220 fsa6.sin6_family = AF_INET6;
3221 fsa6.sin6_addr = ip6->ip6_dst;
3222 fsa6.sin6_port = sh->dest_port;
3224 sctp_print_address((struct sockaddr *)&lsa6);
3226 sctp_print_address((struct sockaddr *)&fsa6);
3230 #if defined(__FreeBSD__) || defined(__APPLE__)
3232 /* cloned from uipc_socket.c */
3234 #define SCTP_SBLINKRECORD(sb, m0) do { \
3235 if ((sb)->sb_lastrecord != NULL) \
3236 (sb)->sb_lastrecord->m_nextpkt = (m0); \
3238 (sb)->sb_mb = (m0); \
3239 (sb)->sb_lastrecord = (m0); \
3240 } while (/*CONSTCOND*/0)
3245 sbappendaddr_nocheck(sb, asa, m0, control, tag, inp)
3247 struct sockaddr *asa;
3248 struct mbuf *m0, *control;
3250 struct sctp_inpcb *inp;
3255 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
3256 panic("sbappendaddr_nocheck");
3258 m0->m_pkthdr.csum_data = (int)tag;
3260 for (n = control; n; n = n->m_next) {
3261 if (n->m_next == 0) /* keep pointer to last control buf */
3264 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3265 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
3266 MGETHDR(m, MB_DONTWAIT, MT_SONAME);
3270 if (asa->sa_len > MHLEN) {
3271 MEXTMALLOC(m, asa->sa_len, M_NOWAIT);
3272 if ((m->m_flags & M_EXT) == 0) {
3277 m->m_len = asa->sa_len;
3278 memcpy(mtod(m, caddr_t), (caddr_t)asa, asa->sa_len);
3283 n->m_next = m0; /* concatenate data to control */
3288 m->m_next = control;
3291 m->m_pkthdr.csum_data = tag;
3293 for (n = m; n; n = n->m_next)
3295 if ((n = sb->sb_mb) != NULL) {
3296 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3297 inp->sb_last_mpkt = NULL;
3299 if (inp->sb_last_mpkt)
3300 inp->sb_last_mpkt->m_nextpkt = m;
3302 while (n->m_nextpkt) {
3307 inp->sb_last_mpkt = m;
3309 inp->sb_last_mpkt = sb->sb_mb = m;
3310 inp->sctp_vtag_first = tag;
3314 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
3315 struct mbuf *m, *n, *nlast;
3318 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
3319 panic("sbappendaddr_nocheck");
3321 for (n = control; n; n = n->m_next) {
3322 if (n->m_next == 0) /* get pointer to last control buf */
3325 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3326 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
3327 if (asa->sa_len > MHLEN)
3330 MGETHDR(m, MB_DONTWAIT, MT_SONAME);
3336 printf("Duplicate mbuf allocated %p in and mget returned %p?\n",
3339 panic("more than once");
3344 m->m_len = asa->sa_len;
3345 bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
3351 n->m_next = m0; /* concatenate data to control */
3355 m->m_next = control;
3358 m->m_pkthdr.csum_data = (int)tag;
3361 for (n = m; n; n = n->m_next)
3364 if (sb->sb_mb == NULL) {
3365 inp->sctp_vtag_first = tag;
3369 if (sb->sb_mb == NULL)
3370 inp->sctp_vtag_first = tag;
3371 SCTP_SBLINKRECORD(sb, m);
3372 sb->sb_mbtail = nlast;
3374 if ((n = sb->sb_mb) != NULL) {
3375 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3376 inp->sb_last_mpkt = NULL;
3378 if (inp->sb_last_mpkt)
3379 inp->sb_last_mpkt->m_nextpkt = m;
3381 while (n->m_nextpkt) {
3386 inp->sb_last_mpkt = m;
3388 inp->sb_last_mpkt = sb->sb_mb = m;
3389 inp->sctp_vtag_first = tag;
3398 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
3399 panic("sbappendaddr_nocheck");
3400 m0->m_pkthdr.csum = (int)tag;
3401 for (n = control; n; n = n->m_next) {
3402 if (n->m_next == 0) /* keep pointer to last control buf */
3405 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3406 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
3407 if (asa->sa_len > MHLEN)
3409 MGETHDR(m, MB_DONTWAIT, MT_SONAME);
3412 m->m_len = asa->sa_len;
3413 bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
3418 n->m_next = m0; /* concatenate data to control */
3422 m->m_pkthdr.csum = (int)tag;
3423 m->m_next = control;
3424 for (n = m; n; n = n->m_next)
3426 if ((n = sb->sb_mb) != NULL) {
3427 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3428 inp->sb_last_mpkt = NULL;
3430 if (inp->sb_last_mpkt)
3431 inp->sb_last_mpkt->m_nextpkt = m;
3433 while (n->m_nextpkt) {
3438 inp->sb_last_mpkt = m;
3440 inp->sb_last_mpkt = sb->sb_mb = m;
3441 inp->sctp_vtag_first = tag;
3447 /*************HOLD THIS COMMENT FOR PATCH FILE OF
3448 *************ALTERNATE ROUTING CODE
3451 /*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
3452 *************ALTERNATE ROUTING CODE
3456 sctp_generate_invmanparam(int err)
3458 /* Return a MBUF with a invalid mandatory parameter */
3461 MGET(m, MB_DONTWAIT, MT_DATA);
3463 struct sctp_paramhdr *ph;
3464 m->m_len = sizeof(struct sctp_paramhdr);
3465 ph = mtod(m, struct sctp_paramhdr *);
3466 ph->param_length = htons(sizeof(struct sctp_paramhdr));
3467 ph->param_type = htons(err);
3473 sctp_should_be_moved(struct mbuf *this, struct sctp_association *asoc)
3477 * given a mbuf chain, look through it finding
3478 * the M_PKTHDR and return 1 if it belongs to
3479 * the association given. We tell this by
3480 * a kludge where we stuff the my_vtag of the asoc
3481 * into the m->m_pkthdr.csum_data/csum field.
3485 if (m->m_flags & M_PKTHDR) {
3487 #if defined(__OpenBSD__)
3488 if ((u_int32_t)m->m_pkthdr.csum == asoc->my_vtag)
3490 if ((u_int32_t)m->m_pkthdr.csum_data == asoc->my_vtag)
3503 sctp_get_first_vtag_from_sb(struct socket *so)
3505 struct mbuf *this, *at;
3509 if (so->so_rcv.sb_mb) {
3511 this = so->so_rcv.sb_mb;
3514 /* get to the m_pkthdr */
3516 if (at->m_flags & M_PKTHDR)
3522 /* now do we have a m_pkthdr */
3523 if (at && (at->m_flags & M_PKTHDR)) {
3525 #if defined(__OpenBSD__)
3526 if ((u_int32_t)at->m_pkthdr.csum != 0)
3528 if ((u_int32_t)at->m_pkthdr.csum_data != 0)
3532 #if defined(__OpenBSD__)
3533 retval = (u_int32_t)at->m_pkthdr.csum;
3536 (u_int32_t)at->m_pkthdr.csum_data;
3541 this = this->m_nextpkt;
3549 sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
3550 struct socket *new, struct sctp_tcb *stcb)
3552 struct mbuf **put, **take, *next, *this;
3553 struct sockbuf *old_sb, *new_sb;
3554 struct sctp_association *asoc;
3558 old_sb = &old->so_rcv;
3559 new_sb = &new->so_rcv;
3560 if (old_sb->sb_mb == NULL) {
3561 /* Nothing to move */
3564 SOCKBUF_LOCK(old_sb);
3565 SOCKBUF_LOCK(new_sb);
3567 if (inp->sctp_vtag_first == asoc->my_vtag) {
3568 /* First one must be moved */
3570 for (mm = old_sb->sb_mb; mm; mm = mm->m_next) {
3572 * Go down the chain and fix
3573 * the space allocation of the
3577 sballoc(new_sb, mm);
3579 new_sb->sb_mb = old_sb->sb_mb;
3580 old_sb->sb_mb = new_sb->sb_mb->m_nextpkt;
3581 new_sb->sb_mb->m_nextpkt = NULL;
3582 put = &new_sb->sb_mb->m_nextpkt;
3585 put = &new_sb->sb_mb;
3588 take = &old_sb->sb_mb;
3589 next = old_sb->sb_mb;
3592 /* postion for next one */
3593 next = this->m_nextpkt;
3594 /* check the tag of this packet */
3595 if (sctp_should_be_moved(this, asoc)) {
3596 /* yes this needs to be moved */
3598 *take = this->m_nextpkt;
3599 this->m_nextpkt = NULL;
3601 for (mm = this; mm; mm = mm->m_next) {
3603 * Go down the chain and fix
3604 * the space allocation of the
3608 sballoc(new_sb, mm);
3610 put = &this->m_nextpkt;
3613 /* no advance our take point. */
3614 take = &this->m_nextpkt;
3619 * Ok so now we must re-postion vtag_first to
3620 * match the new first one since we moved the
3623 inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
3625 SOCKBUF_UNLOCK(old_sb);
3626 SOCKBUF_UNLOCK(new_sb);
3630 sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
3631 struct sctp_tmit_chunk *tp1)
3633 if (tp1->data == NULL) {
3636 #ifdef SCTP_MBCNT_LOGGING
3637 sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
3638 asoc->total_output_queue_size,
3640 asoc->total_output_mbuf_queue_size,
3643 if (asoc->total_output_queue_size >= tp1->book_size) {
3644 asoc->total_output_queue_size -= tp1->book_size;
3646 asoc->total_output_queue_size = 0;
3649 /* Now free the mbuf */
3650 if (asoc->total_output_mbuf_queue_size >= tp1->mbcnt) {
3651 asoc->total_output_mbuf_queue_size -= tp1->mbcnt;
3653 asoc->total_output_mbuf_queue_size = 0;
3655 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3656 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3657 if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
3658 stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
3660 stcb->sctp_socket->so_snd.sb_cc = 0;
3663 if (stcb->sctp_socket->so_snd.sb_mbcnt >= tp1->mbcnt) {
3664 stcb->sctp_socket->so_snd.sb_mbcnt -= tp1->mbcnt;
3666 stcb->sctp_socket->so_snd.sb_mbcnt = 0;
3672 sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
3673 int reason, struct sctpchunk_listhead *queue)
3677 uint8_t foundeom = 0;
3680 ret_sz += tp1->book_size;
3681 tp1->sent = SCTP_FORWARD_TSN_SKIP;
3683 sctp_free_bufspace(stcb, &stcb->asoc, tp1);
3684 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1);
3685 sctp_m_freem(tp1->data);
3687 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
3689 if (tp1->flags & SCTP_PR_SCTP_BUFFER) {
3690 stcb->asoc.sent_queue_cnt_removeable--;
3692 if (queue == &stcb->asoc.send_queue) {
3693 TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
3694 /* on to the sent queue */
3695 TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
3697 stcb->asoc.sent_queue_cnt++;
3699 if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
3700 SCTP_DATA_NOT_FRAG) {
3701 /* not frag'ed we ae done */
3704 } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
3705 /* end of frag, we are done */
3709 /* Its a begin or middle piece, we must mark all of it */
3711 tp1 = TAILQ_NEXT(tp1, sctp_next);
3713 } while (tp1 && notdone);
3714 if ((foundeom == 0) && (queue == &stcb->asoc.sent_queue)) {
3716 * The multi-part message was scattered
3717 * across the send and sent queue.
3719 tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
3721 * recurse throught the send_queue too, starting at the
3725 ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
3726 &stcb->asoc.send_queue);
3728 printf("hmm, nothing on the send queue and no EOM?\n");
3735 * checks to see if the given address, sa, is one that is currently
3736 * known by the kernel
3737 * note: can't distinguish the same address on multiple interfaces and
3738 * doesn't handle multiple addresses with different zone/scope id's
3739 * note: ifa_ifwithaddr() compares the entire sockaddr struct
3742 sctp_find_ifa_by_addr(struct sockaddr *sa)
3747 /* go through all our known interfaces */
3748 TAILQ_FOREACH(ifn, &ifnet, if_list) {
3749 /* go through each interface addresses */
3750 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
3751 /* correct family? */
3752 if (ifa->ifa_addr->sa_family != sa->sa_family)
3756 if (ifa->ifa_addr->sa_family == AF_INET6) {
3758 struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
3759 sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
3760 if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
3761 /* create a copy and clear scope */
3762 memcpy(&sin6_tmp, sin1,
3763 sizeof(struct sockaddr_in6));
3765 in6_clearscope(&sin1->sin6_addr);
3767 sin2 = (struct sockaddr_in6 *)sa;
3768 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
3769 sizeof(struct in6_addr)) == 0) {
3775 if (ifa->ifa_addr->sa_family == AF_INET) {
3777 struct sockaddr_in *sin1, *sin2;
3778 sin1 = (struct sockaddr_in *)ifa->ifa_addr;
3779 sin2 = (struct sockaddr_in *)sa;
3780 if (sin1->sin_addr.s_addr ==
3781 sin2->sin_addr.s_addr) {
3786 /* else, not AF_INET or AF_INET6, so skip */
3787 } /* end foreach ifa */
3788 } /* end foreach ifn */
3796 * here we hack in a fix for Apple's m_copym for the case where the first mbuf
3797 * in the chain is a M_PKTHDR and the length is zero
3800 sctp_pkthdr_fix(struct mbuf *m)
3804 if ((m->m_flags & M_PKTHDR) == 0) {
3809 if (m->m_len != 0) {
3810 /* not a zero length PKTHDR mbuf */
3814 /* let's move in a word into the first mbuf... yes, ugly! */
3816 if (m_nxt == NULL) {
3817 /* umm... not a very useful mbuf chain... */
3820 if ((size_t)m_nxt->m_len > sizeof(long)) {
3821 /* move over a long */
3822 bcopy(mtod(m_nxt, caddr_t), mtod(m, caddr_t), sizeof(long));
3823 /* update mbuf data pointers and lengths */
3824 m->m_len += sizeof(long);
3825 m_nxt->m_data += sizeof(long);
3826 m_nxt->m_len -= sizeof(long);
3830 inline struct mbuf *
3831 sctp_m_copym(struct mbuf *m, int off, int len, int wait)
3834 return (m_copym(m, off, len, wait));
3836 #endif /* __APPLE__ */