[netfilter-cvslog] r4132 - in trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6: include/linux/netfilter net/netfilter

laforge at netfilter.org laforge at netfilter.org
Tue Jul 19 23:16:50 CEST 2005


Author: laforge at netfilter.org
Date: 2005-07-19 23:16:45 +0200 (Tue, 19 Jul 2005)
New Revision: 4132

Modified:
   trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/include/linux/netfilter/nfnetlink.h
   trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/net/netfilter/nfnetlink.c
Log:
- use groups for different event types (Pablo Neira)
- more architecture-indepenent definition of struct nfattr
- add support for nested attributes (Pablo Neira)
- extend nfgenmsg to include version and resource id
- move nfnetlink_check_attributes() into caller (Pablo Neira)
- clean up locking (Pablo Neira)
- get rid of superfluous list_head (Pablo Neira)


Modified: trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/include/linux/netfilter/nfnetlink.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/include/linux/netfilter/nfnetlink.h	2005-07-19 20:24:14 UTC (rev 4131)
+++ trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/include/linux/netfilter/nfnetlink.h	2005-07-19 21:16:45 UTC (rev 4132)
@@ -2,6 +2,14 @@
 #define _NFNETLINK_H
 #include <linux/types.h>
 
+/* nfnetlink groups: Up to 32 maximum */
+#define NF_NETLINK_CONNTRACK_NEW 		0x00000001
+#define NF_NETLINK_CONNTRACK_UPDATE		0x00000002
+#define NF_NETLINK_CONNTRACK_DESTROY		0x00000004
+#define NF_NETLINK_CONNTRACK_EXP_NEW		0x00000008
+#define NF_NETLINK_CONNTRACK_EXP_UPDATE		0x00000010
+#define NF_NETLINK_CONNTRACK_EXP_DESTROY	0x00000020
+
 /* Generic structure for encapsulation optional netfilter information.
  * It is reminiscent of sockaddr, but with sa_family replaced
  * with attribute type. 
@@ -11,10 +19,13 @@
 
 struct nfattr
 {
-	unsigned short  nfa_len;
-	unsigned short  nfa_type;
-};
+	u_int16_t nfa_len;
+	u_int16_t nfa_type;
+} __attribute__ ((packed));
 
+/* FIXME: Shamelessly copy and pasted from rtnetlink.h, it's time
+ * 	  to put this in a generic file */
+
 #define NFA_ALIGNTO     4
 #define NFA_ALIGN(len)	(((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
 #define NFA_OK(nfa,len)	((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
@@ -25,22 +36,32 @@
 #define NFA_SPACE(len)	NFA_ALIGN(NFA_LENGTH(len))
 #define NFA_DATA(nfa)   ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
 #define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
+#define NFA_NEST(skb, type) \
+({	struct nfattr *__start = (struct nfattr *) (skb)->tail; \
+	NFA_PUT(skb, type, 0, NULL); \
+	__start;  })
+#define NFA_NEST_END(skb, start) \
+({      (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \
+        (skb)->len; })
+#define NFA_NEST_CANCEL(skb, start) \
+({      if (start) \
+                skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
+        -1; })
 
 /* General form of address family dependent message.
  */
 struct nfgenmsg {
-	unsigned char nfgen_family;
-};
+	u_int8_t  nfgen_family;		/* AF_xxx */
+	u_int8_t  version;		/* nfnetlink version */
+	u_int16_t res_id;		/* resource id */
+} __attribute__ ((packed));
 
+#define NFNETLINK_V1	1
+
 #define NFM_NFA(n)      ((struct nfattr *)(((char *)(n)) \
         + NLMSG_ALIGN(sizeof(struct nfgenmsg))))
 #define NFM_PAYLOAD(n)  NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
 
-
-#ifndef NETLINK_NETFILTER
-#define NETLINK_NETFILTER	10
-#endif
-
 /* netfilter netlink message types are split in two pieces:
  * 8 bit subsystem, 8bit operation.
  */
@@ -66,19 +87,16 @@
 {
 	kernel_cap_t cap_required; /* capabilities required for this msg */
 	int (*call)(struct sock *nl, struct sk_buff *skb, 
-		struct nlmsghdr *nlh, int *errp);
+		struct nlmsghdr *nlh, struct nfattr *cda[], int *errp);
 };
 
 struct nfnetlink_subsystem
 {
-	/* Internal use. */
-	struct list_head list;
-	
 	const char *name;
 	__u8 subsys_id;		/* nfnetlink subsystem ID */
 	__u8 cb_count;		/* number of callbacks */
 	u_int32_t attr_count;	/* number of nfattr's */
-	struct nfnl_callback cb[0]; /* callback for individual types */
+	struct nfnl_callback *cb; /* callback for individual types */
 };
 
 extern void __nfa_fill(struct sk_buff *skb, int attrtype,
@@ -88,36 +106,40 @@
    __nfa_fill(skb, attrtype, attrlen, data); })
 
 extern struct semaphore nfnl_sem;
-#define nfnl_exlock()		do { } while(0)
-#define nfnl_exunlock()		do { } while(0)
-#define nfnl_exlock_nowait()	(0)
 
 #define nfnl_shlock()		down(&nfnl_sem)
 #define nfnl_shlock_nowait()	down_trylock(&nfnl_sem)
 
-#ifndef CONFIG_NF_NETLINK
-#define nfnl_shunlock()		up(&nfnl_sem)
-#else
 #define nfnl_shunlock()		do { up(&nfnl_sem); \
-                             		if(nfnl && nfnl->receive_queue.qlen) \
-                                     		nfnl->data_ready(nfnl, 0); \
+				     if(nfnl && nfnl->sk_receive_queue.qlen) \
+					    nfnl->sk_data_ready(nfnl, 0); \
                         	} while(0)
-#endif
 
 extern void nfnl_lock(void);
 extern void nfnl_unlock(void);
 
-extern struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count);
 extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n);
 extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n);
 
-extern int nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
-				      struct nlmsghdr *nlh, 
-				      struct nfattr *cda[]);
 extern int nfattr_parse(struct nfattr *tb[], int maxattr, 
 			struct nfattr *nfa, int len);
+
+#define nfattr_parse_nested(tb, max, nfa) \
+	nfattr_parse((tb), (max), NFA_DATA((nfa)), NFA_PAYLOAD((nfa)))
+
+#define nfattr_bad_size(tb, max, cta_min)				\
+({	int __i, __res = 0;						\
+ 	for (__i=0; __i<max; __i++) 					\
+ 		if (tb[__i] && NFA_PAYLOAD(tb[__i]) < cta_min[__i]){	\
+ 			__res = 1;					\
+ 			break;						\
+ 		}							\
+ 	__res;								\
+})
+
 extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, 
 			  int echo);
+extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);
 
 #endif	/* __KERNEL__ */
 #endif	/* _NFNETLINK_H */

Modified: trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/net/netfilter/nfnetlink.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/net/netfilter/nfnetlink.c	2005-07-19 20:24:14 UTC (rev 4131)
+++ trunk/patch-o-matic-ng/patchlets/nfnetlink/linux-2.6/net/netfilter/nfnetlink.c	2005-07-19 21:16:45 UTC (rev 4132)
@@ -2,7 +2,8 @@
  * protocol helpers and general trouble making from userspace.
  *
  * (C) 2001 by Jay Schulist <jschlst at samba.org>,
- * (C) 2002 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2002-2005 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2005 by Pablo Neira Ayuso <pablo at eurodev.net>
  *
  * Initial netfilter messages via netlink development funded and
  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
@@ -31,7 +32,6 @@
 #include <net/sock.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/list.h>
 
 #include <linux/netfilter.h>
 #include <linux/netlink.h>
@@ -39,47 +39,28 @@
 
 MODULE_LICENSE("GPL");
 
-static char __initdata nfversion[] = "0.12";
+static char __initdata nfversion[] = "0.30";
 
-#if 1
+#if 0
 #define DEBUGP printk
 #else
 #define DEBUGP(format, args...)
 #endif
 
 static struct sock *nfnl = NULL;
-static LIST_HEAD(subsys_list);
 static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
 DECLARE_MUTEX(nfnl_sem);
 
 void nfnl_lock(void)
 {
 	nfnl_shlock();
-	nfnl_exlock();
 }
 
 void nfnl_unlock(void)
 {
-	nfnl_exunlock();
 	nfnl_shunlock();
 }
 
-struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count)
-{
-	int size;
-	struct nfnetlink_subsystem *ss;
-
-	size = sizeof(struct nfnetlink_subsystem)
-		+ (cb_count * sizeof(struct nfnl_callback));
-
-	ss = kmalloc(size, GFP_KERNEL);
-	if (!ss)
-		return NULL;
-	memset(ss, 0, size);
-
-	return ss;
-}
-
 int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
 {
 	DEBUGP("registering subsystem ID %u\n", n->subsys_id);
@@ -89,7 +70,6 @@
 		return -1;
 
 	nfnl_lock();
-	list_add(&n->list, &subsys_list);
 	subsys_table[n->subsys_id] = n;
 	nfnl_unlock();
 
@@ -102,30 +82,33 @@
 
 	nfnl_lock();
 	subsys_table[n->subsys_id] = NULL;
-	list_del(&n->list);
 	nfnl_unlock();
 
 	return 0;
 }
 
-struct nfnl_callback *nfnetlink_find_client(u_int16_t nlmsg_type)
+static inline struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type)
 {
-	struct nfnetlink_subsystem *ss;
-	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlmsg_type);
-	u_int8_t type = NFNL_MSG_TYPE(nlmsg_type);
+	u_int8_t subsys_id = NFNL_SUBSYS_ID(type);
 
 	if (subsys_id >= NFNL_SUBSYS_COUNT
 	    || subsys_table[subsys_id] == NULL)
 		return NULL;
 
-	ss = subsys_table[subsys_id];
+	return subsys_table[subsys_id];
+}
 
-	if (type >= ss->cb_count) {
+static inline struct nfnl_callback *
+nfnetlink_find_client(u_int16_t type, struct nfnetlink_subsystem *ss)
+{
+	u_int8_t cb_id = NFNL_MSG_TYPE(type);
+	
+	if (cb_id >= ss->cb_count) {
 		DEBUGP("msgtype %u >= %u, returning\n", type, ss->cb_count);
 		return NULL;
 	}
 
-	return &ss->cb[type];
+	return &ss->cb[cb_id];
 }
 
 void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
@@ -162,7 +145,7 @@
  * cda: array of pointers, needs to be at least subsys->attr_count big
  *
  */
-int
+static int
 nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
 			   struct nlmsghdr *nlh, struct nfattr *cda[])
 {
@@ -171,7 +154,7 @@
 	memset(cda, 0, sizeof(struct nfattr *) * subsys->attr_count);
 
 	/* check attribute lengths. */
-	min_len = sizeof(struct nfgenmsg);
+	min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg));
 	if (nlh->nlmsg_len < min_len)
 		return -EINVAL;
 
@@ -209,11 +192,17 @@
 	return err;
 }
 
+int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags)
+{
+	return netlink_unicast(nfnl, skb, pid, flags);
+}
+
 /* Process one complete nfnetlink message. */
 static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
 				    struct nlmsghdr *nlh, int *errp)
 {
 	struct nfnl_callback *nc;
+	struct nfnetlink_subsystem *ss;
 	int type, err = 0;
 
 	DEBUGP("entered; subsys=%u, msgtype=%u\n",
@@ -226,20 +215,19 @@
 		return 0;
 	}
 
-	/* Unknown message: reply with EINVAL */
-	type = nlh->nlmsg_type;
-	if (NFNL_SUBSYS_ID(type) > NFNL_SUBSYS_COUNT) {
-		DEBUGP("subsys_id > subsys_count\n");
-		goto err_inval;
-	}
-
-	/* All the messages must have at least 1 byte length */
-	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
+	/* All the messages must at least contain nfgenmsg */
+	if (nlh->nlmsg_len < 
+			NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg)))) {
 		DEBUGP("received message was too short\n");
 		return 0;
 	}
 
-	nc = nfnetlink_find_client(type);
+	type = nlh->nlmsg_type;
+	ss = nfnetlink_get_subsys(type);
+	if (!ss)
+		goto err_inval;
+
+	nc = nfnetlink_find_client(type, ss);
 	if (!nc) {
 		DEBUGP("unable to find client for type %d\n", type);
 		goto err_inval;
@@ -252,10 +240,20 @@
 		return -1;
 	}
 
-	err = nc->call(nfnl, skb, nlh, errp);
-	*errp = err;
-	return err;
+	{
+		struct nfattr *cda[ss->attr_count];
 
+		memset(cda, 0, ss->attr_count*sizeof(struct nfattr *));
+		
+		err = nfnetlink_check_attributes(ss, nlh, cda);
+		if (err < 0)
+			goto err_inval;
+
+		err = nc->call(nfnl, skb, nlh, cda, errp);
+		*errp = err;
+		return err;
+	}
+
 err_inval:
 	*errp = -EINVAL;
 	return -1;
@@ -316,19 +314,15 @@
 
 void __exit nfnetlink_exit(void)
 {
-	printk("Netfilter removing netlink socket.\n");
+	printk("Removing netfilter NETLINK layer.\n");
 	sock_release(nfnl->sk_socket);
 	return;
 }
 
 int __init nfnetlink_init(void)
 {
-	int i;
 	printk("Netfilter messages via NETLINK v%s.\n", nfversion);
 
-	for (i = 0; i < NFNL_SUBSYS_COUNT; i++)
-		subsys_table[i] = NULL;
-
 	nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv);
 	if (!nfnl) {
 		printk(KERN_ERR "cannot initialize nfnetlink!\n");
@@ -341,9 +335,9 @@
 module_init(nfnetlink_init);
 module_exit(nfnetlink_exit);
 
-EXPORT_SYMBOL_GPL(nfnetlink_subsys_alloc);
 EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
 EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
-EXPORT_SYMBOL_GPL(nfnetlink_check_attributes);
 EXPORT_SYMBOL_GPL(nfnetlink_send);
+EXPORT_SYMBOL_GPL(nfnetlink_unicast);
+EXPORT_SYMBOL_GPL(nfattr_parse);
 EXPORT_SYMBOL_GPL(__nfa_fill);




More information about the netfilter-cvslog mailing list