changeset 1122:d4371b7aa0ff

New CMake option: ADDRESS_AVP_INCLUDE_PORT. Turn off for standard Host-IP-Address AVPs
author Sebastien Decugis <sdecugis@freediameter.net>
date Tue, 14 May 2013 18:01:31 +0800
parents ccbd1426e04a
children 8027ffc7641e
files include/freeDiameter/CMakeLists.txt include/freeDiameter/freeDiameter-host.h.in include/freeDiameter/libfdcore.h include/freeDiameter/libfdproto.h libfdcore/endpoints.c libfdcore/p_ce.c libfdcore/server.c libfdcore/tcp.c libfdproto/dictionary_functions.c libfdproto/utils.c
diffstat 10 files changed, 112 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- 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)
 
 ########################
--- 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
--- 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 {
--- 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);
 
--- 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" : "-",
--- 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 ) );
--- 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;
--- 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)?:"<error>" );
+	LOG_D( "Attempting TCP connection to %s...", fd_sa_dump(&buf, &len, NULL, sa, NI_NUMERICHOST | NI_NUMERICSERV)?:"<error>" );
 	free(buf);
 	
 	/* Try connecting to the remote address */
--- 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);
 }
 
 
--- 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);
"Welcome to our mercurial repository"