Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 1 | % MAP masquerading application |
| 2 | |
| 3 | % (C) 2010-2011 by Harald Welte <laforge@gnumonks.org> |
| 4 | % (C) 2010-2011 by On-Waves |
| 5 | % |
| 6 | % All Rights Reserved |
| 7 | % |
| 8 | % This program is free software; you can redistribute it and/or modify |
| 9 | % it under the terms of the GNU General Public License as published by |
| 10 | % the Free Software Foundation; either version 2 of the License, or |
| 11 | % (at your option) any later version. |
| 12 | % |
| 13 | % This program is distributed in the hope that it will be useful, |
| 14 | % but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | % GNU General Public License for more details. |
| 17 | % |
| 18 | % You should have received a copy of the GNU General Public License along |
| 19 | % with this program; if not, write to the Free Software Foundation, Inc., |
| 20 | % 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 21 | |
| 22 | |
| 23 | -module(map_masq). |
| 24 | -author('Harald Welte <laforge@gnumonks.org>'). |
| 25 | %-compile(export_all). |
| 26 | |
| 27 | -export([mangle_map/1]). |
| 28 | |
| 29 | -define(PATCH_HLR_NUMBER, [1]). |
| 30 | -define(PATCH_SGSN_NUMBER, [2]). |
| 31 | -define(PATCH_SGSN_ADDRESS, [3]). |
| 32 | -define(PATCH_VMSC_ADDRESS, [4]). |
| 33 | -define(PATCH_GSMSCF_ADDRESS, [5]). |
| 34 | |
| 35 | -include_lib("osmo_map/include/map.hrl"). |
| 36 | |
| 37 | mangle_msisdn(from_stp, _Opcode, AddrIn) -> |
| 38 | {ok, IntPfx} = application:get_env(intern_pfx), |
| 39 | mgw_nat:isup_party_internationalize(AddrIn, IntPfx). |
| 40 | |
Harald Welte | 449a317 | 2011-02-10 15:06:27 +0100 | [diff] [blame^] | 41 | % Someobdy inquires on Routing Info for a MS (from HLR) |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 42 | patch(#'SendRoutingInfoArg'{msisdn = Msisdn} = P) -> |
| 43 | AddrInDec = map_codec:parse_addr_string(Msisdn), |
| 44 | io:format("MSISDN IN = ~p~n", [AddrInDec]), |
| 45 | AddrOutDec = mangle_msisdn(from_stp, 22, AddrInDec), |
| 46 | io:format("MSISDN OUT = ~p~n", [AddrOutDec]), |
| 47 | AddrOutBin = map_codec:encode_addr_string(AddrOutDec), |
| 48 | P#'SendRoutingInfoArg'{msisdn = AddrOutBin}; |
| 49 | |
Harald Welte | 449a317 | 2011-02-10 15:06:27 +0100 | [diff] [blame^] | 50 | % HLR responds with Routing Info for a MS |
| 51 | patch(#'SendRoutingInfoRes'{extendedRoutingInfo = ExtRoutInfo, |
| 52 | 'vmsc-Address' = VmscAddress} = P) -> |
| 53 | P#'SendRoutingInfoRes'{extendedRoutingInfo = patch(ExtRoutInfo), |
| 54 | 'vmsc-Address' = ?PATCH_VMSC_ADDRESS}; |
| 55 | patch(#'CamelRoutingInfo'{gmscCamelSubscriptionInfo = GmscCamelSI} = P) -> |
| 56 | P#'CamelRoutingInfo'{gmscCamelSubscriptionInfo = patch(GmscCamelSI)}; |
| 57 | patch({camelRoutingInfo, CRI}) -> |
| 58 | {camelRoutingInfo, patch(CRI)}; |
| 59 | patch({routingInfo, RI}) -> |
| 60 | {routingInfo, patch(RI)}; |
| 61 | |
| 62 | |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 63 | % patch a UpdateGprsLocationArg and replace SGSN number and SGSN address |
| 64 | % !!! TESTING ONLY !!! |
| 65 | patch(#'UpdateGprsLocationArg'{} = P) -> |
| 66 | P#'UpdateGprsLocationArg'{'sgsn-Number'= ?PATCH_SGSN_NUMBER, |
| 67 | 'sgsn-Address' = ?PATCH_SGSN_ADDRESS}; |
| 68 | |
| 69 | % Some other SGSN is sendingu us a GPRS location update. In the response, |
| 70 | % we indicate teh HLR number, which we need to masquerade |
| 71 | patch(#'UpdateGprsLocationRes'{} = P) -> |
| 72 | P#'UpdateGprsLocationRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}; |
| 73 | |
| 74 | % Some other MSC/VLR is sendingu us a GSM location update. In the response, |
| 75 | % we indicate teh HLR number, which we need to masquerade |
| 76 | patch(#'UpdateLocationRes'{} = P) -> |
| 77 | P#'UpdateLocationRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}; |
| 78 | |
| 79 | % HLR responds to VLR's MAP_RESTORE_REQ (i.e. it has lost information) |
| 80 | patch(#'RestoreDataRes'{} = P) -> |
| 81 | P#'RestoreDataRes'{'hlr-Number' = ?PATCH_HLR_NUMBER}; |
| 82 | |
| 83 | % HLR sends subscriber data to VLR/SGSN, including CAMEL info |
| 84 | patch(#'InsertSubscriberDataArg'{'vlrCamelSubscriptionInfo'=VlrCamel, |
| 85 | 'sgsn-CAMEL-SubscriptionInfo'=SgsnCamel} = Arg) -> |
| 86 | Arg#'InsertSubscriberDataArg'{'vlrCamelSubscriptionInfo'=patch(VlrCamel), |
| 87 | 'sgsn-CAMEL-SubscriptionInfo'=patch(SgsnCamel)}; |
| 88 | |
| 89 | % HLR sends subscriber data to gsmSCF |
| 90 | patch(#'AnyTimeSubscriptionInterrogationRes'{'camel-SubscriptionInfo'=Csi} = P) -> |
| 91 | P#'AnyTimeSubscriptionInterrogationRes'{'camel-SubscriptionInfo'=patch(Csi)}; |
| 92 | |
| 93 | patch(asn1_NOVALUE) -> |
| 94 | asn1_NOVALUE; |
| 95 | |
| 96 | % CAMEL related parsing |
| 97 | |
Harald Welte | 449a317 | 2011-02-10 15:06:27 +0100 | [diff] [blame^] | 98 | % this is part of the SRI Response (HLR->GMSC) |
| 99 | patch(#'GmscCamelSubscriptionInfo'{'o-CSI'=Ocsi, 't-CSI'=Tcsi, |
| 100 | 'd-csi'=Dcsi} = P) -> |
| 101 | P#'GmscCamelSubscriptionInfo'{'o-CSI'=patch(Ocsi), |
| 102 | 't-CSI'=patch(Tcsi), |
| 103 | 'd-csi'=patch(Dcsi)}; |
| 104 | |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 105 | % this is part of the InsertSubscriberData HLR -> VLR |
| 106 | patch(#'VlrCamelSubscriptionInfo'{'o-CSI'=Ocsi, 'mo-sms-CSI'=MoSmsCsi, |
| 107 | 'mt-sms-CSI'=MtSmsCsi, 'ss-CSI'=SsCsi} = P) -> |
| 108 | P#'VlrCamelSubscriptionInfo'{'o-CSI'=patch(Ocsi), |
| 109 | 'mo-sms-CSI'=patch(MoSmsCsi), |
| 110 | 'mt-sms-CSI'=patch(MtSmsCsi), |
| 111 | 'ss-CSI'=patch(SsCsi)}; |
| 112 | |
| 113 | % this is part of the InsertSubscriberData HLR -> SGSN |
| 114 | patch(#'SGSN-CAMEL-SubscriptionInfo'{'gprs-CSI'=GprsCsi, |
| 115 | 'mo-sms-CSI'=MoSmsCsi, |
| 116 | 'mt-sms-CSI'=MtSmsCsi} = P) -> |
| 117 | P#'SGSN-CAMEL-SubscriptionInfo'{'gprs-CSI'=patch(GprsCsi), |
| 118 | 'mo-sms-CSI'=patch(MoSmsCsi), |
| 119 | 'mt-sms-CSI'=patch(MtSmsCsi)}; |
| 120 | |
| 121 | % this is part of the Anytime Subscription Interrogation Result HLR->gsmSCF |
| 122 | patch(#'CAMEL-SubscriptionInfo'{'o-CSI'=Ocsi, |
| 123 | 'd-CSI'=Dcsi, |
| 124 | 't-CSI'=Tcsi, |
| 125 | 'vt-CSI'=Vtcsi, |
| 126 | %'tif-CSI'=Tifcsi, |
| 127 | 'gprs-CSI'=GprsCsi, |
| 128 | 'mo-sms-CSI'=MoSmsCsi, |
| 129 | 'ss-CSI'=SsCsi, |
| 130 | 'm-CSI'=Mcsi, |
| 131 | 'mt-sms-CSI'=MtSmsCsi, |
| 132 | 'mg-csi'=MgCsi, |
| 133 | 'o-IM-CSI'=OimCsi, |
| 134 | 'd-IM-CSI'=DimCsi, |
| 135 | 'vt-IM-CSI'=VtImCsi} = P) -> |
| 136 | P#'CAMEL-SubscriptionInfo'{'o-CSI'=patch(Ocsi), |
| 137 | 'd-CSI'=patch(Dcsi), |
| 138 | 't-CSI'=patch(Tcsi), |
| 139 | 'vt-CSI'=patch(Vtcsi), |
| 140 | 'gprs-CSI'=patch(GprsCsi), |
| 141 | 'mo-sms-CSI'=patch(MoSmsCsi), |
| 142 | 'ss-CSI'=patch(SsCsi), |
| 143 | 'm-CSI'=patch(Mcsi), |
| 144 | 'mt-sms-CSI'=patch(MtSmsCsi), |
| 145 | 'mg-csi'=patch(MgCsi), |
| 146 | 'o-IM-CSI'=patch(OimCsi), |
| 147 | 'd-IM-CSI'=patch(DimCsi), |
| 148 | 'vt-IM-CSI'=patch(VtImCsi)}; |
| 149 | |
| 150 | patch(#'T-CSI'{'t-BcsmCamelTDPDataList'=TdpList} = P) -> |
| 151 | P#'T-CSI'{'t-BcsmCamelTDPDataList'=patch_tBcsmCamelTDPDataList(TdpList)}; |
| 152 | patch(#'M-CSI'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
| 153 | P#'M-CSI'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 154 | patch(#'MG-CSI'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
| 155 | P#'MG-CSI'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 156 | patch(#'O-CSI'{'o-BcsmCamelTDPDataList'=TdpList} = P) -> |
| 157 | P#'O-CSI'{'o-BcsmCamelTDPDataList'=patch_oBcsmCamelTDPDataList(TdpList)}; |
| 158 | patch(#'D-CSI'{'dp-AnalysedInfoCriteriaList'=List} = P) -> |
| 159 | P#'D-CSI'{'dp-AnalysedInfoCriteriaList'=patch_AnInfoCritList(List)}; |
| 160 | patch(#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=TdpList} = P) -> |
| 161 | P#'SMS-CSI'{'sms-CAMEL-TDP-DataList'=patch_SmsCamelTDPDataList(TdpList)}; |
| 162 | patch(#'SS-CSI'{'ss-CamelData'=Sscd} = P) -> |
| 163 | P#'SS-CSI'{'ss-CamelData'=patch(Sscd)}; |
| 164 | patch(#'GPRS-CSI'{'gprs-CamelTDPDataList'=TdpList} = P) -> |
| 165 | P#'GPRS-CSI'{'gprs-CamelTDPDataList'=patch_GprsCamelTDPDataList(TdpList)}; |
| 166 | patch(#'SS-CamelData'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
| 167 | P#'SS-CamelData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 168 | patch(#'O-BcsmCamelTDPData'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
| 169 | P#'O-BcsmCamelTDPData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 170 | patch(#'SMS-CAMEL-TDP-Data'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
| 171 | P#'SMS-CAMEL-TDP-Data'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 172 | patch(#'GPRS-CamelTDPData'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
| 173 | P#'GPRS-CamelTDPData'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 174 | patch(#'DP-AnalysedInfoCriterium'{'gsmSCF-Address'=GsmScfAddr} = P) -> |
Harald Welte | c752362 | 2011-02-10 14:42:31 +0100 | [diff] [blame] | 175 | P#'DP-AnalysedInfoCriterium'{'gsmSCF-Address'=?PATCH_GSMSCF_ADDRESS}; |
| 176 | patch(Default) -> |
| 177 | Default. |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 178 | |
| 179 | patch_oBcsmCamelTDPDataList(List) -> |
| 180 | % we reverse the origianl list, as the tail recursive _acc function |
| 181 | % will invert the order of components again |
| 182 | patch_oBcsmCamelTDPDataList_acc(lists:reverse(List), []). |
| 183 | patch_oBcsmCamelTDPDataList_acc([], NewList) -> NewList; |
| 184 | patch_oBcsmCamelTDPDataList_acc([TdpData|Tail], NewList) -> |
| 185 | NewTdpData = patch(TdpData#'O-BcsmCamelTDPData'{}), |
| 186 | patch_oBcsmCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). |
| 187 | |
| 188 | patch_tBcsmCamelTDPDataList(List) -> |
| 189 | % we reverse the origianl list, as the tail recursive _acc function |
| 190 | % will invert the order of components again |
| 191 | patch_tBcsmCamelTDPDataList_acc(lists:reverse(List), []). |
| 192 | patch_tBcsmCamelTDPDataList_acc([], NewList) -> NewList; |
| 193 | patch_tBcsmCamelTDPDataList_acc([TdpData|Tail], NewList) -> |
| 194 | NewTdpData = patch(TdpData#'T-BcsmCamelTDPData'{}), |
| 195 | patch_tBcsmCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). |
| 196 | |
| 197 | patch_AnInfoCritList(List) -> |
| 198 | % we reverse the origianl list, as the tail recursive _acc function |
| 199 | % will invert the order of components again |
| 200 | patch_AnInfoCritList_acc(lists:reverse(List), []). |
| 201 | patch_AnInfoCritList_acc([], NewList) -> NewList; |
| 202 | patch_AnInfoCritList_acc([Crit|Tail], NewList) -> |
| 203 | NewCrit = patch(Crit#'DP-AnalysedInfoCriterium'{}), |
| 204 | patch_AnInfoCritList_acc(Tail, [NewCrit|NewList]). |
| 205 | |
| 206 | patch_GprsCamelTDPDataList(List) -> |
| 207 | % we reverse the origianl list, as the tail recursive _acc function |
| 208 | % will invert the order of components again |
| 209 | patch_GprsCamelTDPDataList_acc(lists:reverse(List), []). |
| 210 | patch_GprsCamelTDPDataList_acc([], NewList) -> NewList; |
| 211 | patch_GprsCamelTDPDataList_acc([TdpData|Tail], NewList) -> |
| 212 | NewTdpData = patch(TdpData#'GPRS-CamelTDPData'{}), |
| 213 | patch_GprsCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). |
| 214 | |
| 215 | patch_SmsCamelTDPDataList(List) -> |
| 216 | % we reverse the origianl list, as the tail recursive _acc function |
| 217 | % will invert the order of components again |
| 218 | patch_SmsCamelTDPDataList_acc(lists:reverse(List), []). |
| 219 | patch_SmsCamelTDPDataList_acc([], NewList) -> NewList; |
| 220 | patch_SmsCamelTDPDataList_acc([TdpData|Tail], NewList) -> |
| 221 | NewTdpData = patch(TdpData#'SMS-CAMEL-TDP-Data'{}), |
| 222 | patch_GprsCamelTDPDataList_acc(Tail, [NewTdpData|NewList]). |
| 223 | |
| 224 | |
| 225 | |
| 226 | % process the Argument of a particular MAP invocation |
| 227 | process_component_arg(OpCode, Arg) -> |
| 228 | case Arg of |
| 229 | asn1_NOVALUE -> Arg; |
| 230 | _ -> patch(Arg) |
| 231 | end. |
| 232 | |
| 233 | % recurse over all components |
| 234 | handle_tcap_components(List) -> |
| 235 | % we reverse the origianl list, as the tail recursive _acc function |
| 236 | % will invert the order of components again |
| 237 | handle_tcap_components_acc(lists:reverse(List), []). |
| 238 | handle_tcap_components_acc([], NewComponents) -> NewComponents; |
| 239 | handle_tcap_components_acc([Component|Tail], NewComponents) -> |
| 240 | case Component of |
| 241 | {basicROS, {Primitive, Body}} -> |
| 242 | io:format("handle component ~p primitive ~n", [Component]), |
| 243 | case Body of |
| 244 | % BEGIN |
| 245 | #'MapSpecificPDUs_begin_components_SEQOF_basicROS_invoke'{opcode={local, OpCode}, |
| 246 | argument=Arg} -> |
| 247 | NewArg = process_component_arg(OpCode, Arg), |
| 248 | NewBody = Body#'MapSpecificPDUs_begin_components_SEQOF_basicROS_invoke'{argument=NewArg}; |
| 249 | #'MapSpecificPDUs_begin_components_SEQOF_basicROS_returnResult'{result=#'MapSpecificPDUs_begin_components_SEQOF_basicROS_returnResult_result'{opcode={local, OpCode}, result=Arg}} -> |
| 250 | NewArg = process_component_arg(OpCode, Arg), |
| 251 | NewBody = Body#'MapSpecificPDUs_begin_components_SEQOF_basicROS_returnResult'{result=#'MapSpecificPDUs_begin_components_SEQOF_basicROS_returnResult_result'{result=NewArg}}; |
| 252 | #'MapSpecificPDUs_begin_components_SEQOF_returnResultNotLast'{result=#'MapSpecificPDUs_begin_components_SEQOF_returnResultNotLast_result'{opcode={local, OpCode}, result=Arg}} -> |
| 253 | NewArg = process_component_arg(OpCode, Arg), |
| 254 | NewBody = Body#'MapSpecificPDUs_begin_components_SEQOF_returnResultNotLast'{result=#'MapSpecificPDUs_begin_components_SEQOF_returnResultNotLast_result'{result=NewArg}}; |
| 255 | % END |
| 256 | #'MapSpecificPDUs_end_components_SEQOF_basicROS_invoke'{opcode={local, OpCode}, |
| 257 | argument=Arg} -> |
| 258 | NewArg = process_component_arg(OpCode, Arg), |
| 259 | NewBody = Body#'MapSpecificPDUs_end_components_SEQOF_basicROS_invoke'{argument=NewArg}; |
| 260 | #'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult'{result=#'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result'{opcode={local, OpCode}, result=Arg}} -> |
| 261 | NewArg = process_component_arg(OpCode, Arg), |
| 262 | NewBody = Body#'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult'{result=#'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result'{result=NewArg}}; |
| 263 | #'MapSpecificPDUs_end_components_SEQOF_returnResultNotLast'{result=#'MapSpecificPDUs_end_components_SEQOF_returnResultNotLast_result'{opcode={local, OpCode}, result=Arg}} -> |
| 264 | NewArg = process_component_arg(OpCode, Arg), |
| 265 | NewBody = Body#'MapSpecificPDUs_end_components_SEQOF_returnResultNotLast'{result=#'MapSpecificPDUs_end_components_SEQOF_returnResultNotLast_result'{result=NewArg}}; |
| 266 | % CONTINUE |
| 267 | #'MapSpecificPDUs_continue_components_SEQOF_basicROS_invoke'{opcode={local, OpCode}, |
| 268 | argument=Arg} -> |
| 269 | NewArg = process_component_arg(OpCode, Arg), |
| 270 | NewBody = Body#'MapSpecificPDUs_continue_components_SEQOF_basicROS_invoke'{argument=NewArg}; |
| 271 | #'MapSpecificPDUs_continue_components_SEQOF_basicROS_returnResult'{result=#'MapSpecificPDUs_continue_components_SEQOF_basicROS_returnResult_result'{opcode={local, OpCode}, result=Arg}} -> |
| 272 | NewArg = process_component_arg(OpCode, Arg), |
| 273 | NewBody = Body#'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult'{result=#'MapSpecificPDUs_end_components_SEQOF_basicROS_returnResult_result'{result=NewArg}}; |
| 274 | #'MapSpecificPDUs_continue_components_SEQOF_returnResultNotLast'{result=#'MapSpecificPDUs_continue_components_SEQOF_returnResultNotLast_result'{opcode={local, OpCode}, result=Arg}} -> |
| 275 | NewArg = process_component_arg(OpCode, Arg), |
| 276 | NewBody = Body#'MapSpecificPDUs_continue_components_SEQOF_returnResultNotLast'{result=#'MapSpecificPDUs_continue_components_SEQOF_returnResultNotLast_result'{result=NewArg}}; |
| 277 | _ -> |
| 278 | NewBody = Body |
| 279 | end, |
| 280 | %NewBody = setelement(5, Body, NewArg) |
| 281 | NewComponent = {basicROS, {Primitive, NewBody}}; |
| 282 | _ -> |
| 283 | NewComponent = Component |
| 284 | end, |
| 285 | io:format("=> modified component ~p~n", [NewComponent]), |
| 286 | handle_tcap_components_acc(Tail, [NewComponent|NewComponents]). |
| 287 | |
| 288 | |
Harald Welte | 9bc2e4a | 2011-02-10 12:40:31 +0100 | [diff] [blame] | 289 | % Erlang asn1rt has this strange property that all incoming EXTERNAL types are |
| 290 | % converted from the 1990 version into the 1994 version. The latter does not |
| 291 | % preserve the encoding (octet string, single ASN1 type, ...). During encoding, |
| 292 | % it then uses the OCTTET-STRING encoding, which is different from the MAP |
| 293 | % customary single-ASN1-type format. |
Harald Welte | c506fe5 | 2011-02-10 13:09:44 +0100 | [diff] [blame] | 294 | asn1_EXTERNAL1994_fixup({'EXTERNAL', DirRef, IndRef, Data}) when is_list(Data);is_binary(Data) -> |
Harald Welte | 9bc2e4a | 2011-02-10 12:40:31 +0100 | [diff] [blame] | 295 | % our trick is as follows: we simply convert back to 1990 format, and explicitly |
| 296 | % set the single-ASN1-type encoding. asn1rt:s 'enc_EXTERNAL'() will detect this |
| 297 | #'EXTERNAL'{'direct-reference' = DirRef, 'indirect-reference' = IndRef, |
| 298 | 'encoding' = {'single-ASN1-type', Data}}; |
| 299 | asn1_EXTERNAL1994_fixup(Foo) -> |
| 300 | Foo. |
| 301 | |
| 302 | |
| 303 | handle_tcap_dialogue(Foo = {'EXTERNAL', DirRef, IndRef, Data}) -> |
| 304 | asn1_EXTERNAL1994_fixup(Foo); |
| 305 | handle_tcap_dialogue(Foo) -> |
| 306 | Foo. |
| 307 | |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 308 | |
| 309 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 310 | % Actual mangling of the decoded MAP messages |
| 311 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 312 | mangle_map({Type, TcapMsgDec}) -> |
| 313 | case {Type, TcapMsgDec} of |
| 314 | {'unidirectional', #'MapSpecificPDUs_unidirectional'{dialoguePortion=Dialg, |
| 315 | components=Components}} -> |
Harald Welte | 9bc2e4a | 2011-02-10 12:40:31 +0100 | [diff] [blame] | 316 | NewDialg = handle_tcap_dialogue(Dialg), |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 317 | NewComponents = handle_tcap_components(Components), |
Harald Welte | 9bc2e4a | 2011-02-10 12:40:31 +0100 | [diff] [blame] | 318 | NewTcapMsgDec = TcapMsgDec#'MapSpecificPDUs_unidirectional'{dialoguePortion=NewDialg, components=NewComponents}; |
Harald Welte | 29c5f40 | 2011-02-10 13:24:49 +0100 | [diff] [blame] | 319 | {'begin', #'MapSpecificPDUs_begin'{dialoguePortion=Dialg, components=Components}} -> |
| 320 | NewDialg = handle_tcap_dialogue(Dialg), |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 321 | NewComponents = handle_tcap_components(Components), |
Harald Welte | 29c5f40 | 2011-02-10 13:24:49 +0100 | [diff] [blame] | 322 | NewTcapMsgDec = TcapMsgDec#'MapSpecificPDUs_begin'{dialoguePortion=NewDialg, components=NewComponents}; |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 323 | {'continue', #'MapSpecificPDUs_continue'{dialoguePortion=Dialg, components=Components}} -> |
Harald Welte | 9bc2e4a | 2011-02-10 12:40:31 +0100 | [diff] [blame] | 324 | NewDialg = handle_tcap_dialogue(Dialg), |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 325 | NewComponents = handle_tcap_components(Components), |
Harald Welte | 9bc2e4a | 2011-02-10 12:40:31 +0100 | [diff] [blame] | 326 | NewTcapMsgDec = TcapMsgDec#'MapSpecificPDUs_continue'{dialoguePortion=NewDialg, components=NewComponents}; |
Harald Welte | 29c5f40 | 2011-02-10 13:24:49 +0100 | [diff] [blame] | 327 | {'end', #'MapSpecificPDUs_end'{dialoguePortion=Dialg, components=Components}} -> |
| 328 | NewDialg = handle_tcap_dialogue(Dialg), |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 329 | NewComponents = handle_tcap_components(Components), |
Harald Welte | 29c5f40 | 2011-02-10 13:24:49 +0100 | [diff] [blame] | 330 | NewTcapMsgDec = TcapMsgDec#'MapSpecificPDUs_end'{dialoguePortion=NewDialg, components=NewComponents}; |
| 331 | %{_, #'Abort'{reason=Reason} -> |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 332 | _ -> |
| 333 | NewTcapMsgDec = TcapMsgDec |
| 334 | end, |
Harald Welte | 29c5f40 | 2011-02-10 13:24:49 +0100 | [diff] [blame] | 335 | io:format("new TcapMsgDec (Type=~p) ~p~n", [Type, NewTcapMsgDec]), |
Harald Welte | a68d96e | 2011-02-10 09:49:46 +0100 | [diff] [blame] | 336 | {Type, NewTcapMsgDec}. |
| 337 | |