github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/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 // +build darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 package net 8 9 import ( 10 "context" 11 "sync" 12 ) 13 14 var onceReadProtocols sync.Once 15 16 // readProtocols loads contents of /etc/protocols into protocols map 17 // for quick access. 18 func readProtocols() { 19 if file, err := open("/etc/protocols"); err == nil { 20 for line, ok := file.readLine(); ok; line, ok = file.readLine() { 21 // tcp 6 TCP # transmission control protocol 22 if i := byteIndex(line, '#'); i >= 0 { 23 line = line[0:i] 24 } 25 f := getFields(line) 26 if len(f) < 2 { 27 continue 28 } 29 if proto, _, ok := dtoi(f[1]); ok { 30 if _, ok := protocols[f[0]]; !ok { 31 protocols[f[0]] = proto 32 } 33 for _, alias := range f[2:] { 34 if _, ok := protocols[alias]; !ok { 35 protocols[alias] = proto 36 } 37 } 38 } 39 } 40 file.close() 41 } 42 } 43 44 // lookupProtocol looks up IP protocol name in /etc/protocols and 45 // returns correspondent protocol number. 46 func lookupProtocol(_ context.Context, name string) (int, error) { 47 onceReadProtocols.Do(readProtocols) 48 return lookupProtocolMap(name) 49 } 50 51 func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) { 52 order := systemConf().hostLookupOrder(host) 53 if !r.PreferGo && order == hostLookupCgo { 54 if addrs, err, ok := cgoLookupHost(ctx, host); ok { 55 return addrs, err 56 } 57 // cgo not available (or netgo); fall back to Go's DNS resolver 58 order = hostLookupFilesDNS 59 } 60 return goLookupHostOrder(ctx, host, order) 61 } 62 63 func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) { 64 if r.PreferGo { 65 return goLookupIP(ctx, host) 66 } 67 order := systemConf().hostLookupOrder(host) 68 if order == hostLookupCgo { 69 if addrs, err, ok := cgoLookupIP(ctx, host); ok { 70 return addrs, err 71 } 72 // cgo not available (or netgo); fall back to Go's DNS resolver 73 order = hostLookupFilesDNS 74 } 75 return goLookupIPOrder(ctx, host, order) 76 } 77 78 func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { 79 // TODO: use the context if there ever becomes a need. Related 80 // is issue 15321. But port lookup generally just involves 81 // local files, and the os package has no context support. The 82 // files might be on a remote filesystem, though. This should 83 // probably race goroutines if ctx != context.Background(). 84 if !r.PreferGo && systemConf().canUseCgo() { 85 if port, err, ok := cgoLookupPort(ctx, network, service); ok { 86 return port, err 87 } 88 } 89 return goLookupPort(network, service) 90 } 91 92 func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { 93 if !r.PreferGo && systemConf().canUseCgo() { 94 if cname, err, ok := cgoLookupCNAME(ctx, name); ok { 95 return cname, err 96 } 97 } 98 return goLookupCNAME(ctx, name) 99 } 100 101 func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { 102 var target string 103 if service == "" && proto == "" { 104 target = name 105 } else { 106 target = "_" + service + "._" + proto + "." + name 107 } 108 cname, rrs, err := lookup(ctx, target, dnsTypeSRV) 109 if err != nil { 110 return "", nil, err 111 } 112 srvs := make([]*SRV, len(rrs)) 113 for i, rr := range rrs { 114 rr := rr.(*dnsRR_SRV) 115 srvs[i] = &SRV{Target: rr.Target, Port: rr.Port, Priority: rr.Priority, Weight: rr.Weight} 116 } 117 byPriorityWeight(srvs).sort() 118 return cname, srvs, nil 119 } 120 121 func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { 122 _, rrs, err := lookup(ctx, name, dnsTypeMX) 123 if err != nil { 124 return nil, err 125 } 126 mxs := make([]*MX, len(rrs)) 127 for i, rr := range rrs { 128 rr := rr.(*dnsRR_MX) 129 mxs[i] = &MX{Host: rr.Mx, Pref: rr.Pref} 130 } 131 byPref(mxs).sort() 132 return mxs, nil 133 } 134 135 func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { 136 _, rrs, err := lookup(ctx, name, dnsTypeNS) 137 if err != nil { 138 return nil, err 139 } 140 nss := make([]*NS, len(rrs)) 141 for i, rr := range rrs { 142 nss[i] = &NS{Host: rr.(*dnsRR_NS).Ns} 143 } 144 return nss, nil 145 } 146 147 func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { 148 _, rrs, err := lookup(ctx, name, dnsTypeTXT) 149 if err != nil { 150 return nil, err 151 } 152 txts := make([]string, len(rrs)) 153 for i, rr := range rrs { 154 txts[i] = rr.(*dnsRR_TXT).Txt 155 } 156 return txts, nil 157 } 158 159 func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { 160 if !r.PreferGo && systemConf().canUseCgo() { 161 if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { 162 return ptrs, err 163 } 164 } 165 return goLookupPTR(ctx, addr) 166 }