Set NDP hop limit in accordance with RFC 4861

...and do not populate link address cache at dispatch. This partially
reverts 313c767b00, which caused malformed
packets (e.g. NDP Neighbor Adverts with incorrect hop limit values) to
populate the address cache. In particular, this masked a bug that was
introduced to the Neighbor Advert generation code in
7c1587e340.

PiperOrigin-RevId: 274865182
This commit is contained in:
Tamir Duberstein
2019-10-15 12:43:25 -07:00
committed by gVisor bot
parent a295616326
commit db1ca5c786
5 changed files with 27 additions and 20 deletions
+4
View File
@@ -109,7 +109,11 @@ func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
copy(pkt.HardwareAddressTarget(), h.HardwareAddressSender())
copy(pkt.ProtocolAddressTarget(), h.ProtocolAddressSender())
e.linkEP.WritePacket(r, nil /* gso */, hdr, buffer.VectorisedView{}, ProtocolNumber)
fallthrough // also fill the cache from requests
case header.ARPReply:
addr := tcpip.Address(h.ProtocolAddressSender())
linkAddr := tcpip.LinkAddress(h.HardwareAddressSender())
e.linkAddrCache.AddLinkAddress(e.nicid, addr, linkAddr)
}
}
+16 -4
View File
@@ -121,7 +121,6 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, vv buffer.V
case header.ICMPv6NeighborSolicit:
received.NeighborSolicit.Increment()
if len(v) < header.ICMPv6NeighborSolicitMinimumSize {
received.Invalid.Increment()
return
@@ -131,7 +130,6 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, vv buffer.V
// We don't have a useful answer; the best we can do is ignore the request.
return
}
hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.ICMPv6NeighborAdvertSize)
pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6NeighborAdvertSize))
pkt.SetType(header.ICMPv6NeighborAdvert)
@@ -154,7 +152,22 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, vv buffer.V
r.LocalAddress = targetAddr
pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{}))
if err := r.WritePacket(nil /* gso */, hdr, buffer.VectorisedView{}, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: r.DefaultTTL(), TOS: stack.DefaultTOS}); err != nil {
// TODO(tamird/ghanan): there exists an explicit NDP option that is
// used to update the neighbor table with link addresses for a
// neighbor from an NS (see the Source Link Layer option RFC
// 4861 section 4.6.1 and section 7.2.3).
//
// Furthermore, the entirety of NDP handling here seems to be
// contradicted by RFC 4861.
e.linkAddrCache.AddLinkAddress(e.nicid, r.RemoteAddress, r.RemoteLinkAddress)
// RFC 4861 Neighbor Discovery for IP version 6 (IPv6)
//
// 7.1.2. Validation of Neighbor Advertisements
//
// The IP Hop Limit field has a value of 255, i.e., the packet
// could not possibly have been forwarded by a router.
if err := r.WritePacket(nil /* gso */, hdr, buffer.VectorisedView{}, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: ndpHopLimit, TOS: stack.DefaultTOS}); err != nil {
sent.Dropped.Increment()
return
}
@@ -178,7 +191,6 @@ func (e *endpoint) handleICMP(r *stack.Route, netHeader buffer.View, vv buffer.V
received.Invalid.Increment()
return
}
vv.TrimFront(header.ICMPv6EchoMinimumSize)
hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.ICMPv6EchoMinimumSize)
pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6EchoMinimumSize))
+3 -7
View File
@@ -15,7 +15,6 @@
package ipv6
import (
"fmt"
"reflect"
"strings"
"testing"
@@ -179,13 +178,10 @@ func visitStats(v reflect.Value, f func(string, *tcpip.StatCounter)) {
t := v.Type()
for i := 0; i < v.NumField(); i++ {
v := v.Field(i)
switch v.Kind() {
case reflect.Ptr:
f(t.Field(i).Name, v.Interface().(*tcpip.StatCounter))
case reflect.Struct:
if s, ok := v.Interface().(*tcpip.StatCounter); ok {
f(t.Field(i).Name, s)
} else {
visitStats(v, f)
default:
panic(fmt.Sprintf("unexpected type %s", v.Type()))
}
}
}
-2
View File
@@ -632,8 +632,6 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remote, _ tcpip.LinkAddr
src, dst := netProto.ParseAddresses(vv.First())
n.stack.AddLinkAddress(n.id, src, remote)
if ref := n.getRef(protocol, dst); ref != nil {
handlePacket(protocol, dst, src, linkEP.LinkAddress(), remote, ref, vv)
return
+4 -7
View File
@@ -1086,15 +1086,12 @@ func (*TransportEndpointStats) IsEndpointStats() {}
func fillIn(v reflect.Value) {
for i := 0; i < v.NumField(); i++ {
v := v.Field(i)
switch v.Kind() {
case reflect.Ptr:
if s := v.Addr().Interface().(**StatCounter); *s == nil {
*s = &StatCounter{}
if s, ok := v.Addr().Interface().(**StatCounter); ok {
if *s == nil {
*s = new(StatCounter)
}
case reflect.Struct:
} else {
fillIn(v)
default:
panic(fmt.Sprintf("unexpected type %s", v.Type()))
}
}
}