aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2013-02-06 09:02:46 +0100
committerHarald Welte <laforge@gnumonks.org>2013-02-06 09:02:46 +0100
commit7bd1d4ae4fae1924a5b979ece29ab7940dc22207 (patch)
tree7790b7a7e6c53cc97d76174ca0a3fb1505d93046
parent0be74df53e6e310324e43b6b07e85cc32615b87d (diff)
map_masq/imsi_list: bi-directional mapping, also change MO-ForwardSM-Arg
This introduces a second gb_tree of imsi mappings for the inverse direction, in order to mangle MO-ForwardSM-Arg
-rw-r--r--src/imsi_list.erl56
-rw-r--r--src/map_masq.erl17
2 files changed, 56 insertions, 17 deletions
diff --git a/src/imsi_list.erl b/src/imsi_list.erl
index 10dce97..005940b 100644
--- a/src/imsi_list.erl
+++ b/src/imsi_list.erl
@@ -1,7 +1,7 @@
% Maintain a list of IMSIs in a gb_tree and match against it
-% (C) 2012 by Harald Welte <laforge@gnumonks.org>
-% (C) 2012 by On-Waves
+% (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
+% (C) 2012-2013 by On-Waves
%
% All Rights Reserved
%
@@ -35,10 +35,14 @@
-module(imsi_list).
-author('Harald Welte <laforge@gnumonks.org>').
--export([read_file/1, read_list/1, match_imsi/2]).
+-export([read_file/1, read_list/1, match_imsi/2, match_imsi/3]).
+
+-record(state, {forward, reverse}).
lines2tree(Iodev) ->
- lines2tree(Iodev, gb_trees:empty()).
+ S = #state{forward = gb_trees:empty(),
+ reverse = gb_trees:empty()},
+ lines2tree(Iodev, S).
chomp(Line) when is_list(Line) ->
case lists:last(Line) of
@@ -50,12 +54,18 @@ chomp(Line) when is_list(Line) ->
% convert from "12345" to [1,2,3,4,5]
string_num_to_int_list(Line2) ->
- [case string:to_integer([X]) of {Int,[]} -> Int end || X <- Line2].
+ [case string:to_integer([X]) of
+ {Int,[]} -> Int;
+ {error, F} ->
+ error_logger:error_report([{imsi_list_syntax_error,
+ Line2, {error, F}}]),
+ undefined
+ end || X <- Line2].
-lines2tree(Iodev, Tree) ->
+lines2tree(Iodev, State) ->
case file:read_line(Iodev) of
eof ->
- {ok, Tree};
+ {ok, State};
{error, Reason} ->
{error, Reason};
ebadf ->
@@ -67,7 +77,13 @@ lines2tree(Iodev, Tree) ->
[ImsiOldStr, ImsiNewStr] ->
ImsiOld = string_num_to_int_list(ImsiOldStr),
ImsiNew = string_num_to_int_list(ImsiNewStr),
- lines2tree(Iodev, gb_trees:insert(ImsiOld, ImsiNew, Tree));
+ FwNew = gb_trees:insert(ImsiOld, ImsiNew,
+ State#state.forward),
+ RevNew = gb_trees:insert(ImsiNew, ImsiOld,
+ State#state.reverse),
+ lines2tree(Iodev, #state{forward = FwNew,
+ reverse = RevNew});
+ % FIXME: handle empty lines or skip bad lines
_ ->
{error, file_format}
end
@@ -84,15 +100,29 @@ read_file(FileName) ->
end.
read_list(List) when is_list(List) ->
- read_list(List, gb_trees:empty()).
+ S = #state{forward = gb_trees:empty(),
+ reverse = gb_trees:empty()},
+ read_list(List, S).
read_list([], Tree) ->
Tree;
-read_list([{Old, New}|Tail], Tree) ->
- read_list(Tail, gb_trees:enter(Old, New, Tree)).
+read_list([{Old, New}|Tail], State) ->
+ FwNew = gb_trees:insert(Old, New, State#state.forward),
+ RevNew = gb_trees:insert(New, Old, State#state.reverse),
+ read_list(Tail, #state{forward = FwNew, reverse = RevNew}).
+
+match_imsi(State, Imsi) when is_list(Imsi) ->
+ match_imsi(forward, State, Imsi).
-match_imsi(Tree, Imsi) when is_list(Imsi) ->
- case gb_trees:lookup(Imsi, Tree) of
+match_imsi(forward, State, Imsi) when is_list(Imsi) ->
+ case gb_trees:lookup(Imsi, State#state.forward) of
+ {value, ImsiNew} ->
+ {ok, ImsiNew};
+ none ->
+ {error, no_entry}
+ end;
+match_imsi(reverse, State, Imsi) when is_list(Imsi) ->
+ case gb_trees:lookup(Imsi, State#state.reverse) of
{value, ImsiNew} ->
{ok, ImsiNew};
none ->
diff --git a/src/map_masq.erl b/src/map_masq.erl
index 8ab4331..907d1c4 100644
--- a/src/map_masq.erl
+++ b/src/map_masq.erl
@@ -1,7 +1,7 @@
% MAP masquerading application
-% (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
-% (C) 2010-2012 by On-Waves
+% (C) 2010-2013 by Harald Welte <laforge@gnumonks.org>
+% (C) 2010-2013 by On-Waves
%
% All Rights Reserved
%
@@ -143,6 +143,10 @@ patch(From, #'LocationInfoWithLMSI'{'networkNode-Number' = NetNodeNr} = P) ->
NetNodeNrOut = patch_map_isdn_addr(From, NetNodeNr, msc),
P#'LocationInfoWithLMSI'{'networkNode-Number' = NetNodeNrOut};
+% MO-ForwardSM-Arg with optional IMSI
+patch(From, #'MO-ForwardSM-Arg'{imsi = ImsiIn} = P) ->
+ #'MO-ForwardSM-Arg'{imsi = patch_imsi(mo_fw_sm_arg, From, ImsiIn)};
+
% patch the roaming number as it is sent from HLR to G-MSC (SRI Resp)
patch(_From, {roamingNumber, RoamNumTBCD}) ->
RoamNumIn = map_codec:parse_addr_string(RoamNumTBCD),
@@ -504,15 +508,20 @@ generate_rewrite_entry({Name, MscSideInt, StpSideInt}) ->
StpSideList = osmo_util:int2digit_list(StpSideInt),
{Name, MscSideInt, StpSideInt, MscSideList, StpSideList}.
+imsi_direction(sri_sm_res) ->
+ forward;
+imsi_direction(mo_fw_sm_arg) ->
+ reverse.
% check if we need to rewrite the IMSI
-patch_imsi(sri_sm_res, from_msc, ImsiIn) ->
+patch_imsi(MsgType, from_msc, ImsiIn) ->
+ IsForward = imsi_direction(MsgType),
case application:get_env(mgw_nat, imsi_rewrite_tree) of
{ok, ImsiTree} ->
% decode IMSI into list of digits
Imsi = map_codec:parse_map_addr(ImsiIn),
% rewrite prefix, if it matches
- case imsi_list:match_imsi(ImsiTree, Imsi) of
+ case imsi_list:match_imsi(IsForward, ImsiTree, Imsi) of
{ok, NewImsi} ->
map_codec:encode_map_tbcd(NewImsi);
_ ->