OSDN Git Service

libgo: Update to weekly.2012-02-07.
[pf3gnuchains/gcc-fork.git] / libgo / go / net / interface_windows.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 // Network interface identification for Windows
6
7 package net
8
9 import (
10         "os"
11         "syscall"
12         "unsafe"
13 )
14
15 func bytePtrToString(p *uint8) string {
16         a := (*[10000]uint8)(unsafe.Pointer(p))
17         i := 0
18         for a[i] != 0 {
19                 i++
20         }
21         return string(a[:i])
22 }
23
24 func getAdapterList() (*syscall.IpAdapterInfo, error) {
25         b := make([]byte, 1000)
26         l := uint32(len(b))
27         a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
28         err := syscall.GetAdaptersInfo(a, &l)
29         if err == syscall.ERROR_BUFFER_OVERFLOW {
30                 b = make([]byte, l)
31                 a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
32                 err = syscall.GetAdaptersInfo(a, &l)
33         }
34         if err != nil {
35                 return nil, os.NewSyscallError("GetAdaptersInfo", err)
36         }
37         return a, nil
38 }
39
40 func getInterfaceList() ([]syscall.InterfaceInfo, error) {
41         s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
42         if err != nil {
43                 return nil, os.NewSyscallError("Socket", err)
44         }
45         defer syscall.Closesocket(s)
46
47         ii := [20]syscall.InterfaceInfo{}
48         ret := uint32(0)
49         size := uint32(unsafe.Sizeof(ii))
50         err = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
51         if err != nil {
52                 return nil, os.NewSyscallError("WSAIoctl", err)
53         }
54         c := ret / uint32(unsafe.Sizeof(ii[0]))
55         return ii[:c-1], nil
56 }
57
58 // If the ifindex is zero, interfaceTable returns mappings of all
59 // network interfaces.  Otheriwse it returns a mapping of a specific
60 // interface.
61 func interfaceTable(ifindex int) ([]Interface, error) {
62         ai, err := getAdapterList()
63         if err != nil {
64                 return nil, err
65         }
66
67         ii, err := getInterfaceList()
68         if err != nil {
69                 return nil, err
70         }
71
72         var ift []Interface
73         for ; ai != nil; ai = ai.Next {
74                 index := ai.Index
75                 if ifindex == 0 || ifindex == int(index) {
76                         var flags Flags
77
78                         row := syscall.MibIfRow{Index: index}
79                         e := syscall.GetIfEntry(&row)
80                         if e != nil {
81                                 return nil, os.NewSyscallError("GetIfEntry", e)
82                         }
83
84                         for _, ii := range ii {
85                                 ip := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&ii.Address)).Addr
86                                 ipv4 := IPv4(ip[0], ip[1], ip[2], ip[3])
87                                 ipl := &ai.IpAddressList
88                                 for ipl != nil {
89                                         ips := bytePtrToString(&ipl.IpAddress.String[0])
90                                         if ipv4.Equal(parseIPv4(ips)) {
91                                                 break
92                                         }
93                                         ipl = ipl.Next
94                                 }
95                                 if ipl == nil {
96                                         continue
97                                 }
98                                 if ii.Flags&syscall.IFF_UP != 0 {
99                                         flags |= FlagUp
100                                 }
101                                 if ii.Flags&syscall.IFF_LOOPBACK != 0 {
102                                         flags |= FlagLoopback
103                                 }
104                                 if ii.Flags&syscall.IFF_BROADCAST != 0 {
105                                         flags |= FlagBroadcast
106                                 }
107                                 if ii.Flags&syscall.IFF_POINTTOPOINT != 0 {
108                                         flags |= FlagPointToPoint
109                                 }
110                                 if ii.Flags&syscall.IFF_MULTICAST != 0 {
111                                         flags |= FlagMulticast
112                                 }
113                         }
114
115                         name := bytePtrToString(&ai.AdapterName[0])
116
117                         ifi := Interface{
118                                 Index:        int(index),
119                                 MTU:          int(row.Mtu),
120                                 Name:         name,
121                                 HardwareAddr: HardwareAddr(row.PhysAddr[:row.PhysAddrLen]),
122                                 Flags:        flags}
123                         ift = append(ift, ifi)
124                 }
125         }
126         return ift, nil
127 }
128
129 // If the ifindex is zero, interfaceAddrTable returns addresses
130 // for all network interfaces.  Otherwise it returns addresses
131 // for a specific interface.
132 func interfaceAddrTable(ifindex int) ([]Addr, error) {
133         ai, err := getAdapterList()
134         if err != nil {
135                 return nil, err
136         }
137
138         var ifat []Addr
139         for ; ai != nil; ai = ai.Next {
140                 index := ai.Index
141                 if ifindex == 0 || ifindex == int(index) {
142                         ipl := &ai.IpAddressList
143                         for ; ipl != nil; ipl = ipl.Next {
144                                 ifa := IPAddr{}
145                                 ifa.IP = parseIPv4(bytePtrToString(&ipl.IpAddress.String[0]))
146                                 ifat = append(ifat, ifa.toAddr())
147                         }
148                 }
149         }
150         return ifat, nil
151 }
152
153 // If the ifindex is zero, interfaceMulticastAddrTable returns
154 // addresses for all network interfaces.  Otherwise it returns
155 // addresses for a specific interface.
156 func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
157         return nil, nil
158 }