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