Mercurial > hg > freeDiameter
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 } |