diff options
author | Raimo Niskanen <[email protected]> | 2012-10-31 09:17:15 +0100 |
---|---|---|
committer | Raimo Niskanen <[email protected]> | 2012-10-31 09:17:15 +0100 |
commit | 0a42a8be1604a29bfefd62e54a2e8453e237fd73 (patch) | |
tree | ba3754c1ab72ba52f31a7d8f06781cfa9d5eea87 /erts | |
parent | 465be6cd854681093971c2bb0d678993168f4a3e (diff) | |
parent | 7028c8e756129cbb7898798fc81a16de3625709f (diff) | |
download | otp-0a42a8be1604a29bfefd62e54a2e8453e237fd73.tar.gz otp-0a42a8be1604a29bfefd62e54a2e8453e237fd73.tar.bz2 otp-0a42a8be1604a29bfefd62e54a2e8453e237fd73.zip |
Merge branch 'raimo/IPV6_V6ONLY/OTP-8928'
* raimo/IPV6_V6ONLY/OTP-8928:
kernel: Document socket option ipv6_v6only
kernel: Add test cases for socket option ipv6_v6only
erts,kernel: Implement socket option ipv6_v6only in erlang code
erts: Implement socket option IPV6_V6ONLY
erts: Add configure test for IPV6_V6ONLY
Diffstat (limited to 'erts')
-rw-r--r-- | erts/configure.in | 8 | ||||
-rw-r--r-- | erts/emulator/drivers/common/inet_drv.c | 67 | ||||
-rw-r--r-- | erts/preloaded/ebin/prim_inet.beam | bin | 69764 -> 69964 bytes | |||
-rw-r--r-- | erts/preloaded/src/prim_inet.erl | 3 |
4 files changed, 76 insertions, 2 deletions
diff --git a/erts/configure.in b/erts/configure.in index 6ad1951a4e..3256b0cb59 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -2000,8 +2000,12 @@ case "$erts_cv_have_in6addr_loopback" in [Define to 1 if you have the variable in6addr_loopback declared.]) esac -AC_CHECK_DECLS([IN6ADDR_ANY_INIT, IN6ADDR_LOOPBACK_INIT], [], [], - [#include <netinet/in.h>]) +AC_CHECK_DECLS([IN6ADDR_ANY_INIT, IN6ADDR_LOOPBACK_INIT, IPV6_V6ONLY], [], [], + [ + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h> + ]) dnl ---------------------------------------------------------------------- dnl Checks for features/quirks in the system that affects Erlang. diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 80f504a361..3210ffa92a 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -660,6 +660,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) #define UDP_OPT_MULTICAST_LOOP 13 /* set/get IP multicast loopback */ #define UDP_OPT_ADD_MEMBERSHIP 14 /* add an IP group membership */ #define UDP_OPT_DROP_MEMBERSHIP 15 /* drop an IP group membership */ +#define INET_OPT_IPV6_V6ONLY 16 /* IPv6 only socket, no mapped v4 addrs */ /* LOPT is local options */ #define INET_LOPT_BUFFER 20 /* min buffer size hint */ #define INET_LOPT_HEADER 21 /* list header size */ @@ -1167,6 +1168,7 @@ static ErlDrvTermData am_reuseaddr; static ErlDrvTermData am_dontroute; static ErlDrvTermData am_priority; static ErlDrvTermData am_tos; +static ErlDrvTermData am_ipv6_v6only; #endif /* speical errors for bad ports and sequences */ @@ -3486,6 +3488,7 @@ static void inet_init_sctp(void) { INIT_ATOM(dontroute); INIT_ATOM(priority); INIT_ATOM(tos); + INIT_ATOM(ipv6_v6only); /* Option names */ INIT_ATOM(sctp_rtoinfo); @@ -5618,6 +5621,23 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len) #endif /* HAVE_MULTICAST_SUPPORT */ + case INET_OPT_IPV6_V6ONLY: +#if HAVE_DECL_IPV6_V6ONLY + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + propagate = 1; + DEBUGF(("inet_set_opts(%ld): s=%d, IPV6_V6ONLY=%d\r\n", + (long)desc->port, desc->s, ival)); + break; +#elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) + /* Fake a'la OpenBSD; set to 'true' is fine but 'false' invalid. */ + if (ival != 0) continue; + else return -1; + break; +#else + continue; +#endif + case INET_OPT_RAW: if (len < 8) { return -1; @@ -5947,6 +5967,22 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) continue; /* Option not supported -- ignore it */ # endif + case INET_OPT_IPV6_V6ONLY: +# if HAVE_DECL_IPV6_V6ONLY + { + arg.ival= get_int32 (curr); curr += 4; + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + arg_ptr = (char*) (&arg.ival); + arg_sz = sizeof ( arg.ival); + break; + } +# elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) +# error Here is a fix for Win IPv6 SCTP missing +# else + continue; /* Option not supported -- ignore it */ +# endif + case SCTP_OPT_AUTOCLOSE: { arg.ival= get_int32 (curr); curr += 4; @@ -6435,6 +6471,22 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc, break; #endif /* HAVE_MULTICAST_SUPPORT */ + case INET_OPT_IPV6_V6ONLY: +#if HAVE_DECL_IPV6_V6ONLY + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + break; +#elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) + /* Fake reading 'true' */ + *ptr++ = opt; + put_int32(1, ptr); + ptr += 4; + continue; +#else + TRUNCATE_TO(0,ptr); + continue; /* skip - no result */ +#endif + case INET_OPT_RAW: { int data_provided; @@ -6739,6 +6791,7 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, case INET_OPT_DONTROUTE: case INET_OPT_PRIORITY : case INET_OPT_TOS : + case INET_OPT_IPV6_V6ONLY: case SCTP_OPT_AUTOCLOSE: case SCTP_OPT_MAXSEG : /* The following options return true or false: */ @@ -6811,6 +6864,20 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, continue; # endif } + case INET_OPT_IPV6_V6ONLY: +# if HAVE_DECL_IPV6_V6ONLY + { + proto = IPPROTO_IPV6; + type = IPV6_V6ONLY; + tag = am_ipv6_v6only; + break; + } +# elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6) +# error Here is a fix for Win IPv6 SCTP needed +# else + /* Not supported -- ignore */ + continue; +# endif case SCTP_OPT_AUTOCLOSE: { proto = IPPROTO_SCTP; diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex 5409cf2dfc..b2d224e560 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl index b639b1efdd..b9800a05da 100644 --- a/erts/preloaded/src/prim_inet.erl +++ b/erts/preloaded/src/prim_inet.erl @@ -1062,6 +1062,7 @@ enc_opt(multicast_ttl) -> ?UDP_OPT_MULTICAST_TTL; enc_opt(multicast_loop) -> ?UDP_OPT_MULTICAST_LOOP; enc_opt(add_membership) -> ?UDP_OPT_ADD_MEMBERSHIP; enc_opt(drop_membership) -> ?UDP_OPT_DROP_MEMBERSHIP; +enc_opt(ipv6_v6only) -> ?INET_OPT_IPV6_V6ONLY; enc_opt(buffer) -> ?INET_LOPT_BUFFER; enc_opt(header) -> ?INET_LOPT_HEADER; enc_opt(active) -> ?INET_LOPT_ACTIVE; @@ -1115,6 +1116,7 @@ dec_opt(?UDP_OPT_MULTICAST_TTL) -> multicast_ttl; dec_opt(?UDP_OPT_MULTICAST_LOOP) -> multicast_loop; dec_opt(?UDP_OPT_ADD_MEMBERSHIP) -> add_membership; dec_opt(?UDP_OPT_DROP_MEMBERSHIP) -> drop_membership; +dec_opt(?INET_OPT_IPV6_V6ONLY) -> ipv6_v6only; dec_opt(?INET_LOPT_BUFFER) -> buffer; dec_opt(?INET_LOPT_HEADER) -> header; dec_opt(?INET_LOPT_ACTIVE) -> active; @@ -1178,6 +1180,7 @@ type_opt_1(recbuf) -> int; type_opt_1(priority) -> int; type_opt_1(tos) -> int; type_opt_1(nodelay) -> bool; +type_opt_1(ipv6_v6only) -> bool; %% multicast type_opt_1(multicast_ttl) -> int; type_opt_1(multicast_loop) -> bool; |