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