blob: d0c97532699bd411a7a65a3c522cda5ae937d087 [file] [log] [blame]
Ian Lance Taylor98607ac2011-09-16 08:09:31 -07001// 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
7package net
8
9import (
10 "os"
11 "syscall"
12 "unsafe"
13)
14
15func 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
Ian Lance Taylor9d08a452011-12-02 18:16:25 -080024func getAdapterList() (*syscall.IpAdapterInfo, error) {
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070025 b := make([]byte, 1000)
26 l := uint32(len(b))
27 a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080028 err := syscall.GetAdaptersInfo(a, &l)
29 if err == syscall.ERROR_BUFFER_OVERFLOW {
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070030 b = make([]byte, l)
31 a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080032 err = syscall.GetAdaptersInfo(a, &l)
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070033 }
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080034 if err != nil {
35 return nil, os.NewSyscallError("GetAdaptersInfo", err)
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070036 }
37 return a, nil
38}
39
Ian Lance Taylor9d08a452011-12-02 18:16:25 -080040func getInterfaceList() ([]syscall.InterfaceInfo, error) {
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080041 s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
42 if err != nil {
43 return nil, os.NewSyscallError("Socket", err)
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070044 }
45 defer syscall.Closesocket(s)
46
47 ii := [20]syscall.InterfaceInfo{}
48 ret := uint32(0)
49 size := uint32(unsafe.Sizeof(ii))
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080050 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)
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070053 }
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.
Ian Lance Taylor9d08a452011-12-02 18:16:25 -080061func interfaceTable(ifindex int) ([]Interface, error) {
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080062 ai, err := getAdapterList()
63 if err != nil {
64 return nil, err
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070065 }
66
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -080067 ii, err := getInterfaceList()
68 if err != nil {
69 return nil, err
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070070 }
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)
Ian Lance Taylor0f0f9c12012-01-11 17:09:03 -080080 if e != nil {
Ian Lance Taylor98607ac2011-09-16 08:09:31 -070081 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.
Ian Lance Taylor9d08a452011-12-02 18:16:25 -0800132func interfaceAddrTable(ifindex int) ([]Addr, error) {
Ian Lance Taylor8cf10fb2012-02-09 00:06:37 -0800133 ai, err := getAdapterList()
134 if err != nil {
135 return nil, err
Ian Lance Taylor98607ac2011-09-16 08:09:31 -0700136 }
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.
Ian Lance Taylor9d08a452011-12-02 18:16:25 -0800156func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
Ian Lance Taylor98607ac2011-09-16 08:09:31 -0700157 return nil, nil
158}