mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Set LinkHeader for pkts sent by raw packet socket
Previously, when a packet was sent from a raw packet socket, the packet buffer's link header was left unpopulated and the link header was only found in the packet buffer's payload. This breaks the expectations of LinkEndpoints which expect the link layer header to always be populated when the link requires a header. PiperOrigin-RevId: 542349445
This commit is contained in:
committed by
gVisor bot
parent
a056469ab5
commit
a7d4a785b5
@@ -288,3 +288,6 @@ func (*Endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
|
||||
// AddHeader implements stack.LinkEndpoint.AddHeader.
|
||||
func (*Endpoint) AddHeader(stack.PacketBufferPtr) {}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (*Endpoint) ParseHeader(stack.PacketBufferPtr) bool { return true }
|
||||
|
||||
@@ -60,11 +60,10 @@ func (e *Endpoint) MTU() uint32 {
|
||||
|
||||
// DeliverNetworkPacket implements stack.NetworkDispatcher.
|
||||
func (e *Endpoint) DeliverNetworkPacket(_ tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
|
||||
hdr, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
if !ok {
|
||||
if !e.ParseHeader(pkt) {
|
||||
return
|
||||
}
|
||||
eth := header.Ethernet(hdr)
|
||||
eth := header.Ethernet(pkt.LinkHeader().Slice())
|
||||
dst := eth.DestinationAddress()
|
||||
if dst == header.EthernetBroadcastAddress {
|
||||
pkt.PktType = tcpip.PacketBroadcast
|
||||
@@ -113,3 +112,9 @@ func (*Endpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
}
|
||||
eth.Encode(&fields)
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.
|
||||
func (*Endpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
_, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
return ok
|
||||
}
|
||||
|
||||
@@ -528,6 +528,20 @@ func (e *endpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *endpoint) parseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
_, ok := pkt.LinkHeader().Consume(e.hdrSize)
|
||||
return ok
|
||||
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (e *endpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
if e.hdrSize > 0 {
|
||||
return e.parseHeader(pkt)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// writePacket writes outbound packets to the file descriptor. If it is not
|
||||
// currently writable, the packet is dropped.
|
||||
func (e *endpoint) writePacket(pkt stack.PacketBufferPtr) tcpip.Error {
|
||||
|
||||
@@ -189,11 +189,10 @@ func (d *readVDispatcher) dispatch() (bool, tcpip.Error) {
|
||||
|
||||
var p tcpip.NetworkProtocolNumber
|
||||
if d.e.hdrSize > 0 {
|
||||
hdr, ok := pkt.LinkHeader().Consume(d.e.hdrSize)
|
||||
if !ok {
|
||||
if !d.e.parseHeader(pkt) {
|
||||
return false, nil
|
||||
}
|
||||
p = header.Ethernet(hdr).Type()
|
||||
p = header.Ethernet(pkt.LinkHeader().Slice()).Type()
|
||||
} else {
|
||||
// We don't get any indication of what the packet is, so try to guess
|
||||
// if it's an IPv4 or IPv6 packet.
|
||||
|
||||
@@ -107,4 +107,8 @@ func (*endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
return header.ARPHardwareLoopback
|
||||
}
|
||||
|
||||
// AddHeader implements stack.LinkEndpoint.
|
||||
func (*endpoint) AddHeader(stack.PacketBufferPtr) {}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.
|
||||
func (*endpoint) ParseHeader(stack.PacketBufferPtr) bool { return true }
|
||||
|
||||
@@ -147,6 +147,9 @@ func (*InjectableEndpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
// AddHeader implements stack.LinkEndpoint.AddHeader.
|
||||
func (*InjectableEndpoint) AddHeader(stack.PacketBufferPtr) {}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (*InjectableEndpoint) ParseHeader(stack.PacketBufferPtr) bool { return true }
|
||||
|
||||
// NewInjectableEndpoint creates a new multi-endpoint injectable endpoint.
|
||||
func NewInjectableEndpoint(routes map[tcpip.Address]stack.InjectableLinkEndpoint) *InjectableEndpoint {
|
||||
return &InjectableEndpoint{
|
||||
|
||||
@@ -147,3 +147,8 @@ func (e *Endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
func (e *Endpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
e.child.AddHeader(pkt)
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (e *Endpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
return e.child.ParseHeader(pkt)
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ func (e *nullEndpoint) IsAttached() bool { return e.disp !=
|
||||
func (*nullEndpoint) Wait() {}
|
||||
func (*nullEndpoint) ARPHardwareType() header.ARPHardwareType { return header.ARPHardwareNone }
|
||||
func (*nullEndpoint) AddHeader(stack.PacketBufferPtr) {}
|
||||
func (*nullEndpoint) ParseHeader(stack.PacketBufferPtr) bool { return true }
|
||||
|
||||
var _ stack.NetworkDispatcher = (*testNetworkDispatcher)(nil)
|
||||
|
||||
|
||||
@@ -123,3 +123,6 @@ func (*Endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
|
||||
// AddHeader implements stack.LinkEndpoint.
|
||||
func (*Endpoint) AddHeader(stack.PacketBufferPtr) {}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.
|
||||
func (*Endpoint) ParseHeader(stack.PacketBufferPtr) bool { return true }
|
||||
|
||||
@@ -354,6 +354,21 @@ func (e *endpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
})
|
||||
}
|
||||
|
||||
func (e *endpoint) parseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
_, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (e *endpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
// Add ethernet header if needed.
|
||||
if len(e.addr) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return e.parseHeader(pkt)
|
||||
}
|
||||
|
||||
func (e *endpoint) AddVirtioNetHeader(pkt stack.PacketBufferPtr) {
|
||||
virtio := header.VirtioNetHeader(pkt.VirtioNetHeader().Push(header.VirtioNetHeaderSize))
|
||||
virtio.Encode(&header.VirtioNetHeaderFields{})
|
||||
@@ -447,13 +462,12 @@ func (e *endpoint) dispatchLoop(d stack.NetworkDispatcher) {
|
||||
}
|
||||
|
||||
var proto tcpip.NetworkProtocolNumber
|
||||
if e.addr != "" {
|
||||
hdr, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
if !ok {
|
||||
if len(e.addr) != 0 {
|
||||
if !e.parseHeader(pkt) {
|
||||
pkt.DecRef()
|
||||
continue
|
||||
}
|
||||
proto = header.Ethernet(hdr).Type()
|
||||
proto = header.Ethernet(pkt.LinkHeader().Slice()).Type()
|
||||
} else {
|
||||
// We don't get any indication of what the packet is, so try to guess
|
||||
// if it's an IPv4 or IPv6 packet.
|
||||
|
||||
@@ -217,6 +217,21 @@ func (e *serverEndpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
})
|
||||
}
|
||||
|
||||
func (e *serverEndpoint) parseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
_, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (e *serverEndpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
// Add ethernet header if needed.
|
||||
if len(e.addr) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return e.parseHeader(pkt)
|
||||
}
|
||||
|
||||
func (e *serverEndpoint) AddVirtioNetHeader(pkt stack.PacketBufferPtr) {
|
||||
virtio := header.VirtioNetHeader(pkt.VirtioNetHeader().Push(header.VirtioNetHeaderSize))
|
||||
virtio.Encode(&header.VirtioNetHeaderFields{})
|
||||
@@ -304,13 +319,12 @@ func (e *serverEndpoint) dispatchLoop(d stack.NetworkDispatcher) {
|
||||
}
|
||||
}
|
||||
var proto tcpip.NetworkProtocolNumber
|
||||
if e.addr != "" {
|
||||
hdr, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
if !ok {
|
||||
if len(e.addr) != 0 {
|
||||
if !e.parseHeader(pkt) {
|
||||
pkt.DecRef()
|
||||
continue
|
||||
}
|
||||
proto = header.Ethernet(hdr).Type()
|
||||
proto = header.Ethernet(pkt.LinkHeader().Slice()).Type()
|
||||
} else {
|
||||
// We don't get any indication of what the packet is, so try to guess
|
||||
// if it's an IPv4 or IPv6 packet.
|
||||
|
||||
@@ -161,3 +161,8 @@ func (e *Endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
func (e *Endpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
e.lower.AddHeader(pkt)
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (e *Endpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
return e.lower.ParseHeader(pkt)
|
||||
}
|
||||
|
||||
@@ -92,6 +92,11 @@ func (*countedEndpoint) AddHeader(stack.PacketBufferPtr) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (*countedEndpoint) ParseHeader(stack.PacketBufferPtr) bool {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func TestWaitWrite(t *testing.T) {
|
||||
ep := &countedEndpoint{}
|
||||
wep := New(ep)
|
||||
|
||||
@@ -246,6 +246,12 @@ func (ep *endpoint) AddHeader(pkt stack.PacketBufferPtr) {
|
||||
})
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (ep *endpoint) ParseHeader(pkt stack.PacketBufferPtr) bool {
|
||||
_, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType.
|
||||
func (ep *endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
return header.ARPHardwareEther
|
||||
@@ -361,8 +367,8 @@ func (ep *endpoint) dispatch() (bool, tcpip.Error) {
|
||||
Payload: buffer.MakeWithView(view),
|
||||
})
|
||||
// AF_XDP packets always have a link header.
|
||||
if _, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize); !ok {
|
||||
panic(fmt.Sprintf("LinkHeader().Consume(%d) must succeed", header.EthernetMinimumSize))
|
||||
if !ep.ParseHeader(pkt) {
|
||||
panic("ParseHeader(_) must succeed")
|
||||
}
|
||||
d.DeliverNetworkPacket(netProto, pkt)
|
||||
pkt.DecRef()
|
||||
|
||||
@@ -94,6 +94,9 @@ func (*MockLinkEndpoint) ARPHardwareType() header.ARPHardwareType { return heade
|
||||
// AddHeader implements LinkEndpoint.AddHeader.
|
||||
func (*MockLinkEndpoint) AddHeader(stack.PacketBufferPtr) {}
|
||||
|
||||
// ParseHeader implements LinkEndpoint.ParseHeader.
|
||||
func (*MockLinkEndpoint) ParseHeader(stack.PacketBufferPtr) bool { return true }
|
||||
|
||||
// Close releases all resources.
|
||||
func (ep *MockLinkEndpoint) Close() {
|
||||
for _, pkt := range ep.WrittenPackets {
|
||||
|
||||
@@ -229,6 +229,11 @@ func (*testObject) AddHeader(stack.PacketBufferPtr) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (*testObject) ParseHeader(stack.PacketBufferPtr) bool {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
type testContext struct {
|
||||
s *stack.Stack
|
||||
}
|
||||
|
||||
@@ -331,6 +331,9 @@ func (*fwdTestLinkEndpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
// AddHeader implements stack.LinkEndpoint.AddHeader.
|
||||
func (*fwdTestLinkEndpoint) AddHeader(PacketBufferPtr) {}
|
||||
|
||||
// ParseHeader implements stack.LinkEndpoint.ParseHeader.
|
||||
func (*fwdTestLinkEndpoint) ParseHeader(PacketBufferPtr) bool { return true }
|
||||
|
||||
func fwdTestNetFactory(t *testing.T, proto *fwdTestNetworkProtocol) (*faketime.ManualClock, *fwdTestLinkEndpoint, *fwdTestLinkEndpoint) {
|
||||
clock := faketime.NewManualClock()
|
||||
// Create a stack with the network protocol and two NICs.
|
||||
|
||||
@@ -386,6 +386,13 @@ func (n *nic) writePacket(pkt PacketBufferPtr) tcpip.Error {
|
||||
return n.writeRawPacket(pkt)
|
||||
}
|
||||
|
||||
func (n *nic) writeRawPacketWithLinkHeaderInPayload(pkt PacketBufferPtr) tcpip.Error {
|
||||
if !n.NetworkLinkEndpoint.ParseHeader(pkt) {
|
||||
return &tcpip.ErrMalformedHeader{}
|
||||
}
|
||||
return n.writeRawPacket(pkt)
|
||||
}
|
||||
|
||||
func (n *nic) writeRawPacket(pkt PacketBufferPtr) tcpip.Error {
|
||||
// Always an outgoing packet.
|
||||
pkt.PktType = tcpip.PacketOutgoing
|
||||
|
||||
@@ -1065,6 +1065,9 @@ type LinkWriter interface {
|
||||
// WritePackets writes packets. Must not be called with an empty list of
|
||||
// packet buffers.
|
||||
//
|
||||
// Each packet must have the link-layer header set, if the link requires
|
||||
// one.
|
||||
//
|
||||
// WritePackets may modify the packet buffers, and takes ownership of the PacketBufferList.
|
||||
// it is not safe to use the PacketBufferList after a call to WritePackets.
|
||||
WritePackets(PacketBufferList) (int, tcpip.Error)
|
||||
@@ -1121,6 +1124,9 @@ type NetworkLinkEndpoint interface {
|
||||
|
||||
// AddHeader adds a link layer header to the packet if required.
|
||||
AddHeader(PacketBufferPtr)
|
||||
|
||||
// ParseHeader parses the link layer header to the packet.
|
||||
ParseHeader(PacketBufferPtr) bool
|
||||
}
|
||||
|
||||
// QueueingDiscipline provides a queueing strategy for outgoing packets (e.g
|
||||
|
||||
@@ -1887,7 +1887,7 @@ func (s *Stack) WriteRawPacket(nicID tcpip.NICID, proto tcpip.NetworkProtocolNum
|
||||
})
|
||||
defer pkt.DecRef()
|
||||
pkt.NetworkProtocolNumber = proto
|
||||
return nic.writeRawPacket(pkt)
|
||||
return nic.writeRawPacketWithLinkHeaderInPayload(pkt)
|
||||
}
|
||||
|
||||
// NetworkProtocolInstance returns the protocol instance in the stack for the
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user