Files
pg/disco/local_addr.go
2025-05-06 18:45:20 +08:00

138 lines
2.8 KiB
Go

package disco
import (
"log/slog"
"net"
"net/netip"
"slices"
"strings"
)
type cidrs []net.IPNet
func (cs *cidrs) Contains(ip net.IP) bool {
for _, cidr := range *cs {
if cidr.Contains(ip) {
return true
}
}
return false
}
type interfaceNamePrefixs []string
func (inp *interfaceNamePrefixs) HasPrefix(interfaceName string) bool {
for _, ifaceNamePrefix := range *inp {
if strings.HasPrefix(interfaceName, ifaceNamePrefix) {
return true
}
}
return false
}
var (
ignoredLocalCIDRs cidrs
ignoredLocalInterfaceNamePrefixs interfaceNamePrefixs
localIPs []net.IP
)
func SetIgnoredLocalCIDRs(cidrs ...string) {
ignoredLocalCIDRs = ignoredLocalCIDRs[:0]
AddIgnoredLocalCIDRs(cidrs...)
}
func AddIgnoredLocalCIDRs(cidrs ...string) {
for _, cidr := range cidrs {
_, _cidr, err := net.ParseCIDR(cidr)
if err != nil {
slog.Debug("SetIgnoredLocalCIDRs parse cidr failed", "err", err)
continue
}
if _cidr.IP.IsUnspecified() {
continue
}
slog.Debug("IgnoreLocalCIDR " + cidr)
ignoredLocalCIDRs = append(ignoredLocalCIDRs, *_cidr)
}
}
func RemoveIgnoredLocalCIDRs(cidrs ...string) {
var filterd []net.IPNet
for _, cidr := range ignoredLocalCIDRs {
if !slices.Contains(cidrs, cidr.String()) {
filterd = append(filterd, cidr)
}
}
ignoredLocalCIDRs = filterd
}
func IsIgnoredLocalIP(ip net.IP) bool {
return ignoredLocalCIDRs.Contains(ip)
}
func GetIgnoredLocalCIDRs() []net.IPNet {
return slices.Clone(ignoredLocalCIDRs)
}
func SetIgnoredLocalInterfaceNamePrefixs(prefixs ...string) {
ignoredLocalInterfaceNamePrefixs = prefixs
for _, prefix := range prefixs {
slog.Debug("IgnoreInterface", "prefix", prefix)
}
}
func SetLocalIPs(ips ...net.IP) {
localIPs = ips
}
func GetIgnoredLocalInterfaceNamePrefixs() []string {
return slices.Clone(ignoredLocalInterfaceNamePrefixs)
}
func ListLocalIPs() ([]net.IP, error) {
if len(localIPs) > 0 {
return localIPs, nil
}
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
var ips []net.IP
for _, iface := range ifaces {
if iface.Flags&net.FlagRunning != net.FlagRunning {
continue
}
if ignoredLocalInterfaceNamePrefixs.HasPrefix(iface.Name) {
continue
}
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok {
if ipnet.IP.IsLoopback() {
continue
}
if ipnet.IP.IsLinkLocalUnicast() {
continue
}
if ignoredLocalCIDRs.Contains(ipnet.IP) {
continue
}
ips = append(ips, ipnet.IP)
}
}
}
return ips, nil
}
var carrierGradeNAT = netip.MustParsePrefix("100.64.0.0/10")
func IsCGN(ip net.IP) bool {
if ip.To4() == nil {
return false
}
return carrierGradeNAT.Contains(netip.AddrFrom4([4]byte(ip.To4())))
}