diff --git a/internet/stack-ip4.go b/internet/stack-ip4.go index 82153da..d72cd63 100644 --- a/internet/stack-ip4.go +++ b/internet/stack-ip4.go @@ -22,34 +22,35 @@ type StackIPv4 struct { } func (stackip4 *StackIPv4) Reset(vld *lneto.Validator, maxNodes int) error { + stackip4.connID++ stackip4.reset4(vld, maxNodes) return nil } -func (stackip *StackIPv4) ConnectionID() *uint64 { - return &stackip.connID +func (stackip4 *StackIPv4) ConnectionID() *uint64 { + return &stackip4.connID } -func (stackip *StackIPv4) Protocol() uint64 { +func (stackip4 *StackIPv4) Protocol() uint64 { return uint64(ethernet.TypeIPv4) } -func (stackip *StackIPv4) LocalPort() uint16 { return 0 } +func (stackip4 *StackIPv4) LocalPort() uint16 { return 0 } -func (stackip *StackIPv4) SetLogger(logger *slog.Logger) { - stackip.stackip4.handlers.log = logger +func (stackip4 *StackIPv4) SetLogger(logger *slog.Logger) { + stackip4.stackip4.handlers.log = logger } -func (stackip *StackIPv4) Demux(carrierData []byte, offset int) error { +func (stackip4 *StackIPv4) Demux(carrierData []byte, offset int) error { debugLog("ip:demux") - return stackip.stackip4.demux4(carrierData, offset) + return stackip4.stackip4.demux4(carrierData, offset) } -func (stackip *StackIPv4) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) { +func (stackip4 *StackIPv4) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) { if offsetToFrame != offsetToIP { return 0, lneto.ErrBug } - return stackip.stackip4.encapsulate4(carrierData, offsetToIP) + return stackip4.stackip4.encapsulate4(carrierData, offsetToIP) } type stackip4 struct { @@ -58,6 +59,7 @@ type stackip4 struct { ipID uint16 ip4 [4]byte acceptMulticast bool + acceptBroadcast bool } func (si4 *stackip4) reset4(vld *lneto.Validator, maxNodes int) { @@ -86,6 +88,10 @@ func (si4 *stackip4) IsRegistered4(proto lneto.IPProto) bool { func (si4 *stackip4) SetAcceptMulticast4(accept bool) { si4.acceptMulticast = accept } +func (si4 *stackip4) SetAcceptBroadcast4(accept bool) { + si4.acceptBroadcast = accept +} + func (si4 *stackip4) Addr4() [4]byte { return si4.ip4 } func (si4 *stackip4) SetAddr4(ip4 [4]byte) { si4.ip4 = ip4 @@ -100,8 +106,13 @@ func (si4 *stackip4) demux4(carrierData []byte, offset int) error { return err } dst := ifrm.DestinationAddr() - if si4.ip4 != ([4]byte{}) && *dst != si4.ip4 { - if !si4.acceptMulticast || !internal.IsMulticastIPAddr(dst[:]) { + if si4.ip4 != ([4]byte{}) && *dst != si4.ip4 { // Accept all packets when IP zeroed. + switch { + case si4.acceptMulticast && ipv4.IsMulticast(*dst): + // accept multicast. + case si4.acceptBroadcast && ipv4.IsBroadcast(*dst): + // accept broadcast. + default: si4.handlers.debug("ip:not-for-us") return lneto.ErrPacketDrop // Not meant for us. } diff --git a/internet/stack-ip6.go b/internet/stack-ip6.go index f357b67..cd9e675 100644 --- a/internet/stack-ip6.go +++ b/internet/stack-ip6.go @@ -19,35 +19,36 @@ type StackIPv6 struct { stackip6 } -func (stackip4 *StackIPv6) Reset(vld *lneto.Validator, maxNodes int) error { - stackip4.reset6(vld, maxNodes) +func (stackip6 *StackIPv6) Reset(vld *lneto.Validator, maxNodes int) error { + stackip6.connID++ + stackip6.reset6(vld, maxNodes) return nil } -func (stackip *StackIPv6) ConnectionID() *uint64 { - return &stackip.connID +func (stackip6 *StackIPv6) ConnectionID() *uint64 { + return &stackip6.connID } -func (stackip *StackIPv6) Protocol() uint64 { +func (stackip6 *StackIPv6) Protocol() uint64 { return uint64(ethernet.TypeIPv6) } -func (stackip *StackIPv6) LocalPort() uint16 { return 0 } +func (stackip6 *StackIPv6) LocalPort() uint16 { return 0 } -func (stackip *StackIPv6) SetLogger(logger *slog.Logger) { - stackip.stackip6.handlers.log = logger +func (stackip6 *StackIPv6) SetLogger(logger *slog.Logger) { + stackip6.stackip6.handlers.log = logger } -func (stackip *StackIPv6) Demux(carrierData []byte, offset int) error { +func (stackip6 *StackIPv6) Demux(carrierData []byte, offset int) error { debugLog("ip:demux") - return stackip.stackip6.demux6(carrierData, offset) + return stackip6.stackip6.demux6(carrierData, offset) } -func (stackip *StackIPv6) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) { +func (stackip6 *StackIPv6) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (n int, err error) { if offsetToFrame != offsetToIP { return 0, lneto.ErrBug } - return stackip.stackip6.encapsulate6(carrierData, offsetToIP) + return stackip6.stackip6.encapsulate6(carrierData, offsetToIP) } type stackip6 struct { @@ -55,6 +56,7 @@ type stackip6 struct { vld *lneto.Validator ip6 [16]byte acceptMulticast bool + acceptBroadcast bool } func (si6 *stackip6) Register6(h lneto.StackNode) error { diff --git a/ipv4/definitions.go b/ipv4/definitions.go index c0ee648..96c66e0 100644 --- a/ipv4/definitions.go +++ b/ipv4/definitions.go @@ -18,6 +18,17 @@ func IsMulticast(addr [4]byte) bool { return addr[0]&0xf0 == 0xe0 } +// IsBroadcast reports whether addr is the limited broadcast address +// 255.255.255.255 used to address all hosts on the local network segment +// as defined in [RFC919]. It does not detect directed (subnet) broadcast +// addresses, which depend on the network mask and cannot be determined from +// the address alone. +// +// [RFC919]: https://datatracker.ietf.org/doc/html/rfc919 +func IsBroadcast(addr [4]byte) bool { + return addr == [4]byte{255, 255, 255, 255} +} + // IsLinkLocal reports whether addr is within the IPv4 link-local prefix // 169.254.0.0/16 reserved for dynamic link-local configuration as defined in [RFC3927]. // diff --git a/x/xnet/stack-async.go b/x/xnet/stack-async.go index d9e61e0..0be82e7 100644 --- a/x/xnet/stack-async.go +++ b/x/xnet/stack-async.go @@ -103,6 +103,8 @@ type StackConfig struct { MTU uint16 // Accept multicast ethernet and IP packets. Needed for MDNS. AcceptMulticast bool + // Accept broadcast IPv4 packets. Needed for managing access points and DHCPv4 servers. + AcceptIPv4Broadcast bool } func (cfg *StackConfig) id() uint16 { @@ -234,7 +236,7 @@ func (s *StackAsync) Reset(cfg StackConfig) (err error) { } s.ip4.SetAddr4(cfg.StaticAddress4) s.setAcceptMulticast4(cfg.AcceptMulticast) - + s.ip4.SetAcceptBroadcast4(cfg.AcceptIPv4Broadcast) s.arpt.passivePeers = uint8(cfg.PassivePeers) err = s.resetARP() if err != nil {