clientconfig.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package dns
  2. import (
  3. "bufio"
  4. "os"
  5. "strconv"
  6. "strings"
  7. )
  8. // ClientConfig wraps the contents of the /etc/resolv.conf file.
  9. type ClientConfig struct {
  10. Servers []string // servers to use
  11. Search []string // suffixes to append to local name
  12. Port string // what port to use
  13. Ndots int // number of dots in name to trigger absolute lookup
  14. Timeout int // seconds before giving up on packet
  15. Attempts int // lost packets before giving up on server, not used in the package dns
  16. }
  17. // ClientConfigFromFile parses a resolv.conf(5) like file and returns
  18. // a *ClientConfig.
  19. func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
  20. file, err := os.Open(resolvconf)
  21. if err != nil {
  22. return nil, err
  23. }
  24. defer file.Close()
  25. c := new(ClientConfig)
  26. scanner := bufio.NewScanner(file)
  27. c.Servers = make([]string, 0)
  28. c.Search = make([]string, 0)
  29. c.Port = "53"
  30. c.Ndots = 1
  31. c.Timeout = 5
  32. c.Attempts = 2
  33. for scanner.Scan() {
  34. if err := scanner.Err(); err != nil {
  35. return nil, err
  36. }
  37. line := scanner.Text()
  38. f := strings.Fields(line)
  39. if len(f) < 1 {
  40. continue
  41. }
  42. switch f[0] {
  43. case "nameserver": // add one name server
  44. if len(f) > 1 {
  45. // One more check: make sure server name is
  46. // just an IP address. Otherwise we need DNS
  47. // to look it up.
  48. name := f[1]
  49. c.Servers = append(c.Servers, name)
  50. }
  51. case "domain": // set search path to just this domain
  52. if len(f) > 1 {
  53. c.Search = make([]string, 1)
  54. c.Search[0] = f[1]
  55. } else {
  56. c.Search = make([]string, 0)
  57. }
  58. case "search": // set search path to given servers
  59. c.Search = make([]string, len(f)-1)
  60. for i := 0; i < len(c.Search); i++ {
  61. c.Search[i] = f[i+1]
  62. }
  63. case "options": // magic options
  64. for i := 1; i < len(f); i++ {
  65. s := f[i]
  66. switch {
  67. case len(s) >= 6 && s[:6] == "ndots:":
  68. n, _ := strconv.Atoi(s[6:])
  69. if n < 1 {
  70. n = 1
  71. }
  72. c.Ndots = n
  73. case len(s) >= 8 && s[:8] == "timeout:":
  74. n, _ := strconv.Atoi(s[8:])
  75. if n < 1 {
  76. n = 1
  77. }
  78. c.Timeout = n
  79. case len(s) >= 8 && s[:9] == "attempts:":
  80. n, _ := strconv.Atoi(s[9:])
  81. if n < 1 {
  82. n = 1
  83. }
  84. c.Attempts = n
  85. case s == "rotate":
  86. /* not imp */
  87. }
  88. }
  89. }
  90. }
  91. return c, nil
  92. }