Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
2211-erts-esock-Socket-address-encoding.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2211-erts-esock-Socket-address-encoding.patch of Package erlang
From bb8ef7444c80f79aa13f39a8480b8a610272fc01 Mon Sep 17 00:00:00 2001 From: Micael Karlberg <bmk@erlang.org> Date: Fri, 25 Mar 2022 16:52:04 +0100 Subject: [PATCH 1/5] [erts|esock] Socket address encoding Various length related fixes and changes to socket address encoding. OTP-18020 --- erts/emulator/nifs/common/prim_net_nif.c | 6 +- erts/emulator/nifs/common/prim_socket_nif.c | 53 ++++- erts/emulator/nifs/common/socket_int.h | 4 + erts/emulator/nifs/common/socket_util.c | 240 +++++++++++++++++--- erts/emulator/nifs/common/socket_util.h | 2 +- 5 files changed, 252 insertions(+), 53 deletions(-) diff --git a/erts/emulator/nifs/common/prim_net_nif.c b/erts/emulator/nifs/common/prim_net_nif.c index 37d01c9be5..d7c00d96ed 100644 --- a/erts/emulator/nifs/common/prim_net_nif.c +++ b/erts/emulator/nifs/common/prim_net_nif.c @@ -4189,11 +4189,7 @@ ERL_NIF_TERM encode_sockaddr(ErlNifEnv* env, struct sockaddr* sa) ERL_NIF_TERM esa; if (sa != NULL) { - - unsigned int sz = sizeof(ESockAddress); - - esock_encode_sockaddr(env, (ESockAddress*) sa, sz, &esa); - + esock_encode_sockaddr(env, (ESockAddress*) sa, -1, &esa); } else { esa = esock_atom_undefined; } diff --git a/erts/emulator/nifs/common/prim_socket_nif.c b/erts/emulator/nifs/common/prim_socket_nif.c index b4dea1418d..dce01beee6 100644 --- a/erts/emulator/nifs/common/prim_socket_nif.c +++ b/erts/emulator/nifs/common/prim_socket_nif.c @@ -13053,13 +13053,28 @@ ERL_NIF_TERM esock_sockname(ErlNifEnv* env, if (! IS_OPEN(descP->readState)) return esock_make_error(env, atom_closed); + SSDBG( descP, + ("SOCKET", "esock_sockname {%d} -> open - try get sockname\r\n", + descP->sock) ); + sys_memzero((char*) saP, sz); if (sock_name(descP->sock, (struct sockaddr*) saP, &sz) < 0) { return esock_make_error_errno(env, sock_errno()); } else { ERL_NIF_TERM esa; + SSDBG( descP, + ("SOCKET", "esock_sockname {%d} -> " + "got sockname - try decode\r\n", + descP->sock) ); + esock_encode_sockaddr(env, saP, sz, &esa); + + SSDBG( descP, + ("SOCKET", "esock_sockname {%d} -> decoded: " + "\r\n %T\r\n", + descP->sock, esa) ); + return esock_make_ok2(env, esa); } } @@ -13131,14 +13146,29 @@ ERL_NIF_TERM esock_peername(ErlNifEnv* env, if (! IS_OPEN(descP->readState)) return esock_make_error(env, atom_closed); + SSDBG( descP, + ("SOCKET", "esock_peername {%d} -> open - try get peername\r\n", + descP->sock) ); + sys_memzero((char*) saP, sz); if (sock_peer(descP->sock, (struct sockaddr*) saP, &sz) < 0) { - return esock_make_error_errno(env, sock_errno()); + return esock_make_error_errno(env, sock_errno()); } else { - ERL_NIF_TERM esa; + ERL_NIF_TERM esa; - esock_encode_sockaddr(env, saP, sz, &esa); - return esock_make_ok2(env, esa); + SSDBG( descP, + ("SOCKET", "esock_peername {%d} -> " + "got peername - try decode\r\n", + descP->sock) ); + + esock_encode_sockaddr(env, saP, sz, &esa); + + SSDBG( descP, + ("SOCKET", "esock_peername {%d} -> decoded: " + "\r\n %T\r\n", + descP->sock, esa) ); + + return esock_make_ok2(env, esa); } } #endif // #ifndef __WIN32__ @@ -14088,9 +14118,8 @@ ERL_NIF_TERM encode_ioctl_ifraddr(ErlNifEnv* env, struct sockaddr* addrP) { ERL_NIF_TERM eaddr; - unsigned int sz = sizeof(ESockAddress); - esock_encode_sockaddr(env, (ESockAddress*) addrP, sz, &eaddr); + esock_encode_sockaddr(env, (ESockAddress*) addrP, -1, &eaddr); SSDBG( descP, ("SOCKET", "encode_ioctl_ifraddr -> done with" "\r\n Sock Addr: %T" @@ -14334,17 +14363,19 @@ ERL_NIF_TERM encode_ioctl_ifreq_sockaddr(ErlNifEnv* env, struct sockaddr* sa) ERL_NIF_TERM esa; if (sa != NULL) { - unsigned int sz = sizeof(ESockAddress); - esock_encode_sockaddr(env, (ESockAddress*) sa, sz, &esa); - + esock_encode_sockaddr(env, (ESockAddress*) sa, -1, &esa); + } else { - esa = esock_atom_undefined; + + esa = esock_atom_undefined; + } return esa; } + /* The ifreq structure *always* contain a name * and *one* other element. The second element * depend on the ioctl request. @@ -17069,7 +17100,7 @@ BOOLEAN_T esock_cmsg_encode_recverr(ErlNifEnv *env, if (have_offender) { esock_encode_sockaddr(env, (ESockAddress *)offender, - (CHARP(sock_err) + dataLen ) - CHARP(offender), + (CHARP(sock_err) + dataLen) - CHARP(offender), &eSockAddr); } else { eSockAddr = esock_atom_undefined; diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h index 821d8babe1..4193f676b9 100644 --- a/erts/emulator/nifs/common/socket_int.h +++ b/erts/emulator/nifs/common/socket_int.h @@ -129,6 +129,10 @@ typedef union { struct sockaddr_ll ll; #endif +#if defined(AF_LINK) + struct sockaddr_dl dl; +#endif + /* Max size sockaddr on system */ struct sockaddr_storage ss; diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index d0954c195b..744cf02161 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -124,7 +124,9 @@ static void make_sockaddr_ll(ErlNifEnv* env, ERL_NIF_TERM addr, ERL_NIF_TERM* sa); #endif - +#ifdef HAS_AF_LOCAL +static SOCKLEN_T sa_local_length(int l, struct sockaddr_un* sa); +#endif /* *** esock_get_bool_from_map *** @@ -380,21 +382,32 @@ BOOLEAN_T esock_decode_sockaddr(ErlNifEnv* env, * packet - sockaddr_ll: protocol, ifindex, hatype, pkttype, addr * unspec - sockaddr: addr * (int) - sockaddr: addr + * + * An address length > 0 means the caller knows the length, and we use it. + * An address length of '-1' means the caller don't know, which + * in turn mean that "we" has to calculate. + * + * sys/socket.h: + * __SOCKADDR_ALLTYPES */ +#define SALEN(L, SZ) (((L) > 0) ? (L) : (SZ)) + extern void esock_encode_sockaddr(ErlNifEnv* env, ESockAddress* sockAddrP, - SOCKLEN_T addrLen, + int addrLen, ERL_NIF_TERM* eSockAddr) { - int family; + int family; + SOCKLEN_T len; // Sanity check - if (addrLen < (char *)&sockAddrP->sa.sa_data - (char *)sockAddrP) { - // We got crap, cannot even know the address family - esock_encode_sockaddr_broken(env, &sockAddrP->sa, addrLen, eSockAddr); - return; + if ((addrLen > 0) && + (addrLen < (char *)&sockAddrP->sa.sa_data - (char *)sockAddrP)) { + // We got crap, cannot even know the address family + esock_encode_sockaddr_broken(env, &sockAddrP->sa, addrLen, eSockAddr); + return; } family = sockAddrP->ss.ss_family; @@ -405,70 +418,142 @@ void esock_encode_sockaddr(ErlNifEnv* env, switch (family) { case AF_INET: - esock_encode_sockaddr_in(env, &sockAddrP->in4, addrLen, eSockAddr); - break; + len = SALEN(addrLen, sizeof(struct sockaddr_in)); + esock_encode_sockaddr_in(env, &sockAddrP->in4, len, eSockAddr); + break; #if defined(HAVE_IN6) && defined(AF_INET6) case AF_INET6: - esock_encode_sockaddr_in6(env, &sockAddrP->in6, addrLen, eSockAddr); - break; + len = SALEN(addrLen, sizeof(struct sockaddr_in6)); + esock_encode_sockaddr_in6(env, &sockAddrP->in6, len, eSockAddr); + break; #endif #ifdef HAS_AF_LOCAL case AF_LOCAL: - esock_encode_sockaddr_un(env, &sockAddrP->un, addrLen, eSockAddr); - break; + len = sa_local_length(addrLen, &sockAddrP->un); + esock_encode_sockaddr_un(env, &sockAddrP->un, len, eSockAddr); + break; #endif #ifdef AF_UNSPEC case AF_UNSPEC: - esock_encode_sockaddr_native(env, &sockAddrP->sa, - addrLen, esock_atom_unspec, eSockAddr); - break; + len = SALEN(addrLen, 0); + esock_encode_sockaddr_native(env, + &sockAddrP->sa, len, + esock_atom_unspec, + eSockAddr); + break; #endif #if defined(HAVE_NETPACKET_PACKET_H) case AF_PACKET: - esock_encode_sockaddr_ll(env, &sockAddrP->ll, addrLen, eSockAddr); - break; + len = SALEN(addrLen, sizeof(struct sockaddr_ll)); + esock_encode_sockaddr_ll(env, &sockAddrP->ll, len, eSockAddr); + break; #endif #if defined(AF_IMPLINK) case AF_IMPLINK: - esock_encode_sockaddr_native(env, &sockAddrP->sa, - addrLen, esock_atom_implink, eSockAddr); + len = SALEN(addrLen, 0); + esock_encode_sockaddr_native(env, + &sockAddrP->sa, len, + esock_atom_implink, + eSockAddr); break; #endif #if defined(AF_PUP) case AF_PUP: - esock_encode_sockaddr_native(env, &sockAddrP->sa, - addrLen, esock_atom_pup, eSockAddr); - break; + len = SALEN(addrLen, 0); + esock_encode_sockaddr_native(env, + &sockAddrP->sa, len, + esock_atom_pup, + eSockAddr); + break; #endif #if defined(AF_CHAOS) case AF_CHAOS: - esock_encode_sockaddr_native(env, &sockAddrP->sa, - addrLen, esock_atom_chaos, eSockAddr); - break; + len = SALEN(addrLen, 0); + esock_encode_sockaddr_native(env, + &sockAddrP->sa, len, + esock_atom_chaos, + eSockAddr); + break; #endif #if defined(AF_LINK) case AF_LINK: - esock_encode_sockaddr_native(env, &sockAddrP->sa, - addrLen, esock_atom_link, eSockAddr); + /* + * macOS (Darwin Kernel Version 21.4.0): + * ------------------------------------- + * struct sockaddr_dl { + * u_char sdl_len; // Total length of sockaddr + * u_char sdl_family; // AF_LINK + * u_short sdl_index; // if != 0, system given index for interface + * u_char sdl_type; // interface type + * u_char sdl_nlen; // interface name length, no trailing 0 reqd. + * u_char sdl_alen; // link level address length + * u_char sdl_slen; // link layer selector length + * char sdl_data[12]; // minimum work area, can be larger; + * // contains both if name and ll address + * #ifndef __APPLE__ + * // For TokenRing + * u_short sdl_rcf; // source routing control + * u_short sdl_route[16]; // source routing information + * #endif + * }; + * + * FreeBSD (12.2-RELEASE-p14): + * --------------------------- + * struct sockaddr_dl { + * u_char sdl_len; // Total length of sockaddr + * u_char sdl_family; // AF_LINK + * u_short sdl_index; // if != 0, + * // system given index for interface + * u_char sdl_type; // interface type + * u_char sdl_nlen; // interface name length, no trailing 0 reqd + * u_char sdl_alen; // link level address length + * u_char sdl_slen; // link layer selector length + * char sdl_data[46]; // minimum work area, can be larger; + * // contains both if name and ll address + * }; + */ + // len = SALEN(addrLen, sizeof(struct sockaddr_dl)); + len = SALEN(addrLen, sockAddrP->dl.sdl_len); + esock_encode_sockaddr_dl(env, &sockAddrP->dl, + len, esock_atom_link, eSockAddr); break; #endif default: - esock_encode_sockaddr_native(env, &sockAddrP->sa, - addrLen, MKI(env, family), eSockAddr); - break; + len = SALEN(addrLen, 0); + esock_encode_sockaddr_native(env, + &sockAddrP->sa, len, + MKI(env, family), + eSockAddr); + break; } } +#ifdef HAS_AF_LOCAL +static +SOCKLEN_T sa_local_length(int l, struct sockaddr_un* sa) +{ + if (l > 0) { + return ((SOCKLEN_T) l); + } else { +#if defined(SUN_LEN) + return SUN_LEN(sa); +#else + return (offsetof(struct sockaddr_un, sun_path) + strlen(sa->sun_path) + 1); +#endif + } +} +#endif + extern void esock_encode_hwsockaddr(ErlNifEnv* env, @@ -657,7 +742,7 @@ void esock_encode_sockaddr_in(ErlNifEnv* env, "\r\n addr size: %d" "\r\n", addrLen, sizeof(struct sockaddr_in)) ); esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP, - addrLen, MKI(env, AF_INET), eSockAddr); + addrLen, esock_atom_inet, eSockAddr); } } @@ -797,7 +882,7 @@ void esock_encode_sockaddr_in6(ErlNifEnv* env, } else { esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP, - addrLen, MKI(env, AF_INET6), eSockAddr); + addrLen, esock_atom_inet6, eSockAddr); } } #endif @@ -925,7 +1010,7 @@ void esock_encode_sockaddr_un(ErlNifEnv* env, } } else { esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP, - addrLen, MKI(env, AF_LOCAL), eSockAddr); + addrLen, esock_atom_local, eSockAddr); } } #endif @@ -982,7 +1067,71 @@ void esock_encode_sockaddr_ll(ErlNifEnv* env, } else { esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP, - addrLen, MKI(env, AF_PACKET), eSockAddr); + addrLen, esock_atom_packet, eSockAddr); + } +} +#endif + + + +/* +++ esock_encode_sockaddr_dl +++ + * + * Encode a LINK address - sockaddr_dl (link-level layer). In erlang it's + * represented as a map, which has a specific set of attributes + * (beside the mandatory family attribute, which is "inherited" from + * the "sockaddr" type): + * + * The length field (sdl_len) has already been used, so we don't use it + * in *this* function. + * + * index: non_neg_integer() + * type: non_neg_integer() + * nlen: non_neg_integer() (name length) + * alen: non_neg_integer() (address length) + * slen: non_neg_integer() (sector length) + * data: binary() + */ + +#if defined(AF_LINK) +extern +void esock_encode_sockaddr_dl(ErlNifEnv* env, + struct sockaddr_dl* sockAddrP, + SOCKLEN_T addrLen, + ERL_NIF_TERM* eSockAddr) +{ + ERL_NIF_TERM eindex, etype, enlen, ealen, eslen, edata; + SOCKLEN_T dlen; + + /* There is a minumum length (defined by the size of the data field) */ + if (addrLen >= sizeof(struct sockaddr_dl)) { + + /* index - if != 0, system given index for interface */ + eindex = MKUI(env, sockAddrP->dl.sdl_index); + + /* type - interface type */ + etype = MKUI(env, sockAddrP->dl.sdl_type); + + /* nlen - interface name length, no trailing 0 reqd. */ + enlen = MKUI(env, sockAddrP->dl.sdl_nlen); + + /* alen - link level address length */ + ealen = MKUI(env, sockAddrP->dl.sdl_alen); + + /* slen - ink layer selector length */ + eslen = MKUI(env, sockAddrP->dl.sdl_slen); + + /* data - minimum work area, can be larger; * + * contains both if name and ll address */ + dlen = addrLen - (CHARP(sockAddrP->dl.sdl_data)) - CHARP(sockAddrP)); + edata = esock_make_new_binary(env, &sockAddrP->dl.sdl_data, dlen); + + make_sockaddr_dl(env, + eindex, etype, enlen, ealen, eslen, edata, + eSockAddr); + + } else { + esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP, + addrLen, esock_atom_link, eSockAddr); } } #endif @@ -1853,7 +2002,7 @@ BOOLEAN_T esock_decode_sockaddr_native(ErlNifEnv* env, -/* Encode as #{family := integer(), addr := binary()} +/* Encode as #{family := atom() | integer(), addr := binary()} * assuming at least the ->family field can be accessed * and hence at least 0 bytes of address */ @@ -1880,6 +2029,25 @@ void esock_encode_sockaddr_native(ErlNifEnv* env, } } + +/* Encode as #{family := atom() | integer(), addr := undefined} + * assuming at least the ->family field can be accessed + * and the rest is unknown. + */ +static +void esock_encode_sockaddr_undef(ErlNifEnv* env, + ERL_NIF_TERM eFamily, + ERL_NIF_TERM* eSockAddr) +{ + ERL_NIF_TERM keys[] = {esock_atom_family, esock_atom_addr}; + ERL_NIF_TERM vals[] = {eFamily, esock_atom_undefined}; + size_t numKeys = NUM(keys); + + ESOCK_ASSERT( numKeys == NUM(vals) ); + ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, eSockAddr) ); +} + + /* Encode as a raw binary() regarding the whole address * structure as a blob */ diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h index 0a2febf4dd..2533ee145a 100644 --- a/erts/emulator/nifs/common/socket_util.h +++ b/erts/emulator/nifs/common/socket_util.h @@ -75,7 +75,7 @@ BOOLEAN_T esock_decode_sockaddr(ErlNifEnv* env, extern void esock_encode_sockaddr(ErlNifEnv* env, ESockAddress* sockAddrP, - SOCKLEN_T addrLen, + int addrLen, ERL_NIF_TERM* eSockAddr); extern void esock_encode_hwsockaddr(ErlNifEnv* env, -- 2.34.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor