Skip to content

Commit

Permalink
icmp: 支持指定 ttl、size
Browse files Browse the repository at this point in the history
  • Loading branch information
wzv5 committed Apr 24, 2023
1 parent a12dc42 commit 7b1b99f
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 17 deletions.
10 changes: 10 additions & 0 deletions cmd/pping/cmd/icmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
type icmpFlags struct {
privileged bool
timeout time.Duration
ttl int
size int
}

var icmpflag icmpFlags
Expand All @@ -27,6 +29,8 @@ func addIcmpCommand() {

cmd.Flags().DurationVarP(&icmpflag.timeout, "timeout", "w", time.Second*4, "timeout")
cmd.Flags().BoolVarP(&icmpflag.privileged, "privileged", "p", false, "privileged")
cmd.Flags().IntVarP(&icmpflag.ttl, "ttl", "l", 0, "time to live")
cmd.Flags().IntVarP(&icmpflag.size, "size", "s", 0, "send buffer size")
rootCmd.AddCommand(cmd)
}

Expand All @@ -35,5 +39,11 @@ func runicmp(cmd *cobra.Command, args []string) error {
fmt.Printf("Ping %s:\n", host)
p := ping.NewIcmpPing(host, icmpflag.timeout)
p.Privileged = icmpflag.privileged
if icmpflag.ttl > 0 {
p.TTL = icmpflag.ttl
}
if icmpflag.size > 0 {
p.Size = icmpflag.size
}
return RunPing(p)
}
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,13 @@ github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
15 changes: 13 additions & 2 deletions pkg/ping/icmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type IcmpPing struct {

ip net.IP
Privileged bool
TTL int
Size int
}

func (this *IcmpPing) SetHost(host string) {
Expand All @@ -59,6 +61,7 @@ func (this *IcmpPing) Host() string {
func NewIcmpPing(host string, timeout time.Duration) *IcmpPing {
p := &IcmpPing{
Timeout: timeout,
Size: 32,
}
p.SetHost(host)
return p
Expand Down Expand Up @@ -96,10 +99,17 @@ func (this *IcmpPing) rawping(network string) IPingResult {
}
defer conn.Close()
conn.SetDeadline(time.Now().Add(this.Timeout))
if this.TTL > 0 {
if isipv6 {
conn.IPv6PacketConn().SetHopLimit(this.TTL)
} else {
conn.IPv4PacketConn().SetTTL(this.TTL)
}
}

// 发送
r := rand.New(rand.NewSource(time.Now().UnixNano()))
sendData := make([]byte, 32)
sendData := make([]byte, this.Size)
r.Read(sendData)
id := os.Getpid() & 0xffff
sendMsg := this.getmsg(isipv6, id, 0, sendData)
Expand All @@ -123,7 +133,8 @@ func (this *IcmpPing) rawping(network string) IPingResult {
break
}

recvBytes := make([]byte, 1500)
// 直接分配一个足够大的缓冲区
recvBytes := make([]byte, this.Size+128)
recvSize := 0

for {
Expand Down
38 changes: 28 additions & 10 deletions pkg/ping/icmp_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"math/rand"
"net"
"syscall"
"time"
Expand Down Expand Up @@ -67,13 +68,15 @@ func (this *IcmpPing) ping_rootless(ctx context.Context) IPingResult {
IcmpCloseHandle(handle)
}
}()
r := rand.New(rand.NewSource(time.Now().UnixNano()))
if isipv6 {
handle = Icmp6CreateFile()
if handle == syscall.InvalidHandle {
return this.errorResult(errors.New("IcmpCreateFile failed"))
}
data := make([]byte, 32)
recv := Icmp6SendEcho(handle, ip, data, this.Timeout)
data := make([]byte, this.Size)
r.Read(data)
recv := Icmp6SendEcho(handle, ip, data, this.Timeout, this.TTL)
if recv == nil {
return this.errorResult(errors.New("IcmpSendEcho failed"))
}
Expand All @@ -92,8 +95,9 @@ func (this *IcmpPing) ping_rootless(ctx context.Context) IPingResult {
if handle == syscall.InvalidHandle {
return this.errorResult(errors.New("IcmpCreateFile failed"))
}
data := make([]byte, 32)
recv := IcmpSendEcho(handle, ip, data, this.Timeout)
data := make([]byte, this.Size)
r.Read(data)
recv := IcmpSendEcho(handle, ip, data, this.Timeout, this.TTL)
if recv == nil {
return this.errorResult(errors.New("IcmpSendEcho failed"))
}
Expand Down Expand Up @@ -124,8 +128,14 @@ func IcmpCloseHandle(h syscall.Handle) uintptr {
return ret
}

func IcmpSendEcho(handle syscall.Handle, ip net.IP, data []byte, timeout time.Duration) []byte {
buf := make([]byte, 1500)
func IcmpSendEcho(handle syscall.Handle, ip net.IP, data []byte, timeout time.Duration, ttl int) []byte {
buf := make([]byte, (int)(unsafe.Sizeof(icmp_echo_reply{}))+len(data))
var pOptions *ip_option_information
if ttl > 0 {
pOptions = &ip_option_information{
ttl: uint8(ttl),
}
}
n, _, _ := icmpSendEcho2.Call(
uintptr(handle), // icmphandle
0, // event
Expand All @@ -134,7 +144,7 @@ func IcmpSendEcho(handle syscall.Handle, ip net.IP, data []byte, timeout time.Du
uintptr(ipv4ToInt(ip)), // destinationaddress
uintptr(unsafe.Pointer(&data[0])), // requestdata
uintptr(len(data)), // requestsize
0, // requestoptions
uintptr(unsafe.Pointer(pOptions)), // requestoptions
uintptr(unsafe.Pointer(&buf[0])), // replaybuffer
uintptr(len(buf)), // replysize
uintptr(timeout.Milliseconds()), // timeout
Expand All @@ -150,15 +160,21 @@ func Icmp6CreateFile() syscall.Handle {
return syscall.Handle(h)
}

func Icmp6SendEcho(handle syscall.Handle, ip net.IP, data []byte, timeout time.Duration) []byte {
func Icmp6SendEcho(handle syscall.Handle, ip net.IP, data []byte, timeout time.Duration, ttl int) []byte {
ip6source := syscall.RawSockaddrInet6{
Family: syscall.AF_INET6,
}
ip6dest := syscall.RawSockaddrInet6{
Family: syscall.AF_INET6,
}
copy(ip6dest.Addr[:], ip)
buf := make([]byte, 1500)
buf := make([]byte, (int)(unsafe.Sizeof(icmpv6_echo_reply{}))+len(data))
var pOptions *ip_option_information
if ttl > 0 {
pOptions = &ip_option_information{
ttl: uint8(ttl),
}
}
n, _, _ := icmp6SendEcho2.Call(
uintptr(handle), // icmphandle
0, // event
Expand All @@ -168,7 +184,7 @@ func Icmp6SendEcho(handle syscall.Handle, ip net.IP, data []byte, timeout time.D
uintptr(unsafe.Pointer(&ip6dest)), // destinationaddress
uintptr(unsafe.Pointer(&data[0])), // requestdata
uintptr(len(data)), // requestsize
0, // requestoptions
uintptr(unsafe.Pointer(pOptions)), // requestoptions
uintptr(unsafe.Pointer(&buf[0])), // replaybuffer
uintptr(len(buf)), // replysize
uintptr(timeout.Milliseconds()), // timeout
Expand All @@ -187,6 +203,8 @@ func icmpStatusToString(status uint32) string {
return "destination host was unreachable"
case 11010:
return "request timed out"
case 11013:
return "time exceeded"
}
return fmt.Sprintf("unknown error (%d)", status)
}
41 changes: 40 additions & 1 deletion test/pping_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package pping_test

import (
"strings"
"testing"
"time"

"github.com/wzv5/pping/pkg/ping"
)

const HOST = "www.baidu.com"
const HOST = "www.microsoft.com"

func TestTls(t *testing.T) {
p := ping.NewTlsPing(HOST, 443, time.Second*1, time.Second*3)
Expand Down Expand Up @@ -52,3 +53,41 @@ func TestIcmp6(t *testing.T) {
t.Fatal(result.Error())
}
}

func TestIcmp_ttl(t *testing.T) {
p := ping.NewIcmpPing(HOST, time.Second*1)
p.TTL = 1
result := p.Ping()
if !strings.Contains(result.Error().Error(), "exceeded") {
t.Fatal(result.Error())
}
}

func TestIcmp_ttl_root(t *testing.T) {
p := ping.NewIcmpPing(HOST, time.Second*1)
p.Privileged = true
p.TTL = 1
result := p.Ping()
if !strings.Contains(result.Error().Error(), "exceeded") {
t.Fatal(result.Error())
}
}

func TestIcmp_size(t *testing.T) {
p := ping.NewIcmpPing(HOST, time.Second*1)
p.Size = 60000
result := p.Ping()
if result.Error() != nil {
t.Fatal(result.Error())
}
}

func TestIcmp_size_root(t *testing.T) {
p := ping.NewIcmpPing(HOST, time.Second*1)
p.Privileged = true
p.Size = 60000
result := p.Ping()
if result.Error() != nil {
t.Fatal(result.Error())
}
}

0 comments on commit 7b1b99f

Please sign in to comment.