dhcp working!

This commit is contained in:
soypat
2025-07-09 16:54:48 -03:00
parent 9c0e250cf6
commit 489e9951fa
10 changed files with 228 additions and 69 deletions
+25 -22
View File
@@ -19,6 +19,7 @@ type Client struct {
hostname []byte hostname []byte
dns [][4]byte dns [][4]byte
svIPtos ipv4.ToS
tRenew uint32 tRenew uint32
tRebind uint32 tRebind uint32
tIPLease uint32 tIPLease uint32
@@ -73,26 +74,16 @@ func (c *Client) setIP(b []byte, frameOffset int) {
ifrm, _ := ipv4.NewFrame(b) ifrm, _ := ipv4.NewFrame(b)
ifrm.SetID((uint16(c.currentXID) ^ uint16(c.currentXID>>16)) + uint16(c.state)) ifrm.SetID((uint16(c.currentXID) ^ uint16(c.currentXID>>16)) + uint16(c.state))
if c.state > StateInit { if c.state > StateInit {
// TODO(soypat): Document why disabling ToS used by DHCP server may cause Request to fail. // Match server ToS since some routers drop DHCP requests if no ToS set apparently?
// Apparently server sets ToS=192. Uncommenting this line causes DHCP to fail on my setup. ifrm.SetToS(c.svIPtos)
// If left fixed at 192, DHCP does not work.
// If left fixed at 0, DHCP does not work.
// Apparently ToS is a function of which state of DHCP one is in. Not sure why code below works.
// Note: Not exactly needed for all servers.
const ecnmask = 0b1100_0000
ifrm.SetToS(ecnmask)
} }
src := ifrm.SourceAddr() src := ifrm.SourceAddr()
for i := range src { for i := range src {
src[i] = 0 src[i] = 0
} }
dst := ifrm.DestinationAddr()[:] dst := ifrm.DestinationAddr()[:]
if c.svip == ([4]byte{}) { for i := range dst {
for i := range dst { dst[i] = 255
dst[i] = 255
}
} else {
copy(dst, c.svip[:])
} }
} }
@@ -103,6 +94,8 @@ func (c *Client) Encapsulate(carrierFrame []byte, frameOffset int) (int, error)
return 0, nil // No offer received yet. return 0, nil // No offer received yet.
} else if c.state == StateBound { } else if c.state == StateBound {
return 0, nil // Done! return 0, nil // Done!
} else if c.state == StateRequesting {
return 0, nil // Currently awaiting ACK.
} }
dst := carrierFrame[frameOffset:] dst := carrierFrame[frameOffset:]
frm, err := NewFrame(dst) frm, err := NewFrame(dst)
@@ -149,7 +142,7 @@ func (c *Client) Encapsulate(carrierFrame []byte, frameOffset int) (int, error)
nextState = StateRequesting nextState = StateRequesting
default: default:
return 0, errors.New("unhandled state") return 0, errors.New("unhandled state" + c.state.String())
} }
n, _ := EncodeOption(opts[numOpts:], OptClientIdentifier, c.clientMAC[:]...) n, _ := EncodeOption(opts[numOpts:], OptClientIdentifier, c.clientMAC[:]...)
numOpts += n numOpts += n
@@ -166,10 +159,11 @@ func (c *Client) Encapsulate(carrierFrame []byte, frameOffset int) (int, error)
c.setHeader(frm) c.setHeader(frm)
c.setIP(carrierFrame, frameOffset) c.setIP(carrierFrame, frameOffset)
c.state = nextState c.state = nextState
return optionsOffset + numOpts, nil return OptionsOffset + numOpts, nil
} }
func (c *Client) Demux(carrierData []byte, frameOffset int) error { func (c *Client) Demux(carrierData []byte, frameOffset int) error {
fmt.Println("DEMUX DHCP")
if c.isClosed() { if c.isClosed() {
return net.ErrClosed return net.ErrClosed
} }
@@ -212,13 +206,17 @@ func (c *Client) Demux(carrierData []byte, frameOffset int) error {
default: default:
return fmt.Errorf("dcpv4 unexpected state in recv %s", c.state.String()) return fmt.Errorf("dcpv4 unexpected state in recv %s", c.state.String())
} }
if frameOffset > 28 && c.svIPtos == 0 {
ifrm, _ := ipv4.NewFrame(carrierData)
c.svIPtos = ifrm.ToS()
}
return nil return nil
} }
func (c *Client) getMessageType(frm Frame) MessageType { func (c *Client) getMessageType(frm Frame) MessageType {
c.auxbuf[0] = 255 c.auxbuf[0] = 255
ptrMsgType := &c.auxbuf[0] ptrMsgType := &c.auxbuf[0]
frm.ForEachOption(func(opt OptNum, data []byte) error { frm.ForEachOption(func(_ int, opt OptNum, data []byte) error {
if len(data) == 1 { if len(data) == 1 {
*ptrMsgType = data[0] *ptrMsgType = data[0]
return io.EOF return io.EOF
@@ -229,7 +227,7 @@ func (c *Client) getMessageType(frm Frame) MessageType {
} }
func (c *Client) setOptions(frm Frame) error { func (c *Client) setOptions(frm Frame) error {
return frm.ForEachOption(func(opt OptNum, data []byte) error { err := frm.ForEachOption(func(_ int, opt OptNum, data []byte) error {
switch opt { switch opt {
case OptRenewTimeValue: case OptRenewTimeValue:
c.tRenew = maybeU32(data) c.tRenew = maybeU32(data)
@@ -237,7 +235,6 @@ func (c *Client) setOptions(frm Frame) error {
c.tIPLease = maybeU32(data) c.tIPLease = maybeU32(data)
case OptRebindingTimeValue: case OptRebindingTimeValue:
c.tRebind = maybeU32(data) c.tRebind = maybeU32(data)
case OptServerIdentification: case OptServerIdentification:
c.svip = maybe4byte(data) c.svip = maybe4byte(data)
case OptRouter: case OptRouter:
@@ -261,6 +258,7 @@ func (c *Client) setOptions(frm Frame) error {
} }
return nil return nil
}) })
return err
} }
func (c *Client) isClosed() bool { return c.state == 0 || c.currentXID == 0 } func (c *Client) isClosed() bool { return c.state == 0 || c.currentXID == 0 }
@@ -272,16 +270,21 @@ func (c *Client) setHeader(frm Frame) {
frm.SetHardware(1, 6, 0) frm.SetHardware(1, 6, 0)
frm.SetSecs(1) frm.SetSecs(1)
if c.state.HasIP() { if c.state.HasIP() {
copy(frm.CIAddr()[:], c.offer[:]) *frm.CIAddr() = c.offer
} }
if c.state == StateInit { if c.state == StateInit {
siaddr := frm.SIAddr()[:] siaddr := frm.SIAddr()[:]
for i := range siaddr { for i := range siaddr {
siaddr[i] = 255 siaddr[i] = 255
} }
} else {
if c.siip == [4]byte{} {
*frm.SIAddr() = c.svip
} else {
*frm.SIAddr() = c.siip
}
} }
*frm.YIAddr() = c.offer
copy(frm.YIAddr()[:], c.offer[:])
copy(frm.CHAddrAs6()[:], c.clientMAC[:]) copy(frm.CHAddrAs6()[:], c.clientMAC[:])
frm.SetMagicCookie(MagicCookie) frm.SetMagicCookie(MagicCookie)
} }
+27 -13
View File
@@ -98,13 +98,18 @@ func TestExample(t *testing.T) {
Hostname: clientHostname, Hostname: clientHostname,
}) })
buf := make([]byte, 2048) buf := make([]byte, 2048)
buf2 := make([]byte, len(buf))
n, err := cl.Encapsulate(buf, 0) n, err := cl.Encapsulate(buf, 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} else if n <= 0 { } else if n <= 0 {
t.Fatal("no data sent out by client after starting request") t.Fatal("no data sent out by client after starting request")
} }
n, err = cl.Encapsulate(buf2, 0)
if err != nil {
t.Error("client encaps double tap after discover:", err)
}
// Fabricate server OFFER response.
dfrm, _ := NewFrame(buf) dfrm, _ := NewFrame(buf)
dfrm.ClearHeader() dfrm.ClearHeader()
dfrm.SetOp(OpReply) dfrm.SetOp(OpReply)
@@ -116,27 +121,36 @@ func TestExample(t *testing.T) {
copy(dfrm.CHAddr()[:], clientHwaddr[:]) copy(dfrm.CHAddr()[:], clientHwaddr[:])
dfrm.SetMagicCookie(MagicCookie) dfrm.SetMagicCookie(MagicCookie)
ntot := 0 ntot := 0
nopt, _ := EncodeOption(buf[optionsOffset+ntot:], OptMessageType, byte(MsgOffer)) nopt, _ := EncodeOption(buf[OptionsOffset+ntot:], OptMessageType, byte(MsgOffer))
ntot += nopt ntot += nopt
nopt, _ = EncodeOption(buf[optionsOffset+ntot:], OptServerIdentification, serverIP[:]...) nopt, _ = EncodeOption(buf[OptionsOffset+ntot:], OptServerIdentification, serverIP[:]...)
ntot += nopt ntot += nopt
nopt, _ = EncodeOption32(buf[optionsOffset+ntot:], OptServerIdentification, offerLease) nopt, _ = EncodeOption32(buf[OptionsOffset+ntot:], OptServerIdentification, offerLease)
ntot += nopt ntot += nopt
nopt, _ = EncodeOption(buf[optionsOffset+ntot:], OptSubnetMask, subnetMask[:]...) nopt, _ = EncodeOption(buf[OptionsOffset+ntot:], OptSubnetMask, subnetMask[:]...)
ntot += nopt ntot += nopt
nopt, _ = EncodeOption(buf[optionsOffset+ntot:], OptRouter, routerAddr[:]...) nopt, _ = EncodeOption(buf[OptionsOffset+ntot:], OptRouter, routerAddr[:]...)
ntot += nopt ntot += nopt
nopt, _ = EncodeOption(buf[optionsOffset+ntot:], OptDNSServers, dnsAddr[:]...) nopt, _ = EncodeOption(buf[OptionsOffset+ntot:], OptDNSServers, dnsAddr[:]...)
ntot += nopt ntot += nopt
nopt, _ = EncodeOption(buf[optionsOffset+ntot:], OptEnd, dnsAddr[:]...) nopt, _ = EncodeOption(buf[OptionsOffset+ntot:], OptEnd, dnsAddr[:]...)
ntot += nopt ntot += nopt
err = cl.Demux(buf[:optionsOffset+ntot], 0) err = cl.Demux(buf[:OptionsOffset+ntot], 0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// frame := buf[:optionsOffset]
// frame = AppendOption(frame, OptMessageType, byte(MsgOffer)) n, err = cl.Encapsulate(buf[:], 0)
// frame = AppendOption(frame, OptServerIdentification, serverIP[:]...) if err != nil {
// frame = AppendOption(frame, OptIPAddressLeaseTime, serverIP[:]...) t.Fatal(err)
} else if n <= 0 {
t.Fatal("no data written from client in response to offer")
}
n, err = cl.Encapsulate(buf[:], 0)
if err != nil {
t.Error("encapsulate double tap after request:", err)
} else if n > 0 {
t.Error("encapsulate double tap got data!", n)
}
} }
+11 -7
View File
@@ -17,7 +17,7 @@ const (
// Expected Magic Cookie value. // Expected Magic Cookie value.
MagicCookie uint32 = 0x63825363 MagicCookie uint32 = 0x63825363
// DHCP Options offset measured from the start of the UDP payload. // DHCP Options offset measured from the start of the UDP payload.
optionsOffset = magicCookieOffset + 4 OptionsOffset = magicCookieOffset + 4
DefaultClientPort = 68 DefaultClientPort = 68
DefaultServerPort = 67 DefaultServerPort = 67
@@ -26,12 +26,16 @@ const (
// NewFrame returns a new DHCPv4 Frame with data set to buf. // NewFrame returns a new DHCPv4 Frame with data set to buf.
// An error is returned if the buffer size is smaller than 240. // An error is returned if the buffer size is smaller than 240.
func NewFrame(buf []byte) (Frame, error) { func NewFrame(buf []byte) (Frame, error) {
if len(buf) < optionsOffset { if len(buf) < OptionsOffset {
return Frame{}, errSmallFrame return Frame{}, errSmallFrame
} }
return Frame{buf: buf}, nil return Frame{buf: buf}, nil
} }
func PayloadIsDHCPv4(payload []byte) bool {
return len(payload) >= OptionsOffset && binary.BigEndian.Uint32(payload[magicCookieOffset:]) == MagicCookie
}
// Frame encapsulates the raw data of a DHCP packet // Frame encapsulates the raw data of a DHCP packet
// and provides methods for manipulating, validating and // and provides methods for manipulating, validating and
// retrieving fields and payload data. See [RFC2131]. // retrieving fields and payload data. See [RFC2131].
@@ -43,7 +47,7 @@ type Frame struct {
// OptionsPayload returns the options portion of the DHCP frame. May be zero lengthed. // OptionsPayload returns the options portion of the DHCP frame. May be zero lengthed.
func (frm Frame) OptionsPayload() []byte { func (frm Frame) OptionsPayload() []byte {
return frm.buf[optionsOffset:] return frm.buf[OptionsOffset:]
} }
func (frm Frame) Op() Op { return Op(frm.buf[0]) } func (frm Frame) Op() Op { return Op(frm.buf[0]) }
@@ -111,16 +115,16 @@ func (frm Frame) SetMagicCookie(cookie uint32) {
// ClearHeader zeros out the header contents. // ClearHeader zeros out the header contents.
func (frm Frame) ClearHeader() { func (frm Frame) ClearHeader() {
for i := range frm.buf[:optionsOffset] { for i := range frm.buf[:OptionsOffset] {
frm.buf[i] = 0 frm.buf[i] = 0
} }
} }
// ForEachOption iterates over all DHCPv4 options returning an error on a malformed option or when user provided callback returns an error. // ForEachOption iterates over all DHCPv4 options returning an error on a malformed option or when user provided callback returns an error.
// If the user provided callback is nil then only option buffer validation is performed. // If the user provided callback is nil then only option buffer validation is performed.
func (frm Frame) ForEachOption(fn func(op OptNum, data []byte) error) error { func (frm Frame) ForEachOption(fn func(off int, op OptNum, data []byte) error) error {
// Parse DHCP options. // Parse DHCP options.
ptr := optionsOffset ptr := OptionsOffset
if ptr > len(frm.buf) { if ptr > len(frm.buf) {
return errSmallFrame return errSmallFrame
} else if len(frm.buf[ptr:]) == 0 { } else if len(frm.buf[ptr:]) == 0 {
@@ -141,7 +145,7 @@ func (frm Frame) ForEachOption(fn func(op OptNum, data []byte) error) error {
optlen := frm.buf[ptr+1] optlen := frm.buf[ptr+1]
if callback { if callback {
optionData := frm.buf[ptr+2 : ptr+2+int(optlen)] optionData := frm.buf[ptr+2 : ptr+2+int(optlen)]
if err := fn(optnum, optionData); err != nil { if err := fn(ptr, optnum, optionData); err != nil {
return err return err
} }
} }
+2 -2
View File
@@ -77,7 +77,7 @@ func (sv *Server) Demux(carrierData []byte, frameOffset int) error {
var reqlist []byte var reqlist []byte
var reqAddr []byte var reqAddr []byte
var hostname []byte var hostname []byte
err = dfrm.ForEachOption(func(op OptNum, data []byte) error { err = dfrm.ForEachOption(func(off int, op OptNum, data []byte) error {
switch op { switch op {
case OptMessageType: case OptMessageType:
if len(data) == 1 { if len(data) == 1 {
@@ -231,7 +231,7 @@ func (sv *Server) Encapsulate(carrierData []byte, frameOffset int) (int, error)
// Set server state. // Set server state.
sv.hosts[clientID] = client sv.hosts[clientID] = client
sv.pending-- sv.pending--
return optionsOffset + nopt, nil return OptionsOffset + nopt, nil
} }
func (sv *Server) getClient(clientID [36]byte) (serverEntry, bool) { func (sv *Server) getClient(clientID [36]byte) (serverEntry, bool) {
+27 -17
View File
@@ -6,6 +6,7 @@ import (
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"log/slog"
"net" "net"
"net/netip" "net/netip"
"os" "os"
@@ -89,7 +90,7 @@ func run() (err error) {
} }
fmt.Println("NIC hardware address:", net.HardwareAddr(nicHW[:]).String(), "bridgeHW:", net.HardwareAddr(brHW[:]).String(), "mtu:", mtu, "addr:", nicAddr.String()) fmt.Println("NIC hardware address:", net.HardwareAddr(nicHW[:]).String(), "bridgeHW:", net.HardwareAddr(brHW[:]).String(), "mtu:", mtu, "addr:", nicAddr.String())
var stack Stack var stack Stack
err = stack.Reset(brHW, nicAddr.Addr().Next(), uint16(mtu)) err = stack.Reset(brHW, netip.AddrFrom4([4]byte{}), uint16(mtu))
if err != nil { if err != nil {
return err return err
} }
@@ -97,9 +98,7 @@ func run() (err error) {
if err != nil { if err != nil {
return err return err
} }
var shark pcap.PacketBreakdown
buf := make([]byte, mtu) buf := make([]byte, mtu)
var iframes []pcap.Frame
lastAction := time.Now() lastAction := time.Now()
dnsOngoing := false dnsOngoing := false
for { for {
@@ -126,12 +125,6 @@ func run() (err error) {
if err != nil { if err != nil {
fmt.Println("ERR:ENCAPSULATE", err) fmt.Println("ERR:ENCAPSULATE", err)
} else if nwrite > 0 { } else if nwrite > 0 {
iframes, err = shark.CaptureEthernet(iframes[:0], buf[:nwrite], 0)
if err != nil {
fmt.Println("OU", iframes, err.Error())
} else {
fmt.Println("OU", iframes)
}
n, err := iface.Write(buf[:nwrite]) n, err := iface.Write(buf[:nwrite])
if err != nil { if err != nil {
return err return err
@@ -145,12 +138,6 @@ func run() (err error) {
if err != nil { if err != nil {
return err return err
} else if nread > 0 { } else if nread > 0 {
iframes, err = shark.CaptureEthernet(iframes[:0], buf[:nread], 0)
if err != nil {
fmt.Println("IN", iframes, err.Error())
} else {
fmt.Println("IN", iframes)
}
err = stack.Demux(buf[:nread], 0) err = stack.Demux(buf[:nread], 0)
if err != nil { if err != nil {
fmt.Println("ERR:DEMUX", err) fmt.Println("ERR:DEMUX", err)
@@ -174,14 +161,36 @@ type Stack struct {
dhcp dhcpv4.Client dhcp dhcpv4.Client
dns dns.Client dns dns.Client
lookup dns.Message lookup dns.Message
// Packet capture and top level filtering.
shark pcap.PacketBreakdown
aux []pcap.Frame
} }
func (s *Stack) Demux(b []byte, _ int) error { func (s *Stack) Demux(b []byte, _ int) (err error) {
s.aux, err = s.shark.CaptureEthernet(s.aux[:0], b, 0)
if s.aux[len(s.aux)-1].Protocol != "DHCPv4" {
return nil
}
if err != nil {
fmt.Println("IN", s.aux, err.Error())
} else {
fmt.Println("IN", s.aux)
}
return s.link.Demux(b, 0) return s.link.Demux(b, 0)
} }
func (s *Stack) Encapsulate(b []byte, _ int) (int, error) { func (s *Stack) Encapsulate(b []byte, _ int) (int, error) {
return s.link.Encapsulate(b, 0) n, err := s.link.Encapsulate(b, 0)
if n > 0 {
iframes, errpcap := s.shark.CaptureEthernet(s.aux[:0], b[:n], 0)
if errpcap != nil {
fmt.Println("OU", iframes, errpcap.Error())
} else {
fmt.Println("OU", iframes)
}
}
return n, err
} }
func (s *Stack) Reset(mac [6]byte, addr netip.Addr, mtu uint16) error { func (s *Stack) Reset(mac [6]byte, addr netip.Addr, mtu uint16) error {
@@ -227,6 +236,7 @@ func (s *Stack) Reset(mac [6]byte, addr netip.Addr, mtu uint16) error {
if err != nil { if err != nil {
return err return err
} }
s.ip.SetLogger(slog.Default())
return nil return nil
} }
+126 -2
View File
@@ -9,6 +9,7 @@ import (
"github.com/soypat/lneto" "github.com/soypat/lneto"
"github.com/soypat/lneto/arp" "github.com/soypat/lneto/arp"
"github.com/soypat/lneto/dhcpv4"
"github.com/soypat/lneto/ethernet" "github.com/soypat/lneto/ethernet"
"github.com/soypat/lneto/http/httpraw" "github.com/soypat/lneto/http/httpraw"
"github.com/soypat/lneto/ipv4" "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...) 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) { 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[:]...) finfo.Fields = append(finfo.Fields, baseUDPFields[:]...)
dst = append(dst, finfo) dst = append(dst, finfo)
end := bitOffset + 8*octet 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 return dst, nil
} }
@@ -547,6 +589,7 @@ const (
FieldClassOptions // options FieldClassOptions // options
FieldClassPayload // payload FieldClassPayload // payload
FieldClassText // text FieldClassText // text
FieldClassAddress // address
) )
const octet = 8 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 { func remainingFrameInfo(proto any, class FieldClass, pktBitOffset, pktBitLen int) Frame {
return Frame{ return Frame{
Protocol: proto, Protocol: proto,
+1 -1
View File
@@ -100,7 +100,7 @@ func (ls *StackEthernet) Demux(carrierData []byte, frameOffset int) (err error)
} }
DROP: DROP:
ls.info("LinkStack:drop-packet", slog.String("dsthw", net.HardwareAddr(dstaddr[:]).String()), slog.String("ethertype", efrm.EtherTypeOrSize().String())) 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) { func (ls *StackEthernet) Encapsulate(carrierData []byte, frameOffset int) (n int, err error) {
+7 -3
View File
@@ -64,6 +64,10 @@ func (sb *StackIP) Addr() netip.Addr {
return netip.AddrFrom4(sb.ip) 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 { func (sb *StackIP) Demux(carrierData []byte, offset int) error {
sb.info("StackIP.Demux:start") sb.info("StackIP.Demux:start")
frame := carrierData[offset:] // we don't care about carrier data in IP. 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 return err
} }
dst := ifrm.DestinationAddr() dst := ifrm.DestinationAddr()
if *dst != sb.ip { if sb.ip != ([4]byte{}) && *dst != sb.ip {
return nil // Not meant for us. return errors.New("not meant for us") // Not meant for us.
} }
sb.validator.ResetErr() sb.validator.ResetErr()
@@ -155,7 +159,7 @@ func (sb *StackIP) Encapsulate(carrierData []byte, frameOffset int) (int, error)
println("NODE REMOVED", proto.String(), h.port) println("NODE REMOVED", proto.String(), h.port)
h.destroy() 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 continue
} else if n == 0 { } else if n == 0 {
continue continue
+1 -1
View File
@@ -74,7 +74,7 @@ func (sudp *StackUDPPort) Encapsulate(carrierData []byte, frameOffset int) (int,
n, err := sudp.h.encapsulate(carrierData, frameOffset+8) n, err := sudp.h.encapsulate(carrierData, frameOffset+8)
if n == 0 { if n == 0 {
if err != nil { if err != nil {
slog.Error("stackudp:demux", slog.String("err", err.Error())) slog.Error("stackudp:encapsulate", slog.String("err", err.Error()))
} }
return 0, err return 0, err
} }
+1 -1
View File
@@ -46,7 +46,7 @@ func expectExchange(t *testing.T, from, to *StackIP, buf []byte) {
t.Helper() t.Helper()
n, err := from.Encapsulate(buf, 0) n, err := from.Encapsulate(buf, 0)
if err != nil { if err != nil {
t.Error("expectExchange:Handle:", err) t.Error("expectExchange:encapsulate:", err)
} else if n == 0 { } else if n == 0 {
t.Error("expected data exchange") t.Error("expected data exchange")
return return