Source file src/pkg/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 // +build darwin freebsd linux netbsd openbsd
6
7 package net
8
9 import (
10 "errors"
11 "sync"
12 )
13
14 var (
15 protocols map[string]int
16 onceReadProtocols sync.Once
17 )
18
19 // readProtocols loads contents of /etc/protocols into protocols map
20 // for quick access.
21 func readProtocols() {
22 protocols = make(map[string]int)
23 if file, err := open("/etc/protocols"); err == nil {
24 for line, ok := file.readLine(); ok; line, ok = file.readLine() {
25 // tcp 6 TCP # transmission control protocol
26 if i := byteIndex(line, '#'); i >= 0 {
27 line = line[0:i]
28 }
29 f := getFields(line)
30 if len(f) < 2 {
31 continue
32 }
33 if proto, _, ok := dtoi(f[1], 0); ok {
34 protocols[f[0]] = proto
35 for _, alias := range f[2:] {
36 protocols[alias] = proto
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(name string) (proto int, err error) {
47 onceReadProtocols.Do(readProtocols)
48 proto, found := protocols[name]
49 if !found {
50 return 0, errors.New("unknown IP protocol specified: " + name)
51 }
52 return
53 }
54
55 func lookupHost(host string) (addrs []string, err error) {
56 addrs, err, ok := cgoLookupHost(host)
57 if !ok {
58 addrs, err = goLookupHost(host)
59 }
60 return
61 }
62
63 func lookupIP(host string) (addrs []IP, err error) {
64 addrs, err, ok := cgoLookupIP(host)
65 if !ok {
66 addrs, err = goLookupIP(host)
67 }
68 return
69 }
70
71 func lookupPort(network, service string) (port int, err error) {
72 port, err, ok := cgoLookupPort(network, service)
73 if !ok {
74 port, err = goLookupPort(network, service)
75 }
76 return
77 }
78
79 func lookupCNAME(name string) (cname string, err error) {
80 cname, err, ok := cgoLookupCNAME(name)
81 if !ok {
82 cname, err = goLookupCNAME(name)
83 }
84 return
85 }
86
87 func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
88 var target string
89 if service == "" && proto == "" {
90 target = name
91 } else {
92 target = "_" + service + "._" + proto + "." + name
93 }
94 var records []dnsRR
95 cname, records, err = lookup(target, dnsTypeSRV)
96 if err != nil {
97 return
98 }
99 addrs = make([]*SRV, len(records))
100 for i, rr := range records {
101 r := rr.(*dnsRR_SRV)
102 addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
103 }
104 byPriorityWeight(addrs).sort()
105 return
106 }
107
108 func lookupMX(name string) (mx []*MX, err error) {
109 _, records, err := lookup(name, dnsTypeMX)
110 if err != nil {
111 return
112 }
113 mx = make([]*MX, len(records))
114 for i, rr := range records {
115 r := rr.(*dnsRR_MX)
116 mx[i] = &MX{r.Mx, r.Pref}
117 }
118 byPref(mx).sort()
119 return
120 }
121
122 func lookupTXT(name string) (txt []string, err error) {
123 _, records, err := lookup(name, dnsTypeTXT)
124 if err != nil {
125 return
126 }
127 txt = make([]string, len(records))
128 for i, r := range records {
129 txt[i] = r.(*dnsRR_TXT).Txt
130 }
131 return
132 }
133
134 func lookupAddr(addr string) (name []string, err error) {
135 name = lookupStaticAddr(addr)
136 if len(name) > 0 {
137 return
138 }
139 var arpa string
140 arpa, err = reverseaddr(addr)
141 if err != nil {
142 return
143 }
144 var records []dnsRR
145 _, records, err = lookup(arpa, dnsTypePTR)
146 if err != nil {
147 return
148 }
149 name = make([]string, len(records))
150 for i := range records {
151 r := records[i].(*dnsRR_PTR)
152 name[i] = r.Ptr
153 }
154 return
155 }