Browse Source

modules_k/nathelper: add_contact_alias() now accepts parameters

- Function add_contact_alias() can now be given ip addr, port, and proto
  as parameters.
Juha Heinanen 13 years ago
parent
commit
c4b4ec30ce

+ 49 - 48
modules_k/nathelper/README

@@ -24,13 +24,13 @@ Edited by
 
 
 Ovidiu Sas
 Ovidiu Sas
 
 
-   Copyright © 2003-2008 Sippy Software, Inc.
+   Copyright © 2003-2008 Sippy Software, Inc.
 
 
-   Copyright © 2005 Voice Sistem SRL
+   Copyright © 2005 Voice Sistem SRL
 
 
-   Copyright © 2009 TuTPro Inc.
+   Copyright © 2009 TuTPro Inc.
 
 
-   Copyright © 2010 VoIPEmbedded Inc.
+   Copyright © 2010 VoIPEmbedded Inc.
      __________________________________________________________________
      __________________________________________________________________
 
 
    Table of Contents
    Table of Contents
@@ -66,7 +66,7 @@ Ovidiu Sas
               5.5. fix_nated_register()
               5.5. fix_nated_register()
               5.6. nat_uac_test(flags)
               5.6. nat_uac_test(flags)
               5.7. is_rfc1918(ip_address)
               5.7. is_rfc1918(ip_address)
-              5.8. add_contact_alias()
+              5.8. add_contact_alias([ip_addr, port, proto])
               5.9. handle_ruri_alias()
               5.9. handle_ruri_alias()
 
 
         6. Exported Pseudo Variables
         6. Exported Pseudo Variables
@@ -136,7 +136,7 @@ Chapter 1. Admin Guide
         5.5. fix_nated_register()
         5.5. fix_nated_register()
         5.6. nat_uac_test(flags)
         5.6. nat_uac_test(flags)
         5.7. is_rfc1918(ip_address)
         5.7. is_rfc1918(ip_address)
-        5.8. add_contact_alias()
+        5.8. add_contact_alias([ip_addr, port, proto])
         5.9. handle_ruri_alias()
         5.9. handle_ruri_alias()
 
 
    6. Exported Pseudo Variables
    6. Exported Pseudo Variables
@@ -241,7 +241,7 @@ modparam("nathelper", "natping_interval", 10)
 
 
 4.2. ping_nated_only (integer)
 4.2. ping_nated_only (integer)
 
 
-   If this variable is set then only contacts that have "behind_NAT" flag
+   If this variable is set then only contacts that have “behind_NAT� flag
    in user location database set will get ping.
    in user location database set will get ping.
 
 
    Default value is 0.
    Default value is 0.
@@ -316,7 +316,7 @@ modparam("nathelper", "sipping_bflag", 7)
    feature, you have to set this parameter. The SIP request pinging will
    feature, you have to set this parameter. The SIP request pinging will
    be used only for requests marked so.
    be used only for requests marked so.
 
 
-   Default value is "NULL".
+   Default value is “NULL�.
 
 
    Example 1.7. Set sipping_from parameter
    Example 1.7. Set sipping_from parameter
 ...
 ...
@@ -328,7 +328,7 @@ modparam("nathelper", "sipping_from", "sip:[email protected]")
    The parameter sets the SIP method to be used in generating the SIP
    The parameter sets the SIP method to be used in generating the SIP
    requests for NAT ping purposes.
    requests for NAT ping purposes.
 
 
-   Default value is "OPTIONS".
+   Default value is “OPTIONS�.
 
 
    Example 1.8. Set sipping_method parameter
    Example 1.8. Set sipping_method parameter
 ...
 ...
@@ -346,7 +346,7 @@ Note
 
 
    The string must be a complete SDP line, including the EOH (\r\n).
    The string must be a complete SDP line, including the EOH (\r\n).
 
 
-   Default value is "a=nortpproxy:yes\r\n".
+   Default value is “a=nortpproxy:yes\r\n�.
 
 
    Example 1.9. Set nortpproxy_str parameter
    Example 1.9. Set nortpproxy_str parameter
 ...
 ...
@@ -365,7 +365,7 @@ modparam("nathelper", "nortpproxy_str", "a=sdpmangled:yes\r\n")
    Keepalives are sent stateless, not using TM module. The value of this
    Keepalives are sent stateless, not using TM module. The value of this
    parameter has to be few times higher than natping_interval.
    parameter has to be few times higher than natping_interval.
 
 
-   Default value is "0" (feature disabled).
+   Default value is “0� (feature disabled).
 
 
    Example 1.10. Set keepalive_timeout parameter
    Example 1.10. Set keepalive_timeout parameter
 ...
 ...
@@ -381,10 +381,10 @@ modparam("nathelper", "keepalive_timeout", 120)
    5.5. fix_nated_register()
    5.5. fix_nated_register()
    5.6. nat_uac_test(flags)
    5.6. nat_uac_test(flags)
    5.7. is_rfc1918(ip_address)
    5.7. is_rfc1918(ip_address)
-   5.8. add_contact_alias()
+   5.8. add_contact_alias([ip_addr, port, proto])
    5.9. handle_ruri_alias()
    5.9. handle_ruri_alias()
 
 
-5.1. fix_nated_contact()
+5.1.  fix_nated_contact()
 
 
    Rewrites Contact HF to contain request's source address:port.
    Rewrites Contact HF to contain request's source address:port.
 
 
@@ -396,18 +396,18 @@ modparam("nathelper", "keepalive_timeout", 120)
 if (search("User-Agent: Cisco ATA.*") {fix_nated_contact();};
 if (search("User-Agent: Cisco ATA.*") {fix_nated_contact();};
 ...
 ...
 
 
-5.2. fix_nated_sdp(flags [, ip_address])
+5.2.  fix_nated_sdp(flags [, ip_address])
 
 
    Alters the SDP information in orer to facilitate NAT traversal. What
    Alters the SDP information in orer to facilitate NAT traversal. What
-   changes to be performed may be controled via the "flags" parameter.
+   changes to be performed may be controled via the “flags� parameter.
 
 
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
      * flags - the value may be a bitwise OR of the following flags:
      * flags - the value may be a bitwise OR of the following flags:
-          + 0x01 - adds "a=direction:active" SDP line;
+          + 0x01 - adds “a=direction:active� SDP line;
           + 0x02 - rewrite media IP address (c=) with source address of
           + 0x02 - rewrite media IP address (c=) with source address of
             the message or the provided IP address (the provide IP address
             the message or the provided IP address (the provide IP address
             take precedence over the source address).
             take precedence over the source address).
-          + 0x04 - adds "a=nortpproxy:yes" SDP line;
+          + 0x04 - adds “a=nortpproxy:yes� SDP line;
           + 0x08 - rewrite IP from origin description (o=) with source
           + 0x08 - rewrite IP from origin description (o=) with source
             address of the message or the provided IP address (the provide
             address of the message or the provided IP address (the provide
             IP address take precedence over the source address).
             IP address take precedence over the source address).
@@ -424,7 +424,7 @@ if (search("User-Agent: Cisco ATA.*") {fix_nated_contact();};
 if (search("User-Agent: Cisco ATA.*") {fix_nated_sdp("3");};
 if (search("User-Agent: Cisco ATA.*") {fix_nated_sdp("3");};
 ...
 ...
 
 
-5.3. set_rtp_proxy_set()
+5.3.  set_rtp_proxy_set()
 
 
    Sets the Id of the rtpproxy set to be used for the next
    Sets the Id of the rtpproxy set to be used for the next
    [un]force_rtp_proxy(), rtpproxy_offer() or rtpproxy_answer() command.
    [un]force_rtp_proxy(), rtpproxy_offer() or rtpproxy_answer() command.
@@ -438,7 +438,7 @@ set_rtp_proxy_set("2");
 force_rtp_proxy();
 force_rtp_proxy();
 ...
 ...
 
 
-5.4. add_rcv_param([flag]),
+5.4.  add_rcv_param([flag]),
 
 
    Add received parameter to Contact header fields or Contact URI. The
    Add received parameter to Contact header fields or Contact URI. The
    parameter will contain URI created from the source IP, port, and
    parameter will contain URI created from the source IP, port, and
@@ -462,7 +462,7 @@ add_rcv_param(); # add the parameter to the Contact header
 add_rcv_param("1"); # add the parameter to the Contact URI
 add_rcv_param("1"); # add the parameter to the Contact URI
 ...
 ...
 
 
-5.5. fix_nated_register()
+5.5.  fix_nated_register()
 
 
    The function creates a URI consisting of the source IP, port, and
    The function creates a URI consisting of the source IP, port, and
    protocol and stores the URI in an Attribute-Value-Pair. The URI will be
    protocol and stores the URI in an Attribute-Value-Pair. The URI will be
@@ -480,7 +480,7 @@ add_rcv_param("1"); # add the parameter to the Contact URI
 fix_nated_register();
 fix_nated_register();
 ...
 ...
 
 
-5.6. nat_uac_test(flags)
+5.6.  nat_uac_test(flags)
 
 
    Tries to guess if client's request originated behind a nat. The
    Tries to guess if client's request originated behind a nat. The
    parameter determines what heuristics is used.
    parameter determines what heuristics is used.
@@ -503,17 +503,18 @@ fix_nated_register();
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    FAILURE_ROUTE, BRANCH_ROUTE.
    FAILURE_ROUTE, BRANCH_ROUTE.
 
 
-5.7. is_rfc1918(ip_address)
+5.7.  is_rfc1918(ip_address)
 
 
    Determines if the address in the parameter is an rfc1918 address. The
    Determines if the address in the parameter is an rfc1918 address. The
    parameter allows pseudo-variables usage.
    parameter allows pseudo-variables usage.
 
 
    This function can be used from ANY_ROUTE.
    This function can be used from ANY_ROUTE.
 
 
-5.8. add_contact_alias()
+5.8.  add_contact_alias([ip_addr, port, proto])
 
 
-   Adds ;alias=ip:port parameter to contact URI containing received
-   ip:port if contact uri ip:port does not match received ip:port.
+   Adds ;alias=ip~port~transport parameter to contact URI containing
+   either received ip, port, and transport protocol or those given as
+   parameters.
 
 
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
    BRANCH_ROUTE, and LOCAL_ROUTE.
    BRANCH_ROUTE, and LOCAL_ROUTE.
@@ -521,7 +522,7 @@ fix_nated_register();
    Example 1.16. add_contact_alias usage
    Example 1.16. add_contact_alias usage
 ...
 ...
     if (!is_present_hf("Record-Route")) {
     if (!is_present_hf("Record-Route")) {
-        if (!add_contact_alias()) {
+        if (!add_contact_alias("$var(src_ip)", "$Rp", "tcp")) {
             xlog("L_ERR", "Error in aliasing contact $ct\n");
             xlog("L_ERR", "Error in aliasing contact $ct\n");
             send_reply("400", "Bad request");
             send_reply("400", "Bad request");
             exit;
             exit;
@@ -529,7 +530,7 @@ fix_nated_register();
     };
     };
 ...
 ...
 
 
-5.9. handle_ruri_alias()
+5.9.  handle_ruri_alias()
 
 
    Checks if Request URI has alias param and if so, removes it and sets
    Checks if Request URI has alias param and if so, removes it and sets
    $du based on its value. Note that this means that routing of request is
    $du based on its value. Note that this means that routing of request is
@@ -610,45 +611,45 @@ $ kamctl fifo nh_enable_ping 1
 
 
 Chapter 2. Frequently Asked Questions
 Chapter 2. Frequently Asked Questions
 
 
-   2.1. What happend with "rtpproxy_disable" parameter?
+   2.1. What happend with “rtpproxy_disable� parameter?
    2.2. Where can I find more about Kamailio?
    2.2. Where can I find more about Kamailio?
    2.3. Where can I post a question about this module?
    2.3. Where can I post a question about this module?
    2.4. How can I report a bug?
    2.4. How can I report a bug?
 
 
    2.1.
    2.1.
 
 
-   What happend with "rtpproxy_disable" parameter?
+       What happend with “rtpproxy_disable� parameter?
 
 
-   It was removed as it became obsolete - now "rtpproxy_sock" can take
-   empty value to disable the rtpproxy functionality.
+       It was removed as it became obsolete - now “rtpproxy_sock� can take
+       empty value to disable the rtpproxy functionality.
 
 
    2.2.
    2.2.
 
 
-   Where can I find more about Kamailio?
+       Where can I find more about Kamailio?
 
 
-   Take a look at http://www.kamailio.org/.
+       Take a look at http://www.kamailio.org/.
 
 
    2.3.
    2.3.
 
 
-   Where can I post a question about this module?
+       Where can I post a question about this module?
 
 
-   First at all check if your question was already answered on one of our
-   mailing lists:
-     * User Mailing List -
-       http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
-     * Developer Mailing List -
-       http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
+       First at all check if your question was already answered on one of our
+       mailing lists:
+         * User Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
+         * Developer Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
 
 
-   E-mails regarding any stable Kamailio release should be sent to
-   <[email protected]> and e-mails regarding development
-   versions should be sent to <[email protected]>.
+       E-mails regarding any stable Kamailio release should be sent to
+       <[email protected]> and e-mails regarding development
+       versions should be sent to <[email protected]>.
 
 
-   If you want to keep the mail private, send it to
-   <[email protected]>.
+       If you want to keep the mail private, send it to
+       <[email protected]>.
 
 
    2.4.
    2.4.
 
 
-   How can I report a bug?
+       How can I report a bug?
 
 
-   Please follow the guidelines provided at:
-   http://sip-router.org/tracker.
+       Please follow the guidelines provided at:
+       http://sip-router.org/tracker.

+ 5 - 5
modules_k/nathelper/doc/nathelper_admin.xml

@@ -598,12 +598,12 @@ fix_nated_register();
 
 
 	<section>
 	<section>
 		<title>
 		<title>
-		<function moreinfo="none">add_contact_alias()</function>
+		<function moreinfo="none">add_contact_alias([ip_addr, port, proto])</function>
 		</title>
 		</title>
 		<para>
 		<para>
-		Adds ;alias=ip:port parameter to contact URI containing
-		received ip:port if contact uri ip:port does not match
-		received ip:port.
+		Adds ;alias=ip~port~transport parameter to contact URI
+		containing either received ip, port, and transport protocol
+		or those given as parameters.
 		</para>
 		</para>
 		<para>
 		<para>
 		This function can be used from
 		This function can be used from
@@ -614,7 +614,7 @@ fix_nated_register();
 		<programlisting format="linespecific">
 		<programlisting format="linespecific">
 ...
 ...
     if (!is_present_hf("Record-Route")) {
     if (!is_present_hf("Record-Route")) {
-        if (!add_contact_alias()) {
+        if (!add_contact_alias("$var(src_ip)", "$Rp", "tcp")) {
             xlog("L_ERR", "Error in aliasing contact $ct\n");
             xlog("L_ERR", "Error in aliasing contact $ct\n");
             send_reply("400", "Bad request");
             send_reply("400", "Bad request");
             exit;
             exit;

+ 174 - 6
modules_k/nathelper/nathelper.c

@@ -284,7 +284,8 @@ MODULE_VERSION
 #define	CPORT		"22222"
 #define	CPORT		"22222"
 static int nat_uac_test_f(struct sip_msg* msg, char* str1, char* str2);
 static int nat_uac_test_f(struct sip_msg* msg, char* str1, char* str2);
 static int fix_nated_contact_f(struct sip_msg *, char *, char *);
 static int fix_nated_contact_f(struct sip_msg *, char *, char *);
-static int add_contact_alias_f(struct sip_msg *, char *, char *);
+static int add_contact_alias_0_f(struct sip_msg *, char *, char *);
+static int add_contact_alias_3_f(struct sip_msg *, char *, char *, char *);
 static int handle_ruri_alias_f(struct sip_msg *, char *, char *);
 static int handle_ruri_alias_f(struct sip_msg *, char *, char *);
 static int pv_get_rr_count_f(struct sip_msg *, pv_param_t *, pv_value_t *);
 static int pv_get_rr_count_f(struct sip_msg *, pv_param_t *, pv_value_t *);
 static int pv_get_rr_top_count_f(struct sip_msg *, pv_param_t *, pv_value_t *);
 static int pv_get_rr_top_count_f(struct sip_msg *, pv_param_t *, pv_value_t *);
@@ -295,6 +296,7 @@ static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);
 static int fix_nated_register_f(struct sip_msg *, char *, char *);
 static int fix_nated_register_f(struct sip_msg *, char *, char *);
 static int fixup_fix_nated_register(void** param, int param_no);
 static int fixup_fix_nated_register(void** param, int param_no);
 static int fixup_fix_sdp(void** param, int param_no);
 static int fixup_fix_sdp(void** param, int param_no);
+static int fixup_add_contact_alias(void** param, int param_no);
 static int add_rcv_param_f(struct sip_msg *, char *, char *);
 static int add_rcv_param_f(struct sip_msg *, char *, char *);
 static int nh_sip_reply_received(sip_msg_t *msg);
 static int nh_sip_reply_received(sip_msg_t *msg);
 
 
@@ -358,9 +360,12 @@ static cmd_export_t cmds[] = {
 	{"fix_nated_contact",  (cmd_function)fix_nated_contact_f,    0,
 	{"fix_nated_contact",  (cmd_function)fix_nated_contact_f,    0,
 		0, 0,
 		0, 0,
 		REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
 		REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
-	{"add_contact_alias",  (cmd_function)add_contact_alias_f,    0,
+	{"add_contact_alias",  (cmd_function)add_contact_alias_0_f,  0,
 		0, 0,
 		0, 0,
 		REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
 		REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
+	{"add_contact_alias",  (cmd_function)add_contact_alias_3_f,  3,
+		fixup_add_contact_alias, 0,
+		REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
 	{"handle_ruri_alias",  (cmd_function)handle_ruri_alias_f,    0,
 	{"handle_ruri_alias",  (cmd_function)handle_ruri_alias_f,    0,
 		0, 0,
 		0, 0,
 		REQUEST_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
 		REQUEST_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
@@ -469,6 +474,13 @@ static int fixup_fix_nated_register(void** param, int param_no)
 	return 0;
 	return 0;
 }
 }
 
 
+static int fixup_add_contact_alias(void** param, int param_no)
+{
+    if ((param_no >= 1) && (param_no <= 3)) return fixup_spve_null(param, 1);
+ 
+    LM_ERR("invalid parameter number <%d>\n", param_no);
+    return -1;
+}
 
 
 static struct mi_root* mi_enable_natping(struct mi_root* cmd_tree, 
 static struct mi_root* mi_enable_natping(struct mi_root* cmd_tree, 
 											void* param )
 											void* param )
@@ -812,11 +824,12 @@ fix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2)
 #define SALIAS_LEN (sizeof(SALIAS) - 1)
 #define SALIAS_LEN (sizeof(SALIAS) - 1)
 
 
 /*
 /*
- * Adds ;alias=ip:port param to contact uri containing received ip:port
- * if contact uri ip:port does not match received ip:port.
+ * Adds ;alias=ip~port~proto param to contact uri containing received ip,
+ * port, and transport proto if contact uri ip and port do not match
+ * received ip and port.
  */
  */
 static int
 static int
-add_contact_alias_f(struct sip_msg* msg, char* str1, char* str2)
+add_contact_alias_0_f(struct sip_msg* msg, char* str1, char* str2)
 {
 {
     int len, param_len, ip_len;
     int len, param_len, ip_len;
     contact_t *c;
     contact_t *c;
@@ -855,7 +868,7 @@ add_contact_alias_f(struct sip_msg* msg, char* str1, char* str2)
 	
 	
     /* Check if function has been called already */
     /* Check if function has been called already */
     if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
     if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
-	LM_ERR("you can't call alias_contact twice, check your config!\n");
+	LM_ERR("you can't call add_contact_alias twice, check your config!\n");
 	return -1;
 	return -1;
     }
     }
 
 
@@ -940,6 +953,161 @@ add_contact_alias_f(struct sip_msg* msg, char* str1, char* str2)
 }
 }
 
 
 
 
+static int proto_type_to_int(char *proto) {
+    if (strcasecmp(proto, "udp") == 0)
+	return PROTO_UDP;
+    if (strcasecmp(proto, "tcp") == 0)
+	return PROTO_TCP;
+    if (strcasecmp(proto, "tls") == 0)
+	return PROTO_TLS;
+    if (strcasecmp(proto, "sctp") == 0)
+	return PROTO_SCTP;
+    if (strcasecmp(proto, "ws") == 0)
+	return PROTO_WS;
+    if (strcasecmp(proto, "wss") == 0)
+	return PROTO_WSS;
+    return PROTO_OTHER;
+}
+
+
+/*
+ * Adds ;alias=ip~port~proto param to contact uri containing ip, port,
+ * and encoded proto given as parameters.
+ */
+static int
+add_contact_alias_3_f(struct sip_msg* msg, char* _ip, char* _port, char* _proto)
+{
+    int param_len, proto;
+    unsigned int tmp;
+    contact_t *c;
+    struct lump *anchor;
+    struct sip_uri uri;
+    char *bracket, *lt, *param, *at, *start;
+    str ip_str, port_str, proto_str;
+
+    /* Do nothing if Contact header does not exist */
+    if (!msg->contact) {
+	if (parse_headers(msg, HDR_CONTACT_F, 0) == -1)  {
+	    LM_ERR("while parsing headers\n");
+	    return -1;
+	}
+	if (!msg->contact) {
+	    LM_DBG("no contact header\n");
+	    return 2;
+	}
+    }
+    if (get_contact_uri(msg, &uri, &c) == -1) {
+	LM_ERR("failed to get contact uri\n");
+	return -1;
+    }
+
+    /* Get and check param values */
+    if (fixup_get_svalue(msg, (gparam_p)_ip, &ip_str) != 0) {
+	LM_ERR("cannot get ip param value\n");
+	return -1;
+    }
+    if ((str2ip(&ip_str) == NULL)
+#ifdef USE_IPV6
+	&& (str2ip6(&ip_str) == NULL)
+#endif
+	) {
+	LM_ERR("ip param value %s is not valid IP address\n", ip_str.s);
+	return -1;
+    }
+    if (fixup_get_svalue(msg, (gparam_p)_port, &port_str) != 0) {
+	LM_ERR("cannot get port param value\n");
+	return -1;
+    }
+    if ((str2int(&port_str, &tmp) == -1) || (tmp == 0) || (tmp > 65535)) {
+	LM_ERR("port param value is not valid port\n");
+	return -1;
+    }
+    if (fixup_get_svalue(msg, (gparam_p)_proto, &proto_str) != 0) {
+	LM_ERR("cannot get proto param value\n");
+	return -1;
+    }
+    proto = proto_type_to_int(proto_str.s);
+    if (proto == PROTO_OTHER) {
+	LM_ERR("proto param value %s is not a known protocol\n", proto_str.s);
+	return -1;
+    }
+
+    /* Check if function has been called already */
+    if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
+	LM_ERR("you can't call alias_contact twice, check your config!\n");
+	return -1;
+    }
+
+    /* Check if Contact URI needs to be enclosed in <>s */
+    lt = param = NULL;
+    bracket = memchr(msg->contact->body.s, '<', msg->contact->body.len);
+    if (bracket == NULL) {
+	/* add opening < */
+	lt = (char*)pkg_malloc(1);
+	if (!lt) {
+	    LM_ERR("no pkg memory left for lt sign\n");
+	    goto err;
+	}
+	*lt = '<';
+	anchor = anchor_lump(msg, msg->contact->body.s - msg->buf, 0, 0);
+	if (anchor == NULL) {
+	    LM_ERR("anchor_lump for beginning of contact body failed\n");
+	    goto err;
+	}
+	if (insert_new_lump_before(anchor, lt, 1, 0) == 0) {
+	    LM_ERR("insert_new_lump_before for \"<\" failed\n");
+	    goto err;
+	}
+    }
+
+    /* Create  ;alias param */
+    param_len = SALIAS_LEN + IP6_MAX_STR_SIZE + 1 /* ~ */ + 5 /* port */ +
+	1 /* ~ */ + 1 /* proto */ + 1 /* closing > */;
+    param = (char*)pkg_malloc(param_len);
+    if (!param) {
+	LM_ERR("no pkg memory left for alias param\n");
+	goto err;
+    }
+    at = param;
+    /* ip address */
+    append_str(at, SALIAS, SALIAS_LEN);
+    append_str(at, ip_str.s, ip_str.len);
+    /* port */
+    append_chr(at, '~');
+    append_str(at, port_str.s, port_str.len);
+    /* proto */
+    append_chr(at, '~');
+    append_chr(at, proto + '0');
+    /* closing > */
+    if (bracket == NULL) {
+	append_chr(at, '>');
+    }
+    param_len = at - param;
+
+    /* Add  ;alias param */
+    LM_DBG("adding param <%.*s>\n", param_len, param);
+    if (uri.port.len > 0) {
+	start = uri.port.s + uri.port.len;
+    } else {
+	start = uri.host.s + uri.host.len;
+    }
+    anchor = anchor_lump(msg, start - msg->buf, 0, 0);
+    if (anchor == NULL) {
+	LM_ERR("anchor_lump for ;alias param failed\n");
+	goto err;
+    }
+    if (insert_new_lump_after(anchor, param, param_len, 0) == 0) {
+	LM_ERR("insert_new_lump_after for ;alias param failed\n");
+	goto err;
+    }
+    return 1;
+
+ err:
+    if (lt) pkg_free(lt);
+    if (param) pkg_free(param);
+    return -1;
+}
+
 #define ALIAS        "alias="
 #define ALIAS        "alias="
 #define ALIAS_LEN (sizeof(ALIAS) - 1)
 #define ALIAS_LEN (sizeof(ALIAS) - 1)