Skip to content

Instantly share code, notes, and snippets.

@jim3ma
Created August 22, 2018 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jim3ma/c12db698290978d55627e865a0590afe to your computer and use it in GitHub Desktop.
Save jim3ma/c12db698290978d55627e865a0590afe to your computer and use it in GitHub Desktop.
Send a file descriptor over an abstract unix domain socket
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <strings.h>
#include <errno.h>
#define NAME ".socket"
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) {
printf("recvmsg failed with %s", strerror(errno));
return -1;
}
if (len == 0) {
printf("recvmsg failed no data");
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
return fd;
}
main()
{
int fd, sock, msgsock, rval;
struct sockaddr_un server;
char buf[1024];
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path, NAME);
if (bind(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un))) {
perror("binding stream socket");
exit(1);
}
printf("Socket has name %s\n", server.sun_path);
listen(sock, 5);
for (;;) {
msgsock = accept(sock, 0, 0);
if (msgsock == -1)
perror("accept");
fd = recvfd(msgsock);
printf("-->%d\n", fd);
close(msgsock);
}
close(sock);
unlink(NAME);
}
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.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);
}
main(argc, argv)
int argc;
char *argv[];
{
int fd, sock;
struct sockaddr_un server;
char buf[1024];
if (argc < 3) {
printf("usage:%s <sock path> <file name>", argv[0]);
exit(1);
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path, argv[1]);
if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
close(sock);
perror("connecting stream socket");
exit(1);
}
// Open the file descriptor we want to send
fd = open(argv[2], 0);
send_fd(sock, fd);
close(sock);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment