Skip to content

Commit

Permalink
Honor client bootp flags in response.
Browse files Browse the repository at this point in the history
Signed-off-by: s3rj1k <evasive.gyron@gmail.com>
  • Loading branch information
s3rj1k committed Sep 6, 2023
1 parent b2c93e8 commit c7d31ae
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 12 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ This repository contains a DHCPv4 Relay agent written in Go (Golang). This relay
- [RFC3046: DHCP Relay Agent Information Option](https://www.rfc-editor.org/rfc/rfc3046.html)
- [RFC3396: Encoding Long Options in the DHCPv4](https://www.rfc-editor.org/rfc/rfc3396.html)
- [RFC3527: Link Selection sub-option for the Relay Agent Information Option for DHCPv4](https://www.rfc-editor.org/rfc/rfc3527.html)
- [RFC5010: Relay Agent Flags Suboption](https://www.rfc-editor.org/rfc/rfc5010.html)
- [RFC5107: DHCP Server Identifier Override Suboption](https://www.rfc-editor.org/rfc/rfc5107.html)

### Contribution
Expand Down
26 changes: 20 additions & 6 deletions dhcpv4-reply-raw.go → dhcpv4-reply.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,16 @@ import (
"code.local/dhcp-relay/specs"
)

func HandleDHCPv4GenericReplyRaw(
const (
UnicastReply uint8 = 0
BroadcastReply uint8 = 1
)

func HandleDHCPv4GenericReply(
cfg *HandleOptions,
dhcpMessageType string,
layerDHCPv4 *layers.DHCPv4,
replyType uint8,
) error {
srcIP := layerDHCPv4.RelayAgentIP.To4()
if srcIP == nil || srcIP.IsLoopback() || srcIP.Equal(net.IPv4zero) || srcIP.Equal(net.IPv4bcast) {
Expand Down Expand Up @@ -61,8 +67,6 @@ func HandleDHCPv4GenericReplyRaw(
Flags: layers.IPv4DontFragment,
TTL: cfg.ReplyTTL,
Protocol: layers.IPProtocolUDP,
SrcIP: srcIP.To4(),
DstIP: layerDHCPv4.YourClientIP.To4(),
}

layerUDP := &layers.UDP{
Expand All @@ -84,7 +88,17 @@ func HandleDHCPv4GenericReplyRaw(
layerDHCPv4.RelayAgentIP = nil
}

dhcp.SetUnicast(layerDHCPv4)
if replyType == UnicastReply {
layerIPv4.SrcIP = srcIP.To4()
layerIPv4.DstIP = layerDHCPv4.YourClientIP.To4()

dhcp.SetUnicast(layerDHCPv4)
} else if replyType == BroadcastReply {
layerIPv4.SrcIP = net.IPv4zero
layerIPv4.DstIP = net.IPv4bcast

dhcp.SetBroadcast(layerDHCPv4)
}

buffer := gopacket.NewSerializeBuffer()

Expand Down Expand Up @@ -124,10 +138,10 @@ func HandleDHCPv4GenericReplyRaw(
cl.Infof("%s 0x%x: DHCP-%s [%d], IfIndex=%d, Src=%s, Dst=%s\n",
logDataOutPrefix, layerDHCPv4.Xid, dhcpMessageType, layerDHCPv4.Len(), ifIndex,
net.JoinHostPort(
srcIP.To4().String(), strconv.Itoa(specs.DHCPv4ServerPort),
layerIPv4.SrcIP.String(), strconv.Itoa(specs.DHCPv4ServerPort),
),
net.JoinHostPort(
layerDHCPv4.YourClientIP.To4().String(), strconv.Itoa(specs.DHCPv4ClientPort),
layerIPv4.DstIP.String(), strconv.Itoa(specs.DHCPv4ClientPort),
),
)

Expand Down
3 changes: 0 additions & 3 deletions dhcpv4-request.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ func HandleDHCPv4GenericRequest(

dhcp.SetRelayAgentInformationOption(layerDHCPv4, subOpt1)

dhcp.SetUnicast(layerDHCPv4)
layerDHCPv4.RelayHops++

for _, addr := range addrs {
Expand Down Expand Up @@ -106,8 +105,6 @@ func ForwardDHCPv4RelayedRequest(
dhcpMessageType string,
layerDHCPv4 *layers.DHCPv4,
) error {
dhcp.SetUnicast(layerDHCPv4)

buffer := gopacket.NewSerializeBuffer()

err := gopacket.SerializeLayers(
Expand Down
18 changes: 15 additions & 3 deletions dhcpv4.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,21 @@ func HandleDHCPv4(

funcDataInLog()

if err := HandleDHCPv4GenericReplyRaw(cfg, dhcpMessageType, layerDHCPv4); err != nil {
cl.Errorf("Error handling DHCPv4-%s relayed message: %v\n",
dhcpMessageType, err)
bootFileName := dhcp.GetBootFileName(layerDHCPv4)
if bootFileName != "" {
cl.Debugf("Boot File Name: %s\n", bootFileName)
}

if dhcp.IsUnicast(layerDHCPv4) {
if err := HandleDHCPv4GenericReply(cfg, dhcpMessageType, layerDHCPv4, UnicastReply); err != nil {
cl.Errorf("Error handling DHCPv4-%s unicast relayed message: %v\n",
dhcpMessageType, err)
}
} else if dhcp.IsBroadcast(layerDHCPv4) {
if err := HandleDHCPv4GenericReply(cfg, dhcpMessageType, layerDHCPv4, BroadcastReply); err != nil {
cl.Errorf("Error handling DHCPv4-%s broadcast relayed message: %v\n",
dhcpMessageType, err)
}
}
}
}
15 changes: 15 additions & 0 deletions gpckt/dhcp/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dhcp

import (
"bytes"

"github.com/gopacket/gopacket/layers"
)

func GetBootFileName(layerDHCPv4 *layers.DHCPv4) string {
if len(layerDHCPv4.File) == 0 {
return ""
}

return string(bytes.TrimSpace(layerDHCPv4.File))
}
12 changes: 12 additions & 0 deletions gpckt/layer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package gpckt

import (
"fmt"

"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
)
Expand Down Expand Up @@ -60,3 +62,13 @@ func GetDHCPv4(packet gopacket.Packet) *layers.DHCPv4 {

return layerDHCPv4
}

func CopyDHCPv4(layerDHCPv4 *layers.DHCPv4) (*layers.DHCPv4, error) {
out := new(layers.DHCPv4)

if err := out.DecodeFromBytes(layerDHCPv4.Contents, gopacket.NilDecodeFeedback); err != nil {
return nil, fmt.Errorf("copy error: %w", err)
}

return out, nil
}

0 comments on commit c7d31ae

Please sign in to comment.