changeset 1280:3eeb564e7bea

Merge updates from Thomas (thanks\!)
author Sebastien Decugis <sdecugis@freediameter.net>
date Sat, 03 Jan 2015 02:22:07 +0800
parents c748e2439a3a (current diff) a1685a53fe97 (diff)
children ab6457399be2
files
diffstat 11 files changed, 361 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/test_Gx/main_gx.c	Sat Jan 03 02:18:53 2015 +0800
+++ b/contrib/test_Gx/main_gx.c	Sat Jan 03 02:22:07 2015 +0800
@@ -13,58 +13,13 @@
 #define VENDOR_ID_3GPP  			    10415
 /* The content of this file follows the same structure as dict_base_proto.c */
 
+#if 0
 #define CHECK_dict_new( _type, _data, _parent, _ref )  \
        CHECK_FCT(  fd_dict_new( fd_g_config->cnf_dict, (_type), (_data), (_parent), (_ref))  );
-
-#define CHECK_dict_search( _type, _criteria, _what, _result )  \
-       CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, (_type), (_criteria), (_what), (_result), ENOENT) );
+#endif
 
 void dump_sess_eyec(struct session *sess, const char *);
-struct local_rules_definition {
-       char		       *avp_name;
-       enum rule_position      position;
-       int		       min;
-       int		       max;
-};
 
-#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )
-
-#define PARSE_loc_rules( _rulearray, _parent) { 							       \
-       int __ar;										       \
-       for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {		       \
-	       struct dict_rule_data __data = { NULL,						       \
-		       (_rulearray)[__ar].position,						       \
-		       0,									       \
-		       (_rulearray)[__ar].min,  						       \
-		       (_rulearray)[__ar].max}; 						       \
-	       __data.rule_order = RULE_ORDER(__data.rule_position);				       \
-	       CHECK_FCT(  fd_dict_search(							       \
-		       fd_g_config->cnf_dict,							       \
-		       DICT_AVP,								       \
-		       AVP_BY_NAME,								       \
-		       (_rulearray)[__ar].avp_name,						       \
-		       &__data.rule_avp, 0 ) ); 						       \
-	       if ( !__data.rule_avp ) {							       \
-		       TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );         \
-		       return ENOENT;								       \
-	       }										       \
-	       CHECK_FCT_DO( fd_dict_new( fd_g_config->cnf_dict, DICT_RULE, &__data, _parent, NULL),   \
-		       {									       \
-			       TRACE_DEBUG(INFO, "Error on rule with AVP '%s'", 		       \
-					(_rulearray)[__ar].avp_name );  			       \
-			       return EINVAL;							       \
-		       } );									       \
-       }											       \
-}
-
-#define enumval_def_u32( _val_, _str_ ) \
-	       { _str_, 	       { .u32 = _val_ }}
-
-#define enumval_def_os( _len_, _val_, _str_ ) \
-	       { _str_, 	       { .os = { .data = (unsigned char *)_val_, .len = _len_ }}}
-
-
- 
 static int ccr_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
 static int reauth_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
 static int cca_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
@@ -287,7 +242,7 @@
     CHECK_FCT( fd_event_trig_regcb(SIGUSR1, "app_gx", sig_hdlr ) );
 
 
-       TRACE_DEBUG(INFO, "Extension 'Dictionary definitions for DCCA (rfc4006)' initialized");
+       TRACE_DEBUG(INFO, "Extension 'Gx' initialized");
        return 0;
 }
 
@@ -860,5 +815,5 @@
 {
  return 0;
 }
-EXTENSION_ENTRY( "app_gx", app_gx_entry, "dict_dcca");
+EXTENSION_ENTRY( "app_gx", app_gx_entry, "dict_dcca_3gpp");
 //EXTENSION_ENTRY( "app_gx", gx_entry);
--- a/extensions/CMakeLists.txt	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/CMakeLists.txt	Sat Jan 03 02:22:07 2015 +0800
@@ -67,12 +67,13 @@
 ####
 # Routing extensions
 
+FD_EXTENSION_SUBDIR(rt_busypeers "Handling of Diameter TOO_BUSY messages and relay timeouts"	ON)
 FD_EXTENSION_SUBDIR(rt_default   "Configurable routing rules for freeDiameter" 		     	ON)
-FD_EXTENSION_SUBDIR(rt_redirect  "Handling of Diameter Redirect messages" 			ON)
-FD_EXTENSION_SUBDIR(rt_busypeers "Handling of Diameter TOO_BUSY messages and relay timeouts"	ON)
 FD_EXTENSION_SUBDIR(rt_ereg      "Configurable routing based on regexp matching of AVP values" OFF)
 FD_EXTENSION_SUBDIR(rt_ignore_dh "Stow Destination-Host in Proxy-Info, restore to Origin-Host for answers"	ON)
 FD_EXTENSION_SUBDIR(rt_load_balance "Balance load over multiple equal hosts, based on outstanding requests"	ON)
+FD_EXTENSION_SUBDIR(rt_randomize "Randomly choose one of the highest scored hosts and increase its score by one"	ON)
+FD_EXTENSION_SUBDIR(rt_redirect  "Handling of Diameter Redirect messages" 			ON)
 
 
 ####
--- a/extensions/dict_dcca_starent/dict_dcca_starent.c	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/dict_dcca_starent/dict_dcca_starent.c	Sat Jan 03 02:22:07 2015 +0800
@@ -87,10 +87,12 @@
 	/* The following is created automatically. Do not modify. */
 	/* Changes will be lost during the next update. Modify the source org file instead. */
 
-	/* Cisco ASR 5000 Series AAA Interface  */
-	/* Administration and Reference         */
-	/* Release 8.x and 9.0                  */
-	/* Last Updated June 30, 2010           */
+	/* Cisco ASR 5000 Series AAA Interface                                              */
+	/* Administration and Reference                                                     */
+	/* Release 8.x and 9.0                                                              */
+	/* Last Updated June 30, 2010                                                       */
+	/* updated using v15 docs from Jan 2014                                             */
+	/* www.cisco.com/c/dam/en/us/td/docs/wireless/asr_5000/15-0/15-0-AAA-Reference.pdf  */
 	/* SN-Volume-Quota-Threshold */
 	{
 		struct dict_avp_data data = {
@@ -282,9 +284,159 @@
 		CHECK_dict_new(DICT_AVP, &data, type, NULL);
 	};
 
+	/* SN-Session-Start-Indicator */
+	{
+		struct dict_avp_data data = {
+			522,	/* Code */
+			8164,	/* Vendor */
+			"SN-Session-Start-Indicator",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Phase0-PSAPName */
+	{
+		struct dict_avp_data data = {
+			523,	/* Code */
+			8164,	/* Vendor */
+			"SN-Phase0-PSAPName",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-Charging-Id */
+	{
+		struct dict_avp_data data = {
+			525,	/* Code */
+			8164,	/* Vendor */
+			"SN-Charging-Id",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Remaining-Service-Unit */
+	{
+		struct dict_avp_data data = {
+			526,	/* Code */
+			8164,	/* Vendor */
+			"SN-Remaining-Service-Unit",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_GROUPED	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Service-Start-Timestamp */
+	{
+		struct dict_avp_data data = {
+			527,	/* Code */
+			8164,	/* Vendor */
+			"SN-Service-Start-Timestamp",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, Time_type, NULL);
+	};
+
+	/* SN-Rulebase-Id */
+	{
+		struct dict_avp_data data = {
+			528,	/* Code */
+			8164,	/* Vendor */
+			"SN-Rulebase-Id",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-CF-Policy-ID */
+	{
+		struct dict_avp_data data = {
+			529,	/* Code */
+			8164,	/* Vendor */
+			"SN-CF-Policy-ID",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_UNSIGNED32	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Charging-Collection-Function-Name */
+	{
+		struct dict_avp_data data = {
+			530,	/* Code */
+			8164,	/* Vendor */
+			"SN-Charging-Collection-Function-Name",	/* Name */
+			AVP_FLAG_VENDOR,	/* Fixed flags */
+			AVP_FLAG_VENDOR,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, UTF8String_type, NULL);
+	};
+
+	/* SN-Fast-Reauth-Username */
+	{
+		struct dict_avp_data data = {
+			11010,	/* Code */
+			8164,	/* Vendor */
+			"SN-Fast-Reauth-Username",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+	/* SN-Pseudonym-Username */
+	{
+		struct dict_avp_data data = {
+			11011,	/* Code */
+			8164,	/* Vendor */
+			"SN-Pseudonym-Username",	/* Name */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flags */
+			AVP_FLAG_VENDOR |AVP_FLAG_MANDATORY,	/* Fixed flag values */
+			AVP_TYPE_OCTETSTRING	/* base type of data */
+		};
+		CHECK_dict_new(DICT_AVP, &data, NULL, NULL);
+	};
+
+
 
 	/* Rules section */
 
+	/* SN-Remaining-Service-Unit */
+	{
+		struct dict_object *rule_avp;
+		struct dict_avp_request vpa;
+		vpa.avp_vendor = 8164;
+		vpa.avp_name = "SN-Remaining-Service-Unit";
+		CHECK_dict_search(DICT_AVP, AVP_BY_NAME_AND_VENDOR, &vpa, &rule_avp);
+		struct local_rules_definition rules[] = {
+			{  "Tariff-Change-Usage",	RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Time",	       		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Total-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Input-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Output-Octets",		RULE_OPTIONAL,	-1, 1 },
+			{  "CC-Service-Specific-Units",	RULE_OPTIONAL,	-1, 1 },
+			{  "Reporting-Reason",		RULE_OPTIONAL,	-1, 1 }
+		};
+		PARSE_loc_rules( rules, rule_avp );
+	}
+
 	/* SN-Total-Used-Service-Unit */
 	{
 		struct dict_object *rule_avp;
--- a/extensions/dict_dcca_starent/dict_dcca_starent.org	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/dict_dcca_starent/dict_dcca_starent.org	Sat Jan 03 02:22:07 2015 +0800
@@ -1,19 +1,31 @@
-| Attribute Name                        | Code | Section defined | Value Type  | MUST | MAY | SHLD NOT | MUST NOT | Encr |
-| # Cisco ASR 5000 Series AAA Interface |      |                 |             |      |     |          |          |      |
-| # Administration and Reference        |      |                 |             |      |     |          |          |      |
-| # Release 8.x and 9.0                 |      |                 |             |      |     |          |          |      |
-| # Last Updated June 30, 2010          |      |                 |             |      |     |          |          |      |
-| SN-Volume-Quota-Threshold             |  501 |                 | Unsigned32  | M,V  |     |          |          |      |
-| SN-Unit-Quota-Threshold               |  502 |                 | Unsigned32  | M,V  |     |          |          |      |
-| SN-Time-Quota-Threshold               |  503 |                 | Unsigned32  | M,V  |     |          |          |      |
-| SN-Total-Used-Service-Unit            |  504 |                 | Grouped     | V    |     |          |          |      |
-| SN-Absolute-Validity-Time             |  505 |                 | Time        | V    |     |          |          |      |
-| SN-Bandwidth-Control                  |  512 |                 | Enumerated  | M,V  |     |          |          |      |
-| SN-Transparent-Data                   |  513 |                 | OctetString | V    |     |          |          |      |
-| SN-Traffic-Policy                     |  514 |                 | UTF8String  | V    |     |          |          |      |
-| SN-Firewall-Policy                    |  515 |                 | UTF8String  | V    |     |          |          |      |
-| SN-Usage-Monitoring-Control           |  517 |                 | Grouped     | V    |     |          |          |      |
-| SN-Monitoring-Key                     |  518 |                 | Unsigned32  | V    |     |          |          |      |
-| SN-Usage-Volume                       |  519 |                 | Unsigned64  | V    |     |          |          |      |
-| SN-Service-Flow-Detection             |  520 |                 | Enumerated  | V    |     |          |          |      |
-| SN-Usage-Monitoring                   |  521 |                 | Enumerated  | V    |     |          |          |      |
+| Attribute Name                                                                    |  Code | Section defined | Value Type  | MUST | MAY | SHLD NOT | MUST NOT | Encr |
+| # Cisco ASR 5000 Series AAA Interface                                             |       |                 |             |      |     |          |          |      |
+| # Administration and Reference                                                    |       |                 |             |      |     |          |          |      |
+| # Release 8.x and 9.0                                                             |       |                 |             |      |     |          |          |      |
+| # Last Updated June 30, 2010                                                      |       |                 |             |      |     |          |          |      |
+| # updated using v15 docs from Jan 2014                                            |       |                 |             |      |     |          |          |      |
+| # www.cisco.com/c/dam/en/us/td/docs/wireless/asr_5000/15-0/15-0-AAA-Reference.pdf |       |                 |             |      |     |          |          |      |
+| SN-Volume-Quota-Threshold                                                         |   501 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Unit-Quota-Threshold                                                           |   502 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Time-Quota-Threshold                                                           |   503 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Total-Used-Service-Unit                                                        |   504 |                 | Grouped     | V    |     |          |          |      |
+| SN-Absolute-Validity-Time                                                         |   505 |                 | Time        | V    |     |          |          |      |
+| SN-Bandwidth-Control                                                              |   512 |                 | Enumerated  | M,V  |     |          |          |      |
+| SN-Transparent-Data                                                               |   513 |                 | OctetString | V    |     |          |          |      |
+| SN-Traffic-Policy                                                                 |   514 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Firewall-Policy                                                                |   515 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Usage-Monitoring-Control                                                       |   517 |                 | Grouped     | V    |     |          |          |      |
+| SN-Monitoring-Key                                                                 |   518 |                 | Unsigned32  | V    |     |          |          |      |
+| SN-Usage-Volume                                                                   |   519 |                 | Unsigned64  | V    |     |          |          |      |
+| SN-Service-Flow-Detection                                                         |   520 |                 | Enumerated  | V    |     |          |          |      |
+| SN-Usage-Monitoring                                                               |   521 |                 | Enumerated  | V    |     |          |          |      |
+| SN-Session-Start-Indicator                                                        |   522 |                 | OctetString | M,V  |     |          |          |      |
+| SN-Phase0-PSAPName                                                                |   523 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Charging-Id                                                                    |   525 |                 | OctetString | V    |     |          |          |      |
+| SN-Remaining-Service-Unit                                                         |   526 |                 | Grouped     | V    |     |          |          |      |
+| SN-Service-Start-Timestamp                                                        |   527 |                 | Time        | V    |     |          |          |      |
+| SN-Rulebase-Id                                                                    |   528 |                 | UTF8String  | M,V  |     |          |          |      |
+| SN-CF-Policy-ID                                                                   |   529 |                 | Unsigned32  | M,V  |     |          |          |      |
+| SN-Charging-Collection-Function-Name                                              |   530 |                 | UTF8String  | V    |     |          |          |      |
+| SN-Fast-Reauth-Username                                                           | 11010 |                 | OctetString | M,V  |     |          |          |      |
+| SN-Pseudonym-Username                                                             | 11011 |                 | OctetString | M,V  |     |          |          |      |
--- a/extensions/rt_busypeers/rtbusy.c	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/rt_busypeers/rtbusy.c	Sat Jan 03 02:22:07 2015 +0800
@@ -49,7 +49,7 @@
 	struct msg * qry = NULL;
 	struct rt_data * rtd = NULL;
 	struct fd_list * candidates = NULL;
-	int sendingattemtps;
+	int sendingattempts;
 	int resend = 1;
 	
 	
@@ -72,13 +72,13 @@
 				    (uint8_t *)(oh ? (DiamId_t)oh->os.data : fd_g_config->cnf_diamid), oh ? oh->os.len : fd_g_config->cnf_diamid_len , 
 	                            ER_DIAMETER_TOO_BUSY, 
 	                            &candidates, 
-	                            &sendingattemtps) );
+	                            &sendingattempts) );
 	
 	/* Now we need to decide if we re-send this query to a different peer or return an error to upstream */
 	
 	/* First, are we exceeding the allowed attempts? */
 	if (rtbusy_conf.RetryMaxPeers != 0) {
-		if (sendingattemtps >= rtbusy_conf.RetryMaxPeers) {
+		if (sendingattempts >= rtbusy_conf.RetryMaxPeers) {
 			TRACE_DEBUG(FULL, "Maximum number of sending attempts reached for message %p, returning an error upstream", qry);
 			resend = 0;
 		}
@@ -106,10 +106,16 @@
 		}
 		/* Send the query again. We  need to re-associate the expirecb which was cleaned, if it is used */
 		if (rtbusy_conf.RelayTimeout) {
+			char *buf = NULL;
+			size_t len;
 			struct timespec expire;
 			CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &expire)  );
 			expire.tv_sec += rtbusy_conf.RelayTimeout/1000 + ((expire.tv_nsec + (1000000LL * (rtbusy_conf.RelayTimeout % 1000))) / 1000000000LL);
 			expire.tv_nsec = (expire.tv_nsec + (1000000LL * (rtbusy_conf.RelayTimeout % 1000))) % 1000000000LL;
+			CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, *pmsg, fd_g_config->cnf_dict, 0, 1), /* nothing */);
+			TRACE_ERROR( "No answer received for message from peer '%.*s' before timeout (%dms), re-sending: %s", senttolen, sentto,
+				     rtbusy_conf.RelayTimeout, buf);
+			free(buf);
 			CHECK_FCT( fd_msg_send_timeout( pmsg, NULL, NULL, rtbusy_expirecb, &expire ) );
 		} else {
 			CHECK_FCT( fd_msg_send(pmsg, NULL, NULL) );
@@ -117,6 +123,13 @@
 	
 	} else {
 		if (is_req) {
+			char *buf = NULL;
+			size_t len;
+
+			CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, *pmsg, fd_g_config->cnf_dict, 0, 1), /* nothing */);
+			TRACE_ERROR( "No answer received for message from peer '%.*s' before timeout (%dms), giving up and sending error reply: %s", senttolen, sentto,
+				     rtbusy_conf.RelayTimeout, buf);
+			free(buf);
 			/* We must create an answer */
 			CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, pmsg, MSGFL_ANSW_ERROR ) );
 			
--- a/extensions/rt_ignore_dh/rt_ignore_dh.c	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/rt_ignore_dh/rt_ignore_dh.c	Sat Jan 03 02:22:07 2015 +0800
@@ -42,15 +42,6 @@
 struct dict_object * pi_avp_do; /* cache the Proxy-Info dictionary object */
 struct dict_object * ps_avp_do; /* cache the Proxy-State dictionary object */
 
-static void *memdup(void *data, size_t len)
-{
-	void *mem;
-	if ((mem=malloc(len)) == NULL)
-		return NULL;
-	memcpy(mem, data, len);
-	return mem;
-}
-
 static int restore_origin_host(struct msg **msg) {
 	struct avp *avp, *child;
 	struct avp *oh_avp = NULL;
@@ -91,12 +82,8 @@
 							}
 							break;
 						case AC_PROXY_STATE:
+							ps = chdr->avp_value->os.data;
 							ps_len = chdr->avp_value->os.len;
-							ps = memdup(chdr->avp_value->os.data, ps_len);
-							if (!ps) {
-								TRACE_ERROR("malloc failure");
-								return 0;
-							}
 							break;
 						default:
 							break;
@@ -108,8 +95,7 @@
 					new_oh = ps;
 					new_oh_len = ps_len;
 					pi_avp = avp;
-				} else
-					free(ps);
+				}
 				break;
 			default:
 				break;
@@ -151,13 +137,13 @@
 			/* add Proxy-Info->{Proxy-Host, Proxy-State} using Destination-Host information */
 			CHECK_FCT(fd_msg_avp_new(ph_avp_do, 0, &ph_avp));
 			memset(&val, 0, sizeof(val));
-                        val.os.data = memdup(fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len);
+                        val.os.data = fd_g_config->cnf_diamid;
 			val.os.len = fd_g_config->cnf_diamid_len;
 			CHECK_FCT(fd_msg_avp_setvalue(ph_avp, &val));
 
 			CHECK_FCT(fd_msg_avp_new(ps_avp_do, 0, &ps_avp));
 			memset(&val, 0, sizeof(val));
-			val.os.data = memdup(ahdr->avp_value->os.data, ahdr->avp_value->os.len);
+			val.os.data = ahdr->avp_value->os.data;
 			val.os.len = ahdr->avp_value->os.len;
 			CHECK_FCT(fd_msg_avp_setvalue(ps_avp, &val));
 
--- a/extensions/rt_load_balance/CMakeLists.txt	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/rt_load_balance/CMakeLists.txt	Sat Jan 03 02:22:07 2015 +0800
@@ -2,14 +2,14 @@
 PROJECT("Routing extension splits requests evenly over multiple hosts, using current load as routing indicator" C)
 
 # List of source files
-SET(RT_IGNORE_DH_SRC
+SET(RT_LOAD_BALANCE_SRC
 	rt_load_balance.c
 )
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
 # Compile these files as a freeDiameter extension
-FD_ADD_EXTENSION(rt_load_balance ${RT_IGNORE_DH_SRC})
+FD_ADD_EXTENSION(rt_load_balance ${RT_LOAD_BALANCE_SRC})
 
 ####
 ## INSTALL section ##
--- a/extensions/rt_load_balance/rt_load_balance.c	Sat Jan 03 02:18:53 2015 +0800
+++ b/extensions/rt_load_balance/rt_load_balance.c	Sat Jan 03 02:22:07 2015 +0800
@@ -2,7 +2,7 @@
 * Software License Agreement (BSD License)                                                               *
 * Author: Thomas Klausner <tk@giga.or.at>                                                                *
 *                                                                                                        *
-* Copyright (c) 2013, Thomas Klausner                                                                    *
+* Copyright (c) 2013, 2014 Thomas Klausner                                                               *
 * All rights reserved.                                                                                   *
 *                                                                                                        *
 * Written under contract by nfotex IT GmbH, http://nfotex.com/                                           *
@@ -58,12 +58,18 @@
 		CHECK_FCT(fd_peer_getbyid(cand->diamid, cand->diamidlen, 0, &peer));
 		CHECK_FCT(fd_peer_get_load_pending(peer, &to_receive, &to_send));
                 load = to_receive + to_send;
-		score = cand->score;
-		if ((cand->score > 0) && (load >= cand->score))
-			cand->score = 1;
-		else
-			cand->score -= load;
-		TRACE_DEBUG(INFO, "evaluated peer `%.*s', score was %d, now %d", (int)cand->diamidlen, cand->diamid, score, cand->score);
+		/* other routing mechanisms need to add to the
+		 * appropriate entries so their base value is high
+		 * enough that they are considered */
+
+		/* logarithmic scaling */
+                int load_log = 0;
+                while (load > 0) {
+                    load_log++;
+                    load /= 2;
+                }
+		cand->score -= load_log;
+		TRACE_DEBUG(FULL, "evaluated peer `%.*s', score was %d, now %d", (int)cand->diamidlen, cand->diamid, score, cand->score);
 	}
 
 	return 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/rt_randomize/CMakeLists.txt	Sat Jan 03 02:22:07 2015 +0800
@@ -0,0 +1,20 @@
+# The rt_randomize extension
+PROJECT("Routing extension randomly increases the routing count for one of the highest-rated hosts, if there are multiple ones" C)
+
+# List of source files
+SET(RT_RANDOMIZE_SRC
+	rt_randomize.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+# Compile these files as a freeDiameter extension
+FD_ADD_EXTENSION(rt_randomize ${RT_RANDOMIZE_SRC})
+
+####
+## INSTALL section ##
+
+# We install with the daemon component because it is a base feature.
+INSTALL(TARGETS rt_randomize
+	LIBRARY DESTINATION ${INSTALL_EXTENSIONS_SUFFIX}
+	COMPONENT freeDiameter-daemon)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/rt_randomize/rt_randomize.c	Sat Jan 03 02:22:07 2015 +0800
@@ -0,0 +1,111 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Thomas Klausner <tk@giga.or.at>                                                                *
+*                                                                                                        *
+* Copyright (c) 2014 Thomas Klausner                                                                     *
+* All rights reserved.                                                                                   *
+*                                                                                                        *
+* Written under contract by nfotex IT GmbH, http://nfotex.com/                                           *
+*                                                                                                        *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:                                              *
+*                                                                                                        *
+* * Redistributions of source code must retain the above                                                 *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer.                                                                                *
+*                                                                                                        *
+* * Redistributions in binary form must reproduce the above                                              *
+*   copyright notice, this list of conditions and the                                                    *
+*   following disclaimer in the documentation and/or other                                               *
+*   materials provided with the distribution.                                                            *
+*                                                                                                        *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
+*********************************************************************************************************/
+
+#include <freeDiameter/extension.h>
+
+/*
+ * Load balancing extension. If there are multiple highest-rated hosts with the same score,
+ * randomly increase the score of one of them.
+ */
+
+#include <stdlib.h>
+
+static int seed;
+
+static int rt_randomizing(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct fd_list *lic;
+	struct msg * msg = *pmsg;
+	int max_score = -1;
+	int max_score_count = 0;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Check if it is worth processing the message */
+	if (FD_IS_LIST_EMPTY(candidates))
+		return 0;
+
+	/* find out maximal score and how many candidates have it */
+	for (lic = candidates->next; lic != candidates; lic = lic->next) {
+		struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+		if (max_score < cand->score) {
+			max_score = cand->score;
+			max_score_count = 1;
+		}
+		else if (cand->score == max_score) {
+			max_score_count++;
+		}
+	}
+
+	/* if there is more than one with positive score, randomly increase one of their scores by one */
+	if (max_score >= 0 && max_score_count > 1) {
+		int lucky_candidate = rand_r(&seed) % max_score_count;
+		int i = 0;
+
+		for (lic = candidates->next; lic != candidates; lic = lic->next) {
+			struct rtd_candidate * cand = (struct rtd_candidate *) lic;
+			if (cand->score == max_score) {
+				if (i == lucky_candidate) {
+					cand->score++;
+					break;
+				}
+				i++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* handler */
+static struct fd_rt_out_hdl * rt_randomizing_hdl = NULL;
+
+/* entry point */
+static int rt_randomize_entry(char * conffile)
+{
+	/* Register the callback */
+	CHECK_FCT(fd_rt_out_register(rt_randomizing, NULL, 4, &rt_randomizing_hdl));
+	seed = (int)time(NULL);
+	TRACE_DEBUG(INFO, "Extension 'Randomizing' initialized");
+	return 0;
+}
+
+/* Unload */
+void fd_ext_fini(void)
+{
+	/* Unregister the callbacks */
+	CHECK_FCT_DO(fd_rt_out_unregister(rt_randomizing_hdl, NULL), /* continue */);
+	return ;
+}
+
+EXTENSION_ENTRY("rt_randomize", rt_randomize_entry);
--- a/libfdcore/routing_dispatch.c	Sat Jan 03 02:18:53 2015 +0800
+++ b/libfdcore/routing_dispatch.c	Sat Jan 03 02:22:07 2015 +0800
@@ -878,7 +878,7 @@
 
 		/* Find the peer corresponding to this name */
 		CHECK_FCT( fd_peer_getbyid( qry_src, qry_src_len, 0, (void *) &peer ) );
-		if (fd_peer_getstate(peer) != STATE_OPEN) {
+		if (fd_peer_getstate(peer) != STATE_OPEN && fd_peer_getstate(peer) != STATE_CLOSING_GRACE) {
 			char buf[128];
 			snprintf(buf, sizeof(buf), "Unable to forward answer to deleted / closed peer '%s'.", qry_src);
 			fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
"Welcome to our mercurial repository"