Permalink
Browse files

Add an NIF setsockopt for promiscous mode

Add an interface to setsockopt(). procket:setsockopt/4 can be used for
putting the interface into promiscous mode.  Add packet:promiscuous/2
convenience function to do that:

packet:promiscuous(Socket, Ifindex)
  • Loading branch information...
1 parent 9613464 commit 3649b5cb23e1a2242cfc36e691a93436aa122944 @msantos committed Jun 24, 2010
Showing with 54 additions and 4 deletions.
  1. +32 −1 c_src/procket.c
  2. +18 −2 src/packet.erl
  3. +4 −1 src/procket.erl
View
@@ -266,6 +266,36 @@ nif_ioctl(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
}
+/* 0: int socket descriptor, 1: int level,
+ * 2: int optname, 3: void *optval
+ */
+ static ERL_NIF_TERM
+nif_setsockopt(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ int s = -1;
+ int level = 0;
+ int name = 0;
+ ErlNifBinary val;
+
+ if (!enif_get_int(env, argv[0], &s))
+ return enif_make_badarg(env);
+
+ if (!enif_get_int(env, argv[1], &level))
+ return enif_make_badarg(env);
+
+ if (!enif_get_int(env, argv[2], &name))
+ return enif_make_badarg(env);
+
+ if (!enif_inspect_binary(env, argv[3], &val))
+ return enif_make_badarg(env);
+
+ if (setsockopt(s, level, name, (void *)val.data, val.size) < 0)
+ return error_tuple(env, strerror(errno));
+
+ return atom_ok;
+}
+
+
static ERL_NIF_TERM
error_tuple(ErlNifEnv *env, char *err)
{
@@ -293,7 +323,8 @@ static ErlNifFunc nif_funcs[] = {
{"bind", 2, nif_bind},
{"recvfrom", 2, nif_recvfrom},
{"ioctl", 3, nif_ioctl},
- {"sendto", 4, nif_sendto}
+ {"sendto", 4, nif_sendto},
+ {"setsockopt", 4, nif_setsockopt}
};
ERL_NIF_INIT(procket, nif_funcs, load, NULL, NULL, NULL)
View
@@ -33,12 +33,19 @@
socket/0,
makesum/1,
ifindex/2,
+ promiscuous/2,
send/3
]).
-define(SIOCGIFINDEX, 16#8933).
-define(PF_PACKET, 17).
+% Options for promiscuous mode
+-define(SOL_PACKET, 263).
+-define(PACKET_ADD_MEMBERSHIP, 1).
+-define(PACKET_DROP_MEMBERSHIP, 2).
+-define(PACKET_MR_PROMISC, 1).
+
socket() ->
procket:listen(0, [{protocol, 16#0008}, {type, raw}, {family, packet}]).
@@ -50,12 +57,12 @@ ifindex(Socket, Dev) ->
])),
Ifr.
-send(S, Interface, Packet) ->
+send(S, Ifindex, Packet) ->
procket:sendto(S, Packet, 0,
<<
?PF_PACKET:16/native, % sll_family: PF_PACKET
0:16, % sll_protocol: Physical layer protocol
- Interface:32/native, % sll_ifindex: Interface number
+ Ifindex:32/native, % sll_ifindex: Interface number
0:16, % sll_hatype: Header type
0:8, % sll_pkttype: Packet type
0:8, % sll_halen: address length
@@ -69,6 +76,15 @@ send(S, Interface, Packet) ->
0:8 % sll_addr[8]: physical layer address
>>).
+promiscuous(Socket, Ifindex) ->
+ % struct packet_mreq
+ procket:setsockopt(Socket, ?SOL_PACKET, ?PACKET_ADD_MEMBERSHIP, <<
+ Ifindex:32/native, % mr_ifindex: interface index
+ ?PACKET_MR_PROMISC:16/native, % mr_type: action
+ 0:16, % mr_alen: address length
+ 0:64 % mr_address[8]: physical layer address
+ >>).
+
makesum(Hdr) -> 16#FFFF - checksum(Hdr).
checksum(Hdr) ->
View
@@ -33,7 +33,7 @@
-export([
init/0,open/1,poll/1,close/2,listen/1,listen/2,
recvfrom/2,sendto/4,bind/2,
- ioctl/3
+ ioctl/3,setsockopt/4
]).
-export([make_args/2,progname/0]).
@@ -67,6 +67,9 @@ ioctl(_,_,_) ->
sendto(_,_,_,_) ->
erlang:error(not_implemented).
+setsockopt(_,_,_,_) ->
+ erlang:error(not_implemented).
+
listen(Port) ->
listen(Port, []).
listen(Port, Options) when is_integer(Port), is_list(Options) ->

0 comments on commit 3649b5c

Please sign in to comment.