|
|
|
|
@ -38,11 +38,31 @@ func (m *resolvdManager) SetDNS(config OSConfig) error {
|
|
|
|
|
m.ifName,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
origResolv, err := m.readAndCopy(resolvConf, backupConf, 0644)
|
|
|
|
|
// first, read in the resolvConf
|
|
|
|
|
origResolv, err := m.fs.ReadFile(resolvConf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
newResolvConf := removeSearchLines(origResolv)
|
|
|
|
|
|
|
|
|
|
// search for our sentinel in resolvConf, if it's not present
|
|
|
|
|
// it's our first call to SetDNS, and we should make backupConf
|
|
|
|
|
resolvConfOwned := bytes.Contains(origResolv, []byte("generated by tailscale"))
|
|
|
|
|
if !resolvConfOwned {
|
|
|
|
|
_, err = m.fs.Stat(backupConf)
|
|
|
|
|
if err != nil && os.IsNotExist(err) {
|
|
|
|
|
_, err = m.readAndCopy(resolvConf, backupConf, 0644)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove resolvd nameservers and search lines
|
|
|
|
|
origResolv = removeSearchLines(origResolv)
|
|
|
|
|
origResolv = removeResolvdNameserverLines(origResolv)
|
|
|
|
|
// and clean up whitespace
|
|
|
|
|
removeBlanks := regexp.MustCompile(`(?m)^\s*\n`)
|
|
|
|
|
origResolv = removeBlanks.ReplaceAll(origResolv, []byte(""))
|
|
|
|
|
|
|
|
|
|
for _, ns := range config.Nameservers {
|
|
|
|
|
args = append(args, ns.String())
|
|
|
|
|
@ -55,6 +75,15 @@ func (m *resolvdManager) SetDNS(config OSConfig) error {
|
|
|
|
|
newSearch = append(newSearch, s.WithoutTrailingDot())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var resolvConfHeader = []byte("")
|
|
|
|
|
if !resolvConfOwned {
|
|
|
|
|
// if we don't have a header, insert one
|
|
|
|
|
resolvConfHeader = []byte(
|
|
|
|
|
"# resolv.conf(5) file generated by tailscale\n" +
|
|
|
|
|
"# For more info, see https://tailscale.com/s/resolvconf-overwrite\n" +
|
|
|
|
|
"# DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN\n\n")
|
|
|
|
|
}
|
|
|
|
|
newResolvConf := append(resolvConfHeader, origResolv...)
|
|
|
|
|
if len(newSearch) > 1 {
|
|
|
|
|
newResolvConf = append(newResolvConf, []byte(strings.Join(newSearch, " "))...)
|
|
|
|
|
newResolvConf = append(newResolvConf, '\n')
|
|
|
|
|
@ -123,6 +152,11 @@ func (m resolvdManager) readResolvConf() (config OSConfig, err error) {
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func removeResolvdNameserverLines(orig []byte) []byte {
|
|
|
|
|
re := regexp.MustCompile(`(?m)^nameserver\s+[^\s]+\s+#\s+resolvd:.*$`)
|
|
|
|
|
return re.ReplaceAll(orig, []byte(""))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func removeSearchLines(orig []byte) []byte {
|
|
|
|
|
re := regexp.MustCompile(`(?ms)^search\s+.+$`)
|
|
|
|
|
return re.ReplaceAll(orig, []byte(""))
|
|
|
|
|
|