Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing ICMP ping in Go

Tags:

go

sockets

ping

Is it possible to implement an ICMP ping in Go? The alternative is to fork a 'ping' process, but I'd rather write it in Go.

like image 467
marketer Avatar asked May 30 '10 00:05

marketer


2 Answers

The following code shows how to perform a ping over IPv4 using a raw socket (requires root privs):

package main

import (
    "log"
    "net"
    "os"

    "golang.org/x/net/icmp"
    "golang.org/x/net/ipv4"
)

const targetIP = "8.8.8.8"

func main() {
    c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
    if err != nil {
        log.Fatalf("listen err, %s", err)
    }
    defer c.Close()

    wm := icmp.Message{
        Type: ipv4.ICMPTypeEcho, Code: 0,
        Body: &icmp.Echo{
            ID: os.Getpid() & 0xffff, Seq: 1,
            Data: []byte("HELLO-R-U-THERE"),
        },
    }
    wb, err := wm.Marshal(nil)
    if err != nil {
        log.Fatal(err)
    }
    if _, err := c.WriteTo(wb, &net.IPAddr{IP: net.ParseIP(targetIP)}); err != nil {
        log.Fatalf("WriteTo err, %s", err)
    }

    rb := make([]byte, 1500)
    n, peer, err := c.ReadFrom(rb)
    if err != nil {
        log.Fatal(err)
    }
    rm, err := icmp.ParseMessage(ipv4.ICMPTypeEchoReply.Protocol(), rb[:n])
    if err != nil {
        log.Fatal(err)
    }
    switch rm.Type {
    case ipv4.ICMPTypeEchoReply:
        log.Printf("got reflection from %v", peer)
    default:
        log.Printf("got %+v; want echo reply", rm)
    }
}

Code based on the example found here: https://godoc.org/golang.org/x/net/icmp#PacketConn

In order to ping from Linux as a non-privileged user, see this post

like image 94
IanB Avatar answered Sep 21 '22 22:09

IanB


Currently, the ICMP Echo (Ping) function isn't supported in the Go net package.

There's no support for sending ICMP echo requests. You'd have to add support to package net. ping

like image 26
peterSO Avatar answered Sep 21 '22 22:09

peterSO