mirror of
https://github.com/golang/go
synced 2024-11-19 12:04:43 -07:00
net, syscall: interface for windows
R=mikioh.mikioh, alex.brainman, rsc, vincent.vanackere CC=golang-dev https://golang.org/cl/4590050
This commit is contained in:
parent
36b5e1d698
commit
88442358a9
@ -83,7 +83,7 @@ endif
|
||||
|
||||
GOFILES_windows=\
|
||||
file_windows.go\
|
||||
interface_stub.go\
|
||||
interface_windows.go\
|
||||
lookup_windows.go\
|
||||
sendfile_windows.go\
|
||||
sock_windows.go\
|
||||
|
152
src/pkg/net/interface_windows.go
Normal file
152
src/pkg/net/interface_windows.go
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Network interface identification for Windows
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func bytePtrToString(p *uint8) string {
|
||||
a := (*[10000]uint8)(unsafe.Pointer(p))
|
||||
i := 0
|
||||
for a[i] != 0 {
|
||||
i++
|
||||
}
|
||||
return string(a[:i])
|
||||
}
|
||||
|
||||
func getAdapterList() (*syscall.IpAdapterInfo, os.Error) {
|
||||
b := make([]byte, 1000)
|
||||
l := uint32(len(b))
|
||||
a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
|
||||
e := syscall.GetAdaptersInfo(a, &l)
|
||||
if e == syscall.ERROR_BUFFER_OVERFLOW {
|
||||
b = make([]byte, l)
|
||||
a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
|
||||
e = syscall.GetAdaptersInfo(a, &l)
|
||||
}
|
||||
if e != 0 {
|
||||
return nil, os.NewSyscallError("GetAdaptersInfo", e)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func getInterfaceList() ([]syscall.InterfaceInfo, os.Error) {
|
||||
s, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
|
||||
if e != 0 {
|
||||
return nil, os.NewSyscallError("Socket", e)
|
||||
}
|
||||
defer syscall.Closesocket(int32(s))
|
||||
|
||||
ii := [20]syscall.InterfaceInfo{}
|
||||
ret := uint32(0)
|
||||
size := uint32(unsafe.Sizeof(ii))
|
||||
e = syscall.WSAIoctl(int32(s), syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
|
||||
if e != 0 {
|
||||
return nil, os.NewSyscallError("WSAIoctl", e)
|
||||
}
|
||||
c := ret / uint32(unsafe.Sizeof(ii[0]))
|
||||
return ii[:c-1], nil
|
||||
}
|
||||
|
||||
|
||||
// If the ifindex is zero, interfaceTable returns mappings of all
|
||||
// network interfaces. Otheriwse it returns a mapping of a specific
|
||||
// interface.
|
||||
func interfaceTable(ifindex int) ([]Interface, os.Error) {
|
||||
ai, e := getAdapterList()
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
ii, e := getInterfaceList()
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
var ift []Interface
|
||||
for ; ai != nil; ai = ai.Next {
|
||||
index := ai.Index
|
||||
if ifindex == 0 || ifindex == int(index) {
|
||||
var flags Flags
|
||||
|
||||
row := syscall.MibIfRow{Index: index}
|
||||
e := syscall.GetIfEntry(&row)
|
||||
if e != 0 {
|
||||
return nil, os.NewSyscallError("GetIfEntry", e)
|
||||
}
|
||||
|
||||
for _, ii := range ii {
|
||||
ip := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&ii.Address)).Addr
|
||||
ipv4 := IPv4(ip[0], ip[1], ip[2], ip[3])
|
||||
ipl := &ai.IpAddressList
|
||||
for ipl != nil {
|
||||
ips := bytePtrToString(&ipl.IpAddress.String[0])
|
||||
if ipv4.Equal(parseIPv4(ips)) {
|
||||
break
|
||||
}
|
||||
ipl = ipl.Next
|
||||
}
|
||||
if ipl == nil {
|
||||
continue
|
||||
}
|
||||
if ii.Flags&syscall.IFF_UP != 0 {
|
||||
flags |= FlagUp
|
||||
}
|
||||
if ii.Flags&syscall.IFF_LOOPBACK != 0 {
|
||||
flags |= FlagLoopback
|
||||
}
|
||||
if ii.Flags&syscall.IFF_BROADCAST != 0 {
|
||||
flags |= FlagBroadcast
|
||||
}
|
||||
if ii.Flags&syscall.IFF_POINTTOPOINT != 0 {
|
||||
flags |= FlagPointToPoint
|
||||
}
|
||||
if ii.Flags&syscall.IFF_MULTICAST != 0 {
|
||||
flags |= FlagMulticast
|
||||
}
|
||||
}
|
||||
|
||||
name := bytePtrToString(&ai.AdapterName[0])
|
||||
|
||||
ifi := Interface{
|
||||
Index: int(index),
|
||||
MTU: int(row.Mtu),
|
||||
Name: name,
|
||||
HardwareAddr: HardwareAddr(row.PhysAddr[:row.PhysAddrLen]),
|
||||
Flags: flags}
|
||||
ift = append(ift, ifi)
|
||||
}
|
||||
}
|
||||
return ift, nil
|
||||
}
|
||||
|
||||
// If the ifindex is zero, interfaceAddrTable returns addresses
|
||||
// for all network interfaces. Otherwise it returns addresses
|
||||
// for a specific interface.
|
||||
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
|
||||
ai, e := getAdapterList()
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
var ifat []Addr
|
||||
for ; ai != nil; ai = ai.Next {
|
||||
index := ai.Index
|
||||
if ifindex == 0 || ifindex == int(index) {
|
||||
ipl := &ai.IpAddressList
|
||||
for ; ipl != nil; ipl = ipl.Next {
|
||||
ifa := IPAddr{}
|
||||
ifa.IP = parseIPv4(bytePtrToString(&ipl.IpAddress.String[0]))
|
||||
ifat = append(ifat, ifa.toAddr())
|
||||
}
|
||||
}
|
||||
}
|
||||
return ifat, nil
|
||||
}
|
@ -468,6 +468,7 @@ func Chmod(path string, mode uint32) (errno int) {
|
||||
|
||||
//sys WSAStartup(verreq uint32, data *WSAData) (sockerrno int) = wsock32.WSAStartup
|
||||
//sys WSACleanup() (errno int) [failretval==-1] = wsock32.WSACleanup
|
||||
//sys WSAIoctl(s int32, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (errno int) [failretval==-1] = ws2_32.WSAIoctl
|
||||
//sys socket(af int32, typ int32, protocol int32) (handle int32, errno int) [failretval==-1] = wsock32.socket
|
||||
//sys setsockopt(s int32, level int32, optname int32, optval *byte, optlen int32) (errno int) [failretval==-1] = wsock32.setsockopt
|
||||
//sys bind(s int32, name uintptr, namelen int32) (errno int) [failretval==-1] = wsock32.bind
|
||||
@ -488,6 +489,8 @@ func Chmod(path string, mode uint32) (errno int) {
|
||||
//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
|
||||
//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status uint32) = dnsapi.DnsQuery_W
|
||||
//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
|
||||
//sys GetIfEntry(pIfRow *MibIfRow) (errcode int) = iphlpapi.GetIfEntry
|
||||
//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode int) = iphlpapi.GetAdaptersInfo
|
||||
|
||||
// For testing: clients can set this flag to force
|
||||
// creation of IPv6 sockets to return EAFNOSUPPORT.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// mksyscall_windows.pl -l32 syscall_windows.go syscall_windows_386.go
|
||||
// mksyscall_windows.pl
|
||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
package syscall
|
||||
@ -12,6 +12,7 @@ var (
|
||||
modwsock32 = loadDll("wsock32.dll")
|
||||
modws2_32 = loadDll("ws2_32.dll")
|
||||
moddnsapi = loadDll("dnsapi.dll")
|
||||
modiphlpapi = loadDll("iphlpapi.dll")
|
||||
|
||||
procGetLastError = getSysProcAddr(modkernel32, "GetLastError")
|
||||
procLoadLibraryW = getSysProcAddr(modkernel32, "LoadLibraryW")
|
||||
@ -80,6 +81,7 @@ var (
|
||||
procTransmitFile = getSysProcAddr(modwsock32, "TransmitFile")
|
||||
procWSAStartup = getSysProcAddr(modwsock32, "WSAStartup")
|
||||
procWSACleanup = getSysProcAddr(modwsock32, "WSACleanup")
|
||||
procWSAIoctl = getSysProcAddr(modws2_32, "WSAIoctl")
|
||||
procsocket = getSysProcAddr(modwsock32, "socket")
|
||||
procsetsockopt = getSysProcAddr(modwsock32, "setsockopt")
|
||||
procbind = getSysProcAddr(modwsock32, "bind")
|
||||
@ -100,6 +102,8 @@ var (
|
||||
procntohs = getSysProcAddr(modws2_32, "ntohs")
|
||||
procDnsQuery_W = getSysProcAddr(moddnsapi, "DnsQuery_W")
|
||||
procDnsRecordListFree = getSysProcAddr(moddnsapi, "DnsRecordListFree")
|
||||
procGetIfEntry = getSysProcAddr(modiphlpapi, "GetIfEntry")
|
||||
procGetAdaptersInfo = getSysProcAddr(modiphlpapi, "GetAdaptersInfo")
|
||||
)
|
||||
|
||||
func GetLastError() (lasterrno int) {
|
||||
@ -1043,6 +1047,20 @@ func WSACleanup() (errno int) {
|
||||
return
|
||||
}
|
||||
|
||||
func WSAIoctl(s int32, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (errno int) {
|
||||
r1, _, e1 := Syscall9(procWSAIoctl, 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine))
|
||||
if int(r1) == -1 {
|
||||
if e1 != 0 {
|
||||
errno = int(e1)
|
||||
} else {
|
||||
errno = EINVAL
|
||||
}
|
||||
} else {
|
||||
errno = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func socket(af int32, typ int32, protocol int32) (handle int32, errno int) {
|
||||
r0, _, e1 := Syscall(procsocket, 3, uintptr(af), uintptr(typ), uintptr(protocol))
|
||||
handle = int32(r0)
|
||||
@ -1291,3 +1309,15 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
|
||||
Syscall(procDnsRecordListFree, 2, uintptr(unsafe.Pointer(rl)), uintptr(freetype), 0)
|
||||
return
|
||||
}
|
||||
|
||||
func GetIfEntry(pIfRow *MibIfRow) (errcode int) {
|
||||
r0, _, _ := Syscall(procGetIfEntry, 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0)
|
||||
errcode = int(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode int) {
|
||||
r0, _, _ := Syscall(procGetAdaptersInfo, 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0)
|
||||
errcode = int(r0)
|
||||
return
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ const (
|
||||
ERROR_PATH_NOT_FOUND = 3
|
||||
ERROR_NO_MORE_FILES = 18
|
||||
ERROR_BROKEN_PIPE = 109
|
||||
ERROR_BUFFER_OVERFLOW = 111
|
||||
ERROR_INSUFFICIENT_BUFFER = 122
|
||||
ERROR_MOD_NOT_FOUND = 126
|
||||
ERROR_PROC_NOT_FOUND = 127
|
||||
@ -347,6 +348,7 @@ type Timezoneinformation struct {
|
||||
// Socket related.
|
||||
|
||||
const (
|
||||
AF_UNSPEC = 0
|
||||
AF_UNIX = 1
|
||||
AF_INET = 2
|
||||
AF_INET6 = 23
|
||||
@ -561,3 +563,94 @@ type TransmitFileBuffers struct {
|
||||
Tail uintptr
|
||||
TailLength uint32
|
||||
}
|
||||
|
||||
const (
|
||||
IFF_UP = 1
|
||||
IFF_BROADCAST = 2
|
||||
IFF_LOOPBACK = 4
|
||||
IFF_POINTTOPOINT = 8
|
||||
IFF_MULTICAST = 16
|
||||
)
|
||||
|
||||
const SIO_GET_INTERFACE_LIST = 0x4004747F
|
||||
|
||||
// TODO(mattn): SockaddrGen is union of sockaddr/sockaddr_in/sockaddr_in6_old.
|
||||
// will be fixed to change variable type as suitable.
|
||||
|
||||
type SockaddrGen [24]byte
|
||||
|
||||
type InterfaceInfo struct {
|
||||
Flags uint32
|
||||
Address SockaddrGen
|
||||
BroadcastAddress SockaddrGen
|
||||
Netmask SockaddrGen
|
||||
}
|
||||
|
||||
type IpAddressString struct {
|
||||
String [16]byte
|
||||
}
|
||||
|
||||
type IpMaskString IpAddressString
|
||||
|
||||
type IpAddrString struct {
|
||||
Next *IpAddrString
|
||||
IpAddress IpAddressString
|
||||
IpMask IpMaskString
|
||||
Context uint32
|
||||
}
|
||||
|
||||
const MAX_ADAPTER_NAME_LENGTH = 256
|
||||
const MAX_ADAPTER_DESCRIPTION_LENGTH = 128
|
||||
const MAX_ADAPTER_ADDRESS_LENGTH = 8
|
||||
|
||||
type IpAdapterInfo struct {
|
||||
Next *IpAdapterInfo
|
||||
ComboIndex uint32
|
||||
AdapterName [MAX_ADAPTER_NAME_LENGTH + 4]byte
|
||||
Description [MAX_ADAPTER_DESCRIPTION_LENGTH + 4]byte
|
||||
AddressLength uint32
|
||||
Address [MAX_ADAPTER_ADDRESS_LENGTH]byte
|
||||
Index uint32
|
||||
Type uint32
|
||||
DhcpEnabled uint32
|
||||
CurrentIpAddress *IpAddrString
|
||||
IpAddressList IpAddrString
|
||||
GatewayList IpAddrString
|
||||
DhcpServer IpAddrString
|
||||
HaveWins bool
|
||||
PrimaryWinsServer IpAddrString
|
||||
SecondaryWinsServer IpAddrString
|
||||
LeaseObtained int64
|
||||
LeaseExpires int64
|
||||
}
|
||||
|
||||
const MAXLEN_PHYSADDR = 8
|
||||
const MAX_INTERFACE_NAME_LEN = 256
|
||||
const MAXLEN_IFDESCR = 256
|
||||
|
||||
type MibIfRow struct {
|
||||
Name [MAX_INTERFACE_NAME_LEN]uint16
|
||||
Index uint32
|
||||
Type uint32
|
||||
Mtu uint32
|
||||
Speed uint32
|
||||
PhysAddrLen uint32
|
||||
PhysAddr [MAXLEN_PHYSADDR]byte
|
||||
AdminStatus uint32
|
||||
OperStatus uint32
|
||||
LastChange uint32
|
||||
InOctets uint32
|
||||
InUcastPkts uint32
|
||||
InNUcastPkts uint32
|
||||
InDiscards uint32
|
||||
InErrors uint32
|
||||
InUnknownProtos uint32
|
||||
OutOctets uint32
|
||||
OutUcastPkts uint32
|
||||
OutNUcastPkts uint32
|
||||
OutDiscards uint32
|
||||
OutErrors uint32
|
||||
OutQLen uint32
|
||||
DescrLen uint32
|
||||
Descr [MAXLEN_IFDESCR]byte
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user