153 lines
3.5 KiB
Go
153 lines
3.5 KiB
Go
package net_utils
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
|
|
common_utils "nettools/common"
|
|
)
|
|
|
|
var (
|
|
ErrInitializingRequest = errors.New("error while initializing the request")
|
|
ErrReadingBody = errors.New("err while reading the body")
|
|
ErrDialingServ = errors.New("err while dealing the server")
|
|
ErrInterfaceNotFound = errors.New("provided network interface name wasn't found")
|
|
)
|
|
|
|
const (
|
|
DEFAULT_HTTP_PORT = 80
|
|
DEFAULT_WS_PORT = 80
|
|
DEFAULT_WSS_PORT = 443
|
|
DEFAULT_HTTPS_PORT = 443
|
|
DEFAULT_GRPC_PORT = 9090
|
|
)
|
|
|
|
const (
|
|
// network masks
|
|
MASK8 uint32 = 0b11111111_00000000_00000000_00000000
|
|
MASK12 uint32 = 0b11111111_11110000_00000000_00000000
|
|
MASK16 uint32 = 0b11111111_11111111_00000000_00000000
|
|
MASK24 uint32 = 0b11111111_11111111_11111111_00000000
|
|
MASK32 uint32 = 0b11111111_11111111_11111111_11111111
|
|
// reserved IP adresses
|
|
IP_192_168_0_0 uint32 = 0b11000000_10101000_00000000_00000000
|
|
IP_172_16_0_0 uint32 = 0b10101100_00010000_00000000_00000000
|
|
IP_10_0_0_0 uint32 = 0b00001010_00000000_00000000_00000000
|
|
// reserved for Local Network IP addresses
|
|
PRESERVED_IP_RANGE_192 uint32 = IP_192_168_0_0 & MASK16
|
|
PRESERVED_IP_RANGE_172 uint32 = IP_172_16_0_0 & MASK12
|
|
PRESERVED_IP_RANGE_10 uint32 = IP_10_0_0_0 & MASK8
|
|
)
|
|
|
|
func MaskToBytes[T common_utils.Int](mask T) [4]uint8 {
|
|
if mask > 32 {
|
|
panic("mask is invalid: value out of range")
|
|
}
|
|
var out [4]uint8
|
|
for i := 0; i < 4; i++ {
|
|
if mask >= 8 {
|
|
out[i] = 0b11111111
|
|
mask -= 8
|
|
} else {
|
|
out[i] = 1<<mask - 1
|
|
out[i] = out[i] << (8 - mask)
|
|
break
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func BytesToUint32(in []uint8) (uint32, error) {
|
|
bytes := make([]uint8, 4)
|
|
if len(bytes) > 4 {
|
|
return 0, errors.New("bad input value length, expected up to 4 bytes")
|
|
}
|
|
copy(in, bytes)
|
|
return uint32(
|
|
bytes[0])<<24 |
|
|
uint32(bytes[1])<<16 |
|
|
uint32(bytes[2])<<8 |
|
|
uint32(bytes[3]), nil
|
|
}
|
|
|
|
type NetInterfaceNamesT = map[string]struct{}
|
|
|
|
// Those are ones I have on my machine, so they are default, lol
|
|
var DefaultNetInterfaceNames = NetInterfaceNamesT{
|
|
"eth0": {},
|
|
"wlan0": {},
|
|
}
|
|
|
|
// Converts IP which is a byte array to an integer
|
|
// So it can be used with the bitmasks or be compared fast
|
|
func IpToInt(ip net.IP) uint32 {
|
|
if len(ip) == 16 {
|
|
return binary.BigEndian.Uint32(ip[12:16])
|
|
}
|
|
return binary.BigEndian.Uint32(ip)
|
|
}
|
|
|
|
func GetWanIP(ipv4 bool) (net.IP, error) {
|
|
url := "http://4.ident.me"
|
|
if !ipv4 {
|
|
url = "http://6.ident.me"
|
|
}
|
|
|
|
req, err := http.Get(url)
|
|
if err != nil {
|
|
return nil, errors.Join(ErrInitializingRequest, err)
|
|
}
|
|
defer req.Body.Close()
|
|
|
|
body, err := io.ReadAll(req.Body)
|
|
if err != nil {
|
|
return nil, errors.Join(ErrReadingBody, err)
|
|
}
|
|
return net.ParseIP(string(body)), err
|
|
}
|
|
|
|
func GetLanIP(interfaceNames NetInterfaceNamesT) (net.IP, error) {
|
|
if interfaceNames == nil {
|
|
interfaceNames = DefaultNetInterfaceNames
|
|
}
|
|
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, i := range ifaces {
|
|
if i.Name != "" {
|
|
_, whitelisted := interfaceNames[i.Name]
|
|
if !whitelisted {
|
|
continue
|
|
}
|
|
}
|
|
addrs, err := i.Addrs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
var ip net.IP
|
|
switch v := addr.(type) {
|
|
case *net.IPNet:
|
|
ip = v.IP
|
|
case *net.IPAddr:
|
|
ip = v.IP
|
|
}
|
|
|
|
intIP := IpToInt(ip)
|
|
if intIP&MASK16 == PRESERVED_IP_RANGE_192 ||
|
|
intIP&MASK12 == PRESERVED_IP_RANGE_172 ||
|
|
intIP&MASK8 == PRESERVED_IP_RANGE_10 {
|
|
return ip, nil
|
|
}
|
|
}
|
|
}
|
|
return nil, ErrInterfaceNotFound
|
|
}
|