passt, funktion unklar

This commit is contained in:
2025-06-12 06:43:13 +02:00
parent 1b2a0945ad
commit 27ac907eef

81
main.go
View File

@@ -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