1package bridge
2
3import (
4	"bytes"
5	"io/ioutil"
6	"regexp"
7)
8
9const (
10	ipv4NumBlock = `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)`
11	ipv4Address  = `(` + ipv4NumBlock + `\.){3}` + ipv4NumBlock
12
13	// This is not an IPv6 address verifier as it will accept a super-set of IPv6, and also
14	// will *not match* IPv4-Embedded IPv6 Addresses (RFC6052), but that and other variants
15	// -- e.g. other link-local types -- either won't work in containers or are unnecessary.
16	// For readability and sufficiency for Docker purposes this seemed more reasonable than a
17	// 1000+ character regexp with exact and complete IPv6 validation
18	ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})`
19)
20
21var nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
22
23func readResolvConf() ([]byte, error) {
24	resolv, err := ioutil.ReadFile("/etc/resolv.conf")
25	if err != nil {
26		return nil, err
27	}
28	return resolv, nil
29}
30
31// getLines parses input into lines and strips away comments.
32func getLines(input []byte, commentMarker []byte) [][]byte {
33	lines := bytes.Split(input, []byte("\n"))
34	var output [][]byte
35	for _, currentLine := range lines {
36		var commentIndex = bytes.Index(currentLine, commentMarker)
37		if commentIndex == -1 {
38			output = append(output, currentLine)
39		} else {
40			output = append(output, currentLine[:commentIndex])
41		}
42	}
43	return output
44}
45
46// GetNameserversAsCIDR returns nameservers (if any) listed in
47// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
48// This function's output is intended for net.ParseCIDR
49func getNameserversAsCIDR(resolvConf []byte) []string {
50	nameservers := []string{}
51	for _, nameserver := range getNameservers(resolvConf) {
52		nameservers = append(nameservers, nameserver+"/32")
53	}
54	return nameservers
55}
56
57// GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
58func getNameservers(resolvConf []byte) []string {
59	nameservers := []string{}
60	for _, line := range getLines(resolvConf, []byte("#")) {
61		var ns = nsRegexp.FindSubmatch(line)
62		if len(ns) > 0 {
63			nameservers = append(nameservers, string(ns[1]))
64		}
65	}
66	return nameservers
67}
68