|
@@ -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;
|