AF_UNIX comes to Windows

Avatar

Sarah

Introduction: 

Beginning in Insider Build 17063, you’ll be able to use the unix socket (AF_UNIX) address family on Windows to communicate between Win32 processes. Unix sockets allow inter-process communication (IPC) between processes on the same machine. 

Overview: 

Support for the unix socket has existed both in BSD and Linux for the longest time, but, not on Windows. On Windows, there were some alternatives for local IPC, such as named pipes. But, calling conventions are different between the named pipes and sockets, making writing low-maintenance cross-platform applications difficult. For example, one such place where these two constructs differ (other than the API) is terminating the connection. BSD Socket API provides a bidirectional close semantics using </span><a href="http://man7.org/linux/man-pages/man2/shutdown.2.html"><span>shutdown</span></a><span>. There is no direct equivalent of that in named pipes. Such differences make it difficult to port unix socket applications from Linux to Windows and vice versa; up until now! 

Build 17063 brings native support for the unix socket to Windows. Starting this build, two Win32 processes can use the AF_UNIX address family over Winsock API (which is very similar to the BSD socket API) to communicate with each other. Currently, the support only exists for the stream (SOCK_STREAM) socket type, which is a connection-oriented protocol for one-to-one communication. Support for the datagram (SOCK_DGRAM) can be considered in future depending on the adoption, feedback and scenarios. 

Addressing scheme – sockaddr_un: 

The ‘sockaddr_un’ structure is used for defining the address of a unix socket. In the Windows implementation of the unix socket, we have kept the name, definition and semantics of the unix socket address the same as that in Linux, to make cross-platform development easier. 

There are three different addressing formats for unix sockets. ‘pathname’, ‘abstract’ and ‘unnamed’ sockets. ‘pathname’ sockets are bound to the filesystem, where in the ‘sun_path’ member of the struct is used to specify a null-terminated UTF-8 file system path. You can expect the same from the Windows implementation, where ‘sun_path’ specifies a Win32 UTF-8 file system path. 

The second category is the ‘abstract’ socket address where the first character in ‘sun_path’ is a null byte. Windows implementation of AF_UNIX socket can also accept abstract addresses. The one difference noteworthy here is that the Windows unix socket implementation currently does not support the autobind feature whereby an abstract address is auto-generated by the implementation on behalf of the user. 

Lastly, ‘unnamed’ sockets, where the socket is bound to a pathname with no name. This is also supported on Windows unix socket implementation. Although, one of the socket API’s socketpair that generates unnamed sockets, itself is not supported in Winsock 2.0. 

Security: 

Unix sockets provide a mechanism for secure communication. Communication over unix sockets can be secured by controlling the file (or directory) permissions on the pathname sockets (or the parent directory). For example, the bind socket API creates a ‘socket’ file with the given pathname. The creation of the new socket file will fail if the calling process does not has write permission on the directory where the file is being created. Similarly, for connecting to a stream socket, the connecting process should have write permission on the socket. The same level of security is available and enforced on the Windows unix socket implementation. See the man page on AF_UNIX for more details on the security. 

Implementation: 

Majority of the functionality for the Windows AF_UNIX is implemented in the Windows kernel in a driver: afunix.sys. The Windows kernel networking stack provides a very pluggable and extensible model, that makes it easy to support new network providers. The socket file itself that is created as part of the bind call is a custom NTFS reparse point. 

Unsupported\unavailable: 

Summarizing from the above, the following Linux unix socket features are either currently unavailable or unsupported in the Windows unix socket implementation. 

  • AF_UNIX datagram (SOCK_DGRAM) or sequence packet (SOCK_SEQPACKET) socket type. 
  • Ancillary data: Linux‘s unix socket implementation supports passing ancillary data such as passing file descriptors (SCM_RIGHTS) or credentials (‘SCM_CREDENTIALS`) over the socket. There is no support for ancillary data in the Windows unix socket implementation. 
  • Autobind feature (see the section on ‘sockaddr_un’ for details). 
  • socketpair: socketpair socket API is not supported in Winsock 2.0. 

How can I write a Windows AF_UNIX app? 

  1. Download the Windows Insiders SDK for the Windows build 17061 — available here.  
  2. Check whether your Windows build has support for unix socket by running “sc query afunix” from a Windows admin command prompt. 
  3. #include <afunix.h> in your Windows application and write a Windows unix socket winsock application as you would write any other unix socket application, but, using Winsock API’s. 

Note: As mentioned above in the ‘security’ section, when a socket binds a socket to a valid pathname address, a socket file is created within the filesystem. On Linux, the application is expected to unlink (see the notes section in the man page for AF_UNIX) before any other socket can be bound to the same address. The same applies to Windows unix sockets, except that, DeleteFile (or any other file delete API) should be used to delete the socket file prior to calling bind with the same path. 

What’s next? 

We are listening. Please try out the Windows unix socket provider and let us know what works, what doesn’t work, what you like, what you don’t like or what improvements would you like.  For now, the best way to provide feedback is either via Feedback Hub under apps -> Hyper-V, the WSL GitHub issue tracker, or as a comment on this blog.

And, if you are wondering, there is already support for unix socket within Windows Subsystem for Linux (WSL), how does that work with the Windows unix socket implementation? Well, currently, it doesn’t, but stay tuned! 

– Sunil Muthuswamy and the WSL Team

Avatar
Sarah Cooley

Follow Sarah   

2 comments

  • Avatar
    Joshua Schaeffer

    We need socketpair(). A common scenario is to create an endpoint and inherit the handle to a child worker process, and it’s preferable not to clutter the Ipv4 namespace using “localhost”. If we can’t have that yet, then we need server/client code examples for abstract AF_UNIX sockets on Winsock 2.0. Named pipes don’t have the convenient scatter/gather semantics that sockets have.

    In “afunix.h” the sun_path field is actually implemented as wchar_t Path[63] which is Unicode. The text mentioning UTF-8 and a null byte is not correct.

Leave a comment