github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/dnsproxy/lookup_windows.go (about)

     1  package dnsproxy
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"context"
     7  	"fmt"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/telepresenceio/telepresence/v2/pkg/client"
    12  	"github.com/telepresenceio/telepresence/v2/pkg/iputil"
    13  	"github.com/telepresenceio/telepresence/v2/pkg/proc"
    14  )
    15  
    16  func externalLookup(ctx context.Context, host string, timeout time.Duration) (ips iputil.IPs) {
    17  	ctx, cancel := context.WithTimeout(ctx, timeout)
    18  	defer cancel()
    19  	strategy := client.GetConfig(ctx).OSSpecific().Network.GlobalDNSSearchConfigStrategy
    20  	if strategy == client.GSCAuto || strategy == client.GSCRegistry {
    21  		ips = externalLookupWithNsLookup(ctx, host)
    22  	} else {
    23  		ips = externalLookupWithPowershell(ctx, host)
    24  	}
    25  	return
    26  }
    27  
    28  func externalLookupWithPowershell(ctx context.Context, host string) iputil.IPs {
    29  	cmd := proc.CommandContext(ctx, "powershell.exe", "-NoProfile", "-NonInteractive", fmt.Sprintf("(Resolve-DnsName -Name %s -Type A_AAAA -DnsOnly).IPAddress", host))
    30  	cmd.DisableLogging = true
    31  	out, err := cmd.Output()
    32  	if err != nil {
    33  		return nil
    34  	}
    35  	var ips iputil.IPs
    36  	sc := bufio.NewScanner(bytes.NewReader(out))
    37  	for sc.Scan() {
    38  		if ip := iputil.Parse(strings.TrimSpace(sc.Text())); ip != nil {
    39  			ips = append(ips, ip)
    40  		}
    41  	}
    42  	return ips
    43  }
    44  
    45  func externalLookupWithNsLookup(ctx context.Context, host string) iputil.IPs {
    46  	cmd := proc.CommandContext(ctx, "nslookup", host)
    47  	cmd.DisableLogging = true
    48  	out, err := cmd.Output()
    49  	if err != nil {
    50  		return nil
    51  	}
    52  
    53  	// Look for the adjacent lines
    54  	//   Name: <host> [possibly extended with search path]
    55  	//   Address: <ip>
    56  	var ips iputil.IPs
    57  	sc := bufio.NewScanner(bytes.NewReader(out))
    58  	for sc.Scan() {
    59  		s := sc.Text()
    60  		if a := strings.TrimPrefix(s, "Name:"); a != s && strings.HasPrefix(strings.TrimSpace(a), host) && sc.Scan() {
    61  			s = sc.Text()
    62  			if a := strings.TrimPrefix(s, "Address:"); a != s {
    63  				if ip := iputil.Parse(strings.TrimSpace(a)); ip != nil {
    64  					ips = append(ips, ip)
    65  				}
    66  			} else if a := strings.TrimPrefix(s, "Addresses:"); a != s {
    67  				for {
    68  					if ip := iputil.Parse(strings.TrimSpace(a)); ip != nil {
    69  						ips = append(ips, ip)
    70  					} else {
    71  						break
    72  					}
    73  					if !sc.Scan() {
    74  						break
    75  					}
    76  					a = sc.Text()
    77  				}
    78  			}
    79  		}
    80  	}
    81  	return ips
    82  }