Source file src/net/lookup_unix.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build unix || wasip1
     6  
     7  package net
     8  
     9  import (
    10  	"context"
    11  	"internal/bytealg"
    12  	"sync"
    13  	"syscall"
    14  )
    15  
    16  var onceReadProtocols sync.Once
    17  
    18  // readProtocols loads contents of /etc/protocols into protocols map
    19  // for quick access.
    20  func readProtocols() {
    21  	file, err := open("/etc/protocols")
    22  	if err != nil {
    23  		return
    24  	}
    25  	defer file.close()
    26  
    27  	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
    28  		// tcp    6   TCP    # transmission control protocol
    29  		if i := bytealg.IndexByteString(line, '#'); i >= 0 {
    30  			line = line[0:i]
    31  		}
    32  		f := getFields(line)
    33  		if len(f) < 2 {
    34  			continue
    35  		}
    36  		if proto, _, ok := dtoi(f[1]); ok {
    37  			if _, ok := protocols[f[0]]; !ok {
    38  				protocols[f[0]] = proto
    39  			}
    40  			for _, alias := range f[2:] {
    41  				if _, ok := protocols[alias]; !ok {
    42  					protocols[alias] = proto
    43  				}
    44  			}
    45  		}
    46  	}
    47  }
    48  
    49  // lookupProtocol looks up IP protocol name in /etc/protocols and
    50  // returns correspondent protocol number.
    51  func lookupProtocol(_ context.Context, name string) (int, error) {
    52  	onceReadProtocols.Do(readProtocols)
    53  	return lookupProtocolMap(name)
    54  }
    55  
    56  func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
    57  	order, conf := systemConf().hostLookupOrder(r, host)
    58  	if order == hostLookupCgo {
    59  		return cgoLookupHost(ctx, host)
    60  	}
    61  	return r.goLookupHostOrder(ctx, host, order, conf)
    62  }
    63  
    64  func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) {
    65  	if r.preferGo() {
    66  		return r.goLookupIP(ctx, network, host)
    67  	}
    68  	order, conf := systemConf().hostLookupOrder(r, host)
    69  	if order == hostLookupCgo {
    70  		return cgoLookupIP(ctx, network, host)
    71  	}
    72  	ips, _, err := r.goLookupIPCNAMEOrder(ctx, network, host, order, conf)
    73  	return ips, err
    74  }
    75  
    76  func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) {
    77  	// Port lookup is not a DNS operation.
    78  	// Prefer the cgo resolver if possible.
    79  	if !systemConf().mustUseGoResolver(r) {
    80  		port, err := cgoLookupPort(ctx, network, service)
    81  		if err != nil {
    82  			// Issue 18213: if cgo fails, first check to see whether we
    83  			// have the answer baked-in to the net package.
    84  			if port, err := goLookupPort(network, service); err == nil {
    85  				return port, nil
    86  			}
    87  		}
    88  		return port, err
    89  	}
    90  	return goLookupPort(network, service)
    91  }
    92  
    93  func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
    94  	order, conf := systemConf().hostLookupOrder(r, name)
    95  	if order == hostLookupCgo {
    96  		if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
    97  			return cname, err
    98  		}
    99  	}
   100  	return r.goLookupCNAME(ctx, name, order, conf)
   101  }
   102  
   103  func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
   104  	return r.goLookupSRV(ctx, service, proto, name)
   105  }
   106  
   107  func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
   108  	return r.goLookupMX(ctx, name)
   109  }
   110  
   111  func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) {
   112  	return r.goLookupNS(ctx, name)
   113  }
   114  
   115  func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) {
   116  	return r.goLookupTXT(ctx, name)
   117  }
   118  
   119  func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
   120  	order, conf := systemConf().addrLookupOrder(r, addr)
   121  	if order == hostLookupCgo {
   122  		return cgoLookupPTR(ctx, addr)
   123  	}
   124  	return r.goLookupPTR(ctx, addr, order, conf)
   125  }
   126  
   127  // concurrentThreadsLimit returns the number of threads we permit to
   128  // run concurrently doing DNS lookups via cgo. A DNS lookup may use a
   129  // file descriptor so we limit this to less than the number of
   130  // permitted open files. On some systems, notably Darwin, if
   131  // getaddrinfo is unable to open a file descriptor it simply returns
   132  // EAI_NONAME rather than a useful error. Limiting the number of
   133  // concurrent getaddrinfo calls to less than the permitted number of
   134  // file descriptors makes that error less likely. We don't bother to
   135  // apply the same limit to DNS lookups run directly from Go, because
   136  // there we will return a meaningful "too many open files" error.
   137  func concurrentThreadsLimit() int {
   138  	var rlim syscall.Rlimit
   139  	if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil {
   140  		return 500
   141  	}
   142  	r := rlim.Cur
   143  	if r > 500 {
   144  		r = 500
   145  	} else if r > 30 {
   146  		r -= 30
   147  	}
   148  	return int(r)
   149  }
   150  

View as plain text