Merge release-20190806.1-299-gfb69de6 (automated)

This commit is contained in:
gVisor bot 2019-10-22 14:29:06 +00:00
commit 1e55a0ef32
4 changed files with 133 additions and 15 deletions

View File

@ -48,6 +48,28 @@ const (
// EthernetAddressSize is the size, in bytes, of an ethernet address.
EthernetAddressSize = 6
// unspecifiedEthernetAddress is the unspecified ethernet address
// (all bits set to 0).
unspecifiedEthernetAddress = tcpip.LinkAddress("\x00\x00\x00\x00\x00\x00")
// unicastMulticastFlagMask is the mask of the least significant bit in
// the first octet (in network byte order) of an ethernet address that
// determines whether the ethernet address is a unicast or multicast. If
// the masked bit is a 1, then the address is a multicast, unicast
// otherwise.
//
// See the IEEE Std 802-2001 document for more details. Specifically,
// section 9.2.1 of http://ieee802.org/secmail/pdfocSP2xXA6d.pdf:
// "A 48-bit universal address consists of two parts. The first 24 bits
// correspond to the OUI as assigned by the IEEE, expect that the
// assignee may set the LSB of the first octet to 1 for group addresses
// or set it to 0 for individual addresses."
unicastMulticastFlagMask = 1
// unicastMulticastFlagByteIdx is the byte that holds the
// unicast/multicast flag. See unicastMulticastFlagMask.
unicastMulticastFlagByteIdx = 0
)
const (
@ -90,3 +112,25 @@ func (b Ethernet) Encode(e *EthernetFields) {
copy(b[srcMAC:][:EthernetAddressSize], e.SrcAddr)
copy(b[dstMAC:][:EthernetAddressSize], e.DstAddr)
}
// IsValidUnicastEthernetAddress returns true if addr is a valid unicast
// ethernet address.
func IsValidUnicastEthernetAddress(addr tcpip.LinkAddress) bool {
// Must be of the right length.
if len(addr) != EthernetAddressSize {
return false
}
// Must not be unspecified.
if addr == unspecifiedEthernetAddress {
return false
}
// Must not be a multicast.
if addr[unicastMulticastFlagByteIdx]&unicastMulticastFlagMask != 0 {
return false
}
// addr is a valid unicast ethernet address.
return true
}

View File

@ -101,6 +101,15 @@ var IPv6EmptySubnet = func() tcpip.Subnet {
return subnet
}()
// IPv6LinkLocalPrefix is the prefix for IPv6 link-local addresses, as defined
// by RFC 4291 section 2.5.6.
//
// The prefix is fe80::/64
var IPv6LinkLocalPrefix = tcpip.AddressWithPrefix{
Address: "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
PrefixLen: 64,
}
// PayloadLength returns the value of the "payload length" field of the ipv6
// header.
func (b IPv6) PayloadLength() uint16 {

View File

@ -81,6 +81,9 @@ const (
)
func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint, loopback bool) *NIC {
// TODO(b/141011931): Validate a LinkEndpoint (ep) is valid. For
// example, make sure that the link address it provides is a valid
// unicast ethernet address.
nic := &NIC{
stack: stack,
id: id,
@ -139,11 +142,50 @@ func (n *NIC) enable() *tcpip.Error {
// when we perform Duplicate Address Detection, or Router Advertisement
// when we do Router Discovery. See RFC 4862, section 5.4.2 and RFC 4861
// section 4.2 for more information.
if _, ok := n.stack.networkProtocols[header.IPv6ProtocolNumber]; ok {
return n.joinGroup(header.IPv6ProtocolNumber, header.IPv6AllNodesMulticastAddress)
//
// Also auto-generate an IPv6 link-local address based on the NIC's
// link address if it is configured to do so. Note, each interface is
// required to have IPv6 link-local unicast address, as per RFC 4291
// section 2.1.
_, ok := n.stack.networkProtocols[header.IPv6ProtocolNumber]
if !ok {
return nil
}
return nil
n.mu.Lock()
defer n.mu.Unlock()
if err := n.joinGroupLocked(header.IPv6ProtocolNumber, header.IPv6AllNodesMulticastAddress); err != nil {
return err
}
if !n.stack.autoGenIPv6LinkLocal {
return nil
}
l2addr := n.linkEP.LinkAddress()
// Only attempt to generate the link-local address if we have a
// valid MAC address.
//
// TODO(b/141011931): Validate a LinkEndpoint's link address
// (provided by LinkEndpoint.LinkAddress) before reaching this
// point.
if !header.IsValidUnicastEthernetAddress(l2addr) {
return nil
}
addr := header.LinkLocalAddr(l2addr)
_, err := n.addPermanentAddressLocked(tcpip.ProtocolAddress{
Protocol: header.IPv6ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: addr,
PrefixLen: header.IPv6LinkLocalPrefix.PrefixLen,
},
}, CanBePrimaryEndpoint)
return err
}
// attachLinkEndpoint attaches the NIC to the endpoint, which will enable it
@ -582,6 +624,11 @@ func (n *NIC) joinGroup(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address
// exists yet. Otherwise it just increments its count. n MUST be locked before
// joinGroupLocked is called.
func (n *NIC) joinGroupLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) *tcpip.Error {
// TODO(b/143102137): When implementing MLD, make sure MLD packets are
// not sent unless a valid link-local address is available for use on n
// as an MLD packet's source address must be a link-local address as
// outlined in RFC 3810 section 5.
id := NetworkEndpointID{addr}
joins := n.mcastJoins[id]
if joins == 0 {

View File

@ -401,6 +401,11 @@ type Stack struct {
// ndpConfigs is the NDP configurations used by interfaces.
ndpConfigs NDPConfigurations
// autoGenIPv6LinkLocal determines whether or not the stack will attempt
// to auto-generate an IPv6 link-local address for newly enabled NICs.
// See the AutoGenIPv6LinkLocal field of Options for more details.
autoGenIPv6LinkLocal bool
}
// Options contains optional Stack configuration.
@ -431,6 +436,18 @@ type Options struct {
// before assigning an address to a NIC.
NDPConfigs NDPConfigurations
// AutoGenIPv6LinkLocal determins whether or not the stack will attempt
// to auto-generate an IPv6 link-local address for newly enabled NICs.
// Note, setting this to true does not mean that a link-local address
// will be assigned right away, or at all. If Duplicate Address
// Detection is enabled, an address will only be assigned if it
// successfully resolves. If it fails, no further attempt will be made
// to auto-generate an IPv6 link-local address.
//
// The generated link-local address will follow RFC 4291 Appendix A
// guidelines.
AutoGenIPv6LinkLocal bool
// RawFactory produces raw endpoints. Raw endpoints are enabled only if
// this is non-nil.
RawFactory RawFactory
@ -484,18 +501,19 @@ func New(opts Options) *Stack {
opts.NDPConfigs.validate()
s := &Stack{
transportProtocols: make(map[tcpip.TransportProtocolNumber]*transportProtocolState),
networkProtocols: make(map[tcpip.NetworkProtocolNumber]NetworkProtocol),
linkAddrResolvers: make(map[tcpip.NetworkProtocolNumber]LinkAddressResolver),
nics: make(map[tcpip.NICID]*NIC),
linkAddrCache: newLinkAddrCache(ageLimit, resolutionTimeout, resolutionAttempts),
PortManager: ports.NewPortManager(),
clock: clock,
stats: opts.Stats.FillIn(),
handleLocal: opts.HandleLocal,
icmpRateLimiter: NewICMPRateLimiter(),
portSeed: generateRandUint32(),
ndpConfigs: opts.NDPConfigs,
transportProtocols: make(map[tcpip.TransportProtocolNumber]*transportProtocolState),
networkProtocols: make(map[tcpip.NetworkProtocolNumber]NetworkProtocol),
linkAddrResolvers: make(map[tcpip.NetworkProtocolNumber]LinkAddressResolver),
nics: make(map[tcpip.NICID]*NIC),
linkAddrCache: newLinkAddrCache(ageLimit, resolutionTimeout, resolutionAttempts),
PortManager: ports.NewPortManager(),
clock: clock,
stats: opts.Stats.FillIn(),
handleLocal: opts.HandleLocal,
icmpRateLimiter: NewICMPRateLimiter(),
portSeed: generateRandUint32(),
ndpConfigs: opts.NDPConfigs,
autoGenIPv6LinkLocal: opts.AutoGenIPv6LinkLocal,
}
// Add specified network protocols.