200 lines
4.6 KiB
Go
200 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
"net"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/pyke369/golang-support/rcache"
|
|
)
|
|
|
|
func stringInSlice(a string, list []string) bool {
|
|
for _, b := range list {
|
|
if b == a {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// inArray checks if there is a member of "search" in "list". sort list to be more
|
|
// efficiant. adapt with sorting "search" too
|
|
func inArray(search, list []string) bool {
|
|
sort.Strings(list)
|
|
for _, g := range search {
|
|
i := sort.Search(len(list), func(i int) bool { return list[i] >= g })
|
|
if i < len(list) && list[i] == g {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// printJSON pretty print d
|
|
func printJSON(d interface{}) []byte {
|
|
ret, _ := json.MarshalIndent(d, " ", " ")
|
|
return ret
|
|
}
|
|
|
|
// reverse the part order on every member of the array
|
|
func reverse(s string) string {
|
|
part := strings.Split(s, ".")
|
|
for i, j := 0, len(part)-1; i < j; i, j = i+1, j-1 {
|
|
part[i], part[j] = part[j], part[i]
|
|
}
|
|
return strings.Join(part, ".")
|
|
}
|
|
|
|
// domainSort sort string by first reversing them
|
|
func domainSort(s []string) {
|
|
for i := range s {
|
|
s[i] = reverse(s[i])
|
|
}
|
|
sort.Strings(s)
|
|
for i := range s {
|
|
s[i] = reverse(s[i])
|
|
}
|
|
}
|
|
|
|
func ptrToIP(s string) string {
|
|
s = reverse(s)
|
|
count := 0
|
|
ip := ""
|
|
version := 4
|
|
for _, elt := range strings.Split(s, ".") {
|
|
switch elt {
|
|
case "":
|
|
case "ip6":
|
|
version = 6
|
|
case "in-addr":
|
|
case "arpa":
|
|
default:
|
|
count++
|
|
ip += elt
|
|
if version == 4 && count != 4 {
|
|
ip += "."
|
|
}
|
|
if version == 6 && count%4 == 0 && count != 32 {
|
|
ip += ":"
|
|
}
|
|
}
|
|
}
|
|
return ip
|
|
}
|
|
|
|
func ipToInt(ip string) *big.Int {
|
|
return big.NewInt(0).SetBytes([]byte(net.ParseIP(ip)))
|
|
}
|
|
|
|
// iPtoReverse calculate the reverse name associated with an IPv4 or v6
|
|
func iPtoReverse(ip net.IP) (arpa string) {
|
|
const hexDigit = "0123456789abcdef"
|
|
// code copied and adapted from the net library
|
|
// ip can be 4 or 16 bytes long
|
|
if ip.To4() != nil {
|
|
if len(ip) == 16 {
|
|
return uitoa(uint(ip[15])) + "." + uitoa(uint(ip[14])) + "." + uitoa(uint(ip[13])) + "." + uitoa(uint(ip[12])) + ".in-addr.arpa."
|
|
}
|
|
return uitoa(uint(ip[3])) + "." + uitoa(uint(ip[2])) + "." + uitoa(uint(ip[1])) + "." + uitoa(uint(ip[0])) + ".in-addr.arpa."
|
|
}
|
|
// Must be IPv6
|
|
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
|
|
|
|
// Add it, in reverse, to the buffer
|
|
for i := len(ip) - 1; i >= 0; i-- {
|
|
v := ip[i]
|
|
buf = append(buf, hexDigit[v&0xF])
|
|
buf = append(buf, '.')
|
|
buf = append(buf, hexDigit[v>>4])
|
|
buf = append(buf, '.')
|
|
}
|
|
// Append "ip6.arpa." and return (buf already has the final .)
|
|
buf = append(buf, "ip6.arpa."...)
|
|
return string(buf)
|
|
}
|
|
|
|
// Convert unsigned integer to decimal string.
|
|
// code copied from the net library
|
|
func uitoa(val uint) string {
|
|
if val == 0 { // avoid string allocation
|
|
return "0"
|
|
}
|
|
var buf [20]byte // big enough for 64bit value base 10
|
|
i := len(buf) - 1
|
|
for val >= 10 {
|
|
q := val / 10
|
|
buf[i] = byte('0' + val - q*10)
|
|
i--
|
|
val = q
|
|
}
|
|
// val < 10
|
|
buf[i] = byte('0' + val)
|
|
return string(buf[i:])
|
|
}
|
|
|
|
func trimPoint(s string) string {
|
|
return strings.TrimRight(s, ".")
|
|
}
|
|
|
|
func addPoint(s string) string {
|
|
s = trimPoint(s)
|
|
if !strings.HasSuffix(s, ".") && !strings.HasSuffix(s, "*") {
|
|
s = s + "."
|
|
}
|
|
return s
|
|
}
|
|
|
|
// add double quotes at the begining and the end of the string.
|
|
func addQuotes(s string) string {
|
|
const q = "\""
|
|
s = strings.Trim(s, q)
|
|
s = strings.Replace(s, q, "\\\"", -1)
|
|
return q + s + q
|
|
}
|
|
|
|
func validSRVName(s string) bool {
|
|
return rcache.Get("^_[a-z0-9]+\\._(tcp|udp|tls)[^ ]+$").MatchString(s)
|
|
}
|
|
|
|
func validSRV(s string) string {
|
|
// _service._proto.name. TTL class SRV priority weight port target.
|
|
match := rcache.Get("^([0-9]+) +([0-9]+) +([0-9]+) +(.+)$").FindStringSubmatch(s)
|
|
if len(match) > 0 && validName(match[4], false) {
|
|
return match[4]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func validName(s string, wildcard bool) bool {
|
|
if !wildcard {
|
|
return rcache.Get(
|
|
"^(([a-z0-9]|[a-z0-9_][a-z0-9_\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.$").MatchString(s)
|
|
}
|
|
return rcache.Get(
|
|
"^(\\*\\.)?(([a-z0-9]|[a-z0-9_][a-z0-9_\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.$").MatchString(s)
|
|
}
|
|
|
|
func validMX(s string) string {
|
|
match := rcache.Get("^([0-9]+) +(.+)$").FindStringSubmatch(s)
|
|
if len(match) > 0 && validName(match[2], false) {
|
|
return match[2]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func validCAA(s string) string {
|
|
match := rcache.Get("^([0-9]+) +(issue|issuewild|iodef) +(.+)$").FindStringSubmatch(s)
|
|
if len(match) == 0 {
|
|
return ""
|
|
}
|
|
i, _ := strconv.Atoi(match[1])
|
|
if i < 0 || i > 255 {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("%s %s %s", match[1], match[2], addQuotes(match[3]))
|
|
}
|