[netfilter-cvslog] r4215 - in trunk/libnfnetlink: include/libnfnetlink src

laforge at netfilter.org laforge at netfilter.org
Sat Aug 6 11:00:41 CEST 2005


Author: laforge at netfilter.org
Date: 2005-08-06 11:00:20 +0200 (Sat, 06 Aug 2005)
New Revision: 4215

Modified:
   trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h
   trunk/libnfnetlink/src/libnfnetlink.c
Log:
add support for callback-based parsing of messages, similar to kernel API


Modified: trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h
===================================================================
--- trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h	2005-08-05 18:36:49 UTC (rev 4214)
+++ trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h	2005-08-06 09:00:20 UTC (rev 4215)
@@ -16,6 +16,12 @@
 
 #define NFNL_BUFFSIZE		8192
 
+struct nfnl_callback {
+	int (*call)(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data);
+	void *data;
+	u_int16_t attr_count;
+};
+
 struct nfnl_handle {
 	int			fd;
 	struct sockaddr_nl	local;
@@ -24,35 +30,52 @@
 	u_int32_t		seq;
 	u_int32_t		dump;
 	struct nlmsghdr 	*last_nlhdr;
+
+	u_int8_t		cb_count;
+	struct nfnl_callback 	*cb;	/* array of callbacks */
 };
 
 /* get a new library handle */
-extern int nfnl_open(struct nfnl_handle *, u_int8_t, unsigned int);
+extern int nfnl_open(struct nfnl_handle *, u_int8_t, u_int8_t, unsigned int);
 extern int nfnl_close(struct nfnl_handle *);
+
+/* sending of data */
 extern int nfnl_send(struct nfnl_handle *, struct nlmsghdr *);
 extern int nfnl_sendmsg(const struct nfnl_handle *, const struct msghdr *msg,
 			unsigned int flags);
 extern int nfnl_sendiov(const struct nfnl_handle *nfnlh,
 			const struct iovec *iov, unsigned int num,
 			unsigned int flags);
-
 extern void nfnl_fill_hdr(struct nfnl_handle *, struct nlmsghdr *,
 			  unsigned int, u_int8_t, u_int16_t, u_int16_t,
 			  u_int16_t);
+extern int nfnl_talk(struct nfnl_handle *, struct nlmsghdr *, pid_t,
+                     unsigned, struct nlmsghdr *,
+                     int (*)(struct sockaddr_nl *, struct nlmsghdr *, void *),
+                     void *);
 
-extern struct nfattr *nfnl_parse_hdr(const struct nfnl_handle *nfnlh, 
-				     const struct nlmsghdr *nlh,
-				     struct nfgenmsg **genmsg);
-
+/* simple challenge/response */
 extern int nfnl_listen(struct nfnl_handle *,
                       int (*)(struct sockaddr_nl *, struct nlmsghdr *, void *),
                       void *);
 
-extern int nfnl_talk(struct nfnl_handle *, struct nlmsghdr *, pid_t,
-                     unsigned, struct nlmsghdr *,
-                     int (*)(struct sockaddr_nl *, struct nlmsghdr *, void *),
-                     void *);
+/* receiving */
+extern int nfnl_callback_register(struct nfnl_handle *,
+				  u_int8_t type, struct nfnl_callback *cb);
+extern int nfnl_callback_unregister(struct nfnl_handle *, u_int8_t type);
+extern int nfnl_handle_packet(struct nfnl_handle *, char *buf, int len);
 
+/* parsing */
+extern struct nfattr *nfnl_parse_hdr(const struct nfnl_handle *nfnlh, 
+				     const struct nlmsghdr *nlh,
+				     struct nfgenmsg **genmsg);
+extern struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h,
+					   const unsigned char *buf,
+					   size_t len);
+extern struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h,
+					  const unsigned char *buf,
+					  size_t len);
+
 /* nfnl attribute handling functions */
 extern int nfnl_addattr_l(struct nlmsghdr *, int, int, void *, int);
 extern int nfnl_addattr32(struct nlmsghdr *, int, int, u_int32_t);
@@ -74,12 +97,5 @@
 extern unsigned int nfnl_rcvbufsiz(struct nfnl_handle *h, unsigned int size);
 
 
-extern struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h,
-					   const unsigned char *buf,
-					   size_t len);
-extern struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h,
-					  const unsigned char *buf,
-					  size_t len);
-
 extern void nfnl_dump_packet(struct nlmsghdr *, int, char *);
 #endif /* __LIBNFNETLINK_H */

Modified: trunk/libnfnetlink/src/libnfnetlink.c
===================================================================
--- trunk/libnfnetlink/src/libnfnetlink.c	2005-08-05 18:36:49 UTC (rev 4214)
+++ trunk/libnfnetlink/src/libnfnetlink.c	2005-08-06 09:00:20 UTC (rev 4215)
@@ -62,11 +62,16 @@
  * subscriptions: netlink groups we want to be subscribed to
  *
  */
-int nfnl_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
-	      u_int32_t subscriptions)
+int nfnl_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id, 
+	      u_int8_t cb_count, u_int32_t subscriptions)
 {
 	int err;
 	unsigned int addr_len;
+	struct nfnl_callback *cb;
+
+	cb = malloc(sizeof(*cb) * cb_count);
+	if (!cb)
+		return -ENOMEM;
 	
 	memset(nfnlh, 0, sizeof(*nfnlh));
 	nfnlh->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
@@ -101,6 +106,7 @@
 	}
 	nfnlh->seq = time(NULL);
 	nfnlh->subsys_id = subsys_id;
+	nfnlh->cb_count = cb_count;
 
 	return 0;
 }
@@ -113,6 +119,7 @@
  */
 int nfnl_close(struct nfnl_handle *nfnlh)
 {
+	free(nfnlh->cb);
 	return close(nfnlh->fd);
 }
 
@@ -625,3 +632,112 @@
 
 	return nlh;
 }
+
+int nfnl_callback_register(struct nfnl_handle *h,
+			   u_int8_t type, struct nfnl_callback *cb)
+{
+	if (type >= h->cb_count)
+		return -EINVAL;
+
+	memcpy(&h->cb[type], cb, sizeof(*cb));
+
+	return 0;
+}
+
+int nfnl_callback_unregister(struct nfnl_handle *h, u_int8_t type)
+{
+	if (type >= h->cb_count)
+		return -EINVAL;
+
+	h->cb[type].call = NULL;
+
+	return 0;
+}
+
+static int nfnl_check_attributes(struct nfnl_handle *h, struct nlmsghdr *nlh,
+				 struct nfattr *nfa[])
+{
+	int min_len;
+	u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
+	struct nfnl_callback *cb = &h->cb[type];
+
+#if 1
+	/* checks need to be enabled as soon as this is called from
+	 * somebody else than __nfnl_handle_msg */
+	if (type >= h->cb_count)
+		return -EINVAL;
+
+	min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg));
+	if (nlh->nlmsg_len < min_len)
+		return -EINVAL;
+#endif
+	memset(nfa, 0, sizeof(struct nfattr *) * cb->attr_count);
+
+	if (nlh->nlmsg_len > min_len) {
+		struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
+		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
+
+		while (NFA_OK(attr, attrlen)) {
+			unsigned int flavor = attr->nfa_type;
+			if (flavor) {
+				if (flavor > cb->attr_count)
+					return -EINVAL;
+				nfa[flavor - 1] = attr;
+			}
+			attr = NFA_NEXT(attr, attrlen);
+		}
+	}
+
+	return 0;
+}
+
+static int __nfnl_handle_msg(struct nfnl_handle *h, struct nlmsghdr *nlh,
+			     int len)
+{
+	u_int8_t type;
+	int err = 0;
+	struct nfattr *nfa[h->cb_count];
+
+	if (NFNL_SUBSYS_ID(nlh->nlmsg_type) != h->subsys_id)
+		return -1;
+
+	if (nlh->nlmsg_len < NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
+		return -1;
+
+	type = NFNL_MSG_TYPE(nlh->nlmsg_type);
+
+	if (type >= h->cb_count)
+		return -1;
+
+	if (h->cb[type].attr_count) {
+		err = nfnl_check_attributes(h, nlh, nfa);
+		if (err < 0)
+			return err;
+		if (h->cb[type].call)
+			return h->cb[type].call(nlh, nfa, h->cb[type].data);
+	}
+	return 0;
+}
+
+int nfnl_handle_packet(struct nfnl_handle *h, char *buf, int len)
+{
+
+	while (len >= NLMSG_SPACE(0)) {
+		u_int32_t rlen;
+		struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
+
+		if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
+		    || len < nlh->nlmsg_len)
+			return -1;
+
+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (rlen > len)
+			rlen = len;
+
+		if (__nfnl_handle_msg(h, nlh, rlen) < 0)
+			return -1;
+
+		len -= rlen;
+	}
+	return 0;
+}




More information about the netfilter-cvslog mailing list