Changeset 23:db6c40b8b307 in freeDiameter
- Timestamp:
- Oct 20, 2009, 5:30:20 PM (15 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/freediameter.conf.sample
r22 r23 68 68 #ListenOn = "202.249.37.5"; 69 69 #ListenOn = "2001:200:903:2::202:1"; 70 #ListenOn = "fe80::21c:5ff:fe98:7d62%eth0"; 70 71 71 72 ############################################################## … … 201 202 SecPort = 3867; 202 203 TLS_old_method; 203 No_SCTP;204 Prefer_TCP;205 204 SCTP_streams = 50; 206 #ListenOn = "202.249.37.5";207 #ListenOn = "2001:200:903:2::202:1";208 205 TcTimer = 60; 209 206 TwTimer = 6; 207 ListenOn = "133.243.146.201"; 208 ListenOn = "fe80::21d:9ff:fe89:7d68%eth0"; 210 209 NoRelay; 211 210 LoadExtension = "extensions/dbg_monitor.fdx"; -
freeDiameter/cnxctx.c
r22 r23 214 214 break; 215 215 216 #ifndef DISABLE_SCTP 216 217 case IPPROTO_SCTP: 217 218 CHECK_FCT(fd_sctp_listen(conn->cc_socket)); 218 219 break; 220 #endif /* DISABLE_SCTP */ 219 221 220 222 default: … … 400 402 } 401 403 402 /* Get the list of endpoints (IP addresses) of the local and remote peers on this con enction */404 /* Get the list of endpoints (IP addresses) of the local and remote peers on this connection */ 403 405 int fd_cnx_getendpoints(struct cnxctx * conn, struct fd_list * local, struct fd_list * remote) 404 406 { … … 408 410 if (local) { 409 411 /* Retrieve the local endpoint(s) of the connection */ 410 TODO("TCP : getsockname"); 411 TODO("SCTP: sctp_getladdrs / _sctp_getboundaddrs (waaad)"); 412 switch (conn->cc_proto) { 413 case IPPROTO_TCP: { 414 sSS ss; 415 socklen_t sl; 416 CHECK_FCT(fd_tcp_get_local_ep(conn->cc_socket, &ss, &sl)); 417 CHECK_FCT(fd_ep_add_merge( local, (sSA *)&ss, sl, 0, 0, 0, 1 )); 418 } 419 break; 420 421 #ifndef DISABLE_SCTP 422 case IPPROTO_SCTP: { 423 CHECK_FCT(fd_sctp_get_local_ep(conn->cc_socket, local)); 424 } 425 break; 426 #endif /* DISABLE_SCTP */ 427 428 default: 429 CHECK_PARAMS(0); 430 } 412 431 } 413 432 414 433 if (remote) { 434 /* Check we have a full connection object, not a listening socket (with no remote) */ 435 CHECK_PARAMS( conn->cc_events ); 436 415 437 /* Retrieve the peer endpoint(s) of the connection */ 416 TODO("TCP : getpeername"); 417 TODO("SCTP: sctp_getpaddrs"); 418 419 } 420 421 return ENOTSUP; 438 switch (conn->cc_proto) { 439 case IPPROTO_TCP: { 440 sSS ss; 441 socklen_t sl; 442 CHECK_FCT(fd_tcp_get_remote_ep(conn->cc_socket, &ss, &sl)); 443 CHECK_FCT(fd_ep_add_merge( remote, (sSA *)&ss, sl, 0, 0, 0, 1 )); 444 } 445 break; 446 447 #ifndef DISABLE_SCTP 448 case IPPROTO_SCTP: { 449 CHECK_FCT(fd_sctp_get_remote_ep(conn->cc_socket, remote)); 450 } 451 break; 452 #endif /* DISABLE_SCTP */ 453 454 default: 455 CHECK_PARAMS(0); 456 } 457 } 458 459 return 0; 422 460 } 423 461 -
freeDiameter/config.c
r22 r23 100 100 struct fd_endpoint * ep = (struct fd_endpoint *)li; 101 101 if (li != fd_g_config->cnf_endpoints.next) fd_log_debug(" "); 102 sSA_DUMP_NODE( &ep->s s, NI_NUMERICHOST );102 sSA_DUMP_NODE( &ep->sa, NI_NUMERICHOST ); 103 103 fd_log_debug("\n"); 104 104 li = li->next; … … 234 234 for ( li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) { 235 235 struct fd_endpoint * ep = (struct fd_endpoint *)li; 236 if ( (fd_g_config->cnf_flags.no_ip4 && (ep->s s.ss_family == AF_INET))237 ||(fd_g_config->cnf_flags.no_ip6 && (ep->s s.ss_family == AF_INET6)) ) {236 if ( (fd_g_config->cnf_flags.no_ip4 && (ep->sa.sa_family == AF_INET)) 237 ||(fd_g_config->cnf_flags.no_ip6 && (ep->sa.sa_family == AF_INET6)) ) { 238 238 li = li->prev; 239 239 fd_list_unlink(&ep->chain); 240 240 if (TRACE_BOOL(INFO)) { 241 241 fd_log_debug("Info: Removing local address conflicting with the flags no_IP / no_IP6 : "); 242 sSA_DUMP_NODE( &ep->s s, AI_NUMERICHOST );242 sSA_DUMP_NODE( &ep->sa, AI_NUMERICHOST ); 243 243 fd_log_debug("\n"); 244 244 } … … 272 272 return 0; 273 273 } 274 275 /* Add an endpoint information in a list */ 276 int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, int conf, int disc, int adv, int ll ) 277 { 278 struct fd_endpoint * ep; 279 struct fd_list * li; 280 int cmp = -1; 281 282 TRACE_ENTRY("%p %p %u %i %i %i %i", list, sa, sl, conf, disc, adv, ll); 283 CHECK_PARAMS( list && sa && (sl <= sizeof(sSS)) && (conf || disc || adv || ll) ); 284 285 /* Search place in the list */ 286 for (li = list->next; li != list; li = li->next) { 287 ep = (struct fd_endpoint *)li; 288 289 cmp = memcmp(&ep->ss, sa, sl); 290 if (cmp >= 0) 291 break; 292 } 293 294 if (cmp) { 295 /* new item to be added */ 296 CHECK_MALLOC( ep = malloc(sizeof(struct fd_endpoint)) ); 297 memset(ep, 0, sizeof(struct fd_endpoint)); 298 fd_list_init(&ep->chain, NULL); 299 memcpy(&ep->ss, sa, sl); 300 301 /* Insert in the list */ 302 fd_list_insert_before(li, &ep->chain); 303 } 304 305 /* Merge the flags */ 306 ep->meta.conf = conf || ep->meta.conf; 307 ep->meta.disc = disc || ep->meta.disc; 308 ep->meta.adv = adv || ep->meta.adv; 309 ep->meta.ll = ll || ep->meta.ll; 310 311 return 0; 312 } 313 -
freeDiameter/fD.h
r22 r23 222 222 int fd_tcp_create_bind_server( int * sock, sSA * sa, socklen_t salen ); 223 223 int fd_tcp_listen( int sock ); 224 int fd_tcp_get_local_ep(int sock, sSS * ss, socklen_t *sl); 225 int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl); 224 226 225 227 /* SCTP */ … … 227 229 int fd_sctp_create_bind_server( int * sock, struct fd_list * list, uint16_t port ); 228 230 int fd_sctp_listen( int sock ); 229 231 int fd_sctp_get_local_ep(int sock, struct fd_list * list); 232 int fd_sctp_get_remote_ep(int sock, struct fd_list * list); 230 233 int fd_sctp_get_str_info( int socket, int *in, int *out ); 231 234 -
freeDiameter/fdd.y
r22 r23 212 212 listenon: LISTENON '=' QSTRING ';' 213 213 { 214 struct fd_endpoint * ep;215 214 struct addrinfo hints, *ai; 216 215 int ret; 217 218 CHECK_MALLOC_DO( ep = malloc(sizeof(struct fd_endpoint)),219 { yyerror (&yylloc, conf, "Out of memory"); YYERROR; } );220 memset(ep, 0, sizeof(struct fd_endpoint));221 fd_list_init(&ep->chain, NULL);222 ep->meta.conf = 1;223 216 224 217 memset(&hints, 0, sizeof(hints)); 225 218 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 226 219 ret = getaddrinfo($3, NULL, &hints, &ai); 227 if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); free(ep);YYERROR; }228 ASSERT( ai->ai_addrlen <= sizeof(sSS));229 memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen);220 if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; } 221 CHECK_FCT_DO( fd_ep_add_merge( &conf->cnf_endpoints, ai->ai_addr, ai->ai_addrlen, 1, 0, 0, 0 ), YYERROR ); 222 freeaddrinfo(ai); 230 223 free($3); 231 freeaddrinfo(ai);232 fd_list_insert_before(&conf->cnf_endpoints, &ep->chain);233 224 } 234 225 ; … … 430 421 | peerparams CONNTO '=' QSTRING ';' 431 422 { 432 struct fd_endpoint * ep;433 423 struct addrinfo hints, *ai; 434 424 int ret; 425 int disc = 0; 435 426 436 CHECK_MALLOC_DO( ep = malloc(sizeof(struct fd_endpoint)),437 { yyerror (&yylloc, conf, "Out of memory"); YYERROR; } );438 memset(ep, 0, sizeof(struct fd_endpoint));439 fd_list_init(&ep->chain, NULL);440 ep->meta.conf = 1;441 427 memset(&hints, 0, sizeof(hints)); 442 428 hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; … … 444 430 if (ret == EAI_NONAME) { 445 431 /* The name was maybe not numeric, try again */ 446 ep->meta.disc = 1;432 disc = 1; 447 433 hints.ai_flags &= ~ AI_NUMERICHOST; 448 434 ret = getaddrinfo($4, NULL, &hints, &ai); 449 435 } 450 if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); free(ep);YYERROR; }436 if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; } 451 437 452 memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen);438 CHECK_FCT_DO( fd_ep_add_merge( &fddpi.pi_endpoints, ai->ai_addr, ai->ai_addrlen, 1, disc, 0, 0 ), YYERROR ); 453 439 free($4); 454 440 freeaddrinfo(ai); 455 fd_list_insert_before(&fddpi.pi_endpoints, &ep->chain);456 441 } 457 442 ; -
freeDiameter/main.c
r22 r23 106 106 CHECK_FCT( fd_ext_load() ); 107 107 108 fd_conf_dump(); 109 108 110 /* Start the servers */ 109 111 CHECK_FCT( fd_servers_start() ); … … 114 116 /* Now, just wait for events */ 115 117 TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized."); 116 fd_conf_dump();117 118 while (1) { 118 119 int code; -
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 -
freeDiameter/tcp.c
r22 r23 37 37 #include <netinet/tcp.h> 38 38 #include <netinet/ip6.h> 39 #include <sys/socket.h> 39 40 40 41 /* Set the socket options for TCP sockets, before bind is called */ … … 111 112 return 0; 112 113 } 114 115 /* Get the local name of a TCP socket -- would be nice if it did not return "0.0.0.0"... */ 116 int fd_tcp_get_local_ep(int sock, sSS * ss, socklen_t *sl) 117 { 118 TRACE_ENTRY("%d %p %p", sock, ss, sl); 119 CHECK_PARAMS( ss && sl ); 120 121 *sl = sizeof(sSS); 122 CHECK_SYS(getsockname(sock, (sSA *)ss, sl)); 123 124 return 0; 125 } 126 127 /* Get the remote name of a TCP socket */ 128 int fd_tcp_get_remote_ep(int sock, sSS * ss, socklen_t *sl) 129 { 130 TRACE_ENTRY("%d %p %p", sock, ss, sl); 131 CHECK_PARAMS( ss && sl ); 132 133 *sl = sizeof(sSS); 134 CHECK_SYS(getpeername(sock, (sSA *)ss, sl)); 135 136 return 0; 137 } -
include/freeDiameter/CMakeLists.txt
r17 r23 10 10 11 11 # Disable SCTP support completly ? 12 OPTION(DISABLE_SCTP "Disable SCTP support?") 12 OPTION(DISABLE_SCTP "Disable SCTP support?" OFF) 13 IF (NOT DISABLE_SCTP) 14 OPTION(DEBUG_SCTP "Verbose SCTP (for debug)?" OFF) 15 ENDIF (NOT DISABLE_SCTP) 13 16 14 17 # Find TODO items in the code easily ? -
include/freeDiameter/freeDiameter-host.h.in
r13 r23 45 45 46 46 #cmakedefine DISABLE_SCTP 47 #cmakedefine DEBUG_SCTP 47 48 #cmakedefine ERRORS_ON_TODO 48 49 #cmakedefine DEBUG -
include/freeDiameter/freeDiameter.h
r22 r23 118 118 struct fd_endpoint { 119 119 struct fd_list chain; /* link in cnf_endpoints list */ 120 sSS ss; /* the socket information. List is always ordered by ss value (memcmp) */ 120 union { 121 sSS ss; /* the socket information. List is always ordered by ss value (memcmp) */ 122 sSA4 sin; 123 sSA6 sin6; 124 sSA sa; 125 }; 121 126 struct { 122 127 unsigned conf : 1; /* This endpoint is statically configured in a configuration file */ … … 129 134 } meta; /* Additional information about the endpoint */ 130 135 }; 136 137 /* Add a new entry in a list of endpoints -- merge if the sockaddr was already there */ 138 int fd_ep_add_merge( struct fd_list * list, sSA * sa, socklen_t sl, int conf, int disc, int adv, int ll ); 131 139 132 140 /* Applications */ -
include/freeDiameter/libfreeDiameter.h
r22 r23 329 329 flag); \ 330 330 if (__rc) \ 331 fd_log_debug( (char *)gai_strerror(__rc)); \331 fd_log_debug("%s", (char *)gai_strerror(__rc)); \ 332 332 else \ 333 fd_log_debug( &__addrbuf[0]);\333 fd_log_debug("%s", &__addrbuf[0]); \ 334 334 } else { \ 335 335 fd_log_debug("(NULL / ANY)"); \ 336 336 } \ 337 337 } 338 /* if needed, add sSA_DUMP_SERVICE */ 338 /* Same, for a service */ 339 #define sSA_DUMP_SERV( sa, flag ) { \ 340 sSA * __sa = (sSA *)(sa); \ 341 char __servbuf[32]; \ 342 if (__sa) { \ 343 int __rc = getnameinfo(__sa, \ 344 sizeof(sSS), \ 345 NULL, \ 346 0, \ 347 __servbuf, \ 348 sizeof(__servbuf), \ 349 flag); \ 350 if (__rc) \ 351 fd_log_debug("%s", (char *)gai_strerror(__rc)); \ 352 else \ 353 fd_log_debug("%s", &__servbuf[0]); \ 354 } else { \ 355 fd_log_debug("(unknown)"); \ 356 } \ 357 } 358 /* Combine both */ 359 #define sSA_DUMP_NODE_SERV( sa, flag ) { \ 360 sSA * __sa = (sSA *)(sa); \ 361 char __addrbuf[INET6_ADDRSTRLEN]; \ 362 char __servbuf[32]; \ 363 if (__sa) { \ 364 int __rc = getnameinfo(__sa, \ 365 sizeof(sSS), \ 366 __addrbuf, \ 367 sizeof(__addrbuf), \ 368 __servbuf, \ 369 sizeof(__servbuf), \ 370 flag); \ 371 if (__rc) \ 372 fd_log_debug("%s", (char *)gai_strerror(__rc)); \ 373 else \ 374 fd_log_debug("[%s]:%s", &__addrbuf[0],&__servbuf[0]); \ 375 } else { \ 376 fd_log_debug("(NULL / ANY)"); \ 377 } \ 378 } 379 339 380 340 381 /* A l4 protocol name (TCP / SCTP) */
Note: See TracChangeset
for help on using the changeset viewer.