diff options
author | Anders Svensson <[email protected]> | 2015-03-21 10:56:28 +0100 |
---|---|---|
committer | Anders Svensson <[email protected]> | 2015-03-23 13:15:29 +0100 |
commit | 5228b6e5e3906a7a26e2e730b9f0213844e967a8 (patch) | |
tree | bc7b5523cd76a0fe0ba3713ca1ddf4b89783aaad | |
parent | 7d05e55951b4f3fc4af0febb965d3075e5ddf324 (diff) | |
download | otp-5228b6e5e3906a7a26e2e730b9f0213844e967a8.tar.gz otp-5228b6e5e3906a7a26e2e730b9f0213844e967a8.tar.bz2 otp-5228b6e5e3906a7a26e2e730b9f0213844e967a8.zip |
Be lenient with errors in incoming DPR
To avoid having the peer interpret the error as meaning the connection
shouldn't be closed, which probably does more harm than ignoring
syntactic errors in the DPR.
Note that RFC 6733 says this about incoming DPR, in 5.4 Disconnecting
Peer Connections:
Upon receipt of the message, the Disconnect-Peer-Answer message is
returned, which SHOULD contain an error if messages have recently been
forwarded, and are likely in flight, which would otherwise cause a race
condition.
The race here is presumably between answers to forwarded requests and
the outgoing DPA, but we have no handling for this: whether or not there
are pending answers is irrelevant to how DPR is answered. It's
questionable that a peer should be able to prevent disconnection in any
case: it has to be the node sending DPR that decides if it's approriate,
and the peer should take it as an indication of what's coming.
Incoming DPA is already treated leniently: the only error that's not
ignored is mismatching End-to-End and Hop-by-Hop Identifiers, since
there's no distinguishing an erroneous value from an unsolicited DPA.
This mismatch could also be ignored, which is the case for DWA for
example, but this problem is already dealt with by dpa_timeout, which
causes a connection to be closed even when the expected DPA isn't
received.
-rw-r--r-- | lib/diameter/src/base/diameter_peer_fsm.erl | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index 9ff6845ab7..8bfdb3ae39 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -642,7 +642,9 @@ rcv('DPA' = N, diameter_peer:close(TPid), {stop, N}; -%% Ignore anything else, an unsolicited DPA in particular. +%% Ignore anything else, an unsolicited DPA in particular. Note that +%% dpa_timeout deals with the case in which the peer sends the wrong +%% identifiers in DPA. rcv(N, #diameter_packet{header = H}, _) when N == 'CER'; N == 'CEA'; @@ -820,7 +822,7 @@ build_answer(Type, errors = Es} = Pkt, S) -> - {RC, FailedAVP} = result_code(H, Es), + {RC, FailedAVP} = result_code(Type, H, Es), {answer(Type, RC, FailedAVP, S), post(Type, RC, Pkt, S)}. inband_security([]) -> @@ -890,6 +892,19 @@ set(['answer-message' | _] = Ans, FailedAvp) -> set([_|_] = Ans, FailedAvp) -> Ans ++ FailedAvp. +%% result_code/3 + +%% Be lenient with errors in DPR since there's no reason to be +%% otherwise. Rejecting may cause the peer to missinterpret the error +%% as meaning that the connection should not be closed, which may well +%% lead to more problems than any errors in the DPR. + +result_code('DPR', _, _) -> + {2001, []}; + +result_code('CER', H, Es) -> + result_code(H, Es). + %% result_code/2 result_code(#diameter_header{is_error = true}, _) -> |