* [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, ¶ms,
- 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 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-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-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, ¶ms, - 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.