kernel/netinet: Remove some unused variables.
[dragonfly.git] / sys / netinet / sctputil.c
CommitLineData
8d60bf8a 1/* $KAME: sctputil.c,v 1.36 2005/03/06 16:04:19 itojun Exp $ */
8d60bf8a
EN
2
3/*
4 * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Cisco Systems, Inc.
18 * 4. Neither the name of the project nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#if !(defined(__OpenBSD__) || defined(__APPLE__))
36#include "opt_ipsec.h"
37#endif
8e062f96 38#if defined(__FreeBSD__) || defined(__DragonFly__)
8d60bf8a
EN
39#include "opt_compat.h"
40#include "opt_inet6.h"
41#include "opt_inet.h"
8e062f96 42#if !(defined(SCTP_BASE_FREEBSD) || defined(__DragonFly__))
8d60bf8a 43#include "opt_mpath.h"
8e062f96 44#endif /* SCTP_BASE_FREEBSD || __DragonFly__ */
8d60bf8a
EN
45#endif /* FreeBSD */
46#if defined(__NetBSD__)
47#include "opt_inet.h"
48#endif
49#ifdef __APPLE__
50#include <sctp.h>
51#elif !defined(__OpenBSD__)
52#include "opt_sctp.h"
53#endif
54
55#include <sys/param.h>
56#include <sys/systm.h>
57#include <sys/malloc.h>
58#include <sys/mbuf.h>
59#include <sys/domain.h>
60#include <sys/protosw.h>
61#include <sys/socket.h>
62#include <sys/socketvar.h>
63#include <sys/proc.h>
64#include <sys/kernel.h>
65#include <sys/sysctl.h>
66a25ac4 66#include <sys/thread2.h>
8d60bf8a 67
8e062f96 68#if defined(__FreeBSD__) || defined(__DragonFly__)
8d60bf8a
EN
69#include <sys/callout.h>
70#else
71#include <netinet/sctp_callout.h> /* for callout_active() */
72#endif
73
74#include <net/radix.h>
75#include <net/route.h>
76
77#ifdef INET6
78#ifndef __OpenBSD__
79#include <sys/domain.h>
80#endif
81#endif
82
83#if (defined(__FreeBSD__) && __FreeBSD_version >= 500000)
84#include <sys/limits.h>
85#else
86#include <machine/limits.h>
87#endif
88
89#include <net/if.h>
90#include <net/if_types.h>
91#include <net/route.h>
92
93#include <netinet/in.h>
94#include <netinet/in_systm.h>
95#include <netinet/ip.h>
96#include <netinet/in_pcb.h>
97#include <netinet/in_var.h>
98#include <netinet/ip_var.h>
99
100#ifdef INET6
101#include <netinet/ip6.h>
102#include <netinet6/ip6_var.h>
103
8e062f96 104#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__DragonFly_)
8d60bf8a
EN
105#include <netinet6/in6_pcb.h>
106#elif defined(__OpenBSD__)
107#include <netinet/in_pcb.h>
108#endif
109
110#endif /* INET6 */
111
112#include <netinet/sctp_pcb.h>
113
114#ifdef IPSEC
115#ifndef __OpenBSD__
116#include <netinet6/ipsec.h>
7f12b1a3 117#include <netproto/key/key.h>
8d60bf8a
EN
118#else
119#undef IPSEC
120#endif
121#endif /* IPSEC */
122
123#include <netinet/sctputil.h>
124#include <netinet/sctp_var.h>
125#ifdef INET6
126#include <netinet6/sctp6_var.h>
127#endif
128#include <netinet/sctp_header.h>
129#include <netinet/sctp_output.h>
130#include <netinet/sctp_hashdriver.h>
131#include <netinet/sctp_uio.h>
132#include <netinet/sctp_timer.h>
133#include <netinet/sctp_crc32.h>
134#include <netinet/sctp_indata.h> /* for sctp_deliver_data() */
135#define NUMBER_OF_MTU_SIZES 18
136
137#ifdef SCTP_DEBUG
138extern u_int32_t sctp_debug_on;
139#endif
140
141#ifdef SCTP_STAT_LOGGING
142int sctp_cwnd_log_at=0;
143int sctp_cwnd_log_rolled=0;
144struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
145
f3f70f0d
SW
146void
147sctp_clr_stat_log(void)
8d60bf8a
EN
148{
149 sctp_cwnd_log_at=0;
150 sctp_cwnd_log_rolled=0;
151}
152
153void
154sctp_log_strm_del_alt(u_int32_t tsn, u_int16_t sseq, int from)
155{
156
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;
163 sctp_cwnd_log_at++;
164 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
165 sctp_cwnd_log_at = 0;
166 sctp_cwnd_log_rolled = 1;
167 }
168
f3f70f0d 169
8d60bf8a
EN
170}
171
172void
173sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
174{
175
176 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
177 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAP;
178 sctp_clog[sctp_cwnd_log_at].x.map.base = map;
179 sctp_clog[sctp_cwnd_log_at].x.map.cum = cum;
180 sctp_clog[sctp_cwnd_log_at].x.map.high = high;
181 sctp_cwnd_log_at++;
182 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
183 sctp_cwnd_log_at = 0;
184 sctp_cwnd_log_rolled = 1;
185 }
186}
187
188void
189sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
190 int from)
191{
192
193 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
194 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_FR;
195 sctp_clog[sctp_cwnd_log_at].x.fr.largest_tsn = biggest_tsn;
196 sctp_clog[sctp_cwnd_log_at].x.fr.largest_new_tsn = biggest_new_tsn;
197 sctp_clog[sctp_cwnd_log_at].x.fr.tsn = tsn;
198 sctp_cwnd_log_at++;
199 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
200 sctp_cwnd_log_at = 0;
201 sctp_cwnd_log_rolled = 1;
202 }
203}
204
205void
206sctp_log_strm_del(struct sctp_tmit_chunk *chk, struct sctp_tmit_chunk *poschk,
207 int from)
208{
209
210 if (chk == NULL) {
a6ec04bc 211 kprintf("Gak log of NULL?\n");
8d60bf8a
EN
212 return;
213 }
214 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
215 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_STRM;
216 sctp_clog[sctp_cwnd_log_at].x.strlog.n_tsn = chk->rec.data.TSN_seq;
217 sctp_clog[sctp_cwnd_log_at].x.strlog.n_sseq = chk->rec.data.stream_seq;
218 if (poschk != NULL) {
219 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn =
220 poschk->rec.data.TSN_seq;
221 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq =
222 poschk->rec.data.stream_seq;
223 } else {
224 sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn = 0;
225 sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq = 0;
226 }
227 sctp_cwnd_log_at++;
228 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
229 sctp_cwnd_log_at = 0;
230 sctp_cwnd_log_rolled = 1;
231 }
232}
233
234void
235sctp_log_cwnd(struct sctp_nets *net, int augment, uint8_t from)
236{
237
238 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
239 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_CWND;
240 sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
241 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = net->cwnd;
242 sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
243 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = augment;
244 sctp_cwnd_log_at++;
245 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
246 sctp_cwnd_log_at = 0;
247 sctp_cwnd_log_rolled = 1;
248 }
249}
250
251void
252sctp_log_maxburst(struct sctp_nets *net, int error, int burst, uint8_t from)
253{
254 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
255 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAXBURST;
256 sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
257 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = error;
258 sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
259 sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = burst;
260 sctp_cwnd_log_at++;
261 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
262 sctp_cwnd_log_at = 0;
263 sctp_cwnd_log_rolled = 1;
264 }
265}
266
267void
268sctp_log_rwnd(uint8_t from, u_int32_t peers_rwnd , u_int32_t snd_size, u_int32_t overhead)
269{
270 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
271 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
272 sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
273 sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = snd_size;
274 sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
275 sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = 0;
276 sctp_cwnd_log_at++;
277 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
278 sctp_cwnd_log_at = 0;
279 sctp_cwnd_log_rolled = 1;
280 }
281}
282
283void
284sctp_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{
286 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
287 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
288 sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
289 sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = flight_size;
290 sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
291 sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = a_rwndval;
292 sctp_cwnd_log_at++;
293 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
294 sctp_cwnd_log_at = 0;
295 sctp_cwnd_log_rolled = 1;
296 }
297}
298
299void
300sctp_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{
302 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
303 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MBCNT;
304 sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_size = total_oq;
305 sctp_clog[sctp_cwnd_log_at].x.mbcnt.size_change = book;
306 sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_mb_size = total_mbcnt_q;
307 sctp_clog[sctp_cwnd_log_at].x.mbcnt.mbcnt_change = mbcnt;
308 sctp_cwnd_log_at++;
309 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
310 sctp_cwnd_log_at = 0;
311 sctp_cwnd_log_rolled = 1;
312 }
313}
314
315void
316sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc)
317{
318
319 sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
320 sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_BLOCK;
6d49aa6f 321 sctp_clog[sctp_cwnd_log_at].x.blk.maxmb = (u_int16_t)(so->so_snd.ssb_mbmax/1024);
8d60bf8a 322 sctp_clog[sctp_cwnd_log_at].x.blk.onmb = asoc->total_output_mbuf_queue_size;
6d49aa6f 323 sctp_clog[sctp_cwnd_log_at].x.blk.maxsb = (u_int16_t)(so->so_snd.ssb_hiwat/1024);
8d60bf8a
EN
324 sctp_clog[sctp_cwnd_log_at].x.blk.onsb = asoc->total_output_queue_size;
325 sctp_clog[sctp_cwnd_log_at].x.blk.send_sent_qcnt = (u_int16_t)(asoc->send_queue_cnt + asoc->sent_queue_cnt);
326 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (u_int16_t)asoc->stream_queue_cnt;
327 sctp_cwnd_log_at++;
328 if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
329 sctp_cwnd_log_at = 0;
330 sctp_cwnd_log_rolled = 1;
331 }
332}
333
334int
335sctp_fill_stat_log(struct mbuf *m)
336{
337 struct sctp_cwnd_log_req *req;
338 int size_limit, num, i, at, cnt_out=0;
339
340 if (m == NULL)
341 return (EINVAL);
342
343 size_limit = (m->m_len - sizeof(struct sctp_cwnd_log_req));
344 if (size_limit < sizeof(struct sctp_cwnd_log)) {
345 return (EINVAL);
346 }
347 req = mtod(m, struct sctp_cwnd_log_req *);
348 num = size_limit/sizeof(struct sctp_cwnd_log);
349 if (sctp_cwnd_log_rolled) {
350 req->num_in_log = SCTP_STAT_LOG_SIZE;
351 } else {
352 req->num_in_log = sctp_cwnd_log_at;
353 /* if the log has not rolled, we don't
354 * let you have old data.
355 */
356 if (req->end_at > sctp_cwnd_log_at) {
357 req->end_at = sctp_cwnd_log_at;
358 }
359 }
360 if ((num < SCTP_STAT_LOG_SIZE) &&
361 ((sctp_cwnd_log_rolled) || (sctp_cwnd_log_at > num))) {
362 /* we can't return all of it */
363 if (((req->start_at == 0) && (req->end_at == 0)) ||
364 (req->start_at >= SCTP_STAT_LOG_SIZE) ||
365 (req->end_at >= SCTP_STAT_LOG_SIZE)) {
366 /* No user request or user is wacked. */
367 req->num_ret = num;
368 req->end_at = sctp_cwnd_log_at - 1;
369 if ((sctp_cwnd_log_at - num) < 0) {
370 int cc;
371 cc = num - sctp_cwnd_log_at;
372 req->start_at = SCTP_STAT_LOG_SIZE - cc;
373 } else {
374 req->start_at = sctp_cwnd_log_at - num;
375 }
376 } else {
377 /* a user request */
378 int cc;
379 if (req->start_at > req->end_at) {
380 cc = (SCTP_STAT_LOG_SIZE - req->start_at) +
381 (req->end_at + 1);
382 } else {
383
384 cc = req->end_at - req->start_at;
385 }
386 if (cc < num) {
387 num = cc;
388 }
389 req->num_ret = num;
390 }
391 } else {
392 /* We can return all of it */
393 req->start_at = 0;
394 req->end_at = sctp_cwnd_log_at - 1;
395 req->num_ret = sctp_cwnd_log_at;
396 }
397 for (i = 0, at = req->start_at; i < req->num_ret; i++) {
398 req->log[i] = sctp_clog[at];
399 cnt_out++;
400 at++;
401 if (at >= SCTP_STAT_LOG_SIZE)
402 at = 0;
403 }
404 m->m_len = (cnt_out * sizeof(struct sctp_cwnd_log_req)) + sizeof(struct sctp_cwnd_log_req);
405 return (0);
406}
407
408#endif
409
410#ifdef SCTP_AUDITING_ENABLED
411u_int8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
412static int sctp_audit_indx = 0;
413
f3f70f0d
SW
414static void
415sctp_print_audit_report(void)
8d60bf8a
EN
416{
417 int i;
418 int cnt;
419 cnt = 0;
420 for (i=sctp_audit_indx;i<SCTP_AUDIT_SIZE;i++) {
421 if ((sctp_audit_data[i][0] == 0xe0) &&
422 (sctp_audit_data[i][1] == 0x01)) {
423 cnt = 0;
a6ec04bc 424 kprintf("\n");
8d60bf8a
EN
425 } else if (sctp_audit_data[i][0] == 0xf0) {
426 cnt = 0;
a6ec04bc 427 kprintf("\n");
8d60bf8a
EN
428 } else if ((sctp_audit_data[i][0] == 0xc0) &&
429 (sctp_audit_data[i][1] == 0x01)) {
a6ec04bc 430 kprintf("\n");
8d60bf8a
EN
431 cnt = 0;
432 }
a6ec04bc 433 kprintf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
8d60bf8a
EN
434 (uint32_t)sctp_audit_data[i][1]);
435 cnt++;
436 if ((cnt % 14) == 0)
a6ec04bc 437 kprintf("\n");
8d60bf8a
EN
438 }
439 for (i=0;i<sctp_audit_indx;i++) {
440 if ((sctp_audit_data[i][0] == 0xe0) &&
441 (sctp_audit_data[i][1] == 0x01)) {
442 cnt = 0;
a6ec04bc 443 kprintf("\n");
8d60bf8a
EN
444 } else if (sctp_audit_data[i][0] == 0xf0) {
445 cnt = 0;
a6ec04bc 446 kprintf("\n");
8d60bf8a
EN
447 } else if ((sctp_audit_data[i][0] == 0xc0) &&
448 (sctp_audit_data[i][1] == 0x01)) {
a6ec04bc 449 kprintf("\n");
8d60bf8a
EN
450 cnt = 0;
451 }
a6ec04bc 452 kprintf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
8d60bf8a
EN
453 (uint32_t)sctp_audit_data[i][1]);
454 cnt++;
455 if ((cnt % 14) == 0)
a6ec04bc 456 kprintf("\n");
8d60bf8a 457 }
a6ec04bc 458 kprintf("\n");
8d60bf8a
EN
459}
460
f3f70f0d
SW
461void
462sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
463 struct sctp_nets *net)
8d60bf8a
EN
464{
465 int resend_cnt, tot_out, rep, tot_book_cnt;
466 struct sctp_nets *lnet;
467 struct sctp_tmit_chunk *chk;
468
469 sctp_audit_data[sctp_audit_indx][0] = 0xAA;
470 sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
471 sctp_audit_indx++;
472 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
473 sctp_audit_indx = 0;
474 }
475 if (inp == NULL) {
476 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
477 sctp_audit_data[sctp_audit_indx][1] = 0x01;
478 sctp_audit_indx++;
479 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
480 sctp_audit_indx = 0;
481 }
482 return;
483 }
484 if (stcb == NULL) {
485 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
486 sctp_audit_data[sctp_audit_indx][1] = 0x02;
487 sctp_audit_indx++;
488 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
489 sctp_audit_indx = 0;
490 }
491 return;
492 }
493 sctp_audit_data[sctp_audit_indx][0] = 0xA1;
494 sctp_audit_data[sctp_audit_indx][1] =
495 (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
496 sctp_audit_indx++;
497 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
498 sctp_audit_indx = 0;
499 }
500 rep = 0;
501 tot_book_cnt = 0;
502 resend_cnt = tot_out = 0;
503 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
504 if (chk->sent == SCTP_DATAGRAM_RESEND) {
505 resend_cnt++;
506 } else if (chk->sent < SCTP_DATAGRAM_RESEND) {
507 tot_out += chk->book_size;
508 tot_book_cnt++;
509 }
510 }
511 if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
512 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
513 sctp_audit_data[sctp_audit_indx][1] = 0xA1;
514 sctp_audit_indx++;
515 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
516 sctp_audit_indx = 0;
517 }
a6ec04bc 518 kprintf("resend_cnt:%d asoc-tot:%d\n",
8d60bf8a
EN
519 resend_cnt, stcb->asoc.sent_queue_retran_cnt);
520 rep = 1;
521 stcb->asoc.sent_queue_retran_cnt = resend_cnt;
522 sctp_audit_data[sctp_audit_indx][0] = 0xA2;
523 sctp_audit_data[sctp_audit_indx][1] =
524 (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
525 sctp_audit_indx++;
526 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
527 sctp_audit_indx = 0;
528 }
529 }
530 if (tot_out != stcb->asoc.total_flight) {
531 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
532 sctp_audit_data[sctp_audit_indx][1] = 0xA2;
533 sctp_audit_indx++;
534 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
535 sctp_audit_indx = 0;
536 }
537 rep = 1;
a6ec04bc 538 kprintf("tot_flt:%d asoc_tot:%d\n", tot_out,
8d60bf8a
EN
539 (int)stcb->asoc.total_flight);
540 stcb->asoc.total_flight = tot_out;
541 }
542 if (tot_book_cnt != stcb->asoc.total_flight_count) {
543 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
544 sctp_audit_data[sctp_audit_indx][1] = 0xA5;
545 sctp_audit_indx++;
546 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
547 sctp_audit_indx = 0;
548 }
549 rep = 1;
a6ec04bc 550 kprintf("tot_flt_book:%d\n", tot_book);
8d60bf8a
EN
551
552 stcb->asoc.total_flight_count = tot_book_cnt;
553 }
554 tot_out = 0;
555 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
556 tot_out += lnet->flight_size;
557 }
558 if (tot_out != stcb->asoc.total_flight) {
559 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
560 sctp_audit_data[sctp_audit_indx][1] = 0xA3;
561 sctp_audit_indx++;
562 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
563 sctp_audit_indx = 0;
564 }
565 rep = 1;
a6ec04bc 566 kprintf("real flight:%d net total was %d\n",
8d60bf8a
EN
567 stcb->asoc.total_flight, tot_out);
568 /* now corrective action */
569 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
570 tot_out = 0;
571 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
572 if ((chk->whoTo == lnet) &&
573 (chk->sent < SCTP_DATAGRAM_RESEND)) {
574 tot_out += chk->book_size;
575 }
576 }
577 if (lnet->flight_size != tot_out) {
a6ec04bc 578 kprintf("net:%x flight was %d corrected to %d\n",
8d60bf8a
EN
579 (uint32_t)lnet, lnet->flight_size, tot_out);
580 lnet->flight_size = tot_out;
581 }
582
583 }
584 }
585
586 if (rep) {
587 sctp_print_audit_report();
588 }
589}
590
591void
592sctp_audit_log(u_int8_t ev, u_int8_t fd)
593{
66a25ac4 594 crit_enter();
8d60bf8a
EN
595 sctp_audit_data[sctp_audit_indx][0] = ev;
596 sctp_audit_data[sctp_audit_indx][1] = fd;
597 sctp_audit_indx++;
598 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
599 sctp_audit_indx = 0;
600 }
66a25ac4 601 crit_exit();
8d60bf8a
EN
602}
603
604#endif
605
606/*
607 * a list of sizes based on typical mtu's, used only if next hop
608 * size not returned.
609 */
610static int sctp_mtu_sizes[] = {
611 68,
612 296,
613 508,
614 512,
615 544,
616 576,
617 1006,
618 1492,
619 1500,
620 1536,
621 2002,
622 2048,
623 4352,
624 4464,
625 8166,
626 17914,
627 32000,
628 65535
629};
630
631int
632find_next_best_mtu(int totsz)
633{
634 int i, perfer;
635 /*
636 * if we are in here we must find the next best fit based on the
637 * size of the dg that failed to be sent.
638 */
639 perfer = 0;
640 for (i = 0; i < NUMBER_OF_MTU_SIZES; i++) {
641 if (totsz < sctp_mtu_sizes[i]) {
642 perfer = i - 1;
643 if (perfer < 0)
644 perfer = 0;
645 break;
646 }
647 }
648 return (sctp_mtu_sizes[perfer]);
649}
650
651void
652sctp_fill_random_store(struct sctp_pcb *m)
653{
654 /*
655 * Here we use the MD5/SHA-1 to hash with our good randomNumbers
656 * and our counter. The result becomes our good random numbers and
657 * we then setup to give these out. Note that we do no lockig
658 * to protect this. This is ok, since if competing folks call
659 * this we will get more gobbled gook in the random store whic
660 * is what we want. There is a danger that two guys will use
661 * the same random numbers, but thats ok too since that
662 * is random as well :->
663 */
664 m->store_at = 0;
665 sctp_hash_digest((char *)m->random_numbers, sizeof(m->random_numbers),
666 (char *)&m->random_counter, sizeof(m->random_counter),
667 (char *)m->random_store);
668 m->random_counter++;
669}
670
671uint32_t
672sctp_select_initial_TSN(struct sctp_pcb *m)
673{
674 /*
675 * A true implementation should use random selection process to
676 * get the initial stream sequence number, using RFC1750 as a
677 * good guideline
678 */
679 u_long x, *xp;
680 uint8_t *p;
681
682 if (m->initial_sequence_debug != 0) {
683 u_int32_t ret;
684 ret = m->initial_sequence_debug;
685 m->initial_sequence_debug++;
686 return (ret);
687 }
688 if ((m->store_at+sizeof(u_long)) > SCTP_SIGNATURE_SIZE) {
689 /* Refill the random store */
690 sctp_fill_random_store(m);
691 }
692 p = &m->random_store[(int)m->store_at];
693 xp = (u_long *)p;
694 x = *xp;
695 m->store_at += sizeof(u_long);
696 return (x);
697}
698
f3f70f0d
SW
699u_int32_t
700sctp_select_a_tag(struct sctp_inpcb *m)
8d60bf8a
EN
701{
702 u_long x, not_done;
703 struct timeval now;
704
705 SCTP_GETTIME_TIMEVAL(&now);
706 not_done = 1;
707 while (not_done) {
708 x = sctp_select_initial_TSN(&m->sctp_ep);
709 if (x == 0) {
710 /* we never use 0 */
711 continue;
712 }
713 if (sctp_is_vtag_good(m, x, &now)) {
714 not_done = 0;
715 }
716 }
717 return (x);
718}
719
720
721int
722sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
723 int for_a_init, uint32_t override_tag )
724{
725 /*
726 * Anything set to zero is taken care of by the allocation
727 * routine's bzero
728 */
729
730 /*
731 * Up front select what scoping to apply on addresses I tell my peer
732 * Not sure what to do with these right now, we will need to come up
733 * with a way to set them. We may need to pass them through from the
734 * caller in the sctp_aloc_assoc() function.
735 */
736 int i;
737 /* init all variables to a known value.*/
738 asoc->state = SCTP_STATE_INUSE;
739 asoc->max_burst = m->sctp_ep.max_burst;
740 asoc->heart_beat_delay = m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT];
741 asoc->cookie_life = m->sctp_ep.def_cookie_life;
742
743 if (override_tag) {
744 asoc->my_vtag = override_tag;
745 } else {
746 asoc->my_vtag = sctp_select_a_tag(m);
747 }
748 asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
749 sctp_select_initial_TSN(&m->sctp_ep);
750 asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
751 /* we are opptimisitic here */
752 asoc->peer_supports_asconf = 1;
753 asoc->peer_supports_asconf_setprim = 1;
754 asoc->peer_supports_pktdrop = 1;
755
756 asoc->sent_queue_retran_cnt = 0;
757 /* This will need to be adjusted */
758 asoc->last_cwr_tsn = asoc->init_seq_number - 1;
759 asoc->last_acked_seq = asoc->init_seq_number - 1;
760 asoc->advanced_peer_ack_point = asoc->last_acked_seq;
761 asoc->asconf_seq_in = asoc->last_acked_seq;
762
763 /* here we are different, we hold the next one we expect */
764 asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
765
766 asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max;
767 asoc->initial_rto = m->sctp_ep.initial_rto;
768
769 asoc->max_init_times = m->sctp_ep.max_init_times;
770 asoc->max_send_times = m->sctp_ep.max_send_times;
771 asoc->def_net_failure = m->sctp_ep.def_net_failure;
772
773 /* ECN Nonce initialization */
774 asoc->ecn_nonce_allowed = 0;
775 asoc->receiver_nonce_sum = 1;
776 asoc->nonce_sum_expect_base = 1;
777 asoc->nonce_sum_check = 1;
778 asoc->nonce_resync_tsn = 0;
779 asoc->nonce_wait_for_ecne = 0;
780 asoc->nonce_wait_tsn = 0;
781
782 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
783 struct in6pcb *inp6;
784
785
786 /* Its a V6 socket */
787 inp6 = (struct in6pcb *)m;
788 asoc->ipv6_addr_legal = 1;
789 /* Now look at the binding flag to see if V4 will be legal */
790 if (
791#if defined(__OpenBSD__)
792 (0) /* we always do dual bind */
793#elif defined (__NetBSD__)
794 (inp6->in6p_flags & IN6P_IPV6_V6ONLY)
795#else
796 (inp6->inp_flags & IN6P_IPV6_V6ONLY)
797#endif
798 == 0) {
799 asoc->ipv4_addr_legal = 1;
800 } else {
801 /* V4 addresses are NOT legal on the association */
802 asoc->ipv4_addr_legal = 0;
803 }
804 } else {
805 /* Its a V4 socket, no - V6 */
806 asoc->ipv4_addr_legal = 1;
807 asoc->ipv6_addr_legal = 0;
808 }
809
810
6d49aa6f
MD
811 asoc->my_rwnd = max(m->sctp_socket->so_rcv.ssb_hiwat, SCTP_MINIMAL_RWND);
812 asoc->peers_rwnd = m->sctp_socket->so_rcv.ssb_hiwat;
8d60bf8a
EN
813
814 asoc->smallest_mtu = m->sctp_frag_point;
815 asoc->minrto = m->sctp_ep.sctp_minrto;
816 asoc->maxrto = m->sctp_ep.sctp_maxrto;
817
818 LIST_INIT(&asoc->sctp_local_addr_list);
819 TAILQ_INIT(&asoc->nets);
820 TAILQ_INIT(&asoc->pending_reply_queue);
821 asoc->last_asconf_ack_sent = NULL;
822 /* Setup to fill the hb random cache at first HB */
823 asoc->hb_random_idx = 4;
824
825 asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
826
827 /*
828 * Now the stream parameters, here we allocate space for all
829 * streams that we request by default.
830 */
831 asoc->streamoutcnt = asoc->pre_open_streams =
832 m->sctp_ep.pre_open_stream_count;
884717e1
SW
833 asoc->strmout = kmalloc(asoc->streamoutcnt * sizeof(struct sctp_stream_out),
834 M_PCB, M_NOWAIT);
8d60bf8a
EN
835 if (asoc->strmout == NULL) {
836 /* big trouble no memory */
837 return (ENOMEM);
838 }
839 for (i = 0; i < asoc->streamoutcnt; i++) {
840 /*
841 * inbound side must be set to 0xffff,
842 * also NOTE when we get the INIT-ACK back (for INIT sender)
843 * we MUST reduce the count (streamoutcnt) but first check
844 * if we sent to any of the upper streams that were dropped
845 * (if some were). Those that were dropped must be notified
846 * to the upper layer as failed to send.
847 */
848 asoc->strmout[i].next_sequence_sent = 0x0;
849 TAILQ_INIT(&asoc->strmout[i].outqueue);
850 asoc->strmout[i].stream_no = i;
851 asoc->strmout[i].next_spoke.tqe_next = 0;
852 asoc->strmout[i].next_spoke.tqe_prev = 0;
853 }
854 /* Now the mapping array */
855 asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
856#ifdef __NetBSD__
884717e1
SW
857 asoc->mapping_array = kmalloc(SCTP_INITIAL_MAPPING_ARRAY, M_PCB,
858 M_NOWAIT);
8d60bf8a 859#else
884717e1
SW
860 asoc->mapping_array = kmalloc(asoc->mapping_array_size, M_PCB,
861 M_NOWAIT);
8d60bf8a
EN
862#endif
863 if (asoc->mapping_array == NULL) {
884717e1 864 kfree(asoc->strmout, M_PCB);
8d60bf8a
EN
865 return (ENOMEM);
866 }
867 memset(asoc->mapping_array, 0, asoc->mapping_array_size);
868 /* Now the init of the other outqueues */
869 TAILQ_INIT(&asoc->out_wheel);
870 TAILQ_INIT(&asoc->control_send_queue);
871 TAILQ_INIT(&asoc->send_queue);
872 TAILQ_INIT(&asoc->sent_queue);
873 TAILQ_INIT(&asoc->reasmqueue);
874 TAILQ_INIT(&asoc->delivery_queue);
875 asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome;
876
877 TAILQ_INIT(&asoc->asconf_queue);
878 return (0);
879}
880
881int
882sctp_expand_mapping_array(struct sctp_association *asoc)
883{
884 /* mapping array needs to grow */
885 u_int8_t *new_array;
886 uint16_t new_size;
887
888 new_size = asoc->mapping_array_size + SCTP_MAPPING_ARRAY_INCR;
889#ifdef __NetBSD__
884717e1
SW
890 new_array = kmalloc(asoc->mapping_array_size + SCTP_MAPPING_ARRAY_INCR,
891 M_PCB, M_NOWAIT);
8d60bf8a 892#else
884717e1 893 new_array = kmalloc(new_size, M_PCB, M_NOWAIT);
8d60bf8a
EN
894#endif
895 if (new_array == NULL) {
896 /* can't get more, forget it */
a6ec04bc 897 kprintf("No memory for expansion of SCTP mapping array %d\n",
8d60bf8a
EN
898 new_size);
899 return (-1);
900 }
901 memset(new_array, 0, new_size);
902 memcpy(new_array, asoc->mapping_array, asoc->mapping_array_size);
884717e1 903 kfree(asoc->mapping_array, M_PCB);
8d60bf8a
EN
904 asoc->mapping_array = new_array;
905 asoc->mapping_array_size = new_size;
906 return (0);
907}
908
909static void
910sctp_timeout_handler(void *t)
911{
912 struct sctp_inpcb *inp;
913 struct sctp_tcb *stcb;
914 struct sctp_nets *net;
915 struct sctp_timer *tmr;
66a25ac4 916 int did_output, typ;
8d60bf8a
EN
917#if defined(__APPLE__)
918 boolean_t funnel_state;
919
920 /* get BSD kernel funnel/mutex */
921 funnel_state = thread_funnel_set(network_flock, TRUE);
922#endif
923
66a25ac4 924 crit_enter();
8d60bf8a
EN
925 tmr = (struct sctp_timer *)t;
926 inp = (struct sctp_inpcb *)tmr->ep;
927 stcb = (struct sctp_tcb *)tmr->tcb;
928 net = (struct sctp_nets *)tmr->net;
929 did_output = 1;
930
931
932#ifdef SCTP_AUDITING_ENABLED
933 sctp_audit_log(0xF0, (u_int8_t)tmr->type);
934 sctp_auditing(3, inp, stcb, net);
935#endif
936 sctp_pegs[SCTP_TIMERS_EXP]++;
937
938 if (inp == NULL) {
807be17b 939 crit_exit();
8d60bf8a
EN
940 return;
941 }
942
943 SCTP_INP_WLOCK(inp);
944 if (inp->sctp_socket == 0) {
66a25ac4 945 crit_exit();
8d60bf8a
EN
946#if defined(__APPLE__)
947 /* release BSD kernel funnel/mutex */
f3f70f0d 948 thread_funnel_set(network_flock, FALSE);
8d60bf8a
EN
949#endif
950 SCTP_INP_WUNLOCK(inp);
951 return;
952 }
953 if (stcb) {
954 if (stcb->asoc.state == 0) {
66a25ac4 955 crit_exit();
8d60bf8a
EN
956#if defined(__APPLE__)
957 /* release BSD kernel funnel/mutex */
f3f70f0d 958 thread_funnel_set(network_flock, FALSE);
8d60bf8a
EN
959#endif
960 SCTP_INP_WUNLOCK(inp);
961 return;
962 }
963 }
964#ifdef SCTP_DEBUG
965 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 966 kprintf("Timer type %d goes off\n", tmr->type);
8d60bf8a
EN
967 }
968#endif /* SCTP_DEBUG */
969#ifndef __NetBSD__
970 if (!callout_active(&tmr->timer)) {
66a25ac4 971 crit_exit();
8d60bf8a
EN
972#if defined(__APPLE__)
973 /* release BSD kernel funnel/mutex */
f3f70f0d 974 thread_funnel_set(network_flock, FALSE);
8d60bf8a
EN
975#endif
976 SCTP_INP_WUNLOCK(inp);
977 return;
978 }
979#endif
980#if defined(__APPLE__)
981 /* clear the callout pending status here */
982 callout_stop(&tmr->timer);
983#endif
984 if (stcb) {
985 SCTP_TCB_LOCK(stcb);
986 }
987 SCTP_INP_INCR_REF(inp);
988 SCTP_INP_WUNLOCK(inp);
989
990 typ = tmr->type;
991 switch (tmr->type) {
992 case SCTP_TIMER_TYPE_ITERATOR:
993 {
994 struct sctp_iterator *it;
995 it = (struct sctp_iterator *)inp;
996 sctp_iterator_timer(it);
997 }
998 break;
999 /* call the handler for the appropriate timer type */
1000 case SCTP_TIMER_TYPE_SEND:
1001 sctp_pegs[SCTP_TMIT_TIMER]++;
1002 stcb->asoc.num_send_timers_up--;
1003 if (stcb->asoc.num_send_timers_up < 0) {
1004 stcb->asoc.num_send_timers_up = 0;
1005 }
1006 if (sctp_t3rxt_timer(inp, stcb, net)) {
1007 /* no need to unlock on tcb its gone */
1008
1009 goto out_decr;
1010 }
1011#ifdef SCTP_AUDITING_ENABLED
1012 sctp_auditing(4, inp, stcb, net);
1013#endif
1014 sctp_chunk_output(inp, stcb, 1);
1015 if ((stcb->asoc.num_send_timers_up == 0) &&
1016 (stcb->asoc.sent_queue_cnt > 0)
1017 ) {
1018 struct sctp_tmit_chunk *chk;
1019 /*
1020 * safeguard. If there on some on the sent queue
1021 * somewhere but no timers running something is
1022 * wrong... so we start a timer on the first chunk
1023 * on the send queue on whatever net it is sent to.
1024 */
1025 sctp_pegs[SCTP_T3_SAFEGRD]++;
1026 chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
1027 sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
1028 chk->whoTo);
1029 }
1030 break;
1031 case SCTP_TIMER_TYPE_INIT:
1032 if (sctp_t1init_timer(inp, stcb, net)) {
1033 /* no need to unlock on tcb its gone */
1034 goto out_decr;
1035 }
1036 /* We do output but not here */
1037 did_output = 0;
1038 break;
1039 case SCTP_TIMER_TYPE_RECV:
1040 sctp_pegs[SCTP_RECV_TIMER]++;
1041 sctp_send_sack(stcb);
1042#ifdef SCTP_AUDITING_ENABLED
1043 sctp_auditing(4, inp, stcb, net);
1044#endif
1045 sctp_chunk_output(inp, stcb, 4);
1046 break;
1047 case SCTP_TIMER_TYPE_SHUTDOWN:
1048 if (sctp_shutdown_timer(inp, stcb, net) ) {
1049 /* no need to unlock on tcb its gone */
1050 goto out_decr;
1051 }
1052#ifdef SCTP_AUDITING_ENABLED
1053 sctp_auditing(4, inp, stcb, net);
1054#endif
1055 sctp_chunk_output(inp, stcb, 5);
1056 break;
1057 case SCTP_TIMER_TYPE_HEARTBEAT:
1058 if (sctp_heartbeat_timer(inp, stcb, net)) {
1059 /* no need to unlock on tcb its gone */
1060 goto out_decr;
1061 }
1062#ifdef SCTP_AUDITING_ENABLED
1063 sctp_auditing(4, inp, stcb, net);
1064#endif
1065 sctp_chunk_output(inp, stcb, 6);
1066 break;
1067 case SCTP_TIMER_TYPE_COOKIE:
1068 if (sctp_cookie_timer(inp, stcb, net)) {
1069 /* no need to unlock on tcb its gone */
1070 goto out_decr;
1071 }
1072#ifdef SCTP_AUDITING_ENABLED
1073 sctp_auditing(4, inp, stcb, net);
1074#endif
1075 sctp_chunk_output(inp, stcb, 1);
1076 break;
1077 case SCTP_TIMER_TYPE_NEWCOOKIE:
1078 {
1079 struct timeval tv;
1080 int i, secret;
1081 SCTP_GETTIME_TIMEVAL(&tv);
1082 SCTP_INP_WLOCK(inp);
1083 inp->sctp_ep.time_of_secret_change = tv.tv_sec;
1084 inp->sctp_ep.last_secret_number =
1085 inp->sctp_ep.current_secret_number;
1086 inp->sctp_ep.current_secret_number++;
1087 if (inp->sctp_ep.current_secret_number >=
1088 SCTP_HOW_MANY_SECRETS) {
1089 inp->sctp_ep.current_secret_number = 0;
1090 }
1091 secret = (int)inp->sctp_ep.current_secret_number;
1092 for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
1093 inp->sctp_ep.secret_key[secret][i] =
1094 sctp_select_initial_TSN(&inp->sctp_ep);
1095 }
1096 SCTP_INP_WUNLOCK(inp);
1097 sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
1098 }
1099 did_output = 0;
1100 break;
1101 case SCTP_TIMER_TYPE_PATHMTURAISE:
1102 sctp_pathmtu_timer(inp, stcb, net);
1103 did_output = 0;
1104 break;
1105 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1106 if (sctp_shutdownack_timer(inp, stcb, net)) {
1107 /* no need to unlock on tcb its gone */
1108 goto out_decr;
1109 }
1110#ifdef SCTP_AUDITING_ENABLED
1111 sctp_auditing(4, inp, stcb, net);
1112#endif
1113 sctp_chunk_output(inp, stcb, 7);
1114 break;
1115 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1116 sctp_abort_an_association(inp, stcb,
1117 SCTP_SHUTDOWN_GUARD_EXPIRES, NULL);
1118 /* no need to unlock on tcb its gone */
1119 goto out_decr;
1120 break;
1121
1122 case SCTP_TIMER_TYPE_STRRESET:
1123 if (sctp_strreset_timer(inp, stcb, net)) {
1124 /* no need to unlock on tcb its gone */
1125 goto out_decr;
1126 }
1127 sctp_chunk_output(inp, stcb, 9);
1128 break;
1129
1130 case SCTP_TIMER_TYPE_ASCONF:
1131 if (sctp_asconf_timer(inp, stcb, net)) {
1132 /* no need to unlock on tcb its gone */
1133 goto out_decr;
1134 }
1135#ifdef SCTP_AUDITING_ENABLED
1136 sctp_auditing(4, inp, stcb, net);
1137#endif
1138 sctp_chunk_output(inp, stcb, 8);
1139 break;
1140
1141 case SCTP_TIMER_TYPE_AUTOCLOSE:
1142 sctp_autoclose_timer(inp, stcb, net);
1143 sctp_chunk_output(inp, stcb, 10);
1144 did_output = 0;
1145 break;
1146 case SCTP_TIMER_TYPE_INPKILL:
1147 /* special case, take away our
1148 * increment since WE are the killer
1149 */
1150 SCTP_INP_WLOCK(inp);
1151 SCTP_INP_DECR_REF(inp);
1152 SCTP_INP_WUNLOCK(inp);
1153 sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL);
1154 sctp_inpcb_free(inp, 1);
1155 goto out_no_decr;
1156 break;
1157 default:
1158#ifdef SCTP_DEBUG
1159 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1160 kprintf("sctp_timeout_handler:unknown timer %d\n",
8d60bf8a
EN
1161 tmr->type);
1162 }
1163#endif /* SCTP_DEBUG */
1164 break;
1165 };
1166#ifdef SCTP_AUDITING_ENABLED
1167 sctp_audit_log(0xF1, (u_int8_t)tmr->type);
1168 sctp_auditing(5, inp, stcb, net);
1169#endif
1170 if (did_output) {
1171 /*
1172 * Now we need to clean up the control chunk chain if an
1173 * ECNE is on it. It must be marked as UNSENT again so next
1174 * call will continue to send it until such time that we get
1175 * a CWR, to remove it. It is, however, less likely that we
1176 * will find a ecn echo on the chain though.
1177 */
1178 sctp_fix_ecn_echo(&stcb->asoc);
1179 }
1180 if (stcb) {
1181 SCTP_TCB_UNLOCK(stcb);
1182 }
1183 out_decr:
1184 SCTP_INP_WLOCK(inp);
1185 SCTP_INP_DECR_REF(inp);
1186 SCTP_INP_WUNLOCK(inp);
1187
1188 out_no_decr:
1189
1190#ifdef SCTP_DEBUG
1191 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1192 kprintf("Timer now complete (type %d)\n", typ);
8d60bf8a
EN
1193 }
1194#endif /* SCTP_DEBUG */
1195
66a25ac4 1196 crit_exit();
8d60bf8a
EN
1197#if defined(__APPLE__)
1198 /* release BSD kernel funnel/mutex */
f3f70f0d 1199 thread_funnel_set(network_flock, FALSE);
8d60bf8a
EN
1200#endif
1201}
1202
1203int
1204sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1205 struct sctp_nets *net)
1206{
1207 int to_ticks;
1208 struct sctp_timer *tmr;
1209
1210 if (inp == NULL)
1211 return (EFAULT);
1212
1213 to_ticks = 0;
1214
1215 tmr = NULL;
1216 switch (t_type) {
1217 case SCTP_TIMER_TYPE_ITERATOR:
1218 {
1219 struct sctp_iterator *it;
1220 it = (struct sctp_iterator *)inp;
1221 tmr = &it->tmr;
1222 to_ticks = SCTP_ITERATOR_TICKS;
1223 }
1224 break;
1225 case SCTP_TIMER_TYPE_SEND:
1226 /* Here we use the RTO timer */
1227 {
1228 int rto_val;
1229 if ((stcb == NULL) || (net == NULL)) {
1230 return (EFAULT);
1231 }
1232 tmr = &net->rxt_timer;
1233 if (net->RTO == 0) {
1234 rto_val = stcb->asoc.initial_rto;
1235 } else {
1236 rto_val = net->RTO;
1237 }
1238 to_ticks = MSEC_TO_TICKS(rto_val);
1239 }
1240 break;
1241 case SCTP_TIMER_TYPE_INIT:
1242 /*
1243 * Here we use the INIT timer default
1244 * usually about 1 minute.
1245 */
1246 if ((stcb == NULL) || (net == NULL)) {
1247 return (EFAULT);
1248 }
1249 tmr = &net->rxt_timer;
1250 if (net->RTO == 0) {
1251 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1252 } else {
1253 to_ticks = MSEC_TO_TICKS(net->RTO);
1254 }
1255 break;
1256 case SCTP_TIMER_TYPE_RECV:
1257 /*
1258 * Here we use the Delayed-Ack timer value from the inp
1259 * ususually about 200ms.
1260 */
1261 if (stcb == NULL) {
1262 return (EFAULT);
1263 }
1264 tmr = &stcb->asoc.dack_timer;
1265 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV];
1266 break;
1267 case SCTP_TIMER_TYPE_SHUTDOWN:
1268 /* Here we use the RTO of the destination. */
1269 if ((stcb == NULL) || (net == NULL)) {
1270 return (EFAULT);
1271 }
1272
1273 if (net->RTO == 0) {
1274 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1275 } else {
1276 to_ticks = MSEC_TO_TICKS(net->RTO);
1277 }
1278 tmr = &net->rxt_timer;
1279 break;
1280 case SCTP_TIMER_TYPE_HEARTBEAT:
1281 /*
1282 * the net is used here so that we can add in the RTO.
1283 * Even though we use a different timer. We also add the
1284 * HB timer PLUS a random jitter.
1285 */
1286 if (stcb == NULL) {
1287 return (EFAULT);
1288 }
1289 {
1290 uint32_t rndval;
1291 uint8_t this_random;
1292 int cnt_of_unconf=0;
1293 struct sctp_nets *lnet;
1294
1295 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1296 if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
1297 cnt_of_unconf++;
1298 }
1299 }
1300#ifdef SCTP_DEBUG
1301 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1302 kprintf("HB timer to start unconfirmed:%d hb_delay:%d\n",
8d60bf8a
EN
1303 cnt_of_unconf, stcb->asoc.heart_beat_delay);
1304 }
1305#endif
1306 if (stcb->asoc.hb_random_idx > 3) {
1307 rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1308 memcpy(stcb->asoc.hb_random_values, &rndval,
1309 sizeof(stcb->asoc.hb_random_values));
1310 this_random = stcb->asoc.hb_random_values[0];
1311 stcb->asoc.hb_random_idx = 0;
1312 stcb->asoc.hb_ect_randombit = 0;
1313 } else {
1314 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
1315 stcb->asoc.hb_random_idx++;
1316 stcb->asoc.hb_ect_randombit = 0;
1317 }
1318 /*
1319 * this_random will be 0 - 256 ms
1320 * RTO is in ms.
1321 */
1322 if ((stcb->asoc.heart_beat_delay == 0) &&
1323 (cnt_of_unconf == 0)) {
1324 /* no HB on this inp after confirmations */
1325 return (0);
1326 }
1327 if (net) {
1328 struct sctp_nets *lnet;
1329 int delay;
1330 delay = stcb->asoc.heart_beat_delay;
1331 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
1332 if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
1333 ((lnet->dest_state & SCTP_ADDR_OUT_OF_SCOPE) == 0) &&
1334 (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
1335 delay = 0;
1336 }
1337 }
1338 if (net->RTO == 0) {
1339 /* Never been checked */
1340 to_ticks = this_random + stcb->asoc.initial_rto + delay;
1341 } else {
1342 /* set rto_val to the ms */
1343 to_ticks = delay + net->RTO + this_random;
1344 }
1345 } else {
1346 if (cnt_of_unconf) {
1347 to_ticks = this_random + stcb->asoc.initial_rto;
1348 } else {
1349 to_ticks = stcb->asoc.heart_beat_delay + this_random + stcb->asoc.initial_rto;
1350 }
1351 }
1352 /*
1353 * Now we must convert the to_ticks that are now in
1354 * ms to ticks.
1355 */
1356 to_ticks *= hz;
1357 to_ticks /= 1000;
1358#ifdef SCTP_DEBUG
1359 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1360 kprintf("Timer to expire in %d ticks\n", to_ticks);
8d60bf8a
EN
1361 }
1362#endif
1363 tmr = &stcb->asoc.hb_timer;
1364 }
1365 break;
1366 case SCTP_TIMER_TYPE_COOKIE:
1367 /*
1368 * Here we can use the RTO timer from the network since
1369 * one RTT was compelete. If a retran happened then we will
1370 * be using the RTO initial value.
1371 */
1372 if ((stcb == NULL) || (net == NULL)) {
1373 return (EFAULT);
1374 }
1375 if (net->RTO == 0) {
1376 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1377 } else {
1378 to_ticks = MSEC_TO_TICKS(net->RTO);
1379 }
1380 tmr = &net->rxt_timer;
1381 break;
1382 case SCTP_TIMER_TYPE_NEWCOOKIE:
1383 /*
1384 * nothing needed but the endpoint here
1385 * ususually about 60 minutes.
1386 */
1387 tmr = &inp->sctp_ep.signature_change;
1388 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
1389 break;
1390 case SCTP_TIMER_TYPE_INPKILL:
1391 /*
1392 * The inp is setup to die. We re-use the
1393 * signature_chage timer since that has
1394 * stopped and we are in the GONE state.
1395 */
1396 tmr = &inp->sctp_ep.signature_change;
1397 to_ticks = (SCTP_INP_KILL_TIMEOUT * hz) / 1000;
1398 break;
1399 case SCTP_TIMER_TYPE_PATHMTURAISE:
1400 /*
1401 * Here we use the value found in the EP for PMTU
1402 * ususually about 10 minutes.
1403 */
1404 if (stcb == NULL) {
1405 return (EFAULT);
1406 }
1407 if (net == NULL) {
1408 return (EFAULT);
1409 }
1410 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
1411 tmr = &net->pmtu_timer;
1412 break;
1413 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1414 /* Here we use the RTO of the destination */
1415 if ((stcb == NULL) || (net == NULL)) {
1416 return (EFAULT);
1417 }
1418 if (net->RTO == 0) {
1419 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1420 } else {
1421 to_ticks = MSEC_TO_TICKS(net->RTO);
1422 }
1423 tmr = &net->rxt_timer;
1424 break;
1425 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1426 /*
1427 * Here we use the endpoints shutdown guard timer
1428 * usually about 3 minutes.
1429 */
1430 if (stcb == NULL) {
1431 return (EFAULT);
1432 }
1433 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
1434 tmr = &stcb->asoc.shut_guard_timer;
1435 break;
1436 case SCTP_TIMER_TYPE_STRRESET:
1437 /*
1438 * Here the timer comes from the inp
1439 * but its value is from the RTO.
1440 */
1441 if ((stcb == NULL) || (net == NULL)) {
1442 return (EFAULT);
1443 }
1444 if (net->RTO == 0) {
1445 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1446 } else {
1447 to_ticks = MSEC_TO_TICKS(net->RTO);
1448 }
1449 tmr = &stcb->asoc.strreset_timer;
1450 break;
1451
1452 case SCTP_TIMER_TYPE_ASCONF:
1453 /*
1454 * Here the timer comes from the inp
1455 * but its value is from the RTO.
1456 */
1457 if ((stcb == NULL) || (net == NULL)) {
1458 return (EFAULT);
1459 }
1460 if (net->RTO == 0) {
1461 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1462 } else {
1463 to_ticks = MSEC_TO_TICKS(net->RTO);
1464 }
1465 tmr = &stcb->asoc.asconf_timer;
1466 break;
1467 case SCTP_TIMER_TYPE_AUTOCLOSE:
1468 if (stcb == NULL) {
1469 return (EFAULT);
1470 }
1471 if (stcb->asoc.sctp_autoclose_ticks == 0) {
1472 /* Really an error since stcb is NOT set to autoclose */
1473 return (0);
1474 }
1475 to_ticks = stcb->asoc.sctp_autoclose_ticks;
1476 tmr = &stcb->asoc.autoclose_timer;
1477 break;
1478 default:
1479#ifdef SCTP_DEBUG
1480 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1481 kprintf("sctp_timer_start:Unknown timer type %d\n",
8d60bf8a
EN
1482 t_type);
1483 }
1484#endif /* SCTP_DEBUG */
1485 return (EFAULT);
1486 break;
1487 };
1488 if ((to_ticks <= 0) || (tmr == NULL)) {
1489#ifdef SCTP_DEBUG
1490 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1491 kprintf("sctp_timer_start:%d:software error to_ticks:%d tmr:%p not set ??\n",
8d60bf8a
EN
1492 t_type, to_ticks, tmr);
1493 }
1494#endif /* SCTP_DEBUG */
1495 return (EFAULT);
1496 }
1497 if (callout_pending(&tmr->timer)) {
1498 /*
1499 * we do NOT allow you to have it already running.
1500 * if it is we leave the current one up unchanged
1501 */
1502 return (EALREADY);
1503 }
1504 /* At this point we can proceed */
1505 if (t_type == SCTP_TIMER_TYPE_SEND) {
1506 stcb->asoc.num_send_timers_up++;
1507 }
1508 tmr->type = t_type;
1509 tmr->ep = (void *)inp;
1510 tmr->tcb = (void *)stcb;
1511 tmr->net = (void *)net;
1512 callout_reset(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
1513 return (0);
1514}
1515
1516int
1517sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1518 struct sctp_nets *net)
1519{
1520 struct sctp_timer *tmr;
1521
1522 if (inp == NULL)
1523 return (EFAULT);
1524
1525 tmr = NULL;
1526 switch (t_type) {
1527 case SCTP_TIMER_TYPE_ITERATOR:
1528 {
1529 struct sctp_iterator *it;
1530 it = (struct sctp_iterator *)inp;
1531 tmr = &it->tmr;
1532 }
1533 break;
1534 case SCTP_TIMER_TYPE_SEND:
1535 if ((stcb == NULL) || (net == NULL)) {
1536 return (EFAULT);
1537 }
1538 tmr = &net->rxt_timer;
1539 break;
1540 case SCTP_TIMER_TYPE_INIT:
1541 if ((stcb == NULL) || (net == NULL)) {
1542 return (EFAULT);
1543 }
1544 tmr = &net->rxt_timer;
1545 break;
1546 case SCTP_TIMER_TYPE_RECV:
1547 if (stcb == NULL) {
1548 return (EFAULT);
1549 }
1550 tmr = &stcb->asoc.dack_timer;
1551 break;
1552 case SCTP_TIMER_TYPE_SHUTDOWN:
1553 if ((stcb == NULL) || (net == NULL)) {
1554 return (EFAULT);
1555 }
1556 tmr = &net->rxt_timer;
1557 break;
1558 case SCTP_TIMER_TYPE_HEARTBEAT:
1559 if (stcb == NULL) {
1560 return (EFAULT);
1561 }
1562 tmr = &stcb->asoc.hb_timer;
1563 break;
1564 case SCTP_TIMER_TYPE_COOKIE:
1565 if ((stcb == NULL) || (net == NULL)) {
1566 return (EFAULT);
1567 }
1568 tmr = &net->rxt_timer;
1569 break;
1570 case SCTP_TIMER_TYPE_NEWCOOKIE:
1571 /* nothing needed but the endpoint here */
1572 tmr = &inp->sctp_ep.signature_change;
1573 /* We re-use the newcookie timer for
1574 * the INP kill timer. We must assure
1575 * that we do not kill it by accident.
1576 */
1577 break;
1578 case SCTP_TIMER_TYPE_INPKILL:
1579 /*
1580 * The inp is setup to die. We re-use the
1581 * signature_chage timer since that has
1582 * stopped and we are in the GONE state.
1583 */
1584 tmr = &inp->sctp_ep.signature_change;
1585 break;
1586 case SCTP_TIMER_TYPE_PATHMTURAISE:
1587 if (stcb == NULL) {
1588 return (EFAULT);
1589 }
1590 if (net == NULL) {
1591 return (EFAULT);
1592 }
1593 tmr = &net->pmtu_timer;
1594 break;
1595 case SCTP_TIMER_TYPE_SHUTDOWNACK:
1596 if ((stcb == NULL) || (net == NULL)) {
1597 return (EFAULT);
1598 }
1599 tmr = &net->rxt_timer;
1600 break;
1601 case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1602 if (stcb == NULL) {
1603 return (EFAULT);
1604 }
1605 tmr = &stcb->asoc.shut_guard_timer;
1606 break;
1607 case SCTP_TIMER_TYPE_STRRESET:
1608 if (stcb == NULL) {
1609 return (EFAULT);
1610 }
1611 tmr = &stcb->asoc.strreset_timer;
1612 break;
1613 case SCTP_TIMER_TYPE_ASCONF:
1614 if (stcb == NULL) {
1615 return (EFAULT);
1616 }
1617 tmr = &stcb->asoc.asconf_timer;
1618 break;
1619 case SCTP_TIMER_TYPE_AUTOCLOSE:
1620 if (stcb == NULL) {
1621 return (EFAULT);
1622 }
1623 tmr = &stcb->asoc.autoclose_timer;
1624 break;
1625 default:
1626#ifdef SCTP_DEBUG
1627 if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
a6ec04bc 1628 kprintf("sctp_timer_stop:Unknown timer type %d\n",
8d60bf8a
EN
1629 t_type);
1630 }
1631#endif /* SCTP_DEBUG */
1632 break;
1633 };
1634 if (tmr == NULL)
1635 return (EFAULT);
1636
1637 if ((tmr->type != t_type) && tmr->type) {
1638 /*
1639 * Ok we have a timer that is under joint use. Cookie timer
1640 * per chance with the SEND timer. We therefore are NOT
1641 * running the timer that the caller wants stopped. So just
1642 * return.
1643 */
1644 return (0);
1645 }
1646 if (t_type == SCTP_TIMER_TYPE_SEND) {
1647 stcb->asoc.num_send_timers_up--;
1648 if (stcb->asoc.num_send_timers_up < 0) {
1649 stcb->asoc.num_send_timers_up = 0;
1650 }
1651 }
1652 callout_stop(&tmr->timer);
1653 return (0);
1654}
1655
1656#ifdef SCTP_USE_ADLER32
1657static uint32_t
1658update_adler32(uint32_t adler, uint8_t *buf, int32_t len)
1659{
1660 u_int32_t s1 = adler & 0xffff;
1661 u_int32_t s2 = (adler >> 16) & 0xffff;
1662 int n;
1663
1664 for (n = 0; n < len; n++, buf++) {
1665 /* s1 = (s1 + buf[n]) % BASE */
1666 /* first we add */
1667 s1 = (s1 + *buf);
1668 /*
1669 * now if we need to, we do a mod by subtracting. It seems
1670 * a bit faster since I really will only ever do one subtract
1671 * at the MOST, since buf[n] is a max of 255.
1672 */
1673 if (s1 >= SCTP_ADLER32_BASE) {
1674 s1 -= SCTP_ADLER32_BASE;
1675 }
1676 /* s2 = (s2 + s1) % BASE */
1677 /* first we add */
1678 s2 = (s2 + s1);
1679 /*
1680 * again, it is more efficent (it seems) to subtract since
1681 * the most s2 will ever be is (BASE-1 + BASE-1) in the worse
1682 * case. This would then be (2 * BASE) - 2, which will still
1683 * only do one subtract. On Intel this is much better to do
1684 * this way and avoid the divide. Have not -pg'd on sparc.
1685 */
1686 if (s2 >= SCTP_ADLER32_BASE) {
1687 s2 -= SCTP_ADLER32_BASE;
1688 }
1689 }
1690 /* Return the adler32 of the bytes buf[0..len-1] */
1691 return ((s2 << 16) + s1);
1692}
1693
1694#endif
1695
1696
1697u_int32_t
1698sctp_calculate_len(struct mbuf *m)
1699{
1700 u_int32_t tlen=0;
1701 struct mbuf *at;
1702 at = m;
1703 while (at) {
1704 tlen += at->m_len;
1705 at = at->m_next;
1706 }
1707 return (tlen);
1708}
1709
1710#if defined(SCTP_WITH_NO_CSUM)
1711
1712uint32_t
1713sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1714{
1715 /*
1716 * given a mbuf chain with a packetheader offset by 'offset'
1717 * pointing at a sctphdr (with csum set to 0) go through
1718 * the chain of m_next's and calculate the SCTP checksum.
1719 * This is currently Adler32 but will change to CRC32x
1720 * soon. Also has a side bonus calculate the total length
1721 * of the mbuf chain.
1722 * Note: if offset is greater than the total mbuf length,
1723 * checksum=1, pktlen=0 is returned (ie. no real error code)
1724 */
1725 if (pktlen == NULL)
1726 return (0);
1727 *pktlen = sctp_calculate_len(m);
1728 return (0);
1729}
1730
1731#elif defined(SCTP_USE_INCHKSUM)
1732
1733#include <machine/in_cksum.h>
1734
1735uint32_t
1736sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1737{
1738 /*
1739 * given a mbuf chain with a packetheader offset by 'offset'
1740 * pointing at a sctphdr (with csum set to 0) go through
1741 * the chain of m_next's and calculate the SCTP checksum.
1742 * This is currently Adler32 but will change to CRC32x
1743 * soon. Also has a side bonus calculate the total length
1744 * of the mbuf chain.
1745 * Note: if offset is greater than the total mbuf length,
1746 * checksum=1, pktlen=0 is returned (ie. no real error code)
1747 */
1748 int32_t tlen=0;
1749 struct mbuf *at;
1750 uint32_t the_sum, retsum;
1751
1752 at = m;
1753 while (at) {
1754 tlen += at->m_len;
1755 at = at->m_next;
1756 }
1757 the_sum = (uint32_t)(in_cksum_skip(m, tlen, offset));
1758 if (pktlen != NULL)
1759 *pktlen = (tlen-offset);
1760 retsum = htons(the_sum);
1761 return (the_sum);
1762}
1763
1764#else
1765
1766uint32_t
1767sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
1768{
1769 /*
1770 * given a mbuf chain with a packetheader offset by 'offset'
1771 * pointing at a sctphdr (with csum set to 0) go through
1772 * the chain of m_next's and calculate the SCTP checksum.
1773 * This is currently Adler32 but will change to CRC32x
1774 * soon. Also has a side bonus calculate the total length
1775 * of the mbuf chain.
1776 * Note: if offset is greater than the total mbuf length,
1777 * checksum=1, pktlen=0 is returned (ie. no real error code)
1778 */
1779 int32_t tlen=0;
1780#ifdef SCTP_USE_ADLER32
1781 uint32_t base = 1L;
1782#else
1783 uint32_t base = 0xffffffff;
1784#endif /* SCTP_USE_ADLER32 */
1785 struct mbuf *at;
1786 at = m;
1787 /* find the correct mbuf and offset into mbuf */
1788 while ((at != NULL) && (offset > (uint32_t)at->m_len)) {
1789 offset -= at->m_len; /* update remaining offset left */
1790 at = at->m_next;
1791 }
1792
1793 while (at != NULL) {
1794#ifdef SCTP_USE_ADLER32
1795 base = update_adler32(base, at->m_data + offset,
1796 at->m_len - offset);
1797#else
1798 base = update_crc32(base, at->m_data + offset,
1799 at->m_len - offset);
1800#endif /* SCTP_USE_ADLER32 */
1801 tlen += at->m_len - offset;
1802 /* we only offset once into the first mbuf */
1803 if (offset) {
1804 offset = 0;
1805 }
1806 at = at->m_next;
1807 }
1808 if (pktlen != NULL) {
1809 *pktlen = tlen;
1810 }
1811#ifdef SCTP_USE_ADLER32
1812 /* Adler32 */
1813 base = htonl(base);
1814#else
1815 /* CRC-32c */
1816 base = sctp_csum_finalize(base);
1817#endif
1818 return (base);
1819}
1820
1821
1822#endif
1823
1824void
1825sctp_mtu_size_reset(struct sctp_inpcb *inp,
1826 struct sctp_association *asoc, u_long mtu)
1827{
1828 /*
1829 * Reset the P-MTU size on this association, this involves changing
1830 * the asoc MTU, going through ANY chunk+overhead larger than mtu
1831 * to allow the DF flag to be cleared.
1832 */
1833 struct sctp_tmit_chunk *chk;
1834 struct sctp_stream_out *strm;
1835 unsigned int eff_mtu, ovh;
1836 asoc->smallest_mtu = mtu;
1837 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1838 ovh = SCTP_MIN_OVERHEAD;
1839 } else {
1840 ovh = SCTP_MIN_V4_OVERHEAD;
1841 }
1842 eff_mtu = mtu - ovh;
1843 /* Now mark any chunks that need to let IP fragment */
1844 TAILQ_FOREACH(strm, &asoc->out_wheel, next_spoke) {
1845 TAILQ_FOREACH(chk, &strm->outqueue, sctp_next) {
1846 if (chk->send_size > eff_mtu) {
1847 chk->flags &= SCTP_DONT_FRAGMENT;
1848 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1849 }
1850 }
1851 }
1852 TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
1853 if (chk->send_size > eff_mtu) {
1854 chk->flags &= SCTP_DONT_FRAGMENT;
1855 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1856 }
1857 }
1858 TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
1859 if (chk->send_size > eff_mtu) {
1860 chk->flags &= SCTP_DONT_FRAGMENT;
1861 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
1862 }
1863 }
1864}
1865
1866
1867/*
1868 * given an association and starting time of the current RTT period
1869 * return RTO in number of usecs
1870 * net should point to the current network
1871 */
1872u_int32_t
1873sctp_calculate_rto(struct sctp_tcb *stcb,
1874 struct sctp_association *asoc,
1875 struct sctp_nets *net,
1876 struct timeval *old)
1877{
1878 /*
1879 * given an association and the starting time of the current RTT
1880 * period (in value1/value2) return RTO in number of usecs.
1881 */
1882 int calc_time = 0;
8d60bf8a
EN
1883 unsigned int new_rto = 0;
1884 int first_measure = 0;
1885 struct timeval now;
1886
1887 /************************/
1888 /* 1. calculate new RTT */
1889 /************************/
1890 /* get the current time */
1891 SCTP_GETTIME_TIMEVAL(&now);
1892 /* compute the RTT value */
1893 if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
1894 calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
1895 if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
1896 calc_time += (((u_long)now.tv_usec -
1897 (u_long)old->tv_usec)/1000);
1898 } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
1899 /* Borrow 1,000ms from current calculation */
1900 calc_time -= 1000;
1901 /* Add in the slop over */
1902 calc_time += ((int)now.tv_usec/1000);
1903 /* Add in the pre-second ms's */
1904 calc_time += (((int)1000000 - (int)old->tv_usec)/1000);
1905 }
1906 } else if ((u_long)now.tv_sec == (u_long)old->tv_sec) {
1907 if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
1908 calc_time = ((u_long)now.tv_usec -
1909 (u_long)old->tv_usec)/1000;
1910 } else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
1911 /* impossible .. garbage in nothing out */
1912 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1913 } else {
1914 /* impossible .. garbage in nothing out */
1915 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1916 }
1917 } else {
1918 /* Clock wrapped? */
1919 return (((net->lastsa >> 2) + net->lastsv) >> 1);
1920 }
1921 /***************************/
1922 /* 2. update RTTVAR & SRTT */
1923 /***************************/
1924#if 0
1925 /* if (net->lastsv || net->lastsa) {*/
1926 /* per Section 5.3.1 C3 in SCTP */
1927 /* net->lastsv = (int) *//* RTTVAR */
1928 /* (((double)(1.0 - 0.25) * (double)net->lastsv) +
1929 (double)(0.25 * (double)abs(net->lastsa - calc_time)));
1930 net->lastsa = (int) */ /* SRTT */
1931 /*(((double)(1.0 - 0.125) * (double)net->lastsa) +
1932 (double)(0.125 * (double)calc_time));
1933 } else {
1934 *//* the first RTT calculation, per C2 Section 5.3.1 */
1935 /* net->lastsa = calc_time; *//* SRTT */
1936 /* net->lastsv = calc_time / 2; *//* RTTVAR */
1937 /* }*/
1938 /* if RTTVAR goes to 0 you set to clock grainularity */
1939 /* if (net->lastsv == 0) {
1940 net->lastsv = SCTP_CLOCK_GRANULARITY;
1941 }
1942 new_rto = net->lastsa + 4 * net->lastsv;
1943 */
1944#endif
8d60bf8a
EN
1945 /* this is Van Jacobson's integer version */
1946 if (net->RTO) {
1947 calc_time -= (net->lastsa >> 3);
1948 net->lastsa += calc_time;
1949 if (calc_time < 0) {
1950 calc_time = -calc_time;
1951 }
1952 calc_time -= (net->lastsv >> 2);
1953 net->lastsv += calc_time;
1954 if (net->lastsv == 0) {
1955 net->lastsv = SCTP_CLOCK_GRANULARITY;
1956 }
1957 } else {
1958 /* First RTO measurment */
1959 net->lastsa = calc_time;
1960 net->lastsv = calc_time >> 1;
1961 first_measure = 1;
1962 }
1963 new_rto = ((net->lastsa >> 2) + net->lastsv) >> 1;
1964 if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
1965 (stcb->asoc.sat_network_lockout == 0)) {
1966 stcb->asoc.sat_network = 1;
1967 } else if ((!first_measure) && stcb->asoc.sat_network) {
1968 stcb->asoc.sat_network = 0;
1969 stcb->asoc.sat_network_lockout = 1;
1970 }
1971 /* bound it, per C6/C7 in Section 5.3.1 */
1972 if (new_rto < stcb->asoc.minrto) {
1973 new_rto = stcb->asoc.minrto;
1974 }
1975 if (new_rto > stcb->asoc.maxrto) {
1976 new_rto = stcb->asoc.maxrto;
1977 }
1978 /* we are now returning the RTT Smoothed */
1979 return ((u_int32_t)new_rto);
1980}
1981
1982
1983/*
1984 * return a pointer to a contiguous piece of data from the given
1985 * mbuf chain starting at 'off' for 'len' bytes. If the desired
1986 * piece spans more than one mbuf, a copy is made at 'ptr'.
1987 * caller must ensure that the buffer size is >= 'len'
1988 * returns NULL if there there isn't 'len' bytes in the chain.
1989 */
1990caddr_t
1991sctp_m_getptr(struct mbuf *m, int off, int len, u_int8_t *in_ptr)
1992{
1993 uint32_t count;
1994 uint8_t *ptr;
1995 ptr = in_ptr;
1996 if ((off < 0) || (len <= 0))
1997 return (NULL);
1998
1999 /* find the desired start location */
2000 while ((m != NULL) && (off > 0)) {
2001 if (off < m->m_len)
2002 break;
2003 off -= m->m_len;
2004 m = m->m_next;
2005 }
2006 if (m == NULL)
2007 return (NULL);
2008
2009 /* is the current mbuf large enough (eg. contiguous)? */
2010 if ((m->m_len - off) >= len) {
2011 return (mtod(m, caddr_t) + off);
2012 } else {
2013 /* else, it spans more than one mbuf, so save a temp copy... */
2014 while ((m != NULL) && (len > 0)) {
2015 count = min(m->m_len - off, len);
2016 bcopy(mtod(m, caddr_t) + off, ptr, count);
2017 len -= count;
2018 ptr += count;
2019 off = 0;
2020 m = m->m_next;
2021 }
2022 if ((m == NULL) && (len > 0))
2023 return (NULL);
2024 else
2025 return ((caddr_t)in_ptr);
2026 }
2027}
2028
2029
2030struct sctp_paramhdr *
2031sctp_get_next_param(struct mbuf *m,
2032 int offset,
2033 struct sctp_paramhdr *pull,
2034 int pull_limit)
2035{
2036 /* This just provides a typed signature to Peter's Pull routine */
2037 return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
2038 (u_int8_t *)pull));
2039}
2040
2041
2042int
2043sctp_add_pad_tombuf(struct mbuf *m, int padlen)
2044{
2045 /*
2046 * add padlen bytes of 0 filled padding to the end of the mbuf.
2047 * If padlen is > 3 this routine will fail.
2048 */
2049 u_int8_t *dp;
2050 int i;
2051 if (padlen > 3) {
2052 return (ENOBUFS);
2053 }
2054 if (M_TRAILINGSPACE(m)) {
2055 /*
2056 * The easy way.
2057 * We hope the majority of the time we hit here :)
2058 */
2059 dp = (u_int8_t *)(mtod(m, caddr_t) + m->m_len);
2060 m->m_len += padlen;
2061 } else {
2062 /* Hard way we must grow the mbuf */
2063 struct mbuf *tmp;
19267c6d 2064 MGET(tmp, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2065 if (tmp == NULL) {
2066 /* Out of space GAK! we are in big trouble. */
2067 return (ENOSPC);
2068 }
2069 /* setup and insert in middle */
2070 tmp->m_next = m->m_next;
2071 tmp->m_len = padlen;
2072 m->m_next = tmp;
2073 dp = mtod(tmp, u_int8_t *);
2074 }
2075 /* zero out the pad */
2076 for (i= 0; i < padlen; i++) {
2077 *dp = 0;
2078 dp++;
2079 }
2080 return (0);
2081}
2082
2083int
2084sctp_pad_lastmbuf(struct mbuf *m, int padval)
2085{
2086 /* find the last mbuf in chain and pad it */
2087 struct mbuf *m_at;
2088 m_at = m;
2089 while (m_at) {
2090 if (m_at->m_next == NULL) {
2091 return (sctp_add_pad_tombuf(m_at, padval));
2092 }
2093 m_at = m_at->m_next;
2094 }
2095 return (EFAULT);
2096}
2097
2098static void
2099sctp_notify_assoc_change(u_int32_t event, struct sctp_tcb *stcb,
2100 u_int32_t error)
2101{
2102 struct mbuf *m_notify;
2103 struct sctp_assoc_change *sac;
2104 struct sockaddr *to;
2105 struct sockaddr_in6 sin6, lsa6;
2106
2107 /*
2108 * First if we are are going down dump everything we
2109 * can to the socket rcv queue.
2110 */
2111 if ((event == SCTP_SHUTDOWN_COMP) || (event == SCTP_COMM_LOST)) {
2112 sctp_deliver_data(stcb, &stcb->asoc, NULL, 0);
2113 }
2114
2115 /*
2116 * For TCP model AND UDP connected sockets we will send
2117 * an error up when an ABORT comes in.
2118 */
2119 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2120 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
2121 (event == SCTP_COMM_LOST)) {
2122 stcb->sctp_socket->so_error = ECONNRESET;
2123 /* Wake ANY sleepers */
2124 sowwakeup(stcb->sctp_socket);
2125 sorwakeup(stcb->sctp_socket);
2126 }
2127#if 0
2128 if ((event == SCTP_COMM_UP) &&
2129 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2130 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
2131 soisconnected(stcb->sctp_socket);
2132 }
2133#endif
2134 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
2135 /* event not enabled */
2136 return;
2137 }
19267c6d 2138 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2139 if (m_notify == NULL)
2140 /* no space left */
2141 return;
2142 m_notify->m_len = 0;
2143
2144 sac = mtod(m_notify, struct sctp_assoc_change *);
2145 sac->sac_type = SCTP_ASSOC_CHANGE;
2146 sac->sac_flags = 0;
2147 sac->sac_length = sizeof(struct sctp_assoc_change);
2148 sac->sac_state = event;
2149 sac->sac_error = error;
2150 /* XXX verify these stream counts */
2151 sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
2152 sac->sac_inbound_streams = stcb->asoc.streamincnt;
2153 sac->sac_assoc_id = sctp_get_associd(stcb);
2154
2155 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2156 m_notify->m_pkthdr.len = sizeof(struct sctp_assoc_change);
2157 m_notify->m_pkthdr.rcvif = 0;
2158 m_notify->m_len = sizeof(struct sctp_assoc_change);
2159 m_notify->m_next = NULL;
2160
2161 /* append to socket */
2162 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
2163 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2164 to->sa_family == AF_INET) {
2165 struct sockaddr_in *sin;
2166
2167 sin = (struct sockaddr_in *)to;
2168 bzero(&sin6, sizeof(sin6));
2169 sin6.sin6_family = AF_INET6;
2170 sin6.sin6_len = sizeof(struct sockaddr_in6);
2171 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2172 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2173 sizeof(sin6.sin6_addr.s6_addr16[3]));
2174 sin6.sin6_port = sin->sin_port;
2175 to = (struct sockaddr *)&sin6;
2176 }
2177 /* check and strip embedded scope junk */
2178 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2179 &lsa6);
2180 /*
2181 * We need to always notify comm changes.
2182 * if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2183 * sctp_m_freem(m_notify);
2184 * return;
2185 * }
2186 */
2187 SCTP_TCB_UNLOCK(stcb);
2188 SCTP_INP_WLOCK(stcb->sctp_ep);
2189 SCTP_TCB_LOCK(stcb);
6cef7136 2190 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2191 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
8d60bf8a
EN
2192 to, m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2193 /* not enough room */
2194 sctp_m_freem(m_notify);
2195 SCTP_INP_WUNLOCK(stcb->sctp_ep);
6cef7136 2196 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2197 return;
2198 }
6cef7136 2199 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2200 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2201 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2202 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2203 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2204 }
2205 } else {
2206 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2207 }
2208 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2209 /* Wake up any sleeper */
2210 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2211 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
2212}
2213
2214static void
2215sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
2216 struct sockaddr *sa, uint32_t error)
2217{
2218 struct mbuf *m_notify;
2219 struct sctp_paddr_change *spc;
2220 struct sockaddr *to;
2221 struct sockaddr_in6 sin6, lsa6;
2222
2223 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVPADDREVNT))
2224 /* event not enabled */
2225 return;
2226
19267c6d 2227 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2228 if (m_notify == NULL)
2229 return;
2230 m_notify->m_len = 0;
2231
19267c6d 2232 MCLGET(m_notify, MB_DONTWAIT);
8d60bf8a
EN
2233 if ((m_notify->m_flags & M_EXT) != M_EXT) {
2234 sctp_m_freem(m_notify);
2235 return;
2236 }
2237
2238 spc = mtod(m_notify, struct sctp_paddr_change *);
2239 spc->spc_type = SCTP_PEER_ADDR_CHANGE;
2240 spc->spc_flags = 0;
2241 spc->spc_length = sizeof(struct sctp_paddr_change);
2242 if (sa->sa_family == AF_INET) {
2243 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2244 } else {
2245 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2246 }
2247 spc->spc_state = state;
2248 spc->spc_error = error;
2249 spc->spc_assoc_id = sctp_get_associd(stcb);
2250
2251 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2252 m_notify->m_pkthdr.len = sizeof(struct sctp_paddr_change);
2253 m_notify->m_pkthdr.rcvif = 0;
2254 m_notify->m_len = sizeof(struct sctp_paddr_change);
2255 m_notify->m_next = NULL;
2256
eaa63fc9 2257 to = (struct sockaddr *)
8d60bf8a
EN
2258 &stcb->asoc.primary_destination->ro._l_addr;
2259 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2260 to->sa_family == AF_INET) {
2261 struct sockaddr_in *sin;
2262
2263 sin = (struct sockaddr_in *)to;
2264 bzero(&sin6, sizeof(sin6));
2265 sin6.sin6_family = AF_INET6;
2266 sin6.sin6_len = sizeof(struct sockaddr_in6);
2267 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2268 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2269 sizeof(sin6.sin6_addr.s6_addr16[3]));
2270 sin6.sin6_port = sin->sin_port;
2271 to = (struct sockaddr *)&sin6;
2272 }
2273 /* check and strip embedded scope junk */
2274 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2275 &lsa6);
2276
2277 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2278 sctp_m_freem(m_notify);
2279 return;
2280 }
2281 /* append to socket */
2282 SCTP_TCB_UNLOCK(stcb);
2283 SCTP_INP_WLOCK(stcb->sctp_ep);
2284 SCTP_TCB_LOCK(stcb);
6cef7136 2285 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2286 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
8d60bf8a
EN
2287 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2288 /* not enough room */
2289 sctp_m_freem(m_notify);
2290 SCTP_INP_WUNLOCK(stcb->sctp_ep);
6cef7136 2291 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2292 return;
2293 }
6cef7136 2294 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2295 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2296 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2297 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2298 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2299 }
2300 } else {
2301 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2302 }
2303 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2304 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2305}
2306
2307
2308static void
2309sctp_notify_send_failed(struct sctp_tcb *stcb, u_int32_t error,
2310 struct sctp_tmit_chunk *chk)
2311{
2312 struct mbuf *m_notify;
2313 struct sctp_send_failed *ssf;
2314 struct sockaddr_in6 sin6, lsa6;
2315 struct sockaddr *to;
2316 int length;
2317
2318 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2319 /* event not enabled */
2320 return;
2321
2322 length = sizeof(struct sctp_send_failed) + chk->send_size;
19267c6d 2323 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2324 if (m_notify == NULL)
2325 /* no space left */
2326 return;
2327 m_notify->m_len = 0;
2328 ssf = mtod(m_notify, struct sctp_send_failed *);
2329 ssf->ssf_type = SCTP_SEND_FAILED;
2330 if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
2331 ssf->ssf_flags = SCTP_DATA_UNSENT;
2332 else
2333 ssf->ssf_flags = SCTP_DATA_SENT;
2334 ssf->ssf_length = length;
2335 ssf->ssf_error = error;
2336 /* not exactly what the user sent in, but should be close :) */
2337 ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
2338 ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
2339 ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
2340 ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
2341 ssf->ssf_info.sinfo_context = chk->rec.data.context;
2342 ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
2343 ssf->ssf_assoc_id = sctp_get_associd(stcb);
2344 m_notify->m_next = chk->data;
2345 if (m_notify->m_next == NULL)
2346 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2347 else {
2348 struct mbuf *m;
2349 m_notify->m_flags |= M_NOTIFICATION;
2350 m = m_notify;
2351 while (m->m_next != NULL)
2352 m = m->m_next;
2353 m->m_flags |= M_EOR;
2354 }
2355 m_notify->m_pkthdr.len = length;
2356 m_notify->m_pkthdr.rcvif = 0;
2357 m_notify->m_len = sizeof(struct sctp_send_failed);
2358
2359 /* Steal off the mbuf */
2360 chk->data = NULL;
eaa63fc9 2361 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
8d60bf8a
EN
2362 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2363 to->sa_family == AF_INET) {
2364 struct sockaddr_in *sin;
2365
2366 sin = (struct sockaddr_in *)to;
2367 bzero(&sin6, sizeof(sin6));
2368 sin6.sin6_family = AF_INET6;
2369 sin6.sin6_len = sizeof(struct sockaddr_in6);
2370 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2371 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2372 sizeof(sin6.sin6_addr.s6_addr16[3]));
2373 sin6.sin6_port = sin->sin_port;
2374 to = (struct sockaddr *)&sin6;
2375 }
2376 /* check and strip embedded scope junk */
2377 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2378 &lsa6);
2379
2380 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2381 sctp_m_freem(m_notify);
2382 return;
2383 }
2384
2385 /* append to socket */
2386 SCTP_TCB_UNLOCK(stcb);
2387 SCTP_INP_WLOCK(stcb->sctp_ep);
2388 SCTP_TCB_LOCK(stcb);
6cef7136 2389 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2390 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
8d60bf8a
EN
2391 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2392 /* not enough room */
2393 sctp_m_freem(m_notify);
6cef7136 2394 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2395 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2396 return;
2397 }
6cef7136 2398 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2399 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2400 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2401 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2402 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2403 }
2404 } else {
2405 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2406 }
2407 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2408 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2409}
2410
2411static void
2412sctp_notify_adaption_layer(struct sctp_tcb *stcb,
2413 u_int32_t error)
2414{
2415 struct mbuf *m_notify;
2416 struct sctp_adaption_event *sai;
2417 struct sockaddr_in6 sin6, lsa6;
2418 struct sockaddr *to;
2419
2420 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ADAPTIONEVNT))
2421 /* event not enabled */
2422 return;
2423
19267c6d 2424 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2425 if (m_notify == NULL)
2426 /* no space left */
2427 return;
2428 m_notify->m_len = 0;
2429 sai = mtod(m_notify, struct sctp_adaption_event *);
2430 sai->sai_type = SCTP_ADAPTION_INDICATION;
2431 sai->sai_flags = 0;
2432 sai->sai_length = sizeof(struct sctp_adaption_event);
2433 sai->sai_adaption_ind = error;
2434 sai->sai_assoc_id = sctp_get_associd(stcb);
2435
2436 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2437 m_notify->m_pkthdr.len = sizeof(struct sctp_adaption_event);
2438 m_notify->m_pkthdr.rcvif = 0;
2439 m_notify->m_len = sizeof(struct sctp_adaption_event);
2440 m_notify->m_next = NULL;
2441
eaa63fc9 2442 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
8d60bf8a
EN
2443 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2444 (to->sa_family == AF_INET)) {
2445 struct sockaddr_in *sin;
2446
2447 sin = (struct sockaddr_in *)to;
2448 bzero(&sin6, sizeof(sin6));
2449 sin6.sin6_family = AF_INET6;
2450 sin6.sin6_len = sizeof(struct sockaddr_in6);
2451 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2452 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2453 sizeof(sin6.sin6_addr.s6_addr16[3]));
2454 sin6.sin6_port = sin->sin_port;
2455 to = (struct sockaddr *)&sin6;
2456 }
2457 /* check and strip embedded scope junk */
2458 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2459 &lsa6);
2460 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2461 sctp_m_freem(m_notify);
2462 return;
2463 }
2464 /* append to socket */
2465 SCTP_TCB_UNLOCK(stcb);
2466 SCTP_INP_WLOCK(stcb->sctp_ep);
2467 SCTP_TCB_LOCK(stcb);
6cef7136 2468 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2469 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
8d60bf8a
EN
2470 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2471 /* not enough room */
2472 sctp_m_freem(m_notify);
6cef7136 2473 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2474 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2475 return;
2476 }
6cef7136 2477 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2478 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2479 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2480 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2481 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2482 }
2483 } else {
2484 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2485 }
2486 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2487 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2488}
2489
2490static void
2491sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
2492 u_int32_t error)
2493{
2494 struct mbuf *m_notify;
2495 struct sctp_pdapi_event *pdapi;
2496 struct sockaddr_in6 sin6, lsa6;
2497 struct sockaddr *to;
2498
2499 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_PDAPIEVNT))
2500 /* event not enabled */
2501 return;
2502
19267c6d 2503 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2504 if (m_notify == NULL)
2505 /* no space left */
2506 return;
2507 m_notify->m_len = 0;
2508 pdapi = mtod(m_notify, struct sctp_pdapi_event *);
2509 pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
2510 pdapi->pdapi_flags = 0;
2511 pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
2512 pdapi->pdapi_indication = error;
2513 pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
2514
2515 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2516 m_notify->m_pkthdr.len = sizeof(struct sctp_pdapi_event);
2517 m_notify->m_pkthdr.rcvif = 0;
2518 m_notify->m_len = sizeof(struct sctp_pdapi_event);
2519 m_notify->m_next = NULL;
2520
eaa63fc9 2521 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
8d60bf8a
EN
2522 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2523 (to->sa_family == AF_INET)) {
2524 struct sockaddr_in *sin;
2525
2526 sin = (struct sockaddr_in *)to;
2527 bzero(&sin6, sizeof(sin6));
2528 sin6.sin6_family = AF_INET6;
2529 sin6.sin6_len = sizeof(struct sockaddr_in6);
2530 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2531 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2532 sizeof(sin6.sin6_addr.s6_addr16[3]));
2533 sin6.sin6_port = sin->sin_port;
2534 to = (struct sockaddr *)&sin6;
2535 }
2536 /* check and strip embedded scope junk */
2537 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2538 &lsa6);
2539 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2540 sctp_m_freem(m_notify);
2541 return;
2542 }
2543 /* append to socket */
2544 SCTP_TCB_UNLOCK(stcb);
2545 SCTP_INP_WLOCK(stcb->sctp_ep);
2546 SCTP_TCB_LOCK(stcb);
6cef7136 2547 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2548 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
8d60bf8a
EN
2549 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2550 /* not enough room */
2551 sctp_m_freem(m_notify);
6cef7136 2552 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2553 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2554 return;
2555 }
6cef7136 2556 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2557 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2558 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2559 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2560 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2561 }
2562 } else {
2563 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2564 }
2565 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2566 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2567}
2568
2569static void
2570sctp_notify_shutdown_event(struct sctp_tcb *stcb)
2571{
2572 struct mbuf *m_notify;
2573 struct sctp_shutdown_event *sse;
2574 struct sockaddr_in6 sin6, lsa6;
2575 struct sockaddr *to;
2576
2577 /*
2578 * For TCP model AND UDP connected sockets we will send
2579 * an error up when an SHUTDOWN completes
2580 */
2581 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2582 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2583 /* mark socket closed for read/write and wakeup! */
2584 socantrcvmore(stcb->sctp_socket);
2585 socantsendmore(stcb->sctp_socket);
2586 }
2587
2588 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2589 /* event not enabled */
2590 return;
2591
19267c6d 2592 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2593 if (m_notify == NULL)
2594 /* no space left */
2595 return;
2596 m_notify->m_len = 0;
2597 sse = mtod(m_notify, struct sctp_shutdown_event *);
2598 sse->sse_type = SCTP_SHUTDOWN_EVENT;
2599 sse->sse_flags = 0;
2600 sse->sse_length = sizeof(struct sctp_shutdown_event);
2601 sse->sse_assoc_id = sctp_get_associd(stcb);
2602
2603 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2604 m_notify->m_pkthdr.len = sizeof(struct sctp_shutdown_event);
2605 m_notify->m_pkthdr.rcvif = 0;
2606 m_notify->m_len = sizeof(struct sctp_shutdown_event);
2607 m_notify->m_next = NULL;
2608
eaa63fc9 2609 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
8d60bf8a
EN
2610 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2611 to->sa_family == AF_INET) {
2612 struct sockaddr_in *sin;
2613
2614 sin = (struct sockaddr_in *)to;
2615 bzero(&sin6, sizeof(sin6));
2616 sin6.sin6_family = AF_INET6;
2617 sin6.sin6_len = sizeof(struct sockaddr_in6);
2618 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2619 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2620 sizeof(sin6.sin6_addr.s6_addr16[3]));
2621 sin6.sin6_port = sin->sin_port;
2622 to = (struct sockaddr *)&sin6;
2623 }
2624 /* check and strip embedded scope junk */
2625 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2626 &lsa6);
2627 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2628 sctp_m_freem(m_notify);
2629 return;
2630 }
2631 /* append to socket */
2632 SCTP_TCB_UNLOCK(stcb);
2633 SCTP_INP_WLOCK(stcb->sctp_ep);
2634 SCTP_TCB_LOCK(stcb);
6cef7136 2635 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2636 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
8d60bf8a
EN
2637 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2638 /* not enough room */
2639 sctp_m_freem(m_notify);
6cef7136 2640 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2641 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2642 return;
2643 }
6cef7136 2644 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2645 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2646 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2647 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2648 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2649 }
2650 } else {
2651 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2652 }
2653 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2654 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2655}
2656
2657static void
2658sctp_notify_stream_reset(struct sctp_tcb *stcb,
2659 int number_entries, uint16_t *list, int flag)
2660{
2661 struct mbuf *m_notify;
2662 struct sctp_stream_reset_event *strreset;
2663 struct sockaddr_in6 sin6, lsa6;
2664 struct sockaddr *to;
2665 int len;
2666
2667 if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2668 /* event not enabled */
2669 return;
2670
19267c6d 2671 MGETHDR(m_notify, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
2672 if (m_notify == NULL)
2673 /* no space left */
2674 return;
2675 m_notify->m_len = 0;
2676 len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
2677 if (len > M_TRAILINGSPACE(m_notify)) {
19267c6d 2678 MCLGET(m_notify, MB_WAIT);
8d60bf8a
EN
2679 }
2680 if (m_notify == NULL)
2681 /* no clusters */
2682 return;
2683
2684 if (len > M_TRAILINGSPACE(m_notify)) {
2685 /* never enough room */
2686 m_freem(m_notify);
2687 return;
2688 }
2689 strreset = mtod(m_notify, struct sctp_stream_reset_event *);
2690 strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
2691 if (number_entries == 0) {
2692 strreset->strreset_flags = flag | SCTP_STRRESET_ALL_STREAMS;
2693 } else {
2694 strreset->strreset_flags = flag | SCTP_STRRESET_STREAM_LIST;
2695 }
2696 strreset->strreset_length = len;
2697 strreset->strreset_assoc_id = sctp_get_associd(stcb);
2698 if (number_entries) {
2699 int i;
2700 for (i=0; i<number_entries; i++) {
2701 strreset->strreset_list[i] = list[i];
2702 }
2703 }
2704 m_notify->m_flags |= M_EOR | M_NOTIFICATION;
2705 m_notify->m_pkthdr.len = len;
2706 m_notify->m_pkthdr.rcvif = 0;
2707 m_notify->m_len = len;
2708 m_notify->m_next = NULL;
2709 if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
2710 /* no space */
2711 sctp_m_freem(m_notify);
2712 return;
2713 }
eaa63fc9 2714 to = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
8d60bf8a
EN
2715 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2716 to->sa_family == AF_INET) {
2717 struct sockaddr_in *sin;
2718
2719 sin = (struct sockaddr_in *)to;
2720 bzero(&sin6, sizeof(sin6));
2721 sin6.sin6_family = AF_INET6;
2722 sin6.sin6_len = sizeof(struct sockaddr_in6);
2723 sin6.sin6_addr.s6_addr16[2] = 0xffff;
2724 bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
2725 sizeof(sin6.sin6_addr.s6_addr16[3]));
2726 sin6.sin6_port = sin->sin_port;
2727 to = (struct sockaddr *)&sin6;
2728 }
2729 /* check and strip embedded scope junk */
2730 to = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)to,
2731 &lsa6);
2732 /* append to socket */
2733 SCTP_TCB_UNLOCK(stcb);
2734 SCTP_INP_WLOCK(stcb->sctp_ep);
2735 SCTP_TCB_LOCK(stcb);
6cef7136 2736 lwkt_gettoken(&stcb->sctp_socket->so_rcv.ssb_token);
6d49aa6f 2737 if (!sctp_sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
8d60bf8a
EN
2738 m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
2739 /* not enough room */
2740 sctp_m_freem(m_notify);
6cef7136 2741 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2742 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2743 return;
2744 }
6cef7136 2745 lwkt_reltoken(&stcb->sctp_socket->so_rcv.ssb_token);
8d60bf8a
EN
2746 if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
2747 ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
2748 if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
2749 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2750 }
2751 } else {
2752 stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
2753 }
2754 SCTP_INP_WUNLOCK(stcb->sctp_ep);
2755 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
2756}
2757
2758
2759void
2760sctp_ulp_notify(u_int32_t notification, struct sctp_tcb *stcb,
2761 u_int32_t error, void *data)
2762{
2763 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2764 /* No notifications up when we are in a no socket state */
2765 return;
2766 }
2767 if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
2768 /* Can't send up to a closed socket any notifications */
2769 return;
2770 }
2771 switch (notification) {
2772 case SCTP_NOTIFY_ASSOC_UP:
2773 sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error);
2774 break;
2775 case SCTP_NOTIFY_ASSOC_DOWN:
2776 sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error);
2777 break;
2778 case SCTP_NOTIFY_INTERFACE_DOWN:
2779 {
2780 struct sctp_nets *net;
2781 net = (struct sctp_nets *)data;
2782 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
2783 (struct sockaddr *)&net->ro._l_addr, error);
2784 break;
2785 }
2786 case SCTP_NOTIFY_INTERFACE_UP:
2787 {
2788 struct sctp_nets *net;
2789 net = (struct sctp_nets *)data;
2790 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
2791 (struct sockaddr *)&net->ro._l_addr, error);
2792 break;
2793 }
2794 case SCTP_NOTIFY_INTERFACE_CONFIRMED:
2795 {
2796 struct sctp_nets *net;
2797 net = (struct sctp_nets *)data;
2798 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
2799 (struct sockaddr *)&net->ro._l_addr, error);
2800 break;
2801 }
2802 case SCTP_NOTIFY_DG_FAIL:
2803 sctp_notify_send_failed(stcb, error,
2804 (struct sctp_tmit_chunk *)data);
2805 break;
2806 case SCTP_NOTIFY_ADAPTION_INDICATION:
2807 /* Here the error is the adaption indication */
2808 sctp_notify_adaption_layer(stcb, error);
2809 break;
2810 case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
2811 sctp_notify_partial_delivery_indication(stcb, error);
2812 break;
2813 case SCTP_NOTIFY_STRDATA_ERR:
2814 break;
2815 case SCTP_NOTIFY_ASSOC_ABORTED:
2816 sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error);
2817 break;
2818 case SCTP_NOTIFY_PEER_OPENED_STREAM:
2819 break;
2820 case SCTP_NOTIFY_STREAM_OPENED_OK:
2821 break;
2822 case SCTP_NOTIFY_ASSOC_RESTART:
2823 sctp_notify_assoc_change(SCTP_RESTART, stcb, error);
2824 break;
2825 case SCTP_NOTIFY_HB_RESP:
2826 break;
2827 case SCTP_NOTIFY_STR_RESET_SEND:
2828 sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_OUTBOUND_STR);
2829 break;
2830 case SCTP_NOTIFY_STR_RESET_RECV:
2831 sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_INBOUND_STR);
2832 break;
2833 case SCTP_NOTIFY_ASCONF_ADD_IP:
2834 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
2835 error);
2836 break;
2837 case SCTP_NOTIFY_ASCONF_DELETE_IP:
2838 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
2839 error);
2840 break;
2841 case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
2842 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
2843 error);
2844 break;
2845 case SCTP_NOTIFY_ASCONF_SUCCESS:
2846 break;
2847 case SCTP_NOTIFY_ASCONF_FAILED:
2848 break;
2849 case SCTP_NOTIFY_PEER_SHUTDOWN:
2850 sctp_notify_shutdown_event(stcb);
2851 break;
2852 default:
2853#ifdef SCTP_DEBUG
2854 if (sctp_debug_on & SCTP_DEBUG_UTIL1) {
a6ec04bc 2855 kprintf("NOTIFY: unknown notification %xh (%u)\n",
8d60bf8a
EN
2856 notification, notification);
2857 }
2858#endif /* SCTP_DEBUG */
2859 break;
2860 } /* end switch */
2861}
2862
2863void
2864sctp_report_all_outbound(struct sctp_tcb *stcb)
2865{
2866 struct sctp_association *asoc;
2867 struct sctp_stream_out *outs;
2868 struct sctp_tmit_chunk *chk;
2869
2870 asoc = &stcb->asoc;
2871
2872 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2873 return;
2874 }
2875 /* now through all the gunk freeing chunks */
2876 TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
2877 /* now clean up any chunks here */
2878 chk = TAILQ_FIRST(&outs->outqueue);
2879 while (chk) {
2880 stcb->asoc.stream_queue_cnt--;
2881 TAILQ_REMOVE(&outs->outqueue, chk, sctp_next);
2882 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2883 SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2884 if (chk->data) {
2885 sctp_m_freem(chk->data);
2886 chk->data = NULL;
2887 }
2888 if (chk->whoTo)
2889 sctp_free_remote_addr(chk->whoTo);
2890 chk->whoTo = NULL;
2891 chk->asoc = NULL;
2892 /* Free the chunk */
2893 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2894 sctppcbinfo.ipi_count_chunk--;
2895 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2896 panic("Chunk count is negative");
2897 }
2898 sctppcbinfo.ipi_gencnt_chunk++;
2899 chk = TAILQ_FIRST(&outs->outqueue);
2900 }
2901 }
2902 /* pending send queue SHOULD be empty */
2903 if (!TAILQ_EMPTY(&asoc->send_queue)) {
2904 chk = TAILQ_FIRST(&asoc->send_queue);
2905 while (chk) {
2906 TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
2907 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2908 if (chk->data) {
2909 sctp_m_freem(chk->data);
2910 chk->data = NULL;
2911 }
2912 if (chk->whoTo)
2913 sctp_free_remote_addr(chk->whoTo);
2914 chk->whoTo = NULL;
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");
2919 }
2920 sctppcbinfo.ipi_gencnt_chunk++;
2921 chk = TAILQ_FIRST(&asoc->send_queue);
2922 }
2923 }
2924 /* sent queue SHOULD be empty */
2925 if (!TAILQ_EMPTY(&asoc->sent_queue)) {
2926 chk = TAILQ_FIRST(&asoc->sent_queue);
2927 while (chk) {
2928 TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
2929 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2930 SCTP_NOTIFY_DATAGRAM_SENT, chk);
2931 if (chk->data) {
2932 sctp_m_freem(chk->data);
2933 chk->data = NULL;
2934 }
2935 if (chk->whoTo)
2936 sctp_free_remote_addr(chk->whoTo);
2937 chk->whoTo = NULL;
2938 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2939 sctppcbinfo.ipi_count_chunk--;
2940 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2941 panic("Chunk count is negative");
2942 }
2943 sctppcbinfo.ipi_gencnt_chunk++;
2944 chk = TAILQ_FIRST(&asoc->sent_queue);
2945 }
2946 }
2947}
2948
2949void
2950sctp_abort_notification(struct sctp_tcb *stcb, int error)
2951{
2952
2953 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2954 return;
2955 }
2956 /* Tell them we lost the asoc */
2957 sctp_report_all_outbound(stcb);
2958 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL);
2959}
2960
2961void
2962sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2963 struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *op_err)
2964{
2965 u_int32_t vtag;
2966
2967 vtag = 0;
2968 if (stcb != NULL) {
2969 /* We have a TCB to abort, send notification too */
2970 vtag = stcb->asoc.peer_vtag;
2971 sctp_abort_notification(stcb, 0);
2972 }
2973 sctp_send_abort(m, iphlen, sh, vtag, op_err);
2974 if (stcb != NULL) {
2975 /* Ok, now lets free it */
2976 sctp_free_assoc(inp, stcb);
2977 } else {
2978 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2979 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2980 sctp_inpcb_free(inp, 1);
2981 }
2982 }
2983 }
2984}
2985
2986void
2987sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2988 int error, struct mbuf *op_err)
2989{
8d60bf8a
EN
2990 if (stcb == NULL) {
2991 /* Got to have a TCB */
2992 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2993 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2994 sctp_inpcb_free(inp, 1);
2995 }
2996 }
2997 return;
2998 }
8d60bf8a
EN
2999 /* notify the ulp */
3000 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
3001 sctp_abort_notification(stcb, error);
3002 /* notify the peer */
3003 sctp_send_abort_tcb(stcb, op_err);
3004 /* now free the asoc */
3005 sctp_free_assoc(inp, stcb);
3006}
3007
3008void
3009sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
3010 struct sctp_inpcb *inp, struct mbuf *op_err)
3011{
3012 struct sctp_chunkhdr *ch, chunk_buf;
3013 unsigned int chk_length;
3014
3015 /* Generate a TO address for future reference */
3016 if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
3017 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
3018 sctp_inpcb_free(inp, 1);
3019 }
3020 }
3021 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3022 sizeof(*ch), (u_int8_t *)&chunk_buf);
3023 while (ch != NULL) {
3024 chk_length = ntohs(ch->chunk_length);
3025 if (chk_length < sizeof(*ch)) {
3026 /* break to abort land */
3027 break;
3028 }
3029 switch (ch->chunk_type) {
3030 case SCTP_PACKET_DROPPED:
3031 /* we don't respond to pkt-dropped */
3032 return;
3033 case SCTP_ABORT_ASSOCIATION:
3034 /* we don't respond with an ABORT to an ABORT */
3035 return;
3036 case SCTP_SHUTDOWN_COMPLETE:
3037 /*
3038 * we ignore it since we are not waiting for it
3039 * and peer is gone
3040 */
3041 return;
3042 case SCTP_SHUTDOWN_ACK:
3043 sctp_send_shutdown_complete2(m, iphlen, sh);
3044 return;
3045 default:
3046 break;
3047 }
3048 offset += SCTP_SIZE32(chk_length);
3049 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3050 sizeof(*ch), (u_int8_t *)&chunk_buf);
3051 }
3052 sctp_send_abort(m, iphlen, sh, 0, op_err);
3053}
3054
3055/*
3056 * check the inbound datagram to make sure there is not an abort
3057 * inside it, if there is return 1, else return 0.
3058 */
3059int
3060sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, int *vtagfill)
3061{
3062 struct sctp_chunkhdr *ch;
3063 struct sctp_init_chunk *init_chk, chunk_buf;
3064 int offset;
3065 unsigned int chk_length;
3066
3067 offset = iphlen + sizeof(struct sctphdr);
3068 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
3069 (u_int8_t *)&chunk_buf);
3070 while (ch != NULL) {
3071 chk_length = ntohs(ch->chunk_length);
3072 if (chk_length < sizeof(*ch)) {
3073 /* packet is probably corrupt */
3074 break;
3075 }
3076 /* we seem to be ok, is it an abort? */
3077 if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
3078 /* yep, tell them */
3079 return (1);
3080 }
3081 if (ch->chunk_type == SCTP_INITIATION) {
3082 /* need to update the Vtag */
3083 init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
3084 offset, sizeof(*init_chk), (u_int8_t *)&chunk_buf);
3085 if (init_chk != NULL) {
3086 *vtagfill = ntohl(init_chk->init.initiate_tag);
3087 }
3088 }
3089 /* Nope, move to the next chunk */
3090 offset += SCTP_SIZE32(chk_length);
3091 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
3092 sizeof(*ch), (u_int8_t *)&chunk_buf);
3093 }
3094 return (0);
3095}
3096
3097/*
3098 * currently (2/02), ifa_addr embeds scope_id's and don't
3099 * have sin6_scope_id set (i.e. it's 0)
3100 * so, create this function to compare link local scopes
3101 */
3102uint32_t
3103sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
3104{
3105 struct sockaddr_in6 a, b;
3106
3107 /* save copies */
3108 a = *addr1;
3109 b = *addr2;
3110
3111 if (a.sin6_scope_id == 0)
3112 if (in6_recoverscope(&a, &a.sin6_addr, NULL)) {
3113 /* can't get scope, so can't match */
3114 return (0);
3115 }
3116 if (b.sin6_scope_id == 0)
3117 if (in6_recoverscope(&b, &b.sin6_addr, NULL)) {
3118 /* can't get scope, so can't match */
3119 return (0);
3120 }
3121 if (a.sin6_scope_id != b.sin6_scope_id)
3122 return (0);
3123
3124 return (1);
3125}
3126
3127/*
3128 * returns a sockaddr_in6 with embedded scope recovered and removed
3129 */
3130struct sockaddr_in6 *
3131sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
3132{
3133
3134 /* check and strip embedded scope junk */
3135 if (addr->sin6_family == AF_INET6) {
3136 if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
3137 if (addr->sin6_scope_id == 0) {
3138 *store = *addr;
3139 if (!in6_recoverscope(store, &store->sin6_addr,
3140 NULL)) {
3141 /* use the recovered scope */
3142 addr = store;
3143 }
3144 /* else, return the original "to" addr */
3145 }
3146 }
3147 }
3148 return (addr);
3149}
3150
3151/*
3152 * are the two addresses the same? currently a "scopeless" check
3153 * returns: 1 if same, 0 if not
3154 */
3155int
3156sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
3157{
3158
3159 /* must be valid */
3160 if (sa1 == NULL || sa2 == NULL)
3161 return (0);
3162
3163 /* must be the same family */
3164 if (sa1->sa_family != sa2->sa_family)
3165 return (0);
3166
3167 if (sa1->sa_family == AF_INET6) {
3168 /* IPv6 addresses */
3169 struct sockaddr_in6 *sin6_1, *sin6_2;
3170
3171 sin6_1 = (struct sockaddr_in6 *)sa1;
3172 sin6_2 = (struct sockaddr_in6 *)sa2;
3173 return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr,
3174 &sin6_2->sin6_addr));
3175 } else if (sa1->sa_family == AF_INET) {
3176 /* IPv4 addresses */
3177 struct sockaddr_in *sin_1, *sin_2;
3178
3179 sin_1 = (struct sockaddr_in *)sa1;
3180 sin_2 = (struct sockaddr_in *)sa2;
3181 return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
3182 } else {
3183 /* we don't do these... */
3184 return (0);
3185 }
3186}
3187
3188void
3189sctp_print_address(struct sockaddr *sa)
3190{
3191
3192 if (sa->sa_family == AF_INET6) {
3193 struct sockaddr_in6 *sin6;
3194 sin6 = (struct sockaddr_in6 *)sa;
a6ec04bc 3195 kprintf("IPv6 address: %s:%d scope:%u\n",
8d60bf8a
EN
3196 ip6_sprintf(&sin6->sin6_addr), ntohs(sin6->sin6_port),
3197 sin6->sin6_scope_id);
3198 } else if (sa->sa_family == AF_INET) {
3199 struct sockaddr_in *sin;
3200 sin = (struct sockaddr_in *)sa;
a6ec04bc 3201 kprintf("IPv4 address: %s:%d\n", inet_ntoa(sin->sin_addr),
8d60bf8a
EN
3202 ntohs(sin->sin_port));
3203 } else {
a6ec04bc 3204 kprintf("?\n");
8d60bf8a
EN
3205 }
3206}
3207
3208void
3209sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
3210{
3211 if (iph->ip_v == IPVERSION) {
3212 struct sockaddr_in lsa, fsa;
3213
3214 bzero(&lsa, sizeof(lsa));
3215 lsa.sin_len = sizeof(lsa);
3216 lsa.sin_family = AF_INET;
3217 lsa.sin_addr = iph->ip_src;
3218 lsa.sin_port = sh->src_port;
3219 bzero(&fsa, sizeof(fsa));
3220 fsa.sin_len = sizeof(fsa);
3221 fsa.sin_family = AF_INET;
3222 fsa.sin_addr = iph->ip_dst;
3223 fsa.sin_port = sh->dest_port;
a6ec04bc 3224 kprintf("src: ");
8d60bf8a 3225 sctp_print_address((struct sockaddr *)&lsa);
a6ec04bc 3226 kprintf("dest: ");
8d60bf8a
EN
3227 sctp_print_address((struct sockaddr *)&fsa);
3228 } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
3229 struct ip6_hdr *ip6;
3230 struct sockaddr_in6 lsa6, fsa6;
3231
3232 ip6 = (struct ip6_hdr *)iph;
3233 bzero(&lsa6, sizeof(lsa6));
3234 lsa6.sin6_len = sizeof(lsa6);
3235 lsa6.sin6_family = AF_INET6;
3236 lsa6.sin6_addr = ip6->ip6_src;
3237 lsa6.sin6_port = sh->src_port;
3238 bzero(&fsa6, sizeof(fsa6));
3239 fsa6.sin6_len = sizeof(fsa6);
3240 fsa6.sin6_family = AF_INET6;
3241 fsa6.sin6_addr = ip6->ip6_dst;
3242 fsa6.sin6_port = sh->dest_port;
a6ec04bc 3243 kprintf("src: ");
8d60bf8a 3244 sctp_print_address((struct sockaddr *)&lsa6);
a6ec04bc 3245 kprintf("dest: ");
8d60bf8a
EN
3246 sctp_print_address((struct sockaddr *)&fsa6);
3247 }
3248}
3249
3250#if defined(__FreeBSD__) || defined(__APPLE__)
3251
3252/* cloned from uipc_socket.c */
3253
3254#define SCTP_SBLINKRECORD(sb, m0) do { \
3255 if ((sb)->sb_lastrecord != NULL) \
3256 (sb)->sb_lastrecord->m_nextpkt = (m0); \
3257 else \
3258 (sb)->sb_mb = (m0); \
3259 (sb)->sb_lastrecord = (m0); \
3260} while (/*CONSTCOND*/0)
3261#endif
3262
3263
3264int
6d49aa6f 3265sctp_sbappendaddr_nocheck(struct signalsockbuf *ssb, struct sockaddr *asa, struct mbuf *m0,
f3f70f0d
SW
3266 struct mbuf *control, u_int32_t tag,
3267 struct sctp_inpcb *inp)
8d60bf8a 3268{
633abfbf 3269 struct mbuf *m, *n;
8d60bf8a
EN
3270 int cnt=0;
3271
3272 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
6d49aa6f 3273 panic("sctp_sbappendaddr_nocheck");
8d60bf8a
EN
3274
3275 for (n = control; n; n = n->m_next) {
3276 if (n->m_next == 0) /* get pointer to last control buf */
3277 break;
3278 }
3279 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3280 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
9a3fee57
MD
3281 uint32_t len = asa->sa_len; /* workaround GCC stupidity */
3282 if (len > MHLEN)
8d60bf8a
EN
3283 return (0);
3284 try_again:
19267c6d 3285 MGETHDR(m, MB_DONTWAIT, MT_SONAME);
4090d6ff 3286 if (m == NULL)
8d60bf8a
EN
3287 return (0);
3288 m->m_len = 0;
3289 /* safety */
3290 if (m == m0) {
a6ec04bc 3291 kprintf("Duplicate mbuf allocated %p in and mget returned %p?\n",
8d60bf8a
EN
3292 m0, m);
3293 if (cnt) {
3294 panic("more than once");
3295 }
3296 cnt++;
3297 goto try_again;
3298 }
3299 m->m_len = asa->sa_len;
3300 bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
3301 }
3302 else {
3303 m = NULL;
3304 }
3305 if (n)
3306 n->m_next = m0; /* concatenate data to control */
3307 else
3308 control = m0;
3309 if (m)
3310 m->m_next = control;
3311 else
3312 m = control;
3313 m->m_pkthdr.csum_data = (int)tag;
3314
6d49aa6f 3315 SOCKBUF_LOCK(ssb);
8d60bf8a 3316 for (n = m; n; n = n->m_next)
6d49aa6f 3317 sballoc(&ssb->sb, n);
6d49aa6f 3318 if (ssb->ssb_mb == NULL) {
8d60bf8a 3319 inp->sctp_vtag_first = tag;
8d60bf8a 3320 }
6d49aa6f 3321 if ((n = ssb->ssb_mb) != NULL) {
8d60bf8a
EN
3322 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3323 inp->sb_last_mpkt = NULL;
3324 }
3325 if (inp->sb_last_mpkt)
3326 inp->sb_last_mpkt->m_nextpkt = m;
3327 else {
3328 while (n->m_nextpkt) {
3329 n = n->m_nextpkt;
3330 }
3331 n->m_nextpkt = m;
3332 }
3333 inp->sb_last_mpkt = m;
3334 } else {
6d49aa6f 3335 inp->sb_last_mpkt = ssb->ssb_mb = m;
8d60bf8a
EN
3336 inp->sctp_vtag_first = tag;
3337 }
6d49aa6f 3338 SOCKBUF_UNLOCK(ssb);
8d60bf8a 3339 return (1);
8d60bf8a
EN
3340}
3341
3342/*************HOLD THIS COMMENT FOR PATCH FILE OF
3343 *************ALTERNATE ROUTING CODE
3344 */
3345
3346/*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
3347 *************ALTERNATE ROUTING CODE
3348 */
3349
3350struct mbuf *
3351sctp_generate_invmanparam(int err)
3352{
3353 /* Return a MBUF with a invalid mandatory parameter */
3354 struct mbuf *m;
3355
19267c6d 3356 MGET(m, MB_DONTWAIT, MT_DATA);
8d60bf8a
EN
3357 if (m) {
3358 struct sctp_paramhdr *ph;
3359 m->m_len = sizeof(struct sctp_paramhdr);
3360 ph = mtod(m, struct sctp_paramhdr *);
3361 ph->param_length = htons(sizeof(struct sctp_paramhdr));
3362 ph->param_type = htons(err);
3363 }
3364 return (m);
3365}
3366
3367static int
3368sctp_should_be_moved(struct mbuf *this, struct sctp_association *asoc)
3369{
3370 struct mbuf *m;
3371 /*
3372 * given a mbuf chain, look through it finding
3373 * the M_PKTHDR and return 1 if it belongs to
3374 * the association given. We tell this by
3375 * a kludge where we stuff the my_vtag of the asoc
3376 * into the m->m_pkthdr.csum_data/csum field.
3377 */
3378 m = this;
3379 while (m) {
3380 if (m->m_flags & M_PKTHDR) {
3381 /* check it */
3382#if defined(__OpenBSD__)
3383 if ((u_int32_t)m->m_pkthdr.csum == asoc->my_vtag)
3384#else
3385 if ((u_int32_t)m->m_pkthdr.csum_data == asoc->my_vtag)
3386#endif
3387 {
3388 /* Yep */
3389 return (1);
3390 }
3391 }
3392 m = m->m_next;
3393 }
3394 return (0);
3395}
3396
3397u_int32_t
3398sctp_get_first_vtag_from_sb(struct socket *so)
3399{
3400 struct mbuf *this, *at;
3401 u_int32_t retval;
3402
3403 retval = 0;
6cef7136 3404 lwkt_gettoken(&so->so_rcv.ssb_token);
6d49aa6f 3405 if (so->so_rcv.ssb_mb) {
8d60bf8a 3406 /* grubbing time */
6d49aa6f 3407 this = so->so_rcv.ssb_mb;
8d60bf8a
EN
3408 while (this) {
3409 at = this;
3410 /* get to the m_pkthdr */
3411 while (at) {
3412 if (at->m_flags & M_PKTHDR)
3413 break;
3414 else {
3415 at = at->m_next;
3416 }
3417 }
3418 /* now do we have a m_pkthdr */
3419 if (at && (at->m_flags & M_PKTHDR)) {
3420 /* check it */
3421#if defined(__OpenBSD__)
3422 if ((u_int32_t)at->m_pkthdr.csum != 0)
3423#else
3424 if ((u_int32_t)at->m_pkthdr.csum_data != 0)
3425#endif
3426 {
3427 /* its the one */
3428#if defined(__OpenBSD__)
3429 retval = (u_int32_t)at->m_pkthdr.csum;
3430#else
3431 retval =
3432 (u_int32_t)at->m_pkthdr.csum_data;
3433#endif
3434 break;
3435 }
3436 }
3437 this = this->m_nextpkt;
3438 }
3439
3440 }
6cef7136 3441 lwkt_reltoken(&so->so_rcv.ssb_token);
8d60bf8a
EN
3442 return (retval);
3443
3444}
3445void
3446sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
3447 struct socket *new, struct sctp_tcb *stcb)
3448{
3449 struct mbuf **put, **take, *next, *this;
6d49aa6f 3450 struct signalsockbuf *old_sb, *new_sb;
8d60bf8a
EN
3451 struct sctp_association *asoc;
3452 int moved_top = 0;
3453
3454 asoc = &stcb->asoc;
3455 old_sb = &old->so_rcv;
3456 new_sb = &new->so_rcv;
6d49aa6f 3457 if (old_sb->ssb_mb == NULL) {
8d60bf8a
EN
3458 /* Nothing to move */
3459 return;
3460 }
3461 SOCKBUF_LOCK(old_sb);
3462 SOCKBUF_LOCK(new_sb);
6cef7136
MD
3463 lwkt_gettoken(&old_sb->ssb_token);
3464 lwkt_gettoken(&new_sb->ssb_token);
8d60bf8a
EN
3465
3466 if (inp->sctp_vtag_first == asoc->my_vtag) {
3467 /* First one must be moved */
3468 struct mbuf *mm;
6d49aa6f 3469 for (mm = old_sb->ssb_mb; mm; mm = mm->m_next) {
8d60bf8a
EN
3470 /*
3471 * Go down the chain and fix
3472 * the space allocation of the
3473 * two sockets.
3474 */
6d49aa6f
MD
3475 sbfree(&old_sb->sb, mm);
3476 sballoc(&new_sb->sb, mm);
8d60bf8a 3477 }
6d49aa6f
MD
3478 new_sb->ssb_mb = old_sb->ssb_mb;
3479 old_sb->ssb_mb = new_sb->ssb_mb->m_nextpkt;
3480 new_sb->ssb_mb->m_nextpkt = NULL;
3481 put = &new_sb->ssb_mb->m_nextpkt;
8d60bf8a
EN
3482 moved_top = 1;
3483 } else {
6d49aa6f 3484 put = &new_sb->ssb_mb;
8d60bf8a
EN
3485 }
3486
6d49aa6f
MD
3487 take = &old_sb->ssb_mb;
3488 next = old_sb->ssb_mb;
8d60bf8a
EN
3489 while (next) {
3490 this = next;
3491 /* postion for next one */
3492 next = this->m_nextpkt;
3493 /* check the tag of this packet */
3494 if (sctp_should_be_moved(this, asoc)) {
3495 /* yes this needs to be moved */
3496 struct mbuf *mm;
3497 *take = this->m_nextpkt;
3498 this->m_nextpkt = NULL;
3499 *put = this;
3500 for (mm = this; mm; mm = mm->m_next) {
3501 /*
3502 * Go down the chain and fix
3503 * the space allocation of the
3504 * two sockets.
3505 */
6d49aa6f
MD
3506 sbfree(&old_sb->sb, mm);
3507 sballoc(&new_sb->sb, mm);
8d60bf8a
EN
3508 }
3509 put = &this->m_nextpkt;
3510
3511 } else {
3512 /* no advance our take point. */
3513 take = &this->m_nextpkt;
3514 }
3515 }
3516 if (moved_top) {
3517 /*
3518 * Ok so now we must re-postion vtag_first to
3519 * match the new first one since we moved the
3520 * mbuf at the top.
3521 */
3522 inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
3523 }
6cef7136
MD
3524 lwkt_reltoken(&new_sb->ssb_token);
3525 lwkt_reltoken(&old_sb->ssb_token);
8d60bf8a
EN
3526 SOCKBUF_UNLOCK(old_sb);
3527 SOCKBUF_UNLOCK(new_sb);
3528}
3529
3530void
3531sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
3532 struct sctp_tmit_chunk *tp1)
3533{
3534 if (tp1->data == NULL) {
3535 return;
3536 }
3537#ifdef SCTP_MBCNT_LOGGING
3538 sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
3539 asoc->total_output_queue_size,
3540 tp1->book_size,
3541 asoc->total_output_mbuf_queue_size,
3542 tp1->mbcnt);
3543#endif
3544 if (asoc->total_output_queue_size >= tp1->book_size) {
3545 asoc->total_output_queue_size -= tp1->book_size;
3546 } else {
3547 asoc->total_output_queue_size = 0;
3548 }
3549
3550 /* Now free the mbuf */
3551 if (asoc->total_output_mbuf_queue_size >= tp1->mbcnt) {
3552 asoc->total_output_mbuf_queue_size -= tp1->mbcnt;
3553 } else {
3554 asoc->total_output_mbuf_queue_size = 0;
3555 }
3556 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3557 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6d49aa6f
MD
3558 if (stcb->sctp_socket->so_snd.ssb_cc >= tp1->book_size) {
3559 stcb->sctp_socket->so_snd.ssb_cc -= tp1->book_size;
8d60bf8a 3560 } else {
6d49aa6f 3561 stcb->sctp_socket->so_snd.ssb_cc = 0;
8d60bf8a
EN
3562
3563 }
6d49aa6f
MD
3564 if (stcb->sctp_socket->so_snd.ssb_mbcnt >= tp1->mbcnt) {
3565 stcb->sctp_socket->so_snd.ssb_mbcnt -= tp1->mbcnt;
8d60bf8a 3566 } else {
6d49aa6f 3567 stcb->sctp_socket->so_snd.ssb_mbcnt = 0;
8d60bf8a
EN
3568 }
3569 }
3570}
3571
3572int
3573sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
3574 int reason, struct sctpchunk_listhead *queue)
3575{
3576 int ret_sz = 0;
3577 int notdone;
3578 uint8_t foundeom = 0;
3579
3580 do {
3581 ret_sz += tp1->book_size;
3582 tp1->sent = SCTP_FORWARD_TSN_SKIP;
3583 if (tp1->data) {
3584 sctp_free_bufspace(stcb, &stcb->asoc, tp1);
3585 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1);
3586 sctp_m_freem(tp1->data);
3587 tp1->data = NULL;
3588 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
3589 }
3590 if (tp1->flags & SCTP_PR_SCTP_BUFFER) {
3591 stcb->asoc.sent_queue_cnt_removeable--;
3592 }
3593 if (queue == &stcb->asoc.send_queue) {
3594 TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
3595 /* on to the sent queue */
3596 TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
3597 sctp_next);
3598 stcb->asoc.sent_queue_cnt++;
3599 }
3600 if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
3601 SCTP_DATA_NOT_FRAG) {
3602 /* not frag'ed we ae done */
3603 notdone = 0;
3604 foundeom = 1;
3605 } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
3606 /* end of frag, we are done */
3607 notdone = 0;
3608 foundeom = 1;
3609 } else {
3610 /* Its a begin or middle piece, we must mark all of it */
3611 notdone = 1;
3612 tp1 = TAILQ_NEXT(tp1, sctp_next);
3613 }
3614 } while (tp1 && notdone);
3615 if ((foundeom == 0) && (queue == &stcb->asoc.sent_queue)) {
3616 /*
3617 * The multi-part message was scattered
3618 * across the send and sent queue.
3619 */
3620 tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
3621 /*
3622 * recurse throught the send_queue too, starting at the
3623 * beginning.
3624 */
3625 if (tp1) {
3626 ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
3627 &stcb->asoc.send_queue);
3628 } else {
a6ec04bc 3629 kprintf("hmm, nothing on the send queue and no EOM?\n");
8d60bf8a
EN
3630 }
3631 }
3632 return (ret_sz);
3633}
3634
3635/*
3636 * checks to see if the given address, sa, is one that is currently
3637 * known by the kernel
3638 * note: can't distinguish the same address on multiple interfaces and
3639 * doesn't handle multiple addresses with different zone/scope id's
3640 * note: ifa_ifwithaddr() compares the entire sockaddr struct
3641 */
3642struct ifaddr *
3643sctp_find_ifa_by_addr(struct sockaddr *sa)
3644{
3645 struct ifnet *ifn;
8d60bf8a
EN
3646
3647 /* go through all our known interfaces */
3648 TAILQ_FOREACH(ifn, &ifnet, if_list) {
b2632176
SZ
3649 struct ifaddr_container *ifac;
3650
8d60bf8a 3651 /* go through each interface addresses */
b2632176
SZ
3652 TAILQ_FOREACH(ifac, &ifn->if_addrheads[mycpuid], ifa_link) {
3653 struct ifaddr *ifa = ifac->ifa;
3654
8d60bf8a
EN
3655 /* correct family? */
3656 if (ifa->ifa_addr->sa_family != sa->sa_family)
3657 continue;
3658
3659#ifdef INET6
3660 if (ifa->ifa_addr->sa_family == AF_INET6) {
3661 /* IPv6 address */
3662 struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
3663 sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
3664 if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
3665 /* create a copy and clear scope */
3666 memcpy(&sin6_tmp, sin1,
3667 sizeof(struct sockaddr_in6));
3668 sin1 = &sin6_tmp;
3669 in6_clearscope(&sin1->sin6_addr);
3670 }
3671 sin2 = (struct sockaddr_in6 *)sa;
3672 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
3673 sizeof(struct in6_addr)) == 0) {
3674 /* found it */
3675 return (ifa);
3676 }
3677 } else
3678#endif
3679 if (ifa->ifa_addr->sa_family == AF_INET) {
3680 /* IPv4 address */
3681 struct sockaddr_in *sin1, *sin2;
3682 sin1 = (struct sockaddr_in *)ifa->ifa_addr;
3683 sin2 = (struct sockaddr_in *)sa;
3684 if (sin1->sin_addr.s_addr ==
3685 sin2->sin_addr.s_addr) {
3686 /* found it */
3687 return (ifa);
3688 }
3689 }
3690 /* else, not AF_INET or AF_INET6, so skip */
3691 } /* end foreach ifa */
3692 } /* end foreach ifn */
3693 /* not found! */
3694 return (NULL);
3695}
3696
3697
3698#ifdef __APPLE__
3699/*
3700 * here we hack in a fix for Apple's m_copym for the case where the first mbuf
3701 * in the chain is a M_PKTHDR and the length is zero
3702 */
3703static void
3704sctp_pkthdr_fix(struct mbuf *m)
3705{
3706 struct mbuf *m_nxt;
3707
3708 if ((m->m_flags & M_PKTHDR) == 0) {
3709 /* not a PKTHDR */
3710 return;
3711 }
3712
3713 if (m->m_len != 0) {
3714 /* not a zero length PKTHDR mbuf */
3715 return;
3716 }
3717
3718 /* let's move in a word into the first mbuf... yes, ugly! */
3719 m_nxt = m->m_next;
3720 if (m_nxt == NULL) {
3721 /* umm... not a very useful mbuf chain... */
3722 return;
3723 }
3724 if ((size_t)m_nxt->m_len > sizeof(long)) {
3725 /* move over a long */
3726 bcopy(mtod(m_nxt, caddr_t), mtod(m, caddr_t), sizeof(long));
3727 /* update mbuf data pointers and lengths */
3728 m->m_len += sizeof(long);
3729 m_nxt->m_data += sizeof(long);
3730 m_nxt->m_len -= sizeof(long);
3731 }
3732}
3733
3734inline struct mbuf *
3735sctp_m_copym(struct mbuf *m, int off, int len, int wait)
3736{
3737 sctp_pkthdr_fix(m);
3738 return (m_copym(m, off, len, wait));
3739}
3740#endif /* __APPLE__ */