comparison libfdcore/sctp.c @ 1174:b72836fb814b

Add some compliancy to RFC6458. Not tested however as Ubuntu does not support this yet
author Sebastien Decugis <sdecugis@freediameter.net>
date Mon, 03 Jun 2013 12:05:37 +0800
parents 96f2051215c8
children 2da13c87baa7
comparison
equal deleted inserted replaced
1173:d0a7b76a3c1c 1174:b72836fb814b
42 /* Size of buffer to receive ancilliary data. May need to be enlarged if more sockopt are set... */ 42 /* Size of buffer to receive ancilliary data. May need to be enlarged if more sockopt are set... */
43 #ifndef CMSG_BUF_LEN 43 #ifndef CMSG_BUF_LEN
44 #define CMSG_BUF_LEN 1024 44 #define CMSG_BUF_LEN 1024
45 #endif /* CMSG_BUF_LEN */ 45 #endif /* CMSG_BUF_LEN */
46 46
47 /* Level of SCTP-specific traces */ 47 /* Use old draft-ietf-tsvwg-sctpsocket-17 API ? If not defined, RFC6458 API will be used */
48 #ifdef DEBUG_SCTP 48 /* #define OLD_SCTP_SOCKET_API */
49 #define SCTP_LEVEL FULL 49
50 #else /* DEBUG_SCTP */ 50 /* Automatically fallback to old API if some of the new symbols are not defined */
51 #define SCTP_LEVEL (FCTS + 1) 51 #if (!defined(SCTP_CONNECTX_4_ARGS) || (!defined(SCTP_RECVRCVINFO)) || (!defined(SCTP_SNDINFO)))
52 #endif /* DEBUG_SCTP */ 52 # define OLD_SCTP_SOCKET_API
53 #endif
54
53 55
54 /* Temper with the retransmission timers to try and improve disconnection detection response? Undef this to keep the defaults of SCTP stack */ 56 /* Temper with the retransmission timers to try and improve disconnection detection response? Undef this to keep the defaults of SCTP stack */
55 #ifndef USE_DEFAULT_SCTP_RTX_PARAMS /* make this a configuration option if useful */ 57 #ifndef USE_DEFAULT_SCTP_RTX_PARAMS /* make this a configuration option if useful */
56 #define ADJUST_RTX_PARAMS 58 #define ADJUST_RTX_PARAMS
57 #endif /* USE_DEFAULT_SCTP_RTX_PARAMS */ 59 #endif /* USE_DEFAULT_SCTP_RTX_PARAMS */
58 60
59 /* Pre-binding socket options -- # streams read in config */ 61 /* Pre-binding socket options -- # streams read in config */
60 /* The code of this file is based on draft-ietf-tsvwg-sctpsocket, versions 17 to 21 */
61 static int fd_setsockopt_prebind(int sk) 62 static int fd_setsockopt_prebind(int sk)
62 { 63 {
63 socklen_t sz; 64 socklen_t sz;
64 65
65 TRACE_ENTRY( "%d", sk); 66 TRACE_ENTRY( "%d", sk);
76 #ifdef SCTP_RTOINFO 77 #ifdef SCTP_RTOINFO
77 { 78 {
78 struct sctp_rtoinfo rtoinfo; 79 struct sctp_rtoinfo rtoinfo;
79 memset(&rtoinfo, 0, sizeof(rtoinfo)); 80 memset(&rtoinfo, 0, sizeof(rtoinfo));
80 81
81 if (TRACE_BOOL(SCTP_LEVEL)) { 82 if (TRACE_BOOL(ANNOYING)) {
82 sz = sizeof(rtoinfo); 83 sz = sizeof(rtoinfo);
83 /* Read socket defaults */ 84 /* Read socket defaults */
84 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) ); 85 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) );
85 if (sz != sizeof(rtoinfo)) 86 if (sz != sizeof(rtoinfo))
86 { 87 {
97 rtoinfo.srto_min = 1000; /* Value under which the RTO does not descend, we set this value to not conflict with srto_max */ 98 rtoinfo.srto_min = 1000; /* Value under which the RTO does not descend, we set this value to not conflict with srto_max */
98 99
99 /* Set the option to the socket */ 100 /* Set the option to the socket */
100 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) ); 101 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) );
101 102
102 if (TRACE_BOOL(SCTP_LEVEL)) { 103 if (TRACE_BOOL(ANNOYING)) {
103 /* Check new values */ 104 /* Check new values */
104 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) ); 105 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) );
105 fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u", rtoinfo.srto_initial); 106 fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u", rtoinfo.srto_initial);
106 fd_log_debug( " srto_max : %u", rtoinfo.srto_max); 107 fd_log_debug( " srto_max : %u", rtoinfo.srto_max);
107 fd_log_debug( " srto_min : %u", rtoinfo.srto_min); 108 fd_log_debug( " srto_min : %u", rtoinfo.srto_min);
108 } 109 }
109 } 110 }
110 #else /* SCTP_RTOINFO */ 111 #else /* SCTP_RTOINFO */
111 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_RTOINFO"); 112 TRACE_DEBUG(ANNOYING, "Skipping SCTP_RTOINFO");
112 #endif /* SCTP_RTOINFO */ 113 #endif /* SCTP_RTOINFO */
113 114
114 /* Set the association parameters: max number of retransmits, ... */ 115 /* Set the association parameters: max number of retransmits, ... */
115 #ifdef SCTP_ASSOCINFO 116 #ifdef SCTP_ASSOCINFO
116 { 117 {
117 struct sctp_assocparams assoc; 118 struct sctp_assocparams assoc;
118 memset(&assoc, 0, sizeof(assoc)); 119 memset(&assoc, 0, sizeof(assoc));
119 120
120 if (TRACE_BOOL(SCTP_LEVEL)) { 121 if (TRACE_BOOL(ANNOYING)) {
121 sz = sizeof(assoc); 122 sz = sizeof(assoc);
122 /* Read socket defaults */ 123 /* Read socket defaults */
123 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) ); 124 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) );
124 if (sz != sizeof(assoc)) 125 if (sz != sizeof(assoc))
125 { 126 {
137 /* Note that this must remain less than the sum of retransmission parameters of the different paths. */ 138 /* Note that this must remain less than the sum of retransmission parameters of the different paths. */
138 139
139 /* Set the option to the socket */ 140 /* Set the option to the socket */
140 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc)) ); 141 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc)) );
141 142
142 if (TRACE_BOOL(SCTP_LEVEL)) { 143 if (TRACE_BOOL(ANNOYING)) {
143 /* Check new values */ 144 /* Check new values */
144 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) ); 145 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) );
145 fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt : %hu", assoc.sasoc_asocmaxrxt); 146 fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt : %hu", assoc.sasoc_asocmaxrxt);
146 fd_log_debug( " sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations); 147 fd_log_debug( " sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations);
147 fd_log_debug( " sasoc_peer_rwnd : %u" , assoc.sasoc_peer_rwnd); 148 fd_log_debug( " sasoc_peer_rwnd : %u" , assoc.sasoc_peer_rwnd);
148 fd_log_debug( " sasoc_local_rwnd : %u" , assoc.sasoc_local_rwnd); 149 fd_log_debug( " sasoc_local_rwnd : %u" , assoc.sasoc_local_rwnd);
149 fd_log_debug( " sasoc_cookie_life : %u" , assoc.sasoc_cookie_life); 150 fd_log_debug( " sasoc_cookie_life : %u" , assoc.sasoc_cookie_life);
150 } 151 }
151 } 152 }
152 #else /* SCTP_ASSOCINFO */ 153 #else /* SCTP_ASSOCINFO */
153 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_ASSOCINFO"); 154 TRACE_DEBUG(ANNOYING, "Skipping SCTP_ASSOCINFO");
154 #endif /* SCTP_ASSOCINFO */ 155 #endif /* SCTP_ASSOCINFO */
155 #endif /* ADJUST_RTX_PARAMS */ 156 #endif /* ADJUST_RTX_PARAMS */
156 157
157 /* Set the INIT parameters, such as number of streams */ 158 /* Set the INIT parameters, such as number of streams */
158 #ifdef SCTP_INITMSG 159 #ifdef SCTP_INITMSG
159 { 160 {
160 struct sctp_initmsg init; 161 struct sctp_initmsg init;
161 memset(&init, 0, sizeof(init)); 162 memset(&init, 0, sizeof(init));
162 163
163 if (TRACE_BOOL(SCTP_LEVEL)) { 164 if (TRACE_BOOL(ANNOYING)) {
164 sz = sizeof(init); 165 sz = sizeof(init);
165 166
166 /* Read socket defaults */ 167 /* Read socket defaults */
167 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) ); 168 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) );
168 if (sz != sizeof(init)) 169 if (sz != sizeof(init))
181 init.sinit_max_init_timeo = CNX_TIMEOUT * 1000; 182 init.sinit_max_init_timeo = CNX_TIMEOUT * 1000;
182 183
183 /* Set the option to the socket */ 184 /* Set the option to the socket */
184 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)) ); 185 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)) );
185 186
186 if (TRACE_BOOL(SCTP_LEVEL)) { 187 if (TRACE_BOOL(ANNOYING)) {
187 /* Check new values */ 188 /* Check new values */
188 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) ); 189 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) );
189 fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams : %hu", init.sinit_num_ostreams); 190 fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams : %hu", init.sinit_num_ostreams);
190 fd_log_debug( " sinit_max_instreams : %hu", init.sinit_max_instreams); 191 fd_log_debug( " sinit_max_instreams : %hu", init.sinit_max_instreams);
191 fd_log_debug( " sinit_max_attempts : %hu", init.sinit_max_attempts); 192 fd_log_debug( " sinit_max_attempts : %hu", init.sinit_max_attempts);
192 fd_log_debug( " sinit_max_init_timeo : %hu", init.sinit_max_init_timeo); 193 fd_log_debug( " sinit_max_init_timeo : %hu", init.sinit_max_init_timeo);
193 } 194 }
194 } 195 }
195 #else /* SCTP_INITMSG */ 196 #else /* SCTP_INITMSG */
196 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_INITMSG"); 197 TRACE_DEBUG(ANNOYING, "Skipping SCTP_INITMSG");
197 #endif /* SCTP_INITMSG */ 198 #endif /* SCTP_INITMSG */
198 199
199 /* The SO_LINGER option will be reset if we want to perform SCTP ABORT */ 200 /* The SO_LINGER option will be reset if we want to perform SCTP ABORT */
200 #ifdef SO_LINGER 201 #ifdef SO_LINGER
201 { 202 {
202 struct linger linger; 203 struct linger linger;
203 memset(&linger, 0, sizeof(linger)); 204 memset(&linger, 0, sizeof(linger));
204 205
205 if (TRACE_BOOL(SCTP_LEVEL)) { 206 if (TRACE_BOOL(ANNOYING)) {
206 sz = sizeof(linger); 207 sz = sizeof(linger);
207 /* Read socket defaults */ 208 /* Read socket defaults */
208 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) ); 209 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) );
209 if (sz != sizeof(linger)) 210 if (sz != sizeof(linger))
210 { 211 {
219 linger.l_linger = 0; /* Ignored, but it would mean : Return immediately when closing (=> abort) (graceful shutdown in background) */ 220 linger.l_linger = 0; /* Ignored, but it would mean : Return immediately when closing (=> abort) (graceful shutdown in background) */
220 221
221 /* Set the option */ 222 /* Set the option */
222 CHECK_SYS( setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) ); 223 CHECK_SYS( setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) );
223 224
224 if (TRACE_BOOL(SCTP_LEVEL)) { 225 if (TRACE_BOOL(ANNOYING)) {
225 /* Check new values */ 226 /* Check new values */
226 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) ); 227 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) );
227 fd_log_debug( "New SO_LINGER : l_onoff : %d", linger.l_onoff); 228 fd_log_debug( "New SO_LINGER : l_onoff : %d", linger.l_onoff);
228 fd_log_debug( " l_linger : %d", linger.l_linger); 229 fd_log_debug( " l_linger : %d", linger.l_linger);
229 } 230 }
230 } 231 }
231 #else /* SO_LINGER */ 232 #else /* SO_LINGER */
232 TRACE_DEBUG(SCTP_LEVEL, "Skipping SO_LINGER"); 233 TRACE_DEBUG(ANNOYING, "Skipping SO_LINGER");
233 #endif /* SO_LINGER */ 234 #endif /* SO_LINGER */
234 235
235 /* Set the NODELAY option (Nagle-like algorithm) */ 236 /* Set the NODELAY option (Nagle-like algorithm) */
236 #ifdef SCTP_NODELAY 237 #ifdef SCTP_NODELAY
237 { 238 {
238 int nodelay; 239 int nodelay;
239 240
240 if (TRACE_BOOL(SCTP_LEVEL)) { 241 if (TRACE_BOOL(ANNOYING)) {
241 sz = sizeof(nodelay); 242 sz = sizeof(nodelay);
242 /* Read socket defaults */ 243 /* Read socket defaults */
243 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) ); 244 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) );
244 if (sz != sizeof(nodelay)) 245 if (sz != sizeof(nodelay))
245 { 246 {
252 nodelay = 1; /* We turn ON the Nagle algorithm (probably the default already), since we might have several messages to send through the same proxy (not the same session). */ 253 nodelay = 1; /* We turn ON the Nagle algorithm (probably the default already), since we might have several messages to send through the same proxy (not the same session). */
253 254
254 /* Set the option to the socket */ 255 /* Set the option to the socket */
255 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)) ); 256 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)) );
256 257
257 if (TRACE_BOOL(SCTP_LEVEL)) { 258 if (TRACE_BOOL(ANNOYING)) {
258 /* Check new values */ 259 /* Check new values */
259 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) ); 260 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) );
260 fd_log_debug( "New SCTP_NODELAY value : %s", nodelay ? "true" : "false"); 261 fd_log_debug( "New SCTP_NODELAY value : %s", nodelay ? "true" : "false");
261 } 262 }
262 } 263 }
263 #else /* SCTP_NODELAY */ 264 #else /* SCTP_NODELAY */
264 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_NODELAY"); 265 TRACE_DEBUG(ANNOYING, "Skipping SCTP_NODELAY");
265 #endif /* SCTP_NODELAY */ 266 #endif /* SCTP_NODELAY */
266 267
267 /* 268 /*
268 SO_RCVBUF size of receiver window 269 SO_RCVBUF size of receiver window
269 SO_SNDBUF size of pending data to send 270 SO_SNDBUF size of pending data to send
275 /* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */ 276 /* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */
276 #ifdef SCTP_DISABLE_FRAGMENTS 277 #ifdef SCTP_DISABLE_FRAGMENTS
277 { 278 {
278 int nofrag; 279 int nofrag;
279 280
280 if (TRACE_BOOL(SCTP_LEVEL)) { 281 if (TRACE_BOOL(ANNOYING)) {
281 sz = sizeof(nofrag); 282 sz = sizeof(nofrag);
282 /* Read socket defaults */ 283 /* Read socket defaults */
283 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) ); 284 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) );
284 if (sz != sizeof(nofrag)) 285 if (sz != sizeof(nofrag))
285 { 286 {
292 nofrag = 0; /* We turn ON the fragmentation, since Diameter messages & TLS messages can be quite large. */ 293 nofrag = 0; /* We turn ON the fragmentation, since Diameter messages & TLS messages can be quite large. */
293 294
294 /* Set the option to the socket */ 295 /* Set the option to the socket */
295 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag)) ); 296 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag)) );
296 297
297 if (TRACE_BOOL(SCTP_LEVEL)) { 298 if (TRACE_BOOL(ANNOYING)) {
298 /* Check new values */ 299 /* Check new values */
299 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) ); 300 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) );
300 fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false"); 301 fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false");
301 } 302 }
302 } 303 }
311 memset(&parms, 0, sizeof(parms)); 312 memset(&parms, 0, sizeof(parms));
312 313
313 /* Some kernel versions need this to be set */ 314 /* Some kernel versions need this to be set */
314 parms.spp_address.ss_family = AF_INET; 315 parms.spp_address.ss_family = AF_INET;
315 316
316 if (TRACE_BOOL(SCTP_LEVEL)) { 317 if (TRACE_BOOL(ANNOYING)) {
317 sz = sizeof(parms); 318 sz = sizeof(parms);
318 319
319 /* Read socket defaults */ 320 /* Read socket defaults */
320 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz) ); 321 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz) );
321 if (sz != sizeof(parms)) 322 if (sz != sizeof(parms))
342 #endif /* ADJUST_RTX_PARAMS */ 343 #endif /* ADJUST_RTX_PARAMS */
343 344
344 /* Set the option to the socket */ 345 /* Set the option to the socket */
345 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, sizeof(parms)) ); 346 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, sizeof(parms)) );
346 347
347 if (TRACE_BOOL(SCTP_LEVEL)) { 348 if (TRACE_BOOL(ANNOYING)) {
348 /* Check new values */ 349 /* Check new values */
349 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz) ); 350 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz) );
350 fd_log_debug( "New SCTP_PEER_ADDR_PARAMS : spp_hbinterval : %u", parms.spp_hbinterval); 351 fd_log_debug( "New SCTP_PEER_ADDR_PARAMS : spp_hbinterval : %u", parms.spp_hbinterval);
351 fd_log_debug( " spp_pathmaxrxt : %hu", parms.spp_pathmaxrxt); 352 fd_log_debug( " spp_pathmaxrxt : %hu", parms.spp_pathmaxrxt);
352 fd_log_debug( " spp_pathmtu : %u", parms.spp_pathmtu); 353 fd_log_debug( " spp_pathmtu : %u", parms.spp_pathmtu);
354 // fd_log_debug( " spp_ipv6_flowlabel: %u", parms.spp_ipv6_flowlabel); 355 // fd_log_debug( " spp_ipv6_flowlabel: %u", parms.spp_ipv6_flowlabel);
355 // fd_log_debug( " spp_ipv4_tos : %hhu",parms.spp_ipv4_tos); 356 // fd_log_debug( " spp_ipv4_tos : %hhu",parms.spp_ipv4_tos);
356 } 357 }
357 } 358 }
358 #else /* SCTP_PEER_ADDR_PARAMS */ 359 #else /* SCTP_PEER_ADDR_PARAMS */
359 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_PEER_ADDR_PARAMS"); 360 TRACE_DEBUG(ANNOYING, "Skipping SCTP_PEER_ADDR_PARAMS");
360 #endif /* SCTP_PEER_ADDR_PARAMS */ 361 #endif /* SCTP_PEER_ADDR_PARAMS */
361 362
362 /* 363 /*
363 SCTP_DEFAULT_SEND_PARAM parameters for the sendto() call, we don't use it. 364 SCTP_DEFAULT_SEND_PARAM - DEPRECATED // parameters for the sendto() call, we don't use it.
364 */ 365 */
365 366
366 /* Subscribe to some notifications */ 367 /* Subscribe to some notifications */
367 #ifdef SCTP_EVENTS 368 #ifdef OLD_SCTP_SOCKET_API
369 #ifdef SCTP_EVENTS /* DEPRECATED */
368 { 370 {
369 struct sctp_event_subscribe event; 371 struct sctp_event_subscribe event;
370 372
371 memset(&event, 0, sizeof(event)); 373 memset(&event, 0, sizeof(event));
372 event.sctp_data_io_event = 1; /* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */ 374 event.sctp_data_io_event = 1; /* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */
380 // event.sctp_authentication_event = 0; /* when new key is made active */ 382 // event.sctp_authentication_event = 0; /* when new key is made active */
381 383
382 /* Set the option to the socket */ 384 /* Set the option to the socket */
383 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) ); 385 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) );
384 386
385 if (TRACE_BOOL(SCTP_LEVEL)) { 387 if (TRACE_BOOL(ANNOYING)) {
386 sz = sizeof(event); 388 sz = sizeof(event);
387 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) ); 389 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) );
388 if (sz != sizeof(event)) 390 if (sz != sizeof(event))
389 { 391 {
390 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event)); 392 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event));
401 fd_log_debug( " sctp_adaptation_layer_event : %hhu", event.sctp_adaptation_layer_event); 403 fd_log_debug( " sctp_adaptation_layer_event : %hhu", event.sctp_adaptation_layer_event);
402 // fd_log_debug( " sctp_authentication_event : %hhu", event.sctp_authentication_event); 404 // fd_log_debug( " sctp_authentication_event : %hhu", event.sctp_authentication_event);
403 } 405 }
404 } 406 }
405 #else /* SCTP_EVENTS */ 407 #else /* SCTP_EVENTS */
406 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_EVENTS"); 408 TRACE_DEBUG(ANNOYING, "Skipping SCTP_EVENTS");
407 #endif /* SCTP_EVENTS */ 409 #endif /* SCTP_EVENTS */
410 #endif /* OLD_SCTP_SOCKET_API */
408 411
409 /* Set the v4 mapped addresses option */ 412 /* Set the v4 mapped addresses option */
410 #ifdef SCTP_I_WANT_MAPPED_V4_ADDR 413 #ifdef SCTP_I_WANT_MAPPED_V4_ADDR
411 if (!fd_g_config->cnf_flags.no_ip6) { 414 if (!fd_g_config->cnf_flags.no_ip6) {
412 int v4mapped; 415 int v4mapped;
413 416
414 if (TRACE_BOOL(SCTP_LEVEL)) { 417 if (TRACE_BOOL(ANNOYING)) {
415 sz = sizeof(v4mapped); 418 sz = sizeof(v4mapped);
416 /* Read socket defaults */ 419 /* Read socket defaults */
417 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) ); 420 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) );
418 if (sz != sizeof(v4mapped)) 421 if (sz != sizeof(v4mapped))
419 { 422 {
430 #endif /* SCTP_USE_MAPPED_ADDRESSES */ 433 #endif /* SCTP_USE_MAPPED_ADDRESSES */
431 434
432 /* Set the option to the socket */ 435 /* Set the option to the socket */
433 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped)) ); 436 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped)) );
434 437
435 if (TRACE_BOOL(SCTP_LEVEL)) { 438 if (TRACE_BOOL(ANNOYING)) {
436 /* Check new values */ 439 /* Check new values */
437 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) ); 440 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) );
438 fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false"); 441 fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false");
439 } 442 }
440 } else { 443 } else {
441 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR, since IPv6 disabled."); 444 TRACE_DEBUG(ANNOYING, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR, since IPv6 disabled.");
442 } 445 }
443 #else /* SCTP_I_WANT_MAPPED_V4_ADDR */ 446 #else /* SCTP_I_WANT_MAPPED_V4_ADDR */
444 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR"); 447 TRACE_DEBUG(ANNOYING, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
445 #endif /* SCTP_I_WANT_MAPPED_V4_ADDR */ 448 #endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
446 449
447 /* 450 /*
448 SCTP_MAXSEG max size of fragmented segments -- bound to PMTU 451 SCTP_MAXSEG max size of fragmented segments -- bound to PMTU
449 SCTP_HMAC_IDENT authentication algorithms 452 SCTP_HMAC_IDENT authentication algorithms
455 /* Set the interleaving option */ 458 /* Set the interleaving option */
456 #ifdef SCTP_FRAGMENT_INTERLEAVE 459 #ifdef SCTP_FRAGMENT_INTERLEAVE
457 { 460 {
458 int interleave; 461 int interleave;
459 462
460 if (TRACE_BOOL(SCTP_LEVEL)) { 463 if (TRACE_BOOL(ANNOYING)) {
461 sz = sizeof(interleave); 464 sz = sizeof(interleave);
462 /* Read socket defaults */ 465 /* Read socket defaults */
463 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz) ); 466 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz) );
464 if (sz != sizeof(interleave)) 467 if (sz != sizeof(interleave))
465 { 468 {
476 #endif /* 0 */ 479 #endif /* 0 */
477 480
478 /* Set the option to the socket */ 481 /* Set the option to the socket */
479 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave)) ); 482 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave)) );
480 483
481 if (TRACE_BOOL(SCTP_LEVEL)) { 484 if (TRACE_BOOL(ANNOYING)) {
482 /* Check new values */ 485 /* Check new values */
483 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz) ); 486 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz) );
484 fd_log_debug( "New SCTP_FRAGMENT_INTERLEAVE value : %d", interleave); 487 fd_log_debug( "New SCTP_FRAGMENT_INTERLEAVE value : %d", interleave);
485 } 488 }
486 } 489 }
487 #else /* SCTP_FRAGMENT_INTERLEAVE */ 490 #else /* SCTP_FRAGMENT_INTERLEAVE */
488 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_FRAGMENT_INTERLEAVE"); 491 TRACE_DEBUG(ANNOYING, "Skipping SCTP_FRAGMENT_INTERLEAVE");
489 #endif /* SCTP_FRAGMENT_INTERLEAVE */ 492 #endif /* SCTP_FRAGMENT_INTERLEAVE */
490 493
491 /* 494 /*
492 SCTP_PARTIAL_DELIVERY_POINT control partial delivery size 495 SCTP_PARTIAL_DELIVERY_POINT control partial delivery size
493 SCTP_USE_EXT_RCVINFO use extended receive info structure (information about the next message if available) 496 SCTP_USE_EXT_RCVINFO - DEPRECATED use extended receive info structure (information about the next message if available)
494 */ 497 */
495 /* SCTP_AUTO_ASCONF is set by the postbind function */ 498 /* SCTP_AUTO_ASCONF is set by the postbind function */
496 /* 499 /*
497 SCTP_MAX_BURST number of packets that can be burst emitted 500 SCTP_MAX_BURST number of packets that can be burst emitted
498 SCTP_CONTEXT save a context information along with the association. 501 SCTP_CONTEXT save a context information along with the association.
501 /* SCTP_EXPLICIT_EOR: we assume implicit EOR in freeDiameter, so let's ensure this is known by the stack */ 504 /* SCTP_EXPLICIT_EOR: we assume implicit EOR in freeDiameter, so let's ensure this is known by the stack */
502 #ifdef SCTP_EXPLICIT_EOR 505 #ifdef SCTP_EXPLICIT_EOR
503 { 506 {
504 int bool; 507 int bool;
505 508
506 if (TRACE_BOOL(SCTP_LEVEL)) { 509 if (TRACE_BOOL(ANNOYING)) {
507 sz = sizeof(bool); 510 sz = sizeof(bool);
508 /* Read socket defaults */ 511 /* Read socket defaults */
509 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz) ); 512 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz) );
510 if (sz != sizeof(bool)) 513 if (sz != sizeof(bool))
511 { 514 {
518 bool = 0; 521 bool = 0;
519 522
520 /* Set the option to the socket */ 523 /* Set the option to the socket */
521 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, sizeof(bool)) ); 524 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, sizeof(bool)) );
522 525
523 if (TRACE_BOOL(SCTP_LEVEL)) { 526 if (TRACE_BOOL(ANNOYING)) {
524 /* Check new values */ 527 /* Check new values */
525 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz) ); 528 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz) );
526 fd_log_debug( "New SCTP_EXPLICIT_EOR value : %s", bool ? "true" : "false"); 529 fd_log_debug( "New SCTP_EXPLICIT_EOR value : %s", bool ? "true" : "false");
527 } 530 }
528 } 531 }
529 #else /* SCTP_EXPLICIT_EOR */ 532 #else /* SCTP_EXPLICIT_EOR */
530 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_EXPLICIT_EOR"); 533 TRACE_DEBUG(ANNOYING, "Skipping SCTP_EXPLICIT_EOR");
531 #endif /* SCTP_EXPLICIT_EOR */ 534 #endif /* SCTP_EXPLICIT_EOR */
532 535
533 /* 536 /*
534 SCTP_REUSE_PORT share one listening port with several sockets 537 SCTP_REUSE_PORT share one listening port with several sockets
535 SCTP_EVENT same as EVENTS ?
536 */ 538 */
537 539
540 #ifndef OLD_SCTP_SOCKET_API
541 #ifdef SCTP_EVENT
542 {
543 /* Subscribe to the following events */
544 int events_I_want[] = {
545 #ifdef SCTP_ASSOC_CHANGE
546 /* SCTP_ASSOC_CHANGE, */
547 #endif
548 #ifdef SCTP_PEER_ADDR_CHANGE
549 SCTP_PEER_ADDR_CHANGE,
550 #endif
551 #ifdef SCTP_REMOTE_ERROR
552 SCTP_REMOTE_ERROR,
553 #endif
554 #ifdef SCTP_SEND_FAILED_EVENT
555 SCTP_SEND_FAILED_EVENT,
556 #endif
557 #ifdef SCTP_SHUTDOWN_EVENT
558 SCTP_SHUTDOWN_EVENT,
559 #endif
560 #ifdef SCTP_ADAPTATION_INDICATION
561 /* SCTP_ADAPTATION_INDICATION, */
562 #endif
563 #ifdef SCTP_PARTIAL_DELIVERY_EVENT
564 /* SCTP_PARTIAL_DELIVERY_EVENT, */
565 #endif
566 #ifdef SCTP_AUTHENTICATION_EVENT
567 /* SCTP_AUTHENTICATION_EVENT, */
568 #endif
569 #ifdef SCTP_SENDER_DRY_EVENT
570 /* SCTP_SENDER_DRY_EVENT, */
571 #endif
572 0
573 };
574 int i;
575
576 struct sctp_event event;
577
578 for (i = 0; i < (sizeof(events_I_want) / sizeof(events_I_want[0]) - 1; i++) {
579 memset(&event, 0, sizeof(event));
580 event.se_type = events_I_want[i];
581 event.se_on = 1;
582
583 /* Set the option to the socket */
584 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) );
585 }
586 }
587 #else /* SCTP_EVENT */
588 TRACE_DEBUG(ANNOYING, "Skipping SCTP_EVENT");
589 #endif /* SCTP_EVENT */
590
591
592 #ifdef SCTP_RECVRCVINFO /* Replaces SCTP_SNDRCV */
593 {
594 int bool = 1;
595
596 /* Set the option to the socket */
597 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_RECVRCVINFO, &bool, sizeof(bool)) );
598
599 }
600 #else /* SCTP_RECVRCVINFO */
601 TRACE_DEBUG(ANNOYING, "Skipping SCTP_RECVRCVINFO");
602 #endif /* SCTP_RECVRCVINFO */
603
604
605 #endif /* OLD_SCTP_SOCKET_API */
606
607 /*
608 SCTP_RECVNXTINFO
609
610 SCTP_DEFAULT_SNDINFO : send defaults
611 SCTP_DEFAULT_PRINFO : default PR-SCTP
612 */
613
614
538 /* In case of no_ip4, force the v6only option */ 615 /* In case of no_ip4, force the v6only option */
539 #ifdef IPV6_V6ONLY 616 #ifdef IPV6_V6ONLY
540 if (fd_g_config->cnf_flags.no_ip4) { 617 if (fd_g_config->cnf_flags.no_ip4) {
541 int opt = 1; 618 int opt = 1;
542 CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt))); 619 CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
557 /* Set the ASCONF option */ 634 /* Set the ASCONF option */
558 #ifdef SCTP_AUTO_ASCONF 635 #ifdef SCTP_AUTO_ASCONF
559 if (bound_to_default) { 636 if (bound_to_default) {
560 int asconf; 637 int asconf;
561 638
562 if (TRACE_BOOL(SCTP_LEVEL)) { 639 if (TRACE_BOOL(ANNOYING)) {
563 socklen_t sz; 640 socklen_t sz;
564 641
565 sz = sizeof(asconf); 642 sz = sizeof(asconf);
566 /* Read socket defaults */ 643 /* Read socket defaults */
567 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz) ); 644 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz) );
576 asconf = 1; /* allow automatic use of added or removed addresses in the association (for bound-all sockets) */ 653 asconf = 1; /* allow automatic use of added or removed addresses in the association (for bound-all sockets) */
577 654
578 /* Set the option to the socket */ 655 /* Set the option to the socket */
579 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf)) ); 656 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf)) );
580 657
581 if (TRACE_BOOL(SCTP_LEVEL)) { 658 if (TRACE_BOOL(ANNOYING)) {
582 socklen_t sz = sizeof(asconf); 659 socklen_t sz = sizeof(asconf);
583 /* Check new values */ 660 /* Check new values */
584 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz) ); 661 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz) );
585 fd_log_debug( "New SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false"); 662 fd_log_debug( "New SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false");
586 } 663 }
587 } 664 }
588 #else /* SCTP_AUTO_ASCONF */ 665 #else /* SCTP_AUTO_ASCONF */
589 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_AUTO_ASCONF"); 666 TRACE_DEBUG(ANNOYING, "Skipping SCTP_AUTO_ASCONF");
590 #endif /* SCTP_AUTO_ASCONF */ 667 #endif /* SCTP_AUTO_ASCONF */
591 668
592 return 0; 669 return 0;
593 } 670 }
594 671
1002 int fd_sctp_sendstr(struct cnxctx * conn, uint16_t strid, uint8_t * buf, size_t len) 1079 int fd_sctp_sendstr(struct cnxctx * conn, uint16_t strid, uint8_t * buf, size_t len)
1003 { 1080 {
1004 struct msghdr mhdr; 1081 struct msghdr mhdr;
1005 struct iovec iov; 1082 struct iovec iov;
1006 struct cmsghdr *hdr; 1083 struct cmsghdr *hdr;
1084 #ifdef OLD_SCTP_SOCKET_API
1007 struct sctp_sndrcvinfo *sndrcv; 1085 struct sctp_sndrcvinfo *sndrcv;
1008 uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; 1086 uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1087 #else /* OLD_SCTP_SOCKET_API */
1088 struct sctp_sndinfo *sndinf;
1089 uint8_t anci[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
1090 #endif /* OLD_SCTP_SOCKET_API */
1009 ssize_t ret; 1091 ssize_t ret;
1010 int timedout = 0; 1092 int timedout = 0;
1011 1093
1012 TRACE_ENTRY("%p %hu %p %zd", conn, strid, buf, len); 1094 TRACE_ENTRY("%p %hu %p %zd", conn, strid, buf, len);
1013 CHECK_PARAMS(conn && buf && len); 1095 CHECK_PARAMS(conn && buf && len);
1020 iov.iov_base = buf; 1102 iov.iov_base = buf;
1021 iov.iov_len = len; 1103 iov.iov_len = len;
1022 1104
1023 /* Anciliary data: specify SCTP stream */ 1105 /* Anciliary data: specify SCTP stream */
1024 hdr = (struct cmsghdr *)anci; 1106 hdr = (struct cmsghdr *)anci;
1025 sndrcv = (struct sctp_sndrcvinfo *)CMSG_DATA(hdr);
1026 hdr->cmsg_len = sizeof(anci); 1107 hdr->cmsg_len = sizeof(anci);
1027 hdr->cmsg_level = IPPROTO_SCTP; 1108 hdr->cmsg_level = IPPROTO_SCTP;
1109 #ifdef OLD_SCTP_SOCKET_API
1028 hdr->cmsg_type = SCTP_SNDRCV; 1110 hdr->cmsg_type = SCTP_SNDRCV;
1111 sndrcv = (struct sctp_sndrcvinfo *)CMSG_DATA(hdr);
1029 sndrcv->sinfo_stream = strid; 1112 sndrcv->sinfo_stream = strid;
1113 #else /* OLD_SCTP_SOCKET_API */
1114 hdr->cmsg_type = SCTP_SNDINFO;
1115 sndinf = (struct sctp_sndinfo *)CMSG_DATA(hdr);
1116 sndinf->snd_sid = strid;
1117 #endif /* OLD_SCTP_SOCKET_API */
1030 /* note : we could store other data also, for example in .sinfo_ppid for remote peer or in .sinfo_context for errors. */ 1118 /* note : we could store other data also, for example in .sinfo_ppid for remote peer or in .sinfo_context for errors. */
1031 1119
1032 /* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */ 1120 /* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */
1033 1121
1034 mhdr.msg_iov = &iov; 1122 mhdr.msg_iov = &iov;
1082 mhdr.msg_iov = &iov; 1170 mhdr.msg_iov = &iov;
1083 mhdr.msg_iovlen = 1; 1171 mhdr.msg_iovlen = 1;
1084 mhdr.msg_control = &ancidata; 1172 mhdr.msg_control = &ancidata;
1085 mhdr.msg_controllen = sizeof(ancidata); 1173 mhdr.msg_controllen = sizeof(ancidata);
1086 1174
1175 next_message:
1176 datasize = 0;
1177
1087 /* We will loop while all data is not received. */ 1178 /* We will loop while all data is not received. */
1088 incomplete: 1179 incomplete:
1089 while (datasize >= bufsz ) { 1180 while (datasize >= bufsz ) {
1090 /* The buffer is full, enlarge it */ 1181 /* The buffer is full, enlarge it */
1091 bufsz += mempagesz; 1182 bufsz += mempagesz;
1136 1227
1137 TRACE_DEBUG(FULL, "Received %zdb data of notification on socket %d", datasize, conn->cc_socket); 1228 TRACE_DEBUG(FULL, "Received %zdb data of notification on socket %d", datasize, conn->cc_socket);
1138 1229
1139 switch (notif->sn_header.sn_type) { 1230 switch (notif->sn_header.sn_type) {
1140 1231
1141 case SCTP_ASSOC_CHANGE: 1232 case SCTP_ASSOC_CHANGE: /* We should not receive these as we did not subscribe for it */
1142 TRACE_DEBUG(FULL, "Received SCTP_ASSOC_CHANGE notification"); 1233 TRACE_DEBUG(FULL, "Received SCTP_ASSOC_CHANGE notification");
1143 TRACE_DEBUG(SCTP_LEVEL, " state : %hu", notif->sn_assoc_change.sac_state); 1234 TRACE_DEBUG(ANNOYING, " state : %hu", notif->sn_assoc_change.sac_state);
1144 TRACE_DEBUG(SCTP_LEVEL, " error : %hu", notif->sn_assoc_change.sac_error); 1235 TRACE_DEBUG(ANNOYING, " error : %hu", notif->sn_assoc_change.sac_error);
1145 TRACE_DEBUG(SCTP_LEVEL, " instr : %hu", notif->sn_assoc_change.sac_inbound_streams); 1236 TRACE_DEBUG(ANNOYING, " instr : %hu", notif->sn_assoc_change.sac_inbound_streams);
1146 TRACE_DEBUG(SCTP_LEVEL, " outstr : %hu", notif->sn_assoc_change.sac_outbound_streams); 1237 TRACE_DEBUG(ANNOYING, " outstr : %hu", notif->sn_assoc_change.sac_outbound_streams);
1147 1238
1148 *event = FDEVP_CNX_EP_CHANGE; 1239 *event = FDEVP_CNX_EP_CHANGE;
1149 break; 1240 break;
1150 1241
1151 case SCTP_PEER_ADDR_CHANGE: 1242 case SCTP_PEER_ADDR_CHANGE:
1152 TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification"); 1243 TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification");
1153 /* TRACE_sSA(FD_LOG_DEBUG, SCTP_LEVEL, " intf_change : ", &(notif->sn_paddr_change.spc_aaddr), NI_NUMERICHOST | NI_NUMERICSERV, "" ); */ 1244 /* TRACE_sSA(FD_LOG_DEBUG, ANNOYING, " intf_change : ", &(notif->sn_paddr_change.spc_aaddr), NI_NUMERICHOST | NI_NUMERICSERV, "" ); */
1154 TRACE_DEBUG(SCTP_LEVEL, " state : %d", notif->sn_paddr_change.spc_state); 1245 TRACE_DEBUG(ANNOYING, " state : %d", notif->sn_paddr_change.spc_state);
1155 TRACE_DEBUG(SCTP_LEVEL, " error : %d", notif->sn_paddr_change.spc_error); 1246 TRACE_DEBUG(ANNOYING, " error : %d", notif->sn_paddr_change.spc_error);
1156 1247
1157 *event = FDEVP_CNX_EP_CHANGE; 1248 *event = FDEVP_CNX_EP_CHANGE;
1158 break; 1249 break;
1159 1250
1160 case SCTP_SEND_FAILED: 1251 case SCTP_REMOTE_ERROR:
1161 TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED notification"); 1252 TRACE_DEBUG(FULL, "Received SCTP_REMOTE_ERROR notification");
1162 TRACE_DEBUG(SCTP_LEVEL, " len : %hu", notif->sn_send_failed.ssf_length); 1253 TRACE_DEBUG(ANNOYING, " err : %hu", ntohs(notif->sn_remote_error.sre_error));
1163 TRACE_DEBUG(SCTP_LEVEL, " err : %d", notif->sn_send_failed.ssf_error); 1254 TRACE_DEBUG(ANNOYING, " len : %hu", ntohs(notif->sn_remote_error.sre_length));
1164 1255
1165 *event = FDEVP_CNX_ERROR; 1256 *event = FDEVP_CNX_ERROR;
1166 break; 1257 break;
1167 1258
1168 case SCTP_REMOTE_ERROR: 1259 #ifdef OLD_SCTP_SOCKET_API
1169 TRACE_DEBUG(FULL, "Received SCTP_REMOTE_ERROR notification"); 1260 case SCTP_SEND_FAILED:
1170 TRACE_DEBUG(SCTP_LEVEL, " err : %hu", ntohs(notif->sn_remote_error.sre_error)); 1261 TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED notification");
1171 TRACE_DEBUG(SCTP_LEVEL, " len : %hu", ntohs(notif->sn_remote_error.sre_length)); 1262 TRACE_DEBUG(ANNOYING, " len : %hu", notif->sn_send_failed.ssf_length);
1263 TRACE_DEBUG(ANNOYING, " err : %d", notif->sn_send_failed.ssf_error);
1172 1264
1173 *event = FDEVP_CNX_ERROR; 1265 *event = FDEVP_CNX_ERROR;
1174 break; 1266 break;
1175 1267 #else /* OLD_SCTP_SOCKET_API */
1268 case SCTP_SEND_FAILED_EVENT:
1269 TRACE_DEBUG(FULL, "Received SCTP_SEND_FAILED_EVENT notification");
1270 *event = FDEVP_CNX_ERROR;
1271 break;
1272 #endif /* OLD_SCTP_SOCKET_API */
1176 case SCTP_SHUTDOWN_EVENT: 1273 case SCTP_SHUTDOWN_EVENT:
1177 TRACE_DEBUG(FULL, "Received SCTP_SHUTDOWN_EVENT notification"); 1274 TRACE_DEBUG(FULL, "Received SCTP_SHUTDOWN_EVENT notification");
1178 1275
1179 *event = FDEVP_CNX_SHUTDOWN; 1276 *event = FDEVP_CNX_SHUTDOWN;
1180 break; 1277 break;
1278
1279 #ifndef OLD_SCTP_SOCKET_API
1280 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
1281 TRACE_DEBUG(INFO, "Received SCTP_NOTIFICATIONS_STOPPED_EVENT notification, marking the association in error state");
1282 *event = FDEVP_CNX_ERROR;
1283 break;
1284 #endif /* OLD_SCTP_SOCKET_API */
1181 1285
1182 default: 1286 default:
1183 TRACE_DEBUG(FULL, "Received unknown notification %d, assume error", notif->sn_header.sn_type); 1287 TRACE_DEBUG(FULL, "Received unknown notification %d, ignored", notif->sn_header.sn_type);
1184 *event = FDEVP_CNX_ERROR; 1288 goto next_message;
1185 } 1289 }
1186 1290
1187 free(data); 1291 free(data);
1188 return 0; 1292 return 0;
1189 } 1293 }
1193 *buf = data; 1297 *buf = data;
1194 *len = datasize; 1298 *len = datasize;
1195 1299
1196 if (strid) { 1300 if (strid) {
1197 struct cmsghdr *hdr; 1301 struct cmsghdr *hdr;
1302 #ifdef OLD_SCTP_SOCKET_API
1198 struct sctp_sndrcvinfo *sndrcv; 1303 struct sctp_sndrcvinfo *sndrcv;
1304 #else /* OLD_SCTP_SOCKET_API */
1305 struct sctp_rcvinfo *rcvinf;
1306 #endif /* OLD_SCTP_SOCKET_API */
1199 1307
1200 /* Handle the anciliary data */ 1308 /* Handle the anciliary data */
1201 for (hdr = CMSG_FIRSTHDR(&mhdr); hdr; hdr = CMSG_NXTHDR(&mhdr, hdr)) { 1309 for (hdr = CMSG_FIRSTHDR(&mhdr); hdr; hdr = CMSG_NXTHDR(&mhdr, hdr)) {
1202 1310
1203 /* We deal only with anciliary data at SCTP level */ 1311 /* We deal only with anciliary data at SCTP level */
1204 if (hdr->cmsg_level != IPPROTO_SCTP) { 1312 if (hdr->cmsg_level != IPPROTO_SCTP) {
1205 TRACE_DEBUG(FULL, "Received some anciliary data at level %d, skipped", hdr->cmsg_level); 1313 TRACE_DEBUG(FULL, "Received some anciliary data at level %d, skipped", hdr->cmsg_level);
1206 continue; 1314 continue;
1207 } 1315 }
1208 1316
1317 #ifdef OLD_SCTP_SOCKET_API
1209 /* Also only interested in SCTP_SNDRCV message for the moment */ 1318 /* Also only interested in SCTP_SNDRCV message for the moment */
1210 if (hdr->cmsg_type != SCTP_SNDRCV) { 1319 if (hdr->cmsg_type != SCTP_SNDRCV) {
1211 TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type); 1320 TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
1212 continue; 1321 continue;
1213 } 1322 }
1214 1323
1215 sndrcv = (struct sctp_sndrcvinfo *) CMSG_DATA(hdr); 1324 sndrcv = (struct sctp_sndrcvinfo *) CMSG_DATA(hdr);
1216 if (TRACE_BOOL(SCTP_LEVEL)) { 1325 if (TRACE_BOOL(ANNOYING)) {
1217 fd_log_debug( "Anciliary block IPPROTO_SCTP / SCTP_SNDRCV"); 1326 fd_log_debug( "Anciliary block IPPROTO_SCTP / SCTP_SNDRCV");
1218 fd_log_debug( " sinfo_stream : %hu", sndrcv->sinfo_stream); 1327 fd_log_debug( " sinfo_stream : %hu", sndrcv->sinfo_stream);
1219 fd_log_debug( " sinfo_ssn : %hu", sndrcv->sinfo_ssn); 1328 fd_log_debug( " sinfo_ssn : %hu", sndrcv->sinfo_ssn);
1220 fd_log_debug( " sinfo_flags : %hu", sndrcv->sinfo_flags); 1329 fd_log_debug( " sinfo_flags : %hu", sndrcv->sinfo_flags);
1221 /* fd_log_debug( " sinfo_pr_policy : %hu", sndrcv->sinfo_pr_policy); */ 1330 /* fd_log_debug( " sinfo_pr_policy : %hu", sndrcv->sinfo_pr_policy); */
1225 fd_log_debug( " sinfo_tsn : %u" , sndrcv->sinfo_tsn); 1334 fd_log_debug( " sinfo_tsn : %u" , sndrcv->sinfo_tsn);
1226 fd_log_debug( " sinfo_cumtsn : %u" , sndrcv->sinfo_cumtsn); 1335 fd_log_debug( " sinfo_cumtsn : %u" , sndrcv->sinfo_cumtsn);
1227 } 1336 }
1228 1337
1229 *strid = sndrcv->sinfo_stream; 1338 *strid = sndrcv->sinfo_stream;
1339 #else /* OLD_SCTP_SOCKET_API */
1340 /* Also only interested in SCTP_RCVINFO message for the moment */
1341 if (hdr->cmsg_type != SCTP_RCVINFO) {
1342 TRACE_DEBUG(FULL, "Anciliary block IPPROTO_SCTP / %d, skipped", hdr->cmsg_type);
1343 continue;
1344 }
1345
1346 rcvinf = (struct sctp_rcvinfo *) CMSG_DATA(hdr);
1347
1348 *strid = rcvinf->rcv_sid;
1349 #endif /* OLD_SCTP_SOCKET_API */
1350
1351
1230 } 1352 }
1231 TRACE_DEBUG(FULL, "Received %zdb data on socket %d, stream %hu", datasize, conn->cc_socket, *strid); 1353 TRACE_DEBUG(FULL, "Received %zdb data on socket %d, stream %hu", datasize, conn->cc_socket, *strid);
1232 } else { 1354 } else {
1233 TRACE_DEBUG(FULL, "Received %zdb data on socket %d (stream ignored)", datasize, conn->cc_socket); 1355 TRACE_DEBUG(FULL, "Received %zdb data on socket %d (stream ignored)", datasize, conn->cc_socket);
1234 } 1356 }
"Welcome to our mercurial repository"