comparison freeDiameter/sctp.c @ 171:8ccbfdb49f1c

Adjustments on the SCTP parameters
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 02 Feb 2010 14:36:04 +0900
parents 33d8bed6a9d7
children 9c5dfc6399a4
comparison
equal deleted inserted replaced
170:4b62e4a92828 171:8ccbfdb49f1c
49 #define SCTP_LEVEL FULL 49 #define SCTP_LEVEL FULL
50 #else /* DEBUG_SCTP */ 50 #else /* DEBUG_SCTP */
51 #define SCTP_LEVEL (FCTS + 1) 51 #define SCTP_LEVEL (FCTS + 1)
52 #endif /* DEBUG_SCTP */ 52 #endif /* DEBUG_SCTP */
53 53
54 /* 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 */
56 #define ADJUST_RTX_PARAMS
57 #endif /* USE_DEFAULT_SCTP_RTX_PARAMS */
58
54 /* Pre-binding socket options -- # streams read in config */ 59 /* 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 */
55 static int fd_setsockopt_prebind(int sk) 61 static int fd_setsockopt_prebind(int sk)
56 { 62 {
57 socklen_t sz; 63 socklen_t sz;
58 64
59 TRACE_ENTRY( "%d", sk); 65 TRACE_ENTRY( "%d", sk);
60 66
61 CHECK_PARAMS( sk > 0 ); 67 CHECK_PARAMS( sk > 0 );
62 68
69 #ifdef ADJUST_RTX_PARAMS
70 /* Set the retransmit parameters */
71 #ifdef SCTP_RTOINFO
72 {
73 struct sctp_rtoinfo rtoinfo;
74 memset(&rtoinfo, 0, sizeof(rtoinfo));
75
76 if (TRACE_BOOL(SCTP_LEVEL)) {
77 sz = sizeof(rtoinfo);
78 /* Read socket defaults */
79 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) );
80 if (sz != sizeof(rtoinfo))
81 {
82 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo));
83 return ENOTSUP;
84 }
85 fd_log_debug( "Def SCTP_RTOINFO : srto_initial : %u\n", rtoinfo.srto_initial);
86 fd_log_debug( " srto_min : %u\n", rtoinfo.srto_min);
87 fd_log_debug( " srto_max : %u\n", rtoinfo.srto_max);
88 }
89
90 /* rtoinfo.srto_initial: Estimate of the RTT before it can be measured; keep the default value */
91 rtoinfo.srto_max = 5000; /* Maximum retransmit timer (in ms), we want fast retransmission time. */
92 rtoinfo.srto_min = 1000; /* Value under which the RTO does not descend, we set this value to not conflict with srto_max */
93
94 /* Set the option to the socket */
95 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) );
96
97 if (TRACE_BOOL(SCTP_LEVEL)) {
98 /* Check new values */
99 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) );
100 fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u\n", rtoinfo.srto_initial);
101 fd_log_debug( " srto_max : %u\n", rtoinfo.srto_max);
102 fd_log_debug( " srto_min : %u\n", rtoinfo.srto_min);
103 }
104 }
105 #else /* SCTP_RTOINFO */
106 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_RTOINFO");
107 #endif /* SCTP_RTOINFO */
108
109 /* Set the association parameters: max number of retransmits, ... */
110 #ifdef SCTP_ASSOCINFO
111 {
112 struct sctp_assocparams assoc;
113 memset(&assoc, 0, sizeof(assoc));
114
115 if (TRACE_BOOL(SCTP_LEVEL)) {
116 sz = sizeof(assoc);
117 /* Read socket defaults */
118 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) );
119 if (sz != sizeof(assoc))
120 {
121 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc));
122 return ENOTSUP;
123 }
124 fd_log_debug( "Def SCTP_ASSOCINFO : sasoc_asocmaxrxt : %hu\n", assoc.sasoc_asocmaxrxt);
125 fd_log_debug( " sasoc_number_peer_destinations : %hu\n", assoc.sasoc_number_peer_destinations);
126 fd_log_debug( " sasoc_peer_rwnd : %u\n" , assoc.sasoc_peer_rwnd);
127 fd_log_debug( " sasoc_local_rwnd : %u\n" , assoc.sasoc_local_rwnd);
128 fd_log_debug( " sasoc_cookie_life : %u\n" , assoc.sasoc_cookie_life);
129 }
130
131 assoc.sasoc_asocmaxrxt = 4; /* Maximum number of retransmission attempts: we want fast detection of errors */
132 /* Note that this must remain less than the sum of retransmission parameters of the different paths. */
133
134 /* Set the option to the socket */
135 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc)) );
136
137 if (TRACE_BOOL(SCTP_LEVEL)) {
138 /* Check new values */
139 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) );
140 fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt : %hu\n", assoc.sasoc_asocmaxrxt);
141 fd_log_debug( " sasoc_number_peer_destinations : %hu\n", assoc.sasoc_number_peer_destinations);
142 fd_log_debug( " sasoc_peer_rwnd : %u\n" , assoc.sasoc_peer_rwnd);
143 fd_log_debug( " sasoc_local_rwnd : %u\n" , assoc.sasoc_local_rwnd);
144 fd_log_debug( " sasoc_cookie_life : %u\n" , assoc.sasoc_cookie_life);
145 }
146 }
147 #else /* SCTP_ASSOCINFO */
148 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_ASSOCINFO");
149 #endif /* SCTP_ASSOCINFO */
150 #endif /* ADJUST_RTX_PARAMS */
151
152 /* Set the INIT parameters, such as number of streams */
153 #ifdef SCTP_INITMSG
154 {
155 struct sctp_initmsg init;
156 memset(&init, 0, sizeof(init));
157
158 if (TRACE_BOOL(SCTP_LEVEL)) {
159 sz = sizeof(init);
160
161 /* Read socket defaults */
162 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) );
163 if (sz != sizeof(init))
164 {
165 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init));
166 return ENOTSUP;
167 }
168 fd_log_debug( "Def SCTP_INITMSG : sinit_num_ostreams : %hu\n", init.sinit_num_ostreams);
169 fd_log_debug( " sinit_max_instreams : %hu\n", init.sinit_max_instreams);
170 fd_log_debug( " sinit_max_attempts : %hu\n", init.sinit_max_attempts);
171 fd_log_debug( " sinit_max_init_timeo : %hu\n", init.sinit_max_init_timeo);
172 }
173
174 /* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters, but we don't care (best effort) */
175 init.sinit_num_ostreams = fd_g_config->cnf_sctp_str; /* desired number of outgoing streams */
176 init.sinit_max_init_timeo = CNX_TIMEOUT * 1000;
177
178 /* Set the option to the socket */
179 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)) );
180
181 if (TRACE_BOOL(SCTP_LEVEL)) {
182 /* Check new values */
183 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) );
184 fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams : %hu\n", init.sinit_num_ostreams);
185 fd_log_debug( " sinit_max_instreams : %hu\n", init.sinit_max_instreams);
186 fd_log_debug( " sinit_max_attempts : %hu\n", init.sinit_max_attempts);
187 fd_log_debug( " sinit_max_init_timeo : %hu\n", init.sinit_max_init_timeo);
188 }
189 }
190 #else /* SCTP_INITMSG */
191 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_INITMSG");
192 #endif /* SCTP_INITMSG */
193
194 /* The SO_LINGER option will be reset if we want to perform SCTP ABORT */
195 #ifdef SO_LINGER
196 {
197 struct linger linger;
198 memset(&linger, 0, sizeof(linger));
199
200 if (TRACE_BOOL(SCTP_LEVEL)) {
201 sz = sizeof(linger);
202 /* Read socket defaults */
203 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) );
204 if (sz != sizeof(linger))
205 {
206 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger));
207 return ENOTSUP;
208 }
209 fd_log_debug( "Def SO_LINGER : l_onoff : %d\n", linger.l_onoff);
210 fd_log_debug( " l_linger : %d\n", linger.l_linger);
211 }
212
213 linger.l_onoff = 0; /* Do not activate the linger */
214 linger.l_linger = 0; /* Ignored, but it would mean : Return immediately when closing (=> abort) (graceful shutdown in background) */
215
216 /* Set the option */
217 CHECK_SYS( setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) );
218
219 if (TRACE_BOOL(SCTP_LEVEL)) {
220 /* Check new values */
221 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) );
222 fd_log_debug( "New SO_LINGER : l_onoff : %d\n", linger.l_onoff);
223 fd_log_debug( " l_linger : %d\n", linger.l_linger);
224 }
225 }
226 #else /* SO_LINGER */
227 TRACE_DEBUG(SCTP_LEVEL, "Skipping SO_LINGER");
228 #endif /* SO_LINGER */
229
230 /* Set the NODELAY option (Nagle-like algorithm) */
231 #ifdef SCTP_NODELAY
232 {
233 int nodelay;
234
235 if (TRACE_BOOL(SCTP_LEVEL)) {
236 sz = sizeof(nodelay);
237 /* Read socket defaults */
238 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) );
239 if (sz != sizeof(nodelay))
240 {
241 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay));
242 return ENOTSUP;
243 }
244 fd_log_debug( "Def SCTP_NODELAY value : %s\n", nodelay ? "true" : "false");
245 }
246
247 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). */
248
249 /* Set the option to the socket */
250 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)) );
251
252 if (TRACE_BOOL(SCTP_LEVEL)) {
253 /* Check new values */
254 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) );
255 fd_log_debug( "New SCTP_NODELAY value : %s\n", nodelay ? "true" : "false");
256 }
257 }
258 #else /* SCTP_NODELAY */
259 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_NODELAY");
260 #endif /* SCTP_NODELAY */
261
262 /*
263 SO_RCVBUF size of receiver window
264 SO_SNDBUF size of pending data to send
265 SCTP_AUTOCLOSE for one-to-many only
266 SCTP_PRIMARY_ADDR use this address as primary locally
267 SCTP_ADAPTATION_LAYER set adaptation layer indication, we don't use this
268 */
269
270 /* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */
271 #ifdef SCTP_DISABLE_FRAGMENTS
272 {
273 int nofrag;
274
275 if (TRACE_BOOL(SCTP_LEVEL)) {
276 sz = sizeof(nofrag);
277 /* Read socket defaults */
278 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) );
279 if (sz != sizeof(nofrag))
280 {
281 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag));
282 return ENOTSUP;
283 }
284 fd_log_debug( "Def SCTP_DISABLE_FRAGMENTS value : %s\n", nofrag ? "true" : "false");
285 }
286
287 nofrag = 0; /* We turn ON the fragmentation, since Diameter messages & TLS messages can be quite large. */
288
289 /* Set the option to the socket */
290 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag)) );
291
292 if (TRACE_BOOL(SCTP_LEVEL)) {
293 /* Check new values */
294 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) );
295 fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s\n", nofrag ? "true" : "false");
296 }
297 }
298 #else /* SCTP_DISABLE_FRAGMENTS */
299 # error "TLS requires support of SCTP_DISABLE_FRAGMENTS"
300 #endif /* SCTP_DISABLE_FRAGMENTS */
301
302 /* SCTP_PEER_ADDR_PARAMS control heartbeat per peer address. We set it as a default for all addresses in the association; not sure if it works ... */
303 #ifdef SCTP_PEER_ADDR_PARAMS
304 {
305 struct sctp_paddrparams parms;
306 memset(&parms, 0, sizeof(parms));
307
308 if (TRACE_BOOL(SCTP_LEVEL)) {
309 sz = sizeof(parms);
310
311 /* Read socket defaults */
312 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz) );
313 if (sz != sizeof(parms))
314 {
315 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(parms));
316 return ENOTSUP;
317 }
318 fd_log_debug( "Def SCTP_PEER_ADDR_PARAMS : spp_hbinterval : %u\n", parms.spp_hbinterval);
319 fd_log_debug( " spp_pathmaxrxt : %hu\n", parms.spp_pathmaxrxt);
320 fd_log_debug( " spp_pathmtu : %u\n", parms.spp_pathmtu);
321 fd_log_debug( " spp_flags : %x\n", parms.spp_flags);
322 // fd_log_debug( " spp_ipv6_flowlabel: %u\n", parms.spp_ipv6_flowlabel);
323 // fd_log_debug( " spp_ipv4_tos : %hhu\n",parms.spp_ipv4_tos);
324 }
325
326 parms.spp_flags = SPP_HB_ENABLE; /* Enable heartbeat for the associtation */
327 #ifdef SPP_PMTUD_ENABLE
328 parms.spp_flags |= SPP_PMTUD_ENABLE; /* also enable path MTU discovery mechanism */
329 #endif /* SPP_PMTUD_ENABLE */
330
331 #ifdef ADJUST_RTX_PARAMS
332 parms.spp_hbinterval = 6000; /* Send an heartbeat every 6 seconds to quickly start retransmissions */
333 /* parms.spp_pathmaxrxt : max nbr of restransmissions on this address. There is a relationship with sasoc_asocmaxrxt, so we leave the default here */
334 #endif /* ADJUST_RTX_PARAMS */
335
336 /* Set the option to the socket */
337 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, sizeof(parms)) );
338
339 if (TRACE_BOOL(SCTP_LEVEL)) {
340 /* Check new values */
341 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &parms, &sz) );
342 fd_log_debug( "New SCTP_PEER_ADDR_PARAMS : spp_hbinterval : %u\n", parms.spp_hbinterval);
343 fd_log_debug( " spp_pathmaxrxt : %hu\n", parms.spp_pathmaxrxt);
344 fd_log_debug( " spp_pathmtu : %u\n", parms.spp_pathmtu);
345 fd_log_debug( " spp_flags : %x\n", parms.spp_flags);
346 // fd_log_debug( " spp_ipv6_flowlabel: %u\n", parms.spp_ipv6_flowlabel);
347 // fd_log_debug( " spp_ipv4_tos : %hhu\n",parms.spp_ipv4_tos);
348 }
349 }
350 #else /* SCTP_PEER_ADDR_PARAMS */
351 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_PEER_ADDR_PARAMS");
352 #endif /* SCTP_PEER_ADDR_PARAMS */
353
354 /*
355 SCTP_DEFAULT_SEND_PARAM parameters for the sendto() call, we don't use it.
356 */
357
63 /* Subscribe to some notifications */ 358 /* Subscribe to some notifications */
359 #ifdef SCTP_EVENTS
64 { 360 {
65 struct sctp_event_subscribe event; 361 struct sctp_event_subscribe event;
66 362
67 memset(&event, 0, sizeof(event)); 363 memset(&event, 0, sizeof(event));
68 event.sctp_data_io_event = 1; /* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */ 364 event.sctp_data_io_event = 1; /* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */
95 fd_log_debug( " sctp_shutdown_event : %hhu\n", event.sctp_shutdown_event); 391 fd_log_debug( " sctp_shutdown_event : %hhu\n", event.sctp_shutdown_event);
96 fd_log_debug( " sctp_partial_delivery_event : %hhu\n", event.sctp_partial_delivery_event); 392 fd_log_debug( " sctp_partial_delivery_event : %hhu\n", event.sctp_partial_delivery_event);
97 fd_log_debug( " sctp_adaptation_layer_event : %hhu\n", event.sctp_adaptation_layer_event); 393 fd_log_debug( " sctp_adaptation_layer_event : %hhu\n", event.sctp_adaptation_layer_event);
98 // fd_log_debug( " sctp_authentication_event : %hhu\n", event.sctp_authentication_event); 394 // fd_log_debug( " sctp_authentication_event : %hhu\n", event.sctp_authentication_event);
99 } 395 }
100 396 }
101 } 397 #else /* SCTP_EVENTS */
102 398 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_EVENTS");
103 /* Set the INIT parameters, such as number of streams */ 399 #endif /* SCTP_EVENTS */
104 { 400
105 struct sctp_initmsg init; 401 /* Set the v4 mapped addresses option */
106 memset(&init, 0, sizeof(init)); 402 #ifdef SCTP_I_WANT_MAPPED_V4_ADDR
107 403 {
108 if (TRACE_BOOL(SCTP_LEVEL)) { 404 int v4mapped;
109 sz = sizeof(init); 405
110 406 if (TRACE_BOOL(SCTP_LEVEL)) {
407 sz = sizeof(v4mapped);
111 /* Read socket defaults */ 408 /* Read socket defaults */
112 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) ); 409 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) );
113 if (sz != sizeof(init)) 410 if (sz != sizeof(v4mapped))
114 { 411 {
115 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init)); 412 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped));
116 return ENOTSUP; 413 return ENOTSUP;
117 } 414 }
118 fd_log_debug( "Def SCTP_INITMSG : sinit_num_ostreams : %hu\n", init.sinit_num_ostreams); 415 fd_log_debug( "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s\n", v4mapped ? "true" : "false");
119 fd_log_debug( " sinit_max_instreams : %hu\n", init.sinit_max_instreams); 416 }
120 fd_log_debug( " sinit_max_attempts : %hu\n", init.sinit_max_attempts); 417
121 fd_log_debug( " sinit_max_init_timeo : %hu\n", init.sinit_max_init_timeo); 418 #ifndef SCTP_USE_MAPPED_ADDRESSES
122 } 419 v4mapped = 0; /* We don't want v4 mapped addresses */
123 420 #else /* SCTP_USE_MAPPED_ADDRESSES */
124 /* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters */ 421 v4mapped = 1; /* but we may have to, otherwise the bind fails in some environments */
125 init.sinit_num_ostreams = fd_g_config->cnf_sctp_str; /* desired number of outgoing streams */ 422 #endif /* SCTP_USE_MAPPED_ADDRESSES */
126 init.sinit_max_init_timeo = CNX_TIMEOUT * 1000; 423
127
128 /* Set the option to the socket */ 424 /* Set the option to the socket */
129 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)) ); 425 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped)) );
130 426
131 if (TRACE_BOOL(SCTP_LEVEL)) { 427 if (TRACE_BOOL(SCTP_LEVEL)) {
132 /* Check new values */ 428 /* Check new values */
133 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) ); 429 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) );
134 fd_log_debug( "New SCTP_INITMSG : sinit_num_ostreams : %hu\n", init.sinit_num_ostreams); 430 fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s\n", v4mapped ? "true" : "false");
135 fd_log_debug( " sinit_max_instreams : %hu\n", init.sinit_max_instreams); 431 }
136 fd_log_debug( " sinit_max_attempts : %hu\n", init.sinit_max_attempts); 432 }
137 fd_log_debug( " sinit_max_init_timeo : %hu\n", init.sinit_max_init_timeo); 433 #else /* SCTP_I_WANT_MAPPED_V4_ADDR */
138 } 434 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
139 } 435 #endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
140 436
141 /* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */ 437 /*
142 #ifdef SCTP_DISABLE_FRAGMENTS 438 SCTP_MAXSEG max size of fragmented segments -- bound to PMTU
143 { 439 SCTP_HMAC_IDENT authentication algorithms
144 int nofrag; 440 SCTP_AUTH_ACTIVE_KEY set the active key
145 441 SCTP_DELAYED_SACK control delayed acks
146 if (TRACE_BOOL(SCTP_LEVEL)) { 442 */
147 sz = sizeof(nofrag); 443
148 /* Read socket defaults */
149 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) );
150 if (sz != sizeof(nofrag))
151 {
152 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag));
153 return ENOTSUP;
154 }
155 fd_log_debug( "Def SCTP_DISABLE_FRAGMENTS value : %s\n", nofrag ? "true" : "false");
156 }
157
158 nofrag = 0; /* We turn ON the fragmentation */
159
160 /* Set the option to the socket */
161 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag)) );
162
163 if (TRACE_BOOL(SCTP_LEVEL)) {
164 /* Check new values */
165 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) );
166 fd_log_debug( "New SCTP_DISABLE_FRAGMENTS value : %s\n", nofrag ? "true" : "false");
167 }
168 }
169 #else /* SCTP_DISABLE_FRAGMENTS */
170 # error "TLS requires support of SCTP_DISABLE_FRAGMENTS"
171 #endif /* SCTP_DISABLE_FRAGMENTS */
172
173
174 /* Set the RETRANSMIT parameters */
175 #ifdef SCTP_RTOINFO
176 {
177 struct sctp_rtoinfo rtoinfo;
178 memset(&rtoinfo, 0, sizeof(rtoinfo));
179
180 if (TRACE_BOOL(SCTP_LEVEL)) {
181 sz = sizeof(rtoinfo);
182 /* Read socket defaults */
183 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) );
184 if (sz != sizeof(rtoinfo))
185 {
186 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo));
187 return ENOTSUP;
188 }
189 fd_log_debug( "Def SCTP_RTOINFO : srto_initial : %u\n", rtoinfo.srto_initial);
190 fd_log_debug( " srto_max : %u\n", rtoinfo.srto_max);
191 fd_log_debug( " srto_min : %u\n", rtoinfo.srto_min);
192 }
193
194 rtoinfo.srto_max = fd_g_config->cnf_timer_tw * 500 - 1000; /* Maximum retransmit timer (in ms) (set to Tw / 2 - 1) */
195
196 /* Set the option to the socket */
197 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) );
198
199 if (TRACE_BOOL(SCTP_LEVEL)) {
200 /* Check new values */
201 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) );
202 fd_log_debug( "New SCTP_RTOINFO : srto_initial : %u\n", rtoinfo.srto_initial);
203 fd_log_debug( " srto_max : %u\n", rtoinfo.srto_max);
204 fd_log_debug( " srto_min : %u\n", rtoinfo.srto_min);
205 }
206 }
207 #else /* SCTP_RTOINFO */
208 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_RTOINFO");
209 #endif /* SCTP_RTOINFO */
210
211 /* Set the ASSOCIATION parameters */
212 #ifdef SCTP_ASSOCINFO
213 {
214 struct sctp_assocparams assoc;
215 memset(&assoc, 0, sizeof(assoc));
216
217 if (TRACE_BOOL(SCTP_LEVEL)) {
218 sz = sizeof(assoc);
219 /* Read socket defaults */
220 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) );
221 if (sz != sizeof(assoc))
222 {
223 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc));
224 return ENOTSUP;
225 }
226 fd_log_debug( "Def SCTP_ASSOCINFO : sasoc_asocmaxrxt : %hu\n", assoc.sasoc_asocmaxrxt);
227 fd_log_debug( " sasoc_number_peer_destinations : %hu\n", assoc.sasoc_number_peer_destinations);
228 fd_log_debug( " sasoc_peer_rwnd : %u\n" , assoc.sasoc_peer_rwnd);
229 fd_log_debug( " sasoc_local_rwnd : %u\n" , assoc.sasoc_local_rwnd);
230 fd_log_debug( " sasoc_cookie_life : %u\n" , assoc.sasoc_cookie_life);
231 }
232
233 assoc.sasoc_asocmaxrxt = 8; /* Maximum retransmission attempts: we want fast detection of errors */
234
235 /* Set the option to the socket */
236 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc)) );
237
238 if (TRACE_BOOL(SCTP_LEVEL)) {
239 /* Check new values */
240 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) );
241 fd_log_debug( "New SCTP_ASSOCINFO : sasoc_asocmaxrxt : %hu\n", assoc.sasoc_asocmaxrxt);
242 fd_log_debug( " sasoc_number_peer_destinations : %hu\n", assoc.sasoc_number_peer_destinations);
243 fd_log_debug( " sasoc_peer_rwnd : %u\n" , assoc.sasoc_peer_rwnd);
244 fd_log_debug( " sasoc_local_rwnd : %u\n" , assoc.sasoc_local_rwnd);
245 fd_log_debug( " sasoc_cookie_life : %u\n" , assoc.sasoc_cookie_life);
246 }
247 }
248 #else /* SCTP_ASSOCINFO */
249 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_ASSOCINFO");
250 #endif /* SCTP_ASSOCINFO */
251
252
253 /* The SO_LINGER option will be re-set if we want to perform SCTP ABORT */
254 #ifdef SO_LINGER
255 {
256 struct linger linger;
257 memset(&linger, 0, sizeof(linger));
258
259 if (TRACE_BOOL(SCTP_LEVEL)) {
260 sz = sizeof(linger);
261 /* Read socket defaults */
262 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) );
263 if (sz != sizeof(linger))
264 {
265 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger));
266 return ENOTSUP;
267 }
268 fd_log_debug( "Def SO_LINGER : l_onoff : %d\n", linger.l_onoff);
269 fd_log_debug( " l_linger : %d\n", linger.l_linger);
270 }
271
272 linger.l_onoff = 0; /* Do not activate the linger */
273 linger.l_linger = 0; /* Return immediately when closing (=> abort) */
274
275 /* Set the option */
276 CHECK_SYS( setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) );
277
278 if (TRACE_BOOL(SCTP_LEVEL)) {
279 /* Check new values */
280 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) );
281 fd_log_debug( "New SO_LINGER : l_onoff : %d\n", linger.l_onoff);
282 fd_log_debug( " l_linger : %d\n", linger.l_linger);
283 }
284 }
285 #else /* SO_LINGER */
286 TRACE_DEBUG(SCTP_LEVEL, "Skipping SO_LINGER");
287 #endif /* SO_LINGER */
288
289 /* Set the NODELAY option (Nagle-like algorithm) */
290 #ifdef SCTP_NODELAY
291 {
292 int nodelay;
293
294 if (TRACE_BOOL(SCTP_LEVEL)) {
295 sz = sizeof(nodelay);
296 /* Read socket defaults */
297 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) );
298 if (sz != sizeof(nodelay))
299 {
300 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay));
301 return ENOTSUP;
302 }
303 fd_log_debug( "Def SCTP_NODELAY value : %s\n", nodelay ? "true" : "false");
304 }
305
306 nodelay = 0; /* We turn ON the Nagle algorithm (probably the default already) */
307
308 /* Set the option to the socket */
309 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)) );
310
311 if (TRACE_BOOL(SCTP_LEVEL)) {
312 /* Check new values */
313 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) );
314 fd_log_debug( "New SCTP_NODELAY value : %s\n", nodelay ? "true" : "false");
315 }
316 }
317 #else /* SCTP_NODELAY */
318 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_NODELAY");
319 #endif /* SCTP_NODELAY */
320 444
321 /* Set the interleaving option */ 445 /* Set the interleaving option */
322 #ifdef SCTP_FRAGMENT_INTERLEAVE 446 #ifdef SCTP_FRAGMENT_INTERLEAVE
323 { 447 {
324 int interleave; 448 int interleave;
352 } 476 }
353 #else /* SCTP_FRAGMENT_INTERLEAVE */ 477 #else /* SCTP_FRAGMENT_INTERLEAVE */
354 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_FRAGMENT_INTERLEAVE"); 478 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_FRAGMENT_INTERLEAVE");
355 #endif /* SCTP_FRAGMENT_INTERLEAVE */ 479 #endif /* SCTP_FRAGMENT_INTERLEAVE */
356 480
357 /* Set the v4 mapped addresses option */ 481 /*
358 #ifdef SCTP_I_WANT_MAPPED_V4_ADDR
359 {
360 int v4mapped;
361
362 if (TRACE_BOOL(SCTP_LEVEL)) {
363 sz = sizeof(v4mapped);
364 /* Read socket defaults */
365 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) );
366 if (sz != sizeof(v4mapped))
367 {
368 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped));
369 return ENOTSUP;
370 }
371 fd_log_debug( "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s\n", v4mapped ? "true" : "false");
372 }
373
374 #ifndef SCTP_USE_MAPPED_ADDRESSES
375 v4mapped = 0; /* We don't want v4 mapped addresses */
376 #else /* SCTP_USE_MAPPED_ADDRESSES */
377 v4mapped = 1; /* but we may have to, otherwise the bind fails in some environments */
378 #endif /* SCTP_USE_MAPPED_ADDRESSES */
379
380 /* Set the option to the socket */
381 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped)) );
382
383 if (TRACE_BOOL(SCTP_LEVEL)) {
384 /* Check new values */
385 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) );
386 fd_log_debug( "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s\n", v4mapped ? "true" : "false");
387 }
388 }
389 #else /* SCTP_I_WANT_MAPPED_V4_ADDR */
390 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR");
391 #endif /* SCTP_I_WANT_MAPPED_V4_ADDR */
392
393
394 /* Other settable options (draft-ietf-tsvwg-sctpsocket-17):
395 SO_RCVBUF size of receiver window
396 SO_SNDBUF size of pending data to send
397 SCTP_AUTOCLOSE for one-to-many only
398 SCTP_SET_PEER_PRIMARY_ADDR ask remote peer to use this local address as primary
399 SCTP_PRIMARY_ADDR use this address as primary locally
400 SCTP_ADAPTATION_LAYER set adaptation layer indication
401 SCTP_PEER_ADDR_PARAMS control heartbeat per peer address
402 SCTP_DEFAULT_SEND_PARAM parameters for the sendto() call
403 SCTP_MAXSEG max size of fragmented segments -- bound to PMTU
404 SCTP_AUTH_CHUNK request authentication of some type of chunk
405 SCTP_HMAC_IDENT authentication algorithms
406 SCTP_AUTH_KEY set a shared key
407 SCTP_AUTH_ACTIVE_KEY set the active key
408 SCTP_AUTH_DELETE_KEY remove a key
409 SCTP_AUTH_DEACTIVATE_KEY will not use that key anymore
410 SCTP_DELAYED_SACK control delayed acks
411 SCTP_PARTIAL_DELIVERY_POINT control partial delivery size 482 SCTP_PARTIAL_DELIVERY_POINT control partial delivery size
412 SCTP_USE_EXT_RCVINFO use extended receive info structure (information about the next message if available) 483 SCTP_USE_EXT_RCVINFO use extended receive info structure (information about the next message if available)
484 */
485 /* SCTP_AUTO_ASCONF is set by the postbind function */
486 /*
413 SCTP_MAX_BURST number of packets that can be burst emitted 487 SCTP_MAX_BURST number of packets that can be burst emitted
414 SCTP_CONTEXT save a context information along with the association. 488 SCTP_CONTEXT save a context information along with the association.
415 SCTP_EXPLICIT_EOR enable sending one message across several send calls 489 */
490
491 /* SCTP_EXPLICIT_EOR: we assume implicit EOR in freeDiameter, so let's ensure this is known by the stack */
492 #ifdef SCTP_EXPLICIT_EOR
493 {
494 int bool;
495
496 if (TRACE_BOOL(SCTP_LEVEL)) {
497 sz = sizeof(bool);
498 /* Read socket defaults */
499 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz) );
500 if (sz != sizeof(bool))
501 {
502 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(bool));
503 return ENOTSUP;
504 }
505 fd_log_debug( "Def SCTP_EXPLICIT_EOR value : %s\n", bool ? "true" : "false");
506 }
507
508 bool = 0;
509
510 /* Set the option to the socket */
511 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, sizeof(bool)) );
512
513 if (TRACE_BOOL(SCTP_LEVEL)) {
514 /* Check new values */
515 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &bool, &sz) );
516 fd_log_debug( "New SCTP_EXPLICIT_EOR value : %s\n", bool ? "true" : "false");
517 }
518 }
519 #else /* SCTP_EXPLICIT_EOR */
520 TRACE_DEBUG(SCTP_LEVEL, "Skipping SCTP_EXPLICIT_EOR");
521 #endif /* SCTP_EXPLICIT_EOR */
522
523 /*
416 SCTP_REUSE_PORT share one listening port with several sockets 524 SCTP_REUSE_PORT share one listening port with several sockets
417 525 SCTP_EVENT same as EVENTS ?
418 read-only options:
419 SCTP_STATUS retrieve info such as number of streams, pending packets, state, ...
420 SCTP_GET_PEER_ADDR_INFO get information about a specific peer address of the association.
421 SCTP_PEER_AUTH_CHUNKS list of chunks the remote peer wants authenticated
422 SCTP_LOCAL_AUTH_CHUNKS list of chunks the local peer wants authenticated
423 SCTP_GET_ASSOC_NUMBER number of associations in a one-to-many socket
424 SCTP_GET_ASSOC_ID_LIST list of these associations
425 */ 526 */
426 527
427 /* In case of no_ip4, force the v6only option -- is it a valid option for SCTP ? */ 528 /* In case of no_ip4, force the v6only option */
428 #ifdef IPV6_V6ONLY 529 #ifdef IPV6_V6ONLY
429 if (fd_g_config->cnf_flags.no_ip4) { 530 if (fd_g_config->cnf_flags.no_ip4) {
430 int opt = 1; 531 int opt = 1;
431 CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt))); 532 CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)));
432 } 533 }
"Welcome to our mercurial repository"