summaryrefslogtreecommitdiffstats
path: root/src/nlapi.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-08-09 16:41:59 +0000
committerLennart Poettering <lennart@poettering.net>2003-08-09 16:41:59 +0000
commit3e81b0123b4bbfedbdc1135a6a4305c347f91a3a (patch)
tree0df13d3199a04b9ac8b3c576d9f4881593a87a36 /src/nlapi.c
parentba2dc48008777865fec281837ad9869d76cf8e87 (diff)
Initial commit
git-svn-id: file:///home/lennart/svn/public/aeswepd/trunk@3 022f378f-78c4-0310-b860-d162c87e6274
Diffstat (limited to 'src/nlapi.c')
-rw-r--r--src/nlapi.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/nlapi.c b/src/nlapi.c
new file mode 100644
index 0000000..1f6e690
--- /dev/null
+++ b/src/nlapi.c
@@ -0,0 +1,111 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <libdaemon/dlog.h>
+
+#include "nlapi.h"
+
+int nlapi_fd = -1;
+
+struct callback_info {
+ nlapi_callback_t callback;
+ void *userdata;
+ struct callback_info * next;
+};
+
+struct callback_info *callbacks = NULL;
+
+int nlapi_open(uint32_t groups) {
+ struct sockaddr_nl addr;
+
+ if ((nlapi_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
+ fprintf(stderr, "socket(PF_NETLINK): %s\n", strerror(errno));
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_groups = groups;
+ addr.nl_pid = getpid();
+
+ if (bind(nlapi_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(nlapi_fd);
+ fprintf(stderr, "bind(): %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int nlapi_work(int block) {
+
+ assert(nlapi_fd >= 0);
+
+ for (;;) {
+ int bytes;
+ char replybuf[1024];
+ struct nlmsghdr *p = (struct nlmsghdr *) replybuf;
+
+ if ((bytes = recv(nlapi_fd, &replybuf, sizeof(replybuf), block ? 0 : MSG_DONTWAIT)) < 0) {
+
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
+
+ daemon_log(LOG_ERR, "NLAPI: recv(): %s\n", strerror(errno));
+ return -1;
+ }
+
+ for (; bytes > 0; p = NLMSG_NEXT(p, bytes)) {
+ struct callback_info *c;
+
+ if (!NLMSG_OK(p, bytes) || bytes < sizeof(struct nlmsghdr) || bytes < p->nlmsg_len) {
+ daemon_log(LOG_ERR, "NLAPI: Packet too small or truncated!\n");
+ return -1;
+ }
+
+ for (c = callbacks; c; c = c->next)
+ if (c->callback(p, c->userdata) < 0)
+ return -1;
+ }
+
+ if (block)
+ break;
+ }
+
+ return 0;
+}
+
+void nlapi_close(void) {
+ if (nlapi_fd >= 0)
+ close(nlapi_fd);
+ nlapi_fd = -1;
+
+
+ while (callbacks) {
+ struct callback_info *c = callbacks;
+ callbacks = callbacks->next;
+ free(c);
+ }
+}
+
+int nlapi_register(int (*callback) (struct nlmsghdr *n, void *u), void *u) {
+ struct callback_info *c;
+
+ assert(callback);
+
+ if (!(c = malloc(sizeof(struct callback_info)))) {
+ daemon_log(LOG_ERR, "NLAPI: Not enough memory.\n");
+ return -1;
+ }
+
+ c->callback = callback;
+ c->userdata = u;
+
+ c->next = callbacks;
+ callbacks = c;
+ return 0;
+}