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