aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter')
-rw-r--r--lib/diameter/doc/src/notes.xml223
-rw-r--r--lib/diameter/src/base/diameter_capx.erl9
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl82
3 files changed, 300 insertions, 14 deletions
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index ad61f12b5b..e750b56f1e 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -42,6 +42,229 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 1.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix handling of 5014 (INVALID_AVP_LENGTH) errors.</p>
+ <p>
+ This was in some cases reported as 3009
+ (INVALID_AVP_BITS).</p>
+ <p>
+ Note that the correction is partially implemented in
+ modules generated by diameterc(1): a dictionary file must
+ be recompiled for the correction to apply to any messages
+ it defines.</p>
+ <p>
+ Own Id: OTP-11007</p>
+ </item>
+ <item>
+ <p>
+ Fix faulty capitalization in release notes.</p>
+ <p>
+ Diameter = the protocol.<br/> diameter = the Erlang
+ application.</p>
+ <p>
+ Own Id: OTP-11014</p>
+ </item>
+ <item>
+ <p>
+ Fix watchdog memory leak.</p>
+ <p>
+ Entries were not removed from a service-specific ets
+ table, causing them to be orphaned at connection
+ reestablishment for listening transports, and
+ diameter:remove_transport/2 for both listening and
+ connecting transports.</p>
+ <p>
+ The fault was introduced by OTP-10692 in diameter-1.4.1
+ (R16B).</p>
+ <p>
+ Own Id: OTP-11019 Aux Id: OTP-10692 </p>
+ </item>
+ <item>
+ <p>
+ Fix decode failure on AVP Length &lt; 8.</p>
+ <p>
+ The failure caused the message in question to be
+ discarded.</p>
+ <p>
+ Own Id: OTP-11026</p>
+ </item>
+ <item>
+ <p>
+ Respect Host-IP-Address configuration.</p>
+ <p>
+ Addresses returned from a transport module were always
+ used to populate Host-IP-Address AVP's in an outgoing
+ CER/CEA, which precluded the sending of a VIP address.
+ Transport addresses are now only used if Host-IP-Address
+ is unspecified.</p>
+ <p>
+ Own Id: OTP-11045</p>
+ </item>
+ <item>
+ <p>
+ Fix mkdir race.</p>
+ <p>
+ Install could fail if examples/code and examples/dict
+ were created in parallel. Noticed on FreeBSD.</p>
+ <p>
+ Own Id: OTP-11051</p>
+ </item>
+ <item>
+ <p>
+ Fix recognition of 5001 on mandatory AVP's.</p>
+ <p>
+ An AVP setting the M-bit was not regarded as erroneous if
+ it was defined in the dictionary in question and its
+ container (message or Grouped AVP) had an 'AVP' field.
+ It's now regarded as a 5001 error (AVP_UNSUPPORTED), as
+ in the case that the AVP is not defined.</p>
+ <p>
+ Note that the correction is partially implemented in
+ modules generated by diameterc(1): a dictionary file must
+ be recompiled for the correction to apply to any messages
+ it defines.</p>
+ <p>
+ Own Id: OTP-11087</p>
+ </item>
+ <item>
+ <p>
+ Fix setting of Failed-AVP on handle_request
+ {answer_message, 5xxx} return.</p>
+ <p>
+ Failed-AVP was never in the outgoing answer-message. It
+ is now set with the AVP from the first entry with the
+ specified Result-Code in the errors field of the incoming
+ diameter_packet, if found.</p>
+ <p>
+ Own Id: OTP-11092</p>
+ </item>
+ <item>
+ <p>
+ Fix watchdog function_clause</p>
+ <p>
+ A listening transport on a service that allowed multiple
+ connections to the same peer could result in a
+ function_clause error in module diameter_watchdog. The
+ resulting crash was harmless but unseemly.</p>
+ <p>
+ Thanks to Aleksander Nycz.</p>
+ <p>
+ Own Id: OTP-11115</p>
+ </item>
+ <item>
+ <p>
+ Fix population of Failed-AVP.</p>
+ <p>
+ In cases in which diameter populated this AVP, many
+ values were sent instead of one as suggested by RFC 6733.
+ This was partially corrected by OTP-11007.</p>
+ <p>
+ Own Id: OTP-11127 Aux Id: OTP-11007 </p>
+ </item>
+ <item>
+ <p>
+ Fix list-valued Vendor-Specific-Application-Id config</p>
+ <p>
+ R16B (specifically, OTP-10760) broke the handling of such
+ configuration, resulting in a function clause error if
+ the list was not of length 3, and faulty interpretation
+ of the list's contents otherwise. Only record-valued
+ configuration was properly interpreted.</p>
+ <p>
+ Own Id: OTP-11165</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Allow peer connections to be shared between Erlang nodes
+ for the purpose of sending outgoing requests.</p>
+ <p>
+ A diameter_app(3) pick_peer/4 callback gets a list of
+ remote candidates as argument, allowing a callback on one
+ node to select a transport connection established on
+ another node. The service_opt() share_peers controls the
+ extent to which local connections are shared with remote
+ nodes. The service_opt() use_shared_peers controls the
+ extent to which connections shared from remote nodes are
+ utilized on the local node.</p>
+ <p>
+ Own Id: OTP-9610</p>
+ </item>
+ <item>
+ <p>
+ Allow listening diameter_{tcp,sctp} transports to be
+ configured with remote addresses.</p>
+ <p>
+ Option 'accept' allows remote addresses to be configured
+ as tuples or regular expressions. Remote addresses are
+ matched against the configured values at connection
+ establishment, any non-matching address causing the
+ connection to be aborted.</p>
+ <p>
+ Own Id: OTP-10893</p>
+ </item>
+ <item>
+ <p>
+ Detect more transport_opt() configuration errors at
+ diameter:add_transport/2.</p>
+ <p>
+ Many errors would previously not be detected until
+ transport start, diameter:add_transport/2 returning 'ok'
+ but transport connections failing to be established. An
+ error tuple is now returned.</p>
+ <p>
+ Own Id: OTP-10972</p>
+ </item>
+ <item>
+ <p>
+ Make explicit local address configuration optional in
+ diameter_tcp:start/3.</p>
+ <p>
+ The default address (as determined by gen_tcp) is now
+ used when a local address is not explicitly configured.</p>
+ <p>
+ Own Id: OTP-10986</p>
+ </item>
+ <item>
+ <p>
+ Improve handling of unrecognized service options.</p>
+ <p>
+ Such options were silently ignored by
+ diameter:start_service/2. An error tuple is now returned.</p>
+ <p>
+ Own Id: OTP-11017</p>
+ </item>
+ <item>
+ <p>
+ Don't send default Inband-Security-Id in CER/CEA.</p>
+ <p>
+ RFC 6733 recommends against the use of
+ Inband-Security-Id. Only send a value that differs from
+ the default, NO_INBAND_SECURITY = 0.</p>
+ <p>
+ Own Id: OTP-11050</p>
+ </item>
+ <item>
+ <p>
+ Make spawn options for request processes configurable.</p>
+ <p>
+ Own Id: OTP-11060</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 1.4.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/src/base/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl
index 4b821f5139..1a931a9854 100644
--- a/lib/diameter/src/base/diameter_capx.erl
+++ b/lib/diameter/src/base/diameter_capx.erl
@@ -419,12 +419,13 @@ app_union(#diameter_caps{auth_application_id = U,
vendor_specific_application_id = V}) ->
set_list(U ++ C ++ lists:flatmap(fun vsa_apps/1, V)).
-vsa_apps([_ | [_,_] = Ids]) ->
- lists:append(Ids);
+vsa_apps(Vals)
+ when is_list(Vals) ->
+ lists:flatmap(fun({'Vendor-Id', _}) -> []; ({_, Ids}) -> Ids end, Vals);
vsa_apps(Rec)
when is_tuple(Rec) ->
- [_|T] = tuple_to_list(Rec),
- vsa_apps(T).
+ [_Name, _VendorId | Idss] = tuple_to_list(Rec),
+ lists:append(Idss).
%% It's a configuration error for a locally advertised application not
%% to be represented in Apps. Don't just match on lists:keyfind/3 in
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
index 8c9bb67e61..deabdd720b 100644
--- a/lib/diameter/test/diameter_capx_SUITE.erl
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -27,6 +27,8 @@
-export([suite/0,
all/0,
groups/0,
+ init_per_suite/1,
+ end_per_suite/1,
init_per_group/2,
end_per_group/2,
init_per_testcase/2,
@@ -56,6 +58,11 @@
peer_down/4]).
-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+%% Use only the Vendor-Specific-Application-Id record from the base
+%% include, to test the independence of capabilities configuration
+%% from the different definitions of Vendor-Id in RFC's 3588 and RFC
+%% 6733.
%% ===========================================================================
@@ -69,6 +76,11 @@
-define(REALM, "erlang.org").
-define(HOST(Name), Name ++ "." ++ ?REALM).
+%% Application id's that are never agreed upon at capabilities
+%% exchange. Testcase no_common_application references them in order
+%% to exercise Vendor-Specific-Application-Id handling.
+-define(NOAPPS, [1111, 2222, 3333, 4444]).
+
%% Config for diameter:start_service/2.
-define(SERVICE,
[{'Origin-Realm', ?REALM},
@@ -83,7 +95,10 @@
|| {A,D} <- [{base3588, diameter_gen_base_rfc3588},
{acct3588, diameter_gen_base_accounting},
{base6733, diameter_gen_base_rfc6733},
- {acct6733, diameter_gen_acct_rfc6733}]]]).
+ {acct6733, diameter_gen_acct_rfc6733}]]]
+ ++ [{application, [{dictionary, dict(N)},
+ {module, not_really}]}
+ || N <- ?NOAPPS]).
-define(A, list_to_atom).
-define(L, atom_to_list).
@@ -116,6 +131,16 @@ groups() ->
Tc = lists:flatmap(fun tc/1, tc()),
[{D, [], Tc} || D <- ?DICTS].
+init_per_suite(Config) ->
+ lists:foreach(fun load_dict/1, ?NOAPPS),
+ Config.
+
+end_per_suite(_Config) ->
+ [] = [Mod || N <- ?NOAPPS,
+ Mod <- [dict(N)],
+ false <- [code:delete(Mod)]],
+ ok.
+
%% Generate a unique hostname for each testcase so that watchdogs
%% don't prevent a connection from being brought up immediately.
init_per_testcase(Name, Config) ->
@@ -160,7 +185,7 @@ start(_Config) ->
ok = diameter:start().
%% Ensure that both integer and list-valued vendor id's can be
-%% configured in a 'Vendor-Specific-Application-Id, the arity having
+%% configured in a Vendor-Specific-Application-Id, the arity having
%% changed between RFC 3588 and RFC 6733.
vendor_id(_Config) ->
[] = ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]).
@@ -188,13 +213,13 @@ add_listeners(Config) ->
Acct = [listen(?SERVER,
[{capabilities, [{'Origin-Host', ?HOST(H)},
{'Auth-Application-Id', []}]},
- {applications, [A]},
+ {applications, [A | noapps()]},
{capabilities_cb, [fun server_capx/3, acct]}])
|| {A,H} <- [{acct3588, "acct3588-srv"},
{acct6733, "acct6733-srv"}]],
Base = [listen(?SERVER,
[{capabilities, [{'Origin-Host', ?HOST(H)}]},
- {applications, A},
+ {applications, A ++ noapps()},
{capabilities_cb, [fun server_capx/3, base]}])
|| {A,H} <- [{[base3588, acct3588], "base3588-srv"},
{[base6733, acct6733], "base6733-srv"}]],
@@ -224,15 +249,33 @@ stop(_Config) ->
%% DIAMETER_NO_COMMON_APPLICATION = 5010.
s_no_common_application(Config) ->
- server_closed(Config, fun no_common_application/1, 5010).
+ Vs = [[{'Vendor-Id', 111},
+ {'Auth-Application-Id', [1111]}],
+ #'diameter_base_Vendor-Specific-Application-Id'
+ {'Vendor-Id' = [222],
+ 'Acct-Application-Id' = [2222]}],
+ server_closed(Config,
+ fun(C) -> no_common_application(C,Vs) end,
+ 5010).
c_no_common_application(Config) ->
- client_closed(Config, "acct-srv", fun no_common_application/1, 5010).
-
-no_common_application(Config) ->
+ Vs = [#'diameter_base_Vendor-Specific-Application-Id'
+ {'Vendor-Id' = 333,
+ 'Auth-Application-Id' = [3333]},
+ [{'Vendor-Id', [444]},
+ {'Acct-Application-Id', [4444]}]],
+ client_closed(Config,
+ "acct-srv",
+ fun(C) -> no_common_application(C,Vs) end,
+ 5010).
+
+no_common_application(Config, Vs) ->
[Common, _Acct] = apps(Config),
- connect(Config, acct, [{capabilities, [{'Acct-Application-Id', []}]},
- {applications, [Common]}]).
+ connect(Config,
+ acct,
+ [{capabilities, [{'Acct-Application-Id', []},
+ {'Vendor-Specific-Application-Id', Vs}]},
+ {applications, [Common | noapps()]}]).
%% ====================
%% Ask the base server to speak accounting with an unknown security
@@ -324,6 +367,25 @@ client_reject(Config) ->
%% ===========================================================================
+noapps() ->
+ lists:map(fun dict/1, ?NOAPPS).
+
+dict(N) ->
+ ?A(?L(?MODULE) ++ "_" ++ integer_to_list(N)).
+
+%% Compile and load minimal dictionary modules. These actually have to
+%% exists since diameter will call their id/0 to extract application
+%% id's, failing with app_not_configured if it can't.
+load_dict(N) ->
+ Mod = dict(N),
+ Forms = [{attribute, 1, module, Mod},
+ {attribute, 2, compile, [export_all]},
+ {function, 3, id, 0,
+ [{clause, 4, [], [], [{integer, 4, N}]}]}],
+ {ok, Mod, Bin, []} = compile:forms(Forms, [return]),
+ {module, Mod} = code:load_binary(Mod, Mod, Bin),
+ N = Mod:id().
+
%% server_closed/3
server_closed(Config, F, RC) ->