1 /* $KAME: sctputil.c,v 1.39 2005/06/16 20:54:06 jinmei Exp $ */
2 /* $NetBSD: sctputil.c,v 1.20 2024/07/05 04:31:54 rin 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.20 2024/07/05 04:31:54 rin 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
sctp_clr_stat_log(void)118 void sctp_clr_stat_log(void)
119 {
120 sctp_cwnd_log_at=0;
121 sctp_cwnd_log_rolled=0;
122 }
123
124 void
sctp_log_strm_del_alt(u_int32_t tsn,u_int16_t sseq,int from)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
sctp_log_map(uint32_t map,uint32_t cum,uint32_t high,int from)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
sctp_log_fr(uint32_t biggest_tsn,uint32_t biggest_new_tsn,uint32_t tsn,int from)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
sctp_log_strm_del(struct sctp_tmit_chunk * chk,struct sctp_tmit_chunk * poschk,int from)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
sctp_log_cwnd(struct sctp_nets * net,int augment,uint8_t from)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
sctp_log_maxburst(struct sctp_nets * net,int error,int burst,uint8_t from)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
sctp_log_rwnd(uint8_t from,u_int32_t peers_rwnd,u_int32_t snd_size,u_int32_t overhead)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
sctp_log_rwnd_set(uint8_t from,u_int32_t peers_rwnd,u_int32_t flight_size,u_int32_t overhead,u_int32_t a_rwndval)254 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
sctp_log_mbcnt(uint8_t from,u_int32_t total_oq,u_int32_t book,u_int32_t total_mbcnt_q,u_int32_t mbcnt)270 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
sctp_log_block(uint8_t from,struct socket * so,struct sctp_association * asoc)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
sctp_fill_stat_log(struct mbuf * m)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
sctp_print_audit_report(void)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
sctp_auditing(int from,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net)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
sctp_audit_log(u_int8_t ev,u_int8_t fd)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
find_next_best_mtu(int totsz)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
sctp_select_initial_TSN(struct sctp_pcb * m)619 sctp_select_initial_TSN(struct sctp_pcb *m)
620 {
621 return cprng_strong32();
622 }
623
sctp_select_a_tag(struct sctp_inpcb * m)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
sctp_init_asoc(struct sctp_inpcb * m,struct sctp_association * asoc,int for_a_init,uint32_t override_tag)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
sctp_expand_mapping_array(struct sctp_association * asoc)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
sctp_timeout_handler(void * t)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
sctp_timer_start(int t_type,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net)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
sctp_timer_stop(int t_type,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net)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
sctp_calculate_len(struct mbuf * m)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
sctp_calculate_sum(struct mbuf * m,int32_t * pktlen,uint32_t offset)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
sctp_mtu_size_reset(struct sctp_inpcb * inp,struct sctp_association * asoc,u_long mtu)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
sctp_calculate_rto(struct sctp_tcb * stcb,struct sctp_association * asoc,struct sctp_nets * net,struct timeval * old)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 *
sctp_m_getptr(struct mbuf * m,int off,int len,u_int8_t * in_ptr)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 *
sctp_get_next_param(struct mbuf * m,int offset,struct sctp_paramhdr * pull,int pull_limit)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
sctp_add_pad_tombuf(struct mbuf * m,int padlen)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
sctp_pad_lastmbuf(struct mbuf * m,int padval)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
sctp_notify_assoc_change(u_int32_t event,struct sctp_tcb * stcb,u_int32_t error)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
sctp_notify_peer_addr_change(struct sctp_tcb * stcb,uint32_t state,const struct sockaddr * sa,uint32_t error)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
sctp_notify_send_failed(struct sctp_tcb * stcb,u_int32_t error,struct sctp_tmit_chunk * chk)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
sctp_notify_adaption_layer(struct sctp_tcb * stcb,u_int32_t error)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
sctp_notify_partial_delivery_indication(struct sctp_tcb * stcb,u_int32_t error)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
sctp_notify_shutdown_event(struct sctp_tcb * stcb)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
sctp_notify_stream_reset(struct sctp_tcb * stcb,int number_entries,uint16_t * list,int flag)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
sctp_ulp_notify(u_int32_t notification,struct sctp_tcb * stcb,u_int32_t error,void * data)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
sctp_report_all_outbound(struct sctp_tcb * stcb)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 sctp_m_freem(chk->data);
2588 chk->data = NULL;
2589 if (chk->whoTo)
2590 sctp_free_remote_addr(chk->whoTo);
2591 chk->whoTo = NULL;
2592 chk->asoc = NULL;
2593 /* Free the chunk */
2594 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2595 sctppcbinfo.ipi_count_chunk--;
2596 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2597 panic("Chunk count is negative");
2598 }
2599 sctppcbinfo.ipi_gencnt_chunk++;
2600 chk = TAILQ_FIRST(&outs->outqueue);
2601 }
2602 }
2603 /* pending send queue SHOULD be empty */
2604 if (!TAILQ_EMPTY(&asoc->send_queue)) {
2605 chk = TAILQ_FIRST(&asoc->send_queue);
2606 while (chk) {
2607 TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
2608 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
2609 sctp_m_freem(chk->data);
2610 chk->data = NULL;
2611 if (chk->whoTo)
2612 sctp_free_remote_addr(chk->whoTo);
2613 chk->whoTo = NULL;
2614 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2615 sctppcbinfo.ipi_count_chunk--;
2616 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2617 panic("Chunk count is negative");
2618 }
2619 sctppcbinfo.ipi_gencnt_chunk++;
2620 chk = TAILQ_FIRST(&asoc->send_queue);
2621 }
2622 }
2623 /* sent queue SHOULD be empty */
2624 if (!TAILQ_EMPTY(&asoc->sent_queue)) {
2625 chk = TAILQ_FIRST(&asoc->sent_queue);
2626 while (chk) {
2627 TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
2628 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
2629 SCTP_NOTIFY_DATAGRAM_SENT, chk);
2630 sctp_m_freem(chk->data);
2631 chk->data = NULL;
2632 if (chk->whoTo)
2633 sctp_free_remote_addr(chk->whoTo);
2634 chk->whoTo = NULL;
2635 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2636 sctppcbinfo.ipi_count_chunk--;
2637 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2638 panic("Chunk count is negative");
2639 }
2640 sctppcbinfo.ipi_gencnt_chunk++;
2641 chk = TAILQ_FIRST(&asoc->sent_queue);
2642 }
2643 }
2644 }
2645
2646 void
sctp_abort_notification(struct sctp_tcb * stcb,int error)2647 sctp_abort_notification(struct sctp_tcb *stcb, int error)
2648 {
2649
2650 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2651 return;
2652 }
2653 /* Tell them we lost the asoc */
2654 sctp_report_all_outbound(stcb);
2655 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL);
2656 }
2657
2658 void
sctp_abort_association(struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct mbuf * m,int iphlen,struct sctphdr * sh,struct mbuf * op_err)2659 sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2660 struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *op_err)
2661 {
2662 u_int32_t vtag;
2663
2664 vtag = 0;
2665 if (stcb != NULL) {
2666 /* We have a TCB to abort, send notification too */
2667 vtag = stcb->asoc.peer_vtag;
2668 sctp_abort_notification(stcb, 0);
2669 }
2670 sctp_send_abort(m, iphlen, sh, vtag, op_err);
2671 if (stcb != NULL) {
2672 /* Ok, now lets free it */
2673 sctp_free_assoc(inp, stcb);
2674 } else {
2675 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2676 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2677 sctp_inpcb_free(inp, 1);
2678 }
2679 }
2680 }
2681 }
2682
2683 void
sctp_abort_an_association(struct sctp_inpcb * inp,struct sctp_tcb * stcb,int error,struct mbuf * op_err)2684 sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2685 int error, struct mbuf *op_err)
2686 {
2687
2688 if (stcb == NULL) {
2689 /* Got to have a TCB */
2690 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2691 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2692 sctp_inpcb_free(inp, 1);
2693 }
2694 }
2695 return;
2696 }
2697 /* notify the ulp */
2698 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
2699 sctp_abort_notification(stcb, error);
2700 /* notify the peer */
2701 sctp_send_abort_tcb(stcb, op_err);
2702 /* now free the asoc */
2703 sctp_free_assoc(inp, stcb);
2704 }
2705
2706 void
sctp_handle_ootb(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_inpcb * inp,struct mbuf * op_err)2707 sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
2708 struct sctp_inpcb *inp, struct mbuf *op_err)
2709 {
2710 struct sctp_chunkhdr *ch, chunk_buf;
2711 unsigned int chk_length;
2712
2713 /* Generate a TO address for future reference */
2714 if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
2715 if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
2716 sctp_inpcb_free(inp, 1);
2717 }
2718 }
2719 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
2720 sizeof(*ch), (u_int8_t *)&chunk_buf);
2721 while (ch != NULL) {
2722 chk_length = ntohs(ch->chunk_length);
2723 if (chk_length < sizeof(*ch)) {
2724 /* break to abort land */
2725 break;
2726 }
2727 switch (ch->chunk_type) {
2728 case SCTP_PACKET_DROPPED:
2729 /* we don't respond to pkt-dropped */
2730 return;
2731 case SCTP_ABORT_ASSOCIATION:
2732 /* we don't respond with an ABORT to an ABORT */
2733 return;
2734 case SCTP_SHUTDOWN_COMPLETE:
2735 /*
2736 * we ignore it since we are not waiting for it
2737 * and peer is gone
2738 */
2739 return;
2740 case SCTP_SHUTDOWN_ACK:
2741 sctp_send_shutdown_complete2(m, iphlen, sh);
2742 return;
2743 default:
2744 break;
2745 }
2746 offset += SCTP_SIZE32(chk_length);
2747 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
2748 sizeof(*ch), (u_int8_t *)&chunk_buf);
2749 }
2750 sctp_send_abort(m, iphlen, sh, 0, op_err);
2751 }
2752
2753 /*
2754 * check the inbound datagram to make sure there is not an abort
2755 * inside it, if there is return 1, else return 0.
2756 */
2757 int
sctp_is_there_an_abort_here(struct mbuf * m,int iphlen,int * vtagfill)2758 sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, int *vtagfill)
2759 {
2760 struct sctp_chunkhdr *ch;
2761 struct sctp_init_chunk *init_chk, chunk_buf;
2762 int offset;
2763 unsigned int chk_length;
2764
2765 offset = iphlen + sizeof(struct sctphdr);
2766 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
2767 (u_int8_t *)&chunk_buf);
2768 while (ch != NULL) {
2769 chk_length = ntohs(ch->chunk_length);
2770 if (chk_length < sizeof(*ch)) {
2771 /* packet is probably corrupt */
2772 break;
2773 }
2774 /* we seem to be ok, is it an abort? */
2775 if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
2776 /* yep, tell them */
2777 return (1);
2778 }
2779 if (ch->chunk_type == SCTP_INITIATION) {
2780 /* need to update the Vtag */
2781 init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
2782 offset, sizeof(*init_chk), (u_int8_t *)&chunk_buf);
2783 if (init_chk != NULL) {
2784 *vtagfill = ntohl(init_chk->init.initiate_tag);
2785 }
2786 }
2787 /* Nope, move to the next chunk */
2788 offset += SCTP_SIZE32(chk_length);
2789 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
2790 sizeof(*ch), (u_int8_t *)&chunk_buf);
2791 }
2792 return (0);
2793 }
2794
2795 /*
2796 * currently (2/02), ifa_addr embeds scope_id's and don't
2797 * have sin6_scope_id set (i.e. it's 0)
2798 * so, create this function to compare link local scopes
2799 */
2800 uint32_t
sctp_is_same_scope(const struct sockaddr_in6 * addr1,const struct sockaddr_in6 * addr2)2801 sctp_is_same_scope(const struct sockaddr_in6 *addr1, const struct sockaddr_in6 *addr2)
2802 {
2803 struct sockaddr_in6 a, b;
2804
2805 /* save copies */
2806 a = *addr1;
2807 b = *addr2;
2808
2809 if (a.sin6_scope_id == 0)
2810 if (sa6_recoverscope(&a)) {
2811 /* can't get scope, so can't match */
2812 return (0);
2813 }
2814 if (b.sin6_scope_id == 0)
2815 if (sa6_recoverscope(&b)) {
2816 /* can't get scope, so can't match */
2817 return (0);
2818 }
2819 if (a.sin6_scope_id != b.sin6_scope_id)
2820 return (0);
2821
2822 return (1);
2823 }
2824
2825 /*
2826 * returns a sockaddr_in6 with embedded scope recovered and removed
2827 */
2828 const struct sockaddr_in6 *
sctp_recover_scope(const struct sockaddr_in6 * addr,struct sockaddr_in6 * store)2829 sctp_recover_scope(const struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
2830 {
2831 const struct sockaddr_in6 *newaddr;
2832
2833 newaddr = addr;
2834 /* check and strip embedded scope junk */
2835 if (addr->sin6_family == AF_INET6) {
2836 if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
2837 if (addr->sin6_scope_id == 0) {
2838 *store = *addr;
2839 if (sa6_recoverscope(store) == 0) {
2840 /* use the recovered scope */
2841 newaddr = store;
2842 }
2843 /* else, return the original "to" addr */
2844 }
2845 }
2846 }
2847 return (newaddr);
2848 }
2849
2850 /*
2851 * are the two addresses the same? currently a "scopeless" check
2852 * returns: 1 if same, 0 if not
2853 */
2854 int
sctp_cmpaddr(const struct sockaddr * sa1,const struct sockaddr * sa2)2855 sctp_cmpaddr(const struct sockaddr *sa1, const struct sockaddr *sa2)
2856 {
2857
2858 /* must be valid */
2859 if (sa1 == NULL || sa2 == NULL)
2860 return (0);
2861
2862 /* must be the same family */
2863 if (sa1->sa_family != sa2->sa_family)
2864 return (0);
2865
2866 if (sa1->sa_family == AF_INET6) {
2867 /* IPv6 addresses */
2868 const struct sockaddr_in6 *sin6_1, *sin6_2;
2869
2870 sin6_1 = (const struct sockaddr_in6 *)sa1;
2871 sin6_2 = (const struct sockaddr_in6 *)sa2;
2872 return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr,
2873 &sin6_2->sin6_addr));
2874 } else if (sa1->sa_family == AF_INET) {
2875 /* IPv4 addresses */
2876 const struct sockaddr_in *sin_1, *sin_2;
2877
2878 sin_1 = (const struct sockaddr_in *)sa1;
2879 sin_2 = (const struct sockaddr_in *)sa2;
2880 return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
2881 } else {
2882 /* we don't do these... */
2883 return (0);
2884 }
2885 }
2886
2887 void
sctp_print_address(const struct sockaddr * sa)2888 sctp_print_address(const struct sockaddr *sa)
2889 {
2890 char ip6buf[INET6_ADDRSTRLEN];
2891
2892 if (sa->sa_family == AF_INET6) {
2893 const struct sockaddr_in6 *sin6;
2894 sin6 = (const struct sockaddr_in6 *)sa;
2895 printf("IPv6 address: %s:%d scope:%u\n",
2896 IN6_PRINT(ip6buf, &sin6->sin6_addr), ntohs(sin6->sin6_port),
2897 sin6->sin6_scope_id);
2898 } else if (sa->sa_family == AF_INET) {
2899 const struct sockaddr_in *sin;
2900 sin = (const struct sockaddr_in *)sa;
2901 printf("IPv4 address: %s:%d\n", inet_ntoa(sin->sin_addr),
2902 ntohs(sin->sin_port));
2903 } else {
2904 printf("?\n");
2905 }
2906 }
2907
2908 void
sctp_print_address_pkt(struct ip * iph,struct sctphdr * sh)2909 sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
2910 {
2911 if (iph->ip_v == IPVERSION) {
2912 struct sockaddr_in lsa, fsa;
2913
2914 memset(&lsa, 0, sizeof(lsa));
2915 lsa.sin_len = sizeof(lsa);
2916 lsa.sin_family = AF_INET;
2917 lsa.sin_addr = iph->ip_src;
2918 lsa.sin_port = sh->src_port;
2919 memset(&fsa, 0, sizeof(fsa));
2920 fsa.sin_len = sizeof(fsa);
2921 fsa.sin_family = AF_INET;
2922 fsa.sin_addr = iph->ip_dst;
2923 fsa.sin_port = sh->dest_port;
2924 printf("src: ");
2925 sctp_print_address((struct sockaddr *)&lsa);
2926 printf("dest: ");
2927 sctp_print_address((struct sockaddr *)&fsa);
2928 } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
2929 struct ip6_hdr *ip6;
2930 struct sockaddr_in6 lsa6, fsa6;
2931
2932 ip6 = (struct ip6_hdr *)iph;
2933 memset(&lsa6, 0, sizeof(lsa6));
2934 lsa6.sin6_len = sizeof(lsa6);
2935 lsa6.sin6_family = AF_INET6;
2936 lsa6.sin6_addr = ip6->ip6_src;
2937 lsa6.sin6_port = sh->src_port;
2938 memset(&fsa6, 0, sizeof(fsa6));
2939 fsa6.sin6_len = sizeof(fsa6);
2940 fsa6.sin6_family = AF_INET6;
2941 fsa6.sin6_addr = ip6->ip6_dst;
2942 fsa6.sin6_port = sh->dest_port;
2943 printf("src: ");
2944 sctp_print_address((struct sockaddr *)&lsa6);
2945 printf("dest: ");
2946 sctp_print_address((struct sockaddr *)&fsa6);
2947 }
2948 }
2949
2950 #if defined(__FreeBSD__) || defined(__APPLE__)
2951
2952 /* cloned from uipc_socket.c */
2953
2954 #define SCTP_SBLINKRECORD(sb, m0) do { \
2955 if ((sb)->sb_lastrecord != NULL) \
2956 (sb)->sb_lastrecord->m_nextpkt = (m0); \
2957 else \
2958 (sb)->sb_mb = (m0); \
2959 (sb)->sb_lastrecord = (m0); \
2960 } while (/*CONSTCOND*/0)
2961 #endif
2962
2963
2964 int
sbappendaddr_nocheck(struct sockbuf * sb,const struct sockaddr * asa,struct mbuf * m0,struct mbuf * control,u_int32_t tag,struct sctp_inpcb * inp)2965 sbappendaddr_nocheck(struct sockbuf *sb, const struct sockaddr *asa,
2966 struct mbuf *m0, struct mbuf *control,
2967 u_int32_t tag, struct sctp_inpcb *inp)
2968 {
2969 #ifdef __NetBSD__
2970 struct mbuf *m, *n;
2971
2972 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
2973 panic("sbappendaddr_nocheck");
2974
2975 m0->m_pkthdr.csum_data = (int)tag;
2976
2977 for (n = control; n; n = n->m_next) {
2978 if (n->m_next == 0) /* keep pointer to last control buf */
2979 break;
2980 }
2981 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
2982 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
2983 MGETHDR(m, M_DONTWAIT, MT_SONAME);
2984 if (m == 0)
2985 return (0);
2986
2987 m->m_len = asa->sa_len;
2988 memcpy(mtod(m, void *), (const void *)asa, asa->sa_len);
2989 } else {
2990 m = NULL;
2991 }
2992 if (n) {
2993 n->m_next = m0; /* concatenate data to control */
2994 }else {
2995 control = m0;
2996 }
2997 if (m)
2998 m->m_next = control;
2999 else
3000 m = control;
3001 m->m_pkthdr.csum_data = tag;
3002
3003 for (n = m; n; n = n->m_next)
3004 sballoc(sb, n);
3005 if ((n = sb->sb_mb) != NULL) {
3006 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3007 inp->sb_last_mpkt = NULL;
3008 }
3009 if (inp->sb_last_mpkt)
3010 inp->sb_last_mpkt->m_nextpkt = m;
3011 else {
3012 while (n->m_nextpkt) {
3013 n = n->m_nextpkt;
3014 }
3015 n->m_nextpkt = m;
3016 }
3017 inp->sb_last_mpkt = m;
3018 } else {
3019 inp->sb_last_mpkt = sb->sb_mb = m;
3020 inp->sctp_vtag_first = tag;
3021 }
3022 return (1);
3023 #endif
3024 #if defined(__FreeBSD__) || defined(__APPLE__)
3025 struct mbuf *m, *n, *nlast;
3026 int cnt=0;
3027
3028 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
3029 panic("sbappendaddr_nocheck");
3030
3031 for (n = control; n; n = n->m_next) {
3032 if (n->m_next == 0) /* get pointer to last control buf */
3033 break;
3034 }
3035 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3036 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
3037 if (asa->sa_len > MHLEN)
3038 return (0);
3039 try_again:
3040 MGETHDR(m, M_DONTWAIT, MT_SONAME);
3041 if (m == 0)
3042 return (0);
3043 m->m_len = 0;
3044 /* safety */
3045 if (m == m0) {
3046 printf("Duplicate mbuf allocated %p in and mget returned %p?\n",
3047 m0, m);
3048 if (cnt) {
3049 panic("more than once");
3050 }
3051 cnt++;
3052 goto try_again;
3053 }
3054 m->m_len = asa->sa_len;
3055 bcopy((void *)asa, mtod(m, void *), asa->sa_len);
3056 }
3057 else {
3058 m = NULL;
3059 }
3060 if (n)
3061 n->m_next = m0; /* concatenate data to control */
3062 else
3063 control = m0;
3064 if (m)
3065 m->m_next = control;
3066 else
3067 m = control;
3068 m->m_pkthdr.csum_data = (int)tag;
3069
3070 for (n = m; n; n = n->m_next)
3071 sballoc(sb, n);
3072 nlast = n;
3073 if (sb->sb_mb == NULL) {
3074 inp->sctp_vtag_first = tag;
3075 }
3076
3077 #ifdef __FREEBSD__
3078 if (sb->sb_mb == NULL)
3079 inp->sctp_vtag_first = tag;
3080 SCTP_SBLINKRECORD(sb, m);
3081 sb->sb_mbtail = nlast;
3082 #else
3083 if ((n = sb->sb_mb) != NULL) {
3084 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3085 inp->sb_last_mpkt = NULL;
3086 }
3087 if (inp->sb_last_mpkt)
3088 inp->sb_last_mpkt->m_nextpkt = m;
3089 else {
3090 while (n->m_nextpkt) {
3091 n = n->m_nextpkt;
3092 }
3093 n->m_nextpkt = m;
3094 }
3095 inp->sb_last_mpkt = m;
3096 } else {
3097 inp->sb_last_mpkt = sb->sb_mb = m;
3098 inp->sctp_vtag_first = tag;
3099 }
3100 #endif
3101 return (1);
3102 #endif
3103 #ifdef __OpenBSD__
3104 struct mbuf *m, *n;
3105
3106 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
3107 panic("sbappendaddr_nocheck");
3108 m0->m_pkthdr.csum = (int)tag;
3109 for (n = control; n; n = n->m_next) {
3110 if (n->m_next == 0) /* keep pointer to last control buf */
3111 break;
3112 }
3113 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
3114 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
3115 if (asa->sa_len > MHLEN)
3116 return (0);
3117 MGETHDR(m, M_DONTWAIT, MT_SONAME);
3118 if (m == 0)
3119 return (0);
3120 m->m_len = asa->sa_len;
3121 bcopy((void *)asa, mtod(m, void *), asa->sa_len);
3122 } else {
3123 m = NULL;
3124 }
3125 if (n)
3126 n->m_next = m0; /* concatenate data to control */
3127 else
3128 control = m0;
3129
3130 m->m_pkthdr.csum = (int)tag;
3131 m->m_next = control;
3132 for (n = m; n; n = n->m_next)
3133 sballoc(sb, n);
3134 if ((n = sb->sb_mb) != NULL) {
3135 if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
3136 inp->sb_last_mpkt = NULL;
3137 }
3138 if (inp->sb_last_mpkt)
3139 inp->sb_last_mpkt->m_nextpkt = m;
3140 else {
3141 while (n->m_nextpkt) {
3142 n = n->m_nextpkt;
3143 }
3144 n->m_nextpkt = m;
3145 }
3146 inp->sb_last_mpkt = m;
3147 } else {
3148 inp->sb_last_mpkt = sb->sb_mb = m;
3149 inp->sctp_vtag_first = tag;
3150 }
3151 return (1);
3152 #endif
3153 }
3154
3155 /*************HOLD THIS COMMENT FOR PATCH FILE OF
3156 *************ALTERNATE ROUTING CODE
3157 */
3158
3159 /*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
3160 *************ALTERNATE ROUTING CODE
3161 */
3162
3163 struct mbuf *
sctp_generate_invmanparam(int err)3164 sctp_generate_invmanparam(int err)
3165 {
3166 /* Return a MBUF with a invalid mandatory parameter */
3167 struct mbuf *m;
3168
3169 MGET(m, M_DONTWAIT, MT_DATA);
3170 if (m) {
3171 struct sctp_paramhdr *ph;
3172 m->m_len = sizeof(struct sctp_paramhdr);
3173 ph = mtod(m, struct sctp_paramhdr *);
3174 ph->param_length = htons(sizeof(struct sctp_paramhdr));
3175 ph->param_type = htons(err);
3176 }
3177 return (m);
3178 }
3179
3180 static int
sctp_should_be_moved(struct mbuf * this,struct sctp_association * asoc)3181 sctp_should_be_moved(struct mbuf *this, struct sctp_association *asoc)
3182 {
3183 struct mbuf *m;
3184 /*
3185 * given a mbuf chain, look through it finding
3186 * the M_PKTHDR and return 1 if it belongs to
3187 * the association given. We tell this by
3188 * a kludge where we stuff the my_vtag of the asoc
3189 * into the m->m_pkthdr.csum_data/csum field.
3190 */
3191 m = this;
3192 while (m) {
3193 if (m->m_flags & M_PKTHDR) {
3194 /* check it */
3195 #if defined(__OpenBSD__)
3196 if ((u_int32_t)m->m_pkthdr.csum == asoc->my_vtag)
3197 #else
3198 if ((u_int32_t)m->m_pkthdr.csum_data == asoc->my_vtag)
3199 #endif
3200 {
3201 /* Yep */
3202 return (1);
3203 }
3204 }
3205 m = m->m_next;
3206 }
3207 return (0);
3208 }
3209
3210 u_int32_t
sctp_get_first_vtag_from_sb(struct socket * so)3211 sctp_get_first_vtag_from_sb(struct socket *so)
3212 {
3213 struct mbuf *this, *at;
3214 u_int32_t retval;
3215
3216 retval = 0;
3217 if (so->so_rcv.sb_mb) {
3218 /* grubbing time */
3219 this = so->so_rcv.sb_mb;
3220 while (this) {
3221 at = this;
3222 /* get to the m_pkthdr */
3223 while (at) {
3224 if (at->m_flags & M_PKTHDR)
3225 break;
3226 else {
3227 at = at->m_next;
3228 }
3229 }
3230 /* now do we have a m_pkthdr */
3231 if (at && (at->m_flags & M_PKTHDR)) {
3232 /* check it */
3233 #if defined(__OpenBSD__)
3234 if ((u_int32_t)at->m_pkthdr.csum != 0)
3235 #else
3236 if ((u_int32_t)at->m_pkthdr.csum_data != 0)
3237 #endif
3238 {
3239 /* its the one */
3240 #if defined(__OpenBSD__)
3241 retval = (u_int32_t)at->m_pkthdr.csum;
3242 #else
3243 retval =
3244 (u_int32_t)at->m_pkthdr.csum_data;
3245 #endif
3246 break;
3247 }
3248 }
3249 this = this->m_nextpkt;
3250 }
3251
3252 }
3253 return (retval);
3254
3255 }
3256 void
sctp_grub_through_socket_buffer(struct sctp_inpcb * inp,struct socket * old,struct socket * new,struct sctp_tcb * stcb)3257 sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
3258 struct socket *new, struct sctp_tcb *stcb)
3259 {
3260 struct mbuf **put, **take, *next, *this;
3261 struct sockbuf *old_sb, *new_sb;
3262 struct sctp_association *asoc;
3263 int moved_top = 0;
3264
3265 asoc = &stcb->asoc;
3266 old_sb = &old->so_rcv;
3267 new_sb = &new->so_rcv;
3268 if (old_sb->sb_mb == NULL) {
3269 /* Nothing to move */
3270 return;
3271 }
3272
3273 if (inp->sctp_vtag_first == asoc->my_vtag) {
3274 /* First one must be moved */
3275 struct mbuf *mm;
3276 for (mm = old_sb->sb_mb; mm; mm = mm->m_next) {
3277 /*
3278 * Go down the chain and fix
3279 * the space allocation of the
3280 * two sockets.
3281 */
3282 sbfree(old_sb, mm);
3283 sballoc(new_sb, mm);
3284 }
3285 new_sb->sb_mb = old_sb->sb_mb;
3286 old_sb->sb_mb = new_sb->sb_mb->m_nextpkt;
3287 new_sb->sb_mb->m_nextpkt = NULL;
3288 put = &new_sb->sb_mb->m_nextpkt;
3289 moved_top = 1;
3290 } else {
3291 put = &new_sb->sb_mb;
3292 }
3293
3294 take = &old_sb->sb_mb;
3295 next = old_sb->sb_mb;
3296 while (next) {
3297 this = next;
3298 /* position for next one */
3299 next = this->m_nextpkt;
3300 /* check the tag of this packet */
3301 if (sctp_should_be_moved(this, asoc)) {
3302 /* yes this needs to be moved */
3303 struct mbuf *mm;
3304 *take = this->m_nextpkt;
3305 this->m_nextpkt = NULL;
3306 *put = this;
3307 for (mm = this; mm; mm = mm->m_next) {
3308 /*
3309 * Go down the chain and fix
3310 * the space allocation of the
3311 * two sockets.
3312 */
3313 sbfree(old_sb, mm);
3314 sballoc(new_sb, mm);
3315 }
3316 put = &this->m_nextpkt;
3317
3318 } else {
3319 /* no advance our take point. */
3320 take = &this->m_nextpkt;
3321 }
3322 }
3323 if (moved_top) {
3324 /*
3325 * Ok so now we must re-position vtag_first to
3326 * match the new first one since we moved the
3327 * mbuf at the top.
3328 */
3329 inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
3330 }
3331 }
3332
3333 void
sctp_free_bufspace(struct sctp_tcb * stcb,struct sctp_association * asoc,struct sctp_tmit_chunk * tp1)3334 sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
3335 struct sctp_tmit_chunk *tp1)
3336 {
3337 if (tp1->data == NULL) {
3338 return;
3339 }
3340 #ifdef SCTP_MBCNT_LOGGING
3341 sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
3342 asoc->total_output_queue_size,
3343 tp1->book_size,
3344 asoc->total_output_mbuf_queue_size,
3345 tp1->mbcnt);
3346 #endif
3347 if (asoc->total_output_queue_size >= tp1->book_size) {
3348 asoc->total_output_queue_size -= tp1->book_size;
3349 } else {
3350 asoc->total_output_queue_size = 0;
3351 }
3352
3353 /* Now free the mbuf */
3354 if (asoc->total_output_mbuf_queue_size >= tp1->mbcnt) {
3355 asoc->total_output_mbuf_queue_size -= tp1->mbcnt;
3356 } else {
3357 asoc->total_output_mbuf_queue_size = 0;
3358 }
3359 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3360 (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3361 if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
3362 stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
3363 } else {
3364 stcb->sctp_socket->so_snd.sb_cc = 0;
3365
3366 }
3367 if (stcb->sctp_socket->so_snd.sb_mbcnt >= tp1->mbcnt) {
3368 stcb->sctp_socket->so_snd.sb_mbcnt -= tp1->mbcnt;
3369 } else {
3370 stcb->sctp_socket->so_snd.sb_mbcnt = 0;
3371 }
3372 }
3373 }
3374
3375 int
sctp_release_pr_sctp_chunk(struct sctp_tcb * stcb,struct sctp_tmit_chunk * tp1,int reason,struct sctpchunk_listhead * queue)3376 sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
3377 int reason, struct sctpchunk_listhead *queue)
3378 {
3379 int ret_sz = 0;
3380 int notdone;
3381 uint8_t foundeom = 0;
3382
3383 do {
3384 ret_sz += tp1->book_size;
3385 tp1->sent = SCTP_FORWARD_TSN_SKIP;
3386 if (tp1->data) {
3387 sctp_free_bufspace(stcb, &stcb->asoc, tp1);
3388 sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1);
3389 sctp_m_freem(tp1->data);
3390 tp1->data = NULL;
3391 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
3392 }
3393 if (tp1->flags & SCTP_PR_SCTP_BUFFER) {
3394 stcb->asoc.sent_queue_cnt_removeable--;
3395 }
3396 if (queue == &stcb->asoc.send_queue) {
3397 TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
3398 /* on to the sent queue */
3399 TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
3400 sctp_next);
3401 stcb->asoc.sent_queue_cnt++;
3402 }
3403 if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
3404 SCTP_DATA_NOT_FRAG) {
3405 /* not frag'ed we ae done */
3406 notdone = 0;
3407 foundeom = 1;
3408 } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
3409 /* end of frag, we are done */
3410 notdone = 0;
3411 foundeom = 1;
3412 } else {
3413 /* Its a begin or middle piece, we must mark all of it */
3414 notdone = 1;
3415 tp1 = TAILQ_NEXT(tp1, sctp_next);
3416 }
3417 } while (tp1 && notdone);
3418 if ((foundeom == 0) && (queue == &stcb->asoc.sent_queue)) {
3419 /*
3420 * The multi-part message was scattered
3421 * across the send and sent queue.
3422 */
3423 tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
3424 /*
3425 * recurse throught the send_queue too, starting at the
3426 * beginning.
3427 */
3428 if (tp1) {
3429 ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
3430 &stcb->asoc.send_queue);
3431 } else {
3432 printf("hmm, nothing on the send queue and no EOM?\n");
3433 }
3434 }
3435 return (ret_sz);
3436 }
3437
3438 /*
3439 * checks to see if the given address, sa, is one that is currently
3440 * known by the kernel
3441 * note: can't distinguish the same address on multiple interfaces and
3442 * doesn't handle multiple addresses with different zone/scope id's
3443 * note: ifa_ifwithaddr() compares the entire sockaddr struct
3444 */
3445 struct ifaddr *
sctp_find_ifa_by_addr(struct sockaddr * sa)3446 sctp_find_ifa_by_addr(struct sockaddr *sa)
3447 {
3448 struct ifnet *ifn;
3449 struct ifaddr *ifa;
3450 int s;
3451
3452 /* go through all our known interfaces */
3453 s = pserialize_read_enter();
3454 IFNET_READER_FOREACH(ifn) {
3455 /* go through each interface addresses */
3456 IFADDR_READER_FOREACH(ifa, ifn) {
3457 /* correct family? */
3458 if (ifa->ifa_addr->sa_family != sa->sa_family)
3459 continue;
3460
3461 #ifdef INET6
3462 if (ifa->ifa_addr->sa_family == AF_INET6) {
3463 /* IPv6 address */
3464 struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
3465 sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
3466 if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
3467 /* create a copy and clear scope */
3468 memcpy(&sin6_tmp, sin1,
3469 sizeof(struct sockaddr_in6));
3470 sin1 = &sin6_tmp;
3471 in6_clearscope(&sin1->sin6_addr);
3472 }
3473 sin2 = (struct sockaddr_in6 *)sa;
3474 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
3475 sizeof(struct in6_addr)) == 0) {
3476 /* found it */
3477 pserialize_read_exit(s);
3478 return (ifa);
3479 }
3480 } else
3481 #endif
3482 if (ifa->ifa_addr->sa_family == AF_INET) {
3483 /* IPv4 address */
3484 struct sockaddr_in *sin1, *sin2;
3485 sin1 = (struct sockaddr_in *)ifa->ifa_addr;
3486 sin2 = (struct sockaddr_in *)sa;
3487 if (sin1->sin_addr.s_addr ==
3488 sin2->sin_addr.s_addr) {
3489 /* found it */
3490 pserialize_read_exit(s);
3491 return (ifa);
3492 }
3493 }
3494 /* else, not AF_INET or AF_INET6, so skip */
3495 } /* end foreach ifa */
3496 } /* end foreach ifn */
3497 pserialize_read_exit(s);
3498
3499 /* not found! */
3500 return (NULL);
3501 }
3502
3503
3504 #ifdef __APPLE__
3505 /*
3506 * here we hack in a fix for Apple's m_copym for the case where the first mbuf
3507 * in the chain is a M_PKTHDR and the length is zero
3508 */
3509 static void
sctp_pkthdr_fix(struct mbuf * m)3510 sctp_pkthdr_fix(struct mbuf *m)
3511 {
3512 struct mbuf *m_nxt;
3513
3514 if ((m->m_flags & M_PKTHDR) == 0) {
3515 /* not a PKTHDR */
3516 return;
3517 }
3518
3519 if (m->m_len != 0) {
3520 /* not a zero length PKTHDR mbuf */
3521 return;
3522 }
3523
3524 /* let's move in a word into the first mbuf... yes, ugly! */
3525 m_nxt = m->m_next;
3526 if (m_nxt == NULL) {
3527 /* umm... not a very useful mbuf chain... */
3528 return;
3529 }
3530 if ((size_t)m_nxt->m_len > sizeof(long)) {
3531 /* move over a long */
3532 bcopy(mtod(m_nxt, void *), mtod(m, void *), sizeof(long));
3533 /* update mbuf data pointers and lengths */
3534 m->m_len += sizeof(long);
3535 m_nxt->m_data += sizeof(long);
3536 m_nxt->m_len -= sizeof(long);
3537 }
3538 }
3539
3540 inline struct mbuf *
sctp_m_copym(struct mbuf * m,int off,int len,int wait)3541 sctp_m_copym(struct mbuf *m, int off, int len, int wait)
3542 {
3543 sctp_pkthdr_fix(m);
3544 return (m_copym(m, off, len, wait));
3545 }
3546 #endif /* __APPLE__ */
3547