Skip to content

Instantly share code, notes, and snippets.

@shun159
Last active November 26, 2019 13:24
Show Gist options
  • Save shun159/4378c0fbb9870be5a1bc2cdecd72d8f4 to your computer and use it in GitHub Desktop.
Save shun159/4378c0fbb9870be5a1bc2cdecd72d8f4 to your computer and use it in GitHub Desktop.
内容はテキトーなんで許してちょんまげ
-module(bridge).
-export([start/2]).
-define(SIOCGIFINDEX, 16#8933).
-define(ETH_P_ALL, 16#0300).
start(Iface1, Iface2) ->
S1 = bind(Iface1),
S2 = bind(Iface2),
spawn(fun() -> loop(S1, S2) end),
spawn(fun() -> loop(S2, S1) end).
loop(Src, Dst) ->
case socket:recv(Src) of
{error, _} ->
loop(Src, Dst);
{ok, Pkt} ->
_ = socket:send(Dst, Pkt),
loop(Src, Dst)
end.
%% private functions
bind(Iface) ->
{ok, S} = socket:open(packet, raw, {raw, ?ETH_P_ALL}),
{ok, 0} = socket:bind(S, sockaddr_ll(ifindex_of(S, Iface))),
S.
ifindex_of(S, Iface) ->
{ok, Return} = socket:ioctl(S, ?SIOCGIFINDEX, ifreq(Iface)),
<<_Ifname:16/bytes, Ifr:32/native, _/binary>> = Return,
Ifr.
sockaddr_ll(Ifr) ->
#{
family => packet,
protocol => 0,
ifindex => Ifr,
hatype => 0,
pkttype => 0,
halen => 0,
addr => <<0:64>>
}.
ifreq(Dev) ->
list_to_binary(
[
Dev,
<<0:((15*8) - (length(Dev)*8)), 0:8, 0:128>>
]
).
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 7f50372532..8874125618 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -232,7 +232,7 @@ endif
OPSYS=@OPSYS@
sol2CFLAGS=
-linuxCFLAGS=
+linuxCFLAGS=-Wall -g
darwinCFLAGS=-DDARWIN
noopsysCFLAGS=
OPSYSCFLAGS=$($(OPSYS)CFLAGS)
diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h
index 4161775a04..63fec2b5e3 100644
--- a/erts/emulator/nifs/common/socket_int.h
+++ b/erts/emulator/nifs/common/socket_int.h
@@ -54,6 +54,7 @@
#else /* !__WIN32__ */
+#include <netpacket/packet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef HAVE_SYS_UN_H
@@ -82,6 +83,9 @@ typedef union {
struct sockaddr_un un;
#endif
+ /* Link-Layer sockaddr */
+ struct sockaddr_ll ll;
+
} ESockAddress;
@@ -303,7 +307,12 @@ typedef unsigned int BOOLEAN_T;
GLOBAL_ATOM_DEF(user_timeout); \
GLOBAL_ATOM_DEF(use_ext_recvinfo); \
GLOBAL_ATOM_DEF(use_min_mtu); \
- GLOBAL_ATOM_DEF(v6only);
+ GLOBAL_ATOM_DEF(v6only); \
+ GLOBAL_ATOM_DEF(protocol); \
+ GLOBAL_ATOM_DEF(hatype); \
+ GLOBAL_ATOM_DEF(pkttype); \
+ GLOBAL_ATOM_DEF(halen); \
+ GLOBAL_ATOM_DEF(packet);
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index bbeb8b6cdd..cfa0c7e3b1 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -528,6 +528,7 @@ typedef union {
#define ESOCK_DOMAIN_LOCAL 1
#define ESOCK_DOMAIN_INET 2
#define ESOCK_DOMAIN_INET6 3
+#define ESOCK_DOMAIN_PACKET 4
/* type */
#define ESOCK_TYPE_STREAM 1
@@ -2888,7 +2889,11 @@ static char str_exsend[] = "exsend"; // failed send
GLOBAL_ATOM_DECL(user_timeout); \
GLOBAL_ATOM_DECL(use_ext_recvinfo); \
GLOBAL_ATOM_DECL(use_min_mtu); \
- GLOBAL_ATOM_DECL(v6only);
+ GLOBAL_ATOM_DECL(v6only); \
+ GLOBAL_ATOM_DECL(hatype); \
+ GLOBAL_ATOM_DECL(pkttype); \
+ GLOBAL_ATOM_DECL(halen); \
+ GLOBAL_ATOM_DECL(packet);
/* *** Global error reason atoms *** */
@@ -4740,7 +4745,37 @@ ERL_NIF_TERM esock_supports_local(ErlNifEnv* env)
}
#endif
+static
+ERL_NIF_TERM nif_ioctl(ErlNifEnv* env,
+ int argc,
+ const ERL_NIF_TERM argv[])
+{
+#if defined(__WIN32__)
+ return enif_raise_exception(env, MKA(env, "notsup"));
+#else
+ ESockDescriptor* descP;
+ ERL_NIF_TERM sockRef, res;
+ ErlNifBinary arg;
+ int req = 0;
+
+ sockRef = argv[0];
+ if (!enif_get_int(env, argv[1], &req)
+ || !enif_inspect_binary(env, argv[2], &arg)
+ || !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP))
+ return enif_make_badarg(env);
+
+ MLOCK(descP->readMtx);
+
+ if (ioctl(descP->sock, req, arg.data) < 0)
+ res = esock_make_error_errno(env, sock_errno());
+ res = enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_binary(env, &arg));
+
+ MUNLOCK(descP->readMtx);
+
+ return res;
+#endif // if defined(__WIN32__)
+}
/* ----------------------------------------------------------------------
* nif_open
@@ -4766,9 +4801,10 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env,
#if defined(__WIN32__)
return enif_raise_exception(env, MKA(env, "notsup"));
#else
- int edomain, etype, eproto;
+ int edomain, etype;
int domain, type, proto;
char* netns;
+ ERL_NIF_TERM eproto;
ERL_NIF_TERM emap;
ERL_NIF_TERM result;
@@ -4932,7 +4968,7 @@ ERL_NIF_TERM esock_open(ErlNifEnv* env,
/* Does this apply to other types? Such as RAW?
* Also, is this really correct? Should we not wait for bind?
*/
- if (type == SOCK_DGRAM) {
+ if (type == SOCK_DGRAM || type == SOCK_RAW) {
descP->isReadable = TRUE;
descP->isWritable = TRUE;
}
@@ -5145,7 +5181,7 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
*/
if (descP->state != ESOCK_STATE_OPEN)
return esock_make_error(env, atom_exbadstate);
-
+
if ((xres = esock_decode_sockaddr(env, eSockAddr, &sockAddr, &addrLen)) != NULL)
return esock_make_error_str(env, xres);
@@ -17694,6 +17730,12 @@ BOOLEAN_T edomain2domain(int edomain, int* domain)
*domain = AF_INET;
break;
+#if defined(AF_PACKET)
+ case ESOCK_DOMAIN_PACKET:
+ *domain = AF_PACKET;
+ break;
+#endif
+
#if defined(HAVE_IN6) && defined(AF_INET6)
case ESOCK_DOMAIN_INET6:
*domain = AF_INET6;
@@ -17809,7 +17851,7 @@ BOOLEAN_T eproto2proto(ErlNifEnv* env,
*proto = -3;
return FALSE;
}
-
+
if (sz != 2) {
*proto = -4;
return FALSE;
@@ -19575,6 +19617,7 @@ ErlNifFunc esock_funcs[] =
// The proper "socket" interface
// nif_open/1 is (supposed to be) used when we already have a file descriptor
// {"nif_open", 1, nif_open, 0},
+ {"nif_ioctl", 3, nif_ioctl, 0},
{"nif_open", 4, nif_open, 0},
{"nif_bind", 2, nif_bind, 0},
{"nif_connect", 2, nif_connect, 0},
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 54c310ecc7..a065daf9af 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -73,7 +73,14 @@ static char* make_sockaddr_in6(ErlNifEnv* env,
static char* make_sockaddr_un(ErlNifEnv* env,
ERL_NIF_TERM path,
ERL_NIF_TERM* sa);
-
+static char* make_sockaddr_ll(ErlNifEnv* env,
+ ERL_NIF_TERM protocol,
+ ERL_NIF_TERM ifindex,
+ ERL_NIF_TERM hatype,
+ ERL_NIF_TERM pkttype,
+ ERL_NIF_TERM halen,
+ ERL_NIF_TERM addr,
+ ERL_NIF_TERM* sa);
/* +++ esock_encode_iov +++
*
@@ -243,6 +250,11 @@ char* esock_decode_sockaddr(ErlNifEnv* env,
&sockAddrP->in4, addrLen);
break;
+ case AF_PACKET:
+ xres = esock_decode_sockaddr_ll(env, eSockAddr,
+ &sockAddrP->ll, addrLen);
+ break;
+
#if defined(HAVE_IN6) && defined(AF_INET6)
case AF_INET6:
xres = esock_decode_sockaddr_in6(env, eSockAddr,
@@ -298,6 +310,10 @@ char* esock_encode_sockaddr(ErlNifEnv* env,
xres = esock_encode_sockaddr_in4(env, &sockAddrP->in4, addrLen, eSockAddr);
break;
+ case AF_PACKET:
+ xres = esock_encode_sockaddr_ll(env, &sockAddrP->ll, addrLen, eSockAddr);
+ break;
+
#if defined(HAVE_IN6) && defined(AF_INET6)
case AF_INET6:
xres = esock_encode_sockaddr_in6(env, &sockAddrP->in6, addrLen, eSockAddr);
@@ -387,8 +403,6 @@ char* esock_decode_sockaddr_in4(ErlNifEnv* env,
return NULL;
}
-
-
/* +++ esock_encode_sockaddr_in4 +++
*
* Encode a IPv4 socket address - sockaddr_in4. In erlang its represented as
@@ -715,7 +729,145 @@ char* esock_encode_sockaddr_un(ErlNifEnv* env,
}
#endif
+/* +++ esock_decode_sockaddr_ll +++
+ *
+ * Decode a Link-layer address - sockaddr_ll. In erlang its
+ * represented as a map, which has a specific set of attributes
+ * (beside the mandatory family attribute, which is "inherited" from "sockaddr" type):
+ *
+ * protocol :: non_neg_integer()
+ * ifindex :: non_neg_integer()
+ * hatype :: non_neg_integer()
+ * pkttype :: non_neg_integer()
+ * halen :: non_neg_integer()
+ * addr :: <<_:64>>
+ */
+
+extern
+char* esock_decode_sockaddr_ll(ErlNifEnv* env,
+ ERL_NIF_TERM eSockAddr,
+ struct sockaddr_ll* sockAddrP,
+ unsigned int* addrLen)
+{
+ ERL_NIF_TERM eproto, eifindex, ehatype, epkttype, ehalen, eaddr;
+ int ifindex;
+ unsigned int proto, hatype, pkttype, halen;
+ ErlNifBinary addr;
+
+ /* Basic init */
+ sys_memzero((char*) sockAddrP, sizeof(struct sockaddr_ll));
+
+ /* sll_family always AF_PACKET */
+ sockAddrP->sll_family = AF_PACKET;
+
+ /* *** Extract protocol number from map *** */
+ if (!GET_MAP_VAL(env, eSockAddr, esock_atom_protocol, &eproto))
+ return ESOCK_STR_EINVAL;
+
+ /* Decode protocol number */
+ if (!GET_UINT(env, eproto, &proto))
+ return ESOCK_STR_EINVAL;
+
+ sockAddrP->sll_protocol = htons(proto);
+
+ /* *** Extract ifindex from map *** */
+ if (!GET_MAP_VAL(env, eSockAddr, esock_atom_ifindex, &eifindex))
+ return ESOCK_STR_EINVAL;
+
+ /* Decode ifindex */
+ if (!GET_INT(env, eifindex, &ifindex))
+ return ESOCK_STR_EINVAL;
+
+ sockAddrP->sll_ifindex = ifindex;
+
+ /* *** Extract hatype from map *** */
+ if (!GET_MAP_VAL(env, eSockAddr, esock_atom_hatype, &ehatype))
+ return ESOCK_STR_EINVAL;
+
+ /* Decode hatype */
+ if (!GET_UINT(env, ehatype, &hatype))
+ return ESOCK_STR_EINVAL;
+
+ sockAddrP->sll_hatype = hatype;
+
+ /* *** Extract pkttype from map *** */
+ if (!GET_MAP_VAL(env, eSockAddr, esock_atom_pkttype, &epkttype))
+ return ESOCK_STR_EINVAL;
+
+ /* Decode pkttype */
+ if (!GET_UINT(env, epkttype, &pkttype))
+ return ESOCK_STR_EINVAL;
+
+ sockAddrP->sll_pkttype = pkttype;
+
+ /* *** Extract halen from map *** */
+ if (!GET_MAP_VAL(env, eSockAddr, esock_atom_halen, &ehalen))
+ return ESOCK_STR_EINVAL;
+
+ /* Decode halen */
+ if (!GET_UINT(env, ehalen, &halen))
+ return ESOCK_STR_EINVAL;
+
+ sockAddrP->sll_halen = halen;
+
+ /* *** Extract addr from map *** */
+ if (!GET_MAP_VAL(env, eSockAddr, esock_atom_addr, &eaddr))
+ return ESOCK_STR_EINVAL;
+
+ /* Get the addr */
+ if (!GET_BIN(env, eaddr, &addr))
+ return ESOCK_STR_EINVAL;
+
+ sys_memcpy(sockAddrP->sll_addr, addr.data, addr.size);
+ *addrLen = sizeof(struct sockaddr_ll);
+
+ return NULL;
+}
+
+extern
+char* esock_encode_sockaddr_ll(ErlNifEnv* env,
+ struct sockaddr_ll* sockAddrP,
+ unsigned int addrLen,
+ ERL_NIF_TERM* eSockAddr)
+{
+ ERL_NIF_TERM eProto, eIfindex, eHatype, ePkttype, eHalen, eAddr;
+ char* xres;
+
+ if (addrLen >= sizeof(struct sockaddr_ll)) {
+ /* The protocol */
+ eProto = MKI(env, sockAddrP->sll_protocol);
+
+ /* The ifindex */
+ eIfindex = MKI(env, sockAddrP->sll_ifindex);
+
+ /* The hatype */
+ eHatype = MKI(env, sockAddrP->sll_pkttype);
+
+ /* The pkttype */
+ ePkttype = MKI(env, sockAddrP->sll_pkttype);
+
+ /* The halen */
+ eHalen = MKI(env, sockAddrP->sll_halen);
+
+ /* The addr */
+ eAddr = MKBIN(env, &(sockAddrP->sll_addr));
+
+ /* And finally construct the ll_sockaddr record */
+ xres = make_sockaddr_ll(env,
+ eProto,
+ eIfindex,
+ eHatype,
+ ePkttype,
+ eHalen,
+ eAddr,
+ eSockAddr);
+ } else {
+ *eSockAddr = esock_atom_undefined;
+ xres = ESOCK_STR_EINVAL;
+ }
+ return xres;
+}
/* +++ esock_decode_ip4_address +++
*
@@ -932,8 +1084,6 @@ char* esock_encode_ip6_address(ErlNifEnv* env,
}
#endif
-
-
/* +++ esock_encode_timeval +++
*
* Encode a timeval struct into its erlang form, a map with two fields:
@@ -1049,6 +1199,9 @@ char* esock_decode_domain(ErlNifEnv* env,
*domain = AF_UNIX;
#endif
+ } else if (COMPARE(esock_atom_packet, eDomain) == 0) {
+ *domain = AF_PACKET;
+
} else {
*domain = -1;
xres = ESOCK_STR_EAFNOSUPPORT;
@@ -1092,6 +1245,10 @@ char* esock_encode_domain(ErlNifEnv* env,
break;
#endif
+ case AF_PACKET:
+ *eDomain = esock_atom_packet;
+ break;
+
default:
*eDomain = esock_atom_undefined; // Just in case
xres = ESOCK_STR_EAFNOSUPPORT;
@@ -1697,3 +1854,34 @@ char* make_sockaddr_un(ErlNifEnv* env,
}
+/* Construct the Link Layer socket address */
+static
+char* make_sockaddr_ll(ErlNifEnv* env,
+ ERL_NIF_TERM protocol,
+ ERL_NIF_TERM ifindex,
+ ERL_NIF_TERM hatype,
+ ERL_NIF_TERM pkttype,
+ ERL_NIF_TERM halen,
+ ERL_NIF_TERM addr,
+ ERL_NIF_TERM* sa)
+{
+ ERL_NIF_TERM keys[] = {esock_atom_protocol,
+ esock_atom_ifindex,
+ esock_atom_hatype,
+ esock_atom_pkttype,
+ esock_atom_halen,
+ esock_atom_addr};
+ ERL_NIF_TERM vals[] = {protocol, ifindex, hatype, pkttype, halen, addr};
+
+ unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM);
+ unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM);
+
+ ESOCK_ASSERT( (numKeys == numVals) );
+
+ if (!MKMA(env, keys, vals, numKeys, sa)) {
+ *sa = esock_atom_undefined;
+ return ESOCK_STR_EINVAL;
+ } else {
+ return NULL;
+ }
+}
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index 2688a920c4..57da3f522c 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -104,6 +104,18 @@ char* esock_encode_sockaddr_un(ErlNifEnv* env,
ERL_NIF_TERM* eSockAddr);
#endif
+extern
+char* esock_decode_sockaddr_ll(ErlNifEnv* env,
+ ERL_NIF_TERM eSockAddr,
+ struct sockaddr_ll* sockAddrP,
+ unsigned int* addrLen);
+
+extern
+char* esock_encode_sockaddr_ll(ErlNifEnv* env,
+ struct sockaddr_ll* sockAddrP,
+ unsigned int addrLen,
+ ERL_NIF_TERM* eSockAddr);
+
extern
char* esock_decode_ip4_address(ErlNifEnv* env,
ERL_NIF_TERM eAddr,
@@ -124,6 +136,12 @@ char* esock_encode_ip6_address(ErlNifEnv* env,
ERL_NIF_TERM* eAddr);
#endif
+extern
+char* esock_decode_ll_address(ErlNifEnv* env,
+ ERL_NIF_TERM eAddr,
+ unsigned int halen,
+ unsigned char* llAddrP);
+
extern char* esock_encode_timeval(ErlNifEnv* env,
struct timeval* timeP,
ERL_NIF_TERM* eTime);
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index 73a0bd4f72..38a41307b7 100644
Binary files a/erts/preloaded/ebin/socket.beam and b/erts/preloaded/ebin/socket.beam differ
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index 07e720c44d..99bbe13139 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -37,6 +37,7 @@
-export([
open/2, open/3, open/4,
+ ioctl/3,
bind/2, bind/3,
connect/2, connect/3,
listen/1, listen/2,
@@ -320,9 +321,16 @@
addr := any | loopback | ip6_address(),
flowinfo := in6_flow_info(),
scope_id := in6_scope_id()}.
+-type sockaddr_ll() :: #{family := packet,
+ ifindex := integer(),
+ hatype := non_neg_integer(),
+ pkttype := non_neg_integer(),
+ halen := non_neg_integer(),
+ addr := binary()}.
-type sockaddr() :: sockaddr_in4() |
sockaddr_in6() |
- sockaddr_un().
+ sockaddr_un() |
+ sockaddr_ll().
-define(SOCKADDR_IN4_DEFAULTS(A), #{port => 0,
addr => A}).
@@ -334,6 +342,13 @@
scope_id => 0}).
-define(SOCKADDR_IN6_DEFAULTS, ?SOCKADDR_IN6_DEFAULTS(any)).
-define(SOCKADDR_IN6_DEFAULT(A), (?SOCKADDR_IN6_DEFAULTS(A))#{family => inet6}).
+-define(SOCKADDR_LL_DEFAULTS(Ifindex), #{ifindex => IfIndex,
+ hatype => 0,
+ pkttype => 0,
+ halen => 0,
+ addr => <<0:64>>}).
+-define(SOCKADDR_LL_DEFAULTS, ?SOCKADDR_LL_DEFAULTS(0)).
+-define(SOCKADDR_LL_DEFAULT(Ifindex), (?SOCKADDR_LL_DEFAULTS(Ifindex))#{family => packet}).
%% otp - This option is internal to our (OTP) implementation.
%% socket - The socket layer (SOL_SOCKET).
@@ -641,10 +656,11 @@
%%
-define(SOCKET_TAG, '$socket').
--define(SOCKET_DOMAIN_LOCAL, 1).
--define(SOCKET_DOMAIN_UNIX, ?SOCKET_DOMAIN_LOCAL).
--define(SOCKET_DOMAIN_INET, 2).
--define(SOCKET_DOMAIN_INET6, 3).
+-define(SOCKET_DOMAIN_LOCAL, 1).
+-define(SOCKET_DOMAIN_UNIX, ?SOCKET_DOMAIN_LOCAL).
+-define(SOCKET_DOMAIN_INET, 2).
+-define(SOCKET_DOMAIN_INET6, 3).
+-define(SOCKET_DOMAIN_PACKET, 4).
-define(SOCKET_TYPE_STREAM, 1).
-define(SOCKET_TYPE_DGRAM, 2).
@@ -1143,6 +1159,15 @@ open(Domain, Type, Protocol, Extra) when is_map(Extra) ->
end.
+-spec(ioctl(Socket, Request, Arg) -> {ok, binary()} | {error, Reason} when
+ Socket :: socket(),
+ Request :: 0..16#ffff,
+ Arg :: binary(),
+ Reason :: term()).
+ioctl(#socket{ref = SockRef}, Request, Arg)
+ when is_integer(Request),
+ is_binary(Arg) ->
+ nif_ioctl(SockRef, Request, Arg).
%% ===========================================================================
%%
@@ -1305,7 +1330,7 @@ connect(_Socket, _SockAddr, Timeout)
when (is_integer(Timeout) andalso (Timeout =< 0)) ->
{error, timeout};
connect(#socket{ref = SockRef}, #{family := Fam} = SockAddr, Timeout)
- when ((Fam =:= inet) orelse (Fam =:= inet6) orelse (Fam =:= local)) andalso
+ when ((Fam =:= inet) orelse (Fam =:= inet6) orelse (Fam =:= local)) orelse (Fam =:= packet) andalso
((Timeout =:= nowait) orelse
(Timeout =:= infinity) orelse is_integer(Timeout)) ->
TS = timestamp(Timeout),
@@ -2702,6 +2727,7 @@ cancel(#socket{ref = SockRef}, ?SELECT_INFO(Tag, Ref)) ->
enc_domain(local) -> ?SOCKET_DOMAIN_LOCAL;
enc_domain(inet) -> ?SOCKET_DOMAIN_INET;
enc_domain(inet6) -> ?SOCKET_DOMAIN_INET6;
+enc_domain(packet) -> ?SOCKET_DOMAIN_PACKET;
enc_domain(Domain) -> invalid_domain(Domain).
%% -spec enc_type(Domain, Type) -> non_neg_integer() when
@@ -3763,6 +3789,10 @@ ensure_sockaddr(#{family := local, path := Path} = SockAddr)
(byte_size(Path) > 0) andalso
(byte_size(Path) =< 255) ->
SockAddr;
+ensure_sockaddr(#{family := packet, addr := Addr} = SockAddr)
+ when is_binary(Addr),
+ byte_size(Addr) == 8 ->
+ SockAddr;
ensure_sockaddr(_SockAddr) ->
einval().
@@ -3987,3 +4017,5 @@ nif_sockname(_Ref) ->
nif_peername(_Ref) ->
erlang:nif_error(undef).
+nif_ioctl(_SRef, _Req, _Args) ->
+ erlang:nif_error(undef).
SIOCGIFINDEX = 16#8933,
Dev = "enx0022cfab0ec2",
Body = list_to_binary([Dev, <<0:((15*8) - (length(Dev)*8)), 0:8, 0:128>>]),
{ok, Sock1} = socket:open(packet, raw, {raw, 16#300}),
{ok, Return} = socket:ioctl(Sock1, SIOCGIFINDEX, Body),
<<_Ifname:16/bytes, Ifr:32/native, _/binary>> = Return,
SockAddrLl = #{family => packet, protocol => 0, ifindex => Ifr, hatype => 0, pkttype => 0, halen => 0, addr => <<0:64>>},
{ok, 0} = socket:bind(Sock1, SockAddrLl),
{ok, <<Dhost:6/bytes, Shost:6/bytes, Type:16, Payload/binary>>} = socket:recv(Sock1).
@shun159
Copy link
Author

shun159 commented Nov 26, 2019

travelping/gen_socketをお使いください。申し訳ありませんが、私自身あまりErlangでEtherフレームを触るモチベーションがないのです…

@kikuyuta
Copy link

ありがとうございます。無理をもうしてすみませんでした。

@shun159
Copy link
Author

shun159 commented Nov 26, 2019

いえいえ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment