From 9a5162c33017bab6677c528189cff5a501f3822a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Aug 2003 16:36:18 +0000 Subject: netlink monitoring aded wireless querying improved git-svn-id: file:///home/lennart/svn/public/ifplugd/trunk@30 2bf48fe7-cfc1-0310-909f-d9042e1e0fef --- src/nlapi.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/nlapi.c (limited to 'src/nlapi.c') diff --git a/src/nlapi.c b/src/nlapi.c new file mode 100644 index 0000000..33b222b --- /dev/null +++ b/src/nlapi.c @@ -0,0 +1,131 @@ +/* $Id: ifplugd.c 1.12 Sat, 01 Feb 2003 03:00:07 +0100 lennart $ */ + +/* + * This file is part of ifplugd. + * + * ifplugd is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * ifplugd is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ifplugd; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#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; +} -- cgit