mirror of
https://github.com/ergochat/ergo.git
synced 2025-02-16 21:50:39 +01:00
refactor [dk]linemanagers
* Synchronize map accesses * Be more aggressive about cleaning up expired lines * CIDR dlines did not work (nil dereference)
This commit is contained in:
parent
cea6565b80
commit
ae441d22d3
59
irc/dline.go
59
irc/dline.go
@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
@ -79,6 +80,7 @@ type dLineNet struct {
|
|||||||
|
|
||||||
// DLineManager manages and dlines.
|
// DLineManager manages and dlines.
|
||||||
type DLineManager struct {
|
type DLineManager struct {
|
||||||
|
sync.RWMutex
|
||||||
// addresses that are dlined
|
// addresses that are dlined
|
||||||
addresses map[string]*dLineAddr
|
addresses map[string]*dLineAddr
|
||||||
// networks that are dlined
|
// networks that are dlined
|
||||||
@ -97,6 +99,9 @@ func NewDLineManager() *DLineManager {
|
|||||||
func (dm *DLineManager) AllBans() map[string]IPBanInfo {
|
func (dm *DLineManager) AllBans() map[string]IPBanInfo {
|
||||||
allb := make(map[string]IPBanInfo)
|
allb := make(map[string]IPBanInfo)
|
||||||
|
|
||||||
|
dm.RLock()
|
||||||
|
defer dm.RUnlock()
|
||||||
|
|
||||||
for name, info := range dm.addresses {
|
for name, info := range dm.addresses {
|
||||||
allb[name] = info.Info
|
allb[name] = info.Info
|
||||||
}
|
}
|
||||||
@ -118,13 +123,17 @@ func (dm *DLineManager) AddNetwork(network net.IPNet, length *IPRestrictTime, re
|
|||||||
OperReason: operReason,
|
OperReason: operReason,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
dm.Lock()
|
||||||
dm.networks[netString] = &dln
|
dm.networks[netString] = &dln
|
||||||
|
dm.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNetwork removes a network from the blocked list.
|
// RemoveNetwork removes a network from the blocked list.
|
||||||
func (dm *DLineManager) RemoveNetwork(network net.IPNet) {
|
func (dm *DLineManager) RemoveNetwork(network net.IPNet) {
|
||||||
netString := network.String()
|
netString := network.String()
|
||||||
|
dm.Lock()
|
||||||
delete(dm.networks, netString)
|
delete(dm.networks, netString)
|
||||||
|
dm.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddIP adds an IP address to the blocked list.
|
// AddIP adds an IP address to the blocked list.
|
||||||
@ -138,21 +147,27 @@ func (dm *DLineManager) AddIP(addr net.IP, length *IPRestrictTime, reason string
|
|||||||
OperReason: operReason,
|
OperReason: operReason,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
dm.Lock()
|
||||||
dm.addresses[addrString] = &dla
|
dm.addresses[addrString] = &dla
|
||||||
|
dm.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveIP removes an IP from the blocked list.
|
// RemoveIP removes an IP from the blocked list.
|
||||||
func (dm *DLineManager) RemoveIP(addr net.IP) {
|
func (dm *DLineManager) RemoveIP(addr net.IP) {
|
||||||
addrString := addr.String()
|
addrString := addr.String()
|
||||||
|
dm.Lock()
|
||||||
delete(dm.addresses, addrString)
|
delete(dm.addresses, addrString)
|
||||||
|
dm.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckIP returns whether or not an IP address was banned, and how long it is banned for.
|
// CheckIP returns whether or not an IP address was banned, and how long it is banned for.
|
||||||
func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
|
func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
|
||||||
// check IP addr
|
// check IP addr
|
||||||
addrString := addr.String()
|
addrString := addr.String()
|
||||||
|
dm.RLock()
|
||||||
addrInfo := dm.addresses[addrString]
|
addrInfo := dm.addresses[addrString]
|
||||||
|
dm.RUnlock()
|
||||||
|
|
||||||
if addrInfo != nil {
|
if addrInfo != nil {
|
||||||
if addrInfo.Info.Time != nil {
|
if addrInfo.Info.Time != nil {
|
||||||
if addrInfo.Info.Time.IsExpired() {
|
if addrInfo.Info.Time.IsExpired() {
|
||||||
@ -167,30 +182,32 @@ func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check networks
|
// check networks
|
||||||
var netsToRemove []net.IPNet
|
doCleanup := false
|
||||||
|
defer func() {
|
||||||
|
if doCleanup {
|
||||||
|
go func() {
|
||||||
|
dm.Lock()
|
||||||
|
defer dm.Unlock()
|
||||||
|
for key, netInfo := range dm.networks {
|
||||||
|
if netInfo.Info.Time.IsExpired() {
|
||||||
|
delete(dm.networks, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
dm.RLock()
|
||||||
|
defer dm.RUnlock()
|
||||||
|
|
||||||
for _, netInfo := range dm.networks {
|
for _, netInfo := range dm.networks {
|
||||||
if !netInfo.Network.Contains(addr) {
|
if netInfo.Info.Time != nil && netInfo.Info.Time.IsExpired() {
|
||||||
continue
|
// expired ban, ignore and clean up later
|
||||||
}
|
doCleanup = true
|
||||||
|
} else if netInfo.Network.Contains(addr) {
|
||||||
if netInfo.Info.Time != nil {
|
return true, &netInfo.Info
|
||||||
if netInfo.Info.Time.IsExpired() {
|
|
||||||
// ban on network has expired, remove it from our blocked list
|
|
||||||
netsToRemove = append(netsToRemove, netInfo.Network)
|
|
||||||
} else {
|
|
||||||
return true, &addrInfo.Info
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true, &addrInfo.Info
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove expired networks
|
|
||||||
for _, expiredNet := range netsToRemove {
|
|
||||||
dm.RemoveNetwork(expiredNet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// no matches!
|
// no matches!
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
54
irc/kline.go
54
irc/kline.go
@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/goshuirc/irc-go/ircfmt"
|
"github.com/goshuirc/irc-go/ircfmt"
|
||||||
@ -34,6 +35,7 @@ type KLineInfo struct {
|
|||||||
|
|
||||||
// KLineManager manages and klines.
|
// KLineManager manages and klines.
|
||||||
type KLineManager struct {
|
type KLineManager struct {
|
||||||
|
sync.RWMutex
|
||||||
// kline'd entries
|
// kline'd entries
|
||||||
entries map[string]*KLineInfo
|
entries map[string]*KLineInfo
|
||||||
}
|
}
|
||||||
@ -49,6 +51,8 @@ func NewKLineManager() *KLineManager {
|
|||||||
func (km *KLineManager) AllBans() map[string]IPBanInfo {
|
func (km *KLineManager) AllBans() map[string]IPBanInfo {
|
||||||
allb := make(map[string]IPBanInfo)
|
allb := make(map[string]IPBanInfo)
|
||||||
|
|
||||||
|
km.RLock()
|
||||||
|
defer km.RUnlock()
|
||||||
for name, info := range km.entries {
|
for name, info := range km.entries {
|
||||||
allb[name] = info.Info
|
allb[name] = info.Info
|
||||||
}
|
}
|
||||||
@ -67,48 +71,58 @@ func (km *KLineManager) AddMask(mask string, length *IPRestrictTime, reason stri
|
|||||||
OperReason: operReason,
|
OperReason: operReason,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
km.Lock()
|
||||||
km.entries[mask] = &kln
|
km.entries[mask] = &kln
|
||||||
|
km.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveMask removes a mask from the blocked list.
|
// RemoveMask removes a mask from the blocked list.
|
||||||
func (km *KLineManager) RemoveMask(mask string) {
|
func (km *KLineManager) RemoveMask(mask string) {
|
||||||
|
km.Lock()
|
||||||
delete(km.entries, mask)
|
delete(km.entries, mask)
|
||||||
|
km.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckMasks returns whether or not the hostmask(s) are banned, and how long they are banned for.
|
// CheckMasks returns whether or not the hostmask(s) are banned, and how long they are banned for.
|
||||||
func (km *KLineManager) CheckMasks(masks ...string) (isBanned bool, info *IPBanInfo) {
|
func (km *KLineManager) CheckMasks(masks ...string) (isBanned bool, info *IPBanInfo) {
|
||||||
// check networks
|
doCleanup := false
|
||||||
var masksToRemove []string
|
defer func() {
|
||||||
|
// asynchronously remove expired bans
|
||||||
|
if doCleanup {
|
||||||
|
go func() {
|
||||||
|
km.Lock()
|
||||||
|
defer km.Unlock()
|
||||||
|
for key, entry := range km.entries {
|
||||||
|
if entry.Info.Time.IsExpired() {
|
||||||
|
delete(km.entries, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
|
||||||
|
km.RLock()
|
||||||
|
defer km.RUnlock()
|
||||||
|
|
||||||
for _, entryInfo := range km.entries {
|
for _, entryInfo := range km.entries {
|
||||||
var matches bool
|
if entryInfo.Info.Time != nil && entryInfo.Info.Time.IsExpired() {
|
||||||
|
doCleanup = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := false
|
||||||
for _, mask := range masks {
|
for _, mask := range masks {
|
||||||
if entryInfo.Matcher.Match(mask) {
|
if entryInfo.Matcher.Match(mask) {
|
||||||
matches = true
|
matches = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !matches {
|
if matches {
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if entryInfo.Info.Time != nil {
|
|
||||||
if entryInfo.Info.Time.IsExpired() {
|
|
||||||
// ban on network has expired, remove it from our blocked list
|
|
||||||
masksToRemove = append(masksToRemove, entryInfo.Mask)
|
|
||||||
} else {
|
|
||||||
return true, &entryInfo.Info
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true, &entryInfo.Info
|
return true, &entryInfo.Info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove expired networks
|
|
||||||
for _, expiredMask := range masksToRemove {
|
|
||||||
km.RemoveMask(expiredMask)
|
|
||||||
}
|
|
||||||
|
|
||||||
// no matches!
|
// no matches!
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user