All of lore.kernel.org
 help / color / mirror / Atom feed
From: heitzenberger@astaro.com
To: netfilter-devel@vger.kernel.org
Cc: holger@eitzenberger.org
Subject: [ULOGD 04/15] Add IFI list
Date: Sat, 02 Feb 2008 21:48:30 +0100	[thread overview]
Message-ID: <20080202205107.726859754@astaro.com> (raw)
In-Reply-To: 20080202204826.267107164@astaro.com

Hi,
Content-Disposition: inline; filename=ulogd-ifi.diff

IFI implements a list of up-to-date network interfaces with MAC
addresses, mostly used for logging and accounting.  It is therefore
quite redudant to the IFINDEX plugin, but IMO this should go into
ulogd core and not into a plugin.

A future step might be to drop IFINDEX plugin.

Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>

Index: ulogd-netfilter/include/ulogd/ifi.h
===================================================================
--- /dev/null
+++ ulogd-netfilter/include/ulogd/ifi.h
@@ -0,0 +1,43 @@
+/*
+ * ifi.h
+ *
+ * Maintain a list of network interfaces.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Holger Eitzenberger <holger@eitzenberger.org>  Astaro AG, 2007.
+ */
+#ifndef IFI_H
+#define IFI_H
+
+#include <ulogd/linuxlist.h>
+#include <net/if.h>
+
+
+struct ifi {
+	struct llist_head link;
+	unsigned idx;			/* interface index */
+	unsigned used : 1;
+	unsigned flags;
+	char name[IFNAMSIZ];
+	unsigned char lladdr[6];
+};
+
+int ifi_init(void);
+void ifi_fini(void);
+
+struct ifi *ifi_find_by_idx(unsigned);
+
+#endif /* IFI_H */
Index: ulogd-netfilter/src/ifi.c
===================================================================
--- /dev/null
+++ ulogd-netfilter/src/ifi.c
@@ -0,0 +1,379 @@
+/*
+ * ifi.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Holger Eitzenberger <holger@eitzenberger.org>  Astaro AG 2007.
+ */
+
+#include <ulogd/ulogd.h>
+#include <ulogd/common.h>
+#include <ulogd/ifi.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
+
+#define IFI_STATIC_MAX			64
+
+
+/* the first IFI_STATIC_MAX entries are kept in ifi_static[] for performance
+   reasons, whereas all entries with an interface index larger than
+   IFI_STATIX_MAX-1 are kept in the linked ifi_list. */
+static LLIST_HEAD(ifi_list);
+static struct ifi ifi_static[IFI_STATIC_MAX];
+
+static unsigned nl_seq;			/* last seq# */
+
+
+static struct ifi *
+ifi_alloc(void)
+{
+	struct ifi *ifi;
+
+	if ((ifi = calloc(1, sizeof(struct ifi))) == NULL)
+		return NULL;
+
+	return ifi;
+}
+
+
+struct ifi *
+ifi_find_by_idx(unsigned idx)
+{
+	struct ifi *ifi;
+
+	if (idx < IFI_STATIC_MAX)
+		ifi = &ifi_static[idx];
+	else {
+		llist_for_each_entry(ifi, &ifi_list, link) {
+			if (ifi->idx == idx)
+				break;
+		}
+
+		if (ifi == NULL)
+			return NULL;
+	}
+
+	return ifi->used ? ifi : NULL;
+}
+
+
+static struct ifi *
+ifi_find_or_add(unsigned idx)
+{
+	struct ifi *ifi = ifi_find_by_idx(idx);
+
+	if (ifi != NULL) {
+		pr_debug("%s: found ifi '%s' (index %u)\n", __func__,
+				 ifi->name, ifi->idx);
+		return ifi;
+	}
+
+	/* add */
+	if (idx < IFI_STATIC_MAX)
+		ifi = &ifi_static[idx];
+	else {
+		if ((ifi = ifi_alloc()) == NULL) {
+			ulogd_log(ULOGD_ERROR, "ifi: out of memory\n");
+			return NULL;
+		}
+
+		llist_add_tail(&ifi->link, &ifi_list);
+	}
+
+	ifi->idx = idx;
+	ifi->used = 1;
+
+	pr_debug("%s: added interface '%s' (index %u)\n", __func__,
+			 ifi->name, ifi->idx);
+
+	return ifi;
+}
+
+
+static bool
+ifi_del(unsigned idx)
+{
+	struct ifi *ifi;
+
+	if (idx < IFI_STATIC_MAX) {
+		ifi = &ifi_static[idx];
+
+		if (ifi->used) {
+			ifi->used = 0;
+
+			pr_debug("%s: deleted interface '%s' (index %u)\n", __func__,
+					 ifi->name, ifi->idx);
+
+			return true;
+		}
+	} else {
+		struct ifi *tmp;
+
+		llist_for_each_entry_safe(ifi, tmp, &ifi_list, link) {
+			if (ifi->idx == idx) {
+				llist_del(&ifi->link);
+				free(ifi);
+
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+
+static void dump_bytes(const char *, unsigned char *, size_t) __unused;
+
+static void
+dump_bytes(const char *prefix, unsigned char *data, size_t len)
+{
+	int i;
+	static char buf[1024];
+	char *pch = buf;
+
+	if (prefix)
+		pch += sprintf(pch, "%s: ", prefix);
+
+	for (i = 0; i < len; i++)
+		pch += sprintf(pch, "0x%.2x ", data[i]);
+
+	fprintf(stdout, "%s\n", buf);
+}
+
+
+static void dump_nlmsg(FILE *, struct nlmsghdr *) __unused;
+
+static void
+dump_nlmsg(FILE *fp, struct nlmsghdr *nlh)
+{
+	fprintf(fp, "rtmsg: len=%04x type=%08x flags=%08x seq=%08x\n",
+			nlh->nlmsg_len,	nlh->nlmsg_type, nlh->nlmsg_flags,
+			nlh->nlmsg_seq);
+}
+
+
+static ssize_t sprint_lladdr(char *, size_t, const unsigned char *) __unused;
+
+static ssize_t
+sprint_lladdr(char *buf, size_t len, const unsigned char *addr)
+{
+	char *pch = buf;
+
+	pch += sprintf(pch, "%02x:%02x:%02x:%02x:%02x:%02x",
+				   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+	return pch - buf;
+}
+
+static int
+rtnl_parse_attrs(struct rtattr *attr, size_t attr_len,
+				 struct rtattr **rta, size_t rta_len)
+{
+	memset(rta, 0, rta_len * sizeof(struct rtattr *));
+
+	while (RTA_OK(attr, attr_len)) {
+		if (attr->rta_type < rta_len)
+			rta[attr->rta_type] = attr;
+
+		attr = RTA_NEXT(attr, attr_len);
+	}
+
+	return 0;
+}
+
+
+static int
+nl_send(int fd, struct nlmsghdr *nlh)
+{
+	struct sockaddr_nl sa;
+
+	memset(&sa, 0, sizeof(sa));
+
+	sa.nl_family = AF_NETLINK;
+
+	nlh->nlmsg_pid = getpid();
+	nlh->nlmsg_seq = ++nl_seq;
+
+	return sendto(fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&sa,
+				  sizeof(sa));
+}
+
+
+static int
+nl_dump_request(int fd, int type)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct rtgenmsg gen;
+	} req = {
+		.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
+		.gen.rtgen_family = AF_UNSPEC,
+	};
+
+	req.nlh.nlmsg_type = type;
+	req.nlh.nlmsg_len = sizeof(req);
+
+	return nl_send(fd, &req.nlh);
+}
+
+
+static int
+nl_listen(int fd, char *buf, size_t len)
+{
+	return read(fd, buf, len);
+}
+
+
+static int
+rtnl_handle_link(struct nlmsghdr *nlh)
+{
+	struct ifinfomsg *m = NLMSG_DATA(nlh);
+	struct rtattr *ifla[IFLA_MAX];
+	struct ifi *ifi;
+	size_t len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
+
+	rtnl_parse_attrs(IFLA_RTA(m), len, ifla, IFLA_MAX);
+
+	switch (nlh->nlmsg_type) {
+	case RTM_NEWLINK:
+		if (m->ifi_flags & IFF_UP) {
+			if ((ifi = ifi_find_or_add(m->ifi_index)) == NULL)
+				return -1;
+
+			ifi->flags = m->ifi_flags;
+
+			if (ifla[IFLA_ADDRESS])
+				memcpy(ifi->lladdr, RTA_DATA(ifla[IFLA_ADDRESS]), 6);
+
+			if (ifla[IFLA_IFNAME])
+				strcpy(ifi->name, RTA_DATA(ifla[IFLA_IFNAME]));
+		} else
+			ifi_del(m->ifi_index);
+		break;
+
+	case RTM_DELLINK:
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+
+static int
+rtnl_handle_msg(struct nlmsghdr *nlh, size_t len)
+{
+	if (nlh == NULL)
+		return -1;
+
+	while (NLMSG_OK(nlh, len)) {
+		if (nlh->nlmsg_type & NLMSG_DONE)
+			return 0;
+
+#if 0
+		dump_nlmsg(stdout, nlh);
+#endif /* 0 */
+
+		switch (nlh->nlmsg_type) {
+		case RTM_NEWLINK:
+		case RTM_DELLINK:
+			rtnl_handle_link(nlh);
+			break;
+
+		case NLMSG_ERROR:
+			break;
+
+		default:
+			break;
+		}
+
+		nlh = NLMSG_NEXT(nlh, len);
+	}
+
+
+	return 0;
+}
+
+
+static int
+rtnl_read_cb(int fd, unsigned what, void *data)
+{
+	static char buf[4096];
+
+	for (;;) {
+		int nbytes;
+
+		if ((nbytes = nl_listen(fd, buf, sizeof(buf))) < 0) {
+			if (errno == EWOULDBLOCK)
+				return 0;
+
+			ulogd_log(ULOGD_ERROR, "nl_listen: %s\n", strerror(errno));
+
+			return -1;
+		}
+
+		rtnl_handle_msg((struct nlmsghdr *)buf, nbytes);
+	}
+
+	return 0;
+}
+
+
+static struct ulogd_fd nl_fd = {
+	.fd = -1,
+	.cb = rtnl_read_cb,
+	.when = ULOGD_FD_READ,
+};
+
+
+int
+ifi_init(void)
+{
+	struct sockaddr_nl sa = {
+		.nl_family = AF_NETLINK,
+		.nl_groups = RTNLGRP_LINK,
+	};
+
+	pr_debug("Initializing ifi\n");
+
+	sa.nl_pid = getpid();
+
+	if ((nl_fd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
+		ulogd_log(ULOGD_ERROR, "ifi: socket: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if (bind(nl_fd.fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+		ulogd_log(ULOGD_ERROR, "ifi: bind: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if (connect(nl_fd.fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+		ulogd_log(ULOGD_ERROR, "ifi: connect: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if (ulogd_register_fd(&nl_fd) < 0)
+		return -1;
+
+	nl_dump_request(nl_fd.fd, RTM_GETLINK);
+
+	return 0;
+}
Index: ulogd-netfilter/src/Makefile.am
===================================================================
--- ulogd-netfilter.orig/src/Makefile.am
+++ ulogd-netfilter/src/Makefile.am
@@ -5,5 +5,5 @@ AM_CPPFLAGS = $(all_includes) -I$(top_sr
 
 sbin_PROGRAMS = ulogd
 
-ulogd_SOURCES = ulogd.c select.c timer.c conffile.c
+ulogd_SOURCES = ulogd.c ifi.c select.c timer.c conffile.c
 ulogd_LDFLAGS = -export-dynamic
Index: ulogd-netfilter/src/ulogd.c
===================================================================
--- ulogd-netfilter.orig/src/ulogd.c
+++ ulogd-netfilter/src/ulogd.c
@@ -63,6 +63,9 @@
 #include <syslog.h>
 #include <ulogd/conffile.h>
 #include <ulogd/ulogd.h>
+#include <ulogd/ifi.h>
+
+
 #ifdef DEBUG
 #define DEBUGP(format, args...) fprintf(stderr, format, ## args)
 #else
@@ -983,6 +986,9 @@ int main(int argc, char* argv[])
 	ulogd_log(ULOGD_INFO, 
 		  "initialization finished, entering main loop\n");
 
+	if (ifi_init() < 0)
+		exit(EXIT_FAILURE);
+
 	ulogd_main_loop();
 
 	/* hackish, but result is the same */

-- 

  parent reply	other threads:[~2008-02-02 20:51 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-02 20:48 [ULOGD 00/15] ulogd V2 improvements, round 2 heitzenberger
2008-02-02 20:48 ` [ULOGD 01/15] Add NACCT output plugin heitzenberger
2008-02-02 21:24   ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 02/15] common.h: added heitzenberger
2008-02-02 21:30   ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 03/15] Replace timer code by working version heitzenberger
2008-02-02 22:45   ` Pablo Neira Ayuso
2008-02-02 20:48 ` heitzenberger [this message]
2008-02-02 21:36   ` [ULOGD 04/15] Add IFI list Pablo Neira Ayuso
2008-02-02 21:50     ` Holger Eitzenberger
2008-02-02 22:56       ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 05/15] Add signalling subsystem heitzenberger
2008-02-19 19:38   ` Pablo Neira Ayuso
2008-02-20  8:43     ` Holger Eitzenberger
2008-02-20 12:20       ` Patrick McHardy
2008-02-20 12:23       ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 06/15] Conffile cleanup, use common pr_debug() heitzenberger
2008-02-02 21:43   ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 07/15] Renice to -1 on startup heitzenberger
2008-02-02 21:47   ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 08/15] Initial round to make plugins reconfigurable heitzenberger
2008-02-02 20:48 ` [ULOGD 09/15] llist: add llist_for_each_prev_safe() heitzenberger
2008-02-02 20:48 ` [ULOGD 10/15] Improve select performance heitzenberger
2008-02-19 19:58   ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 11/15] Add set_sockbuf_len() heitzenberger
2008-02-19 19:57   ` Pablo Neira Ayuso
2008-02-02 20:48 ` [ULOGD 12/15] Introduce global state, skip some stacks during reconfiguration heitzenberger
2008-02-02 20:48 ` [ULOGD 13/15] llist: turn poisoning off by default heitzenberger
2008-02-02 20:48 ` [ULOGD 14/15] SQLITE3: port to ulogd 2.00, mostly a rewrite heitzenberger
2008-02-02 20:48 ` [ULOGD 15/15] NFCT: rework and let it scale heitzenberger
2008-02-02 22:52 ` [ULOGD 00/15] ulogd V2 improvements, round 2 Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080202205107.726859754@astaro.com \
    --to=heitzenberger@astaro.com \
    --cc=holger@eitzenberger.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.