summaryrefslogtreecommitdiff
path: root/netfilter/nl.c
diff options
context:
space:
mode:
Diffstat (limited to 'netfilter/nl.c')
-rw-r--r--netfilter/nl.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/netfilter/nl.c b/netfilter/nl.c
new file mode 100644
index 0000000..ca71ca0
--- /dev/null
+++ b/netfilter/nl.c
@@ -0,0 +1,193 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <linux/netlink.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+
+enum type_t {
+ TYPE_SYSFS,
+ TYPE_NETLINK,
+};
+
+int dump(void *_a, size_t s)
+{
+ size_t i, j;
+ unsigned char *p = _a;
+
+ for (i = 0; i < s; i += 16) {
+ for (j = 0; j < 16; j ++ ) {
+ if (j == 8)
+ printf(" - ");
+ if (i + j > s) {
+ printf(" ");
+ } else {
+ printf("%c", (isprint(p[i+j])) ? p[i+j] : '.');
+ }
+ }
+ printf(" ");
+ for (j = 0; j < 16; j ++ ) {
+ if (j == 8)
+ printf(" - ");
+ printf("%02X ", p[i+j]);
+ }
+ printf("\n");
+ }
+ return 0;
+}
+
+int sysfs_handle_open(char *name)
+{
+ char sysfs[256] = "/sys/devices/virtual/xt_idletimer/timers/";
+ char buffer[256];
+ int r, rd;
+
+ strcat(sysfs, name);
+ r = open(sysfs, O_RDONLY);
+ if (r < 0)
+ return r;
+ rd = read(r, buffer, sizeof(buffer));
+ return r;
+}
+
+#define sysfs_handle_close(h) close(h)
+
+int netlink_socket_open(struct sockaddr_nl *s_nladdr)
+{
+ int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ bind(fd, (struct sockaddr*)s_nladdr, sizeof(*s_nladdr));
+ return fd;
+}
+
+#define netlink_socket_close(h) close(h)
+
+int do_wait(char *nick, enum type_t type, int seconds)
+{
+ struct pollfd pfd;
+ int r;
+ short exp;
+ struct sockaddr_nl s_nladdr;
+ static char buffer[256];
+ char *ptr;
+
+ pfd.revents = 0;
+
+ if (type == TYPE_SYSFS) {
+
+ pfd.fd = sysfs_handle_open(nick);
+ pfd.events = POLLPRI | POLLERR;
+ exp = POLLPRI | POLLERR;
+
+ }
+
+ if (type == TYPE_NETLINK) {
+
+ memset(&s_nladdr, 0 ,sizeof(s_nladdr));
+ s_nladdr.nl_family = AF_NETLINK ;
+ s_nladdr.nl_pid = getpid();
+ s_nladdr.nl_groups = 0xffffffff;
+
+ pfd.fd = netlink_socket_open(&s_nladdr);
+ pfd.events = POLLIN;
+ exp = POLLIN;
+ }
+
+ r = poll(&pfd, 1, seconds * 1000);
+ if (r <= 0)
+ return r;
+
+ if (type == TYPE_NETLINK) {
+ struct msghdr msg;
+ struct iovec iov[2];
+ struct nlmsghdr nlh;
+
+ iov[0].iov_base = (void *)&nlh;
+ iov[0].iov_len = sizeof(nlh);
+ iov[1].iov_base = (void *)buffer;
+ iov[1].iov_len = sizeof(buffer);
+ msg.msg_name = &s_nladdr;
+ msg.msg_namelen = sizeof(s_nladdr);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
+ memset(buffer, 0, sizeof(buffer));
+
+ r = recvmsg(pfd.fd, &msg, 0);
+ } else {
+ lseek(pfd.fd, 0, SEEK_SET);
+ r = read(pfd.fd, buffer, sizeof(buffer));
+ }
+ if (r < 0)
+ return r;
+
+ for (ptr = buffer; ptr - buffer < r; ptr = ptr + strlen(ptr) + 1) {
+ if (strlen(ptr) == 0)
+ continue;
+ printf("%s\n", ptr);
+ }
+ return 1;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int c, r, opti;
+ int timeout_sec = 10;
+ struct option lopt[] = {
+ { "timeout", required_argument, NULL, 't' },
+ { "sysfs", required_argument, NULL, 's' },
+ { "netlink", no_argument, NULL, 'n' },
+ { NULL, 0, NULL, 0 },
+ };
+ char *shopt = "ts:n";
+ char *nick = NULL;
+ enum type_t type;
+
+ while ((c = getopt_long(argc, argv, shopt, lopt, &opti)) != -1 ) {
+ switch (c) {
+ case 't':
+ timeout_sec = atoi(optarg);
+ break;
+ case 's':
+ case 'n':
+ if (!nick) {
+ if (optarg) {
+ nick = strdup(optarg);
+ } else {
+ nick = (char*)0xffffffff;
+ }
+ type = (c == 's' ? TYPE_SYSFS : TYPE_NETLINK);
+ } else {
+ printf("sysfs and netlink could not be used at the same time\n");
+ exit(1);
+ }
+ break;
+ default:
+ printf("Hmmm, c = 0x%x (%c)\n", c, isprint(c) ? c : '*');
+ break;
+ }
+ }
+ if (!nick) {
+ printf("Sorry, you have to provide one of --sysfs=ARG or --netlink\n");
+ return EINVAL;
+ }
+
+ r = do_wait(nick, type, timeout_sec);
+ if (r < 0) {
+ perror("do_wait");
+ return r;
+ }
+ else if (r == 0) {
+ printf("No data within %d seconds\n", timeout_sec);
+ return 1;
+ }
+ printf("OK\n");
+ return 0;
+}
+