mirror of
https://github.com/soypat/lneto.git
synced 2026-07-26 10:38:47 +00:00
46d4c06b9f
- http/httpraw: cap header slice growth to pre-allocated capacity, fix benchmark to reuse Header across iterations (0 allocs/op) - internal/ring: replace TODO panic comments with invariant explanations - tcp/conn: document truncated-frame offset check - tcp/handler: replace TODO with net.ErrClosed on RST-closed connection - internet/stack-udpport: filter incoming packets by remote IP address when configured via SetStackNode; skip filter for IPv4 multicast destinations (class D) so mDNS and similar protocols work correctly Generated with LLM assistance. Signed-off-by: Marvin Drees <marvin.drees@9elements.com>
105 lines
2.3 KiB
Go
105 lines
2.3 KiB
Go
package internal
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
"github.com/soypat/lneto"
|
|
)
|
|
|
|
func GetIPAddr(buf []byte) (src, dst []byte, id, ipEndOff uint16, err error) {
|
|
b0 := buf[0]
|
|
version := b0 >> 4
|
|
switch version {
|
|
case 4:
|
|
ihl := b0 & 0xf
|
|
ipEndOff = 4 * uint16(ihl)
|
|
id = binary.BigEndian.Uint16(buf[4:6])
|
|
src = buf[12:16]
|
|
dst = buf[16:20]
|
|
case 6:
|
|
src = buf[8:24]
|
|
dst = buf[24:40]
|
|
ipEndOff = 40
|
|
default:
|
|
err = lneto.ErrUnsupported
|
|
}
|
|
return src, dst, id, ipEndOff, err
|
|
}
|
|
|
|
// IsMulticastIPAddr reports whether addr is an IPv4 or IPv6 multicast address.
|
|
func IsMulticastIPAddr(addr []byte) bool {
|
|
switch len(addr) {
|
|
case 4:
|
|
return addr[0]&0xf0 == 0xe0
|
|
case 16:
|
|
return addr[0] == 0xff
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func SetIPAddrs(buf []byte, id uint16, src, dst []byte) (err error) {
|
|
var dstaddr, srcaddr []byte
|
|
version := buf[0] >> 4
|
|
switch version {
|
|
case 4:
|
|
srcaddr = buf[12:16]
|
|
dstaddr = buf[16:20]
|
|
if id > 0 {
|
|
binary.BigEndian.PutUint16(buf[4:6], id)
|
|
}
|
|
case 6:
|
|
srcaddr = buf[8:24]
|
|
dstaddr = buf[24:40]
|
|
default:
|
|
return lneto.ErrUnsupported
|
|
}
|
|
if src != nil && len(srcaddr) != len(src) {
|
|
return lneto.ErrMismatchLen
|
|
}
|
|
if dst != nil && len(dstaddr) != len(dst) {
|
|
return lneto.ErrMismatchLen
|
|
}
|
|
copy(srcaddr, src)
|
|
copy(dstaddr, dst)
|
|
return nil
|
|
}
|
|
|
|
// SetMulticast sets the IP destination to multicastAddr and derives the
|
|
// Ethernet destination MAC from it. It supports IPv4 (RFC 1112 §6.4) and
|
|
// IPv6 (RFC 2464 §7) multicast MAC mapping.
|
|
func SetMulticast(ethernetCarrier []byte, ipOff int, multicastAddr []byte) (err error) {
|
|
ip := ethernetCarrier[ipOff:]
|
|
mac := ethernetCarrier[0:6]
|
|
version := ip[0] >> 4
|
|
switch version {
|
|
case 4:
|
|
if len(multicastAddr) != 4 {
|
|
return lneto.ErrMismatchLen
|
|
}
|
|
copy(ip[16:20], multicastAddr)
|
|
// IPv4 multicast MAC: 01:00:5e + low 23 bits of IP destination.
|
|
mac[0] = 0x01
|
|
mac[1] = 0x00
|
|
mac[2] = 0x5e
|
|
mac[3] = multicastAddr[1] & 0x7f
|
|
mac[4] = multicastAddr[2]
|
|
mac[5] = multicastAddr[3]
|
|
case 6:
|
|
if len(multicastAddr) != 16 {
|
|
return lneto.ErrMismatchLen
|
|
}
|
|
copy(ip[24:40], multicastAddr)
|
|
// IPv6 multicast MAC: 33:33 + last 4 bytes of IP destination.
|
|
mac[0] = 0x33
|
|
mac[1] = 0x33
|
|
mac[2] = multicastAddr[12]
|
|
mac[3] = multicastAddr[13]
|
|
mac[4] = multicastAddr[14]
|
|
mac[5] = multicastAddr[15]
|
|
default:
|
|
return lneto.ErrUnsupported
|
|
}
|
|
return nil
|
|
}
|