github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/net/fd_windows.go (about)

     1  // Copyright 2010 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  	"errors"
     9  	"io"
    10  	"os"
    11  	"runtime"
    12  	"sync"
    13  	"syscall"
    14  	"time"
    15  	"unsafe"
    16  )
    17  
    18  var (
    19  	initErr error
    20  	ioSync  uint64
    21  )
    22  
    23  // CancelIo Windows API cancels all outstanding IO for a particular
    24  // socket on current thread. To overcome that limitation, we run
    25  // special goroutine, locked to OS single thread, that both starts
    26  // and cancels IO. It means, there are 2 unavoidable thread switches
    27  // for every IO.
    28  // Some newer versions of Windows has new CancelIoEx API, that does
    29  // not have that limitation and can be used from any thread. This
    30  // package uses CancelIoEx API, if present, otherwise it fallback
    31  // to CancelIo.
    32  
    33  var (
    34  	canCancelIO                               bool // determines if CancelIoEx API is present
    35  	skipSyncNotif                             bool
    36  	hasLoadSetFileCompletionNotificationModes bool
    37  )
    38  
    39  func sysInit() {
    40  	var d syscall.WSAData
    41  	e := syscall.WSAStartup(uint32(0x202), &d)
    42  	if e != nil {
    43  		initErr = os.NewSyscallError("WSAStartup", e)
    44  	}
    45  	canCancelIO = syscall.LoadCancelIoEx() == nil
    46  	if syscall.LoadGetAddrInfo() == nil {
    47  		lookupPort = newLookupPort
    48  		lookupIP = newLookupIP
    49  	}
    50  
    51  	hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
    52  	if hasLoadSetFileCompletionNotificationModes {
    53  		// It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
    54  		// http://support.microsoft.com/kb/2568167
    55  		skipSyncNotif = true
    56  		protos := [2]int32{syscall.IPPROTO_TCP, 0}
    57  		var buf [32]syscall.WSAProtocolInfo
    58  		len := uint32(unsafe.Sizeof(buf))
    59  		n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
    60  		if err != nil {
    61  			skipSyncNotif = false
    62  		} else {
    63  			for i := int32(0); i < n; i++ {
    64  				if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
    65  					skipSyncNotif = false
    66  					break
    67  				}
    68  			}
    69  		}
    70  	}
    71  }
    72  
    73  func closesocket(s syscall.Handle) error {
    74  	return syscall.Closesocket(s)
    75  }
    76  
    77  func canUseConnectEx(net string) bool {
    78  	switch net {
    79  	case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
    80  		// ConnectEx windows API does not support connectionless sockets.
    81  		return false
    82  	}
    83  	return syscall.LoadConnectEx() == nil
    84  }
    85  
    86  func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
    87  	if !canUseConnectEx(net) {
    88  		// Use the relatively inefficient goroutine-racing
    89  		// implementation of DialTimeout.
    90  		return dialChannel(net, ra, dialer, deadline)
    91  	}
    92  	return dialer(deadline)
    93  }
    94  
    95  // operation contains superset of data necessary to perform all async IO.
    96  type operation struct {
    97  	// Used by IOCP interface, it must be first field
    98  	// of the struct, as our code rely on it.
    99  	o syscall.Overlapped
   100  
   101  	// fields used by runtime.netpoll
   102  	runtimeCtx uintptr
   103  	mode       int32
   104  	errno      int32
   105  	qty        uint32
   106  
   107  	// fields used only by net package
   108  	fd     *netFD
   109  	errc   chan error
   110  	buf    syscall.WSABuf
   111  	sa     syscall.Sockaddr
   112  	rsa    *syscall.RawSockaddrAny
   113  	rsan   int32
   114  	handle syscall.Handle
   115  	flags  uint32
   116  }
   117  
   118  func (o *operation) InitBuf(buf []byte) {
   119  	o.buf.Len = uint32(len(buf))
   120  	o.buf.Buf = nil
   121  	if len(buf) != 0 {
   122  		o.buf.Buf = &buf[0]
   123  	}
   124  }
   125  
   126  // ioSrv executes net IO requests.
   127  type ioSrv struct {
   128  	req chan ioSrvReq
   129  }
   130  
   131  type ioSrvReq struct {
   132  	o      *operation
   133  	submit func(o *operation) error // if nil, cancel the operation
   134  }
   135  
   136  // ProcessRemoteIO will execute submit IO requests on behalf
   137  // of other goroutines, all on a single os thread, so it can
   138  // cancel them later. Results of all operations will be sent
   139  // back to their requesters via channel supplied in request.
   140  // It is used only when the CancelIoEx API is unavailable.
   141  func (s *ioSrv) ProcessRemoteIO() {
   142  	runtime.LockOSThread()
   143  	defer runtime.UnlockOSThread()
   144  	for r := range s.req {
   145  		if r.submit != nil {
   146  			r.o.errc <- r.submit(r.o)
   147  		} else {
   148  			r.o.errc <- syscall.CancelIo(r.o.fd.sysfd)
   149  		}
   150  	}
   151  }
   152  
   153  // ExecIO executes a single IO operation o. It submits and cancels
   154  // IO in the current thread for systems where Windows CancelIoEx API
   155  // is available. Alternatively, it passes the request onto
   156  // runtime netpoll and waits for completion or cancels request.
   157  func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
   158  	fd := o.fd
   159  	// Notify runtime netpoll about starting IO.
   160  	err := fd.pd.Prepare(int(o.mode))
   161  	if err != nil {
   162  		return 0, &OpError{name, fd.net, fd.laddr, err}
   163  	}
   164  	// Start IO.
   165  	if canCancelIO {
   166  		err = submit(o)
   167  	} else {
   168  		// Send request to a special dedicated thread,
   169  		// so it can stop the IO with CancelIO later.
   170  		s.req <- ioSrvReq{o, submit}
   171  		err = <-o.errc
   172  	}
   173  	switch err {
   174  	case nil:
   175  		// IO completed immediately
   176  		if o.fd.skipSyncNotif {
   177  			// No completion message will follow, so return immediately.
   178  			return int(o.qty), nil
   179  		}
   180  		// Need to get our completion message anyway.
   181  	case syscall.ERROR_IO_PENDING:
   182  		// IO started, and we have to wait for its completion.
   183  		err = nil
   184  	default:
   185  		return 0, &OpError{name, fd.net, fd.laddr, err}
   186  	}
   187  	// Wait for our request to complete.
   188  	err = fd.pd.Wait(int(o.mode))
   189  	if err == nil {
   190  		// All is good. Extract our IO results and return.
   191  		if o.errno != 0 {
   192  			err = syscall.Errno(o.errno)
   193  			return 0, &OpError{name, fd.net, fd.laddr, err}
   194  		}
   195  		return int(o.qty), nil
   196  	}
   197  	// IO is interrupted by "close" or "timeout"
   198  	netpollErr := err
   199  	switch netpollErr {
   200  	case errClosing, errTimeout:
   201  		// will deal with those.
   202  	default:
   203  		panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
   204  	}
   205  	// Cancel our request.
   206  	if canCancelIO {
   207  		err := syscall.CancelIoEx(fd.sysfd, &o.o)
   208  		// Assuming ERROR_NOT_FOUND is returned, if IO is completed.
   209  		if err != nil && err != syscall.ERROR_NOT_FOUND {
   210  			// TODO(brainman): maybe do something else, but panic.
   211  			panic(err)
   212  		}
   213  	} else {
   214  		s.req <- ioSrvReq{o, nil}
   215  		<-o.errc
   216  	}
   217  	// Wait for cancellation to complete.
   218  	fd.pd.WaitCanceled(int(o.mode))
   219  	if o.errno != 0 {
   220  		err = syscall.Errno(o.errno)
   221  		if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
   222  			err = netpollErr
   223  		}
   224  		return 0, &OpError{name, fd.net, fd.laddr, err}
   225  	}
   226  	// We issued cancellation request. But, it seems, IO operation succeeded
   227  	// before cancellation request run. We need to treat IO operation as
   228  	// succeeded (the bytes are actually sent/recv from network).
   229  	return int(o.qty), nil
   230  }
   231  
   232  // Start helper goroutines.
   233  var rsrv, wsrv *ioSrv
   234  var onceStartServer sync.Once
   235  
   236  func startServer() {
   237  	rsrv = new(ioSrv)
   238  	wsrv = new(ioSrv)
   239  	if !canCancelIO {
   240  		// Only CancelIo API is available. Lets start two special goroutines
   241  		// locked to an OS thread, that both starts and cancels IO. One will
   242  		// process read requests, while other will do writes.
   243  		rsrv.req = make(chan ioSrvReq)
   244  		go rsrv.ProcessRemoteIO()
   245  		wsrv.req = make(chan ioSrvReq)
   246  		go wsrv.ProcessRemoteIO()
   247  	}
   248  }
   249  
   250  // Network file descriptor.
   251  type netFD struct {
   252  	// locking/lifetime of sysfd + serialize access to Read and Write methods
   253  	fdmu fdMutex
   254  
   255  	// immutable until Close
   256  	sysfd         syscall.Handle
   257  	family        int
   258  	sotype        int
   259  	isConnected   bool
   260  	skipSyncNotif bool
   261  	net           string
   262  	laddr         Addr
   263  	raddr         Addr
   264  
   265  	rop operation // read operation
   266  	wop operation // write operation
   267  
   268  	// wait server
   269  	pd pollDesc
   270  }
   271  
   272  func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
   273  	if initErr != nil {
   274  		return nil, initErr
   275  	}
   276  	onceStartServer.Do(startServer)
   277  	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
   278  }
   279  
   280  func (fd *netFD) init() error {
   281  	if err := fd.pd.Init(fd); err != nil {
   282  		return err
   283  	}
   284  	if hasLoadSetFileCompletionNotificationModes {
   285  		// We do not use events, so we can skip them always.
   286  		flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
   287  		// It's not safe to skip completion notifications for UDP:
   288  		// http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
   289  		if skipSyncNotif && fd.net == "tcp" {
   290  			flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
   291  		}
   292  		err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags)
   293  		if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
   294  			fd.skipSyncNotif = true
   295  		}
   296  	}
   297  	// Disable SIO_UDP_CONNRESET behavior.
   298  	// http://support.microsoft.com/kb/263823
   299  	switch fd.net {
   300  	case "udp", "udp4", "udp6":
   301  		ret := uint32(0)
   302  		flag := uint32(0)
   303  		size := uint32(unsafe.Sizeof(flag))
   304  		err := syscall.WSAIoctl(fd.sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
   305  		if err != nil {
   306  			return os.NewSyscallError("WSAIoctl", err)
   307  		}
   308  	}
   309  	fd.rop.mode = 'r'
   310  	fd.wop.mode = 'w'
   311  	fd.rop.fd = fd
   312  	fd.wop.fd = fd
   313  	fd.rop.runtimeCtx = fd.pd.runtimeCtx
   314  	fd.wop.runtimeCtx = fd.pd.runtimeCtx
   315  	if !canCancelIO {
   316  		fd.rop.errc = make(chan error)
   317  		fd.wop.errc = make(chan error)
   318  	}
   319  	return nil
   320  }
   321  
   322  func (fd *netFD) setAddr(laddr, raddr Addr) {
   323  	fd.laddr = laddr
   324  	fd.raddr = raddr
   325  	runtime.SetFinalizer(fd, (*netFD).Close)
   326  }
   327  
   328  func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
   329  	// Do not need to call fd.writeLock here,
   330  	// because fd is not yet accessible to user,
   331  	// so no concurrent operations are possible.
   332  	if err := fd.init(); err != nil {
   333  		return err
   334  	}
   335  	if !deadline.IsZero() {
   336  		fd.setWriteDeadline(deadline)
   337  		defer fd.setWriteDeadline(noDeadline)
   338  	}
   339  	if !canUseConnectEx(fd.net) {
   340  		return syscall.Connect(fd.sysfd, ra)
   341  	}
   342  	// ConnectEx windows API requires an unconnected, previously bound socket.
   343  	if la == nil {
   344  		switch ra.(type) {
   345  		case *syscall.SockaddrInet4:
   346  			la = &syscall.SockaddrInet4{}
   347  		case *syscall.SockaddrInet6:
   348  			la = &syscall.SockaddrInet6{}
   349  		default:
   350  			panic("unexpected type in connect")
   351  		}
   352  		if err := syscall.Bind(fd.sysfd, la); err != nil {
   353  			return err
   354  		}
   355  	}
   356  	// Call ConnectEx API.
   357  	o := &fd.wop
   358  	o.sa = ra
   359  	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
   360  		return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
   361  	})
   362  	if err != nil {
   363  		return err
   364  	}
   365  	// Refresh socket properties.
   366  	return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
   367  }
   368  
   369  func (fd *netFD) destroy() {
   370  	if fd.sysfd == syscall.InvalidHandle {
   371  		return
   372  	}
   373  	// Poller may want to unregister fd in readiness notification mechanism,
   374  	// so this must be executed before closesocket.
   375  	fd.pd.Close()
   376  	closesocket(fd.sysfd)
   377  	fd.sysfd = syscall.InvalidHandle
   378  	// no need for a finalizer anymore
   379  	runtime.SetFinalizer(fd, nil)
   380  }
   381  
   382  // Add a reference to this fd.
   383  // Returns an error if the fd cannot be used.
   384  func (fd *netFD) incref() error {
   385  	if !fd.fdmu.Incref() {
   386  		return errClosing
   387  	}
   388  	return nil
   389  }
   390  
   391  // Remove a reference to this FD and close if we've been asked to do so
   392  // (and there are no references left).
   393  func (fd *netFD) decref() {
   394  	if fd.fdmu.Decref() {
   395  		fd.destroy()
   396  	}
   397  }
   398  
   399  // Add a reference to this fd and lock for reading.
   400  // Returns an error if the fd cannot be used.
   401  func (fd *netFD) readLock() error {
   402  	if !fd.fdmu.RWLock(true) {
   403  		return errClosing
   404  	}
   405  	return nil
   406  }
   407  
   408  // Unlock for reading and remove a reference to this FD.
   409  func (fd *netFD) readUnlock() {
   410  	if fd.fdmu.RWUnlock(true) {
   411  		fd.destroy()
   412  	}
   413  }
   414  
   415  // Add a reference to this fd and lock for writing.
   416  // Returns an error if the fd cannot be used.
   417  func (fd *netFD) writeLock() error {
   418  	if !fd.fdmu.RWLock(false) {
   419  		return errClosing
   420  	}
   421  	return nil
   422  }
   423  
   424  // Unlock for writing and remove a reference to this FD.
   425  func (fd *netFD) writeUnlock() {
   426  	if fd.fdmu.RWUnlock(false) {
   427  		fd.destroy()
   428  	}
   429  }
   430  
   431  func (fd *netFD) Close() error {
   432  	if !fd.fdmu.IncrefAndClose() {
   433  		return errClosing
   434  	}
   435  	// unblock pending reader and writer
   436  	fd.pd.Evict()
   437  	fd.decref()
   438  	return nil
   439  }
   440  
   441  func (fd *netFD) shutdown(how int) error {
   442  	if err := fd.incref(); err != nil {
   443  		return err
   444  	}
   445  	defer fd.decref()
   446  	err := syscall.Shutdown(fd.sysfd, how)
   447  	if err != nil {
   448  		return &OpError{"shutdown", fd.net, fd.laddr, err}
   449  	}
   450  	return nil
   451  }
   452  
   453  func (fd *netFD) closeRead() error {
   454  	return fd.shutdown(syscall.SHUT_RD)
   455  }
   456  
   457  func (fd *netFD) closeWrite() error {
   458  	return fd.shutdown(syscall.SHUT_WR)
   459  }
   460  
   461  func (fd *netFD) Read(buf []byte) (int, error) {
   462  	if err := fd.readLock(); err != nil {
   463  		return 0, err
   464  	}
   465  	defer fd.readUnlock()
   466  	o := &fd.rop
   467  	o.InitBuf(buf)
   468  	n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
   469  		return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
   470  	})
   471  	if err == nil && n == 0 {
   472  		err = io.EOF
   473  	}
   474  	if raceenabled {
   475  		raceAcquire(unsafe.Pointer(&ioSync))
   476  	}
   477  	return n, err
   478  }
   479  
   480  func (fd *netFD) readFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
   481  	if len(buf) == 0 {
   482  		return 0, nil, nil
   483  	}
   484  	if err := fd.readLock(); err != nil {
   485  		return 0, nil, err
   486  	}
   487  	defer fd.readUnlock()
   488  	o := &fd.rop
   489  	o.InitBuf(buf)
   490  	n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
   491  		if o.rsa == nil {
   492  			o.rsa = new(syscall.RawSockaddrAny)
   493  		}
   494  		o.rsan = int32(unsafe.Sizeof(*o.rsa))
   495  		return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
   496  	})
   497  	if err != nil {
   498  		return 0, nil, err
   499  	}
   500  	sa, _ = o.rsa.Sockaddr()
   501  	return
   502  }
   503  
   504  func (fd *netFD) Write(buf []byte) (int, error) {
   505  	if err := fd.writeLock(); err != nil {
   506  		return 0, err
   507  	}
   508  	defer fd.writeUnlock()
   509  	if raceenabled {
   510  		raceReleaseMerge(unsafe.Pointer(&ioSync))
   511  	}
   512  	o := &fd.wop
   513  	o.InitBuf(buf)
   514  	return wsrv.ExecIO(o, "WSASend", func(o *operation) error {
   515  		return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
   516  	})
   517  }
   518  
   519  func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
   520  	if len(buf) == 0 {
   521  		return 0, nil
   522  	}
   523  	if err := fd.writeLock(); err != nil {
   524  		return 0, err
   525  	}
   526  	defer fd.writeUnlock()
   527  	o := &fd.wop
   528  	o.InitBuf(buf)
   529  	o.sa = sa
   530  	return wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
   531  		return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
   532  	})
   533  }
   534  
   535  func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
   536  	// Get new socket.
   537  	s, err := sysSocket(fd.family, fd.sotype, 0)
   538  	if err != nil {
   539  		return nil, &OpError{"socket", fd.net, fd.laddr, err}
   540  	}
   541  
   542  	// Associate our new socket with IOCP.
   543  	netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
   544  	if err != nil {
   545  		closesocket(s)
   546  		return nil, &OpError{"accept", fd.net, fd.laddr, err}
   547  	}
   548  	if err := netfd.init(); err != nil {
   549  		fd.Close()
   550  		return nil, err
   551  	}
   552  
   553  	// Submit accept request.
   554  	o.handle = s
   555  	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
   556  	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
   557  		return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
   558  	})
   559  	if err != nil {
   560  		netfd.Close()
   561  		return nil, err
   562  	}
   563  
   564  	// Inherit properties of the listening socket.
   565  	err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
   566  	if err != nil {
   567  		netfd.Close()
   568  		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
   569  	}
   570  
   571  	return netfd, nil
   572  }
   573  
   574  func (fd *netFD) accept() (*netFD, error) {
   575  	if err := fd.readLock(); err != nil {
   576  		return nil, err
   577  	}
   578  	defer fd.readUnlock()
   579  
   580  	o := &fd.rop
   581  	var netfd *netFD
   582  	var err error
   583  	var rawsa [2]syscall.RawSockaddrAny
   584  	for {
   585  		netfd, err = fd.acceptOne(rawsa[:], o)
   586  		if err == nil {
   587  			break
   588  		}
   589  		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
   590  		// returned here. These happen if connection reset is received
   591  		// before AcceptEx could complete. These errors relate to new
   592  		// connection, not to AcceptEx, so ignore broken connection and
   593  		// try AcceptEx again for more connections.
   594  		operr, ok := err.(*OpError)
   595  		if !ok {
   596  			return nil, err
   597  		}
   598  		errno, ok := operr.Err.(syscall.Errno)
   599  		if !ok {
   600  			return nil, err
   601  		}
   602  		switch errno {
   603  		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
   604  			// ignore these and try again
   605  		default:
   606  			return nil, err
   607  		}
   608  	}
   609  
   610  	// Get local and peer addr out of AcceptEx buffer.
   611  	var lrsa, rrsa *syscall.RawSockaddrAny
   612  	var llen, rlen int32
   613  	syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
   614  		0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
   615  	lsa, _ := lrsa.Sockaddr()
   616  	rsa, _ := rrsa.Sockaddr()
   617  
   618  	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
   619  	return netfd, nil
   620  }
   621  
   622  func skipRawSocketTests() (skip bool, skipmsg string, err error) {
   623  	// From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
   624  	// Note: To use a socket of type SOCK_RAW requires administrative privileges.
   625  	// Users running Winsock applications that use raw sockets must be a member of
   626  	// the Administrators group on the local computer, otherwise raw socket calls
   627  	// will fail with an error code of WSAEACCES. On Windows Vista and later, access
   628  	// for raw sockets is enforced at socket creation. In earlier versions of Windows,
   629  	// access for raw sockets is enforced during other socket operations.
   630  	s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
   631  	if err == syscall.WSAEACCES {
   632  		return true, "skipping test; no access to raw socket allowed", nil
   633  	}
   634  	if err != nil {
   635  		return true, "", err
   636  	}
   637  	defer syscall.Closesocket(s)
   638  	return false, "", nil
   639  }
   640  
   641  // Unimplemented functions.
   642  
   643  func (fd *netFD) dup() (*os.File, error) {
   644  	// TODO: Implement this
   645  	return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
   646  }
   647  
   648  var errNoSupport = errors.New("address family not supported")
   649  
   650  func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
   651  	return 0, 0, 0, nil, errNoSupport
   652  }
   653  
   654  func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
   655  	return 0, 0, errNoSupport
   656  }