Merge release-20190806.1-299-gfb69de6 (automated)
This commit is contained in:
commit
1e55a0ef32
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue