#include <stdio.h>
#include <memory.h>
#include <malloc.h>
#include <unistd.h>
#include <bits/sockaddr.h>
#include <linux/netlink.h>
#include <sys/socket.h>

/* Sollte in .../include/linux/netlink.h stehen */
#define NETLINK_TEST 25

#define MY_NL_COMMAND 0x11
#define MAX_PAYLOAD 1024

int main( int argc, char **argv )
{
 struct sockaddr_nl src_addr, dst_addr;
 struct nlmsghdr *nlh = NULL;
 struct msghdr msg;
 struct iovec iov;
 int sock_fd;

 /* Eigenen Endpoint erstellen */
 sock_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_TEST);
 memset(&src_addr, 0, sizeof(src_addr));
 src_addr.nl_family = AF_NETLINK;
 src_addr.nl_pid = getpid();
 src_addr.nl_groups = 0; /* kein multicast */
 bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));

 /* Zieladresse vorbereiten */
 memset(&dst_addr, 0, sizeof(dst_addr));
 dst_addr.nl_family = AF_NETLINK;
 dst_addr.nl_pid = 0; /* 0 -> kernel */
 dst_addr.nl_groups = 0; /* kein multicast */

 /* Netlink-Header erstellen */
 nlh = (struct nlmsghdr *)calloc(1, NLMSG_SPACE(MAX_PAYLOAD));
 memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
 nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
 nlh->nlmsg_pid = getpid();
 printf("Absender: %d\n", nlh->nlmsg_pid);
 nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ECHO;
 nlh->nlmsg_type = MY_NL_COMMAND;

 /* Daten einpacken */
 strcpy(NLMSG_DATA(nlh), "Hello World");

 iov.iov_base = (void *)nlh;
 iov.iov_len = nlh->nlmsg_len;

 memset(&msg,0,sizeof(msg));
 msg.msg_name = (void *)&dst_addr;
 msg.msg_namelen = sizeof(dst_addr);
 msg.msg_iov = &iov;
 msg.msg_iovlen = 1; /* Anzahl */
 sendmsg(sock_fd, &msg, 0);

 /* Read message from kernel */
 printf("Warte auf Antwort...\n");
 recvmsg(sock_fd, &msg, 0);
 printf("Antwort:\n\tflags %d\n\ttype %d\n\t%s\n",
   nlh->nlmsg_flags,
   nlh->nlmsg_type,
   (char *)NLMSG_DATA(nlh));
 close(sock_fd);
 return 0;
}