github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/net/lookup_unix.go (about) 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 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 := systemConf().hostLookupOrder(r, host) 58 if !r.preferGo() && order == hostLookupCgo { 59 if addrs, err, ok := cgoLookupHost(ctx, host); ok { 60 return addrs, err 61 } 62 // cgo not available (or netgo); fall back to Go's DNS resolver 63 order = hostLookupFilesDNS 64 } 65 return r.goLookupHostOrder(ctx, host, order) 66 } 67 68 func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) { 69 if r.preferGo() { 70 return r.goLookupIP(ctx, network, host) 71 } 72 order := systemConf().hostLookupOrder(r, host) 73 if order == hostLookupCgo { 74 if addrs, err, ok := cgoLookupIP(ctx, network, host); ok { 75 return addrs, err 76 } 77 // cgo not available (or netgo); fall back to Go's DNS resolver 78 order = hostLookupFilesDNS 79 } 80 ips, _, err := r.goLookupIPCNAMEOrder(ctx, network, host, order) 81 return ips, err 82 } 83 84 func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { 85 if !r.preferGo() && systemConf().canUseCgo() { 86 if port, err, ok := cgoLookupPort(ctx, network, service); ok { 87 if err != nil { 88 // Issue 18213: if cgo fails, first check to see whether we 89 // have the answer baked-in to the net package. 90 if port, err := goLookupPort(network, service); err == nil { 91 return port, nil 92 } 93 } 94 return port, err 95 } 96 } 97 return goLookupPort(network, service) 98 } 99 100 func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { 101 if !r.preferGo() && systemConf().canUseCgo() { 102 if cname, err, ok := cgoLookupCNAME(ctx, name); ok { 103 return cname, err 104 } 105 } 106 return r.goLookupCNAME(ctx, name) 107 } 108 109 func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { 110 return r.goLookupSRV(ctx, service, proto, name) 111 } 112 113 func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { 114 return r.goLookupMX(ctx, name) 115 } 116 117 func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { 118 return r.goLookupNS(ctx, name) 119 } 120 121 func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { 122 return r.goLookupTXT(ctx, name) 123 } 124 125 func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { 126 if !r.preferGo() && systemConf().canUseCgo() { 127 if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { 128 return ptrs, err 129 } 130 } 131 return r.goLookupPTR(ctx, addr) 132 } 133 134 // concurrentThreadsLimit returns the number of threads we permit to 135 // run concurrently doing DNS lookups via cgo. A DNS lookup may use a 136 // file descriptor so we limit this to less than the number of 137 // permitted open files. On some systems, notably Darwin, if 138 // getaddrinfo is unable to open a file descriptor it simply returns 139 // EAI_NONAME rather than a useful error. Limiting the number of 140 // concurrent getaddrinfo calls to less than the permitted number of 141 // file descriptors makes that error less likely. We don't bother to 142 // apply the same limit to DNS lookups run directly from Go, because 143 // there we will return a meaningful "too many open files" error. 144 func concurrentThreadsLimit() int { 145 var rlim syscall.Rlimit 146 if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { 147 return 500 148 } 149 r := int(rlim.Cur) 150 if r > 500 { 151 r = 500 152 } else if r > 30 { 153 r -= 30 154 } 155 return r 156 }