Giter Club home page Giter Club logo

gen_icmp's Introduction

Package Version Hex Docs

gen_icmp aspires to be a simple interface for using ICMP and ICMPv6 sockets in Erlang, just like gen_tcp and gen_udp do for their protocol types; incidentally messing up Google searches for whomever someday writes a proper gen_icmp module.

gen_icmp uses procket to get a raw socket and abuses gen_udp for the socket handling. gen_icmp should work on Linux and BSDs.

For a simple example of sending a ping, also see:

https://github.com/msantos/procket/blob/master/src/icmp.erl

EXPORTS

open() -> {ok, Socket}
open(SocketOptions) -> {ok, Socket}
open(RawOptions, SocketOptions) -> {ok, Socket}

    Types   Socket = pid()
            RawOptions = [ RawOption ]
            RawOption = options()
            SocketOptions = SocketOpt
            SocketOpt = [ {active, true} | {active, once} |
                {active, false} | inet | inet6 ]

    By default, the ICMP socket is opened in {active,false} mode. No
    packets will be received by the socket. setopts/2 can be used
    to place the socket in {active,true} mode.

    See the procket README for the raw socket options and for
    instructions on setting up the setuid helper.

    gen_icmp first attempts to natively open the socket and falls
    back to forking the setuid helper program if beam does not have
    the appropriate privileges.  Privileges to open a raw socket can
    be given by, for example, running as root or, on Linux, granting
    the CAP_NET_RAW capability to beam:

        setcap cap_net_raw=ep /usr/local/lib/erlang/erts-5.8.3/bin/beam.smp

    Only the owning process will receive ICMP packets (see
    controlling_process/2 to change the owner). The process owning the
    raw socket will receive all ICMP packets sent to the host.

    Messages sent to the controlling process are:

    {icmp, Socket, Address, TTL, Packet}

    Where:

        * Socket is the pid of the gen_icmp process

        * Address is a tuple representing the IPv4 or IPv6 source address

        * TTL is the IP TTL
            * IPv4: TTL taken from the IP header
            * IPv6: the socket's hop limit returned from
              getsockopt(IPV6_UNICAST_HOPS) (this is not the packet's
              TTL, it is the socket's max TTL)

        * Packet is the complete ICMP packet including the ICMP headers

close(Socket) -> ok | {error, Reason}

    Types   Socket = pid()
            Reason = posix()

    Close the ICMP socket.

send(Socket, Address, Packet) -> ok | {error, Reason}

    Types   Socket = pid()
            Address = tuple()
            Packet = binary()
            Reason = not_owner | posix()

    Like the gen_udp and gen_tcp modules, any process can send ICMP
    packets but only the owner will receive the responses.

recv(Socket, Length) -> {ok, {Address, Packet}} | {error, Reason}
recv(Socket, Length, Timeout) -> {ok, {Address, Packet}} | {error, Reason}

    Types   Socket = socket()
            Length = int()
            Address = ip_address()
            Packet = [char()] | binary()
            Timeout = int() | infinity
            Reason = not_owner | posix()

    This function receives a packet from a socket in passive mode.

    The optional Timeout parameter specifies a timeout in
    milliseconds. The default value is infinity.

controlling_process(Socket, Pid) -> ok

    Types   Socket = pid()
            Pid = pid()

    Change the process owning the socket. Allows another process to
    receive the ICMP responses.

setopts(Socket, Options) ->

    Types   Socket = pid()
            Options = list()

    For options, see the inet man page. Simply calls inet:setopts/2
    on the gen_udp socket.

    setopts/2 can be used to toggle the socket between passive and
    active mode:

        {ok, Socket} = gen_icmp:open(), % socket is {active,false}
        ok = gen_icmp:setopts(Socket, [{active, true}]),
        % do stuff with the socket
        ok = gen_icmp:setopts(Socket, [{active, false}]).

ping(Host) -> Responses
ping(Host, Options) -> Responses
ping(Socket, Hosts, Options) -> Responses

    Types   Socket = pid()
            Host = Address | Hostname | Hosts
            Address = ReplyAddr = tuple()
            Hostname = string()
            Hosts = [ tuple() | string() ]
            Options = [ Option ]
            Option = {id, Id} | {sequence, Sequence} | {timeout, Timeout} | {data, Data} |
                {timestamp, boolean()} | {ttl, TTL} | {filter, Filter} | inet | inet6
            Id = uint16()
            Sequence = uint16()
            Timeout = non_neg_integer() | infinity
            TTL = uint8()
            Data = binary()
            Filter = binary()
            Responses = [ Response ]
            Response = {ok, Host, Address, ReplyAddr, Details, Payload}
                | {error, ICMPError, Host, Address, ReplyAddr, Details, Payload}
                | {error, Error, Host, Address}
            Details = {Id, Sequence, TTL, Elapsed}
            Elapsed = int() | undefined
            Payload = binary()
            ICMPError = unreach_host | timxceed_intrans
            Error = timeout | inet:posix()

    ping/1 is a convenience function to send a single ping
    packet. The argument to ping/1 can be either a hostname or a
    list of hostnames.

    To prevent the process mailbox from being flooded with ICMP
    messages, ping/3 will put the socket into {active,false} mode
    after completing.

    The ping/3 function blocks until either an ICMP ECHO REPLY is
    received from all hosts or Timeout is reached.

    Id and sequence are used to differentiate ping responses. Usually,
    the sequence is incremented for each ping in one run.

    A list of responses is returned. If the ping was successful,
    the elapsed time in milliseconds is included (calculated by
    subtracting the current time from the time we sent in the ICMP
    ECHO packet and returned to us in the ICMP ECHOREPLY payload)
    where:

        Host: the provided hostname

        Address: the resolved IPv4 or IPv6 network address represented
        as a 4 or 8-tuple used in the ICMP echo request

        ReplyAddr: the IPv4 or IPv6 network address originating the
        ICMP echo reply

    The timeout is set for all ICMP packets and is set after all
    packets have been sent out.

    ping/1 and ping/2 open and close an ICMP socket for the user. For
    best performance, ping/3 should be used instead, with the socket
    being maintained between runs.

    By default only one address per hostname is pinged. To
    enable pinging all addresses per hostname pass {multi, true}
    to options.

    A ping payload contains an 8 byte timestamp in microseconds. When
    creating a custom payload, the first 8 bytes of the ICMP echo
    reply payload will be used for calculating the elapsed time. To
    disable this behaviour, use the option {timestamp,false} (the
    elapsed time in the return value will be set to 0).

    The timeout defaults to 5 seconds.

    ICMPv6 sockets can restrict which ICMPv6 types are received by the
    socket using the filter option.  The filter argument is a binary
    generated using the icmp6_filter functions described below.

    The default filter allows: ICMP6_ECHO_REPLY, ICMP6_DST_UNREACH,
    ICMP6_PACKET_TOO_BIG, ICMP6_TIME_EXCEEDED and ICMP6_PARAM_PROB.
    Note: ping/3 does not restore the original filter on the socket.

echo(Id, Sequence) -> Packet

    Types   Id = uint16()
            Sequence = uint16()
            Packet = binary()

    Creates an ICMP echo packet with an 8 byte timestamp and a
    payload consisting of ASCII 32 to 79.

echo(Id, Sequence, Payload) -> Packet

    Types   Id = uint16()
            Sequence = uint16()
            Payload = binary()
            Packet = binary()

    Creates an ICMP echo packet with the results of erlang:now() used
    as the timestamp and a user specified payload (which should pad the
    packet to 64 bytes).


packet(Header, Payload) -> Packet

    Types   Header = [ #icmp{} | Options ]
            Options = [ Opts ]
            Opts = [{type, Type} | {code, Code} | {id, Id} | {sequence, Sequence} |
                        {gateway, Gateway} | {mtu, MTU} | {pointer, Pointer} |
                        {ts_orig, TS_orig} | {ts_recv, TS_recv} | {ts_tx, TS_tx} ]
            Type = uint8() | ICMP_type
            Code = uint8() | ICMP_code
            ICMP_type = echoreply | dest_unreach | source_quench | redirect | echo |
                time_exceeded | parameterprob | timestamp | timestampreply | info_request |
                info_reply | address | addressreply
            ICMP_code = unreach_net | unreach_host | unreach_protocol | unreach_port |
                unreach_needfrag | unreach_srcfail | redirect_net | redirect_host |
                redirect_tosnet | redirect_toshost | timxceed_intrans | timxceed_reass
            Id = uint16()
            Sequence = uint16()
            Payload = binary()
            Packet = binary()

    Convenience function for creating arbitrary ICMP packets. This
    function will calculate the ICMP checksum and insert it into the
    packet.

filter(Socket) -> {ok, Filter} | unsupported
filter(Socket, Filter) -> ok | unsupported

    Types   Socket = pid()
            Filter = binary()

    Sets or retrieves an ICMPv6 filter on a socket. For ICMPv4
    sockets, the atom 'unsupported' is returned.

    Filters can be generated by using the icmp6_filter functions.

icmp6_filter_setblockall() -> binary()
icmp6_filter_setpassall() -> binary()
icmp6_filter_setpass(Type, Filter) -> binary()
icmp6_filter_setblock(Type, Filter) -> binary()
icmp6_filter_willpass(Type, Filter) -> true | false
icmp6_filter_willblock(Type, Filter) -> true | false

    Types   Type = icmp_type()
            Filter = binary()

    Generate a ICMPv6 filter that can be set on a socket using
    filter/2.

    For example, to generate a filter that allowed only
    ICMP6_ECHO_REPLY messages:

        {ok, Socket} = gen_icmp:open([inet6]),
        Filter = gen_icmp:icmp6_filter_setpass(echo_reply,
                    gen_icmp:icmp6_filter_setblockall()),
        ok = gen_icmp:filter(Socket, Filter).

Traceroute

tracert is an Erlang traceroute implementation built using gen_icmp.

host(Host) -> Path
host(Host, Options) -> Path
host(Socket, Host, Options) -> Path

    Types   Socket = pid()
            Host = Address | Hostname
            Address = tuple()
            Hostname = string()
            Options = [ Option ]
            Option = {protocol, Protocol}
                | {max_hops, uint()}
                | {timeout, uint()}
                | {setuid, bool()}
                | {saddr, Address}
                | {sport, uint16()}
            Protocol = icmp | udp
            Path = [ {Address, MicroSeconds, {Protocol, binary()}
                | timeout ]

    Perform a traceroute to a destination. ICMP and UDP probes are
    supported. ICMP probes are the default.

    max_hops is the maximum TTL (default: 30)

    Set the time in milliseconds to wait for a response using the
    timeout option (default: 1000 ms).  WARNING: if the response
    arrives after the timeout, tracert will insert spurious entries
    into the path.

    tracert will not spawn the setuid helper if the {setuid, false}
    option is used. In this case, beam must either be running as
    root or have the cap_net_raw privileges under Linux.

    The {sport, Port} option sets the initial source port for UDP
    probes. The port will be incremented by 1 for each subsequent
    probe (default: random high port).  For ICMP probes, the ICMP
    ID field will be set to this value.

    The return value is an ordered list of tuples:

        Address: the source address responding to the probe

        MicroSeconds: time elapsed between the probe and receiving
        the response

        Protocol: icmp or udp

        Protocol data: a binary representing the received packet
        contents

path(Path) -> Reasons

    Types   Path = [ {Address, MicroSeconds, {Protocol, binary()} ]
            Reasons = [ {Address, MicroSeconds, Reason} ]
            Reason = ICMP | UDP | timeout
            ICMP = timxceed_intrans | echo_reply | ...
            UDP = unreach_port | ...

    Convert the list of binaries returned by host/1,2,3 to atoms
    representing the ICMP response codes and UDP errors.

COMPILING

rebar3 do clean, compile, ct

Also see the README for procket for additional setup (the procket executable needs superuser privileges).

EXAMPLE

Simple ping interface

1> gen_icmp:ping("www.google.com").
[{ok,"www.google.com",
     {173,194,64,99},
     {173,194,64,99},
     18411,0,50,
     <<" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO">>}]

2> gen_icmp:ping(["www.google.com", {192,168,213,4}, "193.180.168.20", {192,0,32,10}]).
[{error,timeout,"193.180.168.20",{193,180,168,20}},
 {error,unreach_host,
        {192,168,213,4},
        {192,168,213,4},
        {192,168,213,54},
        {18411,2,undefined},
        <<69,0,0,84,0,0,64,0,64,1,15,29,192,168,213,54,192,168,
          213,4,...>>},
 {ok,{192,0,32,10},
     {192,0,32,10},
     {192,0,32,10},
     {18411,1,103},
     <<" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO">>},
 {ok,"www.google.com",
     {173,194,77,99},
     {173,194,77,99},
     {18411,0,50},
     <<" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO">>}]

IPv6

1> gen_icmp:ping("google.com", [inet6]).
[{ok,"google.com",
     {9735,63664,16395,2054,0,0,0,4098},
     {9735,63664,16395,2054,0,0,0,4098},
     {18411,0,64,62},
     <<" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO">>}]

2> tracert:host("google.com", [inet6]).

Re-using the ICMP ping socket

Keeping the ICMP socket around between runs is more efficient:

{ok, Socket} = gen_icmp:open(),
P1 = gen_icmp:ping(Socket, [{10,1,1,1}, "www.google.com"], []),
P2 = gen_icmp:ping(Socket, [{10,2,2,2}, "www.yahoo.com"], []),
gen_icmp:close(Socket).

Working with ICMP sockets

{ok, Socket} = gen_icmp:open().

% By default, the ICMP socket is in passive mode
ok = gen_icmp:setopts(Socket, [{active, true}]),

% ICMP host unreachable, empty payload (should contain an IPv4 header
% and the first 8 bytes of the packet data)
Packet = gen_icmp:packet([{type, 3}, {code, 0}], <<0:160, 0:64>>).

gen_icmp:send(Socket, {127,0,0,1}, Packet),

% Put the socket back into passive mode
ok = gen_icmp:setopts(Socket, [{active, false}]).

Setting Up an ICMP Ping Tunnel

ptun is an example of using gen_icmp to tunnel TCP over ICMP.

To compile ptun:

make eg

Host1 (1.1.1.1) listens for TCP on port 8787 and forwards the data over ICMP:

erl -noshell -pa ebin deps/*/ebin -eval 'ptun:server({2,2,2,2},8787)' -s erlang halt

Host2 (2.2.2.2) receives ICMP echo requests and opens a TCP connection to 127.0.0.1:22:

erl -noshell -pa ebin deps/*/ebin -eval 'ptun:client({1,1,1,1},22)' -s erlang halt

To use the proxy on host1:

ssh -p 8787 127.0.0.1

Traceroute

  • ICMP traceroute

      1> Path = tracert:host({8,8,8,8}).
      [{{216,239,46,191},
       36149,
       {icmp,<<11,0,111,150,0,0,0,0,69,128,0,84,0,0,64,...>>}},
       {{216,239,47,189},
       51459,
       {icmp,<<11,0,111,150,0,0,0,0,69,128,0,84,0,0,...>>}},
       {{8,8,8,8},
       34946,
       {icmp,<<0,0,170,0,219,104,0,0,32,33,34,35,36,...>>}}]
    
      2> tracert:path(Path).
      [{{216,239,46,191},62815,timxceed_intrans},
       {{216,239,47,189},44244,timxceed_intrans},
       {{8,8,8,8},34825,echoreply}]
    
  • UDP traceroute

      1> Path = tracert:host({8,8,8,8}, [{protocol, udp}]).
    
  • IPv6 traceroute

      1> Path = tracert:host("google.com", [inet6]).
    

TODO

  • tests: do not depend on list order

  • handle rfc 4884 (Extended ICMP to Support Multi-Part Messages)

  • handle ICMP router renumbering messages

  • IPv6: handle socket ancillary data (RFC 3542)

    • retrieve the packet TTL rather than using the IPV6_UNICAST_HOPS

gen_icmp's People

Contributors

gleber avatar idubrov avatar msantos avatar superbobry avatar tnt-dev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gen_icmp's Issues

ipv6 works on linux, but not on mac

heya,
i'm trying to use this to send ipv6 icmp ping requests using

gen_icmp:ping("dns.google", [inet6])

this works perfectly fine on linux, but errors with enoprotoopt on mac -- both machines are in the same network and have a valid IPv6 address assigned to them

what would be the steps to get this working on macos, or what information would you need to figure out why it's not working?

Trouble running via elixir releases

Hello!

I have no idea if this problem is related to this project at all but the error mentions it so I figured I'd start here. I'm running an elixir app via releases and I'm seeing some issues with another library I wrote that uses gen_icmp - error I'm seeing is:

{:error, {:undef, [{:procket, :socket, [:inet, :raw, :icmp], []}, {:gen_icmp, :init, 1, [file: '/app/deps/gen_icmp/src/gen_icmp.erl', line: 233]}, {:gen_server, :init_it, 2, [file: 'gen_server.erl', line: 374]}, {:gen_server, :init_it, 6, [file: 'gen_server.erl', line: 342]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}]}}

I wrote a very thin wrapper around this that I'm currently using: https://github.com/silverp1/elixir-ping

Just wondering if anything in the error happens to jump out at you, I'm a bit stumped. Thank you!

Sending packets via specific network interfaces

Hi,

This is not an issue but a feature inquiry (unless it already exists and I've missed it).

I need to send packets (mainly for ping and traceroute) through different interfaces and I couldn't find the way do do it. On the command line with the linux ping, you can set the option -I <interface> or -I <address> and the packets are sent through the interface with the proper source address regardless of the routing table.

  1. Is there a way to do this
  2. Is there a way to set the source address
  3. If not, do you have plans to integrate it ?

Thanks for the great work anyway : this lib is very useful.
Cheers
Maurycy

Compilation fails on macOS (arm64)

Hello,

I'm using gen_icmp in an Elixir project. The compilation fails on macOS.

I've cloned to test it, and sure enough when I run rebar3 compile it fails with the following error:

/Applications/Xcode.app/Contents/Developer/usr/bin/make -f /Users/tester/clones/gen_icmp/_build/default/lib/procket/c_src/Makefile.ancillary
cc -c -Wall -fPIC -g -O2  -DNDEBUG -DSPARE_SEND_FDS -DSPARE_RECV_FDS fd_send.c
cc -c -Wall -fPIC -g -O2  -DNDEBUG -DSPARE_SEND_FDS -DSPARE_RECV_FDS fd_recv.c
cc -m64  -g -Wall -o /Users/tester/clones/gen_icmp/_build/default/lib/procket/priv/procket -L/Users/tester/clones/gen_icmp/_build/default/lib/procket/c_src procket_cmd.c -lancillary
ld: warning: ignoring file /Users/tester/clones/gen_icmp/_build/default/lib/procket/c_src/libancillary.a, building for macOS-arm64 but attempting to link with file built for unknown-unsupported file format ( 0x21 0x3C 0x61 0x72 0x63 0x68 0x3E 0x0A 0x2F 0x20 0x20 0x20 0x20 0x20 0x20 0x20 )
Undefined symbols for architecture arm64:
  "_ancil_send_fd", referenced from:
      _procket_pipe in procket_cmd-930b73.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [cmd] Error 1
===> Hook for compile failed!

Since in Elixir land one can override dependencies, I've managed to get it to compile inside my project by using the latest version of procket with {:procket, git: "https://github.com/msantos/procket", override: true}, but it would be nice if gen_icmp could compile without additional workarounds.

Cheers!

Build on OS X

Hi

Currently building procket is broken on at least OS X, this is resolved in the procket master branch.

Procket has not been released with the new rebar3 commit which solves the OS X building.

Would it be possible to either push a new version of procket or to switch to procket master?

Also, to send ICMP on OS X, i need to start the Erlang VM with root privileges, is there a workaround for this?

Works on ubuntu v20 (x86_64); timeouts on custom ARM 32-bit Linux distro.

Hello,

Linux ubuntu 5.4.0-70-generic #78-Ubuntu SMP Fri Mar 19 13:29:52 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux:

iex(2)> :gen_icmp.ping('192.168.1.1', [ttl: 1])
[
  {:ok, '192.168.1.1', {192, 168, 1, 1}, {192, 168, 1, 1}, {15829, 0, 255, 7},
   " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO"}
]

On: Linux smartslot 5.4.66nmc4-dirty #10 SMP PREEMPT Tue Mar 23 05:06:09 PDT 2021 armv7l GNU/Linux:
iex(1)> :gen_icmp.ping('127.0.0.1', [])
[{:error, :timeout, '127.0.0.1', {127, 0, 0, 1}}]

Needless to mention that a standard command line ping works perfectly fine. I am getting timeout in 100% calls. I am not an Erlang expert but wrote few things. I would appreciate any help with debugging this as I do not even know at this stage what might have gone wrong. This is not the only module that involves cross-compilation but this is the only one that works-otherwise. First of all I checked the procket's cross-compile's CFLAGS and LDFLAGS and I haven't noticed anything apparent. Please see below excerpt.

613 ===> Compiling procket
614 make: Entering directory '/mnt/src/agilis_fw/firmware.gvs/deps/lces2/procket/c_src'
615 make -f /mnt/src/agilis_fw/firmware.gvs/deps/lces2/procket/c_src/Makefile.ancillary
616 make[1]: Entering directory '/mnt/src/agilis_fw/firmware.gvs/deps/lces2/procket/c_src'
617 arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=vfpv4-d16 -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-sec>
618 arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=vfpv4-d16 -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-sec>
619 ar cr libancillary.a fd_send.o fd_recv.o
620 ranlib libancillary.a
621 make[1]: Leaving directory '/mnt/src/agilis_fw/firmware.gvs/deps/lces2/procket/c_src'
622 echo "CFLAGS =  -O2 -pipe -g -feliminate-unused-debug-types  -fPIC -O2 -I  -I  -I/home/motyl/.local/share/nerves/artifacts/nerves_system_poky-portable->
623 CFLAGS =  -O2 -pipe -g -feliminate-unused-debug-types  -fPIC -O2 -I  -I  -I/home/motyl/.local/share/nerves/artifacts/nerves_system_poky-portable-3.1.3->
624 echo "LDFLAGS = -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -fstack-protector-strong -Wl,-z,relro,-z,now -shared -L/home/motyl/.local/share/nerves/art>
625 LDFLAGS = -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -fstack-protector-strong -Wl,-z,relro,-z,now -shared -L/home/motyl/.local/share/nerves/artifacts>
626 arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=vfpv4-d16 -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-sec>
627 arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=vfpv4-d16 -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-sec>
628 arm-poky-linux-gnueabi-gcc  -march=armv7ve -mthumb -mfpu=vfpv4-d16 -mfloat-abi=hard -fstack-protector-strong  -D_FORTIFY_SOURCE=2 -Wformat -Wformat-sec>
629 make: Leaving directory '/mnt/src/agilis_fw/firmware.gvs/deps/lces2/procket/c_src'

This is probably something silly on my side and I hope to help improving the module's cross-compile build if this would appear to be the case.

Checked with the wireshark and no single ICMP packet is being spit out onto the wire.

With my best wishes
Tomasz Motyl

Running gen_icmp in iex mix project

Hello!

I'am newbie in erlang and elixir. i'am totally misunderstand why :gen_icmp.ping doesnt works in elixir.

elixir@elixir-VirtualBox:~$ uname -a
Linux elixir-VirtualBox 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:16:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

I created test mix project, where i include gen_icmp as dependency

defmodule KV.Mixfile do
  use Mix.Project

  def project do
    [app: :kv,
     version: "0.0.1",
     elixir: "~> 1.0",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type `mix help compile.app` for more information
  def application do
    [applications: [:logger, :gen_icmp]]
  end

  defp deps do
    [{:gen_icmp, git: "https://github.com/msantos/gen_icmp.git"}]
  end
end

then i ran (i'am trying with sudo and without)

sudo mix deps.get
sudo mix deps.compile
sudo mix compile

As i realize, all compiled successfully, because on erlang (but in another folder and with rebar), on same machine all works well.

After that i ran:

elixir@elixir-VirtualBox:~/elixir_test/kv$ iex -S mix
Erlang/OTP 18 [erts-7.0] [source-4d83b58] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :gen_icmp.ping
ping/1    ping/2    ping/3    
iex(1)> :gen_icmp.ping "google.ru"
** (EXIT from #PID<0.95.0>) {:error, :eperm}

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :gen_icmp.ping("google.com")
** (EXIT from #PID<0.100.0>) {:error, :eperm}

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :gen_icmp.ping.("google.com")
** (UndefinedFunctionError) undefined function: :gen_icmp.ping/0
    (gen_icmp) :gen_icmp.ping()

When i'am run this from sudo - it's behave slighty different

elixir@elixir-VirtualBox:~/elixir_test/kv$ sudo iex -S mix
Erlang/OTP 18 [erts-7.0] [source-4d83b58] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.0.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :gen_icmp.ping
ping/1    ping/2    ping/3    
iex(1)> :gen_icmp.ping("ya.ru")
** (FunctionClauseError) no function clause matching in :gen_icmp.ping/3
    (gen_icmp) src/gen_icmp.erl:147: :gen_icmp.ping(#PID<0.97.0>, "ya.ru", [])
    (gen_icmp) src/gen_icmp.erl:143: :gen_icmp.ping/2
iex(1)> :gen_icmp.ping "ya.com"
** (FunctionClauseError) no function clause matching in :gen_icmp.ping/3
    (gen_icmp) src/gen_icmp.erl:147: :gen_icmp.ping(#PID<0.100.0>, "ya.com", [])
    (gen_icmp) src/gen_icmp.erl:143: :gen_icmp.ping/2
iex(1)> 

Please, tell me what's wrong? Thanks!

:gen__icmp.ping crashes on CentOS 7

I'm using :gen_icmp.ping in an Elixir project.

The code works fine when I run it via mix on my laptop, but when I make a release with distillery and run the same code on CentOS7, the line:

:gen_icmp.ping(addr)

crashes the process without any message.

I'm building the release inside a docker centos7 container. But later trying to run it on a physical CentOS 7 server.

how to get the same display as a ping command ?

Hi, Any idea how I could return something like :

$ ping friendpaste.com
PING friendpaste.com (94.23.221.113): 56 data bytes
64 bytes from 94.23.221.113: icmp_seq=0 ttl=54 time=36.183 ms
64 bytes from 94.23.221.113: icmp_seq=1 ttl=54 time=321.526 ms

ie, how can I get the ttl ? and packet size (for the last one I guess the payload lenght is OK) .

get timeout in tracert:host({8,8,8,8}).

Hi, when I track an IP address, I get the below answer : [timeout,timeout,timeout,timeout,timeout,timeout,timeout,
timeout,timeout,timeout,timeout,timeout,timeout,timeout,
timeout,timeout,timeout,timeout,timeout,timeout,timeout,
timeout,timeout,timeout,timeout,timeout,timeout,timeout,
timeout|...]
how i'can fix it ?
thank.

Build fails with current pkt master

Broken by msantos/pkt@41a9907

==> gen_icmp (compile)
Compiled src/icmp_message.erl
Compiled src/icmp6_message.erl
Compiling src/tracert.erl failed:
src/tracert.erl:268: undefined macro 'PF_INET6'
src/tracert.erl:347: undefined macro 'PF_INET6'
src/tracert.erl:58: function handle_call/3 undefined

How to make use of Elapsed value in response

I always get big negative values for Elapsed. Is this fine? How can I make use of it? (like converting it to ms as in ping):

49> gen_icmp:ping(["google.com"]).
[{ok,"google.com",
{216,58,220,14},
{216,58,220,14},
{29619,0,55,-4294971590971590814},
<<" !"#$%&'()+,-./0123456789:;<=>?@abcdefghijk">>}]
50> gen_icmp:ping(["google.com", "google.com", "google.com"]).
[{ok,"google.com",
{216,58,220,14},
{216,58,220,14},
{29619,0,55,-4294971590971590871},
<<" !"#$%&'()
+,-./0123456789:;<=>?@abcdefghijk">>},
{ok,"google.com",
{216,58,220,14},
{216,58,220,14},
{29619,1,55,-4294971590971590871},
<<" !"#$%&'()+,-./0123456789:;<=>?@abcdefghijk">>},
{ok,"google.com",
{216,58,220,14},
{216,58,220,14},
{29619,2,55,-4294971590971590872},
<<" !"#$%&'()
+,-./0123456789:;<=>?@abcdefghijk">>}]

$ ping google.com
PING google.com (216.58.220.14): 56 data bytes
64 bytes from 216.58.220.14: icmp_seq=0 ttl=56 time=87.072 ms
64 bytes from 216.58.220.14: icmp_seq=1 ttl=56 time=89.757 ms
64 bytes from 216.58.220.14: icmp_seq=2 ttl=56 time=90.696 ms
64 bytes from 216.58.220.14: icmp_seq=3 ttl=56 time=89.885 ms
64 bytes from 216.58.220.14: icmp_seq=4 ttl=56 time=89.419 ms
^C
--- google.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 87.072/89.366/90.696/1.221 ms

rebar compile won't work

rebar compile
==> procket (compile)
/usr/bin/ld: cannot find -lancillary
collect2: ld returned 1 exit status
ERROR: cc c_src/procket.o -Lc_src -lancillary -shared -L/usr/local/lib/erlang/lib/erl_interface-3.7.4/lib -lerl_interface -lei -o priv/procket.so failed with error: 1

Match error with [{:error, 'google.com', :nxdomain}]

I'm having this error when my laptop doesn't resolve a domain name.

11:24:32.031 [error] GenServer #PID<0.304.0> terminating
** (MatchError) no match of right hand side value: [{:error, 'google.com', :nxdomain}]
    src/gen_icmp.erl:532: :gen_icmp."-addr_list0/3-lc$^2/1-0-"/2
    src/gen_icmp.erl:514: :gen_icmp.addr_list/4
    src/gen_icmp.erl:176: :gen_icmp.ping/3
    src/gen_icmp.erl:143: :gen_icmp.ping/2
    (nvjorn) lib/nvjorn/workers/icmp.ex:73: Nvjorn.Workers.ICMP.connect/1
    (nvjorn) lib/nvjorn/workers/icmp.ex:58: Nvjorn.Workers.ICMP.handle_call/3
    (stdlib) gen_server.erl:629: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:661: :gen_server.handle_msg/5
Last message: {:check, %Nvjorn.Services.ICMP{failure_count: 0, host: 'google.com', inet: 'inet', name: 'Google'}}
State: :ok

My own code looks like

result = :gen_icmp.ping(item.host, [List.to_atom(item.inet)])

So I don't think it could be an error from my side (although I may be wrong).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.