Skip to content

Commit

Permalink
test raw handler
Browse files Browse the repository at this point in the history
  • Loading branch information
BeryJu committed Jan 7, 2025
1 parent 0894243 commit 0848a3d
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 49 deletions.
99 changes: 50 additions & 49 deletions pkg/roles/dhcp/dhcp_handler4.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (h *handler4) Serve() error {
}
}

func (h *handler4) Handle(buf []byte, oob *ipv4.ControlMessage, _peer net.Addr) {
func (h *handler4) Handle(buf []byte, oob *ipv4.ControlMessage, peer net.Addr) {
if extconfig.Get().ListenOnlyMode {
return
}
Expand All @@ -59,7 +59,7 @@ func (h *handler4) Handle(buf []byte, oob *ipv4.ControlMessage, _peer net.Addr)
}

r := h.role.NewRequest4(m)
r.peer = _peer
r.peer = peer
r.Context = context
r.oob = oob

Expand All @@ -73,64 +73,65 @@ func (h *handler4) Handle(buf []byte, oob *ipv4.ControlMessage, _peer net.Addr)
}
hub.Scope().SetUser(sentry.User{
Username: m.HostName(),
IPAddress: strings.Split(_peer.String(), ":")[0],
IPAddress: strings.Split(peer.String(), ":")[0],
})

span.Description = m.MessageType().String()
defer span.Finish()
resp := h.HandleRequest(r)

if resp != nil {
h.role.logDHCPMessage(r, resp, []zapcore.Field{})
useEthernet := false
var peer *net.UDPAddr
if !r.GatewayIPAddr.IsUnspecified() {
peer = &net.UDPAddr{IP: r.GatewayIPAddr, Port: dhcpv4.ServerPort}
} else if resp.MessageType() == dhcpv4.MessageTypeNak {
peer = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
} else if !r.ClientIPAddr.IsUnspecified() {
peer = &net.UDPAddr{IP: r.ClientIPAddr, Port: dhcpv4.ClientPort}
} else if r.IsBroadcast() {
peer = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
} else {
// sends a layer2 frame so that we can define the destination MAC address
peer = &net.UDPAddr{IP: resp.YourIPAddr, Port: dhcpv4.ClientPort}
useEthernet = true
}
if resp == nil {
r.log.Debug("handler4: dropping request because response is nil")
return
}

h.role.logDHCPMessage(r, resp, []zapcore.Field{})
useEthernet := false
var p *net.UDPAddr
if !r.GatewayIPAddr.IsUnspecified() {
p = &net.UDPAddr{IP: r.GatewayIPAddr, Port: dhcpv4.ServerPort}
} else if resp.MessageType() == dhcpv4.MessageTypeNak {
p = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
} else if !r.ClientIPAddr.IsUnspecified() {
p = &net.UDPAddr{IP: r.ClientIPAddr, Port: dhcpv4.ClientPort}
} else if r.IsBroadcast() {
p = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
} else {
// sends a layer2 frame so that we can define the destination MAC address
p = &net.UDPAddr{IP: resp.YourIPAddr, Port: dhcpv4.ClientPort}
useEthernet = true
}

var woob *ipv4.ControlMessage
if peer.IP.Equal(net.IPv4bcast) || peer.IP.IsLinkLocalUnicast() || useEthernet {
// Direct broadcasts, link-local and layer2 unicasts to the interface the ruest was
// received on. Other packets should use the normal routing table in
// case of asymetric routing
switch {
case h.iface.Index != 0:
woob = &ipv4.ControlMessage{IfIndex: h.iface.Index}
case r.oob != nil && r.oob.IfIndex != 0:
woob = &ipv4.ControlMessage{IfIndex: r.oob.IfIndex}
default:
r.log.Error("HandleMsg4: Did not receive interface information")
}
var woob *ipv4.ControlMessage
if p.IP.Equal(net.IPv4bcast) || p.IP.IsLinkLocalUnicast() || useEthernet {
// Direct broadcasts, link-local and layer2 unicasts to the interface the ruest was
// received on. Other packets should use the normal routing table in
// case of asymetric routing
switch {
case h.iface.Index != 0:
woob = &ipv4.ControlMessage{IfIndex: h.iface.Index}
case r.oob != nil && r.oob.IfIndex != 0:
woob = &ipv4.ControlMessage{IfIndex: r.oob.IfIndex}
default:
r.log.Error("HandleMsg4: Did not receive interface information")
}
}

if useEthernet {
r.log.Debug("sending via ethernet")
intf, err := net.InterfaceByIndex(woob.IfIndex)
if err != nil {
r.log.Error("handler4: Can not get Interface for index", zap.Error(err), zap.Int("index", woob.IfIndex))
return
}
err = h.sendEthernet(*intf, resp)
if err != nil {
r.log.Error("handler4: Cannot send Ethernet packet", zap.Error(err))
}
} else {
if _, err := h.pc.WriteTo(resp.ToBytes(), woob, peer); err != nil {
r.log.Error("handler4: conn.Write failed", zap.Error(err), zap.String("peer", peer.String()))
}
if useEthernet {
r.log.Debug("sending via ethernet")
intf, err := net.InterfaceByIndex(woob.IfIndex)
if err != nil {
r.log.Error("handler4: Can not get Interface for index", zap.Error(err), zap.Int("index", woob.IfIndex))
return
}
err = h.sendEthernet(*intf, resp)
if err != nil {
r.log.Error("handler4: Cannot send Ethernet packet", zap.Error(err))
}
} else {
r.log.Debug("handler4: dropping request because response is nil")
if _, err := h.pc.WriteTo(resp.ToBytes(), woob, p); err != nil {
r.log.Error("handler4: conn.Write failed", zap.Error(err), zap.String("peer", p.String()))
}
}
}

Expand Down
45 changes: 45 additions & 0 deletions pkg/roles/dhcp/dhcp_handler4_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dhcp_test

import (
"net"
"testing"

"beryju.io/gravity/pkg/instance"
"beryju.io/gravity/pkg/roles/dhcp"
"beryju.io/gravity/pkg/roles/dhcp/types"
"beryju.io/gravity/pkg/tests"
"golang.org/x/net/ipv4"
)

func TestDHCP4_handle(t *testing.T) {
defer tests.Setup(t)()
rootInst := instance.New()
ctx := tests.Context()
inst := rootInst.ForRole("dhcp", ctx)
role := dhcp.New(inst)

tests.PanicIfError(inst.KV().Put(
ctx,
inst.KV().Key(
types.KeyRole,
types.KeyScopes,
"test",
).String(),
tests.MustJSON(dhcp.Scope{
SubnetCIDR: "10.100.0.0/24",
Default: true,
TTL: 86400,
IPAM: map[string]string{
"type": "internal",
"range_start": "10.100.0.100",
"range_end": "10.100.0.250",
},
}),
))
tests.PanicIfError(role.Start(ctx, RoleConfig()))
defer role.Stop()

role.Handler4().Handle(DHCPRequestPayload, &ipv4.ControlMessage{
IfIndex: 1,
}, &net.UDPAddr{})
}

0 comments on commit 0848a3d

Please sign in to comment.