aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/test/diameter_traffic_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/test/diameter_traffic_SUITE.erl')
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl150
1 files changed, 101 insertions, 49 deletions
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 781ed234cc..38bdf55af8 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -49,9 +49,12 @@
send_unsupported_app/1,
send_error_bit/1,
send_unsupported_version/1,
- send_invalid_avp_bits/1,
+ send_long_avp_length/1,
+ send_short_avp_length/1,
+ send_zero_avp_length/1,
send_invalid_avp_length/1,
send_invalid_reject/1,
+ send_unrecognized_mandatory/1,
send_long/1,
send_nopeer/1,
send_noapp/1,
@@ -268,9 +271,12 @@ tc() ->
send_unsupported_app,
send_error_bit,
send_unsupported_version,
- send_invalid_avp_bits,
+ send_long_avp_length,
+ send_short_avp_length,
+ send_zero_avp_length,
send_invalid_avp_length,
send_invalid_reject,
+ send_unrecognized_mandatory,
send_long,
send_nopeer,
send_noapp,
@@ -405,7 +411,7 @@ send_eval(Config) ->
send_bad_answer(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 2}],
- {error, timeout} = call(Config, Req).
+ {timeout, _} = call(Config, Req).
%% Send an ACR that the server callback answers explicitly with a
%% protocol error.
@@ -416,13 +422,14 @@ send_protocol_error(Config) ->
?answer_message(?TOO_BUSY)
= call(Config, Req).
-%% Send an ASR with an arbitrary AVP and expect success and the same
-%% AVP in the reply.
+%% Send an ASR with an arbitrary non-mandatory AVP and expect success
+%% and the same AVP in the reply.
send_arbitrary(Config) ->
- Req = ['ASR', {'AVP', [#diameter_avp{name = 'Class', value = "XXX"}]}],
+ Req = ['ASR', {'AVP', [#diameter_avp{name = 'Product-Name',
+ value = "XXX"}]}],
['ASA', _SessionId, {'Result-Code', ?SUCCESS} | Avps]
= call(Config, Req),
- {'AVP', [#diameter_avp{name = 'Class',
+ {'AVP', [#diameter_avp{name = 'Product-Name',
value = "XXX"}]}
= lists:last(Avps).
@@ -455,7 +462,7 @@ send_unknown_mandatory(Config) ->
%% Send an STR that the server ignores.
send_noreply(Config) ->
Req = ['STR', {'Termination-Cause', ?BAD_ANSWER}],
- {error, timeout} = call(Config, Req).
+ {timeout, _} = call(Config, Req).
%% Send an unsupported command and expect 3001.
send_unsupported(Config) ->
@@ -481,19 +488,33 @@ send_unsupported_version(Config) ->
['STA', _SessionId, {'Result-Code', ?UNSUPPORTED_VERSION} | _]
= call(Config, Req).
-%% Send a request containing an incorrect AVP length.
-send_invalid_avp_bits(Config) ->
- Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+%% Send a request containing an AVP length > data size.
+send_long_avp_length(Config) ->
+ send_invalid_avp_length(Config).
- ?answer_message(?INVALID_AVP_BITS)
- = call(Config, Req).
+%% Send a request containing an AVP length < data size.
+send_short_avp_length(Config) ->
+ send_invalid_avp_length(Config).
+
+%% Send a request containing an AVP whose advertised length is < 8.
+send_zero_avp_length(Config) ->
+ send_invalid_avp_length(Config).
%% Send a request containing an AVP length that doesn't match the
%% AVP's type.
send_invalid_avp_length(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', _SessionId, {'Result-Code', ?INVALID_AVP_LENGTH} | _]
+ ['STA', _SessionId,
+ {'Result-Code', ?INVALID_AVP_LENGTH},
+ _OriginHost,
+ _OriginRealm,
+ _UserName,
+ _Class,
+ _ErrorMessage,
+ _ErrorReportingHost,
+ {'Failed-AVP', [#'diameter_base_Failed-AVP'{'AVP' = [_]}]}
+ | _]
= call(Config, Req).
%% Send a request containing 5xxx errors that the server rejects with
@@ -504,6 +525,14 @@ send_invalid_reject(Config) ->
?answer_message(?TOO_BUSY)
= call(Config, Req).
+%% Send an STR containing a known AVP, but one that's not allowed and
+%% sets the M-bit.
+send_unrecognized_mandatory(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+
+ ['STA', _SessionId, {'Result-Code', ?AVP_UNSUPPORTED} | _]
+ = call(Config, Req).
+
%% Send something long that will be fragmented by TCP.
send_long(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
@@ -552,7 +581,7 @@ send_all_2(Config) ->
%% Timeout before the server manages an answer.
send_timeout(Config) ->
Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}],
- {error, timeout} = call(Config, Req, [{timeout, 1000}]).
+ {timeout, _} = call(Config, Req, [{timeout, 1000}]).
%% Explicitly answer with an answer-message and ensure that we
%% received the Session-Id.
@@ -560,7 +589,7 @@ send_error(Config) ->
Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_AUTHENTICATE}],
?answer_message(SId, ?TOO_BUSY)
= call(Config, Req),
- undefined /= SId.
+ true = undefined /= SId.
%% Send a request with the detached option and receive it as a message
%% from handle_answer instead.
@@ -568,7 +597,7 @@ send_detach(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Ref = make_ref(),
ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]),
- Ans = receive {Ref, T} -> T after 2000 -> false end,
+ Ans = receive {Ref, T} -> T end,
['STA', _SessionId, {'Result-Code', ?SUCCESS} | _]
= Ans.
@@ -683,7 +712,7 @@ call(Config, Req, Opts) ->
diameter:call(?CLIENT,
dict(Req, Dict0),
msg(Req, ReqEncoding, Dict0),
- [{extra, [Name, Group]} | Opts]).
+ [{extra, [{Name, Group}, now()]} | Opts]).
origin({A,C}) ->
2*codec(A) + container(C);
@@ -767,14 +796,14 @@ peer_down(_SvcName, _Peer, State) ->
%% pick_peer/6-7
-pick_peer(Peers, _, ?CLIENT, _State, Name, Group)
+pick_peer(Peers, _, ?CLIENT, _State, {Name, Group}, _)
when Name /= send_detach ->
find(Group, Peers).
-pick_peer(_Peers, _, ?CLIENT, _State, send_nopeer, _, ?EXTRA) ->
+pick_peer(_Peers, _, ?CLIENT, _State, {send_nopeer, _}, _, ?EXTRA) ->
false;
-pick_peer(Peers, _, ?CLIENT, _State, send_detach, Group, {_,_}) ->
+pick_peer(Peers, _, ?CLIENT, _State, {send_detach, Group}, _, {_,_}) ->
find(Group, Peers).
find(#group{server_encoding = A, server_container = C}, Peers) ->
@@ -789,13 +818,13 @@ id(Id, {Pid, _Caps}) ->
%% prepare_request/5-6
-prepare_request(_Pkt, ?CLIENT, {_Ref, _Caps}, send_discard, _) ->
+prepare_request(_Pkt, ?CLIENT, {_Ref, _Caps}, {send_discard, _}, _) ->
{discard, unprepared};
-prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Name, Group) ->
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, {Name, Group}, _) ->
{send, prepare(Pkt, Caps, Name, Group)}.
-prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, send_detach, Group, _) ->
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, {send_detach, Group}, _, _) ->
{eval_packet, {send, prepare(Pkt, Caps, Group)}, [fun log/2, detach]}.
log(#diameter_packet{bin = Bin} = P, T)
@@ -804,45 +833,63 @@ log(#diameter_packet{bin = Bin} = P, T)
%% prepare/4
-prepare(Pkt, Caps, send_invalid_avp_bits, #group{client_dict0 = Dict0}
- = Group) ->
+prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+ when N == send_long_avp_length;
+ N == send_short_avp_length;
+ N == send_zero_avp_length ->
Req = prepare(Pkt, Caps, Group),
- %% Last AVP in our STR is Termination-Cause of type Unsigned32:
- %% set its length improperly.
+ %% Second last AVP in our STR is Auth-Application-Id of type
+ %% Unsigned32: set AVP Length to a value other than 12 and place
+ %% it last in the message (so as not to mess with Termination-Cause).
#diameter_packet{header = #diameter_header{length = L},
bin = B}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
- Offset = L - 7, %% to AVP Length
- <<H:Offset/binary, 12:24/integer, T:4/binary>> = B,
- E#diameter_packet{bin = <<H/binary, 13:24/integer, T/binary>>};
+ Offset = L - 24, %% to Auth-Application-Id
+ <<H:Offset/binary,
+ Hdr:5/binary, 12:24, Data:4/binary,
+ T:12/binary>>
+ = B,
+ AL = case N of
+ send_long_avp_length -> 13;
+ send_short_avp_length -> 11;
+ send_zero_avp_length -> 0
+ end,
+ E#diameter_packet{bin = <<H/binary,
+ T/binary,
+ Hdr/binary, AL:24, Data/binary>>};
prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
when N == send_invalid_avp_length;
N == send_invalid_reject ->
Req = prepare(Pkt, Caps, Group),
%% Second last AVP in our STR is Auth-Application-Id of type
- %% Unsigned32: Send a value of length 8.
+ %% Unsigned32: send data of length 8.
#diameter_packet{header = #diameter_header{length = L},
bin = B0}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
Offset = L - 7 - 12, %% to AVP Length
- <<H0:Offset/binary, 12:24/integer, T:16/binary>> = B0,
- <<V, L:24/integer, H/binary>> = H0, %% assert
- E#diameter_packet{bin = <<V,
- (L+4):24/integer,
- H/binary,
- 16:24/integer,
- 0:32/integer,
- T/binary>>};
+ <<H0:Offset/binary, 12:24, T:16/binary>> = B0,
+ <<V, L:24, H/binary>> = H0, %% assert
+ E#diameter_packet{bin = <<V, (L+4):24, H/binary, 16:24, 0:32, T/binary>>};
+
+prepare(Pkt, Caps, send_unrecognized_mandatory, #group{client_dict0 = Dict0}
+ = Group) ->
+ Req = prepare(Pkt, Caps, Group),
+ #diameter_packet{bin = <<V, Len:24, T/binary>>}
+ = E
+ = diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
+ {Code, Flags, undefined} = Dict0:avp_header('Proxy-State'),
+ Avp = <<Code:32, Flags, 8:24>>,
+ E#diameter_packet{bin = <<V, (Len+8):24, T/binary, Avp/binary>>};
prepare(Pkt, Caps, send_unsupported, #group{client_dict0 = Dict0} = Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <<H:5/binary, _CmdCode:3/binary, T/binary>>}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
- E#diameter_packet{bin = <<H/binary, 42:24/integer, T/binary>>};
+ E#diameter_packet{bin = <<H/binary, 42:24, T/binary>>};
prepare(Pkt, Caps, send_unsupported_app, #group{client_dict0 = Dict0}
= Group) ->
@@ -850,7 +897,7 @@ prepare(Pkt, Caps, send_unsupported_app, #group{client_dict0 = Dict0}
#diameter_packet{bin = <<H:8/binary, _ApplId:4/binary, T/binary>>}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
- E#diameter_packet{bin = <<H/binary, ?BAD_APP:32/integer, T/binary>>};
+ E#diameter_packet{bin = <<H/binary, ?BAD_APP:32, T/binary>>};
prepare(Pkt, Caps, send_error_bit, Group) ->
#diameter_packet{header = Hdr} = Pkt,
@@ -928,10 +975,10 @@ prepare_retransmit(_Pkt, false, _Peer, _Name, _Group) ->
%% handle_answer/6-7
-handle_answer(Pkt, Req, ?CLIENT, Peer, Name, Group) ->
+handle_answer(Pkt, Req, ?CLIENT, Peer, {Name, Group}, _) ->
answer(Pkt, Req, Peer, Name, Group).
-handle_answer(Pkt, Req, ?CLIENT, Peer, send_detach = Name, Group, X) ->
+handle_answer(Pkt, Req, ?CLIENT, Peer, {send_detach = Name, Group}, _, X) ->
{Pid, Ref} = X,
Pid ! {Ref, answer(Pkt, Req, Peer, Name, Group)}.
@@ -944,7 +991,9 @@ answer(Pkt, Req, _Peer, Name, #group{client_dict0 = Dict0}) ->
[Dict:rec2msg(R) | Vs].
answer(Rec, [_|_], N)
- when N == send_invalid_avp_bits;
+ when N == send_long_avp_length;
+ N == send_short_avp_length;
+ N == send_zero_avp_length;
N == send_invalid_avp_length;
N == send_invalid_reject ->
Rec;
@@ -959,7 +1008,11 @@ app(Req, _, Dict0) ->
%% handle_error/6
-handle_error(Reason, _Req, ?CLIENT, _Peer, _Name, _Group) ->
+handle_error(timeout = Reason, _Req, ?CLIENT, _Peer, _, Time) ->
+ Now = now(),
+ {Reason, {Time, Now, timer:now_diff(Now, Time)}};
+
+handle_error(Reason, _Req, ?CLIENT, _Peer, _, _Time) ->
{error, Reason}.
%% handle_request/3
@@ -1085,7 +1138,6 @@ request(#diameter_base_STR{'Session-Id' = SId},
{'Origin-Host', OH},
{'Origin-Realm', OR}]};
-%% send_error
+%% send_error/send_timeout
request(#diameter_base_RAR{}, _Caps) ->
- receive after 2000 -> ok end,
- {protocol_error, ?TOO_BUSY}.
+ receive after 2000 -> {protocol_error, ?TOO_BUSY} end.