Can not connect to an abstract unix socket in python
Question: I have a server written in c++ which creates and binds to an abstract unix
socket with a namespace address of `"\0hidden"`. I also have a client which is
written in c++ also and this client can **successfully** connect to my server.
BTW, I do not have the source code of this client. Now I am trying to connect
to my server using a client I have written in python with no success. I do not
understand why my python client is not working. I am posting the relevant
parts of my server and client codes.

Server

    
    
    #define UD_SOCKET_PATH          "\0hidden"
    struct sockaddr_un addr;
    int fd,cl;
    
    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 
    {
        syslog(LOG_CRIT, "Error creating socket!");
        exit(1);
    }
    
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, UD_SOCKET_PATH, sizeof(addr.sun_path)-1);
    unlink(UD_SOCKET_PATH);
    
    
    if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) 
    {
        syslog(LOG_CRIT, "Bind error");
        exit(1);
    }
    
    if (listen(fd, MAX_CONN_PENDING) == -1) 
    {
        syslog(LOG_CRIT, "Listen error");
        exit(1);
    }
    
    syslog(LOG_INFO, "Start listening.");
    

And my client code

    
    
    #! /opt/python/bin/python
    import os
    import socket
    import sys
    # Create a UDS socket
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    
    server_address = "\0hidden"
    print >>sys.stderr, 'connecting to %s' % server_address.decode("utf-8")
    try:
        sock.connect(server_address)
    except socket.error, msg:
        print >>sys.stderr, msg
        sys.exit(1)
    

After running the client I get the following error output:

    
    
    connecting to hidden
    [Errno 111] Connection refused
    

And for some extra information I am posting the relevant parts of the strace
outputs of my working c++ client and non-working python client:

Working c++ client:

    
    
    socket(PF_FILE, SOCK_STREAM, 0)         = 3
    connect(3, {sa_family=AF_FILE, path=@""}, 110) = 0
    fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d7000
    write(1, "Sent message is: 00014 www.googl"..., 38) = 38
    write(3, "00014 www.google.com", 20)    = 20
    recv(3, "014 Search Engines", 99, 0)    = 18
    write(1, "014 Search Engines\n", 19)    = 19
    close(3)                                = 0
    exit_group(0)                           = ?
    

None working python client:

    
    
    socket(PF_FILE, SOCK_STREAM, 0)         = 3
    connect(3, {sa_family=AF_FILE, path=@"hidden"...}, 9) = -1 ECONNREFUSED (Connection refused)
    write(2, "Traceback (most recent call last"..., 35) = 35
    write(2, "  File \"./uds.py\", line 13, in <"..., 40) = 40
    open("./uds.py", O_RDONLY|O_LARGEFILE)  = 4
    fstat64(4, {st_mode=S_IFREG|0755, st_size=839, ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7792000
    read(4, "#! /opt/python/bin/python\nimport"..., 4096) = 839
    write(2, "    ", 4)                     = 4
    write(2, "sock.connect('\\0hidden')\n", 25) = 25
    close(4)                                = 0
    munmap(0xb7792000, 4096)                = 0
    write(2, "  File \"/opt/python/lib/python2."..., 64) = 64
    open("/opt/python/lib/python2.7/socket.py", O_RDONLY|O_LARGEFILE) = 4
    fstat64(4, {st_mode=S_IFREG|0755, st_size=20234, ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7792000
    read(4, "# Wrapper module for _socket, pr"..., 4096) = 4096
    read(4, "oo long.\"\n    errorTab[10064] = "..., 4096) = 4096
    write(2, "    ", 4)                     = 4
    write(2, "return getattr(self._sock,name)("..., 39) = 39
    close(4)                                = 0
    munmap(0xb7792000, 4096)                = 0
    write(2, "socket", 6)                   = 6
    write(2, ".", 1)                        = 1
    write(2, "error", 5)                    = 5
    write(2, ": ", 2)                       = 2
    write(2, "[Errno 111] Connection refused", 30) = 30
    write(2, "\n", 1)                       = 1
    rt_sigaction(SIGINT, {SIG_DFL, [], 0}, {0x810fbe0, [], 0}, 8) = 0
    close(3)                                = 0
    exit_group(1)                           = ?
    

And also when I run my c++ client, I get this strace output from my server:

    
    
    0, NULL)                      = 12
    futex(0x80646a4, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x8064688, 360) = 10
    futex(0x8064688, FUTEX_WAKE_PRIVATE, 1) = 1
    accept(5, 
    

But when I run my python client, no output is shown on strace. So it seems
like I am trying to connect to a wrong address, but my address is defined as
`"\0hidden"` in both my server and my client.


Answer: Your C++ doesn't do quite what you think it does. This line:

    
    
    strncpy(addr.sun_path, UD_SOCKET_PATH, sizeof(addr.sun_path)-1);
    

Copies a single null character `'\0'` into `addr.sun_path`. Note this line in
the manpage for `strncpy()`:

> If the length of src is less than n, strncpy() writes additional null bytes
> to dest to ensure that a total of n bytes are written.

As a result your C++ actually connects to an abstract domain socket at `"\0"`.
Python does the right thing here and connects to an abstract domain socket at
`"\0hidden"`.

