123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- package firewall
- import (
- "encoding/json"
- "fmt"
- mathrand "math/rand"
- "net/netip"
- )
- type m = map[string]any
- const (
- ProtoAny = 0 // When we want to handle HOPOPT (0) we can change this, if ever
- ProtoTCP = 6
- ProtoUDP = 17
- ProtoICMP = 1
- ProtoICMPv6 = 58
- PortAny = 0 // Special value for matching `port: any`
- PortFragment = -1 // Special value for matching `port: fragment`
- )
- type Packet struct {
- LocalAddr netip.Addr
- RemoteAddr netip.Addr
- LocalPort uint16
- RemotePort uint16
- Protocol uint8
- Fragment bool
- }
- func (fp *Packet) Copy() *Packet {
- return &Packet{
- LocalAddr: fp.LocalAddr,
- RemoteAddr: fp.RemoteAddr,
- LocalPort: fp.LocalPort,
- RemotePort: fp.RemotePort,
- Protocol: fp.Protocol,
- Fragment: fp.Fragment,
- }
- }
- func (fp Packet) MarshalJSON() ([]byte, error) {
- var proto string
- switch fp.Protocol {
- case ProtoTCP:
- proto = "tcp"
- case ProtoICMP:
- proto = "icmp"
- case ProtoUDP:
- proto = "udp"
- default:
- proto = fmt.Sprintf("unknown %v", fp.Protocol)
- }
- return json.Marshal(m{
- "LocalAddr": fp.LocalAddr.String(),
- "RemoteAddr": fp.RemoteAddr.String(),
- "LocalPort": fp.LocalPort,
- "RemotePort": fp.RemotePort,
- "Protocol": proto,
- "Fragment": fp.Fragment,
- })
- }
- // UDPSendPort calculates the UDP port to send from when using multiport mode.
- // The result will be from [0, numBuckets)
- func (fp Packet) UDPSendPort(numBuckets int) uint16 {
- if numBuckets <= 1 {
- return 0
- }
- // If there is no port (like an ICMP packet), pick a random UDP send port
- if fp.LocalPort == 0 {
- return uint16(mathrand.Intn(numBuckets))
- }
- // A decent enough 32bit hash function
- // Prospecting for Hash Functions
- // - https://nullprogram.com/blog/2018/07/31/
- // - https://github.com/skeeto/hash-prospector
- // [16 21f0aaad 15 d35a2d97 15] = 0.10760229515479501
- x := (uint32(fp.LocalPort) << 16) | uint32(fp.RemotePort)
- x ^= x >> 16
- x *= 0x21f0aaad
- x ^= x >> 15
- x *= 0xd35a2d97
- x ^= x >> 15
- return uint16(x) % uint16(numBuckets)
- }
|