mirror of
https://github.com/soypat/lneto.git
synced 2026-08-19 22:24:03 +00:00
dhcp working!
This commit is contained in:
+126
-2
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/soypat/lneto"
|
||||
"github.com/soypat/lneto/arp"
|
||||
"github.com/soypat/lneto/dhcpv4"
|
||||
"github.com/soypat/lneto/ethernet"
|
||||
"github.com/soypat/lneto/http/httpraw"
|
||||
"github.com/soypat/lneto/ipv4"
|
||||
@@ -238,7 +239,6 @@ func (pc *PacketBreakdown) CaptureIPv4(dst []Frame, pkt []byte, bitOffset int) (
|
||||
}
|
||||
}
|
||||
return pc.captureIPProto(proto, dst, pkt, end, protoErrs...)
|
||||
|
||||
}
|
||||
|
||||
func (pc *PacketBreakdown) captureIPProto(proto lneto.IPProto, dst []Frame, pkt []byte, bitOffset int, ipProtoErrs ...error) (_ []Frame, err error) {
|
||||
@@ -321,7 +321,49 @@ func (pc *PacketBreakdown) CaptureUDP(dst []Frame, pkt []byte, bitOffset int) ([
|
||||
finfo.Fields = append(finfo.Fields, baseUDPFields[:]...)
|
||||
dst = append(dst, finfo)
|
||||
end := bitOffset + 8*octet
|
||||
dst = append(dst, remainingFrameInfo(unknownPayloadProto, FieldClassPayload, end, octet*len(pkt)))
|
||||
payload := ufrm.Payload()
|
||||
if dhcpv4.PayloadIsDHCPv4(payload) {
|
||||
return pc.CaptureDHCPv4(dst, pkt, end)
|
||||
} else {
|
||||
dst = append(dst, remainingFrameInfo(unknownPayloadProto, FieldClassPayload, end, octet*len(pkt)))
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (pc *PacketBreakdown) CaptureDHCPv4(dst []Frame, pkt []byte, bitOffset int) ([]Frame, error) {
|
||||
if bitOffset%8 != 0 {
|
||||
return nil, errors.New("DHCP must be parsed at byte boundary")
|
||||
}
|
||||
dhcpData := pkt[bitOffset/8:]
|
||||
dfrm, err := dhcpv4.NewFrame(dhcpData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finfo := Frame{
|
||||
Protocol: "DHCPv4",
|
||||
PacketBitOffset: bitOffset,
|
||||
}
|
||||
magic := dfrm.MagicCookie()
|
||||
if magic != dhcpv4.MagicCookie {
|
||||
finfo.Errors = append(finfo.Errors, errors.New("incorrect DHCPv4 magic cookie"))
|
||||
}
|
||||
finfo.Fields = append(finfo.Fields, baseDHCPv4Fields[:]...)
|
||||
options := dfrm.OptionsPayload()
|
||||
if len(options) > 0 {
|
||||
err = dfrm.ForEachOption(func(optoff int, op dhcpv4.OptNum, data []byte) error {
|
||||
finfo.Fields = append(finfo.Fields, FrameField{
|
||||
Name: op.String(),
|
||||
Class: FieldClassOptions,
|
||||
FrameBitOffset: optoff * octet,
|
||||
BitLength: (2 + len(data)) * octet,
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
finfo.Errors = append(finfo.Errors, err)
|
||||
}
|
||||
}
|
||||
dst = append(dst, finfo)
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
@@ -547,6 +589,7 @@ const (
|
||||
FieldClassOptions // options
|
||||
FieldClassPayload // payload
|
||||
FieldClassText // text
|
||||
FieldClassAddress // address
|
||||
)
|
||||
|
||||
const octet = 8
|
||||
@@ -799,6 +842,87 @@ var baseUDPFields = [...]FrameField{
|
||||
},
|
||||
}
|
||||
|
||||
var baseDHCPv4Fields = [...]FrameField{
|
||||
{
|
||||
Name: "Opcode",
|
||||
Class: FieldClassType,
|
||||
FrameBitOffset: 0,
|
||||
BitLength: 1 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Hardware Address Type",
|
||||
Class: FieldClassProto,
|
||||
FrameBitOffset: 1 * octet,
|
||||
BitLength: 1 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Hardware Address Length",
|
||||
Class: FieldClassSize,
|
||||
FrameBitOffset: 2 * octet,
|
||||
BitLength: 1 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Hops",
|
||||
Class: fieldClassUndefined,
|
||||
FrameBitOffset: 3 * octet,
|
||||
BitLength: 1 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Transaction ID",
|
||||
Class: FieldClassID,
|
||||
FrameBitOffset: 4 * octet,
|
||||
BitLength: 4 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Start Time",
|
||||
Class: fieldClassUndefined,
|
||||
FrameBitOffset: 8 * octet,
|
||||
BitLength: 2 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Flags",
|
||||
Class: FieldClassFlags,
|
||||
FrameBitOffset: 10 * octet,
|
||||
BitLength: 2 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Client Address",
|
||||
Class: FieldClassAddress,
|
||||
FrameBitOffset: 12 * octet,
|
||||
BitLength: 4 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Offered Address",
|
||||
Class: FieldClassAddress,
|
||||
FrameBitOffset: 16 * octet,
|
||||
BitLength: 4 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Server Next Address",
|
||||
Class: FieldClassAddress,
|
||||
FrameBitOffset: 20 * octet,
|
||||
BitLength: 4 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Relay Agent Address",
|
||||
Class: FieldClassAddress,
|
||||
FrameBitOffset: 24 * octet,
|
||||
BitLength: 4 * octet,
|
||||
},
|
||||
{
|
||||
Name: "Client Hardware Address",
|
||||
Class: FieldClassAddress,
|
||||
FrameBitOffset: 28 * octet,
|
||||
BitLength: 16 * octet,
|
||||
},
|
||||
{
|
||||
Name: "BOOTP",
|
||||
Class: FieldClassAddress,
|
||||
FrameBitOffset: (28 + 16) * octet,
|
||||
BitLength: (dhcpv4.OptionsOffset - (28 + 16)) * octet,
|
||||
},
|
||||
}
|
||||
|
||||
func remainingFrameInfo(proto any, class FieldClass, pktBitOffset, pktBitLen int) Frame {
|
||||
return Frame{
|
||||
Protocol: proto,
|
||||
|
||||
@@ -100,7 +100,7 @@ func (ls *StackEthernet) Demux(carrierData []byte, frameOffset int) (err error)
|
||||
}
|
||||
DROP:
|
||||
ls.info("LinkStack:drop-packet", slog.String("dsthw", net.HardwareAddr(dstaddr[:]).String()), slog.String("ethertype", efrm.EtherTypeOrSize().String()))
|
||||
return nil
|
||||
return errors.New("drop packet")
|
||||
}
|
||||
|
||||
func (ls *StackEthernet) Encapsulate(carrierData []byte, frameOffset int) (n int, err error) {
|
||||
|
||||
@@ -64,6 +64,10 @@ func (sb *StackIP) Addr() netip.Addr {
|
||||
return netip.AddrFrom4(sb.ip)
|
||||
}
|
||||
|
||||
func (sb *StackIP) SetLogger(logger *slog.Logger) {
|
||||
sb.logger.log = logger
|
||||
}
|
||||
|
||||
func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
||||
sb.info("StackIP.Demux:start")
|
||||
frame := carrierData[offset:] // we don't care about carrier data in IP.
|
||||
@@ -72,8 +76,8 @@ func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
||||
return err
|
||||
}
|
||||
dst := ifrm.DestinationAddr()
|
||||
if *dst != sb.ip {
|
||||
return nil // Not meant for us.
|
||||
if sb.ip != ([4]byte{}) && *dst != sb.ip {
|
||||
return errors.New("not meant for us") // Not meant for us.
|
||||
}
|
||||
|
||||
sb.validator.ResetErr()
|
||||
@@ -155,7 +159,7 @@ func (sb *StackIP) Encapsulate(carrierData []byte, frameOffset int) (int, error)
|
||||
println("NODE REMOVED", proto.String(), h.port)
|
||||
h.destroy()
|
||||
}
|
||||
sb.error("StackIP:handle", slog.String("proto", proto.String()), slog.String("err", err.Error()))
|
||||
sb.error("StackIP:encapsulate", slog.String("proto", proto.String()), slog.String("err", err.Error()))
|
||||
continue
|
||||
} else if n == 0 {
|
||||
continue
|
||||
|
||||
@@ -74,7 +74,7 @@ func (sudp *StackUDPPort) Encapsulate(carrierData []byte, frameOffset int) (int,
|
||||
n, err := sudp.h.encapsulate(carrierData, frameOffset+8)
|
||||
if n == 0 {
|
||||
if err != nil {
|
||||
slog.Error("stackudp:demux", slog.String("err", err.Error()))
|
||||
slog.Error("stackudp:encapsulate", slog.String("err", err.Error()))
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func expectExchange(t *testing.T, from, to *StackIP, buf []byte) {
|
||||
t.Helper()
|
||||
n, err := from.Encapsulate(buf, 0)
|
||||
if err != nil {
|
||||
t.Error("expectExchange:Handle:", err)
|
||||
t.Error("expectExchange:encapsulate:", err)
|
||||
} else if n == 0 {
|
||||
t.Error("expected data exchange")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user