feature: ipv4 broadcast support and bugfix for reset connection reset of IPv4+IPv6 stacks (#139)

* feature: ipv4 broadcast support

* stackip4 method receiver varname
This commit is contained in:
Pat Whittingslow
2026-06-24 16:54:41 -03:00
committed by GitHub
parent ef279863a9
commit a42f0b404c
4 changed files with 51 additions and 25 deletions
+23 -12
View File
@@ -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.
}
+14 -12
View File
@@ -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 {
+11
View File
@@ -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].
//
+3 -1
View File
@@ -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 {