add /etc/resolv.conf parsing from official go pkg
This commit is contained in:
parent
30e535b495
commit
f4257272fa
1
TODO
1
TODO
|
@ -3,6 +3,7 @@ Todo:
|
|||
* Cleanup the code
|
||||
* Tsig testing
|
||||
* Private key file parsing, exponent 65536 does not work
|
||||
* Parsing from /etc/resolv.conf
|
||||
|
||||
Longer term:
|
||||
* Parsing from strings, going with goyacc and own lexer
|
||||
|
|
|
@ -7,6 +7,8 @@ include $(GOROOT)/src/Make.inc
|
|||
TARG=dns/resolver
|
||||
GOFILES=\
|
||||
resolver.go\
|
||||
parse.go\
|
||||
config.go\
|
||||
|
||||
DEPS=..
|
||||
include $(GOROOT)/src/Make.pkg
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Read system DNS config from /etc/resolv.conf
|
||||
|
||||
package resolver
|
||||
|
||||
import ( "os"; "net" )
|
||||
|
||||
// See resolv.conf(5) on a Linux machine.
|
||||
// TODO(rsc): Supposed to call uname() and chop the beginning
|
||||
// of the host name to get the default search domain.
|
||||
// We assume it's in resolv.conf anyway.
|
||||
func dnsReadConfig() (*Resolver, os.Error) {
|
||||
file, err := open("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf := new(Resolver)
|
||||
conf.Servers = make([]string, 3)[0:0] // small, but the standard limit
|
||||
conf.Search = make([]string, 0)
|
||||
conf.Ndots = 1
|
||||
conf.Timeout = 5
|
||||
conf.Attempts = 2
|
||||
conf.Rotate = false
|
||||
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
|
||||
f := getFields(line)
|
||||
if len(f) < 1 {
|
||||
continue
|
||||
}
|
||||
switch f[0] {
|
||||
case "nameserver": // add one name server
|
||||
a := conf.Servers
|
||||
n := len(a)
|
||||
if len(f) > 1 && n < cap(a) {
|
||||
// One more check: make sure server name is
|
||||
// just an IP address. Otherwise we need DNS
|
||||
// to look it up.
|
||||
name := f[1]
|
||||
switch len(net.ParseIP(name)) {
|
||||
case 16:
|
||||
name = "[" + name + "]"
|
||||
fallthrough
|
||||
case 4:
|
||||
a = a[0 : n+1]
|
||||
a[n] = name
|
||||
conf.Servers = a
|
||||
}
|
||||
}
|
||||
|
||||
case "domain": // set search path to just this domain
|
||||
if len(f) > 1 {
|
||||
conf.Search = make([]string, 1)
|
||||
conf.Search[0] = f[1]
|
||||
} else {
|
||||
conf.Search = make([]string, 0)
|
||||
}
|
||||
|
||||
case "search": // set search path to given servers
|
||||
conf.Search = make([]string, len(f)-1)
|
||||
for i := 0; i < len(conf.Search); i++ {
|
||||
conf.Search[i] = f[i+1]
|
||||
}
|
||||
|
||||
case "options": // magic options
|
||||
for i := 1; i < len(f); i++ {
|
||||
s := f[i]
|
||||
switch {
|
||||
case len(s) >= 6 && s[0:6] == "ndots:":
|
||||
n, _, _ := dtoi(s, 6)
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
conf.Ndots = n
|
||||
case len(s) >= 8 && s[0:8] == "timeout:":
|
||||
n, _, _ := dtoi(s, 8)
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
conf.Timeout = n
|
||||
case len(s) >= 8 && s[0:9] == "attempts:":
|
||||
n, _, _ := dtoi(s, 9)
|
||||
if n < 1 {
|
||||
n = 1
|
||||
}
|
||||
conf.Attempts = n
|
||||
case s == "rotate":
|
||||
conf.Rotate = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close()
|
||||
return conf, nil
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Simple file i/o and string manipulation, to avoid
|
||||
// depending on strconv and bufio and strings.
|
||||
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type file struct {
|
||||
file *os.File
|
||||
data []byte
|
||||
atEOF bool
|
||||
}
|
||||
|
||||
func (f *file) close() { f.file.Close() }
|
||||
|
||||
func (f *file) getLineFromData() (s string, ok bool) {
|
||||
data := f.data
|
||||
i := 0
|
||||
for i = 0; i < len(data); i++ {
|
||||
if data[i] == '\n' {
|
||||
s = string(data[0:i])
|
||||
ok = true
|
||||
// move data
|
||||
i++
|
||||
n := len(data) - i
|
||||
copy(data[0:], data[i:])
|
||||
f.data = data[0:n]
|
||||
return
|
||||
}
|
||||
}
|
||||
if f.atEOF && len(f.data) > 0 {
|
||||
// EOF, return all we have
|
||||
s = string(data)
|
||||
f.data = f.data[0:0]
|
||||
ok = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (f *file) readLine() (s string, ok bool) {
|
||||
if s, ok = f.getLineFromData(); ok {
|
||||
return
|
||||
}
|
||||
if len(f.data) < cap(f.data) {
|
||||
ln := len(f.data)
|
||||
n, err := io.ReadFull(f.file, f.data[ln:cap(f.data)])
|
||||
if n >= 0 {
|
||||
f.data = f.data[0 : ln+n]
|
||||
}
|
||||
if err == os.EOF {
|
||||
f.atEOF = true
|
||||
}
|
||||
}
|
||||
s, ok = f.getLineFromData()
|
||||
return
|
||||
}
|
||||
|
||||
func open(name string) (*file, os.Error) {
|
||||
fd, err := os.Open(name, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &file{fd, make([]byte, 1024)[0:0], false}, nil
|
||||
}
|
||||
|
||||
func byteIndex(s string, c byte) int {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == c {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Count occurrences in s of any bytes in t.
|
||||
func countAnyByte(s string, t string) int {
|
||||
n := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if byteIndex(t, s[i]) >= 0 {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Split s at any bytes in t.
|
||||
func splitAtBytes(s string, t string) []string {
|
||||
a := make([]string, 1+countAnyByte(s, t))
|
||||
n := 0
|
||||
last := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if byteIndex(t, s[i]) >= 0 {
|
||||
if last < i {
|
||||
a[n] = string(s[last:i])
|
||||
n++
|
||||
}
|
||||
last = i + 1
|
||||
}
|
||||
}
|
||||
if last < len(s) {
|
||||
a[n] = string(s[last:])
|
||||
n++
|
||||
}
|
||||
return a[0:n]
|
||||
}
|
||||
|
||||
func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
|
||||
|
||||
// Bigger than we need, not too big to worry about overflow
|
||||
const big = 0xFFFFFF
|
||||
|
||||
// Decimal to integer starting at &s[i0].
|
||||
// Returns number, new offset, success.
|
||||
func dtoi(s string, i0 int) (n int, i int, ok bool) {
|
||||
n = 0
|
||||
for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
||||
n = n*10 + int(s[i]-'0')
|
||||
if n >= big {
|
||||
return 0, i, false
|
||||
}
|
||||
}
|
||||
if i == i0 {
|
||||
return 0, i, false
|
||||
}
|
||||
return n, i, true
|
||||
}
|
||||
|
||||
// Hexadecimal to integer starting at &s[i0].
|
||||
// Returns number, new offset, success.
|
||||
func xtoi(s string, i0 int) (n int, i int, ok bool) {
|
||||
n = 0
|
||||
for i = i0; i < len(s); i++ {
|
||||
if '0' <= s[i] && s[i] <= '9' {
|
||||
n *= 16
|
||||
n += int(s[i] - '0')
|
||||
} else if 'a' <= s[i] && s[i] <= 'f' {
|
||||
n *= 16
|
||||
n += int(s[i]-'a') + 10
|
||||
} else if 'A' <= s[i] && s[i] <= 'F' {
|
||||
n *= 16
|
||||
n += int(s[i]-'A') + 10
|
||||
} else {
|
||||
break
|
||||
}
|
||||
if n >= big {
|
||||
return 0, i, false
|
||||
}
|
||||
}
|
||||
if i == i0 {
|
||||
return 0, i, false
|
||||
}
|
||||
return n, i, true
|
||||
}
|
||||
|
||||
// Integer to decimal.
|
||||
func itoa(i int) string {
|
||||
var buf [30]byte
|
||||
n := len(buf)
|
||||
neg := false
|
||||
if i < 0 {
|
||||
i = -i
|
||||
neg = true
|
||||
}
|
||||
ui := uint(i)
|
||||
for ui > 0 || n == len(buf) {
|
||||
n--
|
||||
buf[n] = byte('0' + ui%10)
|
||||
ui /= 10
|
||||
}
|
||||
if neg {
|
||||
n--
|
||||
buf[n] = '-'
|
||||
}
|
||||
return string(buf[n:])
|
||||
}
|
||||
|
||||
// Number of occurrences of b in s.
|
||||
func count(s string, b byte) int {
|
||||
n := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == b {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Returns the prefix of s up to but not including the character c
|
||||
func prefixBefore(s string, c byte) string {
|
||||
for i, v := range s {
|
||||
if v == int(c) {
|
||||
return s[0:i]
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Index of rightmost occurrence of b in s.
|
||||
func last(s string, b byte) int {
|
||||
i := len(s)
|
||||
for i--; i >= 0; i-- {
|
||||
if s[i] == b {
|
||||
break
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
Loading…
Reference in New Issue