return
}
// Only run tcp6 if the kernel will take it.
- if !*testIPv6 || !supportsIPv6 {
+ if !supportsIPv6 {
+ t.Logf("skipping test; ipv6 is not supported")
+ return
+ }
+ if !*testIPv6 {
+ t.Logf("test disabled; use -ipv6 to enable")
return
}
var canCancelIO = true // used for testing current package
+func sysInit() {
+}
+
func init() {
pollMaxN = runtime.NumCPU()
if pollMaxN > 8 {
var canCancelIO bool // determines if CancelIoEx API is present
-func init() {
+func sysInit() {
var d syscall.WSAData
e := syscall.WSAStartup(uint32(0x202), &d)
if e != nil {
initErr = os.NewSyscallError("WSAStartup", e)
}
canCancelIO = syscall.LoadCancelIoEx() == nil
+ if syscall.LoadGetAddrInfo() == nil {
+ lookupIP = newLookupIP
+ }
}
func closesocket(s syscall.Handle) error {
package net
-var supportsIPv6, supportsIPv4map = probeIPv6Stack()
+var supportsIPv6, supportsIPv4map bool
+
+func init() {
+ sysInit()
+ supportsIPv6, supportsIPv4map = probeIPv6Stack()
+}
func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
if filter == nil {
var canCancelIO = true // used for testing current package
+func sysInit() {
+}
+
// parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80).
func parsePlan9Addr(s string) (ip IP, iport int, err error) {
addr := IPv4zero // address contains port only
return
}
-func lookupIP(name string) (addrs []IP, err error) {
+var lookupIP = oldLookupIP
+
+func oldLookupIP(name string) (addrs []IP, err error) {
hostentLock.Lock()
defer hostentLock.Unlock()
h, err := syscall.GetHostByName(name)
}
addrs = addrs[0:i]
default: // TODO(vcc): Implement non IPv4 address lookups.
- return nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
+ return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS)
+ }
+ return addrs, nil
+}
+
+func newLookupIP(name string) (addrs []IP, err error) {
+ hints := syscall.AddrinfoW{
+ Family: syscall.AF_UNSPEC,
+ Socktype: syscall.SOCK_STREAM,
+ Protocol: syscall.IPPROTO_IP,
+ }
+ var result *syscall.AddrinfoW
+ e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &result)
+ if e != nil {
+ return nil, os.NewSyscallError("GetAddrInfoW", e)
+ }
+ defer syscall.FreeAddrInfoW(result)
+ addrs = make([]IP, 0, 5)
+ for ; result != nil; result = result.Next {
+ addr := unsafe.Pointer(result.Addr)
+ switch result.Family {
+ case syscall.AF_INET:
+ a := (*syscall.RawSockaddrInet4)(addr).Addr
+ addrs = append(addrs, IPv4(a[0], a[1], a[2], a[3]))
+ case syscall.AF_INET6:
+ a := (*syscall.RawSockaddrInet6)(addr).Addr
+ addrs = append(addrs, IP{a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]})
+ default:
+ return nil, os.NewSyscallError("LookupIP", syscall.EWINDOWS)
+ }
}
return addrs, nil
}
//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
+//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW
+//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW
//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
Zero [8]uint8
}
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
type RawSockaddr struct {
Family uint16
Data [14]int8
Port int
ZoneId uint32
Addr [16]byte
+ raw RawSockaddrInet6
}
func (sa *SockaddrInet6) sockaddr() (uintptr, int32, error) {
- // TODO(brainman): implement SockaddrInet6.sockaddr()
- return 0, 0, EWINDOWS
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return 0, 0, EINVAL
+ }
+ sa.raw.Family = AF_INET6
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+ p[0] = byte(sa.Port >> 8)
+ p[1] = byte(sa.Port)
+ sa.raw.Scope_id = sa.ZoneId
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
+ return uintptr(unsafe.Pointer(&sa.raw)), int32(unsafe.Sizeof(sa.raw)), nil
}
type SockaddrUnix struct {
return sa, nil
case AF_INET6:
- return nil, EWINDOWS
+ pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
+ sa := new(SockaddrInet6)
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port))
+ sa.Port = int(p[0])<<8 + int(p[1])
+ sa.ZoneId = pp.Scope_id
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i]
+ }
+ return sa, nil
}
return nil, EAFNOSUPPORT
}
return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine)
}
+func LoadGetAddrInfo() error {
+ return procGetAddrInfoW.Find()
+}
+
// Invented structures to support what package os expects.
type Rusage struct {
CreationTime Filetime
procgetprotobyname = modws2_32.NewProc("getprotobyname")
procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W")
procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree")
+ procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW")
+ procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
procTranslateNameW = modsecur32.NewProc("TranslateNameW")
return
}
+func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) {
+ r0, _, _ := Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0)
+ if r0 != 0 {
+ sockerr = Errno(r0)
+ }
+ return
+}
+
+func FreeAddrInfoW(addrinfo *AddrinfoW) {
+ Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0)
+ return
+}
+
func GetIfEntry(pIfRow *MibIfRow) (errcode error) {
r0, _, _ := Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0)
if r0 != 0 {
procgetprotobyname = modws2_32.NewProc("getprotobyname")
procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W")
procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree")
+ procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW")
+ procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW")
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
procTranslateNameW = modsecur32.NewProc("TranslateNameW")
return
}
+func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) {
+ r0, _, _ := Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0)
+ if r0 != 0 {
+ sockerr = Errno(r0)
+ }
+ return
+}
+
+func FreeAddrInfoW(addrinfo *AddrinfoW) {
+ Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0)
+ return
+}
+
func GetIfEntry(pIfRow *MibIfRow) (errcode error) {
r0, _, _ := Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0)
if r0 != 0 {
REG_DWORD = REG_DWORD_LITTLE_ENDIAN
REG_QWORD = REG_QWORD_LITTLE_ENDIAN
)
+
+type AddrinfoW struct {
+ Flags int32
+ Family int32
+ Socktype int32
+ Protocol int32
+ Addrlen uintptr
+ Canonname *uint16
+ Addr uintptr
+ Next *AddrinfoW
+}
+
+const (
+ AI_PASSIVE = 1
+ AI_CANONNAME = 2
+ AI_NUMERICHOST = 4
+)