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:
Ghanan Gowripalan
2023-06-21 13:41:22 -07:00
committed by gVisor bot
parent a056469ab5
commit a7d4a785b5
23 changed files with 254 additions and 18 deletions
+3
View File
@@ -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 }
+8 -3
View File
@@ -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
}
+14
View File
@@ -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 {
+2 -3
View File
@@ -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.
+4
View File
@@ -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 }
+3
View File
@@ -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{
+5
View File
@@ -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)
+3
View File
@@ -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 }
+18 -4
View File
@@ -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.
+18 -4
View File
@@ -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.
+5
View File
@@ -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)
}
+5
View File
@@ -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)
+8 -2
View File
@@ -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 {
+5
View File
@@ -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
}
+3
View File
@@ -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.
+7
View File
@@ -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
+6
View File
@@ -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
+1 -1
View File
@@ -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