Skip to content

Commit 07811e5

Browse files
foogodcorny
authored andcommitted
Add ability to change the ICMP ID and seq counter
1 parent bc50d4a commit 07811e5

File tree

3 files changed

+30
-28
lines changed

3 files changed

+30
-28
lines changed

Diff for: pinger.go

+11-9
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,20 @@ const (
1818
ProtocolICMPv6 = 58
1919
)
2020

21-
// sequence number for this process
21+
// default sequence counter for this process
2222
var sequence uint32
2323

2424
// Pinger is a instance for ICMP echo requests
2525
type Pinger struct {
2626
LogUnexpectedPackets bool // increases log verbosity
27+
Id uint16
28+
SequenceCounter *uint32
2729

2830
payload Payload
2931
payloadMu sync.RWMutex
3032

31-
requests map[uint16]request // currently running requests
33+
requests map[uint32]request // currently running requests
3234
mtx sync.RWMutex // lock for the requests map
33-
id uint16
3435
conn4 net.PacketConn
3536
conn6 net.PacketConn
3637
write4 sync.Mutex // lock for conn4.WriteTo
@@ -60,10 +61,11 @@ func New(bind4, bind6 string) (*Pinger, error) {
6061
}
6162

6263
pinger := Pinger{
63-
conn4: conn4,
64-
conn6: conn6,
65-
id: uint16(os.Getpid()),
66-
requests: make(map[uint16]request),
64+
conn4: conn4,
65+
conn6: conn6,
66+
Id: uint16(os.Getpid()),
67+
SequenceCounter: &sequence,
68+
requests: make(map[uint32]request),
6769
}
6870
pinger.SetPayloadSize(56)
6971

@@ -101,9 +103,9 @@ func (pinger *Pinger) close(conn net.PacketConn) {
101103
}
102104
}
103105

104-
func (pinger *Pinger) removeRequest(seq uint16) {
106+
func (pinger *Pinger) removeRequest(idseq uint32) {
105107
pinger.mtx.Lock()
106-
delete(pinger.requests, seq)
108+
delete(pinger.requests, idseq)
107109
pinger.mtx.Unlock()
108110
}
109111

Diff for: receiving.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,14 @@ func (pinger *Pinger) process(body icmp.MessageBody, result error, addr net.IP,
9898
return
9999
}
100100

101-
// check if we sent this
102-
if uint16(echo.ID) != pinger.id {
103-
return
104-
}
101+
idseq := (uint32(uint16(echo.ID)) << 16) | uint32(uint16(echo.Seq))
105102

106103
// search for existing running echo request
107104
pinger.mtx.Lock()
108-
req := pinger.requests[uint16(echo.Seq)]
105+
req := pinger.requests[idseq]
109106
if _, ok := req.(*simpleRequest); ok {
110107
// a simpleRequest is finished on the first reply
111-
delete(pinger.requests, uint16(echo.Seq))
108+
delete(pinger.requests, idseq)
112109
}
113110
pinger.mtx.Unlock()
114111

Diff for: sending.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (pinger *Pinger) Ping(destination *net.IPAddr, timeout time.Duration) (time
4242
func (pinger *Pinger) PingContext(ctx context.Context, destination *net.IPAddr) (time.Duration, error) {
4343
req := simpleRequest{}
4444

45-
seq, err := pinger.sendRequest(destination, &req)
45+
idseq, err := pinger.sendRequest(destination, &req)
4646
if err != nil {
4747
return 0, err
4848
}
@@ -54,7 +54,7 @@ func (pinger *Pinger) PingContext(ctx context.Context, destination *net.IPAddr)
5454
err = req.result
5555
case <-ctx.Done():
5656
// dequeue request
57-
pinger.removeRequest(seq)
57+
pinger.removeRequest(idseq)
5858
err = &timeoutError{}
5959
}
6060

@@ -77,7 +77,7 @@ func (pinger *Pinger) PingMulticast(destination *net.IPAddr, wait time.Duration)
7777
func (pinger *Pinger) PingMulticastContext(ctx context.Context, destination *net.IPAddr) (<-chan Reply, error) {
7878
req := multiRequest{}
7979

80-
seq, err := pinger.sendRequest(destination, &req)
80+
idseq, err := pinger.sendRequest(destination, &req)
8181
if err != nil {
8282
return nil, err
8383
}
@@ -86,7 +86,7 @@ func (pinger *Pinger) PingMulticastContext(ctx context.Context, destination *net
8686
<-ctx.Done()
8787

8888
// dequeue request
89-
pinger.removeRequest(seq)
89+
pinger.removeRequest(idseq)
9090

9191
req.close()
9292
}()
@@ -95,9 +95,12 @@ func (pinger *Pinger) PingMulticastContext(ctx context.Context, destination *net
9595
}
9696

9797
// sendRequest marshals the payload and sends the packet.
98-
// It returns the sequence number and an error if the sending failed.
99-
func (pinger *Pinger) sendRequest(destination *net.IPAddr, req request) (uint16, error) {
100-
seq := uint16(atomic.AddUint32(&sequence, 1))
98+
// It returns the combined id+sequence number and an error if the sending failed.
99+
func (pinger *Pinger) sendRequest(destination *net.IPAddr, req request) (uint32, error) {
100+
id := uint16(pinger.Id)
101+
seq := uint16(atomic.AddUint32(pinger.SequenceCounter, 1))
102+
103+
idseq := (uint32(id) << 16) | uint32(seq)
101104

102105
pinger.payloadMu.RLock()
103106
defer pinger.payloadMu.RUnlock()
@@ -106,7 +109,7 @@ func (pinger *Pinger) sendRequest(destination *net.IPAddr, req request) (uint16,
106109
wm := icmp.Message{
107110
Code: 0,
108111
Body: &icmp.Echo{
109-
ID: int(pinger.id),
112+
ID: int(id),
110113
Seq: int(seq),
111114
Data: pinger.payload,
112115
},
@@ -128,12 +131,12 @@ func (pinger *Pinger) sendRequest(destination *net.IPAddr, req request) (uint16,
128131
// serialize packet
129132
wb, err := wm.Marshal(nil)
130133
if err != nil {
131-
return seq, err
134+
return idseq, err
132135
}
133136

134137
// enqueue in currently running requests
135138
pinger.mtx.Lock()
136-
pinger.requests[seq] = req
139+
pinger.requests[idseq] = req
137140
pinger.mtx.Unlock()
138141

139142
// start measurement (tStop is set in the receiving end)
@@ -147,10 +150,10 @@ func (pinger *Pinger) sendRequest(destination *net.IPAddr, req request) (uint16,
147150
// send failed, need to remove request from list
148151
if err != nil {
149152
req.close()
150-
pinger.removeRequest(seq)
153+
pinger.removeRequest(idseq)
151154

152-
return 0, err
155+
return idseq, err
153156
}
154157

155-
return seq, nil
158+
return idseq, nil
156159
}

0 commit comments

Comments
 (0)