Index: extensions/app_radgw/rgw_clients.c
===================================================================
--- extensions/app_radgw/rgw_clients.c	(revision 554)
+++ extensions/app_radgw/rgw_clients.c	(revision 706)
@@ -86,8 +86,12 @@
 	int			 is_local; /* true if the RADIUS client runs on the same host -- we use Diameter Identity in that case */
 	enum rgw_cli_type 	 type; /* is it a proxy ? */
-	char 			*fqdn;
+	DiamId_t		 fqdn; /* malloc'd here */
 	size_t			 fqdn_len;
-	char			*realm;
-	char			**aliases;
+	DiamId_t		 realm; /* references another string, do not free */
+	size_t			 realm_len;
+	struct {
+		os0_t		 name;
+		size_t		 len;
+	}			*aliases; /* Received aliases */
 	size_t			 aliases_nb;
 	
@@ -210,5 +214,6 @@
 {
 	struct rgw_client *tmp = NULL;
-	char buf[255];
+	DiamId_t fqdn;
+	size_t fqdn_len;
 	int ret, i;
 	int loc = 0;
@@ -220,4 +225,5 @@
 		loc = 1;
 	} else {
+		char buf[255];
 	
 		/* Search FQDN for the client */
@@ -227,4 +233,10 @@
 			return EINVAL;
 		}
+		fqdn = &buf[0];
+		CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&fqdn, &fqdn_len, 1),
+			{
+				TRACE_DEBUG(INFO, "Unable to use resolved peer name '%s' as DiameterIdentity: %s", buf, strerror(ret));
+				return ret;
+			} );
 	}
 	
@@ -246,12 +258,17 @@
 	} else {
 		/* Copy the fqdn */
-		CHECK_MALLOC( tmp->fqdn = strdup(buf) );
-		tmp->fqdn_len = strlen(tmp->fqdn);
+		tmp->fqdn = fqdn;
+		tmp->fqdn_len = fqdn_len;
+
 		/* Find an appropriate realm */
-		tmp->realm = strchr(tmp->fqdn, '.');
-		if (tmp->realm)
+		tmp->realm = strchr(fqdn, '.');
+		if (tmp->realm) {
 			tmp->realm += 1;
-		if ((!tmp->realm) || (*tmp->realm == '\0')) /* in case the fqdn was "localhost." for example, if it is possible... */
+			tmp->realm_len = tmp->fqdn_len - (tmp->realm - fqdn);
+		}
+		if ((!tmp->realm) || (*tmp->realm == '\0')) { /* in case the fqdn was "localhost." for example, if it is possible... */
 			tmp->realm = fd_g_config->cnf_diamrlm;
+			tmp->realm_len = fd_g_config->cnf_diamrlm_len;
+		}
 	}
 	
@@ -282,5 +299,5 @@
 		/* Free the data */
 		for (idx = 0; idx < client->aliases_nb; idx++)
-			free(client->aliases[idx]);
+			free(client->aliases[idx].name);
 		free(client->aliases);
 		free(client->fqdn);
@@ -532,7 +549,8 @@
 	int valid_nas_info = 0;
 	struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL;
-	char * oh_str = NULL;
-	char * or_str = NULL;
-	char * rr_str = NULL;
+	size_t nas_id_len;
+	char * oh_str = NULL; size_t oh_strlen; int oh_free = 0;
+	char * or_str = NULL; size_t or_strlen;
+	char * rr_str = NULL; size_t rr_strlen;
 	char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */
 	
@@ -555,4 +573,5 @@
 		if ((attr->type == RADIUS_ATTR_NAS_IDENTIFIER) && (attr_len > 0)) {
 			nas_id = attr;
+			nas_id_len = attr_len;
 			continue;
 		}
@@ -568,5 +587,5 @@
 		
 		/* Get information on this peer */
-		CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+		CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 		
 		goto diameter;
@@ -619,10 +638,12 @@
 				return EINVAL;
 			} else {
+				int ret;
+				sSS ss;
 				/* the peer is configured as a proxy, or running on localhost, so accept the message */
-				sSS ss;
 				
 				/* In that case, the cli will be stored as Route-Record and the NAS-IP-Address as origin */
 				if (!cli->is_local) {
 					rr_str = cli->fqdn;
+					rr_strlen = cli->fqdn_len;
 				}
 				
@@ -641,5 +662,5 @@
 					{
 						if (cli->is_local) {
-							CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+							CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 							goto diameter;
 						}
@@ -648,6 +669,18 @@
 						return EINVAL;
 					} );
+					
+				oh_str = &buf[0];
+				CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
+					{
+						if (cli->is_local) {
+							CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
+							goto diameter;
+						}
+						
+						TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
+						return ret;
+					} );
+				oh_free = 1;
 				
-				oh_str = &buf[0];
 				or_str = strchr(oh_str, '.');
 				if (or_str) {
@@ -655,9 +688,11 @@
 					if (*or_str == '\0')
 						or_str = NULL; /* Discard this realm, we will use the local realm later */
+					else
+						or_strlen = oh_strlen - (or_str - oh_str);
 				}
 			}
 		} else {
 			/* The attribute matches the source address, just use this in origin-host */
-			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 		}
 		
@@ -668,5 +703,5 @@
 	if (cli->is_local) {
 		/* Simple: we use our own configuration */
-		CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+		CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 		goto diameter;
 	}
@@ -697,12 +732,12 @@
 		
 		/* first, check if the nas_id is the fqdn of the peer or a known alias */
-		if ((cli->fqdn_len == (nas_id->length - sizeof(struct radius_attr_hdr))) 
-		&& (!strncasecmp((char *)(nas_id + 1), cli->fqdn, nas_id->length - sizeof(struct radius_attr_hdr)))) {
+		if (!fd_os_almostcasecmp(nas_id + 1, nas_id_len, 
+						cli->fqdn, cli->fqdn_len)) {
 			TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client");
 			found = 1;
 		} else {
 			for (idx = 0; idx < cli->aliases_nb; idx++) {
-				if (((nas_id->length - sizeof(struct radius_attr_hdr)) == strlen(cli->aliases[idx])) 
-				&& (!strncasecmp((char *)(nas_id + 1), cli->aliases[idx], nas_id->length - sizeof(struct radius_attr_hdr)))) {
+				if (!fd_os_cmp(nas_id + 1, nas_id_len, 
+						cli->aliases[idx].name, cli->aliases[idx].len)) {
 					TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache");
 					found = 1;
@@ -714,5 +749,5 @@
 		if (found) {
 			/* The NAS-Identifier matches the source IP */
-			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 
 			goto diameter;
@@ -720,6 +755,6 @@
 		
 		/* Attempt DNS resolution of the identifier */
-		ASSERT( nas_id->length - sizeof(struct radius_attr_hdr) < sizeof(buf) );
-		memcpy(buf, nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr));
+		ASSERT( nas_id_len < sizeof(buf) );
+		memcpy(buf, nas_id + 1, nas_id_len);
 		buf[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0';
 		
@@ -745,5 +780,5 @@
 				if (cli->type == RGW_CLI_NAS) {
 					TRACE_DEBUG(INFO, "The NAS-Identifier value '%.*s' resolves to a different IP than the client's, discarding the message. \nConfigure this client as a Proxy if this message should be valid.", 
-						nas_id->length - sizeof(struct radius_attr_hdr), nas_id + 1);
+						nas_id_len, nas_id + 1);
 					return EINVAL;
 				} else {
@@ -751,6 +786,13 @@
 					if (!cli->is_local) {
 						rr_str = cli->fqdn;
+						rr_strlen = cli->fqdn_len;
 					}
 					oh_str = &buf[0]; /* The canonname resolved */
+					CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
+						{
+							TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
+							return ret;
+						} );
+					oh_free = 1;
 					or_str = strchr(oh_str, '.');
 					if (or_str) {
@@ -758,15 +800,18 @@
 						if (*or_str == '\0')
 							or_str = NULL; /* Discard this realm, we will use the local realm later */
+						else
+							or_strlen = oh_strlen - (or_str - oh_str);
 					}
 				}
 			} else {
 				/* It is a valid alias, save it */
-				CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(char *)) );
-				CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1] = malloc( 1 + nas_id->length - sizeof(struct radius_attr_hdr) ));
-				memcpy( cli->aliases[cli->aliases_nb + 1], nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr));
-				*(cli->aliases[cli->aliases_nb + 1] + nas_id->length - sizeof(struct radius_attr_hdr)) = '\0';
+				CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(cli->aliases[0])) );
+				
+				CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1].name = os0dup(nas_id + 1, nas_id_len ) );
+				cli->aliases[cli->aliases_nb + 1].len = nas_id_len;
+
 				cli->aliases_nb ++;
-				TRACE_DEBUG(FULL, "Saved valid alias for client: '%s' -> '%s'", cli->aliases[cli->aliases_nb + 1], cli->fqdn);
-				CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+				TRACE_DEBUG(FULL, "Saved valid alias for client: '%.*s' -> '%s'", nas_id_len, nas_id + 1, cli->fqdn);
+				CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 			}
 		} else {
@@ -774,5 +819,5 @@
 			TRACE_DEBUG(INFO, "NAS-Identifier '%s' cannot be resolved: %s. Ignoring...", buf, gai_strerror(ret));
 			/* Assume this is a valid identifier for the client */
-			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) );
+			CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
 		}
 	}
@@ -781,6 +826,8 @@
 diameter:
 	ASSERT(oh_str); /* If it is not defined here, there is a bug... */
-	if (!or_str)
+	if (!or_str) {
 		or_str = fd_g_config->cnf_diamrlm; /* Use local realm in that case */
+		or_strlen = fd_g_config->cnf_diamrlm_len;
+	}
 	
 	/* Create an empty Diameter message so that extensions can store their AVPs */
@@ -791,5 +838,5 @@
 	memset(&avp_val, 0, sizeof(avp_val));
 	avp_val.os.data = (unsigned char *)oh_str;
-	avp_val.os.len = strlen(oh_str);
+	avp_val.os.len = oh_strlen;
 	CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
 	CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
@@ -799,5 +846,5 @@
 	memset(&avp_val, 0, sizeof(avp_val));
 	avp_val.os.data = (unsigned char *)or_str;
-	avp_val.os.len = strlen(or_str);
+	avp_val.os.len = or_strlen;
 	CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
 	CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
@@ -807,26 +854,35 @@
 		memset(&avp_val, 0, sizeof(avp_val));
 		avp_val.os.data = (unsigned char *)rr_str;
-		avp_val.os.len = strlen(rr_str);
+		avp_val.os.len = rr_strlen;
 		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
 		CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
 	}
 	
+	if (oh_free)
+		free(oh_str);
+	
 	/* Done! */
 	return 0;
 }
 
-int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm)
-{
-	TRACE_ENTRY("%p %p %p", cli, fqdn, realm);
-	CHECK_PARAMS(cli && fqdn);
+int rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen)
+{
+	TRACE_ENTRY("%p %p %p %p %p", cli, fqdn, fqdnlen, realm, realmlen);
+	CHECK_PARAMS(cli && fqdn && fqdnlen);
 	
 	if (cli->is_local) {
 		*fqdn = fd_g_config->cnf_diamid;
+		*fqdnlen = fd_g_config->cnf_diamid_len;
 		if (realm)
 			*realm= fd_g_config->cnf_diamrlm;
+		if (realmlen)
+			*realmlen= fd_g_config->cnf_diamrlm_len;
 	} else {
 		*fqdn = cli->fqdn;
+		*fqdnlen = cli->fqdn_len;
 		if (realm)
 			*realm= cli->realm;
+		if (realmlen)
+			*realmlen= cli->realm_len;
 	}
 		
Index: extensions/app_radgw/rgw_common.h
===================================================================
--- extensions/app_radgw/rgw_common.h	(revision 403)
+++ extensions/app_radgw/rgw_common.h	(revision 706)
@@ -59,5 +59,5 @@
 int    rgw_clients_getkey(struct rgw_client * cli, unsigned char **key, size_t *key_len);
 char * rgw_clients_id(struct rgw_client *cli);
-int    rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm);
+int    rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen);
 
 /* Each plugin must provide the following structure. */
Index: extensions/app_radgw/rgw_servers.c
===================================================================
--- extensions/app_radgw/rgw_servers.c	(revision 553)
+++ extensions/app_radgw/rgw_servers.c	(revision 706)
@@ -148,6 +148,7 @@
 		CHECK_FCT_DO( rgw_msg_parse(&buf[0], len, &msg), 
 			{
-				char * cliname = NULL;
-				CHECK_FCT_DO( rgw_clients_get_origin(nas_info, &cliname, NULL), );
+				DiamId_t cliname = NULL;
+				size_t clisz;
+				CHECK_FCT_DO( rgw_clients_get_origin(nas_info, &cliname, &clisz, NULL, NULL), );
 				TRACE_DEBUG(INFO, "Discarding invalid RADIUS message from '%s'", cliname);
 				rgw_clients_dispose(&nas_info);
Index: extensions/app_radgw/rgwx_acct.c
===================================================================
--- extensions/app_radgw/rgwx_acct.c	(revision 705)
+++ extensions/app_radgw/rgwx_acct.c	(revision 706)
@@ -306,7 +306,7 @@
 	const char * prefix = "Diameter/";
 	size_t pref_len;
-	uint8_t * si = NULL;
+	os0_t si = NULL;
 	size_t si_len = 0;
-	uint8_t * un = NULL;
+	os0_t un = NULL;
 	size_t un_len = 0;
 	
@@ -487,5 +487,5 @@
 	/* Create the Session-Id AVP if needed */
 	if (!*session) {
-		CHECK_FCT( fd_sess_fromsid ( (char *)/* cast should be removed later */si, si_len, session, NULL) );
+		CHECK_FCT( fd_sess_fromsid ( si, si_len, session, NULL) );
 		
 		TRACE_DEBUG(FULL, "[acct.rgwx] Translating new accounting message for session '%.*s'...", si_len, si);
@@ -663,11 +663,11 @@
 					char * attr_val, *auth_val;
 					attr_val = (char *)(attr + 1);
-					auth_val = attr_val + strlen(CLASS_AAI_PREFIX);
-					if (	(attr->length > sizeof(struct radius_attr_hdr) + strlen(CLASS_AAI_PREFIX)  )
-						&& (attr->length < sizeof(struct radius_attr_hdr) + strlen(CLASS_AAI_PREFIX) + sizeof(buf))
-						&& ! strncmp(attr_val, CLASS_AAI_PREFIX, strlen(CLASS_AAI_PREFIX))) {
+					auth_val = attr_val + CONSTSTRLEN(CLASS_AAI_PREFIX);
+					if (	(attr->length > sizeof(struct radius_attr_hdr) + CONSTSTRLEN(CLASS_AAI_PREFIX)  )
+						&& (attr->length < sizeof(struct radius_attr_hdr) + CONSTSTRLEN(CLASS_AAI_PREFIX) + sizeof(buf))
+						&& ! strncmp(attr_val, CLASS_AAI_PREFIX, CONSTSTRLEN(CLASS_AAI_PREFIX))) {
 					
 						memset(buf, 0, sizeof(buf));
-						memcpy(buf, auth_val, attr->length - sizeof(struct radius_attr_hdr) - strlen(CLASS_AAI_PREFIX));
+						memcpy(buf, auth_val, attr->length - sizeof(struct radius_attr_hdr) - CONSTSTRLEN(CLASS_AAI_PREFIX));
 						if (sscanf(buf, "%u", &auth_appl) == 1) {
 							TRACE_DEBUG(ANNOYING, "Found Class attribute with '%s' prefix (attr #%d), AAI:%u.", CLASS_AAI_PREFIX, idx, auth_appl);
@@ -1301,6 +1301,8 @@
 		struct msg * str = NULL;
 		struct msg_hdr * hdr = NULL;
-		char * fqdn;
-		char * realm;
+		DiamId_t fqdn;
+		size_t fqdn_len;
+		DiamId_t realm;
+		size_t realm_len;
 		union avp_value avp_val;
 		
@@ -1323,5 +1325,5 @@
 
 		/* Get information on the NAS */
-		CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) );
+		CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdn_len, &realm, &realm_len) );
 
 		/* Add the Origin-Host as next AVP */
@@ -1329,5 +1331,5 @@
 		memset(&avp_val, 0, sizeof(avp_val));
 		avp_val.os.data = (unsigned char *)fqdn;
-		avp_val.os.len = strlen(fqdn);
+		avp_val.os.len = fqdn_len;
 		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
 		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
@@ -1337,5 +1339,5 @@
 		memset(&avp_val, 0, sizeof(avp_val));
 		avp_val.os.data = (unsigned char *)realm;
-		avp_val.os.len = strlen(realm);
+		avp_val.os.len = realm_len;
 		CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
 		CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
Index: extensions/app_radgw/rgwx_auth.c
===================================================================
--- extensions/app_radgw/rgwx_auth.c	(revision 705)
+++ extensions/app_radgw/rgwx_auth.c	(revision 706)
@@ -239,11 +239,11 @@
 	const char * prefix = "Diameter/";
 	size_t pref_len;
-	uint8_t * dh = NULL;
+	os0_t dh = NULL;
 	size_t dh_len = 0;
-	uint8_t * dr = NULL;
+	os0_t dr = NULL;
 	size_t dr_len = 0;
-	uint8_t * si = NULL;
+	os0_t si = NULL;
 	size_t si_len = 0;
-	uint8_t * un = NULL;
+	os0_t un = NULL;
 	size_t un_len = 0;
 	size_t nattr_used = 0;
@@ -293,5 +293,5 @@
         	 and/or to the NAS-Identifier attribute.  (Note that the RADIUS
         	 NAS-Identifier is not required to be an FQDN.)
-		     -> done in rgw_msg_create_base.
+		     -> done in rgw_clients_create_origin.
 
 	      -  The response MUST have an Origin-AAA-Protocol AVP added,
@@ -453,25 +453,28 @@
 	/* Create the session if it is not already done */
 	if (*session == NULL) {
-		char * sess_str = NULL;
+		os0_t sess_str = NULL;
+		size_t sess_strlen;
 		
 		if (si_len) {
 			/* We already have the Session-Id, just use it */
-			CHECK_FCT( fd_sess_fromsid ( (char *) /* this cast will be removed later */ si, si_len, session, NULL) );
+			CHECK_FCT( fd_sess_fromsid ( si, si_len, session, NULL) );
 		} else {
 			/* Create a new Session-Id string */
 			
-			char * fqdn;
-			char * realm;
+			DiamId_t fqdn;
+			size_t fqdnlen;
+			DiamId_t realm;
+			size_t realmlen;
 			
 			/* Get information on the RADIUS client */
-			CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) );
+			CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdnlen, &realm, &realmlen) );
 			
 			/* If we have a user name, create the new session with it */
 			if (un) {
 				int len;
-				/* If not found, create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */
+				/* If not found, create a new Session-Id. Our format is: {fqdn;hi32;lo32;username;diamid} */
 				CHECK_MALLOC( sess_str = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) );
-				len = sprintf(sess_str, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
-				CHECK_FCT( fd_sess_new(session, fqdn, sess_str, len) );
+				len = sprintf((char *)sess_str, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
+				CHECK_FCT( fd_sess_new(session, fqdn, fqdnlen, sess_str, len) );
 				free(sess_str);
 			} else {
@@ -483,5 +486,5 @@
 		
 		/* Now, add the Session-Id AVP at beginning of Diameter message */
-		CHECK_FCT( fd_sess_getsid(*session, &sess_str) );
+		CHECK_FCT( fd_sess_getsid(*session, &sess_str, &sess_strlen) );
 		
 		TRACE_DEBUG(FULL, "[auth.rgwx] Translating new message for session '%s'...", sess_str);
@@ -489,6 +492,6 @@
 		/* Add the Session-Id AVP as first AVP */
 		CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) );
-		value.os.data = (unsigned char *)sess_str;
-		value.os.len = strlen(sess_str);
+		value.os.data = sess_str;
+		value.os.len = sess_strlen;
 		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
 		CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
@@ -564,9 +567,9 @@
 			/* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
 			#define CONV2DIAM_STR( _dictobj_ )	\
-				CHECK_PARAMS( attr->length >= 2 );						\
+				CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );			\
 				/* Create the AVP with the specified dictionary model */			\
 				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
-				value.os.len = attr->length - 2;						\
-				value.os.data = (unsigned char *)(attr + 1);					\
+				value.os.len = attr->length - sizeof(struct radius_attr_hdr);			\
+				value.os.data = (os0_t)(attr + 1);						\
 				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
 				/* Add the AVP in the Diameter message. */					\
@@ -575,5 +578,5 @@
 			/* Same thing, for scalar AVPs of 32 bits */
 			#define CONV2DIAM_32B( _dictobj_ )	\
-				CHECK_PARAMS( attr->length == 6 );						\
+				CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint32_t) );\
 				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
 				{										\
@@ -589,5 +592,5 @@
 			/* And the 64b version */
 			#define CONV2DIAM_64B( _dictobj_ )	\
-				CHECK_PARAMS( attr->length == 10);						\
+				CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint64_t) );\
 				CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
 				{										\
@@ -609,5 +612,5 @@
 			      -  The Destination-Realm AVP is created from the information found
         			 in the RADIUS User-Name attribute.
-				 	-> done in rgw_msg_create_base
+				 	-> done in rgw_clients_create_origin
 			*/
 			case RADIUS_ATTR_USER_NAME:
Index: extensions/app_radgw/rgwx_debug.c
===================================================================
--- extensions/app_radgw/rgwx_debug.c	(revision 356)
+++ extensions/app_radgw/rgwx_debug.c	(revision 706)
@@ -102,6 +102,7 @@
 		fd_log_debug(" Diameter session: NULL pointer\n");
 	} else {
-		char * str;
-		CHECK_FCT( fd_sess_getsid(*session, &str) );
+		os0_t str;
+		size_t str_len;
+		CHECK_FCT( fd_sess_getsid(*session, &str, &str_len) );
 
 		fd_log_debug(" Diameter session: %s\n", str);
Index: extensions/app_radgw/rgwx_sip.c
===================================================================
--- extensions/app_radgw/rgwx_sip.c	(revision 705)
+++ extensions/app_radgw/rgwx_sip.c	(revision 706)
@@ -58,9 +58,9 @@
 /* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */
 #define CONV2DIAM_STR( _dictobj_ )	\
-	CHECK_PARAMS( attr->length >= 2 );						\
+	CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );			\
 	/* Create the AVP with the specified dictionary model */			\
 	CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
-	value.os.len = attr->length - 2;						\
-	value.os.data = (unsigned char *)(attr + 1);					\
+	value.os.len = attr->length - sizeof(struct radius_attr_hdr);			\
+	value.os.data = (os0_t)(attr + 1);						\
 	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
 	/* Add the AVP in the Diameter message. */					\
@@ -68,26 +68,26 @@
 
 #define CONV2DIAM_STR_AUTH( _dictobj_ )	\
-	CHECK_PARAMS( attr->length >= 2 );						\
+	CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );			\
 	/* Create the AVP with the specified dictionary model */			\
 	CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
-	value.os.len = attr->length - 2;						\
-	value.os.data = (unsigned char *)(attr + 1);					\
+	value.os.len = attr->length - sizeof(struct radius_attr_hdr);			\
+	value.os.data = (os0_t)(attr + 1);						\
 	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
 	/* Add the AVP in the Diameter message. */					\
-	CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );		\
+	CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );			\
 		
 /* Same thing, for scalar AVPs of 32 bits */
 #define CONV2DIAM_32B( _dictobj_ )	\
-	CHECK_PARAMS( attr->length == 6 );						\
+	CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint32_t) );\
 	CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );			\
 	{										\
 		uint8_t * v = (uint8_t *)(attr + 1);					\
 		value.u32  = (v[0] << 24)						\
-		           | (v[1] << 16)						\
-		           | (v[2] <<  8)						\
-		           |  v[3] ;							\
+			   | (v[1] << 16)						\
+			   | (v[2] <<  8)						\
+			   |  v[3] ;							\
 	}										\
 	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );				\
-	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
+	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );		\
 				
 				
@@ -145,12 +145,12 @@
 {
 	struct fd_list chain;
-    char * sid;
+    os0_t sid;
     size_t sidlen;
-    char * nonce;
+    os0_t nonce;
     size_t noncelen;
     
 };
 
-static int nonce_add_element(char * nonce, size_t noncelen,char * sid, size_t sidlen, struct rgwp_config * state)
+static int nonce_add_element(os0_t nonce, size_t noncelen, os0_t sid, size_t sidlen, struct rgwp_config * state)
 {
 	CHECK_PARAMS(nonce && state && sid && sidlen && noncelen);
@@ -159,10 +159,8 @@
 	CHECK_MALLOC(newelt=malloc(sizeof(noncechain)));
 	
-	CHECK_MALLOC(newelt->nonce=malloc(noncelen));
-	memcpy(newelt->nonce,nonce,noncelen);
+	CHECK_MALLOC(newelt->nonce= os0dup(nonce, noncelen));
 	newelt->noncelen=noncelen;
 	
-	CHECK_MALLOC(newelt->sid=malloc(sidlen));
-	memcpy(newelt->sid,sid,sidlen);
+	CHECK_MALLOC(newelt->sid=os0dup(sid, sidlen));
 	newelt->sidlen=sidlen;
 	
@@ -198,13 +196,13 @@
 */
 //Retrieve sid from nonce
-static char * nonce_get_sid(char * nonce, size_t noncelen, size_t * sidlen, struct rgwp_config *state)
+static os0_t nonce_get_sid(os0_t nonce, size_t noncelen, size_t * sidlen, struct rgwp_config *state)
 {
 	struct fd_list * li;
-	char *sid=NULL;
+	os0_t sid=NULL;
 	
 	CHECK_PARAMS_DO(nonce && state && noncelen && sidlen, return NULL);
 	*sidlen=0;
 	
-	//**Start mutex
+	// **Start mutex
 	CHECK_POSIX_DO(pthread_mutex_lock(&state->nonce_mutex),); 
 	for(li=state->listnonce.next;li!=&state->listnonce;li=li->next)
@@ -212,5 +210,5 @@
 		noncechain *temp=(noncechain *)li;
 		
-		if(temp->noncelen==noncelen && strncmp(temp->nonce,nonce, noncelen)==0)
+		if (!fd_os_cmp(temp->nonce, temp->noncelen, nonce, noncelen))
 		{
 			fd_list_unlink (li);
@@ -224,5 +222,5 @@
 	}
 	CHECK_POSIX_DO(pthread_mutex_unlock(&state->nonce_mutex),); 
-	//***Stop mutex
+	// ***Stop mutex
 	return sid;
 }
@@ -230,5 +228,5 @@
 static void nonce_deletelistnonce(struct rgwp_config *state)
 {
-	//**Start mutex
+	// **Start mutex
 	CHECK_POSIX_DO(pthread_mutex_lock(&state->nonce_mutex),); 
 	while(!(FD_IS_LIST_EMPTY(&state->listnonce)) )
@@ -243,5 +241,5 @@
 	}
 	CHECK_POSIX_DO(pthread_mutex_unlock(&state->nonce_mutex),); 
-	//***Stop mutex
+	// ***Stop mutex
 }
 
@@ -338,6 +336,7 @@
 	int got_Dresponse = 0;
 	int got_Dalgorithm = 0;
-	char * sid = NULL;
-	char * un=NULL;
+	os0_t sid = NULL;
+	size_t sidlen;
+	os0_t un=NULL;
 	size_t  un_len;
 	size_t nattr_used = 0;
@@ -352,5 +351,5 @@
 	if(*session)
 	{
-		TRACE_DEBUG(INFO,"We are not supposed to receive a session in radSIP plugin.");
+		TRACE_DEBUG(INFO,"INTERNAL ERROR: We are not supposed to receive a session in radSIP plugin.");
 		return EINVAL;
 	}
@@ -371,5 +370,5 @@
 				{
 					TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", attr->length- sizeof(struct radius_attr_hdr), (char *)(attr+1));
-					un = (char *)(attr + 1);
+					un = (os0_t)(attr + 1);
 					un_len =attr->length - sizeof(struct radius_attr_hdr);
 				}
@@ -396,7 +395,5 @@
 				got_Dnonce = 1;
 				
-				size_t sidlen;
-				
-				sid=nonce_get_sid((char *)(attr+1),attr->length-2,&sidlen,cs);
+				sid=nonce_get_sid((os0_t)(attr+1), attr->length - sizeof(struct radius_attr_hdr), &sidlen, cs);
 				if(!sid)
 				{
@@ -406,5 +403,5 @@
 				CHECK_FCT(fd_sess_fromsid (sid, sidlen, session, NULL));
 				free(sid);
-								
+							
 				
 			break;
@@ -432,6 +429,8 @@
 	if (!*session) {
 		
-		char * fqdn;
-		char * realm;
+		DiamId_t fqdn;
+		size_t fqdn_len;
+		DiamId_t realm;
+		size_t realm_len;
 		
 		
@@ -439,11 +438,10 @@
 		
 		/* Get information on the RADIUS client */
-		CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) );
-		
-		int len;
+		CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdn_len, &realm, &realm_len) );
+		
 		/* Create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */
 		CHECK_MALLOC( sid = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) );
-		len = sprintf(sid, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
-		CHECK_FCT( fd_sess_new(session, fqdn, sid, len) );
+		sidlen = sprintf((char *)sid, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid);
+		CHECK_FCT( fd_sess_new(session, fqdn, fqdn_len, sid, sidlen) );
 		free(sid);
 	}
@@ -453,19 +451,19 @@
 	
 	int i = 0;
-	if (un) {
-		/* Is there an '@' in the user name? We don't care for decorated NAI here */
-		for (i = un_len - 2; i > 0; i--) {
-			if (un[i] == '@') {
-				i++;
-				break;
-			}
+	
+	/* Is there an '@' in the user name? We don't care for decorated NAI here */
+	for (i = un_len - 2; i > 0; i--) {
+		if (un[i] == '@') {
+			i++;
+			break;
 		}
 	}
+
 	if (i == 0) {
 		/* Not found in the User-Name => we use the local domain of this gateway */
-		value.os.data = (unsigned char *)fd_g_config->cnf_diamrlm;
+		value.os.data = (os0_t)fd_g_config->cnf_diamrlm;
 		value.os.len  = fd_g_config->cnf_diamrlm_len;
 	} else {
-		value.os.data = (unsigned char *)(un + i);
+		value.os.data = un + i;
 		value.os.len  = un_len - i;
 	}
@@ -475,5 +473,5 @@
 	
 	/* Now, add the Session-Id AVP at beginning of Diameter message */
-	CHECK_FCT( fd_sess_getsid(*session, &sid) );
+	CHECK_FCT( fd_sess_getsid(*session, &sid, &sidlen) );
 	
 	TRACE_DEBUG(FULL, "[sip.rgwx] Translating new message for session '%s'...", sid);
@@ -481,6 +479,6 @@
 	/* Add the Session-Id AVP as first AVP */
 	CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) );
-	value.os.data = (unsigned char *)sid;
-	value.os.len = strlen(sid);
+	value.os.data = sid;
+	value.os.len = sidlen;
 	CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
 	CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) );
@@ -552,5 +550,4 @@
 		CHECK_FCT( fd_msg_avp_add ( auth_data, MSG_BRW_LAST_CHILD, auth) );
 	}
-	char * temp=NULL,*sipuri=NULL;
 
 	for (idx = 0; idx < rad_req->attr_used; idx++) 
@@ -597,19 +594,24 @@
 			{
 				//We extract Realm from Digest_URI
-				char *realm=NULL;
-			
-				CHECK_MALLOC(temp=malloc(attr->length -1));
-				strncpy(temp, (char *)(attr + 1), attr->length -2);
-				temp[attr->length-2] = '\0';
-			
-				realm = strtok( (char *)(temp), "@" );
-				realm = strtok( NULL, "@" );
-				free(temp);
-				temp=NULL;
+				DiamId_t realm=NULL;
+				size_t realm_len;
+				os0_t temp;
+				
+				temp = (os0_t)(attr + 1);
+				
+				for (i=attr->length - sizeof(struct radius_attr_hdr) - 1; i>=0; i--) {
+					if (temp[i] == '@') {
+						realm = (DiamId_t)temp + i + 1;
+						CHECK_FCT_DO( fd_os_validate_DiameterIdentity(&realm, &realm_len, 1),
+							realm = NULL );
+						break;
+					}
+				}
+			
 				if(realm!=NULL)
 				{
 					CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Realm, 0, &avp ) );
-					value.os.data=(unsigned char *)realm;
-					value.os.len=strlen(realm);
+					value.os.data=(os0_t)realm;
+					value.os.len=realm_len;
 					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
 					CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );
@@ -617,9 +619,10 @@
 					//We add SIP-Server-URI AVP because SIP server is registrar (through gateway)
 					CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Server_URI, 0, &avp ) );
-					value.os.data=(unsigned char *)realm;
-					value.os.len=strlen(realm);
+					value.os.data=(os0_t)realm;
+					value.os.len=realm_len;
 					CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
 					CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
 					
+					free(realm);
 				}
 				else
@@ -641,18 +644,15 @@
 			//We add SIP-Server-URI AVP because SIP server is registrar (through gateway)
 			CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Server_URI, 0, &avp ) );
-			
-			
-			CHECK_MALLOC(temp=malloc(attr->length -1));
-			strncpy(temp, (char *)(attr + 1), attr->length -2);
-			
-			
-			CHECK_MALLOC(sipuri=malloc(attr->length +3));
-			strcpy(sipuri,"sip:");
-			strcat(sipuri,(const char *)temp);
-			value.os.data=(unsigned char *)sipuri;
-			value.os.len=attr->length +2;
+			os0_t temp;
+			#define SIP_PREFIX	"sip:"
+			size_t temp_len = attr->length - sizeof(struct radius_attr_hdr) + CONSTSTRLEN(SIP_PREFIX) + 1;
+			CHECK_MALLOC( temp = malloc(temp_len) );
+			temp_len = snprintf((char *)temp, temp_len, SIP_PREFIX "%.*s", attr->length - sizeof(struct radius_attr_hdr), (char *)(attr + 1));
+			
+			value.os.data=temp;
+			value.os.len=temp_len;
 			
 			free(temp);
-			temp=NULL;
+			
 			CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
 			CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );
@@ -689,9 +689,10 @@
 			{
 				//[Note 3] If Digest-Algorithm is missing, 'MD5' is assumed.
+				#define DIGEST_ALGO_MD5	"MD5"
 										
 				CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Algorithm, 0, &avp ) );			
 										
-				value.os.data = (unsigned char *)"MD5";
-				value.os.len = strlen((const char *)value.os.data);
+				value.os.data = (os0_t)DIGEST_ALGO_MD5;
+				value.os.len = CONSTSTRLEN(DIGEST_ALGO_MD5) - 1;
 				CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );					
 				CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );	
@@ -831,10 +832,9 @@
 					/* Retrieve the request identified which was stored in the session */
 					if (session) {
-						char *sid=NULL;
+						os0_t sid=NULL;
 						size_t sidlen;
-						fd_sess_getsid (session, &sid );
-						sidlen=strlen(sid);
+						fd_sess_getsid (session, &sid, &sidlen );
 						
-						nonce_add_element((char *)ahdr->avp_value->os.data,ahdr->avp_value->os.len, sid,sidlen, cs);
+						nonce_add_element(ahdr->avp_value->os.data, ahdr->avp_value->os.len, sid, sidlen, cs);
 					}
 					break;
