-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgetdns.go
115 lines (103 loc) · 3.11 KB
/
getdns.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package getdns
// #cgo LDFLAGS: -lgetdns
// #include <getdns/getdns_extra.h>
import "C"
import (
"fmt"
"strings"
"unsafe"
)
// List is a Go type representing a getdns_list.
type List []interface{}
// Dict is a Go type representing a getdns_dict.
type Dict map[string]interface{}
// Error reports a getdns return code.
type Error interface {
error
ReturnCode() ReturnCode
}
type returnCodeError struct {
rc ReturnCode
}
// Code returns the getdns numeric return code.
func (err *returnCodeError) ReturnCode() ReturnCode {
return err.rc
}
// Error implements the error interface and returns a printable
// description of the error.
func (err *returnCodeError) Error() string {
return fmt.Sprintf("getdns error %d: %s", err.rc, C.GoString(C.getdns_get_errorstr_by_id(C.uint16_t(err.rc))))
}
// ConvertDNSNametoFQDN converts a name in DNS label format to a FQDN.
// It reimplements the getdns library routine in pure Go rather than
// calling into the library.
func ConvertDNSNameToFQDN(b []byte) (string, error) {
res := ""
p := 0
if len(b) < 1 {
return "", &returnCodeError{RETURN_BAD_DOMAIN_NAME}
}
for b[p] != 0 {
labelLen := int(b[p])
p = p + 1
if labelLen > 63 || p+labelLen >= len(b) {
return "", &returnCodeError{RETURN_BAD_DOMAIN_NAME}
}
labelContent := b[p : p+labelLen]
res = res + string(labelContent) + "."
p = p + int(labelLen)
}
if len(res) == 0 {
res = "."
}
return res, nil
}
// ConvertFQDNToDNSName converts a name to DNS label format.
// It reimplements the getdns library routine in pure Go rather than
// calling into the library. This implementation does not insist that
// the name is in fact a FQDN; "www.example.com" produces the same
// output as "www.example.com.".
func ConvertFQDNToDNSName(s string) ([]byte, error) {
chunks := strings.Split(s, ".")
reslen := len(chunks) + 1
for _, c := range chunks {
if len(c) > 63 {
return nil, &returnCodeError{RETURN_INVALID_PARAMETER}
}
reslen += len(c)
}
res := make([]byte, reslen)
pos := 0
for _, c := range chunks {
res[pos] = byte(len(c))
pos++
copy(res[pos:], []byte(c))
pos += len(c)
}
res[pos] = 0
return res, nil
}
// Convert IDN ASCII label to Unicode, translating Punycode if present.
func ALabelToULabel(s string) (string, error) {
cname := C.CString(s)
defer C.free(unsafe.Pointer(cname))
cres := C.getdns_convert_alabel_to_ulabel(cname)
if cres == nil {
return "", &returnCodeError{RETURN_INVALID_PARAMETER}
}
res := C.GoString(cres)
C.free(unsafe.Pointer(cres))
return res, nil
}
// Convert IDN Unicode label to ASCII, performing Punycode encoding if
func ULabelToALabel(s string) (string, error) {
cname := C.CString(s)
defer C.free(unsafe.Pointer(cname))
cres := C.getdns_convert_ulabel_to_alabel(cname)
if cres == nil {
return "", &returnCodeError{RETURN_INVALID_PARAMETER}
}
res := C.GoString(cres)
C.free(unsafe.Pointer(cres))
return res, nil
}