Skip to content

Instantly share code, notes, and snippets.

@linuxthor
Created November 20, 2020 12:03
Show Gist options
  • Save linuxthor/a66ae4e106478c60c8a6d3ab0e4c5f59 to your computer and use it in GitHub Desktop.
Save linuxthor/a66ae4e106478c60c8a6d3ab0e4c5f59 to your computer and use it in GitHub Desktop.
dbus-message.c
// linuxthor
//
// Showing how to open a socket connection to dbus and do 'raw' messages (i.e. just sending
// some bytes and not worrying about weird stuff like Dict of{String, Variant} or whatever
// for the moment..)
//
// Started off fun but the whole thing is surprisingly bulky & annoying tbh
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <poll.h>
#include <signal.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "hexdump.h"
int main(void)
{
int x,y;
struct sockaddr_un *sock;
struct msghdr *mhdr;
struct msghdr *rxmhdr;
struct iovec iov[2];
struct iovec rxv[2];
char take[1024];
socklen_t *socklen;
struct pollfd fds;
char *dbus_path = "/run/user/1000/bus"; // <-- 'session bus' for uid 1000
char *auth_string = "AUTH EXTERNAL 31303030\r\n"; // <-- other methods per docs but only seen this
char *dbus_hello = "l\1\0\1\0\0\0\0\1\0\0\0n\0\0\0\1\1o\0\25\0\0\0/org/freedesktop/DBus\0\0\0\6\1s\0\24\0\0\0\
org.freedesktop.DBus\0\0\0\0\2\1s\0\24\0\0\0org.freedesktop.DBus\0\0\0\0\3\1s\0\5\0\0\0Hello\0\0\0";
char *dbus_mesg = "l\1\0\1\0\0\0\0\2\0\0\0h\0\0\0\1\1o\0\20\0\0\0/org/freedesktop\0\0\0\0\0\0\0\0\2\1s\0\17\0\0\0\
org.freedesktop\0\3\1s\0\7\0\0\0attempt\0\6\1s\0\27\0\0\0org.freedesktop.attempt\0";
sock = malloc(sizeof(struct sockaddr_un));
mhdr = (struct msghdr *)malloc(sizeof(struct msghdr));
rxmhdr = (struct msghdr *)malloc(sizeof(struct msghdr));
socklen = malloc(sizeof (socklen_t));
sock->sun_family = AF_UNIX;
strncpy(sock->sun_path, dbus_path, sizeof(sock->sun_path) - 1);
socklen[0] = 256;
// preamble.. (you MUST do the poll() dance or nothing happens)
x = socket(AF_UNIX, SOCK_STREAM, 0);
fds.fd = x;
fds.events = POLLOUT;
printf("Connecting. .\n");
connect(x, (struct sockaddr *)sock, 20);
fcntl(x, F_GETFL);
fcntl(x, F_SETFL, O_RDWR|O_NONBLOCK);
poll(&fds, 1, 0);
fds.events = POLLIN;
printf("Sending null. .\n");
sendto(x, "\0", 1, MSG_NOSIGNAL, NULL, 0);
printf("Sending auth. .\n");
sendto(x, auth_string, strlen(auth_string), MSG_NOSIGNAL, NULL, 0);
poll(&fds, 1, -1);
read(x, take, 1024);
printf("Server replies: %s\n",take);
sendto(x, "NEGOTIATE_UNIX_FD\r\n", 19, MSG_NOSIGNAL, NULL, 0);
poll(&fds, 1, -1);
read(x, take, 1024);
printf("Server replies: %s\n",take);
sendto(x, "BEGIN\r\n", 7, MSG_NOSIGNAL, NULL, 0);
fds.events = POLLIN|POLLOUT;
poll(&fds, 1, -1);
// tx vectors (like writev/readv)
iov[0].iov_base = dbus_hello;
iov[0].iov_len = 128;
iov[1].iov_base = 0;
iov[1].iov_len = 0;
mhdr->msg_iov = iov;
mhdr->msg_iovlen = 2;
// rx vectors
rxv[0].iov_base = take;
rxv[0].iov_len = 1024;
rxv[1].iov_base = 0;
rxv[1].iov_len = 0;
rxmhdr->msg_namelen = 0;
rxmhdr->msg_iov = rxv;
rxmhdr->msg_iovlen = 2;
// switch to sendmsg / recvmsg and do hello - should check the response here
printf("Sending hello\n");
y = sendmsg(x, mhdr, MSG_NOSIGNAL);
hexdump(iov[0].iov_base, y);
fds.events = POLLIN;
poll(&fds, 1, 2500);
printf("Server replies\n");
y = recvmsg(x, rxmhdr, MSG_CMSG_CLOEXEC);
hexdump(rxv[0].iov_base,y);
// end of preamble.. now prepare the actual message
iov[0].iov_base = dbus_mesg;
iov[0].iov_len = 120;
iov[1].iov_base = 0;
iov[1].iov_len = 0;
mhdr->msg_iov = iov;
mhdr->msg_iovlen = 2;
// and send it..
printf("Sending message\n");
y = sendmsg(x, mhdr, MSG_NOSIGNAL);
hexdump(iov[0].iov_base, y);
fds.events = POLLIN;
poll(&fds, 1, 2500);
printf("Server replies\n");
y = recvmsg(x, rxmhdr, MSG_CMSG_CLOEXEC);
hexdump(rxv[0].iov_base,y);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment