Golang Implementing the ping command

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// taken from http://golang.org/src/pkg/net/ipraw_test.go

package ping

import (
"bytes"
"errors"
"net"
"os"
"time"
)

const (
icmpv4EchoRequest = 8
icmpv4EchoReply   = 0
icmpv6EchoRequest = 128
icmpv6EchoReply   = 129
)

type icmpMessage struct {
Type     int             // type
Code     int             // code
Checksum int             // checksum
Body     icmpMessageBody // body
}

type icmpMessageBody interface {
Len() int
Marshal() ([]byte, error)
}

//Marshal returns the binary enconding of the ICMP echo request or
//reply message M.
func (M *ICMPMESSAG e) Marshal ([]byte, error) {
b: = []byte{byte (M.type), Byte (M.code), 0, 0}
If m.body! = Nil && M.body.le N ()! = 0 {
  MB, err: = M.body.marshal ()
  if err! = Nil {
   return nil, err
 }
  B = Append (b, mb ...)
}
Switch M.type {
Case icmpv6echorequest, icmpv6echoreply:
  return B, nil
}
CSUMCV: = Len (b) -1//checksum coverage
S: = UInt32 (0)
for I: = 0; i < CSUMCV; i + = 2 {
  s + = UInt32 (b[i+1]) << 8 | UInt32 (B[i])
}
If csumcv&1 = = 0 {
  s + = UInt32 (B[CSUMCV])
}
S = s>>16 + S&0XFFFF
S = s + s>>16
//Place checksum back in header; using ^= avoids the
//assumption the checksum bytes is Z Ero.
B[2] ^= byte (^s & 0xFF)
B[3] ^= byte (^s >> 8)
return B, nil
}

// parseICMPMessage parses b as an ICMP message.
func parseICMPMessage(b []byte) (*icmpMessage, error) {
msglen := len(b)
if msglen < 4 {
  return nil, errors.New("message too short")
}
m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
if msglen > 4 {
  var err error
  switch m.Type {
  case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
   m.Body, err = parseICMPEcho(b[4:])
   if err != nil {
    return nil, err
   }
  }
}
return m, nil
}

// imcpEcho represenets an ICMP echo request or reply message body.
type icmpEcho struct {
ID   int    // identifier
Seq  int    // sequence number
Data []byte // data
}

func (p *icmpEcho) Len() int {
if p == nil {
  return 0
}
return 4 + len(p.Data)
}

// Marshal returns the binary enconding of the ICMP echo request or
// reply message body p.
func (p *icmpEcho) Marshal() ([]byte, error) {
b := make([]byte, 4+len(p.Data))
b[0], b[1] = byte(p.ID>>8), byte(p.ID&0xff)
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq&0xff)
copy(b[4:], p.Data)
return b, nil
}

// parseICMPEcho parses b as an ICMP echo request or reply message body.
func parseICMPEcho(b []byte) (*icmpEcho, error) {
bodylen := len(b)
p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
if bodylen > 4 {
  p.Data = make([]byte, bodylen-4)
  copy(p.Data, b[4:])
}
return p, nil
}

func Ping(address string, timeout int) (alive bool) {
err := Pinger(address, timeout)
alive = err == nil
return
}

func Pinger(address string, timeout int) (err error) {
c, err := net.Dial("ip4:icmp", address)
if err != nil {
  return
}
c.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
defer c.Close()

Typ: = Icmpv4echorequest
XID, xseq: = OS. Getpid () &0XFFFF, 1
WB, err: = (&icmpmessage{
  Type:typ, code:0,
  Body: &icmpecho{
   Id:xid, Seq:xseq,
   data:bytes. Repeat ([]byte ("Go Go Gadget Ping!!!"), 3),
 },
}). Marshal ()
If err! = Nil {
  return
}
If _, err = C.write (WB); Err! = nil {
  return
}
var m *icmpmessage
RB: = Make ([]byte, 20+len (WB)]
for {
  if _, err = C.read (RB); Err! = Nil {
&NBSP;&N Bsp Return
 }
  RB = Ipv4payload (RB)
  if m, err = Parseicmpmessage (RB); Err! = Nil {
   Return
 }
  switch m.type {
  case icmpv4echorequest, Icmpv6echorequest:
   Continue
 }
  Break
}
return
}

func ipv4payload (b []byte) []byte {
If Len (b) < {
  return b
}
Hdrlen: = Int (b[0]&0 x0f) << 2
Return B[hdrlen:]
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.