Introduce pet-projects dir
[lcapit-junk-code.git] / linux-kernel / netlink / echo / echo-test.c
blob9b96aa722d62d076016aad247c7864a282016ef4
1 /*
2 * echo-test: sends a netlink message to the kernel and reads it back.
3 *
4 * This requires the netlink-echo kernel module. It reads a netlink
5 * message (a string) from user-space and sends it back.
6 *
7 * Luiz Fernando N. Capitulino
8 * <lcapitulino@gmail.com>
9 */
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <linux/netlink.h>
18 #define NETLINK_ECHO 20 // from netlink-echo.c
20 static void usage(void)
22 printf("echo-test < string >\n");
25 /* create_socket(): Create a netlink socket and bind it.
26 * Return a file-descriptor on success, -1 otherwise. */
27 static int create_socket(void)
29 int err, fd;
30 struct sockaddr_nl sa;
32 fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ECHO);
33 if (fd < 0)
34 return -1;
36 memset(&sa, 0, sizeof(sa));
37 sa.nl_family = AF_NETLINK;
38 sa.nl_pid = getpid(); // self pid
40 err = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
41 if (err)
42 return -1;
44 return fd;
47 /* send_message(): Send a netlink message to the kernel.
48 * The argument 'message' must be a human readable string.
49 * Return the amount of bytes sent on success, -1 on failure. */
50 static ssize_t send_message(int sock_fd, const char *message)
52 size_t len;
53 ssize_t bytes;
54 struct iovec iov;
55 struct msghdr msg;
56 struct nlmsghdr *nlhdr;
57 struct sockaddr_nl nladdr;
59 len = sizeof(*nlhdr) + strlen(message) + 1;
60 nlhdr = malloc(len);
61 if (!nlhdr)
62 return -1;
64 memset(nlhdr, 0, len);
65 nlhdr->nlmsg_len = len;
66 nlhdr->nlmsg_pid = getpid();
67 strcpy(NLMSG_DATA(nlhdr), message);
69 iov.iov_base = (void *) nlhdr;
70 iov.iov_len = nlhdr->nlmsg_len;
72 memset(&nladdr, 0, sizeof(nladdr));
73 nladdr.nl_family = AF_NETLINK;
75 memset(&msg, 0, sizeof(msg));
76 msg.msg_name = (void *) &(nladdr);
77 msg.msg_namelen = sizeof(nladdr);
78 msg.msg_iov = &iov;
79 msg.msg_iovlen = 1;
81 bytes = sendmsg(sock_fd, &msg, 0);
83 free(nlhdr);
84 return bytes;
87 static struct nlmsghdr *read_message(int sock_fd, size_t len)
89 ssize_t bytes;
90 struct iovec iov;
91 struct msghdr msg;
92 struct nlmsghdr *nlhdr;
93 struct sockaddr_nl nladdr;
95 len += sizeof(*nlhdr);
96 nlhdr = malloc(len);
97 if (!nlhdr)
98 return NULL;
100 memset(nlhdr, 0, len);
101 nlhdr->nlmsg_len = len;
102 nlhdr->nlmsg_pid = getpid();
103 iov.iov_base = (void *) nlhdr;
104 iov.iov_len = nlhdr->nlmsg_len;
106 memset(&nladdr, 0, sizeof(nladdr));
107 nladdr.nl_family = AF_NETLINK;
109 memset(&msg, 0, sizeof(msg));
110 msg.msg_name = (void *) &(nladdr);
111 msg.msg_namelen = sizeof(nladdr);
112 msg.msg_iov = &iov;
113 msg.msg_iovlen = 1;
115 bytes = recvmsg(sock_fd, &msg, 0);
116 if (bytes < 0) {
117 free(nlhdr);
118 return NULL;
121 return nlhdr;
124 int main(int argc, char *argv[])
126 int sock_fd;
127 ssize_t bytes;
128 struct nlmsghdr *msg;
130 if (argc != 2) {
131 usage();
132 exit(1);
135 sock_fd = create_socket();
136 if (sock_fd < 0) {
137 perror("create_socket()");
138 exit(1);
141 bytes = send_message(sock_fd, argv[1]);
142 if (bytes < 0) {
143 perror("send_message()");
144 exit(1);
147 msg = read_message(sock_fd, strlen(argv[1]) + 1);
148 if (!msg) {
149 perror("read_message()");
150 exit(1);
153 printf("%s\n", (char *) NLMSG_DATA(msg));
155 free(msg);
156 close(sock_fd);
158 return 0;