github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/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], 0); 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 proto, found := protocols[name] 49 if !found { 50 return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name} 51 } 52 return proto, nil 53 } 54 55 func lookupHost(ctx context.Context, host string) (addrs []string, err error) { 56 order := systemConf().hostLookupOrder(host) 57 if order == hostLookupCgo { 58 if addrs, err, ok := cgoLookupHost(ctx, host); ok { 59 return addrs, err 60 } 61 // cgo not available (or netgo); fall back to Go's DNS resolver 62 order = hostLookupFilesDNS 63 } 64 return goLookupHostOrder(ctx, host, order) 65 } 66 67 func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) { 68 order := systemConf().hostLookupOrder(host) 69 if order == hostLookupCgo { 70 if addrs, err, ok := cgoLookupIP(ctx, host); ok { 71 return addrs, err 72 } 73 // cgo not available (or netgo); fall back to Go's DNS resolver 74 order = hostLookupFilesDNS 75 } 76 return goLookupIPOrder(ctx, host, order) 77 } 78 79 func lookupPort(ctx context.Context, network, service string) (int, error) { 80 // TODO: use the context if there ever becomes a need. Related 81 // is issue 15321. But port lookup generally just involves 82 // local files, and the os package has no context support. The 83 // files might be on a remote filesystem, though. This should 84 // probably race goroutines if ctx != context.Background(). 85 if systemConf().canUseCgo() { 86 if port, err, ok := cgoLookupPort(ctx, network, service); ok { 87 return port, err 88 } 89 } 90 return goLookupPort(network, service) 91 } 92 93 func lookupCNAME(ctx context.Context, name string) (string, error) { 94 if systemConf().canUseCgo() { 95 if cname, err, ok := cgoLookupCNAME(ctx, name); ok { 96 return cname, err 97 } 98 } 99 return goLookupCNAME(ctx, name) 100 } 101 102 func lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { 103 var target string 104 if service == "" && proto == "" { 105 target = name 106 } else { 107 target = "_" + service + "._" + proto + "." + name 108 } 109 cname, rrs, err := lookup(ctx, target, dnsTypeSRV) 110 if err != nil { 111 return "", nil, err 112 } 113 srvs := make([]*SRV, len(rrs)) 114 for i, rr := range rrs { 115 rr := rr.(*dnsRR_SRV) 116 srvs[i] = &SRV{Target: rr.Target, Port: rr.Port, Priority: rr.Priority, Weight: rr.Weight} 117 } 118 byPriorityWeight(srvs).sort() 119 return cname, srvs, nil 120 } 121 122 func lookupMX(ctx context.Context, name string) ([]*MX, error) { 123 _, rrs, err := lookup(ctx, name, dnsTypeMX) 124 if err != nil { 125 return nil, err 126 } 127 mxs := make([]*MX, len(rrs)) 128 for i, rr := range rrs { 129 rr := rr.(*dnsRR_MX) 130 mxs[i] = &MX{Host: rr.Mx, Pref: rr.Pref} 131 } 132 byPref(mxs).sort() 133 return mxs, nil 134 } 135 136 func lookupNS(ctx context.Context, name string) ([]*NS, error) { 137 _, rrs, err := lookup(ctx, name, dnsTypeNS) 138 if err != nil { 139 return nil, err 140 } 141 nss := make([]*NS, len(rrs)) 142 for i, rr := range rrs { 143 nss[i] = &NS{Host: rr.(*dnsRR_NS).Ns} 144 } 145 return nss, nil 146 } 147 148 func lookupTXT(ctx context.Context, name string) ([]string, error) { 149 _, rrs, err := lookup(ctx, name, dnsTypeTXT) 150 if err != nil { 151 return nil, err 152 } 153 txts := make([]string, len(rrs)) 154 for i, rr := range rrs { 155 txts[i] = rr.(*dnsRR_TXT).Txt 156 } 157 return txts, nil 158 } 159 160 func lookupAddr(ctx context.Context, addr string) ([]string, error) { 161 if systemConf().canUseCgo() { 162 if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok { 163 return ptrs, err 164 } 165 } 166 return goLookupPTR(ctx, addr) 167 }