# HG changeset patch # User Sebastien Decugis # Date 1368525691 -28800 # Node ID d4371b7aa0ffdf4734f160aaaa7a8953db39ec39 # Parent ccbd1426e04a57243bb1bb5384d6a9444bfad8e1 New CMake option: ADDRESS_AVP_INCLUDE_PORT. Turn off for standard Host-IP-Address AVPs diff -r ccbd1426e04a -r d4371b7aa0ff include/freeDiameter/CMakeLists.txt --- a/include/freeDiameter/CMakeLists.txt Tue May 14 15:27:28 2013 +0800 +++ b/include/freeDiameter/CMakeLists.txt Tue May 14 18:01:31 2013 +0800 @@ -33,6 +33,9 @@ # compliancy of their implementation with the Diameter RFC... OPTION(WORKAROUND_ACCEPT_INVALID_VSAI "Do not reject a CER/CEA with a Vendor-Specific-Application-Id AVP containing both Auth- and Acct- application AVPs?" OFF) +# If the following is defined, the Address-based AVPs issued locally are extended to include the port information. +OPTION(ADDRESS_AVP_INCLUDE_PORT "Include the port number in the Address-based AVPs?" ON) + MARK_AS_ADVANCED(DISABLE_SCTP DEBUG_SCTP SCTP_USE_MAPPED_ADDRESSES ERRORS_ON_TODO DIAMID_IDNA_IGNORE DIAMID_IDNA_REJECT DISABLE_PEER_EXPIRY WORKAROUND_ACCEPT_INVALID_VSAI) ######################## diff -r ccbd1426e04a -r d4371b7aa0ff include/freeDiameter/freeDiameter-host.h.in --- a/include/freeDiameter/freeDiameter-host.h.in Tue May 14 15:27:28 2013 +0800 +++ b/include/freeDiameter/freeDiameter-host.h.in Tue May 14 18:01:31 2013 +0800 @@ -60,6 +60,7 @@ #cmakedefine DIAMID_IDNA_REJECT #cmakedefine DISABLE_PEER_EXPIRY #cmakedefine WORKAROUND_ACCEPT_INVALID_VSAI +#cmakedefine ADDRESS_AVP_INCLUDE_PORT #cmakedefine GNUTLS_VERSION_210 #cmakedefine GNUTLS_VERSION_300 #cmakedefine GNUTLS_VERSION_310 diff -r ccbd1426e04a -r d4371b7aa0ff include/freeDiameter/libfdcore.h --- a/include/freeDiameter/libfdcore.h Tue May 14 15:27:28 2013 +0800 +++ b/include/freeDiameter/libfdcore.h Tue May 14 18:01:31 2013 +0800 @@ -136,7 +136,7 @@ uint16_t cnf_port; /* the local port for legacy Diameter (default: 3868) in host byte order */ uint16_t cnf_port_tls; /* the local port for Diameter/TLS (default: 3869) in host byte order */ uint16_t cnf_sctp_str; /* default max number of streams for SCTP associations (def: 30) */ - struct fd_list cnf_endpoints; /* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all) */ + struct fd_list cnf_endpoints; /* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all). After servers are started, this is the actual list of endpoints including port information. */ struct fd_list cnf_apps; /* Applications locally supported (except relay, see flags). Use fd_disp_app_support to add one. list of struct fd_app. */ uint16_t cnf_dispthr; /* Number of dispatch threads to create */ struct { diff -r ccbd1426e04a -r d4371b7aa0ff include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Tue May 14 15:27:28 2013 +0800 +++ b/include/freeDiameter/libfdproto.h Tue May 14 18:01:31 2013 +0800 @@ -609,9 +609,12 @@ ( (socklen_t) ( (((sSA *)_sa_)->sa_family == AF_INET) ? (sizeof(sSA4)) : \ ((((sSA *)_sa_)->sa_family == AF_INET6) ? (sizeof(sSA6)) : \ 0 ) ) ) - -DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags); -DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags); +#define sSAport( _sa_ ) \ + ( (socklen_t) ( (((sSA *)_sa_)->sa_family == AF_INET) ? (((sSA4 *)(_sa_))->sin_port) : \ + ((((sSA *)_sa_)->sa_family == AF_INET6) ? (((sSA6 *)(_sa_))->sin6_port) : \ + 0 ) ) ) + +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump, sSA * sa, int flags); #define sSA_DUMP_STRLEN (INET6_ADDRSTRLEN + 1 + 32 + 2) void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa); diff -r ccbd1426e04a -r d4371b7aa0ff libfdcore/endpoints.c --- a/libfdcore/endpoints.c Tue May 14 15:27:28 2013 +0800 +++ b/libfdcore/endpoints.c Tue May 14 18:01:31 2013 +0800 @@ -93,7 +93,7 @@ LOG_A(" DEBUG:fd_ep_add_merge Address family was unknown, not added."); return 0; } - + /* remove the ACCEPTALL flag */ flags &= ~EP_ACCEPTALL; @@ -134,8 +134,10 @@ *ep_port = *port; break; } - if (*ep_port < *port) + if (*ep_port < *port) { + cmp = -1; continue; + } if (*ep_port > *port) cmp = 1; break; @@ -216,7 +218,8 @@ /* Now browse both lists in parallel */ while ((li_out != list) && (li_ex != exclude_list)) { int cmp; - + in_port_t * port_out, *port_ex; + out = (struct fd_endpoint *)li_out; ex = (struct fd_endpoint *)li_ex; @@ -234,9 +237,13 @@ switch (out->sa.sa_family) { case AF_INET: cmp = memcmp(&out->sin.sin_addr, &ex->sin.sin_addr, sizeof(struct in_addr)); + port_out = &out->sin.sin_port; + port_ex = &ex->sin.sin_port; break; case AF_INET6: cmp = memcmp(&out->sin6.sin6_addr, &ex->sin6.sin6_addr, sizeof(struct in6_addr)); + port_out = &out->sin6.sin6_port; + port_ex = &ex->sin6.sin6_port; break; default: /* Filter this out */ @@ -250,6 +257,17 @@ li_ex = li_ex->next; continue; } + + if (port_out && (*port_out != 0) && (*port_ex != 0)) { + if (*port_out < *port_ex) { + li_out = li_out->next; + continue; + } + if (*port_out > *port_ex) { + li_ex = li_ex->next; + continue; + } + } /* We remove this element then loop */ li = li_out; @@ -297,7 +315,7 @@ return *buf; } - CHECK_MALLOC_DO( fd_sa_dump_node_serv( FD_DUMP_STD_PARAMS, &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ), return NULL); + CHECK_MALLOC_DO( fd_sa_dump( FD_DUMP_STD_PARAMS, &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ), return NULL); CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{%s%s%s%s%s}", (ep->flags & EP_FL_CONF) ? "C" : "-", (ep->flags & EP_FL_DISC) ? "D" : "-", diff -r ccbd1426e04a -r d4371b7aa0ff libfdcore/p_ce.c --- a/libfdcore/p_ce.c Tue May 14 15:27:28 2013 +0800 +++ b/libfdcore/p_ce.c Tue May 14 18:01:31 2013 +0800 @@ -109,7 +109,6 @@ /* Add the AVP(s) -- not sure what is the purpose... We could probably only add the primary one ? */ for (li = fd_g_config->cnf_endpoints.next; li != &fd_g_config->cnf_endpoints; li = li->next) { struct fd_endpoint * ep = (struct fd_endpoint *)li; - CHECK_FCT( fd_msg_avp_new ( dictobj, 0, &avp ) ); CHECK_FCT( fd_msg_avp_value_encode ( &ep->ss, avp ) ); CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); diff -r ccbd1426e04a -r d4371b7aa0ff libfdcore/server.c --- a/libfdcore/server.c Tue May 14 15:27:28 2013 +0800 +++ b/libfdcore/server.c Tue May 14 18:01:31 2013 +0800 @@ -341,6 +341,8 @@ int empty_conf_ep = FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints); + struct fd_list filter_list = FD_LIST_INITIALIZER(filter_list); + /* SCTP */ if (!fd_g_config->cnf_flags.no_sctp) { #ifdef DISABLE_SCTP @@ -446,6 +448,33 @@ } } + /* we will filter this list and create endpoints with port information */ + #ifdef ADDRESS_AVP_INCLUDE_PORT + fd_list_move_end(&filter_list, &fd_g_config->cnf_endpoints); + while (!FD_IS_LIST_EMPTY(&filter_list)) { + struct fd_endpoint * ep = (struct fd_endpoint *)filter_list.next; + in_port_t * port = NULL; + fd_list_unlink(&ep->chain); + + switch( ep->sa.sa_family ) { + case AF_INET: port = &ep->sin.sin_port; break; + case AF_INET6: port = &ep->sin6.sin6_port; break; + } + + if (port) { + if (fd_g_config->cnf_port) { + *port = htons(fd_g_config->cnf_port); + CHECK_FCT(fd_ep_add_merge( &fd_g_config->cnf_endpoints, &ep->sa, sSAlen(&ep->sa), ep->flags )); + } + if (fd_g_config->cnf_port_tls) { + *port = htons(fd_g_config->cnf_port_tls); + CHECK_FCT(fd_ep_add_merge( &fd_g_config->cnf_endpoints, &ep->sa, sSAlen(&ep->sa), ep->flags )); + } + } + free(ep); + } + #endif /* ADDRESS_AVP_INCLUDE_PORT */ + { char * buf = NULL; size_t len = 0, offset = 0; diff -r ccbd1426e04a -r d4371b7aa0ff libfdcore/tcp.c --- a/libfdcore/tcp.c Tue May 14 15:27:28 2013 +0800 +++ b/libfdcore/tcp.c Tue May 14 18:01:31 2013 +0800 @@ -137,7 +137,7 @@ /* Cleanup if we are cancelled */ pthread_cleanup_push(fd_cleanup_socket, &s); - LOG_D( "Attempting TCP connection to %s...", fd_sa_dump_node(&buf, &len, NULL, sa, NI_NUMERICHOST | NI_NUMERICSERV)?:"" ); + LOG_D( "Attempting TCP connection to %s...", fd_sa_dump(&buf, &len, NULL, sa, NI_NUMERICHOST | NI_NUMERICSERV)?:"" ); free(buf); /* Try connecting to the remote address */ diff -r ccbd1426e04a -r d4371b7aa0ff libfdproto/dictionary_functions.c --- a/libfdproto/dictionary_functions.c Tue May 14 15:27:28 2013 +0800 +++ b/libfdproto/dictionary_functions.c Tue May 14 18:01:31 2013 +0800 @@ -73,11 +73,20 @@ AddressType = 1;/* see http://www.iana.org/assignments/address-family-numbers/ */ size = 6; /* 2 for AddressType + 4 for data */ + #ifdef ADDRESS_AVP_INCLUDE_PORT + if (sin->sin_port != 0) + size += 2; + #endif /* ADDRESS_AVP_INCLUDE_PORT */ CHECK_MALLOC( buf = malloc(size) ); /* may not work because of alignment: *(uint32_t *)(buf+2) = htonl(sin->sin_addr.s_addr); */ memcpy(buf + 2, &sin->sin_addr.s_addr, 4); + + #ifdef ADDRESS_AVP_INCLUDE_PORT + if (sin->sin_port != 0) + memcpy(buf + 6, &sin->sin_port, 2); + #endif /* ADDRESS_AVP_INCLUDE_PORT */ } break; @@ -88,11 +97,20 @@ AddressType = 2;/* see http://www.iana.org/assignments/address-family-numbers/ */ size = 18; /* 2 for AddressType + 16 for data */ + #ifdef ADDRESS_AVP_INCLUDE_PORT + if (sin6->sin6_port != 0) + size += 2; + #endif /* ADDRESS_AVP_INCLUDE_PORT */ CHECK_MALLOC( buf = malloc(size) ); /* The order is already good here */ memcpy(buf + 2, &sin6->sin6_addr.s6_addr, 16); + + #ifdef ADDRESS_AVP_INCLUDE_PORT + if (sin6->sin6_port != 0) + memcpy(buf + 18, &sin6->sin6_port, 2); + #endif /* ADDRESS_AVP_INCLUDE_PORT */ } break; @@ -125,11 +143,14 @@ { sSA4 * sin = (sSA4 *)interpreted; - CHECK_PARAMS( avp_value->os.len == 6 ); + CHECK_PARAMS( avp_value->os.len >= 6 ); sin->sin_family = AF_INET; /* sin->sin_addr.s_addr = ntohl( * (uint32_t *) buf); -- may not work because of bad alignment */ memcpy(&sin->sin_addr.s_addr, buf, 4); + + if (avp_value->os.len == 8) + memcpy(&sin->sin_port, buf + 4, 2); } break; @@ -137,10 +158,14 @@ { sSA6 * sin6 = (sSA6 *)interpreted; - CHECK_PARAMS( avp_value->os.len == 18 ); + CHECK_PARAMS( avp_value->os.len >= 18 ); sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr.s6_addr, buf, 16); + + if (avp_value->os.len == 20) + memcpy(&sin6->sin6_port, buf + 16, 2); + } break; @@ -178,27 +203,31 @@ case 1: /* IP */ s.sa.sa_family = AF_INET; - if (avp_value->os.len != 6) { + if ((avp_value->os.len != 6) && (avp_value->os.len != 8)) { CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP length: %zd]", avp_value->os.len), return NULL); return *buf; } memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4); + if (avp_value->os.len == 8) + memcpy(&s.sin.sin_port, avp_value->os.data + 6, 2); break; case 2: /* IP6 */ s.sa.sa_family = AF_INET6; - if (avp_value->os.len != 18) { + if ((avp_value->os.len != 18) && (avp_value->os.len != 20)) { CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP6 length: %zd]", avp_value->os.len), return NULL); return *buf; } memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16); + if (avp_value->os.len == 20) + memcpy(&s.sin6.sin6_port, avp_value->os.data + 18, 2); break; default: CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[unsupported family: 0x%hx]", fam), return NULL); return *buf; } - return fd_sa_dump_node(FD_DUMP_STD_PARAMS, &s.sa, NI_NUMERICHOST); + return fd_sa_dump(FD_DUMP_STD_PARAMS, &s.sa, NI_NUMERICHOST); } diff -r ccbd1426e04a -r d4371b7aa0ff libfdproto/utils.c --- a/libfdproto/utils.c Tue May 14 15:27:28 2013 +0800 +++ b/libfdproto/utils.c Tue May 14 18:01:31 2013 +0800 @@ -35,37 +35,29 @@ #include "fdproto-internal.h" -DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags) +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump, sSA * sa, int flags) { char addrbuf[INET6_ADDRSTRLEN]; + char servbuf[32]; + int rc; FD_DUMP_HANDLE_OFFSET(); + servbuf[0] = 0; + if (sa) { - int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), NULL, 0, flags); + if (sSAport(sa)) { + rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), flags); + } else { + rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), NULL, 0, flags); + } if (rc) { CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL); } else { - CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL); - } - } else { - CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL); - } - - return *buf; -} - -DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags) -{ - char addrbuf[INET6_ADDRSTRLEN]; - char servbuf[32]; - FD_DUMP_HANDLE_OFFSET(); - - if (sa) { - int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), flags); - if (rc) { - CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL); - } else { - CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%s)", &addrbuf[0], &servbuf[0]), return NULL); + if (servbuf[0]) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(%s)", &addrbuf[0], &servbuf[0]), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL); + } } } else { CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL);