forked from u-root/u-root
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ping.go
115 lines (101 loc) · 2.85 KB
/
ping.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 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.
// Send icmp packets to a server to test network connectivity.
//
// Synopsis:
// ping [-hV] [-c COUNT] [-i INTERVAL] [-s PACKETSIZE] [-w DEADLINE] DESTINATION
//
// Options:
// -6: use ipv6 (ip6:ipv6-icmp)
// -s: data size (default: 64)
// -c: # iterations, 0 to run forever (default)
// -i: interval in milliseconds (default: 1000)
// -V: version
// -w: wait time in milliseconds (default: 100)
// -h: help
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"time"
)
var (
net6 = flag.Bool("6", false, "use ipv4 (means ip4:icmp) or 6 (ip6:ipv6-icmp)")
packetSize = flag.Int("s", 64, "Data size")
iter = flag.Int64("c", 0, "# iterations")
intv = flag.Int("i", 1000, "interval in milliseconds")
version = flag.Bool("V", false, "version")
wtf = flag.Int("w", 100, "wait time in milliseconds")
help = flag.Bool("h", false, "help")
)
func usage() {
fmt.Fprintf(os.Stdout, "ping [-hV] [-c count] [-i interval] [-s packetsize] [-w deadline] destination\n")
os.Exit(0)
}
func showversion() {
fmt.Fprintf(os.Stdout, "ping utility, Uroot version\n")
os.Exit(0)
}
func optwithoutparam() {
if *version {
showversion()
}
// if we reach this point, invalid or help (-h) gets the same result
usage()
}
func beatifulLatency(before time.Time) (latency string) {
now := float64(time.Since(before).Nanoseconds())
switch {
case now > 1e6:
latency = fmt.Sprintf("%.2f ms", now/1e6)
case now > 1e3:
latency = fmt.Sprintf("%.2f µ", now/1e3)
default:
latency = fmt.Sprintf("%v ns", now)
}
return latency
}
func main() {
flag.Parse()
// options without parameters (right now just: -hV)
if flag.NArg() < 1 {
optwithoutparam()
}
netname := "ip4:icmp"
interval := time.Duration(*intv)
waitFor := time.Duration(*wtf) * time.Millisecond
host := flag.Args()[0]
// todo: just figure out if it's an ip6 address and go from there.
if *net6 {
netname = "ip6:ipv6-icmp"
}
msg := make([]byte, *packetSize)
// ping needs to run forever, except if '*iter' is not zero
var i int64
for i = 1; *iter == 0 || i < *iter; i++ {
c, err := net.Dial(netname, host)
if err != nil {
log.Fatalf("net.Dial(%v %v) failed: %v", netname, host, err)
}
c.SetDeadline(time.Now().Add(waitFor))
defer c.Close()
msg[0] = byte(i)
if _, err := c.Write(msg[:]); err != nil {
log.Printf("Write failed: %v", err)
} else {
before := time.Now()
c.SetDeadline(time.Now().Add(waitFor))
if amt, err := c.Read(msg[:]); err == nil {
latency := beatifulLatency(before)
log.Printf("%d bytes from %v: icmp_seq=%v, time=%v", amt, host, i, latency)
} else {
log.Printf("Read failed: %v", err)
}
}
time.Sleep(time.Millisecond * interval)
}
}