ソースを参照

modules/sipt added new method sipt_set_calling

Torrey Searle 12 年 前
コミット
717cd63e7f
5 ファイル変更344 行追加28 行削除
  1. 44 25
      modules/sipt/README
  2. 19 1
      modules/sipt/doc/sipt_admin.xml
  3. 139 2
      modules/sipt/sipt.c
  4. 15 0
      modules/sipt/ss7.h
  5. 127 0
      modules/sipt/ss7_parser.c

+ 44 - 25
modules/sipt/README

@@ -17,18 +17,20 @@ Torrey Searle
         3. Functions
 
               3.1. sipt_destination(destination, hops, nai)
-              3.2. sipt_get_hop_counter()
-              3.3. sipt_get_cpc()
-              3.4. sipt_get_calling_party_nai()
-              3.5. sipt_get_called_party_nai()
+              3.2. sipt_set_calling(origin, nai, presentation, screening)
+              3.3. sipt_get_hop_counter()
+              3.4. sipt_get_cpc()
+              3.5. sipt_get_calling_party_nai()
+              3.6. sipt_get_called_party_nai()
 
    List of Examples
 
    1.1. sipt_destination(destination, hops, nai) usage
-   1.2. sipt_get_hop_counter() usage
-   1.3. sipt_get_cpc() usage
-   1.4. sipt_get_calling_party_nai() usage
-   1.5. sipt_get_called_party_nai() usage
+   1.2. sipt_set_calling(origin, nai, presentation, screening) usage
+   1.3. sipt_get_hop_counter() usage
+   1.4. sipt_get_cpc() usage
+   1.5. sipt_get_calling_party_nai() usage
+   1.6. sipt_get_called_party_nai() usage
 
 Chapter 1. Admin Guide
 
@@ -39,17 +41,19 @@ Chapter 1. Admin Guide
    3. Functions
 
         3.1. sipt_destination(destination, hops, nai)
-        3.2. sipt_get_hop_counter()
-        3.3. sipt_get_cpc()
-        3.4. sipt_get_calling_party_nai()
-        3.5. sipt_get_called_party_nai()
+        3.2. sipt_set_calling(origin, nai, presentation, screening)
+        3.3. sipt_get_hop_counter()
+        3.4. sipt_get_cpc()
+        3.5. sipt_get_calling_party_nai()
+        3.6. sipt_get_called_party_nai()
 
 1. Overview
 
    Module for updating ISUP encapuslated in SIP (SIP-T/SIP-I)
 
    The sipt module can be used to update various ss7 headers contained
-   inside a message.
+   inside a message. If you want to call modify methods multiple times, be
+   sure to call msg_apply_changes from the textopsx package
 
 2. Dependencies
 
@@ -60,10 +64,11 @@ Chapter 1. Admin Guide
 3. Functions
 
    3.1. sipt_destination(destination, hops, nai)
-   3.2. sipt_get_hop_counter()
-   3.3. sipt_get_cpc()
-   3.4. sipt_get_calling_party_nai()
-   3.5. sipt_get_called_party_nai()
+   3.2. sipt_set_calling(origin, nai, presentation, screening)
+   3.3. sipt_get_hop_counter()
+   3.4. sipt_get_cpc()
+   3.5. sipt_get_calling_party_nai()
+   3.6. sipt_get_called_party_nai()
 
 3.1. sipt_destination(destination, hops, nai)
 
@@ -80,12 +85,26 @@ $rU = "19495551234";
 sipt_destination($rU, 31, 4);
 ...
 
-3.2. sipt_get_hop_counter()
+3.2. sipt_set_calling(origin, nai, presentation, screening)
+
+   updates the IAM in the body if it exists, setting (or adding) the
+   calling party number to “origin” with the nature address specified in
+   “nai” and setting the presentation and screening values to
+   “presentation” and “screening”.
+
+   Example 1.2. sipt_set_calling(origin, nai, presentation, screening)
+   usage
+...
+# update the calling party to the value in the from header
+sipt_set_calling($fU, 4, 0, 3);
+...
+
+3.3. sipt_get_hop_counter()
 
    Returns the value of the Hop Counter for the IAM message if it exists.
    Returns -1 if there isn't a hop counter.
 
-   Example 1.2. sipt_get_hop_counter() usage
+   Example 1.3. sipt_get_hop_counter() usage
 ...
 # get the hop counter and update the Max-Forwards header if it exists
 $avp(s:hop) = sipt_get_hop_counter();
@@ -97,12 +116,12 @@ if($avp(s:hop) > 0)
 
 ...
 
-3.3. sipt_get_cpc()
+3.4. sipt_get_cpc()
 
    Returns the value of the Calling Party Category for the IAM message.
    Returns -1 if there is a parsing error.
 
-   Example 1.3. sipt_get_cpc() usage
+   Example 1.4. sipt_get_cpc() usage
 ...
 # get the Cpc code and set put it in a custom sip header
 $avp(s:cpc) = sipt_get_cpc();
@@ -110,13 +129,13 @@ append_hf("X-CPC: $avp(s:cpc)\r\n");
 
 ...
 
-3.4. sipt_get_calling_party_nai()
+3.5. sipt_get_calling_party_nai()
 
    Returns the value of the Nature of Address Indicator of the Calling
    Party for the IAM message. Returns -1 if there is a parsing error or if
    the Calling Party Number is not present.
 
-   Example 1.4. sipt_get_calling_party_nai() usage
+   Example 1.5. sipt_get_calling_party_nai() usage
 ...
 # get the Calling Nai and add country code if national
 $avp(s:from_nai) = sipt_get_calling_party_nai();
@@ -127,12 +146,12 @@ if($avp(s:from_nai) == 3)
 
 ...
 
-3.5. sipt_get_called_party_nai()
+3.6. sipt_get_called_party_nai()
 
    Returns the value of the Nature of Address Indicator of the Called
    Party for the IAM message. Returns -1 if there is a parsing error.
 
-   Example 1.5. sipt_get_called_party_nai() usage
+   Example 1.6. sipt_get_called_party_nai() usage
 ...
 # get the Called Nai and add country code if national
 $avp(s:to_nai) = sipt_get_called_party_nai();

+ 19 - 1
modules/sipt/doc/sipt_admin.xml

@@ -19,7 +19,8 @@
 	<para>Module for updating ISUP encapuslated in SIP (SIP-T/SIP-I)</para>
 	<para>
 	The sipt module can be used to update various ss7 headers contained inside
-	a message.
+	a message.  If you want to call modify methods multiple times, be sure to call
+	msg_apply_changes from the textopsx package
 	</para>
 	</section>
 	<section>
@@ -53,6 +54,23 @@
 $rU = "19495551234";
 sipt_destination($rU, 31, 4);
 ...
+</programlisting>
+		</example>
+	</section>
+	<section id="sipt.f.sipt_set_calling">
+		<title><function moreinfo="none">sipt_set_calling(origin, nai, presentation, screening)</function></title>
+		<para>
+			updates the IAM in the body if it exists, setting (or adding) the calling party number to <quote>origin</quote>
+			with the nature address specified in <quote>nai</quote> and setting the presentation and screening values to 
+			 <quote>presentation</quote> and <quote>screening</quote>.
+		</para>
+		<example>
+			<title><function moreinfo="none">sipt_set_calling(origin, nai, presentation, screening)</function> usage</title>
+			<programlisting format="linespecific">
+...
+# update the calling party to the value in the from header
+sipt_set_calling($fU, 4, 0, 3);
+...
 </programlisting>
 		</example>
 	</section>

+ 139 - 2
modules/sipt/sipt.c

@@ -40,6 +40,7 @@
 MODULE_VERSION
 
 static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops, char * _nai);
+static int sipt_set_calling(struct sip_msg *msg, char *_origin, char *_nai, char *_pres, char * _screen);
 static int sipt_get_hop_counter(struct sip_msg *msg, char *x, char *y);
 static int sipt_get_cpc(struct sip_msg *msg, char *x, char *y);
 static int sipt_get_calling_party_nai(struct sip_msg *msg, char *x, char *y);
@@ -52,7 +53,7 @@ static void mod_destroy(void);
 
 static int fixup_str_str_str(void** param, int param_no)
 {
-	if(param_no == 1 || param_no == 2 || param_no == 3)
+	if(param_no == 1 || param_no == 2 || param_no == 3 || param_no == 4)
 	{
 		return fixup_str_null(param, 1);
 	}
@@ -61,7 +62,7 @@ static int fixup_str_str_str(void** param, int param_no)
 
 static int fixup_free_str_str_str(void** param, int param_no)
 {
-	if(param_no == 1 || param_no == 2 || param_no == 3)
+	if(param_no == 1 || param_no == 2 || param_no == 3 || param_no == 4)
 	{
 		return fixup_free_str_null(param, 1);
 	}
@@ -76,6 +77,12 @@ static cmd_export_t cmds[]={
 		fixup_str_str_str, fixup_free_str_str_str,         /* */
 		/* can be applied to original requests */
 		REQUEST_ROUTE|BRANCH_ROUTE}, 
+	{"sipt_set_calling", /* action name as in scripts */
+		(cmd_function)sipt_set_calling,  /* C function name */
+		4,          /* number of parameters */
+		fixup_str_str_str, fixup_free_str_str_str,         /* */
+		/* can be applied to original requests */
+		REQUEST_ROUTE|BRANCH_ROUTE}, 
 	{"sipt_get_hop_counter", /* action name as in scripts */
 		(cmd_function)sipt_get_hop_counter,  /* C function name */
 		0,          /* number of parameters */
@@ -482,6 +489,136 @@ static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops
 
 
 
+	str nb = {(char*)newbuf, offset};
+	replace_body(msg, &nb);
+
+	return 1;
+}
+
+static int sipt_set_calling(struct sip_msg *msg, char *_origin, char *_nai, char * _pres, char *_screen)
+{
+	unsigned int pres = 0;
+	str * str_pres = (str*)_pres;
+	str2int(str_pres, &pres);
+	unsigned int screen = 0;
+	str * str_screen = (str*)_screen;
+	str2int(str_screen, &screen);
+	str * nai = (str*)_nai;
+	unsigned int int_nai = 0;
+	str2int(nai, &int_nai);
+	str * origin = (str*)_origin;
+
+	// update forwarded iam
+	str body;
+	body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
+
+	if(body.s == NULL)
+	{
+		LM_ERR("No ISUP Message Found");
+		return -1;
+	}
+	str sdp;
+	sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
+	
+	unsigned char newbuf[1024];
+	memset(newbuf, 0, 1024);
+	if (body.s==0) {
+		LM_ERR("failed to get the message body\n");
+		return -1;
+	}
+	body.len = msg->len -(int)(body.s-msg->buf);
+	if (body.len==0) {
+		LM_DBG("message body has zero length\n");
+		return -1;
+	}
+
+	if(body.s[0] != ISUP_IAM)
+	{
+		LM_DBG("message not an IAM\n");
+		return -1;
+	}
+
+
+
+	unsigned int offset = 0;
+
+	if(sdp.s != NULL)
+	{
+		// we need to be clean, handle 2 cases
+		// one with sdp, one without sdp
+		str boundary = {0,0}; 
+		get_boundary_param(msg, &boundary);
+		memcpy(newbuf+offset, "--", 2);
+		offset+=2;
+
+		memcpy(newbuf+offset,boundary.s, boundary.len);
+		offset += boundary.len;
+
+		memcpy(newbuf+offset, "\r\n", 2);
+		offset+=2;
+
+		memcpy(newbuf+offset,SDP_HEADER, strlen(SDP_HEADER));
+		offset += strlen(SDP_HEADER);
+
+
+		memcpy(newbuf+offset,sdp.s, sdp.len);
+		offset += sdp.len;
+
+		memcpy(newbuf+offset, "\r\n", 2);
+		offset+=2;
+		memcpy(newbuf+offset, "\r\n--", 4);
+		offset+=4;
+
+		memcpy(newbuf+offset,boundary.s, boundary.len);
+		offset += boundary.len;
+
+		memcpy(newbuf+offset, "\r\n", 2);
+		offset+=2;
+
+		memcpy(newbuf+offset,ISUP_HEADER, strlen(ISUP_HEADER));
+		offset += strlen(ISUP_HEADER);
+
+		char * digits = calloc(1,origin->len+1);
+		memcpy(digits, origin->s, origin->len);
+
+		int res = isup_update_calling(digits, int_nai, pres, screen, (unsigned char*)body.s, body.len, newbuf+offset, 512);
+
+		if(res == -1)
+		{
+			LM_DBG("error updating IAM\n");
+			return -1;
+		}
+
+		free(digits);
+		offset += res;
+
+		memcpy(newbuf+offset, "\r\n--", 4);
+		offset+=4;
+
+		memcpy(newbuf+offset,boundary.s, boundary.len);
+		offset += boundary.len;
+
+		memcpy(newbuf+offset, "--\r\n", 4);
+		offset+=4;
+	}
+	else
+	{
+		// isup only body
+		char * digits = calloc(1,origin->len+1);
+		memcpy(digits, origin->s, origin->len);
+
+		int res = isup_update_calling(digits, int_nai, pres, screen, (unsigned char*)body.s, body.len, newbuf, 512);
+		free(digits);
+		offset = res;
+		if(res == -1)
+		{
+			LM_DBG("error updating IAM\n");
+			return -1;
+		}
+	}
+
+
+
 	str nb = {(char*)newbuf, offset};
 	replace_body(msg, &nb);
 

+ 15 - 0
modules/sipt/ss7.h

@@ -136,6 +136,19 @@
 #define ISUP_PARM_DIVERSION_INFORMATION 0x36
 #define ISUP_PARM_UUI 0x20
 
+/* Address Presentation */
+#define SS7_PRESENTATION_ALLOWED                       0x00
+#define SS7_PRESENTATION_RESTRICTED                    0x01
+#define SS7_PRESENTATION_ADDR_NOT_AVAILABLE            0x02
+
+/* Screening */
+#define SS7_SCREENING_USER_PROVIDED_NOT_VERIFIED       0x00
+#define SS7_SCREENING_USER_PROVIDED                    0x01
+#define SS7_SCREENING_NETWORK_PROVIDED_FAILED          0x02
+#define SS7_SCREENING_NETWORK_PROVIDED                 0x03
+
+
+
 #ifndef bool
 #define bool unsigned char
 #endif
@@ -165,5 +178,7 @@ int isup_get_cpc(unsigned char *buf, int len);
 int isup_get_calling_party_nai(unsigned char *buf, int len);
 int isup_get_called_party_nai(unsigned char *buf, int len);
 int isup_update_destination(char * dest, int hops, int nai, unsigned char *buf, int len, unsigned char * obuf, int olen);
+int isup_update_calling(char * origin, int nai, int presentation, int screening, unsigned char * buf, int len, unsigned char * obuf, int olen);
+
 
 #endif

+ 127 - 0
modules/sipt/ss7_parser.c

@@ -115,6 +115,33 @@ static int encode_called_party(char * number, unsigned char * flags, int nai, un
 	return numlen + 2;
 }
 
+static int encode_calling_party(char * number, int nai, int presentation, int screening, unsigned char * buf, int len) 
+{
+        int oddeven, datalen;
+
+        if (!number[0] && presentation != SS7_PRESENTATION_ADDR_NOT_AVAILABLE)
+                return 0;
+
+        if (number[0] && presentation != SS7_PRESENTATION_ADDR_NOT_AVAILABLE)
+	{
+                isup_put_number(&buf[2], number, &datalen, &oddeven);
+	}
+        else 
+	{
+                datalen = 0;
+                oddeven = 0;
+                nai = 0;
+        }
+
+        buf[0] = (oddeven << 7) | nai;      /* Nature of Address Indicator */
+         /* Assume E.164 ISDN numbering plan, calling number complete */
+        buf[1] = ((presentation == SS7_PRESENTATION_ADDR_NOT_AVAILABLE) ? 0 : (1 << 4)) |
+                ((presentation & 0x3) << 2) |
+                (screening & 0x3);
+
+        return datalen + 2;
+}
+
 // returns start of specified optional header of IAM, otherwise return -1
 static int get_optional_header(unsigned char header, unsigned char *buf, int len)
 {
@@ -332,3 +359,103 @@ int isup_update_destination(char * dest, int hops, int nai, unsigned char *buf,
 
 	return offset2;
 }
+
+int isup_update_calling(char * origin, int nai, int presentation, int screening, unsigned char * buf, int len, unsigned char * obuf, int olen)
+{
+	int offset = 0, offset2 = 0;
+	int res;
+	struct isup_iam_fixed * message = (struct isup_iam_fixed*)obuf;
+	struct isup_iam_fixed * orig_message = (struct isup_iam_fixed*)buf;
+
+	// not an iam? do nothing
+	if(orig_message->type != ISUP_IAM)
+	{
+		int l = len > olen ? olen : len;
+		memcpy((void*)obuf, (void *)(buf), l);
+		return l;
+	}
+
+	/* Message Type = 1 */
+	memset(obuf, 0, olen);
+
+	/* Copy the fixed parms */
+	memcpy((void*)obuf, (void *)(buf), offsetof(struct isup_iam_fixed, called_party_number));
+	len -= offsetof(struct isup_iam_fixed, called_party_number);
+	olen -= offsetof(struct isup_iam_fixed, called_party_number);
+	offset += offsetof(struct isup_iam_fixed, called_party_number);
+	offset2 += offsetof(struct isup_iam_fixed, called_party_number);
+
+	if (len < 1)
+		return -1;
+
+
+	/* IAM has one Fixed variable param, Called party number, we need to modify this */
+
+
+	// add the new mandatory fixed header
+	res = buf[offset];
+	memcpy((void*)(obuf+offset2), (void *)(buf+offset), res+1);
+	offset += res+1;
+	offset2 += res+1;
+	len -= res+1;
+	olen -= res+1;
+
+
+	
+	if (len < 1 )
+		return -1;
+
+
+	
+	// set the pointer to the optional part (there will be at least one optional header when we are done)
+	message->optional_pointer = (char)(offset2 - offsetof(struct isup_iam_fixed, optional_pointer));
+
+	/* Optional paramter parsing code */
+	if (orig_message->optional_pointer) {
+
+		bool has_calling = 0;
+		
+		while ((len > 0) && (buf[offset] != 0)) {
+			int res2 = 0;
+			struct isup_parm_opt *optparm = (struct isup_parm_opt *)(buf + offset);
+
+
+			res = optparm->len+2;
+			switch(optparm->type)
+			{
+				case ISUP_PARM_CALLING_PARTY_NUM:
+					obuf[offset2++] = ISUP_PARM_CALLING_PARTY_NUM;
+					res2 = encode_calling_party(origin, nai, presentation, screening, obuf+offset2+1, olen-1);
+					obuf[offset2] = (char)res2;
+
+					offset2 += res2+1;
+					olen -= res2+1;
+					has_calling = 1;
+					break;
+				default:
+					memcpy((void*)(obuf+offset2), (void *)(buf + offset), res);
+					offset2 += res;
+			}
+
+			len -= res;
+			offset += res;
+		}
+
+		// add missing headers
+		if(!has_calling)
+		{
+			obuf[offset2++] = ISUP_PARM_CALLING_PARTY_NUM;
+			res = encode_calling_party(origin, nai, presentation, screening, obuf+offset2+1, olen-1);
+			obuf[offset2] = (char)res;
+
+			offset2 += res+1;
+			olen -= res+1;
+			has_calling = 1;
+		}
+
+		// nicely null terminate it
+		obuf[offset2++] = 0;
+	}
+
+	return offset2;
+}