github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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 addrs, _, err = goLookupIPCNAMEOrder(ctx, host, order) 76 return 77 } 78 79 func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) { 80 if !r.PreferGo && systemConf().canUseCgo() { 81 if port, err, ok := cgoLookupPort(ctx, network, service); ok { 82 if err != nil { 83 // Issue 18213: if cgo fails, first check to see whether we 84 // have the answer baked-in to the net package. 85 if port, err := goLookupPort(network, service); err == nil { 86 return port, nil 87 } 88 } 89 return port, err 90 } 91 } 92 return goLookupPort(network, service) 93 } 94 95 func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { 96 if !r.PreferGo && systemConf().canUseCgo() { 97 if cname, err, ok := cgoLookupCNAME(ctx, name); ok { 98 return cname, err 99 } 100 } 101 return goLookupCNAME(ctx, name) 102 } 103 104 func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { 105 var target string 106 if service == "" && proto == "" { 107 target = name 108 } else { 109 target = "_" + service + "._" + proto + "." + name 110 } 111 cname, rrs, err := lookup(ctx, target, dnsTypeSRV) 112 if err != nil { 113 return "", nil, err 114 } 115 srvs := make([]*SRV, len(rrs)) 116 for i, rr := range rrs { 117 rr := rr.(*dnsRR_SRV) 118 srvs[i] = &SRV{Target: rr.Target, Port: rr.Port, Priority: rr.Priority, Weight: rr.Weight} 119 } 120 byPriorityWeight(srvs).sort() 121 return cname, srvs, nil 122 } 123 124 func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { 125 _, rrs, err := lookup(ctx, name, dnsTypeMX) 126 if err != nil { 127 return nil, err 128 } 129 mxs := make([]*MX, len(rrs)) 130 for i, rr := range rrs { 131 rr := rr.(*dnsRR_MX) 132 mxs[i] = &MX{Host: rr.Mx, Pref: rr.Pref} 133 } 134 byPref(mxs).sort() 135 return mxs, nil 136 } 137 138 func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { 139 _, rrs, err := lookup(ctx, name, dnsTypeNS) 140 if err != nil { 141 return nil, err 142 } 143 nss := make([]*NS, len(rrs)) 144 for i, rr := range rrs { 145 nss[i] = &NS{Host: rr.(*dnsRR_NS).Ns} 146 } 147 return nss, nil 148 } 149 150 func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { 151 _, rrs, err := lookup(ctx, name, dnsTypeTXT) 152 if err != nil { 153 return nil, err 154 } 155 txts := make([]string, len(rrs)) 156 for i, rr := range rrs { 157 txts[i] = rr.(*dnsRR_TXT).Txt 158 } 159 return txts, nil 160 } 161 162 func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) { 163 if !r.PreferGo && systemConf().canUseCgo() { 164 if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { 165 return ptrs, err 166 } 167 } 168 return goLookupPTR(ctx, addr) 169 }