diff options
author | Fredrik Gustafsson <[email protected]> | 2012-08-27 10:20:36 +0200 |
---|---|---|
committer | Fredrik Gustafsson <[email protected]> | 2012-08-27 10:20:36 +0200 |
commit | 618e0f37c9dda5bc26900692ed0cc41031be9e76 (patch) | |
tree | adad7379350ddf7bfd782d72c4b95c38ee6fc7d5 /lib/kernel/src/inet.erl | |
parent | ae2c50f36806b26530de88d2609cd6ced018cb54 (diff) | |
parent | 87570500f821c4aaeafa18705b3a4a479f5d9baa (diff) | |
download | otp-618e0f37c9dda5bc26900692ed0cc41031be9e76.tar.gz otp-618e0f37c9dda5bc26900692ed0cc41031be9e76.tar.bz2 otp-618e0f37c9dda5bc26900692ed0cc41031be9e76.zip |
Merge branch 'tab/fix-sctp-multihoming-IPv6/OTP-10217' into maint
* tab/fix-sctp-multihoming-IPv6/OTP-10217:
Allow mixed IPv4 and IPv6 addresses to sctp_bindx
Add checks for in6addr_any and in6addr_loopback
Fix SCTP multihoming
inet_drv.c: Set sockaddr lengths in inet_set_[f]address
Diffstat (limited to 'lib/kernel/src/inet.erl')
-rw-r--r-- | lib/kernel/src/inet.erl | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 0bb5444dbb..1a03424f88 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -763,8 +763,12 @@ sctp_opt([Opt|Opts], Mod, R, As) -> {Name,Val} -> sctp_opt (Opts, Mod, R, As, Name, Val); _ -> {error,badarg} end; -sctp_opt([], _Mod, R, _SockOpts) -> - {ok, R}. +sctp_opt([], _Mod, #sctp_opts{ifaddr=IfAddr}=R, _SockOpts) -> + if is_list(IfAddr) -> + {ok, R#sctp_opts{ifaddr=lists:reverse(IfAddr)}}; + true -> + {ok, R} + end. sctp_opt(Opts, Mod, R, As, Name, Val) -> case add_opt(Name, Val, R#sctp_opts.opts, As) of @@ -1015,11 +1019,7 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 -> case prim_inet:setopts(S, Opts) of ok -> case if is_list(Addr) -> - prim_inet:bind(S, add, - [case A of - {_,_} -> A; - _ -> {A,Port} - end || A <- Addr]); + bindx(S, Addr, Port); true -> prim_inet:bind(S, Addr, Port) end of @@ -1040,6 +1040,34 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 -> open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) -> fdopen(Fd, Opts, Protocol, Family, Type, Module). +bindx(S, [Addr], Port0) -> + {IP, Port} = set_bindx_port(Addr, Port0), + prim_inet:bind(S, IP, Port); +bindx(S, Addrs, Port0) -> + [{IP, Port} | Rest] = [set_bindx_port(Addr, Port0) || Addr <- Addrs], + case prim_inet:bind(S, IP, Port) of + {ok, AssignedPort} when Port =:= 0 -> + %% On newer Linux kernels, Solaris and FreeBSD, calling + %% bindx with port 0 is ok, but on SuSE 10, it results in einval + Rest2 = [change_bindx_0_port(Addr, AssignedPort) || Addr <- Rest], + prim_inet:bind(S, add, Rest2); + {ok, _} -> + prim_inet:bind(S, add, Rest); + Error -> + Error + end. + +set_bindx_port({_IP, _Port}=Addr, _OtherPort) -> + Addr; +set_bindx_port(IP, Port) -> + {IP, Port}. + +change_bindx_0_port({IP, 0}, AssignedPort) -> + {IP, AssignedPort}; +change_bindx_0_port({_IP, _Port}=Addr, _AssignedPort) -> + Addr. + + -spec fdopen(Fd :: non_neg_integer(), Opts :: [socket_setopt()], Protocol :: socket_protocol(), |