Changeset 23:db6c40b8b307 in freeDiameter for freeDiameter/sctp.c
- Timestamp:
- Oct 20, 2009, 5:30:20 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
freeDiameter/sctp.c
r22 r23 35 35 36 36 #include "fD.h" 37 #include <netinet/sctp.h> 38 #include <sys/uio.h> 39 40 /* Pre-binding socket options -- # streams read in config */ 41 static int fd_setsockopt_prebind(int sk) 42 { 43 #ifdef DEBUG_SCTP 44 socklen_t sz; 45 #endif /* DEBUG_SCTP */ 46 47 TRACE_ENTRY( "%d", sk); 48 49 CHECK_PARAMS( sk > 0 ); 50 51 /* Subscribe to some notifications */ 52 { 53 struct sctp_event_subscribe event; 54 55 memset(&event, 0, sizeof(event)); 56 event.sctp_data_io_event = 1; /* to receive the stream ID in SCTP_SNDRCV ancilliary data on message reception */ 57 event.sctp_association_event = 0; /* new or closed associations (mostly for one-to-many style sockets) */ 58 event.sctp_address_event = 1; /* address changes */ 59 event.sctp_send_failure_event = 1; /* delivery failures */ 60 event.sctp_peer_error_event = 1; /* remote peer sends an error */ 61 event.sctp_shutdown_event = 1; /* peer has sent a SHUTDOWN */ 62 event.sctp_partial_delivery_event = 1; /* a partial delivery is aborted, probably indicating the connection is being shutdown */ 63 // event.sctp_adaptation_layer_event = 0; /* adaptation layer notifications */ 64 // event.sctp_authentication_event = 0; /* when new key is made active */ 65 66 /* Set the option to the socket */ 67 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) ); 68 69 #ifdef DEBUG_SCTP 70 sz = sizeof(event); 71 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_EVENTS, &event, &sz) ); 72 if (sz != sizeof(event)) 73 { 74 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(event)); 75 return ENOTSUP; 76 } 77 78 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_data_io_event : %hhu", event.sctp_data_io_event); 79 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_association_event : %hhu", event.sctp_association_event); 80 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_address_event : %hhu", event.sctp_address_event); 81 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_send_failure_event : %hhu", event.sctp_send_failure_event); 82 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_peer_error_event : %hhu", event.sctp_peer_error_event); 83 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_shutdown_event : %hhu", event.sctp_shutdown_event); 84 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_partial_delivery_event : %hhu", event.sctp_partial_delivery_event); 85 TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_adaptation_layer_event : %hhu", event.sctp_adaptation_layer_event); 86 // TRACE_DEBUG(FULL, "SCTP_EVENTS sctp_authentication_event : %hhu", event.sctp_authentication_event); 87 #endif /* DEBUG_SCTP */ 88 89 } 90 91 /* Set the INIT parameters, such as number of streams */ 92 { 93 struct sctp_initmsg init; 94 memset(&init, 0, sizeof(init)); 95 96 #ifdef DEBUG_SCTP 97 sz = sizeof(init); 98 99 /* Read socket defaults */ 100 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) ); 101 if (sz != sizeof(init)) 102 { 103 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(init)); 104 return ENOTSUP; 105 } 106 TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_num_ostreams : %hu", init.sinit_num_ostreams); 107 TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_max_instreams : %hu", init.sinit_max_instreams); 108 TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_max_attempts : %hu", init.sinit_max_attempts); 109 TRACE_DEBUG(FULL, "Def SCTP_INITMSG sinit_max_init_timeo : %hu", init.sinit_max_init_timeo); 110 #endif /* DEBUG_SCTP */ 111 112 /* Set the init options -- need to receive SCTP_COMM_UP to confirm the requested parameters */ 113 init.sinit_num_ostreams = fd_g_config->cnf_sctp_str; /* desired number of outgoing streams */ 114 init.sinit_max_init_timeo = CNX_TIMEOUT * 1000; 115 116 /* Set the option to the socket */ 117 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)) ); 118 119 #ifdef DEBUG_SCTP 120 /* Check new values */ 121 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_INITMSG, &init, &sz) ); 122 TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_num_ostreams : %hu", init.sinit_num_ostreams); 123 TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_max_instreams : %hu", init.sinit_max_instreams); 124 TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_max_attempts : %hu", init.sinit_max_attempts); 125 TRACE_DEBUG(FULL, "New SCTP_INITMSG sinit_max_init_timeo : %hu", init.sinit_max_init_timeo); 126 #endif /* DEBUG_SCTP */ 127 } 128 129 /* Set the SCTP_DISABLE_FRAGMENTS option, required for TLS */ 130 #ifdef SCTP_DISABLE_FRAGMENTS 131 { 132 int nofrag; 133 134 #ifdef DEBUG_SCTP 135 sz = sizeof(nofrag); 136 /* Read socket defaults */ 137 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) ); 138 if (sz != sizeof(nofrag)) 139 { 140 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nofrag)); 141 return ENOTSUP; 142 } 143 TRACE_DEBUG(FULL, "Def SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false"); 144 #endif /* DEBUG_SCTP */ 145 146 nofrag = 0; /* We turn ON the fragmentation */ 147 148 /* Set the option to the socket */ 149 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, sizeof(nofrag)) ); 150 151 #ifdef DEBUG_SCTP 152 /* Check new values */ 153 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &nofrag, &sz) ); 154 TRACE_DEBUG(FULL, "New SCTP_DISABLE_FRAGMENTS value : %s", nofrag ? "true" : "false"); 155 #endif /* DEBUG_SCTP */ 156 } 157 #else /* SCTP_DISABLE_FRAGMENTS */ 158 # error "TLS requires support of SCTP_DISABLE_FRAGMENTS" 159 #endif /* SCTP_DISABLE_FRAGMENTS */ 160 161 162 /* Set the RETRANSMIT parameters */ 163 #ifdef SCTP_RTOINFO 164 { 165 struct sctp_rtoinfo rtoinfo; 166 memset(&rtoinfo, 0, sizeof(rtoinfo)); 167 168 #ifdef DEBUG_SCTP 169 sz = sizeof(rtoinfo); 170 /* Read socket defaults */ 171 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) ); 172 if (sz != sizeof(rtoinfo)) 173 { 174 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(rtoinfo)); 175 return ENOTSUP; 176 } 177 TRACE_DEBUG(FULL, "Def SCTP_RTOINFO srto_initial : %u", rtoinfo.srto_initial); 178 TRACE_DEBUG(FULL, "Def SCTP_RTOINFO srto_max : %u", rtoinfo.srto_max); 179 TRACE_DEBUG(FULL, "Def SCTP_RTOINFO srto_min : %u", rtoinfo.srto_min); 180 #endif /* DEBUG_SCTP */ 181 182 rtoinfo.srto_max = fd_g_config->cnf_timer_tw * 500 - 1000; /* Maximum retransmit timer (in ms) (set to Tw / 2 - 1) */ 183 184 /* Set the option to the socket */ 185 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, sizeof(rtoinfo)) ); 186 187 #ifdef DEBUG_SCTP 188 /* Check new values */ 189 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_RTOINFO, &rtoinfo, &sz) ); 190 TRACE_DEBUG(FULL, "New SCTP_RTOINFO srto_initial : %u", rtoinfo.srto_initial); 191 TRACE_DEBUG(FULL, "New SCTP_RTOINFO srto_max : %u", rtoinfo.srto_max); 192 TRACE_DEBUG(FULL, "New SCTP_RTOINFO srto_min : %u", rtoinfo.srto_min); 193 #endif /* DEBUG_SCTP */ 194 } 195 #else /* SCTP_RTOINFO */ 196 # ifdef DEBUG_SCTP 197 TRACE_DEBUG(FULL, "Skipping SCTP_RTOINFO"); 198 # endif /* DEBUG_SCTP */ 199 #endif /* SCTP_RTOINFO */ 200 201 /* Set the ASSOCIATION parameters */ 202 #ifdef SCTP_ASSOCINFO 203 { 204 struct sctp_assocparams assoc; 205 memset(&assoc, 0, sizeof(assoc)); 206 207 #ifdef DEBUG_SCTP 208 sz = sizeof(assoc); 209 /* Read socket defaults */ 210 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) ); 211 if (sz != sizeof(assoc)) 212 { 213 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(assoc)); 214 return ENOTSUP; 215 } 216 TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_asocmaxrxt : %hu", assoc.sasoc_asocmaxrxt); 217 TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations); 218 TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_peer_rwnd : %u" , assoc.sasoc_peer_rwnd); 219 TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_local_rwnd : %u" , assoc.sasoc_local_rwnd); 220 TRACE_DEBUG(FULL, "Def SCTP_ASSOCINFO sasoc_cookie_life : %u" , assoc.sasoc_cookie_life); 221 #endif /* DEBUG_SCTP */ 222 223 assoc.sasoc_asocmaxrxt = 5; /* Maximum retransmission attempts: we want fast detection of errors */ 224 225 /* Set the option to the socket */ 226 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, sizeof(assoc)) ); 227 228 #ifdef DEBUG_SCTP 229 /* Check new values */ 230 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_ASSOCINFO, &assoc, &sz) ); 231 TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_asocmaxrxt : %hu", assoc.sasoc_asocmaxrxt); 232 TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_number_peer_destinations : %hu", assoc.sasoc_number_peer_destinations); 233 TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_peer_rwnd : %u" , assoc.sasoc_peer_rwnd); 234 TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_local_rwnd : %u" , assoc.sasoc_local_rwnd); 235 TRACE_DEBUG(FULL, "New SCTP_ASSOCINFO sasoc_cookie_life : %u" , assoc.sasoc_cookie_life); 236 #endif /* DEBUG_SCTP */ 237 } 238 #else /* SCTP_ASSOCINFO */ 239 # ifdef DEBUG_SCTP 240 TRACE_DEBUG(FULL, "Skipping SCTP_ASSOCINFO"); 241 # endif /* DEBUG_SCTP */ 242 #endif /* SCTP_ASSOCINFO */ 243 244 245 /* The SO_LINGER option will be re-set if we want to perform SCTP ABORT */ 246 #ifdef SO_LINGER 247 { 248 struct linger linger; 249 memset(&linger, 0, sizeof(linger)); 250 251 #ifdef DEBUG_SCTP 252 sz = sizeof(linger); 253 /* Read socket defaults */ 254 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) ); 255 if (sz != sizeof(linger)) 256 { 257 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(linger)); 258 return ENOTSUP; 259 } 260 TRACE_DEBUG(FULL, "Def SO_LINGER l_onoff : %d", linger.l_onoff); 261 TRACE_DEBUG(FULL, "Def SO_LINGER l_linger : %d", linger.l_linger); 262 #endif /* DEBUG_SCTP */ 263 264 linger.l_onoff = 0; /* Do not activate the linger */ 265 linger.l_linger = 0; /* Return immediately when closing (=> abort) */ 266 267 /* Set the option */ 268 CHECK_SYS( setsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) ); 269 270 #ifdef DEBUG_SCTP 271 /* Check new values */ 272 CHECK_SYS( getsockopt(sk, SOL_SOCKET, SO_LINGER, &linger, &sz) ); 273 TRACE_DEBUG(FULL, "New SO_LINGER l_onoff : %d", linger.l_onoff); 274 TRACE_DEBUG(FULL, "New SO_LINGER l_linger : %d", linger.l_linger); 275 #endif /* DEBUG_SCTP */ 276 } 277 #else /* SO_LINGER */ 278 # ifdef DEBUG_SCTP 279 TRACE_DEBUG(FULL, "Skipping SO_LINGER"); 280 # endif /* DEBUG_SCTP */ 281 #endif /* SO_LINGER */ 282 283 /* Set the NODELAY option (Nagle-like algorithm) */ 284 #ifdef SCTP_NODELAY 285 { 286 int nodelay; 287 288 #ifdef DEBUG_SCTP 289 sz = sizeof(nodelay); 290 /* Read socket defaults */ 291 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) ); 292 if (sz != sizeof(nodelay)) 293 { 294 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(nodelay)); 295 return ENOTSUP; 296 } 297 TRACE_DEBUG(FULL, "Def SCTP_NODELAY value : %s", nodelay ? "true" : "false"); 298 #endif /* DEBUG_SCTP */ 299 300 nodelay = 0; /* We turn ON the Nagle algorithm (probably the default already) */ 301 302 /* Set the option to the socket */ 303 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)) ); 304 305 #ifdef DEBUG_SCTP 306 /* Check new values */ 307 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, &sz) ); 308 TRACE_DEBUG(FULL, "New SCTP_NODELAY value : %s", nodelay ? "true" : "false"); 309 #endif /* DEBUG_SCTP */ 310 } 311 #else /* SCTP_NODELAY */ 312 # ifdef DEBUG_SCTP 313 TRACE_DEBUG(FULL, "Skipping SCTP_NODELAY"); 314 # endif /* DEBUG_SCTP */ 315 #endif /* SCTP_NODELAY */ 316 317 /* Set the interleaving option */ 318 #ifdef SCTP_FRAGMENT_INTERLEAVE 319 { 320 int interleave; 321 322 #ifdef DEBUG_SCTP 323 sz = sizeof(interleave); 324 /* Read socket defaults */ 325 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz) ); 326 if (sz != sizeof(interleave)) 327 { 328 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(interleave)); 329 return ENOTSUP; 330 } 331 TRACE_DEBUG(FULL, "Def SCTP_FRAGMENT_INTERLEAVE value : %d", interleave); 332 #endif /* DEBUG_SCTP */ 333 334 #if 0 335 interleave = 2; /* Allow partial delivery on several streams at the same time, since we are stream-aware in our security modules */ 336 #else /* 0 */ 337 interleave = 1; /* hmmm actually, we are not yet capable of handling this, and we don t need it. */ 338 #endif /* 0 */ 339 340 /* Set the option to the socket */ 341 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, sizeof(interleave)) ); 342 343 #ifdef DEBUG_SCTP 344 /* Check new values */ 345 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE, &interleave, &sz) ); 346 TRACE_DEBUG(FULL, "New SCTP_FRAGMENT_INTERLEAVE value : %d", interleave); 347 #endif /* DEBUG_SCTP */ 348 } 349 #else /* SCTP_FRAGMENT_INTERLEAVE */ 350 # ifdef DEBUG_SCTP 351 TRACE_DEBUG(FULL, "Skipping SCTP_FRAGMENT_INTERLEAVE"); 352 # endif /* DEBUG_SCTP */ 353 #endif /* SCTP_FRAGMENT_INTERLEAVE */ 354 355 /* Set the v4 mapped addresses option */ 356 #ifdef SCTP_I_WANT_MAPPED_V4_ADDR 357 { 358 int v4mapped; 359 360 #ifdef DEBUG_SCTP 361 sz = sizeof(v4mapped); 362 /* Read socket defaults */ 363 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) ); 364 if (sz != sizeof(v4mapped)) 365 { 366 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(v4mapped)); 367 return ENOTSUP; 368 } 369 TRACE_DEBUG(FULL, "Def SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false"); 370 #endif /* DEBUG_SCTP */ 371 372 v4mapped = 0; /* We don't want v4 mapped addresses */ 373 v4mapped = 1; /* but we have to, otherwise the bind fails in linux currently ... (Ok, It'd be better with a cmake test, any volunteer?) */ 374 375 /* Set the option to the socket */ 376 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, sizeof(v4mapped)) ); 377 378 #ifdef DEBUG_SCTP 379 /* Check new values */ 380 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, &v4mapped, &sz) ); 381 TRACE_DEBUG(FULL, "New SCTP_I_WANT_MAPPED_V4_ADDR value : %s", v4mapped ? "true" : "false"); 382 #endif /* DEBUG_SCTP */ 383 } 384 #else /* SCTP_I_WANT_MAPPED_V4_ADDR */ 385 # ifdef DEBUG_SCTP 386 TRACE_DEBUG(FULL, "Skipping SCTP_I_WANT_MAPPED_V4_ADDR"); 387 # endif /* DEBUG_SCTP */ 388 #endif /* SCTP_I_WANT_MAPPED_V4_ADDR */ 389 390 391 /* Other settable options (draft-ietf-tsvwg-sctpsocket-17): 392 SO_RCVBUF size of receiver window 393 SO_SNDBUF size of pending data to send 394 SCTP_AUTOCLOSE for one-to-many only 395 SCTP_SET_PEER_PRIMARY_ADDR ask remote peer to use this local address as primary 396 SCTP_PRIMARY_ADDR use this address as primary locally 397 SCTP_ADAPTATION_LAYER set adaptation layer indication 398 SCTP_PEER_ADDR_PARAMS control heartbeat per peer address 399 SCTP_DEFAULT_SEND_PARAM parameters for the sendto() call 400 SCTP_MAXSEG max size of fragmented segments -- bound to PMTU 401 SCTP_AUTH_CHUNK request authentication of some type of chunk 402 SCTP_HMAC_IDENT authentication algorithms 403 SCTP_AUTH_KEY set a shared key 404 SCTP_AUTH_ACTIVE_KEY set the active key 405 SCTP_AUTH_DELETE_KEY remove a key 406 SCTP_AUTH_DEACTIVATE_KEY will not use that key anymore 407 SCTP_DELAYED_SACK control delayed acks 408 SCTP_PARTIAL_DELIVERY_POINT control partial delivery size 409 SCTP_USE_EXT_RCVINFO use extended receive info structure (information about the next message if available) 410 SCTP_MAX_BURST number of packets that can be burst emitted 411 SCTP_CONTEXT save a context information along with the association. 412 SCTP_EXPLICIT_EOR enable sending one message across several send calls 413 SCTP_REUSE_PORT share one listening port with several sockets 414 415 read-only options: 416 SCTP_STATUS retrieve info such as number of streams, pending packets, state, ... 417 SCTP_GET_PEER_ADDR_INFO get information about a specific peer address of the association. 418 SCTP_PEER_AUTH_CHUNKS list of chunks the remote peer wants authenticated 419 SCTP_LOCAL_AUTH_CHUNKS list of chunks the local peer wants authenticated 420 SCTP_GET_ASSOC_NUMBER number of associations in a one-to-many socket 421 SCTP_GET_ASSOC_ID_LIST list of these associations 422 */ 423 424 /* In case of no_ip4, force the v6only option */ 425 #ifdef IPV6_V6ONLY 426 if (fd_g_config->cnf_flags.no_ip4) { 427 int opt = 1; 428 CHECK_SYS(setsockopt(sk, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt))); 429 } 430 #endif /* IPV6_V6ONLY */ 431 432 return 0; 433 } 434 435 436 /* Post-binding socket options */ 437 static int fd_setsockopt_postbind(int sk, int bound_to_default) 438 { 439 TRACE_ENTRY( "%d %d", sk, bound_to_default); 440 441 CHECK_PARAMS( (sk > 0) ); 442 443 /* Set the ASCONF option */ 444 #ifdef SCTP_AUTO_ASCONF 445 { 446 int asconf; 447 448 #ifdef DEBUG_SCTP 449 socklen_t sz; 450 451 sz = sizeof(asconf); 452 /* Read socket defaults */ 453 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz) ); 454 if (sz != sizeof(asconf)) 455 { 456 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %d", sz, (socklen_t)sizeof(asconf)); 457 return ENOTSUP; 458 } 459 TRACE_DEBUG(FULL, "Def SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false"); 460 #endif /* DEBUG_SCTP */ 461 462 asconf = bound_to_default ? 1 : 0; /* allow automatic use of added or removed addresses in the association (for bound-all sockets) */ 463 464 /* Set the option to the socket */ 465 CHECK_SYS( setsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, sizeof(asconf)) ); 466 467 #ifdef DEBUG_SCTP 468 /* Check new values */ 469 CHECK_SYS( getsockopt(sk, IPPROTO_SCTP, SCTP_AUTO_ASCONF, &asconf, &sz) ); 470 TRACE_DEBUG(FULL, "New SCTP_AUTO_ASCONF value : %s", asconf ? "true" : "false"); 471 #endif /* DEBUG_SCTP */ 472 } 473 #else /* SCTP_AUTO_ASCONF */ 474 # ifdef DEBUG_SCTP 475 TRACE_DEBUG(FULL, "Skipping SCTP_AUTO_ASCONF"); 476 # endif /* DEBUG_SCTP */ 477 #endif /* SCTP_AUTO_ASCONF */ 478 479 return 0; 480 } 37 481 38 482 /* Create a socket server and bind it according to daemon s configuration */ 39 483 int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port ) 40 484 { 41 TODO("Create sctp server, using fd_g_config: cnf_endpoints, no_ip4, no_ip6, cnf_sctp_str"); 42 43 return ENOTSUP; 485 int family; 486 int bind_default; 487 488 TRACE_ENTRY("%p %p %hu", sock, list, port); 489 CHECK_PARAMS(sock); 490 491 if (fd_g_config->cnf_flags.no_ip6) { 492 family = AF_INET; 493 } else { 494 family = AF_INET6; /* can create socket for both IP and IPv6 */ 495 } 496 497 /* Create the socket */ 498 CHECK_SYS( *sock = socket(family, SOCK_STREAM, IPPROTO_SCTP) ); 499 500 /* Set pre-binding socket options, including number of streams etc... */ 501 CHECK_FCT( fd_setsockopt_prebind(*sock) ); 502 503 bind_default = (! list) || (FD_IS_LIST_EMPTY(list)) ; 504 redo: 505 if ( bind_default ) { 506 /* Implicit endpoints : bind to default addresses */ 507 union { 508 sSS ss; 509 sSA sa; 510 sSA4 sin; 511 sSA6 sin6; 512 } s; 513 514 /* 0.0.0.0 and [::] are all zeros */ 515 memset(&s, 0, sizeof(s)); 516 517 s.sa.sa_family = family; 518 519 if (family == AF_INET) 520 s.sin.sin_port = htons(port); 521 else 522 s.sin6.sin6_port = htons(port); 523 524 CHECK_SYS( bind(*sock, &s.sa, sizeof(s)) ); 525 526 } else { 527 /* Explicit endpoints to bind to from config */ 528 union { 529 sSA *sa; 530 sSA4 *sin; 531 sSA6 *sin6; 532 } sar; /* build the list of endpoints to bind to */ 533 int count = 0; /* number of sock addr in sar array */ 534 struct fd_list * li; 535 536 sar.sa = NULL; 537 538 /* Create a flat array from the list of configured addresses */ 539 for (li = list->next; li != list; li = li->next) { 540 struct fd_endpoint * ep = (struct fd_endpoint *)li; 541 542 if ( ! ep->meta.conf ) 543 continue; 544 545 count++; 546 if (fd_g_config->cnf_flags.no_ip6) { 547 ASSERT(ep->sa.sa_family == AF_INET); 548 CHECK_MALLOC( sar.sa = realloc(sar.sa, count * sizeof(sSA4)) ); 549 memcpy(&sar.sin[count - 1], &ep->sin, sizeof(sSA4)); 550 sar.sin[count - 1].sin_port = htons(port); 551 } else { 552 /* Pass all addresses as IPv6, eventually mapped -- we already filtered out IPv4 addresses if no_ip4 flag is set */ 553 CHECK_MALLOC( sar.sa = realloc(sar.sa, count * sizeof(sSA6)) ); 554 if (ep->sa.sa_family == AF_INET) { 555 memset(&sar.sin6[count - 1], 0, sizeof(sSA6)); 556 sar.sin6[count - 1].sin6_family = AF_INET6; 557 IN6_ADDR_V4MAP( &sar.sin6[count - 1].sin6_addr.s6_addr, ep->sin.sin_addr.s_addr ); 558 } else { 559 memcpy(&sar.sin6[count - 1], &ep->sin6, sizeof(sSA6)); 560 } 561 sar.sin6[count - 1].sin6_port = htons(port); 562 } 563 } 564 565 if (!count) { 566 /* None of the addresses in the list came from configuration, we bind to default */ 567 bind_default = 1; 568 goto redo; 569 } 570 571 # ifdef DEBUG_SCTP 572 if (TRACE_BOOL(FULL)) { 573 int i; 574 fd_log_debug("Calling sctp_bindx with the following array:\n"); 575 for (i = 0; i < count; i++) { 576 fd_log_debug(" - "); 577 sSA_DUMP_NODE_SERV( (sar.sa[0].sa_family == AF_INET) ? (sSA *)(&sar.sin[i]) : (sSA *)(&sar.sin6[i]), NI_NUMERICHOST | NI_NUMERICSERV ); 578 fd_log_debug("\n"); 579 } 580 } 581 #endif /* DEBUG_SCTP */ 582 583 CHECK_SYS( sctp_bindx(*sock, sar.sa, count, SCTP_BINDX_ADD_ADDR) ); 584 585 } 586 587 /* Now, the server is bound, set remaining sockopt */ 588 CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) ); 589 590 #ifdef DEBUG_SCTP 591 /* Debug: show all local listening addresses */ 592 if (TRACE_BOOL(FULL)) { 593 sSA *sa, *sar; 594 int sz; 595 596 CHECK_SYS( sz = sctp_getladdrs(*sock, 0, &sar) ); 597 598 fd_log_debug("SCTP server bound on :\n"); 599 for (sa = sar; sz-- > 0; sa = (sSA *)(((uint8_t *)sa) + ((sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6)))) { 600 fd_log_debug(" - "); 601 sSA_DUMP_NODE_SERV( sa, NI_NUMERICHOST | NI_NUMERICSERV ); 602 fd_log_debug("\n"); 603 } 604 sctp_freeladdrs(sar); 605 } 606 #endif /* DEBUG_SCTP */ 607 608 return 0; 44 609 } 45 610 … … 60 625 } 61 626 627 /* Get the list of local endpoints of the socket */ 628 int fd_sctp_get_local_ep(int sock, struct fd_list * list) 629 { 630 union { 631 sSA *sa; 632 sSA4 *sin; 633 sSA6 *sin6; 634 uint8_t *buf; 635 } ptr; 636 637 sSA * data; 638 int count; 639 640 TRACE_ENTRY("%d %p", sock, list); 641 CHECK_PARAMS(list); 642 643 /* Read the list on the socket */ 644 CHECK_SYS( count = sctp_getladdrs(sock, 0, &data) ); 645 ptr.sa = data; 646 647 while (count) { 648 TODO("get the data from ptr"); 649 TODO("Increment ptr to the next sa in data"); 650 651 count --; 652 } 653 654 /* And now, free the list and return */ 655 sctp_freeladdrs(data); 656 657 return ENOTSUP; 658 } 659 660 /* Get the list of remote endpoints of the socket */ 661 int fd_sctp_get_remote_ep(int sock, struct fd_list * list) 662 { 663 TODO("SCTP: sctp_getpaddrs"); 664 665 666 return ENOTSUP; 667 } 668
Note: See TracChangeset
for help on using the changeset viewer.