Browse Source

Merge pull request #850 from mslehto/pcv

P-Charging-Vector related updates
Daniel-Constantin Mierla 8 năm trước cách đây
mục cha
commit
beda05be61

+ 91 - 39
modules/siputils/chargingvector.c

@@ -30,15 +30,17 @@
 #include "chargingvector.h"
 #include "chargingvector.h"
 
 
 #define SIZE_CONF_ID 16
 #define SIZE_CONF_ID 16
-#define P_CHARGING_VECTOR    "P-Charging-Vector"
-#define LOOPBACK_IP  16777343
+#define P_CHARGING_VECTOR "P-Charging-Vector"
+#define LOOPBACK_IP 16777343
 
 
-#define PVC_BUF_SIZE	256
-static char pcv_buf[PVC_BUF_SIZE];
+#define PCV_BUF_SIZE 256
+static char pcv_buf[PCV_BUF_SIZE];
 static str pcv = { pcv_buf, 0 };
 static str pcv = { pcv_buf, 0 };
-static str pcv_host = { NULL, 0 };
 static str pcv_id = { NULL, 0 };
 static str pcv_id = { NULL, 0 };
-static uint64_t     	counter = 0 ;
+static str pcv_host = { NULL, 0 };
+static str pcv_orig = { NULL, 0 };
+static str pcv_term = { NULL, 0 };
+static uint64_t counter = 0;
 
 
 
 
 enum PCV_Status {
 enum PCV_Status {
@@ -54,15 +56,15 @@ static void sip_generate_charging_vector(char * pcv)
 {
 {
 	char             s[PATH_MAX]        = {0};
 	char             s[PATH_MAX]        = {0};
 	struct hostent*  host               = NULL;
 	struct hostent*  host               = NULL;
-	int              cdx                = 0 ;
-	int              tdx                = 0 ;
-	int              idx                = 0 ;
-	int              ipx                = 0 ;
+	int              cdx                = 0;
+	int              tdx                = 0;
+	int              idx                = 0;
+	int              ipx                = 0;
 	int pid;
 	int pid;
-	uint64_t         ct                 = 0 ;
+	uint64_t         ct                 = 0;
 	struct in_addr*  in                 = NULL;
 	struct in_addr*  in                 = NULL;
 	static struct in_addr ip            = {0};
 	static struct in_addr ip            = {0};
-	unsigned char             		newConferenceIdentifier[SIZE_CONF_ID]={0};
+	unsigned char newConferenceIdentifier[SIZE_CONF_ID]={0};
 
 
 	memset(pcv,0,SIZE_CONF_ID);
 	memset(pcv,0,SIZE_CONF_ID);
 	pid = getpid();
 	pid = getpid();
@@ -79,7 +81,7 @@ static void sip_generate_charging_vector(char * pcv)
 					in = (struct in_addr*)host->h_addr_list[idx];
 					in = (struct in_addr*)host->h_addr_list[idx];
 					if (in->s_addr == LOOPBACK_IP )
 					if (in->s_addr == LOOPBACK_IP )
 					{
 					{
-						if ( ip.s_addr  == 0 )
+						if ( ip.s_addr == 0 )
 						{
 						{
 							ip=*in;
 							ip=*in;
 						}
 						}
@@ -128,12 +130,12 @@ static void sip_generate_charging_vector(char * pcv)
 		}
 		}
 		idx++;
 		idx++;
 	}
 	}
-	LM_DBG("CV generate");
-	int i =0;
+	LM_DBG("PCV generate\n");
+	int i = 0;
 	pcv[0] = '\0';
 	pcv[0] = '\0';
 	for ( i = 0 ; i < SIZE_CONF_ID ; i ++ )
 	for ( i = 0 ; i < SIZE_CONF_ID ; i ++ )
 	{
 	{
-		char hex[4] = {0 };
+		char hex[4] = {0};
 
 
 		snprintf(hex,4,"%02X",newConferenceIdentifier[i]);
 		snprintf(hex,4,"%02X",newConferenceIdentifier[i]);
 		strcat(pcv,hex);
 		strcat(pcv,hex);
@@ -155,45 +157,75 @@ static unsigned int sip_param_end(const char * s, unsigned int len)
 	return len;
 	return len;
 }
 }
 
 
-static int sip_parse_charging_vector(const char * pvc_value, unsigned int len)
+static int sip_parse_charging_vector(const char * pcv_value, unsigned int len)
 {
 {
 	/* now point to each PCV component */
 	/* now point to each PCV component */
-	LM_DBG("acc: parsing PCV header [%s].\n", pvc_value);
+	LM_DBG("parsing PCV header [%s]\n", pcv_value);
+
+	char *s = NULL;
 
 
-	char *s = strstr(pvc_value, "icid-value=");
+	s = strstr(pcv_value, "icid-value=");
 	if (s != NULL)
 	if (s != NULL)
 	{
 	{
 		pcv_id.s = s + strlen("icid-value=");
 		pcv_id.s = s + strlen("icid-value=");
 		pcv_id.len = sip_param_end(pcv_id.s, len);
 		pcv_id.len = sip_param_end(pcv_id.s, len);
-		LM_INFO("acc: parsed P-Charging-Vector icid-value=%.*s",
+		LM_DBG("parsed P-Charging-Vector icid-value=%.*s\n",
 				pcv_id.len, pcv_id.s );
 				pcv_id.len, pcv_id.s );
 	}
 	}
 	else
 	else
 	{
 	{
+		LM_WARN("mandatory icid-value not found\n");
 		pcv_id.s = NULL;
 		pcv_id.s = NULL;
 		pcv_id.len = 0;
 		pcv_id.len = 0;
 	}
 	}
 
 
-	s = strstr(pvc_value, "icid-generated-at=");
+	s = strstr(pcv_value, "icid-generated-at=");
 	if (s != NULL)
 	if (s != NULL)
 	{
 	{
 		pcv_host.s = s + strlen("icid-generated-at=");
 		pcv_host.s = s + strlen("icid-generated-at=");
-		pcv_host.len = sip_param_end(pcv_id.s, len);
-		LM_DBG("acc: parsed P-Charging-Vector icid-generated-at=%.*s",
+		pcv_host.len = sip_param_end(pcv_host.s, len);
+		LM_DBG("parsed P-Charging-Vector icid-generated-at=%.*s\n",
 				pcv_host.len, pcv_host.s );
 				pcv_host.len, pcv_host.s );
 	}
 	}
 	else
 	else
 	{
 	{
+		LM_DBG("icid-generated-at not found\n");
 		pcv_host.s = NULL;
 		pcv_host.s = NULL;
 		pcv_host.len = 0;
 		pcv_host.len = 0;
 	}
 	}
 
 
-	// Buggy charging vector where only icid-value is sent ...
-	if ( pcv_host.s == NULL &&  pcv_id.s == NULL && len > 0)
+	s = strstr(pcv_value, "orig-ioi=");
+	if (s != NULL)
 	{
 	{
-		pcv_id.s = (char *) pvc_value,
-			pcv_id.len = sip_param_end(pcv_id.s, len);
-		LM_WARN("acc: parsed BUGGY P-Charging-Vector %.*s", pcv_id.len, pcv_id.s );
+		pcv_orig.s = s + strlen("orig-ioi=");
+		pcv_orig.len = sip_param_end(pcv_orig.s, len);
+		LM_INFO("parsed P-Charging-Vector orig-ioi=%.*s\n",
+				pcv_orig.len, pcv_orig.s );
+	}
+	else
+	{
+		pcv_orig.s = NULL;
+		pcv_orig.len = 0;
+	}
+
+	s = strstr(pcv_value, "term-ioi=");
+	if (s != NULL)
+	{
+		pcv_term.s = s + strlen("term-ioi=");
+		pcv_term.len = sip_param_end(pcv_term.s, len);
+		LM_INFO("parsed P-Charging-Vector term-ioi=%.*s\n",
+				pcv_term.len, pcv_term.s );
+	}
+	else
+	{
+		pcv_term.s = NULL;
+		pcv_term.len = 0;
+	}
+
+	// only icid-value is mandatory, log anyway when missing icid-generated-at
+	if ( pcv_host.s == NULL && pcv_id.s != NULL && len > 0)
+	{
+		LM_WARN("icid-generated-at is missing %.*s\n", len, pcv_value);
 	}
 	}
 
 
 	return (pcv_id.s != NULL);
 	return (pcv_id.s != NULL);
@@ -214,15 +246,15 @@ static int sip_get_charging_vector(struct sip_msg *msg, struct hdr_field ** hf_p
 
 
 	for (hf=msg->headers; hf; hf=hf->next)
 	for (hf=msg->headers; hf; hf=hf->next)
 	{
 	{
-		if ( hf->name.s[0] == 'P' )
+		if ( hf->name.s[0] != 'P' )
 		{
 		{
-			LM_INFO("acc: checking heander=%.*s\n", hf->name.len, hf->name.s );
+			continue;
 		}
 		}
 
 
 		if ( cmp_hdrname_str(&hf->name, &hdrname) == 0)
 		if ( cmp_hdrname_str(&hf->name, &hdrname) == 0)
 		{
 		{
 			/*
 			/*
-			 * append p charging vector valus after the header name "P-Charging-Vector" and
+			 * append p charging vector values after the header name "P-Charging-Vector" and
 			 * the ": " (+2)
 			 * the ": " (+2)
 			 */
 			 */
 			char * pcv_body = pcv_buf + strlen(P_CHARGING_VECTOR) + 2;
 			char * pcv_body = pcv_buf + strlen(P_CHARGING_VECTOR) + 2;
@@ -235,16 +267,21 @@ static int sip_get_charging_vector(struct sip_msg *msg, struct hdr_field ** hf_p
 				if ( sip_parse_charging_vector( pcv_body, hf->body.len ) == 0)
 				if ( sip_parse_charging_vector( pcv_body, hf->body.len ) == 0)
 				{
 				{
 					LM_ERR("P-Charging-Vector header found but failed to parse value [%s].\n", pcv_body);
 					LM_ERR("P-Charging-Vector header found but failed to parse value [%s].\n", pcv_body);
+					pcv_status = PCV_NONE;
+					pcv.s = NULL;
+					pcv.len = 0;
 				}
 				}
 				else
 				else
 				{
 				{
 					pcv_status = PCV_PARSED;
 					pcv_status = PCV_PARSED;
+					pcv.s = hf->body.s;
+					pcv.len = hf->body.len;
 				}
 				}
 				return 2;
 				return 2;
 			}
 			}
 			else
 			else
 			{
 			{
-				pcv_id.s =0;
+				pcv_id.s = 0;
 				pcv_id.len = 0;
 				pcv_id.len = 0;
 				pcv_host.s = 0;
 				pcv_host.s = 0;
 				pcv_host.len = 0;
 				pcv_host.len = 0;
@@ -253,11 +290,11 @@ static int sip_get_charging_vector(struct sip_msg *msg, struct hdr_field ** hf_p
 			*hf_pcv = hf;
 			*hf_pcv = hf;
 		}
 		}
 	}
 	}
-	LM_INFO("No valid P-Charging-Vector header found.\n");
+	LM_DBG("No valid P-Charging-Vector header found.\n");
 	return 1;
 	return 1;
 }
 }
 
 
-// Remove PVC if it is in the inbound request (if it was found by sip_get_charging_vector)
+// Remove PCV if it is in the inbound request (if it was found by sip_get_charging_vector)
 static int  sip_remove_charging_vector(struct sip_msg *msg, struct hdr_field *hf)
 static int  sip_remove_charging_vector(struct sip_msg *msg, struct hdr_field *hf)
 {
 {
 	struct lump* l;
 	struct lump* l;
@@ -290,7 +327,7 @@ static int sip_add_charging_vector(struct sip_msg *msg)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	s  = (char*)pkg_malloc(pcv.len);
+	s = (char*)pkg_malloc(pcv.len);
 	if (!s) {
 	if (!s) {
 		LM_ERR("no pkg memory left\n");
 		LM_ERR("no pkg memory left\n");
 		return -1;
 		return -1;
@@ -349,7 +386,7 @@ int sip_handle_pcv(struct sip_msg *msg, char *flags, char *str2)
 	sip_get_charging_vector(msg, &hf_pcv);
 	sip_get_charging_vector(msg, &hf_pcv);
 
 
 	/*
 	/*
-	 * We need to remove the original PCV if it was present and ether
+	 * We need to remove the original PCV if it was present and either
 	 * we were asked to remove it or we were asked to replace it
 	 * we were asked to remove it or we were asked to replace it
 	 */
 	 */
 	if ( pcv_status == PCV_PARSED && (replace_pcv || remove_pcv)  )
 	if ( pcv_status == PCV_PARSED && (replace_pcv || remove_pcv)  )
@@ -379,7 +416,7 @@ int sip_handle_pcv(struct sip_msg *msg, char *flags, char *str2)
 
 
 		sip_generate_charging_vector(pcv_value);
 		sip_generate_charging_vector(pcv_value);
 
 
-		pcv.len = snprintf( pcv_body, PVC_BUF_SIZE - 19, "icid-value=%.*s; icid-generated-at=%.*s\r\n", 32, pcv_value,
+		pcv.len = snprintf( pcv_body, PCV_BUF_SIZE - 19, "icid-value=%.*s; icid-generated-at=%.*s\r\n", 32, pcv_value,
 				msg->rcv.bind_address->address_str.len,
 				msg->rcv.bind_address->address_str.len,
 				msg->rcv.bind_address->address_str.s );
 				msg->rcv.bind_address->address_str.s );
 		pcv.len += 19;
 		pcv.len += 19;
@@ -389,7 +426,7 @@ int sip_handle_pcv(struct sip_msg *msg, char *flags, char *str2)
 		/* if generated, reparse it */
 		/* if generated, reparse it */
 		sip_parse_charging_vector( pcv_body, pcv.len-19 );
 		sip_parse_charging_vector( pcv_body, pcv.len-19 );
 		/* if it was generated, we need to send it out as a header */
 		/* if it was generated, we need to send it out as a header */
-		LM_INFO("Generated PCV header %.*s.\n", pcv.len, pcv_buf );
+		LM_INFO("Generated PCV header %.*s\n", pcv.len-2, pcv_buf );
 		i = sip_add_charging_vector(msg);
 		i = sip_add_charging_vector(msg);
 		if (i <= 0)
 		if (i <= 0)
 		{
 		{
@@ -414,7 +451,7 @@ int pv_get_charging_vector(struct sip_msg *msg, pv_param_t *param, pv_value_t *r
 		{
 		{
 			current_msg_id = msg->id;
 			current_msg_id = msg->id;
 		}
 		}
-		LM_DBG("Parsed charging vector for pseudo-var \n");
+		LM_DBG("Parsed charging vector for pseudo-var\n");
 	}
 	}
 	else
 	else
 	{
 	{
@@ -424,9 +461,17 @@ int pv_get_charging_vector(struct sip_msg *msg, pv_param_t *param, pv_value_t *r
 	switch(pcv_status)
 	switch(pcv_status)
 	{
 	{
 		case PCV_GENERATED:
 		case PCV_GENERATED:
+			LM_DBG("pcv_status==PCV_GENERATED\n");
 		case PCV_PARSED:
 		case PCV_PARSED:
+			LM_DBG("pcv_status==PCV_PARSED\n");
 			switch( param->pvn.u.isname.name.n )
 			switch( param->pvn.u.isname.name.n )
 			{
 			{
+				case 5:
+					pcv_pv = pcv_term;
+					break;
+				case 4:
+					pcv_pv = pcv_orig;
+					break;
 				case 2:
 				case 2:
 					pcv_pv = pcv_host;
 					pcv_pv = pcv_host;
 					break;
 					break;
@@ -468,6 +513,13 @@ int pv_parse_charging_vector_name(pv_spec_p sp, str *in)
 				sp->pvp.pvn.u.isname.name.n = 1;
 				sp->pvp.pvn.u.isname.name.n = 1;
 			else goto error;
 			else goto error;
 		break;
 		break;
+		case 4:
+			if(strncmp(in->s, "orig", 4)==0)
+				sp->pvp.pvn.u.isname.name.n = 4;
+			else if(strncmp(in->s, "term", 4)==0)
+				sp->pvp.pvn.u.isname.name.n = 5;
+			else goto error;
+		break;
 		case 5:
 		case 5:
 			if(strncmp(in->s, "value", 5)==0)
 			if(strncmp(in->s, "value", 5)==0)
 				sp->pvp.pvn.u.isname.name.n = 3;
 				sp->pvp.pvn.u.isname.name.n = 3;

+ 8 - 5
modules/siputils/chargingvector.h

@@ -19,19 +19,22 @@
  */
  */
 
 
 /*
 /*
- * Support for rfc3455 P-Charging-Vector
+ * Support for RFC3455 / RFC7315 P-Charging-Vector
  * - parse charging vector from SIP message
  * - parse charging vector from SIP message
  * - generate new unique charging vector
  * - generate new unique charging vector
  * - can remove charging vector
  * - can remove charging vector
  *
  *
- * pseudo variables are exported and enable R ondly access to charging vector fields
+ * pseudo variables are exported and enable read only access to charging vector fields
  * $pcv(all) = whole field
  * $pcv(all) = whole field
  * $pcv(value) = icid-value field (see RFC3455 section 5.6)
  * $pcv(value) = icid-value field (see RFC3455 section 5.6)
  * $pcv(genaddr) = icid-generated-at field (see RFC3455 section 5.6)
  * $pcv(genaddr) = icid-generated-at field (see RFC3455 section 5.6)
+ * $pcv(orig) = orig-ioi field (see RFC3455 section 5.6)
+ * $pcv(term) = term-ioi field (see RFC3455 section 5.6)
  *
  *
- * to be supported
- * $pcv(orig)
- * $pcv(term)
+ * missing:
+ * $pcv(transit-ioi) RFC7315 5.6
+ * $pcv(related-icid) RFC7315 5.6
+ * $pcv(related-icid-gen-addr) RFC7315 5.6
  */
  */
 
 
 #ifndef _CHARGINGVECTOR_H_
 #ifndef _CHARGINGVECTOR_H_

+ 31 - 1
modules/siputils/doc/siputils_admin.xml

@@ -1066,7 +1066,7 @@ if(is_first_hop()) { ... }
 			<function moreinfo="none">sip_p_charging_vector(flags)</function>
 			<function moreinfo="none">sip_p_charging_vector(flags)</function>
 		</title>
 		</title>
 		<para>
 		<para>
-			Manage the P-Charging-Vector header (RFC3455). The flags can be:
+			Manage the P-Charging-Vector header (RFC7315). The flags can be:
 			'r' - remove; 'g' - generate; 'f' - force (remove + generate).
 			'r' - remove; 'g' - generate; 'f' - force (remove + generate).
 		</para>
 		</para>
 		<para>
 		<para>
@@ -1083,4 +1083,34 @@ sip_p_charging_vector("g");
 	</section>
 	</section>
 	</section>
 	</section>
 
 
+	<section>
+			<title>Exported pseudo-variables</title>
+			<section id="siputils.v.pcv_all">
+					<title><varname>$pcv(all)</title>
+					<para>
+						full P-Charging-Vector header
+					</para>
+			<section id="siputils.v.pcv_value">
+					<title><varname>$pcv(value)</title>
+					<para>
+						icid-value field (see RFC7315 section 5.6)
+					</para>
+			<section id="siputils.v.pcv_genaddr">
+					<title><varname>$pcv(genaddr)</title>
+					<para>
+						icid-generated-at field (see RFC7315 section 5.6)
+					</para>
+			<section id="siputils.v.pcv_orig">
+					<title><varname>$pcv(orig)</title>
+					<para>
+						orig-ioi field (see RFC7315 section 5.6)
+					</para>
+			<section id="siputils.v.pcv_term">
+					<title><varname>$pcv(term)</title>
+					<para>
+						term-ioi field (see RFC7315 section 5.6)
+					</para>
+			</section>
+	<section>
+
 </chapter>
 </chapter>

+ 1 - 1
modules/siputils/siputils.c

@@ -199,7 +199,7 @@ static param_export_t params[] = {
 
 
 
 
 static pv_export_t mod_pvs[] =  {
 static pv_export_t mod_pvs[] =  {
-	{ {"pcv", (sizeof("pvc")-1)}, PVT_OTHER, pv_get_charging_vector,
+	{ {"pcv", (sizeof("pcv")-1)}, PVT_OTHER, pv_get_charging_vector,
 		0, pv_parse_charging_vector_name, 0, 0, 0},
 		0, pv_parse_charging_vector_name, 0, 0, 0},
 
 
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }