From 0848a3d73bdc18caa273731f9dfd8ebcbacc959a Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 7 Jan 2025 22:38:51 +0100 Subject: [PATCH] test raw handler --- pkg/roles/dhcp/dhcp_handler4.go | 99 ++++++++++++++-------------- pkg/roles/dhcp/dhcp_handler4_test.go | 45 +++++++++++++ 2 files changed, 95 insertions(+), 49 deletions(-) create mode 100644 pkg/roles/dhcp/dhcp_handler4_test.go diff --git a/pkg/roles/dhcp/dhcp_handler4.go b/pkg/roles/dhcp/dhcp_handler4.go index 30a5cd08..70701cea 100644 --- a/pkg/roles/dhcp/dhcp_handler4.go +++ b/pkg/roles/dhcp/dhcp_handler4.go @@ -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 } @@ -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 @@ -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())) + } } } diff --git a/pkg/roles/dhcp/dhcp_handler4_test.go b/pkg/roles/dhcp/dhcp_handler4_test.go new file mode 100644 index 00000000..8f761def --- /dev/null +++ b/pkg/roles/dhcp/dhcp_handler4_test.go @@ -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{}) +}