| package resolvconf |
| |
| import ( |
| "bytes" |
| "io/ioutil" |
| "regexp" |
| "strings" |
| ) |
| |
| var ( |
| nsRegexp = regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`) |
| searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`) |
| ) |
| |
| func Get() ([]byte, error) { |
| resolv, err := ioutil.ReadFile("/etc/resolv.conf") |
| if err != nil { |
| return nil, err |
| } |
| return resolv, nil |
| } |
| |
| // getLines parses input into lines and strips away comments. |
| func getLines(input []byte, commentMarker []byte) [][]byte { |
| lines := bytes.Split(input, []byte("\n")) |
| var output [][]byte |
| for _, currentLine := range lines { |
| var commentIndex = bytes.Index(currentLine, commentMarker) |
| if commentIndex == -1 { |
| output = append(output, currentLine) |
| } else { |
| output = append(output, currentLine[:commentIndex]) |
| } |
| } |
| return output |
| } |
| |
| // GetNameservers returns nameservers (if any) listed in /etc/resolv.conf |
| func GetNameservers(resolvConf []byte) []string { |
| nameservers := []string{} |
| for _, line := range getLines(resolvConf, []byte("#")) { |
| var ns = nsRegexp.FindSubmatch(line) |
| if len(ns) > 0 { |
| nameservers = append(nameservers, string(ns[1])) |
| } |
| } |
| return nameservers |
| } |
| |
| // GetNameserversAsCIDR returns nameservers (if any) listed in |
| // /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32") |
| // This function's output is intended for net.ParseCIDR |
| func GetNameserversAsCIDR(resolvConf []byte) []string { |
| nameservers := []string{} |
| for _, nameserver := range GetNameservers(resolvConf) { |
| nameservers = append(nameservers, nameserver+"/32") |
| } |
| return nameservers |
| } |
| |
| // GetSearchDomains returns search domains (if any) listed in /etc/resolv.conf |
| // If more than one search line is encountered, only the contents of the last |
| // one is returned. |
| func GetSearchDomains(resolvConf []byte) []string { |
| domains := []string{} |
| for _, line := range getLines(resolvConf, []byte("#")) { |
| match := searchRegexp.FindSubmatch(line) |
| if match == nil { |
| continue |
| } |
| domains = strings.Fields(string(match[1])) |
| } |
| return domains |
| } |
| |
| func Build(path string, dns, dnsSearch []string) error { |
| content := bytes.NewBuffer(nil) |
| for _, dns := range dns { |
| if _, err := content.WriteString("nameserver " + dns + "\n"); err != nil { |
| return err |
| } |
| } |
| if len(dnsSearch) > 0 { |
| if searchString := strings.Join(dnsSearch, " "); strings.Trim(searchString, " ") != "." { |
| if _, err := content.WriteString("search " + searchString + "\n"); err != nil { |
| return err |
| } |
| } |
| } |
| |
| return ioutil.WriteFile(path, content.Bytes(), 0644) |
| } |