Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Erlang interface to low level socket operations
Erlang C Other
tree: eba4ec34ed

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
c_src
ebin
src
.gitignore
Makefile
README
rebar
rebar.config

README

procket is an Erlang interface for requesting socket features that
usually require superuser privileges.

procket uses the experimental NIF interface first introduced in Erlang
R13B03.


EXPORTS

listen(Port, Options) -> {ok, FD} | {error, Reason} | {error, {Reason, Description}}

    Types   Port = 0..65535
            Options = [Opts]
            Opts = {pipe, Path} | {protocol, Protocol} | {ip, IPAddress} |
                    {progname, string()}
            Protocol = tcp | udp
            IPAddress = string() | tuple()
            Reason = posix()
            Description = string()


COMPILING

Try running: make


SETUID vs SUDO

The procket executable needs root privileges. Either allow your user to
run procket using sudo or copy procket to somewhere owned by root and
make it setuid.

* for sudo

    sudo visudo
    youruser ALL=NOPASSWD: /path/to/procket/priv/procket

* to make it setuid

    sudo cp priv/procket /usr/local/bin
    sudo chown root:yourgroup /usr/local/bin/procket
    sudo chmod 750 /usr/local/bin/procket
    sudo chmod u+s /usr/local/bin/procket


USING IT

$ erl -pa ebin
Erlang R13B03 (erts-5.7.4) [source] [rq:1] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4  (abort with ^G)
1> {ok, FD} = procket:listen(53, [{progname, "sudo priv/procket"},{protocol, udp}]).
{ok,9}
2> {ok, S} = gen_udp:open(53, [{fd,FD}]).
{ok,#Port<0.929>}
3> receive M -> M end.
{udp,#Port<0.929>,{127,0,0,1},47483,"hello\n"}
4> 

$ nc -u localhost 53
hello
^C


EXAMPLE

echo is a sample client using procket.

$ erl -pa ebin
1> echo:start(53, [{progname, "sudo priv/procket"}, {protocol, tcp}]).

ICMP Ping:

1> icmp:ping("www.yahoo.com").

Sniff the network:

1> {ok, S} = procket:listen(0, [{protocol, 16#0008}, {type, raw}, {family, packet}]).
{ok,12}
2> procket:recvfrom(S, 2048).   
{ok,<<0,21,175,89,8,38,0,3,82,3,39,36,8,0,69,0,0,52,242,
          0,0,0,52,6,188,81,209,...>>}
3> {ok, S1} = gen_udp:open(0, [binary, {fd, S}, {active, false}]).
4> gen_udp:recv(S1, 2048).

HOW IT WORKS

procket creates a local domain socket and spawns a small setuid binary
(or runs it under sudo). The executable opens a socket, drops privs and
passes the file descriptor back to Erlang over the Unix socket.

procket uses libanciallary for passing file descriptors between processes:

    http://www.normalesup.org/~george/comp/libancillary/


TODO

1. Support BPF on BSD for sending/receiving packets

2. Examples/changes to support sending TCP/UDP packets using the raw
   socket interface, using epcap to receive packets

Something went wrong with that request. Please try again.