| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- package job
- import (
- "net/netip"
- "strings"
- )
- // An address that matches is neither counted towards a client's IP limit nor
- // banned: counting it would still cut the shared network it protects (#5378).
- type ipLimitAllowlist struct {
- prefixes []netip.Prefix
- addrs []netip.Addr
- }
- // Comma-separated, each entry a CIDR or a bare address. Unparseable entries are
- // skipped: the validator uses these same rules, so only a hand-edited DB differs.
- func parseIpLimitAllowlist(raw string) ipLimitAllowlist {
- var list ipLimitAllowlist
- for _, field := range strings.Split(raw, ",") {
- field = strings.TrimSpace(field)
- if field == "" {
- continue
- }
- if prefix, err := netip.ParsePrefix(field); err == nil {
- // Unmapped: contains() unmaps the queried address, and Prefix.Contains
- // is false whenever the bit lengths disagree.
- if addr := prefix.Addr(); addr.Is4In6() {
- if p4, perr := addr.Unmap().Prefix(prefix.Bits() - 96); perr == nil {
- prefix = p4
- }
- }
- list.prefixes = append(list.prefixes, prefix.Masked())
- continue
- }
- if addr, err := netip.ParseAddr(field); err == nil {
- list.addrs = append(list.addrs, addr.Unmap())
- }
- }
- return list
- }
- func (l ipLimitAllowlist) empty() bool {
- return len(l.prefixes) == 0 && len(l.addrs) == 0
- }
- func (l ipLimitAllowlist) contains(ip string) bool {
- if l.empty() {
- return false
- }
- addr, err := netip.ParseAddr(strings.TrimSpace(ip))
- if err != nil {
- return false
- }
- addr = addr.Unmap()
- for _, allowed := range l.addrs {
- if allowed == addr {
- return true
- }
- }
- for _, prefix := range l.prefixes {
- if prefix.Contains(addr) {
- return true
- }
- }
- return false
- }
- // split separates the entries an allowlist protects from the ones the limit
- // still applies to, preserving the caller's ordering in both.
- func (l ipLimitAllowlist) split(entries []IPWithTimestamp) (limited, allowed []IPWithTimestamp) {
- if l.empty() {
- return entries, nil
- }
- limited = make([]IPWithTimestamp, 0, len(entries))
- for _, entry := range entries {
- if l.contains(entry.IP) {
- allowed = append(allowed, entry)
- continue
- }
- limited = append(limited, entry)
- }
- return limited, allowed
- }
|