package main import ( "encoding/binary" "log" "net" "github.com/cespare/xxhash/v2" ) // TODO: write more convenient version func addrMap(srcIp net.IP, dstCidr *net.IPNet) net.IP { addrlen := len(srcIp) if addrlen != len(dstCidr.IP) { log.Fatalf("addrMap(): src/dst size mismatch: %v vs %v", len(srcIp), len(dstCidr.IP)) } var addr net.IP = make([]byte, addrlen) hsum := xxhash.Sum64(srcIp) bsum := binary.NativeEndian.AppendUint64([]byte{}, hsum) blen := len(bsum) if addrlen > blen { // extend bsum tmp := append(make([]byte, addrlen-blen), bsum...) bsum = tmp } if addrlen < blen { // trim bsum bsum = bsum[:addrlen] } // apply inverted mask to bsum and sum with addr for i := range addrlen / 4 { a := binary.NativeEndian.Uint32(dstCidr.IP[i*4:]) b := binary.NativeEndian.Uint32(bsum[i*4:]) m := binary.NativeEndian.Uint32(dstCidr.Mask[i*4:]) a += (b & ^m) binary.NativeEndian.PutUint32(addr[i*4:], a) } return addr }