aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/nifs/common/net_nif.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/nifs/common/net_nif.c')
-rw-r--r--erts/emulator/nifs/common/net_nif.c511
1 files changed, 389 insertions, 122 deletions
diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c
index e0129aec69..90263d11c2 100644
--- a/erts/emulator/nifs/common/net_nif.c
+++ b/erts/emulator/nifs/common/net_nif.c
@@ -174,6 +174,9 @@
#include <erl_nif.h>
+#include "socket_dbg.h"
+#include "socket_int.h"
+
/* All platforms fail on malloc errors. */
#define FATAL_MALLOC
@@ -263,66 +266,67 @@ typedef unsigned long long llu_t;
* *
* =================================================================== */
-#define MALLOC(SZ) enif_alloc((SZ))
-#define FREE(P) enif_free((P))
-
-#define MKA(E,S) enif_make_atom((E), (S))
-#define MKBIN(E,B) enif_make_binary((E), (B))
-#define MKI(E,I) enif_make_int((E), (I))
-#define MKLA(E,A,L) enif_make_list_from_array((E), (A), (L))
-#define MKEL(E) enif_make_list((E), 0)
-#define MKREF(E) enif_make_ref((E))
-#define MKS(E,S) enif_make_string((E), (S), ERL_NIF_LATIN1)
-#define MKSL(E,S,L) enif_make_string_len((E), (S), (L), ERL_NIF_LATIN1)
-#define MKSBIN(E,B,ST,SZ) enif_make_sub_binary((E), (B), (ST), (SZ))
-#define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2))
-#define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3))
-#define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4))
-#define MKT5(E,E1,E2,E3,E4,E5) \
- enif_make_tuple5((E), (E1), (E2), (E3), (E4), (E5))
-#define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \
- enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8))
-
-#define MCREATE(N) enif_mutex_create((N))
-#define MDESTROY(M) enif_mutex_destroy((M))
-#define MLOCK(M) enif_mutex_lock((M))
-#define MUNLOCK(M) enif_mutex_unlock((M))
-
-#define MONP(E,D,P,M) enif_monitor_process((E), (D), (P), (M))
-#define DEMONP(E,D,M) enif_demonitor_process((E), (D), (M))
-
-#define SELECT(E,FD,M,O,P,R) \
- enif_select((E), (FD), (M), (O), (P), (R))
-#define SELECT_READ(E, DP, P, R) \
- SELECT((E), (DP)->sock, (ERL_NIF_SELECT_READ), (DP), (P), (R))
-#define SELECT_WRITE(E, DP, P, R) \
- SELECT((E), (DP)->sock, (ERL_NIF_SELECT_WRITE), (DP), (P), (R))
-#define SELECT_STOP(E, DP) \
- enif_select((E), (DP)->sock, (ERL_NIF_SELECT_STOP), (DP), NULL, atom_undefined)
-
-#define IS_ATOM(E, TE) enif_is_atom((E), (TE))
-#define IS_BIN(E, TE) enif_is_binary((E), (TE))
-#define IS_NUM(E, TE) enif_is_number((E), (TE))
-#define IS_TUPLE(E, TE) enif_is_tuple((E), (TE))
-#define IS_LIST(E, TE) enif_is_list((E), (TE))
-
-#define COMPARE(L, R) enif_compare((L), (R))
-
-#define GET_ATOM_LEN(E, TE, LP) \
- enif_get_atom_length((E), (TE), (LP), ERL_NIF_LATIN1)
-#define GET_ATOM(E, TE, BP, MAX) \
- enif_get_atom((E), (TE), (BP), (MAX), ERL_NIF_LATIN1)
-#define GET_BIN(E, TE, BP) enif_inspect_iolist_as_binary((E), (TE), (BP))
-#define GET_INT(E, TE, IP) enif_get_int((E), (TE), (IP))
-#define GET_LIST_ELEM(E, L, HP, TP) enif_get_list_cell((E), (L), (HP), (TP))
-#define GET_LIST_LEN(E, L, LP) enif_get_list_length((E), (L), (LP))
-#define GET_STR(E, L, B, SZ) \
- enif_get_string((E), (L), (B), (SZ), ERL_NIF_LATIN1)
-#define GET_UINT(E, TE, IP) enif_get_uint((E), (TE), (IP))
-#define GET_TUPLE(E, TE, TSZ, TA) enif_get_tuple((E), (TE), (TSZ), (TA))
-
-#define ALLOC_BIN(SZ, BP) enif_alloc_binary((SZ), (BP))
-#define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP))
+/* #define MALLOC(SZ) enif_alloc((SZ)) */
+/* #define FREE(P) enif_free((P)) */
+
+/* #define MKA(E,S) enif_make_atom((E), (S)) */
+/* #define MKBIN(E,B) enif_make_binary((E), (B)) */
+/* #define MKI(E,I) enif_make_int((E), (I)) */
+/* #define MKLA(E,A,L) enif_make_list_from_array((E), (A), (L)) */
+/* #define MKEL(E) enif_make_list((E), 0) */
+/* #define MKREF(E) enif_make_ref((E)) */
+/* #define MKS(E,S) enif_make_string((E), (S), ERL_NIF_LATIN1) */
+/* #define MKSL(E,S,L) enif_make_string_len((E), (S), (L), ERL_NIF_LATIN1) */
+/* #define MKSBIN(E,B,ST,SZ) enif_make_sub_binary((E), (B), (ST), (SZ)) */
+/* #define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2)) */
+/* #define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3)) */
+/* #define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4)) */
+/* #define MKT5(E,E1,E2,E3,E4,E5) \ */
+/* enif_make_tuple5((E), (E1), (E2), (E3), (E4), (E5)) */
+/* #define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \ */
+/* enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8)) */
+/* #define MKTA(E, A, AL) enif_make_tuple_from_array((E), (A), (AL)) */
+
+/* #define MCREATE(N) enif_mutex_create((N)) */
+/* #define MDESTROY(M) enif_mutex_destroy((M)) */
+/* #define MLOCK(M) enif_mutex_lock((M)) */
+/* #define MUNLOCK(M) enif_mutex_unlock((M)) */
+
+/* #define MONP(E,D,P,M) enif_monitor_process((E), (D), (P), (M)) */
+/* #define DEMONP(E,D,M) enif_demonitor_process((E), (D), (M)) */
+
+/* #define SELECT(E,FD,M,O,P,R) \ */
+/* enif_select((E), (FD), (M), (O), (P), (R)) */
+/* #define SELECT_READ(E, DP, P, R) \ */
+/* SELECT((E), (DP)->sock, (ERL_NIF_SELECT_READ), (DP), (P), (R)) */
+/* #define SELECT_WRITE(E, DP, P, R) \ */
+/* SELECT((E), (DP)->sock, (ERL_NIF_SELECT_WRITE), (DP), (P), (R)) */
+/* #define SELECT_STOP(E, DP) \ */
+/* enif_select((E), (DP)->sock, (ERL_NIF_SELECT_STOP), (DP), NULL, atom_undefined) */
+
+/* #define IS_ATOM(E, TE) enif_is_atom((E), (TE)) */
+/* #define IS_BIN(E, TE) enif_is_binary((E), (TE)) */
+/* #define IS_NUM(E, TE) enif_is_number((E), (TE)) */
+/* #define IS_TUPLE(E, TE) enif_is_tuple((E), (TE)) */
+/* #define IS_LIST(E, TE) enif_is_list((E), (TE)) */
+
+/* #define COMPARE(L, R) enif_compare((L), (R)) */
+
+/* #define GET_ATOM_LEN(E, TE, LP) \ */
+/* enif_get_atom_length((E), (TE), (LP), ERL_NIF_LATIN1) */
+/* #define GET_ATOM(E, TE, BP, MAX) \ */
+/* enif_get_atom((E), (TE), (BP), (MAX), ERL_NIF_LATIN1) */
+/* #define GET_BIN(E, TE, BP) enif_inspect_iolist_as_binary((E), (TE), (BP)) */
+/* #define GET_INT(E, TE, IP) enif_get_int((E), (TE), (IP)) */
+/* #define GET_LIST_ELEM(E, L, HP, TP) enif_get_list_cell((E), (L), (HP), (TP)) */
+/* #define GET_LIST_LEN(E, L, LP) enif_get_list_length((E), (L), (LP)) */
+/* #define GET_STR(E, L, B, SZ) \ */
+/* enif_get_string((E), (L), (B), (SZ), ERL_NIF_LATIN1) */
+/* #define GET_UINT(E, TE, IP) enif_get_uint((E), (TE), (IP)) */
+/* #define GET_TUPLE(E, TE, TSZ, TA) enif_get_tuple((E), (TE), (TSZ), (TA)) */
+
+/* #define ALLOC_BIN(SZ, BP) enif_alloc_binary((SZ), (BP)) */
+/* #define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP)) */
#ifdef HAVE_SOCKLEN_T
@@ -342,12 +346,16 @@ typedef unsigned long long llu_t;
typedef union {
struct sockaddr sa;
- struct sockaddr_in in;
+ struct sockaddr_in in4;
#ifdef HAVE_IN6
struct sockaddr_in6 in6;
#endif
+#ifdef HAVE_SYS_UN_H
+ struct sockaddr_un un;
+#endif
+
} SockAddress;
typedef struct {
@@ -440,6 +448,22 @@ static BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env,
SockAddress* saP,
SOCKLEN_T* saLen);
#endif
+static ERL_NIF_TERM encode_in_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP,
+ SOCKLEN_T addrLen);
+static ERL_NIF_TERM encode_in4_sockaddr(ErlNifEnv* env,
+ struct sockaddr_in* addrP,
+ SOCKLEN_T addrLen);
+#if defined(HAVE_IN6) && defined(AF_INET6)
+static ERL_NIF_TERM encode_in6_sockaddr(ErlNifEnv* env,
+ struct sockaddr_in6* addrP,
+ SOCKLEN_T addrLen);
+#endif
+#ifdef HAVE_SYS_UN_H
+static ERL_NIF_TERM encode_un_sockaddr(ErlNifEnv* env,
+ struct sockaddr_un* addrP,
+ SOCKLEN_T addrLen);
+#endif
static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env,
const ERL_NIF_TERM eflags,
int* flags);
@@ -453,28 +477,50 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env,
static ERL_NIF_TERM decode_bool(ErlNifEnv* env,
ERL_NIF_TERM eBool,
BOOLEAN_T* bool);
+static ERL_NIF_TERM encode_address_infos(ErlNifEnv* env,
+ struct addrinfo* addrInfo);
static ERL_NIF_TERM encode_address_info(ErlNifEnv* env,
- struct addrinfo* addrInfo);
+ struct addrinfo* addrInfoP);
static unsigned int address_info_length(struct addrinfo* addrInfoP);
-static ERL_NIF_TERM make_address_info(ErlNifEnv* env,
- struct addrinfo* addrInfoP);
-static ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env,
+static ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env,
int family);
-static ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env,
+static ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env,
int socktype);
-static ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env,
+static ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env,
int proto);
-static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env,
- struct sockaddr* addrP,
- SOCKLEN_T addrLen);
+/* static ERL_NIF_TERM make_address_info(ErlNifEnv* env, */
+/* struct addrinfo* addrInfoP); */
+/* static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, */
+/* struct sockaddr* addrP, */
+/* SOCKLEN_T addrLen); */
+
+static ERL_NIF_TERM make_in4_sockaddr(ErlNifEnv* env,
+ ERL_NIF_TERM port,
+ ERL_NIF_TERM addr);
+#if defined(HAVE_IN6) && defined(AF_INET6)
+static ERL_NIF_TERM make_in6_sockaddr(ErlNifEnv* env,
+ ERL_NIF_TERM port,
+ ERL_NIF_TERM addr,
+ ERL_NIF_TERM flowInfo,
+ ERL_NIF_TERM scopeId);
+#endif
+static ERL_NIF_TERM make_address_info(ErlNifEnv* env,
+ ERL_NIF_TERM fam,
+ ERL_NIF_TERM sockType,
+ ERL_NIF_TERM proto,
+ ERL_NIF_TERM addr);
static ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM val);
// static ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2);
static ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason);
static ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason);
static ERL_NIF_TERM make_error2(ErlNifEnv* env, int err);
+#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE)
+static size_t my_strnlen(const char *s, size_t maxlen);
+#endif
+
static void dbg_printf( const char* format, ... );
static int dbg_realtime(struct timespec* tsP);
static int dbg_timespec2str(char *buf, unsigned int len, struct timespec *ts);
@@ -522,9 +568,12 @@ static char str_false[] = "false";
static char str_idn[] = "idn";
static char str_idna_allow_unassigned[] = "idna_allow_unassigned";
static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules";
+static char str_in4_sockaddr[] = "in4_sockaddr";
+static char str_in6_sockaddr[] = "in6_sockaddr";
static char str_inet[] = "inet";
static char str_inet6[] = "inet6";
static char str_ip[] = "ip";
+static char str_ipv6[] = "ipv6";
static char str_namereqd[] = "namereqd";
static char str_name_info[] = "name_info";
static char str_nofqdn[] = "nofqdn";
@@ -585,9 +634,12 @@ static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_idn;
static ERL_NIF_TERM atom_idna_allow_unassigned;
static ERL_NIF_TERM atom_idna_use_std3_ascii_rules;
+static ERL_NIF_TERM atom_in4_sockaddr;
+static ERL_NIF_TERM atom_in6_sockaddr;
static ERL_NIF_TERM atom_inet;
static ERL_NIF_TERM atom_inet6;
static ERL_NIF_TERM atom_ip;
+static ERL_NIF_TERM atom_ipv6;
static ERL_NIF_TERM atom_namereqd;
static ERL_NIF_TERM atom_name_info;
static ERL_NIF_TERM atom_nofqdn;
@@ -1009,9 +1061,9 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env,
// eHints = argv[2];
NDBG( ("nif_getaddrinfo -> "
- "\r\n Host: %T"
- "\r\n Service: %T"
- "\r\n Hints: %T"
+ "\r\n ehost: %T"
+ "\r\n eservice: %T"
+ "\r\n ehints: %T"
"\r\n", argv[0], argv[1], argv[2]) );
if (!decode_addrinfo_string(env, eHostName, &hostName))
@@ -1071,7 +1123,7 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env,
switch (res) {
case 0:
{
- ERL_NIF_TERM addrInfo = encode_address_info(env, addrInfoP);
+ ERL_NIF_TERM addrInfo = encode_address_infos(env, addrInfoP);
freeaddrinfo(addrInfoP);
result = make_ok2(env, addrInfo);
}
@@ -1454,14 +1506,14 @@ BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env,
/* And finally initialize the sockaddr structure (and size) */
sys_memzero((char*)saP, sizeof(struct sockaddr_in));
- saP->in.sin_family = AF_INET;
- saP->in.sin_port = htons(port);
+ saP->in4.sin_family = AF_INET;
+ saP->in4.sin_port = htons(port);
for (a = 0; a < 4; a++) {
if (!GET_INT(env, ipAddrT[a], &v))
return FALSE;
addr[a] = v;
}
- sys_memcpy(&saP->in.sin_addr, &addr, sizeof(addr));
+ sys_memcpy(&saP->in4.sin_addr, &addr, sizeof(addr));
*saLen = sizeof(struct sockaddr_in);
return TRUE;
}
@@ -1552,6 +1604,168 @@ BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env,
+static
+ERL_NIF_TERM encode_in_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP,
+ SOCKLEN_T addrLen)
+{
+ SockAddress* sockAddrP = (SockAddress*) addrP;
+ ERL_NIF_TERM sockAddr;
+
+ switch (sockAddrP->sa.sa_family) {
+ case AF_INET:
+ sockAddr = encode_in4_sockaddr(env, &sockAddrP->in4, addrLen);
+ break;
+
+#if defined(HAVE_IN6) && defined(AF_INET6)
+ case AF_INET6:
+ sockAddr = encode_in6_sockaddr(env, &sockAddrP->in6, addrLen);
+ break;
+#endif
+
+#ifdef HAVE_SYS_UN_H
+ case AF_UNIX:
+ sockAddr = encode_un_sockaddr(env, &sockAddrP->un, addrLen);
+ break;
+#endif
+
+ default:
+ sockAddr = atom_undefined;
+ break;
+ }
+
+ return sockAddr;
+}
+
+
+
+/* Encode an IPv4 socket address; in4_sockaddr */
+static
+ERL_NIF_TERM encode_in4_sockaddr(ErlNifEnv* env,
+ struct sockaddr_in* addrP,
+ SOCKLEN_T addrLen)
+{
+ ERL_NIF_TERM sockAddr;
+ short port;
+ ERL_NIF_TERM ePort, eAddr;
+
+
+ if (addrLen >= sizeof(struct sockaddr_in)) {
+ unsigned int i;
+ ERL_NIF_TERM at[4];
+ unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM);
+ unsigned char* a = (unsigned char*) &addrP->sin_addr;
+
+ /* The port */
+ port = ntohs(addrP->sin_port);
+ ePort = MKI(env, port);
+
+ /* The address */
+ for (i = 0; i < atLen; i++) {
+ at[i] = MKI(env, a[i]);
+ }
+ eAddr = MKTA(env, at, atLen);
+ // eAddr = MKT4(env, at[0], at[1], at[2], at[3]);
+
+ /* And finally construct the in4_sockaddr record */
+ sockAddr = make_in4_sockaddr(env, ePort, eAddr);
+
+ } else {
+ sockAddr = atom_undefined;
+ }
+
+ return sockAddr;
+}
+
+
+
+/* Encode an IPv6 socket address; in6_sockaddr */
+#if defined(HAVE_IN6) && defined(AF_INET6)
+static
+ERL_NIF_TERM encode_in6_sockaddr(ErlNifEnv* env,
+ struct sockaddr_in6* addrP,
+ SOCKLEN_T addrLen)
+{
+ ERL_NIF_TERM sockAddr;
+ short port;
+ ERL_NIF_TERM ePort, eAddr, eFlowInfo, eScopeId;
+
+
+ if (addrLen >= sizeof(struct sockaddr_in6)) {
+ unsigned int i;
+ ERL_NIF_TERM at[8];
+ unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM);
+ unsigned char* a = (unsigned char*) &addrP->sin6_addr;
+
+ /* The port */
+ port = ntohs(addrP->sin6_port);
+ ePort = MKI(env, port);
+
+ /* The address */
+ for (i = 0; i < atLen; i++) {
+ at[i] = MKI(env, get_int16(a + i*2));
+ }
+ eAddr = MKTA(env, at, atLen);
+
+ /* The flowInfo */
+ eFlowInfo = MKI(env, addrP->sin6_flowinfo);
+
+ /* The scopeId */
+ eScopeId = MKI(env, addrP->sin6_scope_id);
+
+ /* And finally construct the in6_sockaddr record */
+ sockAddr = make_in6_sockaddr(env, ePort, eAddr, eFlowInfo, eScopeId);
+
+ } else {
+ sockAddr = atom_undefined;
+ }
+
+ return sockAddr;
+}
+#endif
+
+
+
+/* Encode an Unix Domain socket address: string() */
+#ifdef HAVE_SYS_UN_H
+static
+ERL_NIF_TERM encode_un_sockaddr(ErlNifEnv* env,
+ struct sockaddr_un* addrP,
+ SOCKLEN_T addrLen)
+{
+ ERL_NIF_TERM sockAddr;
+ size_t n, m;
+
+ if (addrLen >= offsetof(struct sockaddr_un, sun_path)) {
+ n = addrLen - offsetof(struct sockaddr_un, sun_path);
+ if (255 < n) {
+ sockAddr = atom_undefined;
+ } else {
+ m = my_strnlen(addrP->sun_path, n);
+#ifdef __linux__
+ /* Assume that the address is a zero terminated string,
+ * except when the first byte is \0 i.e the string length is 0,
+ * then use the reported length instead.
+ * This fix handles Linux's nonportable
+ * abstract socket address extension.
+ */
+ if (m == 0) {
+ m = n;
+ }
+#endif
+
+ sockAddr = MKSL(env, addrP->sun_path, m);
+ }
+ } else {
+ sockAddr = atom_undefined;
+ }
+
+ return sockAddr;
+}
+#endif
+
+
+
/* The erlang format for a set of flags is a list of atoms.
* A special case is when there is no flags, which is
* represented by the atom undefined.
@@ -1710,13 +1924,13 @@ ERL_NIF_TERM decode_bool(ErlNifEnv* env,
* will result in the result being a list of zero or more length.
*/
static
-ERL_NIF_TERM encode_address_info(ErlNifEnv* env,
- struct addrinfo* addrInfo)
+ERL_NIF_TERM encode_address_infos(ErlNifEnv* env,
+ struct addrinfo* addrInfo)
{
ERL_NIF_TERM result;
unsigned int len = address_info_length(addrInfo);
- NDBG( ("encode_address_info -> len: %d\r\n", len) );
+ NDBG( ("encode_address_infos -> len: %d\r\n", len) );
if (len > 0) {
ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM));
@@ -1724,22 +1938,17 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env,
struct addrinfo* p = addrInfo;
while (i < len) {
- array[i] = make_address_info(env, p);
+ array[i] = encode_address_info(env, p);
p = p->ai_next;
i++;
}
- /*
- for (i = 0; i < len; i++) {
- array[i] = make_address_info(env, &addrInfo[i]);
- }
- */
result = MKLA(env, array, len);
} else {
result = MKEL(env);
}
- NDBG( ("encode_address_info -> result: "
+ NDBG( ("encode_address_infos -> result: "
"\r\n %T\r\n", result) );
return result;
@@ -1780,28 +1989,17 @@ unsigned int address_info_length(struct addrinfo* addrInfoP)
* {address_info, Fam, Type, Proto, Addr}
*/
static
-ERL_NIF_TERM make_address_info(ErlNifEnv* env,
- struct addrinfo* addrInfoP)
+ERL_NIF_TERM encode_address_info(ErlNifEnv* env,
+ struct addrinfo* addrInfoP)
{
ERL_NIF_TERM result, fam, type, proto, addr;
- fam = make_addrinfo_family(env, addrInfoP->ai_family);
- // NDBG( ("make_address_info -> fam: %T\r\n", fam) );
- type = make_addrinfo_type(env, addrInfoP->ai_socktype);
- // NDBG( ("make_address_info -> type: %T\r\n", type) );
- proto = make_addrinfo_proto(env, addrInfoP->ai_protocol);
- // NDBG( ("make_address_info -> proto: %T\r\n", proto) );
- addr = make_addrinfo_addr(env,
- addrInfoP->ai_addr,
- addrInfoP->ai_addrlen);
- // NDBG( ("make_address_info -> addr: %T\r\n", addr) );
+ fam = encode_address_info_family(env, addrInfoP->ai_family);
+ type = encode_address_info_type(env, addrInfoP->ai_socktype);
+ proto = encode_address_info_proto(env, addrInfoP->ai_protocol);
+ addr = encode_in_sockaddr(env, addrInfoP->ai_addr, addrInfoP->ai_addrlen);
- result = MKT5(env, atom_address_info, fam, type, proto, addr);
-
- /*
- NDBG( ("make_address_info -> result: "
- "\r\n %T\r\n", result) );
- */
+ result = make_address_info(env, fam, type, proto, addr);
return result;
@@ -1814,23 +2012,29 @@ ERL_NIF_TERM make_address_info(ErlNifEnv* env,
* in the form of an integer.
*/
static
-ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env,
- int family)
+ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env,
+ int family)
{
ERL_NIF_TERM efam;
switch (family) {
case AF_INET:
- efam = atom_inet;
+ efam = esock_atom_inet;
break;
#if defined(HAVE_IN6) && defined(AF_INET6)
case AF_INET6:
- efam = atom_inet6;
+ efam = esock_atom_inet6;
break;
#endif
- default:
+ #ifdef HAVE_SYS_UN_H
+ case AF_UNIX:
+ efam = esock_atom_local;
+ break;
+#endif
+
+ default:
efam = MKI(env, family);
break;
}
@@ -1846,8 +2050,8 @@ ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env,
* in the form of an integer.
*/
static
-ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env,
- int socktype)
+ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env,
+ int socktype)
{
ERL_NIF_TERM etype;
@@ -1872,10 +2076,6 @@ ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env,
etype = atom_seqpacket;
break;
- case SOCK_DCCP:
- etype = atom_dccp;
- break;
-
default:
etype = MKI(env, socktype);
break;
@@ -1892,8 +2092,8 @@ ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env,
* in the form of an integer.
*/
static
-ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env,
- int proto)
+ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env,
+ int proto)
{
ERL_NIF_TERM eproto;
@@ -1906,6 +2106,12 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env,
eproto = atom_ip;
break;
+#if defined(SOL_IPV6)
+ case SOL_IPV6:
+ eproto = atom_ipv6;
+ break;
+#endif
+
case IPPROTO_TCP:
eproto = atom_tcp;
break;
@@ -1914,6 +2120,12 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env,
eproto = atom_udp;
break;
+#if defined(HAVE_SCTP)
+ case IPPROTO_SCTP:
+ eproto = atom_sctp;
+ break;
+#endif
+
default:
eproto = MKI(env, proto);
break;
@@ -1929,15 +2141,16 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env,
* IPv4 and IPv6 addresses. Values of other families will be
* returned as an undefined.
*/
+/*
static
-ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env,
- struct sockaddr* addrP,
- SOCKLEN_T addrLen)
+ERL_NIF_TERM encode_address_info_addr(ErlNifEnv* env,
+ struct sockaddr* addrP,
+ SOCKLEN_T addrLen)
{
ERL_NIF_TERM port, addr, eaddr;
SockAddress* p = (SockAddress*) addrP;
- NDBG( ("make_addrinfo_addr -> entry with"
+ NDBG( ("encode_address_info_addr -> entry with"
"\r\n family: %d"
"\r\n addrLen: %d"
"\r\n", addrP->sa_family, addrLen) );
@@ -1985,6 +2198,57 @@ ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env,
return eaddr;
}
+*/
+
+
+
+#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE)
+/* strnlen doesn't exist everywhere */
+static
+size_t my_strnlen(const char *s, size_t maxlen)
+{
+ size_t i = 0;
+ while (i < maxlen && s[i] != '\0')
+ i++;
+ return i;
+}
+#endif
+
+
+
+/* Construct the IPv4 socket address record: in4_sockaddr */
+static
+ERL_NIF_TERM make_in4_sockaddr(ErlNifEnv* env,
+ ERL_NIF_TERM port,
+ ERL_NIF_TERM addr)
+{
+ return MKT3(env, atom_in4_sockaddr, port, addr);
+}
+
+
+
+/* Construct the IPv6 socket address record: in6_sockaddr */
+static
+ERL_NIF_TERM make_in6_sockaddr(ErlNifEnv* env,
+ ERL_NIF_TERM port,
+ ERL_NIF_TERM addr,
+ ERL_NIF_TERM flowInfo,
+ ERL_NIF_TERM scopeId)
+{
+ return MKT5(env, atom_in6_sockaddr, port, addr, flowInfo, scopeId);
+}
+
+
+
+static
+ERL_NIF_TERM make_address_info(ErlNifEnv* env,
+ ERL_NIF_TERM fam,
+ ERL_NIF_TERM sockType,
+ ERL_NIF_TERM proto,
+ ERL_NIF_TERM addr)
+{
+ return MKT5(env, atom_address_info, fam, sockType, proto, addr);
+}
@@ -2248,9 +2512,12 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_idn = MKA(env, str_idn);
atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned);
atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules);
+ atom_in4_sockaddr = MKA(env, str_in4_sockaddr);
+ atom_in6_sockaddr = MKA(env, str_in6_sockaddr);
atom_inet = MKA(env, str_inet);
atom_inet6 = MKA(env, str_inet6);
atom_ip = MKA(env, str_ip);
+ atom_ipv6 = MKA(env, str_ipv6);
atom_namereqd = MKA(env, str_namereqd);
atom_name_info = MKA(env, str_name_info);
atom_nofqdn = MKA(env, str_nofqdn);