Skip to content

Commit a74fc46

Browse files
committed
[nathelper] add functions to preserve the original private contact.
The fix_nated_contact() take a flag in order to save the original private IP and port into the 'org' uri param (b64 encoded) The new restore_nated_ruri() function (upon routing sequential requests) extract the info from the 'org' RURI param and restores the private ip:port in RURI. The received RURI is pushed into DURI for routing purposes ;) Alternative to #3769
1 parent 43b696d commit a74fc46

3 files changed

Lines changed: 209 additions & 21 deletions

File tree

modules/nathelper/README

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@ nathelper Module
3636

3737
1.5. Exported Functions
3838

39-
1.5.1. fix_nated_contact([uri_params])
39+
1.5.1. fix_nated_contact([uri_params [, flags]])
4040
1.5.2. fix_nated_sdp(flags [, ip_address [,
4141
sdp_fields]])
4242

4343
1.5.3. add_rcv_param([flag]),
4444
1.5.4. fix_nated_register()
4545
1.5.5. nat_uac_test(flags)
46+
1.5.6. restore_nated_ruri()
4647

4748
1.6. Exported MI Functions
4849

@@ -448,7 +449,7 @@ modparam("nathelper", "cluster_sharing_tag", "vip")
448449

449450
1.5. Exported Functions
450451

451-
1.5.1. fix_nated_contact([uri_params])
452+
1.5.1. fix_nated_contact([uri_params [, flags]])
452453

453454
Rewrites the URI Contact HF to contain request's source
454455
address:port. If a list of URI parameter is provided, it will
@@ -460,14 +461,20 @@ modparam("nathelper", "cluster_sharing_tag", "vip")
460461

461462
Parameters:
462463
* uri_params (string, optional)
464+
* flags (string, optional) - CSV list of flags:
465+
+ preserve-uri - add an extra Contact URI parameter
466+
named "org". The org value is the Base64 encoding of
467+
the original Contact URI host:port part. Pair it with
468+
restore_nated_ruri() for restoring the original
469+
host:port into R-URI.
463470

464471
This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
465472
BRANCH_ROUTE.
466473

467474
Example 1.20. fix_nated_contact usage
468475
...
469476
if (search("User-Agent: Cisco ATA.*") {
470-
fix_nated_contact(";ata=cisco");
477+
fix_nated_contact(";ata=cisco", "preserve-uri");
471478
} else {
472479
fix_nated_contact();
473480
}
@@ -595,6 +602,19 @@ if (nat_uac_test("private-contact,private-sdp"))
595602
xlog("SIP message is NAT'ed (Call-ID: $ci)\n");
596603
...
597604

605+
1.5.6. restore_nated_ruri()
606+
607+
Restores the original R-URI host:port from the "org" URI
608+
parameter generated by fix_nated_contact("...", "preserve-uri").
609+
610+
Returns -1 on error or if "org" does not exist in R-URI. On
611+
success, returns 1 after removing "org" from R-URI, storing
612+
the resulting R-URI into D-URI, decoding the original host:port
613+
from "org", and rewriting R-URI host:port with the decoded
614+
value.
615+
616+
This function can be used from REQUEST_ROUTE, BRANCH_ROUTE.
617+
598618
1.6. Exported MI Functions
599619

600620
1.6.1. nathelper:enable_ping

modules/nathelper/doc/nathelper_admin.xml

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ modparam("nathelper", "cluster_sharing_tag", "vip")
594594
<title>Exported Functions</title>
595595
<section id="func_fix_nated_contact" xreflabel="fix_nated_contact()">
596596
<title>
597-
<function moreinfo="none">fix_nated_contact([uri_params])</function>
597+
<function moreinfo="none">fix_nated_contact([uri_params [, flags]])</function>
598598
</title>
599599
<para>
600600
Rewrites the URI Contact <acronym>HF</acronym> to contain request's
@@ -611,6 +611,18 @@ modparam("nathelper", "cluster_sharing_tag", "vip")
611611
<listitem><para>
612612
<emphasis>uri_params (string, optional)</emphasis>
613613
</para></listitem>
614+
<listitem><para>
615+
<emphasis>flags (string, optional)</emphasis> - CSV list of flags:
616+
<itemizedlist>
617+
<listitem><para>
618+
<emphasis>preserve-uri</emphasis> - add an extra Contact URI
619+
parameter named "org". The org value is the Base64 encoding of
620+
the original Contact URI host:port part. Pair it with
621+
<function>restore_nated_ruri()</function> for restoring the
622+
original host:port into R-URI.
623+
</para></listitem>
624+
</itemizedlist>
625+
</para></listitem>
614626
</itemizedlist>
615627
<para>
616628
This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE.
@@ -620,7 +632,7 @@ modparam("nathelper", "cluster_sharing_tag", "vip")
620632
<programlisting format="linespecific">
621633
...
622634
if (search("User-Agent: Cisco ATA.*") {
623-
fix_nated_contact(";ata=cisco");
635+
fix_nated_contact(";ata=cisco", "preserve-uri");
624636
} else {
625637
fix_nated_contact();
626638
}
@@ -836,6 +848,25 @@ if (nat_uac_test("private-contact,private-sdp"))
836848
</programlisting>
837849
</example>
838850
</section>
851+
<section id="func_restore_nated_ruri" xreflabel="restore_nated_ruri()">
852+
<title>
853+
<function>restore_nated_ruri()</function>
854+
</title>
855+
<para>
856+
Restores the original R-URI host:port from the "org" URI parameter
857+
generated by
858+
<function>fix_nated_contact("...", "preserve-uri")</function>.
859+
</para>
860+
<para>
861+
Returns -1 on error or if "org" does not exist in R-URI. On success,
862+
returns 1 after removing "org" from R-URI, storing the resulting
863+
R-URI into D-URI, decoding the original host:port from "org", and
864+
rewriting R-URI host:port with the decoded value.
865+
</para>
866+
<para>
867+
This function can be used from REQUEST_ROUTE, BRANCH_ROUTE.
868+
</para>
869+
</section>
839870
</section>
840871

841872
<section id="exported_mi_functions" xreflabel="Exported MI Functions">
@@ -877,4 +908,3 @@ $
877908
</section>
878909

879910
</chapter>
880-

modules/nathelper/nathelper.c

Lines changed: 153 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ static int sipping_latency_flag = -1; /* by the code imported by sip_pinger*/
9595
#define NAT_UAC_TEST_C_RPORT 0x40
9696
#define NAT_UAC_TEST_RFC_6333 0x80
9797

98+
#define FIX_NATED_CONTACT_PRESERVE_URI 0x01
99+
98100
#define MI_SET_NATPING_STATE "enable_ping"
99101
#define MI_DEFAULT_NATPING_STATE 1
100102

@@ -113,9 +115,11 @@ static int sipping_latency_flag = -1; /* by the code imported by sip_pinger*/
113115

114116
static int fixup_flags_uac_test(void** param);
115117
static int fixup_flags_sdp(void** param);
118+
static int fixup_flags_fix_nated_contact(void** param);
116119

117120
static int nat_uac_test_f(struct sip_msg* msg, void *tests);
118-
static int fix_nated_contact_f(struct sip_msg* msg, str *params);
121+
static int fix_nated_contact_f(struct sip_msg* msg, str *params, void *flags);
122+
static int restore_nated_ruri_f(struct sip_msg *msg);
119123
static int fix_nated_sdp_f(struct sip_msg* msg, void *flags, str *ip,
120124
str *new_sdp_lines);
121125
static int fix_nated_register_f(struct sip_msg *, char *, char *);
@@ -222,8 +226,12 @@ unsigned int *natping_state=0;
222226

223227
static const cmd_export_t cmds[] = {
224228
{"fix_nated_contact", (cmd_function)fix_nated_contact_f, {
225-
{CMD_PARAM_STR|CMD_PARAM_OPT,0,0}, {0,0,0}},
229+
{CMD_PARAM_STR|CMD_PARAM_OPT,0,0},
230+
{CMD_PARAM_STR|CMD_PARAM_OPT,fixup_flags_fix_nated_contact,0},
231+
{0,0,0}},
226232
REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
233+
{"restore_nated_ruri", (cmd_function)restore_nated_ruri_f, {{0,0,0}},
234+
REQUEST_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
227235
{"fix_nated_sdp", (cmd_function)fix_nated_sdp_f, {
228236
{CMD_PARAM_STR,fixup_flags_sdp,0},
229237
{CMD_PARAM_STR|CMD_PARAM_OPT,0,0},
@@ -630,7 +638,7 @@ isnulladdr(str *sx, int pf)
630638
* of the packet.
631639
*/
632640
static int
633-
fix_nated_contact_f(struct sip_msg* msg, str *params)
641+
fix_nated_contact_f(struct sip_msg* msg, str *params, void *_flags)
634642
{
635643
int len, len1;
636644
char *cp, *buf, temp, *p;
@@ -640,6 +648,10 @@ fix_nated_contact_f(struct sip_msg* msg, str *params)
640648
struct sip_uri uri;
641649
str hostport, left, left2;
642650
int is_enclosed;
651+
unsigned int flags = (unsigned int)(unsigned long)_flags;
652+
int preserve_uri = !!(flags & FIX_NATED_CONTACT_PRESERVE_URI);
653+
str org_param = STR_NULL;
654+
int org_val_len;
643655

644656
if (params && params->len==0)
645657
params = 0;
@@ -681,44 +693,67 @@ fix_nated_contact_f(struct sip_msg* msg, str *params)
681693
if (anchor == 0)
682694
return -1;
683695

696+
org_param = STR_NULL;
697+
if (preserve_uri) {
698+
org_val_len = calc_base64_encode_len(hostport.len);
699+
org_param.len = 5 + org_val_len; /* ;org= + b64 */
700+
org_param.s = pkg_malloc(org_param.len);
701+
if (org_param.s == NULL) {
702+
LM_ERR("out of pkg memory\n");
703+
return -1;
704+
}
705+
memcpy(org_param.s, ";org=", 5);
706+
base64encode((unsigned char *)(org_param.s + 5),
707+
(unsigned char *)hostport.s, hostport.len);
708+
}
709+
684710
cp = ip_addr2a(&msg->rcv.src_ip);
685711
len = (hostport.s-c->uri.s) + strlen(cp) + 6 /* :port */
686712
+ 2 /* just in case if IPv6 */
687713
+ (params?params->len+(is_enclosed?0:2):0)
714+
+ org_param.len
688715
+ 1 + left.len + left2.len;
689716
buf = pkg_malloc(len);
690717
if (buf == NULL) {
691718
LM_ERR("out of pkg memory\n");
719+
if (org_param.s)
720+
pkg_free(org_param.s);
692721
return -1;
693722
}
694723
temp = hostport.s[0]; hostport.s[0] = '\0';
695724
if (params==NULL) {
696725
if (msg->rcv.src_ip.af==AF_INET6)
697-
len1 = snprintf(buf, len, "%s[%s]:%d%.*s%.*s", c->uri.s, cp,
698-
msg->rcv.src_port,left.len,left.s,left2.len,left2.s);
726+
len1 = snprintf(buf, len, "%s[%s]:%d%.*s%.*s%.*s", c->uri.s, cp,
727+
msg->rcv.src_port,org_param.len,org_param.s,
728+
left.len,left.s,left2.len,left2.s);
699729
else
700-
len1 = snprintf(buf, len, "%s%s:%d%.*s%.*s", c->uri.s, cp,
701-
msg->rcv.src_port,left.len,left.s,left2.len,left2.s);
730+
len1 = snprintf(buf, len, "%s%s:%d%.*s%.*s%.*s", c->uri.s, cp,
731+
msg->rcv.src_port,org_param.len,org_param.s,
732+
left.len,left.s,left2.len,left2.s);
702733
} else if (!is_enclosed) {
703734
if (msg->rcv.src_ip.af==AF_INET6)
704-
len1 = snprintf(buf, len, "<%s[%s]:%d%.*s>", c->uri.s, cp,
705-
msg->rcv.src_port,params->len,params->s);
735+
len1 = snprintf(buf, len, "<%s[%s]:%d%.*s%.*s>", c->uri.s, cp,
736+
msg->rcv.src_port,params->len,params->s,
737+
org_param.len,org_param.s);
706738
else
707-
len1 = snprintf(buf, len, "<%s%s:%d%.*s>", c->uri.s, cp,
708-
msg->rcv.src_port,params->len,params->s);
739+
len1 = snprintf(buf, len, "<%s%s:%d%.*s%.*s>", c->uri.s, cp,
740+
msg->rcv.src_port,params->len,params->s,
741+
org_param.len,org_param.s);
709742
} else {
710743
if (msg->rcv.src_ip.af==AF_INET6)
711-
len1 = snprintf(buf, len, "%s[%s]:%d%.*s%.*s%.*s", c->uri.s, cp,
744+
len1 = snprintf(buf, len, "%s[%s]:%d%.*s%.*s%.*s%.*s", c->uri.s, cp,
712745
msg->rcv.src_port,params->len,params->s,
713-
left.len,left.s,left2.len,left2.s);
746+
org_param.len,org_param.s,left.len,left.s,left2.len,left2.s);
714747
else
715-
len1 = snprintf(buf, len, "%s%s:%d%.*s%.*s%.*s", c->uri.s, cp,
748+
len1 = snprintf(buf, len, "%s%s:%d%.*s%.*s%.*s%.*s", c->uri.s, cp,
716749
msg->rcv.src_port,params->len,params->s,
717-
left.len,left.s,left2.len,left2.s);
750+
org_param.len,org_param.s,left.len,left.s,left2.len,left2.s);
718751
}
719752
if (len1 < len)
720753
len = len1;
721754
hostport.s[0] = temp;
755+
if (org_param.s)
756+
pkg_free(org_param.s);
722757
//LM_DBG("lump--- |%.*s|\n",len,buf);
723758
if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) {
724759
pkg_free(buf);
@@ -743,6 +778,109 @@ fix_nated_contact_f(struct sip_msg* msg, str *params)
743778
return 1;
744779
}
745780

781+
static int restore_nated_ruri_f(struct sip_msg *msg)
782+
{
783+
static const str org_uri_param = str_init("org");
784+
struct sip_uri *parsed_uri;
785+
str org_val, hostport;
786+
str old_uri, new_uri, param_tok;
787+
int begin_len, end_len, dec_buf_len;
788+
int org_idx;
789+
790+
if (parse_sip_msg_uri(msg) < 0) {
791+
LM_ERR("failed to parse R-URI\n");
792+
return -1;
793+
}
794+
795+
parsed_uri = &msg->parsed_uri;
796+
if (get_uri_param_val(parsed_uri, &org_uri_param, &org_val) < 0 ||
797+
org_val.len <= 0)
798+
return -1;
799+
800+
dec_buf_len = calc_max_base64_decode_len(org_val.len);
801+
if (dec_buf_len <= 0) {
802+
LM_ERR("invalid 'org' URI parameter\n");
803+
return -1;
804+
}
805+
hostport.s = pkg_malloc(dec_buf_len + 1);
806+
if (hostport.s == NULL) {
807+
LM_ERR("out of pkg memory\n");
808+
return -1;
809+
}
810+
811+
hostport.len = base64decode((unsigned char *)hostport.s,
812+
(unsigned char *)org_val.s, org_val.len);
813+
if (hostport.len <= 0) {
814+
LM_ERR("invalid base64 in 'org' URI parameter\n");
815+
pkg_free(hostport.s);
816+
return -1;
817+
}
818+
819+
org_idx = get_uri_param_idx(&org_uri_param, parsed_uri);
820+
if (org_idx < 0) {
821+
pkg_free(hostport.s);
822+
return -1;
823+
}
824+
825+
param_tok.s = parsed_uri->u_name[org_idx].s - 1; /* include leading ';' */
826+
if (parsed_uri->u_val[org_idx].s)
827+
param_tok.len = parsed_uri->u_val[org_idx].s +
828+
parsed_uri->u_val[org_idx].len - parsed_uri->u_name[org_idx].s + 1;
829+
else
830+
param_tok.len = parsed_uri->u_name[org_idx].len + 1;
831+
832+
old_uri = *GET_RURI(msg);
833+
new_uri.len = old_uri.len - param_tok.len;
834+
new_uri.s = pkg_malloc(new_uri.len);
835+
if (!new_uri.s) {
836+
LM_ERR("out of pkg memory\n");
837+
pkg_free(hostport.s);
838+
return -1;
839+
}
840+
841+
begin_len = param_tok.s - old_uri.s;
842+
memcpy(new_uri.s, old_uri.s, begin_len);
843+
end_len = old_uri.len - ((param_tok.s + param_tok.len) - old_uri.s);
844+
if (end_len)
845+
memcpy(new_uri.s + begin_len, param_tok.s + param_tok.len, end_len);
846+
847+
if (set_ruri(msg, &new_uri) < 0) {
848+
pkg_free(new_uri.s);
849+
pkg_free(hostport.s);
850+
LM_ERR("failed to remove 'org' from R-URI\n");
851+
return -1;
852+
}
853+
854+
pkg_free(new_uri.s);
855+
856+
old_uri = *GET_RURI(msg);
857+
if (set_dst_uri(msg, &old_uri) < 0) {
858+
pkg_free(hostport.s);
859+
LM_ERR("failed to set destination URI\n");
860+
return -1;
861+
}
862+
863+
if (rewrite_ruri(msg, &hostport, 0, RW_RURI_HOSTPORT) < 0) {
864+
pkg_free(hostport.s);
865+
LM_ERR("failed to rewrite R-URI host:port\n");
866+
return -1;
867+
}
868+
869+
pkg_free(hostport.s);
870+
return 1;
871+
}
872+
873+
static str fix_nated_contact_flag_names[] =
874+
{
875+
str_init("preserve-uri"), /* FIX_NATED_CONTACT_PRESERVE_URI */
876+
STR_NULL
877+
};
878+
879+
static int fixup_flags_fix_nated_contact(void** param)
880+
{
881+
return fixup_named_flags(param, fix_nated_contact_flag_names, NULL, NULL);
882+
}
883+
746884

747885
/*
748886
* test for occurrence of RFC1918 / RFC6598 IP address in Contact HF

0 commit comments

Comments
 (0)