0

I have several pieces of codes to establish a Unix domain socket and a service using this socket. While there are some confusing errors here leading to a failure.

the code that creats the Unix domain socket is written in c:

#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

int main(int ac, char *av[])
{
if (ac != 4) {
    printf("Usage: %s dummy-fd sockpath binary\n", av[0]);
    exit(-1);
    }

    char *sockpn = av[2];
    char *bin = av[3];

    int srvfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (srvfd < 0) {
    perror("socket");
    exit(-1);
    }

    fcntl(srvfd, F_SETFD, FD_CLOEXEC);

    struct stat st;
    if (stat(sockpn, &st) >= 0) {
    if (!S_ISSOCK(st.st_mode)) {
        fprintf(stderr, "socket pathname %s exists and is not a socket\n",
            sockpn);
        exit(-1);
    }

    unlink(sockpn);
    }

    struct sockaddr_un addr;
    addr.sun_family = AF_UNIX;
    snprintf(&addr.sun_path[0], sizeof(addr.sun_path), "%s", sockpn);
    if (bind(srvfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        fprintf(stderr, "WARNING: cannot bind to socket %s (%s), exiting\n",
                sockpn, strerror(errno));
    exit(-1);
    }

    // allow anyone to connect; for access control, use directory permissions
    chmod(sockpn, 0777);

    listen(srvfd, 5);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    for (;;) {
    struct sockaddr_un client_addr;
    unsigned int addrlen = sizeof(client_addr);

    int cfd = accept(srvfd, (struct sockaddr *) &client_addr, &addrlen);
    if (cfd < 0) {
        perror("accept");
        continue;
    }

    int pid = fork();
    if (pid < 0) {
        perror("fork");
        close(cfd);
        continue;
    }

    if (pid == 0) {
        // Child process
        dup2(cfd, 0);
        dup2(cfd, 1);
        close(cfd);

        execl(bin, bin, 0);
        perror("execl");
        exit(-1);
    }

    close(cfd);
    }
}

the client Python to using this sock is as follow(unixclient.py):

def call(pn, req):
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.connect(pn)
    sock.send(req)
    sock.shutdown(socket.SHUT_DOWN)
    data = ""
    while True:
        buf = sock.recv(1024)
        if not buf:
             break
        data += buf
    sock.close()
    return data

And I trigger this piece of client code in another Python code, by importing this file and call the call funciton:(Both "/jail/zoobar/echosvc" and "/jail/zoobar/echosvc/sock" will fail)

   resp = call("/jail/zoobar/echosvc", str1)

There the error occurs, showing that:

   FIle "zoobar/unixclient.py", line 8, in call
    sock.connect(pn)
   File "<string>", line 1, in connect
   error: [ERROR 2] No such file or directory

Yet I swear the directory and the socket does exist(/jail/zoobar/echosvc/sock), and the permission is correct, too(777), so I can't understand this weird error. Does anyone know about it?

I would appreciate very much for sparing time to help.

5
  • I add a line memset(&address, 0, sizeof(struct sockaddr_un)); in the first piece of code, yet the same failure. Commented Feb 5, 2013 at 16:42
  • pn is the path of domain socket, here is "/jail/zoobar/echosvc", req is a parameter, it doesn't matter in connection. When pn is "/jail/zoobar/echosvc/sock" the same failure still occurs. Commented Feb 5, 2013 at 16:55
  • sorry I made a typo, the second sock is actually socket, I'll fix it immediately Commented Feb 5, 2013 at 16:56
  • Probably not helping you, but I have no problem running your programs on my machine. Only thing I can think of: I'm running this all under my home directory (though 777 would suggest that shouldn't matter anyway). So it doesn't look like to be the programs; more like something in the system. Commented Feb 5, 2013 at 17:06
  • Thank you anyway :), but I can't find other problems except the permission. Commented Feb 5, 2013 at 17:14

1 Answer 1

1

Looks like you're trying to open the wrong filename. The code looks like:

resp = call("/jail/zoobar/echosvc", str1)

But you say "the file exists":

/jail/zoobar/echosvc/sock

Try changing your call line to:

resp = call("/jail/zoobar/echosvc/sock", str1)
Sign up to request clarification or add additional context in comments.

5 Comments

Actually I already tried, but it doesn't work. :( Still same result. Maybe it's more like something in the system.
Hmm. OK. Most of the example code I've seen creates unix sockets in /tmp. Maybe there's a reason for that? Also, the "/jail/..." implies there's possibly some kind of chroot or sandboxing going on. Are you running the python script and the C program as the same user?
No, I don't. The C program is started by a deamon process. The python script is triggered by a .cgi file using HTTP request. They are running under different UIDs.
OK, so in addition to the file permissions, I believe you also need to make sure the directory is world readable (and maybe the parent directories, too). Or, figure out a spot on the filesystem where the HTTP user has access, and put the socket file there.
the parent directories' permissions are all 755 and the sock itself is 777, and socket file does exit within the access to HTTP user, that's...so strange...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.