Skip to content

Instantly share code, notes, and snippets.

@legionus
Created June 13, 2017 12:03
Show Gist options
  • Save legionus/aef922106f6173f071c2f8fabd20d418 to your computer and use it in GitHub Desktop.
Save legionus/aef922106f6173f071c2f8fabd20d418 to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
int main(int argc, const char *argv[])
{
int sock_pair[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sock_pair) < 0) {
perror("socketpair: ");
return -1;
}
int reader_fd = sock_pair[0];
int writer_fd = sock_pair[1];
int enable = 1;
if (setsockopt(reader_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) < 0) {
perror("setsockopt: ");
return -1;
}
char buf[] = "hello";
const size_t length = sizeof(buf);
struct iovec iov = { buf, length };
struct msghdr msg = {};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
const ssize_t control_len_snd = CMSG_SPACE(sizeof(int));
char control_buf_snd[control_len_snd];
msg.msg_control = control_buf_snd;
msg.msg_controllen = control_len_snd;
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &reader_fd, sizeof(int));
if (sendmsg(writer_fd, &msg, 0) < 0) {
perror("sendmesg: ");
return -1;
}
char recv_buf[sizeof(buf)] = {};
struct iovec iov2 = { recv_buf, length };
msg.msg_iov = &iov2;
msg.msg_iovlen = 1;
const ssize_t control_len_rcv = CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int));
char control_buf_rcv[control_len_rcv];
msg.msg_control = control_buf_rcv;
msg.msg_controllen = control_len_rcv;
if (recvmsg(reader_fd, &msg, 0) < 0) {
perror("recvmesg: ");
return -1;
}
int got_fd = -1;
pid_t got_pid = -1;
if (msg.msg_controllen > 0) {
struct cmsghdr *cmsg; // hides
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
switch (cmsg->cmsg_type) {
case SCM_RIGHTS:
if (payload_len != sizeof(int)) {
fprintf(stderr, "expected fd payload sizeof(int)\n");
return -1;
}
got_fd = *((int *)(CMSG_DATA(cmsg)));
printf("got fd: %d\n", got_fd);
break;
case SCM_CREDENTIALS:
if (payload_len != sizeof(struct ucred)) {
fprintf(stderr, "expected rights payload sizeof(struct ucred)\n");
return -1;
}
got_pid = ((struct ucred *)(CMSG_DATA(cmsg)))->pid;
printf("got pid: %d\n", got_pid);
break;
}
}
}
printf("got message buffer: %s\n", recv_buf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment