-
-
Save jim3ma/93c41ac2bdf347579524b81064b5b03d to your computer and use it in GitHub Desktop.
Send a file descriptor over an abstract unix domain socket
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// compile with: gcc -static -o recvfd recvfd.c | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#include <strings.h> | |
/** | |
* Receives file descriptor using given socket | |
* | |
* @param socket to be used for fd recepion | |
* @return received file descriptor; -1 if failed | |
* | |
* @note socket should be (PF_UNIX, SOCK_DGRAM) | |
*/ | |
int recvfd(int socket) { | |
int len; | |
int fd; | |
char buf[1]; | |
struct iovec iov; | |
struct msghdr msg; | |
struct cmsghdr *cmsg; | |
char cms[CMSG_SPACE(sizeof(int))]; | |
iov.iov_base = buf; | |
iov.iov_len = sizeof(buf); | |
msg.msg_name = 0; | |
msg.msg_namelen = 0; | |
msg.msg_iov = &iov; | |
msg.msg_iovlen = 1; | |
msg.msg_flags = 0; | |
msg.msg_control = (caddr_t) cms; | |
msg.msg_controllen = sizeof cms; | |
len = recvmsg(socket, &msg, 0); | |
if (len < 0) { | |
LOGE("recvmsg failed with %s", strerror(errno)); | |
return -1; | |
} | |
if (len == 0) { | |
LOGE("recvmsg failed no data"); | |
return -1; | |
} | |
cmsg = CMSG_FIRSTHDR(&msg); | |
memmove(&fd, CMSG_DATA(cmsg), sizeof(int)); | |
return fd; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// compile with: gcc -static -o sendfd sendfd.c | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/un.h> | |
#include <strings.h> | |
/** | |
* Sends given file descriptior via given socket | |
* | |
* @param socket to be used for fd sending | |
* @param fd to be sent | |
* @return sendmsg result | |
* | |
* @note socket should be (PF_UNIX, SOCK_DGRAM) | |
*/ | |
int send_fd(int sock, int fd){ | |
// This function does the arcane magic for sending | |
// file descriptors over unix domain sockets | |
struct msghdr msg; | |
struct iovec iov[1]; | |
struct cmsghdr *cmsg = NULL; | |
char ctrl_buf[CMSG_SPACE(sizeof(int))]; | |
char data[1]; | |
memset(&msg, 0, sizeof(struct msghdr)); | |
memset(ctrl_buf, 0, CMSG_SPACE(sizeof(int))); | |
data[0] = ' '; | |
iov[0].iov_base = data; | |
iov[0].iov_len = sizeof(data); | |
msg.msg_name = NULL; | |
msg.msg_namelen = 0; | |
msg.msg_iov = iov; | |
msg.msg_iovlen = 1; | |
msg.msg_controllen = CMSG_SPACE(sizeof(int)); | |
msg.msg_control = ctrl_buf; | |
cmsg = CMSG_FIRSTHDR(&msg); | |
cmsg->cmsg_level = SOL_SOCKET; | |
cmsg->cmsg_type = SCM_RIGHTS; | |
cmsg->cmsg_len = CMSG_LEN(sizeof(int)); | |
*((int *) CMSG_DATA(cmsg)) = fd; | |
return sendmsg(sock, &msg, 0); | |
} | |
int main(int argc, char **argv){ | |
struct sockaddr_un addr; | |
int sock; | |
int conn; | |
int fd; | |
// Create a unix domain socket | |
sock = socket(AF_UNIX, SOCK_STREAM, 0); | |
// Bind it to a abstract address | |
memset(&addr, 0, sizeof(addr)); | |
addr.sun_family = AF_UNIX; | |
strcpy(&addr.sun_path[1], argv[1]); | |
bind(sock, (struct sockaddr *)&addr, sizeof(addr)); | |
// Open the file descriptor we want to send | |
fd = open(argv[2], 0); | |
// Listen | |
listen(sock, 1); | |
// Just send the file descriptor to anyone who connects | |
for(;;){ | |
conn = accept(sock, NULL, 0); | |
send_fd(conn, fd); | |
close(conn); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment