UNIX domain sockets not accessable across users?
With some assistance from the ZMQ mailing list, I have made a work around. It's ugly, but seems to work consistently.
I had to make a subdirectory under /tmp and chmod 777
it. The server now creates the socket in that new folder. It also programmatically chmod 777
the socket. Now, as long as the server is run as root, any user can run a client and talk to the server.
I don't know why UNIX domain socket behave this way, but it sure is annoying.
why my unix domain socket can't work
You should be sending to /var/run/lsvr.sock
not to /var/run/lcli.sock
.
Also you don't have to bind in client so comment it out from client:
/* if(bind(CliFD, (struct sockaddr *)&cliaddr, sizeof(cliaddr)))
mpExit("cli bind");*/
can i access a unix domain socket on a remote machine?
Unix domain sockets are meant for inter-process communication within the same host machine. Data sent through these sockets are handled entirely inside the kernel. For communication between processes in different machines, you should use network sockets.
How do Unix Domain Sockets differentiate between multiple clients?
If you create a PF_UNIX
socket of type SOCK_STREAM
, and accept connections on it, then each time you accept a connection, you get a new file descriptor (as the return value of the accept
system call). This file descriptor reads data from and writes data to a file descriptor in the client process. Thus it works just like a TCP/IP connection.
There's no “unix domain protocol format”. There doesn't need to be, because a Unix-domain socket can't be connected to a peer over a network connection. In the kernel, the file descriptor representing your end of a SOCK_STREAM
Unix-domain socket points to a data structure that tells the kernel which file descriptor is at the other end of the connection. When you write data to your file descriptor, the kernel looks up the file descriptor at the other end of the connection and appends the data to that other file descriptor's read buffer. The kernel doesn't need to put your data inside a packet with a header describing its destination.
For a SOCK_DGRAM
socket, you have to tell the kernel the path of the socket that should receive your data, and it uses that to look up the file descriptor for that receiving socket.
If you bind a path to your client socket before you connect to the server socket (or before you send data if you're using SOCK_DGRAM
), then the server process can get that path using getpeername
(for SOCK_STREAM
). For a SOCK_DGRAM
, the receiving side can use recvfrom
to get the path of the sending socket.
If you don't bind a path, then the receiving process can't get an id that uniquely identifies the peer. At least, not on the Linux kernel I'm running (2.6.18-238.19.1.el5
).
How to create a Unix-domain socket with specific access permissions
Is there a way to allow the OS to implicitly generate the socket for my endpoint (i.e. the address to which the service will respond) but request that it be given certain permissions?
I solved this very problem once using two calls to umask()
.
Pseudo code:
current_mask = umask(umask_to_be_used_on_afunix_socket_file_system_entry_creation);
bind afunix socket here
umask(current_umask);
Does data passed across a unix domain socket cross the kernel boundary?
Of course Unix sockets go via the kernel, but your question is founded on a misconception. You wouldn't see a benefit from introducing another copy step via splice
.
Calling open() on a Unix domain socket failed with error No such device or address
The /tmp/pipe1
is not a pipe file. It's a socket file. That's what the leading s
means in srwxr-xr-x
.
And Bash's redirection like >
does not support socket files. You need to use socket API to open the file.
With strace (e.g. strace bash -c 'echo > /tmp/sockfile'
) we can see:
...
openat(AT_FDCWD, "/tmp/sockfile", ...) = -1 ENXIO (No such device or address)
...
So the error code is ENXIO
whose corresponding error message is No such device or address
. Bash is just calling standard C API (like strerror) to print the error.
Exampe code for client side:
int
sock_connect(char * sockpath)
{
int sock_fd;
struct sockaddr_un srv_addr = { 0 };
sock_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
if (sock_fd < 0) {
return -1;
}
srv_addr.sun_family = AF_LOCAL;
snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s", sockpath);
if (connect(sock_fd, (struct sockaddr *) & srv_addr, sizeof(srv_addr)) < 0) {
return -1;
}
return sock_fd;
}
Related Topics
"Must Be Connected to a Terminal Error" with Screen -X Command on a Linux Container
Shared Volume in Docker Through Vagrant
Executing Exe or Bat File on Remote Windows Machine from *Nix
Sudo Apt-Get Update Fail on Ubuntu 17.04
Getting Following Error After The Command Sudo Apt-Get Update on Ubuntu 16.04
Expect, Interact and Then Again Expect
What Is The Size of Coap Packet
Linux Asynch Io - Difference Between Aio.H and Libaio.H
Bash: Split Stdout from Multiple Concurrent Commands into Columns
Qemu on Raspberry Pi Arch Linux Latest Sd Image
Copy Lines Containing Word from One File to Another File in Linux
How Can Beaglebone Black Be Used as Mass Storage Device
Powershell's Equivalent to Linux's: Ls -Al
Transpose Rows into Column in Unix
What Ncurses Frameworks Are Available for Bash
Berkeley Db Mismatch Error While Configuring Ldap