From b02221cf90bf7021b382e4bdfb61b08cccc2c99d Mon Sep 17 00:00:00 2001 From: Roger Lipscombe Date: Mon, 7 Sep 2015 19:53:43 +0100 Subject: Pass 'raw' options through In Erlang R16B03-1, I've been passing raw options to ssl:listen as follows, and it's been working fine: % The constants are defined elsewhere. LOpts = [{raw, ?IPPROTO_TCP, ?TCP_MAXSEG, <>} | ...], {ok, LSocket} = ssl:listen(0, LOpts) In Erlang 17.3, this fails with {option_not_a_key_value_tuple,{raw,6,2,<<64,2,0,0>>}} I originally reported this in http://erlang.org/pipermail/erlang-questions/2014-October/081226.html I need to pass this particular raw option to ssl:listen, because it needs to be applied when the socket is first opened -- between inet:open and prim_inet:listen -- it cannot be applied later by setopts. This means that it needs to be done by inet_tcp:listen/2 -- well, actually by inet:open/8, but... Otherwise it's racey -- a client could connect between prim_inet:listen and the setopts call. The MSS option is advertised in the SYN,ACK packet, and can't be changed later. --- lib/ssl/src/ssl.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 9f2af73204..19b091df59 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -1169,6 +1169,8 @@ assert_proplist([]) -> assert_proplist([{Key,_} | Rest]) when is_atom(Key) -> assert_proplist(Rest); %% Handle exceptions +assert_proplist([{raw,_,_,_} | Rest]) -> + assert_proplist(Rest); assert_proplist([inet | Rest]) -> assert_proplist(Rest); assert_proplist([inet6 | Rest]) -> -- cgit v1.2.3 From 3dd86e73c17631a1e8c12ae4bed8bd320ae66082 Mon Sep 17 00:00:00 2001 From: Roger Lipscombe Date: Wed, 25 Nov 2015 14:26:38 +0000 Subject: Ensure single 'raw' option is handled correctly Add a test to ensure that a single 'raw' option can be passed to ssl:listen correctly. Note: multiple raw options are (incorrectly) handled by inet:listen_options. See http://erlang.org/pipermail/erlang-questions/2014-March/078371.html --- lib/ssl/test/ssl_basic_SUITE.erl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index ecedb89c23..0712764274 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -96,6 +96,7 @@ options_tests() -> [der_input, misc_ssl_options, ssl_options_not_proplist, + raw_ssl_option, socket_options, invalid_inet_get_option, invalid_inet_get_option_not_list, @@ -311,6 +312,14 @@ init_per_testcase(clear_pem_cache, Config) -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), ct:timetrap({seconds, 20}), Config; +init_per_testcase(raw_ssl_option, Config) -> + ct:timetrap({seconds, 5}), + case os:type() of + {unix,linux} -> + Config; + _ -> + {skip, "Raw options are platform-specific"} + end; init_per_testcase(_TestCase, Config) -> ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), @@ -1135,6 +1144,23 @@ ssl_options_not_proplist(Config) when is_list(Config) -> ssl:connect("twitter.com", 443, [binary, {active, false}, BadOption]). +%%-------------------------------------------------------------------- +raw_ssl_option() -> + [{doc,"Ensure that a single 'raw' option is passed to ssl:listen correctly."}]. + +raw_ssl_option(Config) when is_list(Config) -> + % 'raw' option values are platform-specific; these are the Linux values: + IpProtoTcp = 6, + % Use TCP_KEEPIDLE, because (e.g.) TCP_MAXSEG can't be read back reliably. + TcpKeepIdle = 4, + KeepAliveTimeSecs = 55, + LOptions = [{raw, IpProtoTcp, TcpKeepIdle, <>}], + {ok, LSocket} = ssl:listen(0, LOptions), + % Per http://www.erlang.org/doc/man/inet.html#getopts-2, we have to specify + % exactly which raw option we want, and the size of the buffer. + {ok, [{raw, IpProtoTcp, TcpKeepIdle, <>}]} = ssl:getopts(LSocket, [{raw, IpProtoTcp, TcpKeepIdle, 4}]). + + %%-------------------------------------------------------------------- versions() -> [{doc,"Test API function versions/0"}]. -- cgit v1.2.3