Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to listen for ICMP packets?

I'm working on a two part application where one side sends ICMP packets and the other side listens for the ICMP packets and takes action when it receives them. The problem is, I'm not sure how to keep the listener alive indefinitely (just want it sitting there in a loop only taking action when it receives a packet).

Currently, I'm able to use the go-fastping library and can send and receive packets if it's a two way communication (I send it, they respond, I process the remote response). The question is how do I make this asymmetrical?

My attempt at a listener was:

for {
    conn, err := icmp.ListenPacket("ip4:icmp", "192.168.1.8")
    if err != nil {
        fmt.Println(err)
    }
}

but this doesn't work. My logic here was that I want a while true loop to keep the listener alive (in this case that's the for {), then I listen for new packets with ICMP's ListenPacket but I don't seem to be getting anything using this approach.

Any ideas or help would be greatly appreciated. Thanks in advance for your time and assistance.

like image 588
kkirsche Avatar asked Oct 26 '15 12:10

kkirsche


1 Answers

icmp.ListenPacket() creates a *icmp.PacketConn - in other words a listener. You are creating listeners in an infinite loop! Since you are not even closing them, your program will start complaining about too many open files faster than you can say "ping".

Here is an example of a working listener

package main

import (
    "golang.org/x/net/icmp"
    "log"
)

func main() {
    conn, err := icmp.ListenPacket("ip4:icmp", "192.168.0.12")
    if err != nil {
        log.Fatal(err)
    }

    for {
        var msg []byte
        length, sourceIP, err := conn.ReadFrom(msg)
        if err != nil {
            log.Println(err)
            continue
        }

        log.Printf("message = '%s', length = %d, source-ip = %s", string(msg), length, sourceIP)
    }
    _ = conn.Close()
}

This produces:

2015/10/26 10:35:00 message = '', length = 0, source-ip = 192.168.0.7
2015/10/26 10:35:00 message = '', length = 0, source-ip = 192.168.0.25
2015/10/26 10:35:01 message = '', length = 0, source-ip = 192.168.0.7
2015/10/26 10:35:01 message = '', length = 0, source-ip = 192.168.0.25
2015/10/26 10:35:02 message = '', length = 0, source-ip = 192.168.0.7
2015/10/26 10:35:02 message = '', length = 0, source-ip = 192.168.0.25

I was pinging the host from 2 hosts simultaneously.

You can choose to discard the incoming message and other return values if you want.

like image 62
Satyen Rai Avatar answered Oct 07 '22 06:10

Satyen Rai