From 5dce45b2b680c398f6052c14c0f7558add495130 Mon Sep 17 00:00:00 2001 From: lprylli <49498490+lprylli@users.noreply.github.com> Date: Wed, 22 May 2019 02:15:26 -0700 Subject: Ignore bytes after end of IP packet in BroadcastRawUDPConn.ReadFrom (#292) When reading raw packets from the network, it can happen that the raw ethernet packet read has undefined bytes after the end of the ip packet (either from the network or in some cases from the local stack). Those bytes should not be passed to the dhcp-receiver otherwise the option parser which is picky about final padding byte will silently discard the dhcp-reply. Rename ipLen, udpLen variables with more explicit names to avoid confusion between header, payload, total length possibly considered in this function. Tested: ast2500 bmc reproducing the issue + existing go test for coverage. Signed-off-by: Loic Prylli --- dhcpv4/nclient4/conn_linux.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dhcpv4/nclient4/conn_linux.go b/dhcpv4/nclient4/conn_linux.go index 00c8a32..d6edc38 100644 --- a/dhcpv4/nclient4/conn_linux.go +++ b/dhcpv4/nclient4/conn_linux.go @@ -115,11 +115,11 @@ func udpMatch(addr *net.UDPAddr, bound *net.UDPAddr) bool { // ReadFrom reads raw IP packets and will try to match them against // upc.boundAddr. Any matching packets are returned via the given buffer. func (upc *BroadcastRawUDPConn) ReadFrom(b []byte) (int, net.Addr, error) { - ipLen := IPv4MaximumHeaderSize - udpLen := UDPMinimumSize + ipHdrMaxLen := IPv4MaximumHeaderSize + udpHdrLen := UDPMinimumSize for { - pkt := make([]byte, ipLen+udpLen+len(b)) + pkt := make([]byte, ipHdrMaxLen+udpHdrLen+len(b)) n, _, err := upc.PacketConn.ReadFrom(pkt) if err != nil { return 0, nil, err @@ -137,7 +137,7 @@ func (upc *BroadcastRawUDPConn) ReadFrom(b []byte) (int, net.Addr, error) { if ipHdr.TransportProtocol() != UDPProtocolNumber { continue } - udpHdr := UDP(buf.Consume(udpLen)) + udpHdr := UDP(buf.Consume(udpHdrLen)) addr := &net.UDPAddr{ IP: net.IP(ipHdr.DestinationAddress()), @@ -150,7 +150,10 @@ func (upc *BroadcastRawUDPConn) ReadFrom(b []byte) (int, net.Addr, error) { IP: net.IP(ipHdr.SourceAddress()), Port: int(udpHdr.SourcePort()), } - return copy(b, buf.ReadAll()), srcAddr, nil + // Extra padding after end of IP packet should be ignored, + // if not dhcp option parsing will fail. + dhcpLen := int(ipHdr.PayloadLength()) - udpHdrLen + return copy(b, buf.Consume(dhcpLen)), srcAddr, nil } } -- cgit v1.2.3