passt, funktion unklar
This commit is contained in:
81
main.go
81
main.go
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"expvar"
|
"expvar"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -151,31 +152,79 @@ func handleCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// liefert alle möglichen Präfixe dieser IP, beginnend beim längsten (/32 oder /128)
|
||||||
|
func supernets(ip netip.Addr) []string {
|
||||||
|
if ip.Is4() {
|
||||||
|
a := ip.As4() // Kopie addressierbar machen
|
||||||
|
u := binary.BigEndian.Uint32(a[:]) // jetzt darf man slicen
|
||||||
|
|
||||||
|
supers := make([]string, 33) // /32 … /0
|
||||||
|
for bits := 32; bits >= 0; bits-- {
|
||||||
|
mask := uint32(0xffffffff) << (32 - bits)
|
||||||
|
n := u & mask
|
||||||
|
addr := netip.AddrFrom4([4]byte{
|
||||||
|
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
|
||||||
|
})
|
||||||
|
supers[32-bits] = fmt.Sprintf("%s/%d", addr, bits)
|
||||||
|
}
|
||||||
|
return supers
|
||||||
|
}
|
||||||
|
|
||||||
|
a := ip.As16() // Kopie addressierbar
|
||||||
|
supers := make([]string, 129) // /128 … /0
|
||||||
|
for bits := 128; bits >= 0; bits-- {
|
||||||
|
b := a // Wert-Kopie für Modifikation
|
||||||
|
|
||||||
|
// vollständige Bytes auf 0 setzen
|
||||||
|
full := (128 - bits) / 8
|
||||||
|
for i := 0; i < full; i++ {
|
||||||
|
b[15-i] = 0
|
||||||
|
}
|
||||||
|
// Restbits maskieren
|
||||||
|
rem := (128 - bits) % 8
|
||||||
|
if rem != 0 {
|
||||||
|
b[15-full] &= 0xFF << rem
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := netip.AddrFrom16(b)
|
||||||
|
supers[128-bits] = fmt.Sprintf("%s/%d", addr, bits)
|
||||||
|
}
|
||||||
|
return supers
|
||||||
|
}
|
||||||
|
|
||||||
func checkIP(ip netip.Addr, cats []string) ([]string, error) {
|
func checkIP(ip netip.Addr, cats []string) ([]string, error) {
|
||||||
if res, ok := ipCache.Get(ip.String()); ok {
|
if res, ok := ipCache.Get(ip.String()); ok {
|
||||||
hits.Add(1)
|
hits.Add(1)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
matches := []string{}
|
supers := supernets(ip)
|
||||||
|
pipe := rdb.Pipeline()
|
||||||
|
cmds := make([]*redis.IntCmd, 0, len(cats)*len(supers))
|
||||||
|
|
||||||
|
// *einen* Redis-Roundtrip bauen
|
||||||
for _, cat := range cats {
|
for _, cat := range cats {
|
||||||
iter := rdb.Scan(ctx, 0, "bl:"+cat+":*", 0).Iterator()
|
for _, pfx := range supers {
|
||||||
for iter.Next(ctx) {
|
key := "bl:" + cat + ":" + pfx
|
||||||
key := iter.Val()
|
cmds = append(cmds, pipe.Exists(ctx, key))
|
||||||
parts := strings.SplitN(key, ":", 3)
|
|
||||||
if len(parts) != 3 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pfx, err := netip.ParsePrefix(parts[2])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if pfx.Contains(ip) {
|
|
||||||
matches = append(matches, cat)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if _, err := pipe.Exec(ctx); err != nil && err != redis.Nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := make([]string, 0, len(cats))
|
||||||
|
idx := 0
|
||||||
|
for _, cat := range cats {
|
||||||
|
for range supers {
|
||||||
|
if cmds[idx].Val() == 1 {
|
||||||
|
matches = append(matches, cat)
|
||||||
|
break // Kategorie gefunden → nächste
|
||||||
|
}
|
||||||
|
idx++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
misses.Add(1)
|
misses.Add(1)
|
||||||
ipCache.Add(ip.String(), matches)
|
ipCache.Add(ip.String(), matches)
|
||||||
return matches, nil
|
return matches, nil
|
||||||
|
Reference in New Issue
Block a user