resolvconf.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package resolvconf
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "regexp"
  6. "strings"
  7. )
  8. var (
  9. nsRegexp = regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`)
  10. searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
  11. )
  12. func Get() ([]byte, error) {
  13. resolv, err := ioutil.ReadFile("/etc/resolv.conf")
  14. if err != nil {
  15. return nil, err
  16. }
  17. return resolv, nil
  18. }
  19. // getLines parses input into lines and strips away comments.
  20. func getLines(input []byte, commentMarker []byte) [][]byte {
  21. lines := bytes.Split(input, []byte("\n"))
  22. var output [][]byte
  23. for _, currentLine := range lines {
  24. var commentIndex = bytes.Index(currentLine, commentMarker)
  25. if commentIndex == -1 {
  26. output = append(output, currentLine)
  27. } else {
  28. output = append(output, currentLine[:commentIndex])
  29. }
  30. }
  31. return output
  32. }
  33. // GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
  34. func GetNameservers(resolvConf []byte) []string {
  35. nameservers := []string{}
  36. for _, line := range getLines(resolvConf, []byte("#")) {
  37. var ns = nsRegexp.FindSubmatch(line)
  38. if len(ns) > 0 {
  39. nameservers = append(nameservers, string(ns[1]))
  40. }
  41. }
  42. return nameservers
  43. }
  44. // GetNameserversAsCIDR returns nameservers (if any) listed in
  45. // /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
  46. // This function's output is intended for net.ParseCIDR
  47. func GetNameserversAsCIDR(resolvConf []byte) []string {
  48. nameservers := []string{}
  49. for _, nameserver := range GetNameservers(resolvConf) {
  50. nameservers = append(nameservers, nameserver+"/32")
  51. }
  52. return nameservers
  53. }
  54. // GetSearchDomains returns search domains (if any) listed in /etc/resolv.conf
  55. // If more than one search line is encountered, only the contents of the last
  56. // one is returned.
  57. func GetSearchDomains(resolvConf []byte) []string {
  58. domains := []string{}
  59. for _, line := range getLines(resolvConf, []byte("#")) {
  60. match := searchRegexp.FindSubmatch(line)
  61. if match == nil {
  62. continue
  63. }
  64. domains = strings.Fields(string(match[1]))
  65. }
  66. return domains
  67. }
  68. func Build(path string, dns, dnsSearch []string) error {
  69. content := bytes.NewBuffer(nil)
  70. for _, dns := range dns {
  71. if _, err := content.WriteString("nameserver " + dns + "\n"); err != nil {
  72. return err
  73. }
  74. }
  75. if len(dnsSearch) > 0 {
  76. if searchString := strings.Join(dnsSearch, " "); strings.Trim(searchString, " ") != "." {
  77. if _, err := content.WriteString("search " + searchString + "\n"); err != nil {
  78. return err
  79. }
  80. }
  81. }
  82. return ioutil.WriteFile(path, content.Bytes(), 0644)
  83. }