mirror of https://github.com/0xERR0R/blocky.git
92 lines
1.8 KiB
Go
92 lines
1.8 KiB
Go
package util
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
IPv4PtrSuffix = ".in-addr.arpa."
|
|
IPv6PtrSuffix = ".ip6.arpa."
|
|
|
|
byteBits = 8
|
|
)
|
|
|
|
var ErrInvalidArpaAddrLen = errors.New("arpa hostname is not of expected length")
|
|
|
|
func ParseIPFromArpaAddr(arpa string) (net.IP, error) {
|
|
if strings.HasSuffix(arpa, IPv4PtrSuffix) {
|
|
return parseIPv4FromArpaAddr(arpa)
|
|
}
|
|
|
|
if strings.HasSuffix(arpa, IPv6PtrSuffix) {
|
|
return parseIPv6FromArpaAddr(arpa)
|
|
}
|
|
|
|
return nil, fmt.Errorf("invalid arpa hostname: %s", arpa)
|
|
}
|
|
|
|
func parseIPv4FromArpaAddr(arpa string) (net.IP, error) {
|
|
const base10 = 10
|
|
|
|
revAddr := strings.TrimSuffix(arpa, IPv4PtrSuffix)
|
|
|
|
parts := strings.Split(revAddr, ".")
|
|
if len(parts) != net.IPv4len {
|
|
return nil, ErrInvalidArpaAddrLen
|
|
}
|
|
|
|
buf := make([]byte, 0, net.IPv4len)
|
|
|
|
// Parse and add each byte, in reverse, to the buffer
|
|
for i := len(parts) - 1; i >= 0; i-- {
|
|
part, err := strconv.ParseUint(parts[i], base10, byteBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
buf = append(buf, byte(part))
|
|
}
|
|
|
|
return net.IPv4(buf[0], buf[1], buf[2], buf[3]), nil
|
|
}
|
|
|
|
func parseIPv6FromArpaAddr(arpa string) (net.IP, error) {
|
|
const (
|
|
base16 = 16
|
|
ipv6Bytes = 2 * net.IPv6len
|
|
nibbleBits = byteBits / 2
|
|
)
|
|
|
|
revAddr := strings.TrimSuffix(arpa, IPv6PtrSuffix)
|
|
|
|
parts := strings.Split(revAddr, ".")
|
|
if len(parts) != ipv6Bytes {
|
|
return nil, ErrInvalidArpaAddrLen
|
|
}
|
|
|
|
buf := make([]byte, 0, net.IPv6len)
|
|
|
|
// Parse and add each byte, in reverse, to the buffer
|
|
for i := len(parts) - 1; i >= 0; i -= 2 {
|
|
msNibble, err := strconv.ParseUint(parts[i], base16, byteBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
lsNibble, err := strconv.ParseUint(parts[i-1], base16, byteBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
part := msNibble<<nibbleBits | lsNibble
|
|
|
|
buf = append(buf, byte(part))
|
|
}
|
|
|
|
return net.IP(buf), nil
|
|
}
|