All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] message parsing functions for nfqueue
@ 2005-08-11 21:01 Eric Leblond
  2005-08-11 22:48 ` Harald Welte
  2005-08-12  1:30 ` Pablo Neira
  0 siblings, 2 replies; 7+ messages in thread
From: Eric Leblond @ 2005-08-11 21:01 UTC (permalink / raw)
  To: laforge; +Cc: netfilter-devel, Vincent Deffontaines


[-- Attachment #1.1: Type: text/plain, Size: 700 bytes --]

Hi,

This is a patch against libnfnetlink_queue.

It adds "high" level functions to access to the data contained in a
nfqueue message. These are mostly encapsulation of NFA macros.

The exemple provided in the utils directory now uses these functions.
I've also modified NuFW to use the new API to test its usability. The
obtained code is clean and the port was easy, thus I consider it
improves the situation. Although, it may miss some higher level
functions to access to multiple fields at the same time. I've thought
about some but they may be too NuFW oriented. 

Feedbacks welcome.

BR,
-- 
Eric Leblond <eric@regit.org>
NuFW, Now User Filtering Works : http://www.nufw.org

[-- Attachment #1.2: libnfnetlink_nfqueue.diff --]
[-- Type: text/x-patch, Size: 9779 bytes --]

Index: utils/nfqnl_test.c
===================================================================
--- utils/nfqnl_test.c	(revision 4237)
+++ utils/nfqnl_test.c	(working copy)
@@ -11,35 +11,37 @@
 static u_int32_t print_pkt (struct nfattr *tb[])
 {
 	int id = 0;
-
-	if (tb[NFQA_PACKET_HDR-1]) {
-		struct nfqnl_msg_packet_hdr *ph = 
-					NFA_DATA(tb[NFQA_PACKET_HDR-1]);
+	struct nfqnl_msg_packet_hdr *ph;
+	u_int32_t mark,ifi; 
+	int ret;
+	unsigned int datalength;
+	char * data;
+	
+	ph = nfqnl_get_msg_packet_hdr(tb);
+	if (ph){
 		id = ntohl(ph->packet_id);
 		printf("hw_protocol=0x%04x hook=%u id=%u ",
 			ntohs(ph->hw_protocol), ph->hook, id);
 	}
-
-	if (tb[NFQA_MARK-1]) {
-		u_int32_t mark = 
-			ntohl(*(u_int32_t *)NFA_DATA(tb[NFQA_MARK-1]));
+	
+	mark=nfqnl_get_nfmark(tb);
+	if (mark) {
 		printf("mark=%u ", mark);
 	}
 
-	if (tb[NFQA_IFINDEX_INDEV-1]) {
-		u_int32_t ifi = 
-			ntohl(*(u_int32_t *)NFA_DATA(tb[NFQA_IFINDEX_INDEV-1]));
-		printf("indev=%u ", ifi);
+	ret=nfqnl_get_indev(tb,&ifi,NULL);
+	if (ret) {
+		printf("indev=%u ", ntohl(ifi));
 	}
 
-	if (tb[NFQA_IFINDEX_OUTDEV-1]) {
-		u_int32_t ifi =
-			ntohl(*(u_int32_t *)NFA_DATA(tb[NFQA_IFINDEX_OUTDEV-1]));
-		printf("outdev=%u ", ifi);
+	ret=nfqnl_get_outdev(tb,&ifi,NULL);
+	if (ret) {
+		printf("outdev=%u ", ntohl(ifi));
 	}
 
-	if (tb[NFQA_PAYLOAD-1]) {
-		printf("payload_len=%d ", NFA_PAYLOAD(tb[NFQA_PAYLOAD-1]));
+	ret=nfqnl_get_payload(tb,&data,&datalength);
+	if (ret) {
+		printf("payload_len=%d ", datalength);
 	}
 
 	fputc('\n', stdout);
Index: include/libnfnetlink_queue/libnfnetlink_queue.h
===================================================================
--- include/libnfnetlink_queue/libnfnetlink_queue.h	(revision 4237)
+++ include/libnfnetlink_queue/libnfnetlink_queue.h	(working copy)
@@ -2,6 +2,10 @@
  *
  * (C) 2005 by Harald Welte <laforge@gnumonks.org>
  *
+ *
+ * Changelog : 
+ * 	(2005/08/11)  added  parsing function (Eric Leblond <regit@inl.fr>)
+ * 
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
  */
@@ -21,7 +25,7 @@
 extern struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h);
 extern int nfqnl_fd(struct nfqnl_handle *h);
 
-typedef nfqnl_callback(struct nfqnl_q_handle *gh, struct nfgenmsg *nfmsg,
+typedef int  nfqnl_callback(struct nfqnl_q_handle *gh, struct nfgenmsg *nfmsg,
 		       struct nfattr *nfa[], void *data);
 
 
@@ -47,10 +51,33 @@
 			     u_int32_t verdict,
 			     u_int32_t data_len,
 			     unsigned char *buf);
+
 extern int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, 
 				  u_int32_t id,
 			   	  u_int32_t verdict, 
 				  u_int32_t mark,
 			   	  u_int32_t datalen,
 				  unsigned char *buf);
+
+/* message parsing function */
+
+extern struct nfqnl_msg_packet_hdr * nfqnl_get_msg_packet_hdr(struct nfattr *nfa[]);
+
+extern u_int32_t nfqnl_get_nfmark(struct nfattr *nfa[]);
+
+extern struct nfqnl_msg_packet_timestamp * nfqnl_get_timestamp(struct nfattr *nfa[]);
+
+/* return 0 if not set */
+extern int nfqnl_get_indev(struct nfattr *nfa[],u_int32_t* indev, u_int32_t* physindev);
+
+/* return 0 if not set */
+extern int nfqnl_get_outdev(struct nfattr *nfa[],u_int32_t* outdev, u_int32_t* physoutdev);
+
+extern struct nfqnl_msg_packet_hw * nfqnl_get_packet_hw(struct nfattr *nfa[]);
+
+/* return 0 if problem */
+extern int nfqnl_get_payload(struct nfattr *nfa[],char ** data,unsigned int* datalen);
+
+
+
 #endif	/* __LIBNFQNETLINK_H */
Index: src/libnfnetlink_queue.c
===================================================================
--- src/libnfnetlink_queue.c	(revision 4237)
+++ src/libnfnetlink_queue.c	(working copy)
@@ -89,9 +89,9 @@
 }
 
 /* build a NFQNL_MSG_CONFIG message */
-static int
+	static int
 __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command,
-		     u_int16_t queuenum, u_int16_t pf)
+		u_int16_t queuenum, u_int16_t pf)
 {
 	char buf[NFNL_HEADER_LEN
 		+NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
@@ -99,7 +99,7 @@
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
 	nfnl_fill_hdr(&h->nfnlh, nmh, 0, AF_UNSPEC, queuenum,
-		      NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+			NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	cmd.command = command;
 	cmd.pf = htons(pf);
@@ -109,7 +109,7 @@
 }
 
 static int __nfqnl_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
-			   void *data)
+		void *data)
 {
 	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
 	struct nfqnl_handle *h = data;
@@ -196,9 +196,9 @@
 
 /* bind this socket to a specific queue number */
 struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h, 
-					  u_int16_t num,
-					  nfqnl_callback *cb,
-					  void *data)
+		u_int16_t num,
+		nfqnl_callback *cb,
+		void *data)
 {
 	int ret;
 	struct nfqnl_q_handle *qh;
@@ -243,7 +243,7 @@
 }
 
 int nfqnl_set_mode(struct nfqnl_q_handle *qh,
-		   u_int8_t mode, u_int32_t range)
+		u_int8_t mode, u_int32_t range)
 {
 	char buf[NFNL_HEADER_LEN
 		+NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
@@ -251,19 +251,19 @@
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
 	nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
-		      NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+			NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	params.copy_range = htonl(range);
 	params.copy_mode = mode;
 	nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, &params,
-		       sizeof(params));
+			sizeof(params));
 
 	return nfnl_talk(&qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
-			 u_int32_t verdict, u_int32_t mark, int set_mark,
-			 u_int32_t data_len, unsigned char *data)
+		u_int32_t verdict, u_int32_t mark, int set_mark,
+		u_int32_t data_len, unsigned char *data)
 {
 	struct nfqnl_msg_verdict_hdr vh;
 	char buf[NFNL_HEADER_LEN
@@ -278,8 +278,8 @@
 	vh.id = htonl(id);
 
 	nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
-		      NFQNL_MSG_VERDICT, NLM_F_REQUEST);
-			
+			NFQNL_MSG_VERDICT, NLM_F_REQUEST);
+
 	/* add verdict header */
 	nfnl_addattr_l(nmh, sizeof(buf), NFQA_VERDICT_HDR, &vh, sizeof(vh));
 
@@ -294,7 +294,7 @@
 		struct nfattr data_attr;
 
 		nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
-				     data_len, data);
+				data_len, data);
 		nvecs += 2;
 	}
 
@@ -302,15 +302,98 @@
 }
 
 int nfqnl_set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
-		      u_int32_t verdict, u_int32_t data_len, 
-		      unsigned char *buf)
+		u_int32_t verdict, u_int32_t data_len, 
+		unsigned char *buf)
 {
 	return __set_verdict(qh, id, verdict, 0, 0, data_len, buf);
 }	
 
 int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, u_int32_t id,
-			   u_int32_t verdict, u_int32_t mark,
-			   u_int32_t datalen, unsigned char *buf)
+		u_int32_t verdict, u_int32_t mark,
+		u_int32_t datalen, unsigned char *buf)
 {
 	return __set_verdict(qh, id, verdict, mark, 1, datalen, buf);
 }
+
+/*************************************************************
+ * Message parsing functions 
+ *************************************************************/
+
+
+struct nfqnl_msg_packet_hdr * nfqnl_get_msg_packet_hdr(struct nfattr *nfa[]){
+	if (nfa){
+		if (nfa[NFQA_PACKET_HDR-1]) {
+			return (struct nfqnl_msg_packet_hdr *)NFA_DATA(nfa[NFQA_PACKET_HDR-1]);
+		}
+	}
+	return NULL;
+}
+
+uint32_t nfqnl_get_nfmark(struct nfattr *nfa[]){
+	if (nfa){
+		if (nfa[NFQA_MARK-1]) {
+			return ntohl(*(u_int32_t *)NFA_DATA(nfa[NFQA_MARK-1]));
+		}
+	}
+	return 0;
+}
+
+struct nfqnl_msg_packet_timestamp * nfqnl_get_timestamp(struct nfattr *nfa[]){
+	if (nfa){
+		if (nfa[NFQA_TIMESTAMP-1]) {
+			return (struct nfqnl_msg_packet_timestamp *)NFA_DATA(nfa[NFQA_TIMESTAMP-1]);
+		}
+	}
+	return NULL;
+}
+
+/* return 0 if not set */
+int nfqnl_get_indev(struct nfattr *nfa[],u_int32_t* indev, u_int32_t* physindev){
+	if (nfa){
+		if (indev && nfa[NFQA_IFINDEX_INDEV-1]) {
+			*indev =	ntohl(*(u_int32_t *)NFA_DATA(nfa[NFQA_IFINDEX_INDEV-1]));
+			if (physindev && nfa[NFQA_IFINDEX_PHYSINDEV-1] ) {
+				*physindev = ntohl(*(u_int32_t *)NFA_DATA(nfa[NFQA_IFINDEX_PHYSINDEV-1]));
+			}
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/* return 0 if not set */
+int nfqnl_get_outdev(struct nfattr *nfa[],u_int32_t* outdev, u_int32_t* physoutdev){
+	if (nfa){
+		if (outdev && nfa[NFQA_IFINDEX_OUTDEV-1]) {
+			*outdev =	ntohl(*(u_int32_t *)NFA_DATA(nfa[NFQA_IFINDEX_OUTDEV-1]));
+			if (physoutdev && nfa[NFQA_IFINDEX_PHYSOUTDEV-1]) {
+				*physoutdev = ntohl(*(u_int32_t *)NFA_DATA(nfa[NFQA_IFINDEX_PHYSOUTDEV-1]));
+			}
+			return 1;
+		}
+	}
+	return 0;
+}
+
+struct nfqnl_msg_packet_hw * nfqnl_get_packet_hw(struct nfattr *nfa[]){
+	if (nfa){
+		if (nfa[NFQA_HWADDR-1]) {
+			return (struct nfqnl_msg_packet_hw*)NFA_DATA(nfa[NFQA_HWADDR-1]);
+		}
+	}
+	return NULL;
+}
+
+int nfqnl_get_payload(struct nfattr *nfa[],char ** data,unsigned int* datalen){
+	if (nfa && datalen) {
+		if (nfa[NFQA_PAYLOAD-1]) {
+			*data=NFA_DATA(nfa[NFQA_PAYLOAD-1]);
+			*datalen=NFA_PAYLOAD(nfa[NFQA_PAYLOAD-1]);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 4237)
+++ src/Makefile.am	(working copy)
@@ -2,7 +2,7 @@
 
 #EXTRA_DIST = $(man_MANS) acinclude.m4
 
-INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} 
+INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR}
 AM_CFLAGS=-fPIC -Wall
 LIBS=
 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] message parsing functions for nfqueue
  2005-08-11 21:01 [PATCH] message parsing functions for nfqueue Eric Leblond
@ 2005-08-11 22:48 ` Harald Welte
  2005-08-12 12:41   ` Harald Welte
  2005-08-12  1:30 ` Pablo Neira
  1 sibling, 1 reply; 7+ messages in thread
From: Harald Welte @ 2005-08-11 22:48 UTC (permalink / raw)
  To: Eric Leblond; +Cc: Netfilter Development Mailinglist, Vincent Deffontaines

[-- Attachment #1: Type: text/plain, Size: 1440 bytes --]

On Thu, Aug 11, 2005 at 11:01:46PM +0200, Eric Leblond wrote:
> Hi,
> 
> This is a patch against libnfnetlink_queue.

At the first sight, the patch looks fine to me.  I'll look at it in
detail over the weekend.

Oh. One thing that comes to my mind is "get_{in,out}dev" don't return a
device [name], but ifindex.  that should be reflected in the names.

Also, I think we should implement some common ifindex<->devicename
mapping/resolval code.  This could be part of libnfnetlink (but be put
into a separate source code file).

IMHO, all required information can be accessed via nfnetlink.  I've once
written some code for caching the ifindex<->devicename in userspace (it
receives rtnetlink events of ifup/ifdown messages and keeps the cache in
sync).  I'll try to locate that code.

If you (or anyone else) is interested in cleanly integrating it into
libnfnetlink, please contact me and I'll give you that code.

It has to be common, since other nfnetlink users also need the same
information.  masq_index in the conntrack structure, e.g. 

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] message parsing functions for nfqueue
  2005-08-11 21:01 [PATCH] message parsing functions for nfqueue Eric Leblond
  2005-08-11 22:48 ` Harald Welte
@ 2005-08-12  1:30 ` Pablo Neira
  2005-08-12  8:42   ` Eric Leblond
  1 sibling, 1 reply; 7+ messages in thread
From: Pablo Neira @ 2005-08-12  1:30 UTC (permalink / raw)
  To: Eric Leblond; +Cc: laforge, netfilter-devel, Vincent Deffontaines

Eric Leblond wrote:
> This is a patch against libnfnetlink_queue.
> 
> It adds "high" level functions to access to the data contained in a
> nfqueue message. These are mostly encapsulation of NFA macros.
> 
> -
> -	if (tb[NFQA_PACKET_HDR-1]) {
> -		struct nfqnl_msg_packet_hdr *ph = 
> -					NFA_DATA(tb[NFQA_PACKET_HDR-1]);
> +	struct nfqnl_msg_packet_hdr *ph;
> +	u_int32_t mark,ifi; 
> +	int ret;
> +	unsigned int datalength;
> +	char * data;
> +	
> +	ph = nfqnl_get_msg_packet_hdr(tb);
> +	if (ph){
>  		id = ntohl(ph->packet_id);
>  		printf("hw_protocol=0x%04x hook=%u id=%u ",
>  			ntohs(ph->hw_protocol), ph->hook, id);
>  	}

Instead of adding a function to access every attribute like above, why 
don't we add something more generic in libnfnetlink? Like the following 
macros:

#define nfnl_get_data(tb, attr, type)			\
({	type __ret = 0;					\
  	if (tb[attr-1])					\
  		__ret = *(type *)NFA_DATA(tb[attr-1]);	\
	__ret;						\
})

#define nfnl_get_pointer_to_data(tb, attr, type)	\
({	type *__ret = NULL;				\
  	if (tb[attr-1])					\
  		__ret = NFA_DATA(tb[attr-1]);		\
  	__ret;						\
})

Maybe too generic ?

OTOH, if we add such high level functions we'll have to do the same in 
other libnfnetlink_* libraries to keep homogeneity of the API.

--
Pablo

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] message parsing functions for nfqueue
  2005-08-12  1:30 ` Pablo Neira
@ 2005-08-12  8:42   ` Eric Leblond
  2005-08-12 12:04     ` Harald Welte
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Leblond @ 2005-08-12  8:42 UTC (permalink / raw)
  To: Pablo Neira; +Cc: laforge, netfilter-devel, Vincent Deffontaines, Eric Leblond

> Eric Leblond wrote:
>> This is a patch against libnfnetlink_queue.
>>
>> It adds "high" level functions to access to the data contained in a
>> nfqueue message. These are mostly encapsulation of NFA macros.

> Instead of adding a function to access every attribute like above, why
> don't we add something more generic in libnfnetlink? Like the following
> macros:
>
> Maybe too generic ?

In a way, yes, you will only access to things one at a time, and when you
want the payload you also want to know its size.
But I think such functions are needed to be able to have an evolving API.
I will try to work on it.

> OTOH, if we add such high level functions we'll have to do the same in
> other libnfnetlink_* libraries to keep homogeneity of the API.

yes ...

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] message parsing functions for nfqueue
  2005-08-12  8:42   ` Eric Leblond
@ 2005-08-12 12:04     ` Harald Welte
  2005-09-14 19:57       ` Eric Leblond
  0 siblings, 1 reply; 7+ messages in thread
From: Harald Welte @ 2005-08-12 12:04 UTC (permalink / raw)
  To: Eric Leblond; +Cc: netfilter-devel, Vincent Deffontaines, Pablo Neira

[-- Attachment #1: Type: text/plain, Size: 2834 bytes --]

On Fri, Aug 12, 2005 at 10:42:56AM +0200, Eric Leblond wrote:
> > Eric Leblond wrote:
> >> This is a patch against libnfnetlink_queue.
> >>
> >> It adds "high" level functions to access to the data contained in a
> >> nfqueue message. These are mostly encapsulation of NFA macros.
> 
> > Instead of adding a function to access every attribute like above, why
> > don't we add something more generic in libnfnetlink? Like the following
> > macros:
> >
> > Maybe too generic ?
> 
> In a way, yes, you will only access to things one at a time, and when you
> want the payload you also want to know its size.
> But I think such functions are needed to be able to have an evolving API.
> I will try to work on it.

I like the generic macros proposed by Pablo, but making nfnetlink_queue
users directly use them is somewhat of a layering violation.

The application shouldn't have to understand anything about netlink,
nfattrs, the nfnetlink wire format or anything else.  It's the job of
the API to hide all those details.  Ideally we don't even export any of
that information to the application, by putting it in private header
files.

Only this way we can make sure that if we'd ever have to change the
underlying mechanism [again], the applications wouldn't be affected -
they'd just link against a different libnfnetlink_queue.  This is not
too unlikely.  There were discussions about netlink2 as well as having
mmap() capability of netlink sockets.  Obviously nfnetlink_queue would
want to take advantage of that...

> > OTOH, if we add such high level functions we'll have to do the same in
> > other libnfnetlink_* libraries to keep homogeneity of the API.
> 
> yes ...

I'm not actually too worried about homogenous API between all the
different libnfnetlink_* variants.  It's just _queue and _log which are
similar enough in functionality so that the API's would look very
similar.  But think about management of conntrack tables or even
pkt_tables at some point... they serve a totally different purpose, and
the API will look different.

One thing that somebody could look into (if there are any volunteers) is
thread-safety of libnfnetlink{,_queue,_log}.  There will be users who
want to use multithreaded programs, once this takes off.

I've personally never believed in multithreading anyway (I'm more a
select/poll kind of guy), so I'm certainly not the best person to get
those libs threadsafe...

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] message parsing functions for nfqueue
  2005-08-11 22:48 ` Harald Welte
@ 2005-08-12 12:41   ` Harald Welte
  0 siblings, 0 replies; 7+ messages in thread
From: Harald Welte @ 2005-08-12 12:41 UTC (permalink / raw)
  To: Eric Leblond, Vincent Deffontaines,
	Netfilter Development Mailinglist, Thomas Graf

[-- Attachment #1: Type: text/plain, Size: 2565 bytes --]

[added Thomas Graf to Cc list, please see bottom of this mail]

On Fri, Aug 12, 2005 at 12:48:13AM +0200, Harald Welte wrote:
> On Thu, Aug 11, 2005 at 11:01:46PM +0200, Eric Leblond wrote:
> > Hi,
> > 
> > This is a patch against libnfnetlink_queue.
> 
> At the first sight, the patch looks fine to me.  I'll look at it in
> detail over the weekend.
> 
> Oh. One thing that comes to my mind is "get_{in,out}dev" don't return a
> device [name], but ifindex.  that should be reflected in the names.
> 
> Also, I think we should implement some common ifindex<->devicename
> mapping/resolval code.  This could be part of libnfnetlink (but be put
> into a separate source code file).
> 
> IMHO, all required information can be accessed via netlink.  I've once
> written some code for caching the ifindex<->devicename in userspace (it
> receives rtnetlink events of ifup/ifdown messages and keeps the cache in
> sync).  I'll try to locate that code.

Ok, located it (and got permission to put it under GPL).  It's now in
https://svn.netfilter.org/netfilter/trunk/libnfnetlink/src/{rtnl,iftable}.{c,h}

I'm not going to have the time to work on this before I'll get back from
my holidays on Aug 26.  So whoever wants to dig into this, feel free to
go ahead.

One problem, though, is how we will integrate that functionality with
the rest of the application.  In order to receive the ifup/ifdown/...
events by rtnetlink, the main application needs to select() on yet
another filedescriptor - and call some rtnl message handling function.

One idea was ot skip the event messages and only poll the kernel every
time the application requests it. Somthing like

iftable_cache_fill(void)
	- read out a list of ifindex<->devicename mappings
iftable_cache_lookup(int ifindex)
	- lookup devname for given ifindex
iftable_lookup(int ifindex)
	- lookup directly, bypassing the cache.

This time the app would have to call iftable_cache_fill() every so
often.  It's not very elegant.  

In the end, this really belongs into yet-another netlink-related
library.  Something like librtnetlink.  Maybe Thomas can help us if
there is something that we could use.

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] message parsing functions for nfqueue
  2005-08-12 12:04     ` Harald Welte
@ 2005-09-14 19:57       ` Eric Leblond
  0 siblings, 0 replies; 7+ messages in thread
From: Eric Leblond @ 2005-09-14 19:57 UTC (permalink / raw)
  To: Harald Welte; +Cc: netfilter-devel, Vincent Deffontaines, Pablo Neira


[-- Attachment #1.1: Type: text/plain, Size: 716 bytes --]

Hi,

On Fri, 2005-08-12 at 14:04 +0200, Harald Welte wrote:
> On Fri, Aug 12, 2005 at 10:42:56AM +0200, Eric Leblond wrote:
> > > Eric Leblond wrote:
> > >> This is a patch against libnfnetlink_queue.
> > >>
> > >> It adds "high" level functions to access to the data contained in a
> > >> nfqueue message. These are mostly encapsulation of NFA macros.

> I like the generic macros proposed by Pablo, but making nfnetlink_queue
> users directly use them is somewhat of a layering violation.

I've finally found some time to rewrite the provided functions with
Pablo's macros.

I've tested it against provided exemple and NuFW and it seems to work
fine.

BR,
-- 
Eric Leblond <eric@inl.fr>
INL

[-- Attachment #1.2: nfnetlink_queue.diff --]
[-- Type: text/x-patch, Size: 9658 bytes --]

Index: utils/nfqnl_test.c
===================================================================
--- utils/nfqnl_test.c	(révision 4261)
+++ utils/nfqnl_test.c	(copie de travail)
@@ -11,35 +11,37 @@
 static u_int32_t print_pkt (struct nfattr *tb[])
 {
 	int id = 0;
-
-	if (tb[NFQA_PACKET_HDR-1]) {
-		struct nfqnl_msg_packet_hdr *ph = 
-					NFA_DATA(tb[NFQA_PACKET_HDR-1]);
+	struct nfqnl_msg_packet_hdr *ph;
+	u_int32_t mark,ifi; 
+	int ret;
+	unsigned int datalength;
+	char * data;
+	
+	ph = nfqnl_get_msg_packet_hdr(tb);
+	if (ph){
 		id = ntohl(ph->packet_id);
 		printf("hw_protocol=0x%04x hook=%u id=%u ",
 			ntohs(ph->hw_protocol), ph->hook, id);
 	}
-
-	if (tb[NFQA_MARK-1]) {
-		u_int32_t mark = 
-			ntohl(*(u_int32_t *)NFA_DATA(tb[NFQA_MARK-1]));
+	
+	mark=nfqnl_get_nfmark(tb);
+	if (mark) {
 		printf("mark=%u ", mark);
 	}
 
-	if (tb[NFQA_IFINDEX_INDEV-1]) {
-		u_int32_t ifi = 
-			ntohl(*(u_int32_t *)NFA_DATA(tb[NFQA_IFINDEX_INDEV-1]));
-		printf("indev=%u ", ifi);
+	ret=nfqnl_get_indev(tb,&ifi,NULL);
+	if (ret) {
+		printf("indev=%u ", ntohl(ifi));
 	}
 
-	if (tb[NFQA_IFINDEX_OUTDEV-1]) {
-		u_int32_t ifi =
-			ntohl(*(u_int32_t *)NFA_DATA(tb[NFQA_IFINDEX_OUTDEV-1]));
-		printf("outdev=%u ", ifi);
+	ret=nfqnl_get_outdev(tb,&ifi,NULL);
+	if (ret) {
+		printf("outdev=%u ", ntohl(ifi));
 	}
 
-	if (tb[NFQA_PAYLOAD-1]) {
-		printf("payload_len=%d ", NFA_PAYLOAD(tb[NFQA_PAYLOAD-1]));
+	ret=nfqnl_get_payload(tb,&data,&datalength);
+	if (ret) {
+		printf("payload_len=%d ", datalength);
 	}
 
 	fputc('\n', stdout);
Index: include/libnfnetlink_queue/libnfnetlink_queue.h
===================================================================
--- include/libnfnetlink_queue/libnfnetlink_queue.h	(révision 4261)
+++ include/libnfnetlink_queue/libnfnetlink_queue.h	(copie de travail)
@@ -2,6 +2,10 @@
  *
  * (C) 2005 by Harald Welte <laforge@gnumonks.org>
  *
+ *
+ * Changelog : 
+ * 	(2005/08/11)  added  parsing function (Eric Leblond <regit@inl.fr>)
+ * 
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
  */
@@ -21,7 +25,7 @@
 extern struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h);
 extern int nfqnl_fd(struct nfqnl_handle *h);
 
-typedef nfqnl_callback(struct nfqnl_q_handle *gh, struct nfgenmsg *nfmsg,
+typedef int  nfqnl_callback(struct nfqnl_q_handle *gh, struct nfgenmsg *nfmsg,
 		       struct nfattr *nfa[], void *data);
 
 
@@ -47,10 +51,33 @@
 			     u_int32_t verdict,
 			     u_int32_t data_len,
 			     unsigned char *buf);
+
 extern int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, 
 				  u_int32_t id,
 			   	  u_int32_t verdict, 
 				  u_int32_t mark,
 			   	  u_int32_t datalen,
 				  unsigned char *buf);
+
+/* message parsing function */
+
+extern struct nfqnl_msg_packet_hdr * nfqnl_get_msg_packet_hdr(struct nfattr *nfa[]);
+
+extern u_int32_t nfqnl_get_nfmark(struct nfattr *nfa[]);
+
+extern struct nfqnl_msg_packet_timestamp * nfqnl_get_timestamp(struct nfattr *nfa[]);
+
+/* return 0 if not set */
+extern int nfqnl_get_indev(struct nfattr *nfa[],u_int32_t* indev, u_int32_t* physindev);
+
+/* return 0 if not set */
+extern int nfqnl_get_outdev(struct nfattr *nfa[],u_int32_t* outdev, u_int32_t* physoutdev);
+
+extern struct nfqnl_msg_packet_hw * nfqnl_get_packet_hw(struct nfattr *nfa[]);
+
+/* return 0 if problem */
+extern int nfqnl_get_payload(struct nfattr *nfa[],char ** data,unsigned int* datalen);
+
+
+
 #endif	/* __LIBNFQNETLINK_H */
Index: src/libnfnetlink_queue.c
===================================================================
--- src/libnfnetlink_queue.c	(révision 4261)
+++ src/libnfnetlink_queue.c	(copie de travail)
@@ -89,9 +89,9 @@
 }
 
 /* build a NFQNL_MSG_CONFIG message */
-static int
+	static int
 __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command,
-		     u_int16_t queuenum, u_int16_t pf)
+		u_int16_t queuenum, u_int16_t pf)
 {
 	char buf[NFNL_HEADER_LEN
 		+NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
@@ -99,7 +99,7 @@
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
 	nfnl_fill_hdr(&h->nfnlh, nmh, 0, AF_UNSPEC, queuenum,
-		      NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+			NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	cmd.command = command;
 	cmd.pf = htons(pf);
@@ -109,7 +109,7 @@
 }
 
 static int __nfqnl_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
-			   void *data)
+		void *data)
 {
 	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
 	struct nfqnl_handle *h = data;
@@ -196,9 +196,9 @@
 
 /* bind this socket to a specific queue number */
 struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h, 
-					  u_int16_t num,
-					  nfqnl_callback *cb,
-					  void *data)
+		u_int16_t num,
+		nfqnl_callback *cb,
+		void *data)
 {
 	int ret;
 	struct nfqnl_q_handle *qh;
@@ -243,7 +243,7 @@
 }
 
 int nfqnl_set_mode(struct nfqnl_q_handle *qh,
-		   u_int8_t mode, u_int32_t range)
+		u_int8_t mode, u_int32_t range)
 {
 	char buf[NFNL_HEADER_LEN
 		+NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
@@ -251,19 +251,19 @@
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
 	nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
-		      NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+			NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	params.copy_range = htonl(range);
 	params.copy_mode = mode;
 	nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, &params,
-		       sizeof(params));
+			sizeof(params));
 
 	return nfnl_talk(&qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
-			 u_int32_t verdict, u_int32_t mark, int set_mark,
-			 u_int32_t data_len, unsigned char *data)
+		u_int32_t verdict, u_int32_t mark, int set_mark,
+		u_int32_t data_len, unsigned char *data)
 {
 	struct nfqnl_msg_verdict_hdr vh;
 	char buf[NFNL_HEADER_LEN
@@ -278,8 +278,8 @@
 	vh.id = htonl(id);
 
 	nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
-		      NFQNL_MSG_VERDICT, NLM_F_REQUEST);
-			
+			NFQNL_MSG_VERDICT, NLM_F_REQUEST);
+
 	/* add verdict header */
 	nfnl_addattr_l(nmh, sizeof(buf), NFQA_VERDICT_HDR, &vh, sizeof(vh));
 
@@ -294,7 +294,7 @@
 		struct nfattr data_attr;
 
 		nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
-				     data_len, data);
+				data_len, data);
 		nvecs += 2;
 	}
 
@@ -302,15 +302,87 @@
 }
 
 int nfqnl_set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
-		      u_int32_t verdict, u_int32_t data_len, 
-		      unsigned char *buf)
+		u_int32_t verdict, u_int32_t data_len, 
+		unsigned char *buf)
 {
 	return __set_verdict(qh, id, verdict, 0, 0, data_len, buf);
 }	
 
 int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, u_int32_t id,
-			   u_int32_t verdict, u_int32_t mark,
-			   u_int32_t datalen, unsigned char *buf)
+		u_int32_t verdict, u_int32_t mark,
+		u_int32_t datalen, unsigned char *buf)
 {
 	return __set_verdict(qh, id, verdict, mark, 1, datalen, buf);
 }
+
+/*************************************************************
+ * Message parsing functions 
+ *************************************************************/
+
+#define nfnl_get_data(tb, attr, type)			\
+	({	type __ret = 0;					\
+	 if (tb[attr-1])					\
+	 __ret = *(type *)NFA_DATA(tb[attr-1]);	\
+	 __ret;						\
+	 })
+
+#define nfnl_get_pointer_to_data(tb, attr, type)	\
+	({	type *__ret = NULL;				\
+	 if (tb[attr-1])					\
+	 __ret = NFA_DATA(tb[attr-1]);		\
+	 __ret;						\
+	 })
+
+struct nfqnl_msg_packet_hdr * nfqnl_get_msg_packet_hdr(struct nfattr *nfa[]){
+	return nfnl_get_pointer_to_data(nfa,NFQA_PACKET_HDR,struct nfqnl_msg_packet_hdr );
+}
+
+uint32_t nfqnl_get_nfmark(struct nfattr *nfa[]){
+	return nfnl_get_data(nfa, NFQA_MARK, u_int32_t);
+}
+
+struct nfqnl_msg_packet_timestamp * nfqnl_get_timestamp(struct nfattr *nfa[]){
+	return nfnl_get_pointer_to_data(nfa,NFQA_TIMESTAMP,struct nfqnl_msg_packet_timestamp);
+}
+
+/* return 0 if not set */
+int nfqnl_get_indev(struct nfattr *nfa[],u_int32_t* indev, u_int32_t* physindev){
+	if (indev){
+		*indev=nfnl_get_data(nfa, NFQA_IFINDEX_INDEV, u_int32_t);
+		if (physindev){
+			*physindev=nfnl_get_data(nfa, NFQA_IFINDEX_PHYSINDEV, u_int32_t);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+/* return 0 if not set */
+int nfqnl_get_outdev(struct nfattr *nfa[],u_int32_t* outdev, u_int32_t* physoutdev){
+	if (outdev){
+		*outdev=nfnl_get_data(nfa, NFQA_IFINDEX_OUTDEV, u_int32_t);
+		if (physoutdev){
+			*physoutdev=nfnl_get_data(nfa, NFQA_IFINDEX_PHYSOUTDEV, u_int32_t);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+struct nfqnl_msg_packet_hw * nfqnl_get_packet_hw(struct nfattr *nfa[]){
+	return nfnl_get_pointer_to_data(nfa,NFQA_HWADDR,struct nfqnl_msg_packet_hw);
+}
+
+int nfqnl_get_payload(struct nfattr *nfa[],char ** data,unsigned int* datalen){
+	if (datalen) {
+		*data=nfnl_get_pointer_to_data(nfa, NFQA_PAYLOAD, char*);
+		if (*data){
+			*datalen=NFA_PAYLOAD(nfa[NFQA_PAYLOAD-1]);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(révision 4261)
+++ src/Makefile.am	(copie de travail)
@@ -2,7 +2,7 @@
 
 #EXTRA_DIST = $(man_MANS) acinclude.m4
 
-INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR} 
+INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR}
 AM_CFLAGS=-fPIC -Wall
 LIBS=
 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-09-14 19:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-11 21:01 [PATCH] message parsing functions for nfqueue Eric Leblond
2005-08-11 22:48 ` Harald Welte
2005-08-12 12:41   ` Harald Welte
2005-08-12  1:30 ` Pablo Neira
2005-08-12  8:42   ` Eric Leblond
2005-08-12 12:04     ` Harald Welte
2005-09-14 19:57       ` Eric Leblond

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.