From eca2411eb67461bf3cda66d0f981b47698ab99f3 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Wed, 25 Aug 2010 14:43:49 +0200
Subject: Fill in sinfo_assoc_id in struct sctp_sndrcvinfo for getopt()

The assoc_id field was uninitialized causing random answers.
---
 erts/emulator/drivers/common/inet_drv.c |   4 ++++
 erts/preloaded/ebin/prim_inet.beam      | Bin 57272 -> 57280 bytes
 erts/preloaded/src/prim_inet.erl        |   2 +-
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 059288d1cb..10cd140cf4 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -6193,6 +6193,10 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen,
 	    struct       sctp_sndrcvinfo sri;
 	    unsigned int sz  = sizeof(sri);
 	    
+	    if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL);
+	    sri.sinfo_assoc_id = GET_ASSOC_ID(buf);
+	    buf += ASSOC_ID_LEN;
+	    buflen -= ASSOC_ID_LEN;
 	    if (sock_getopt(desc->s, IPPROTO_SCTP, SCTP_DEFAULT_SEND_PARAM,
 			    &sri, &sz) < 0) continue;
 	    /* Fill in the response: */
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index ac336c1b2d..71f6643368 100644
Binary files a/erts/preloaded/ebin/prim_inet.beam and b/erts/preloaded/ebin/prim_inet.beam differ
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 0feb591efb..015c693888 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -1206,7 +1206,7 @@ type_opt_1(sctp_default_send_param) ->
 	timetolive        = [uint32,0],
 	tsn               = [],
 	cumtsn            = [],
-	assoc_id          = [sctp_assoc_id,0]}}];
+	assoc_id          = [[sctp_assoc_id,0]]}}];
 %% for SCTP_OPT_EVENTS
 type_opt_1(sctp_events) ->
     [{record,#sctp_event_subscribe{
-- 
cgit v1.2.3


From eaf1d4c5850ee84427d70e3df42fe777d82249c2 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Wed, 25 Aug 2010 18:03:09 +0200
Subject: Keep default #sctp_sndrcvinfo{} fields on gen_sctp:send/4

---
 lib/kernel/src/gen_sctp.erl        |   8 +-
 lib/kernel/src/inet6_sctp.erl      |  21 ++++-
 lib/kernel/src/inet_sctp.erl       |  21 ++++-
 lib/kernel/test/gen_sctp_SUITE.erl | 158 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 196 insertions(+), 12 deletions(-)

diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 5a31e3976f..a1542ab507 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -166,18 +166,14 @@ send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data)
   when is_port(S), is_integer(Stream) ->
     case inet_db:lookup_socket(S) of
 	{ok,Mod} ->
-	    Mod:sendmsg(S, #sctp_sndrcvinfo{
-			  stream   = Stream,
-			  assoc_id = AssocId}, Data);
+	    Mod:send(S, AssocId, Stream, Data);
 	Error -> Error
     end;
 send(S, AssocId, Stream, Data)
   when is_port(S), is_integer(AssocId), is_integer(Stream) ->
     case inet_db:lookup_socket(S) of
 	{ok,Mod} ->
-	    Mod:sendmsg(S, #sctp_sndrcvinfo{
-			  stream   = Stream,
-			  assoc_id = AssocId}, Data);
+	    Mod:send(S, AssocId, Stream, Data);
 	Error -> Error
     end;
 send(S, AssocChange, Stream, Data) ->
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index 5c49c4fec3..6534af7c52 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_sctp.erl
@@ -32,7 +32,7 @@
 
 -define(FAMILY, inet6).
 -export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,recv/2]).
+-export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
 
 
 
@@ -71,5 +71,24 @@ connect(S, Addr, Port, Opts, Timer) ->
 sendmsg(S, SRI, Data) ->
     prim_inet:sendmsg(S, SRI, Data).
 
+send(S, AssocId, Stream, Data) ->
+    case prim_inet:getopts(
+	   S,
+	   [{sctp_default_send_param,#sctp_sndrcvinfo{assoc_id=AssocId}}]) of
+	{ok,
+	 [{sctp_default_send_param,
+	   #sctp_sndrcvinfo{
+	     flags=Flags, context=Context, ppid=PPID, timetolive=TTL}}]} ->
+	    prim_inet:sendmsg(
+	      S,
+	      #sctp_sndrcvinfo{
+		flags=Flags, context=Context, ppid=PPID, timetolive=TTL,
+		assoc_id=AssocId, stream=Stream},
+	      Data);
+	_ ->
+	    prim_inet:sendmsg(
+	      S, #sctp_sndrcvinfo{assoc_id=AssocId, stream=Stream}, Data)
+    end.
+
 recv(S, Timeout) ->
     prim_inet:recvfrom(S, 0, Timeout).
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index 795bf83807..de74b573bd 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -31,7 +31,7 @@
 
 -define(FAMILY, inet).
 -export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,recv/2]).
+-export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
 
 
 
@@ -141,5 +141,24 @@ connect_get_assoc(S, Addr, Port, Active, Timer) ->
 sendmsg(S, SRI, Data) ->
     prim_inet:sendmsg(S, SRI, Data).
 
+send(S, AssocId, Stream, Data) ->
+    case prim_inet:getopts(
+	   S,
+	   [{sctp_default_send_param,#sctp_sndrcvinfo{assoc_id=AssocId}}]) of
+	{ok,
+	 [{sctp_default_send_param,
+	   #sctp_sndrcvinfo{
+	     flags=Flags, context=Context, ppid=PPID, timetolive=TTL}}]} ->
+	    prim_inet:sendmsg(
+	      S,
+	      #sctp_sndrcvinfo{
+		flags=Flags, context=Context, ppid=PPID, timetolive=TTL,
+		assoc_id=AssocId, stream=Stream},
+	      Data);
+	_ ->
+	    prim_inet:sendmsg(
+	      S, #sctp_sndrcvinfo{assoc_id=AssocId, stream=Stream}, Data)
+    end.
+
 recv(S, Timeout) ->
     prim_inet:recvfrom(S, 0, Timeout).
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index fad8c7398b..72f1436415 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -23,12 +23,16 @@
 
 %%-compile(export_all).
 
--export([all/1,init_per_testcase/2,fin_per_testcase/2,
-	 basic/1,api_open_close/1,api_listen/1,api_connect_init/1,
-	 xfer_min/1,xfer_active/1]).
+-export([all/1,init_per_testcase/2,fin_per_testcase/2]).
+-export(
+   [basic/1,
+    api_open_close/1,api_listen/1,api_connect_init/1,
+    xfer_min/1,xfer_active/1,def_sndrcvinfo/1]).
 
 all(suite) ->
-    [basic,api_open_close,api_listen,api_connect_init,xfer_min,xfer_active].
+    [basic,
+     api_open_close,api_listen,api_connect_init,
+     xfer_min,xfer_active,def_sndrcvinfo].
 
 init_per_testcase(_Func, Config) ->
     Dog = test_server:timetrap(test_server:seconds(15)),
@@ -39,6 +43,10 @@ fin_per_testcase(_Func, Config) ->
 
 
 
+-define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end).
+
+
+
 basic(doc) ->
     "Hello world";
 basic(suite) ->
@@ -228,6 +236,148 @@ xfer_active(Config) when is_list(Config) ->
 	  end,
     ok.
 
+def_sndrcvinfo(doc) ->
+    "Test that #sctp_sndrcvinfo{} parameters set on a socket "
+	"are used by gen_sctp:send/4";
+def_sndrcvinfo(suite) ->
+    [];
+def_sndrcvinfo(Config) when is_list(Config) ->
+    ?line Loopback = {127,0,0,1},
+    ?line Data = <<"What goes up, must come down.">>,
+    %%
+    ?line S1 =
+	ok(gen_sctp:open(
+	     0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])),
+    ?LOGVAR(S1),
+    ?line P1 =
+	ok(inet:port(S1)),
+    ?LOGVAR(P1),
+    ?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
+	getopt(S1, sctp_default_send_param),
+    ?line ok =
+	gen_sctp:listen(S1, true),
+    %%
+    ?line S2 =
+	ok(gen_sctp:open()),
+    ?LOGVAR(S2),
+    ?line P2 =
+	ok(inet:port(S2)),
+    ?LOGVAR(P2),
+    ?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
+	getopt(S2, sctp_default_send_param),
+    %%
+    ?line #sctp_assoc_change{
+       state=comm_up,
+       error=0,
+       assoc_id=S2AssocId} = S2AssocChange =
+	ok(gen_sctp:connect(S2, Loopback, P1, [])),
+    ?LOGVAR(S2AssocChange),
+    ?line case ok(gen_sctp:recv(S1)) of
+	      {Loopback, P2,[],
+	       #sctp_assoc_change{
+			      state=comm_up,
+			      error=0,
+			      assoc_id=S1AssocId}} ->
+		  ?LOGVAR(S1AssocId)
+	  end,
+    ?line #sctp_sndrcvinfo{
+       ppid=17, context=0, timetolive=0, assoc_id=S1AssocId} =
+	getopt(
+	  S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
+    ?line #sctp_sndrcvinfo{
+       ppid=0, context=0, timetolive=0, assoc_id=S2AssocId} =
+	getopt(
+	  S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}),
+    %%
+    ?line ok =
+	gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>),
+    ?line case ok(gen_sctp:recv(S2)) of
+	      {Loopback,P1,
+	       [#sctp_sndrcvinfo{
+		   stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+	       <<"1: ",Data/binary>>} -> ok
+	  end,
+    %%
+    ?line ok =
+	setopt(
+	  S1, sctp_default_send_param, #sctp_sndrcvinfo{ppid=18}),
+    ?line ok =
+	setopt(
+	  S1, sctp_default_send_param,
+	  #sctp_sndrcvinfo{ppid=19, assoc_id=S1AssocId}),
+    ?line #sctp_sndrcvinfo{
+       ppid=18, context=0, timetolive=0, assoc_id=0} =
+	getopt(S1, sctp_default_send_param),
+    ?line #sctp_sndrcvinfo{
+       ppid=19, context=0, timetolive=0, assoc_id=S1AssocId} =
+	getopt(
+	  S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
+    %%
+    ?line ok =
+	gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>),
+    ?line case ok(gen_sctp:recv(S2)) of
+	      {Loopback,P1,
+	       [#sctp_sndrcvinfo{
+		   stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
+	       <<"2: ",Data/binary>>} -> ok
+	  end,
+    ?line ok =
+	gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>),
+    ?line case ok(gen_sctp:recv(S1)) of
+	      {Loopback,P2,
+	       [#sctp_sndrcvinfo{
+		   stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
+	       <<"3: ",Data/binary>>} -> ok;
+	      {Loopback,P2,[],
+	       #sctp_paddr_change{
+			  addr={Loopback,_}, state=addr_available,
+			  error=0, assoc_id=S1AssocId}} ->
+		  ?line case ok(gen_sctp:recv(S1)) of
+			    {Loopback,P2,
+			     [#sctp_sndrcvinfo{
+				 stream=1, ppid=0, context=0,
+				 assoc_id=S1AssocId}],
+			     <<"3: ",Data/binary>>} -> ok
+			end
+	  end,
+    ?line ok =
+	gen_sctp:send(
+	  S2,
+	  #sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
+	  <<"4: ",Data/binary>>),
+    ?line case ok(gen_sctp:recv(S1)) of
+	      {Loopback,P2,
+	       [#sctp_sndrcvinfo{
+		   stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
+	       <<"4: ",Data/binary>>} -> ok
+	  end,
+    %%
+    ?line ok =
+	gen_sctp:close(S1),
+    ?line ok =
+	gen_sctp:close(S2),
+    ?line receive
+	      Msg ->
+		  test_server:fail({received,Msg})
+	  after 17 -> ok
+	  end,
+    ok.
+
+getopt(S, Opt) ->
+    {ok,[{Opt,Val}]} = inet:getopts(S, [Opt]),
+    Val.
+
+getopt(S, Opt, Param) ->
+    {ok,[{Opt,Val}]} = inet:getopts(S, [{Opt,Param}]),
+    Val.
+
+setopt(S, Opt, Val) ->
+    inet:setopts(S, [{Opt,Val}]).
+
+ok({ok,X}) ->
+    io:format("OK: ~p~n", [X]),
+    X.
+
 flush() ->
     receive
 	Msg ->
-- 
cgit v1.2.3


From 8a0e1429ef2099378cdab0288224207d4d64332d Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Tue, 31 Aug 2010 16:37:32 +0200
Subject: Fix xfer_active close expection for Solaris behaviour

---
 lib/kernel/test/gen_sctp_SUITE.erl | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 72f1436415..ceda5b0af6 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -222,12 +222,17 @@ xfer_active(Config) when is_list(Config) ->
 	  end,
     ?line ok = gen_sctp:close(Sb),
     ?line receive
-	      {sctp,Sa,Loopback,Pb,
-	       {[],
-		#sctp_assoc_change{state=comm_lost,
-				   assoc_id=SaAssocId}}} -> ok
-	  after 17 -> ok %% On Solaris this does not arrive
-	  end,
+              {sctp,Sa,Loopback,Pb,
+               {[],
+                #sctp_assoc_change{state=comm_lost,
+                                   assoc_id=SaAssocId}}} -> ok
+          after Timeout ->
+                  ?line test_server:fail({unexpected,flush()})
+          end,
+    ?line receive
+              {sctp_error,Sa,enotconn} -> ok % Solaris
+          after 17 -> ok %% Only happens on Solaris
+          end,
     ?line ok = gen_sctp:close(Sa),
     %%
     ?line receive
-- 
cgit v1.2.3