@@ -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
114116static int fixup_flags_uac_test (void * * param );
115117static int fixup_flags_sdp (void * * param );
118+ static int fixup_flags_fix_nated_contact (void * * param );
116119
117120static 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 );
119123static int fix_nated_sdp_f (struct sip_msg * msg , void * flags , str * ip ,
120124 str * new_sdp_lines );
121125static int fix_nated_register_f (struct sip_msg * , char * , char * );
@@ -222,8 +226,12 @@ unsigned int *natping_state=0;
222226
223227static 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 */
632640static 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