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