Imported Upstream version 4.7.2
[platform/upstream/gcc48.git] / libgo / go / net / lookup_windows.go
1 // Copyright 2009 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 package net
6
7 import (
8         "os"
9         "sync"
10         "syscall"
11         "unsafe"
12 )
13
14 var (
15         protoentLock sync.Mutex
16         hostentLock  sync.Mutex
17         serventLock  sync.Mutex
18 )
19
20 // lookupProtocol looks up IP protocol name and returns correspondent protocol number.
21 func lookupProtocol(name string) (proto int, err error) {
22         protoentLock.Lock()
23         defer protoentLock.Unlock()
24         p, err := syscall.GetProtoByName(name)
25         if err != nil {
26                 return 0, os.NewSyscallError("GetProtoByName", err)
27         }
28         return int(p.Proto), nil
29 }
30
31 func lookupHost(name string) (addrs []string, err error) {
32         ips, err := LookupIP(name)
33         if err != nil {
34                 return
35         }
36         addrs = make([]string, 0, len(ips))
37         for _, ip := range ips {
38                 addrs = append(addrs, ip.String())
39         }
40         return
41 }
42
43 func lookupIP(name string) (addrs []IP, err error) {
44         hostentLock.Lock()
45         defer hostentLock.Unlock()
46         h, err := syscall.GetHostByName(name)
47         if err != nil {
48                 return nil, os.NewSyscallError("GetHostByName", err)
49         }
50         switch h.AddrType {
51         case syscall.AF_INET:
52                 i := 0
53                 addrs = make([]IP, 100) // plenty of room to grow
54                 for p := (*[100](*[4]byte))(unsafe.Pointer(h.AddrList)); i < cap(addrs) && p[i] != nil; i++ {
55                         addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3])
56                 }
57                 addrs = addrs[0:i]
58         default: // TODO(vcc): Implement non IPv4 address lookups.
59                 return nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
60         }
61         return addrs, nil
62 }
63
64 func lookupPort(network, service string) (port int, err error) {
65         switch network {
66         case "tcp4", "tcp6":
67                 network = "tcp"
68         case "udp4", "udp6":
69                 network = "udp"
70         }
71         serventLock.Lock()
72         defer serventLock.Unlock()
73         s, err := syscall.GetServByName(service, network)
74         if err != nil {
75                 return 0, os.NewSyscallError("GetServByName", err)
76         }
77         return int(syscall.Ntohs(s.Port)), nil
78 }
79
80 func lookupCNAME(name string) (cname string, err error) {
81         var r *syscall.DNSRecord
82         e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
83         if e != nil {
84                 return "", os.NewSyscallError("LookupCNAME", e)
85         }
86         defer syscall.DnsRecordListFree(r, 1)
87         if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
88                 v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0]))
89                 cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."
90         }
91         return
92 }
93
94 func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
95         var target string
96         if service == "" && proto == "" {
97                 target = name
98         } else {
99                 target = "_" + service + "._" + proto + "." + name
100         }
101         var r *syscall.DNSRecord
102         e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil)
103         if e != nil {
104                 return "", nil, os.NewSyscallError("LookupSRV", e)
105         }
106         defer syscall.DnsRecordListFree(r, 1)
107         addrs = make([]*SRV, 0, 10)
108         for p := r; p != nil && p.Type == syscall.DNS_TYPE_SRV; p = p.Next {
109                 v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0]))
110                 addrs = append(addrs, &SRV{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight})
111         }
112         byPriorityWeight(addrs).sort()
113         return name, addrs, nil
114 }
115
116 func lookupMX(name string) (mx []*MX, err error) {
117         var r *syscall.DNSRecord
118         e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
119         if e != nil {
120                 return nil, os.NewSyscallError("LookupMX", e)
121         }
122         defer syscall.DnsRecordListFree(r, 1)
123         mx = make([]*MX, 0, 10)
124         for p := r; p != nil && p.Type == syscall.DNS_TYPE_MX; p = p.Next {
125                 v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
126                 mx = append(mx, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]) + ".", v.Preference})
127         }
128         byPref(mx).sort()
129         return mx, nil
130 }
131
132 func lookupTXT(name string) (txt []string, err error) {
133         var r *syscall.DNSRecord
134         e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
135         if e != nil {
136                 return nil, os.NewSyscallError("LookupTXT", e)
137         }
138         defer syscall.DnsRecordListFree(r, 1)
139         txt = make([]string, 0, 10)
140         if r != nil && r.Type == syscall.DNS_TYPE_TEXT {
141                 d := (*syscall.DNSTXTData)(unsafe.Pointer(&r.Data[0]))
142                 for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringArray[0])))[:d.StringCount] {
143                         s := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(v))[:])
144                         txt = append(txt, s)
145                 }
146         }
147         return
148 }
149
150 func lookupAddr(addr string) (name []string, err error) {
151         arpa, err := reverseaddr(addr)
152         if err != nil {
153                 return nil, err
154         }
155         var r *syscall.DNSRecord
156         e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil)
157         if e != nil {
158                 return nil, os.NewSyscallError("LookupAddr", e)
159         }
160         defer syscall.DnsRecordListFree(r, 1)
161         name = make([]string, 0, 10)
162         for p := r; p != nil && p.Type == syscall.DNS_TYPE_PTR; p = p.Next {
163                 v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
164                 name = append(name, syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))
165         }
166         return name, nil
167 }