@@ -63,12 +63,27 @@ func (r *icmpResponder) respond(pkt *stack.PacketBuffer) (handled bool) {
6363 if ! r .ok () {
6464 return
6565 }
66- return r .handle (pkt .NICID , pkt )
66+ h := hdlEcho .Load ()
67+ if h == nil {
68+ log .E ("icmp: responder: no handler" )
69+ return
70+ }
71+ if useIcmpForwarder {
72+ var id stack.TransportEndpointID
73+ id .LocalAddress = pkt .Network ().SourceAddress ()
74+ id .RemoteAddress = pkt .Network ().DestinationAddress ()
75+ if settings .Debug {
76+ log .VV ("icmp: responder: forward (sz: %d); src %s => dst %s" ,
77+ pkt .Size (), id .RemoteAddress , id .LocalAddress )
78+ }
79+ return icmpForward2 (h , pkt , id )
80+ }
81+ return r .handle (h , pkt .NICID , pkt )
6782}
6883
6984// handle returns true if the packet is ICMP and is handled (or dropped) by the
7085// bypass path.
71- func (r * icmpResponder ) handle (nic tcpip.NICID , pkt * stack.PacketBuffer ) (handled bool ) {
86+ func (r * icmpResponder ) handle (h * icmpForwarder , nic tcpip.NICID , pkt * stack.PacketBuffer ) (handled bool ) {
7287 if ! r .ok () {
7388 return
7489 }
@@ -85,7 +100,6 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
85100
86101 v := c .ToView ()
87102 b := v .ToSlice ()
88- h := hdlEcho .Load ()
89103 n := len (b )
90104
91105 notok := n <= 0 || h == nil
@@ -111,7 +125,6 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
111125 return
112126 }
113127
114- // Capture fields before spawning the goroutine.
115128 src := parsed .Src
116129 dst := parsed .Dst
117130 has := parsed .HasTransportData ()
@@ -135,7 +148,7 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
135148
136149 if useIcmpForwarder {
137150 wire .Pool .Put (parsed )
138- return r . forward (h , pkt , src , dst )
151+ return icmpForward (h , pkt , src , dst )
139152 } else {
140153 // Process asynchronously to avoid blocking the dispatcher loop.
141154 core .Gx ("icmp.responder" , func () {
@@ -146,10 +159,7 @@ func (r *icmpResponder) handle(nic tcpip.NICID, pkt *stack.PacketBuffer) (handle
146159 return true
147160}
148161
149- func (r * icmpResponder ) forward (h * icmpForwarder , pkt * stack.PacketBuffer , src , dst netip.AddrPort ) bool {
150- pkt = pkt .Clone ()
151- defer pkt .DecRef ()
152-
162+ func icmpForward (h * icmpForwarder , pkt * stack.PacketBuffer , src , dst netip.AddrPort ) bool {
153163 // local is dst / remote is src; see: netstack/icmp/icmp.go:func (h *icmpForwarder) reply4
154164 // and netstack/icmp/icmp.go:func (h *icmpForwarder) reply6
155165 local := dst .Addr ().AsSlice ()
@@ -166,17 +176,24 @@ func (r *icmpResponder) forward(h *icmpForwarder, pkt *stack.PacketBuffer, src,
166176 id .RemoteAddress = tcpip .AddrFromSlice (remote )
167177 // ICMP does not use ports, so they remain zero.
168178
179+ return icmpForward2 (h , pkt , id )
180+ }
181+
182+ func icmpForward2 (h * icmpForwarder , pkt * stack.PacketBuffer , id stack.TransportEndpointID ) bool {
183+ pkt = pkt .Clone ()
184+ defer pkt .DecRef ()
185+
169186 switch pkt .NetworkProtocolNumber {
170187 case header .IPv4ProtocolNumber :
171- v , got := core .Await1 (func () bool { defer pkt .DecRef (); return h .reply4 (id , pkt .IncRef ()) }, 3 * time .Second )
188+ v , got := core .Await1 (func () bool { defer pkt .DecRef (); return h .reply4 (id , pkt .IncRef ()) }, 5 * time .Second )
172189 return got && v
173190 case header .IPv6ProtocolNumber :
174- v , got := core .Await1 (func () bool { defer pkt .DecRef (); return h .reply6 (id , pkt .IncRef ()) }, 3 * time .Second )
191+ v , got := core .Await1 (func () bool { defer pkt .DecRef (); return h .reply6 (id , pkt .IncRef ()) }, 5 * time .Second )
175192 return got && v
176193 }
177194
178195 log .W ("icmp: responder: unsupported proto: %d; %s => %s" ,
179- pkt .NetworkProtocolNumber , src , dst )
196+ pkt .NetworkProtocolNumber , id . RemoteAddress , id . LocalAddress )
180197 return false
181198}
182199
0 commit comments