libnfnetlink fixes
PATCH 1/1 libnfnetlink fixes
This fixes:
a) Check for bad file descriptor, otherwise this can result in a infinite loop during event display cancelation.
b) Return 0 on success. -100 is ugly and we this since we use explicit ACK confirmation (NLM_F_ACK) since it's cleaner.
c) nfnl_nest and nfnl_nest_end to build up nested attributes.
d) NLMSG_TAIL introduced in recent rtnetlinkv2 changes.
libnfnetlink.c +11 -8
@@ -108,10 +108,11 @@*/ int nfnl_close (struct nfnl_handle *nfnlh) { -if (nfnlh->fd) -close (nfnlh->fd); +int err; + + err =close (nfnlh->fd); -return 0 ; +return err; }/**
@@ -202,6 +203,9 @@if (remain <0 ) {if (errno ==EINTR )continue ; +/* Bad file descriptor */ +if (errno ==EBADF ) +break ;nfnl_error ("recvmsg overrun" );continue ; }
@@ -231,7 +235,7 @@/* end of messages reached, let's return */ if (h->nlmsg_type ==NLMSG_DONE ) -return -100 ; +return 0 ;/* Break the loop if success is explicitely * reported via NLM_F_ACK flag set */
@@ -400,12 +404,11 @@return -1 ; } - nfa = (struct nfattr *)(((char *)n) +NLMSG_ALIGN (n->nlmsg_len)); + nfa =NLMSG_TAIL (n); nfa->nfa_type = type; nfa->nfa_len = len;memcpy (NFA_DATA (nfa), data, alen); - n->nlmsg_len = (NLMSG_ALIGN (n->nlmsg_len) + len); - + n->nlmsg_len = (NLMSG_ALIGN (n->nlmsg_len) +NFA_ALIGN (len));return 0 ; }
@@ -482,7 +485,7 @@ {while (NFA_OK (nfa, len)) {if (nfa->nfa_type <= max) - tb[nfa->nfa_type] = nfa; + tb[nfa->nfa_type-1 ] = nfa; nfa =NFA_NEXT (nfa,len); }if (len)
libnfnetlink.h +9 -0
@@ -10,6 +10,9 @@#include <linux/netlink.h> #include <linux/netfilter/nfnetlink.h> +#define NLMSG_TAIL (nlh) \ + ((void *) (nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len) +#define NFNL_BUFFSIZE 8192struct nfnl_handle {
@@ -45,6 +48,12 @@extern int nfnl_nfa_addattr_l (struct nfattr *,int ,int ,void *,int );extern int nfnl_nfa_addattr32 (struct nfattr *,int ,int ,u_int32_t );extern int nfnl_parse_attr (struct nfattr **,int ,struct nfattr *,int ); +#define nfnl_nest (nlh, bufsize, type) \ +({ struct nfattr *__start = NLMSG_TAIL(nlh); \ + nfnl_addattr_l(nlh, bufsize, type, NULL, 0); \ + __start; }) +#define nfnl_nest_end (nlh, tail) \ +({ (tail)->nfa_len = (void *) NLMSG_TAIL(nlh) - (void *) tail; })extern void nfnl_dump_packet (struct nlmsghdr *,int ,char *);#endif /* __LIBNFNETLINK_H */
Here is a patch I propose for libnfnetlink.c
It allows the application-supplied callback handler to signifiy in its return code whether or not the nfnl_listen read-loop should terminate.
If the handler returns a negative code, then nfnl_listen returns immediately with the same return code.
If the handler returns a postitive code, then nfnl_listen returns at the next iteration of the while loop, which is when it finishes handing all netlink messages in the current packet.
This avois the need to duplicate most of nfnl_listen in a non-loop context where the application needs control over the read and packet decode process.
I use it to break out of the loop when a signal handler sets a flag, once the loop has broken I then do some per-signal processing and re-enter the loop.
Sam
opt/KERNEL/SVN/libnfnetlink/libnfnetlink.c +4 -2
@@ -184,6 +193,7 @@int remain;struct nlmsghdr *h;struct nlmsgerr *msgerr; +int quit=0 ;struct msghdr msg = { (void *)&nladdr,sizeof (nladdr),
@@ -197,7 +207,7 @@ iov.iov_base = buf; iov.iov_len =sizeof (buf); -while (1 ) { +while (! quit) { remain =recvmsg (nfnlh->fd, &msg,0 );if (remain <0 ) {if (errno ==EINTR )
@@ -243,6 +253,7 @@ err =handler (&nladdr, h, jarg);if (err <0 )return err; + quit |= err;/* FIXME: why not _NEXT macros, etc.? */ //h = NLMSG_NEXT(h, remain);
@@ -259,7 +270,7 @@ } } -return 0 ; +return quit; } int nfnl_talk(struct nfnl_handle *nfnlh, struct nlmsghdr *n, pid_t peer,
Harald Welte
AppliedQuoted 1 line · Pablo Neira
This fixes:
Thanks, applied with some minor cosmetic changes.
Signature · 5 lines
- Harald Welte <[email protected]> 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
Quoted 6 lines · Amin Azez
It allows the application-supplied callback handler to signifiy in its return code whether or not the
nfnl_listenread-loop should terminate.If the handler returns a negative code, then
nfnl_listenreturns immediately with the same return code.
Quoted 7 lines
If the handler returns a postitive code, then
nfnl_listenreturns at the next iteration of the while loop, which is when it finishes handing all netlink messages in the current packet.This avois the need to duplicate most of
nfnl_listenin a non-loop context where the application needs control over the read and packet decode process.
I think this change is fine. Would you mind to re-submit the patch against current svn? Please also document the meaning of the return values, probably with a comment in the code or the header file?
Thanks!
Signature · 5 lines
- Harald Welte <[email protected]> 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
Quoted 10 lines · Harald Welte
On Wed, Jul 13, 2005 at 09:23:56AM +0100, Amin Azez wrote:
I think this change is fine. Would you mind to re-submit the patch against current svn? Please also document the meaning of the return values, probably with a comment in the code or the header file?
Will do (Monday)
thanks for the feedback.
Azez
Attached, with explanatory notes in the function comment.
Sam
Quoted 18 lines · Harald Welte
Quoted 6 lines · Amin Azez
It allows the application-supplied callback handler to signifiy in its return code whether or not the
nfnl_listenread-loop should terminate.If the handler returns a negative code, then
nfnl_listenreturns immediately with the same return code.Quoted 7 lines
If the handler returns a postitive code, then
nfnl_listenreturns at the next iteration of the while loop, which is when it finishes handing all netlink messages in the current packet.This avois the need to duplicate most of
nfnl_listenin a non-loop context where the application needs control over the read and packet decode process.
Quoted 6 lines
I think this change is fine. Would you mind to re-submit the patch against current svn? Please also document the meaning of the return values, probably with a comment in the code or the header file?
Thanks!
libnfnetlink.c +14 -2
@@ -257,6 +257,16 @@* * nfnhl: libnfnetlink handle * handler: callback function to be called for every netlink message +* - the callback handler should normally return 0 +* - but may return a negative error code which will cause +* nfnl_listen to return immediately with the same error code +* - or return a postivie error code which will cause +* nfnl_listen to return after it has finished processing all +* the netlink messages in the current packet +* Thus a positive error code will terminate nfnl_listen "soon" +* without any loss of data, a negative error code will terminate +* nfnl_listen "very soon" and throw away data already read from +* the netlink socket. * jarg: opaque argument passed on to callback * */
@@ -270,6 +280,7 @@int remain;struct nlmsghdr *h;struct nlmsgerr *msgerr; +int quit=0 ;struct msghdr msg = { (void *)&nladdr,sizeof (nladdr),
@@ -283,7 +294,7 @@ iov.iov_base = buf; iov.iov_len =sizeof (buf); -while (1 ) { +while (! quit) { remain =recvmsg (nfnlh->fd, &msg,0 );if (remain <0 ) {if (errno ==EINTR )
@@ -332,6 +343,7 @@ err =handler (&nladdr, h, jarg);if (err <0 )return err; + quit |= err;/* FIXME: why not _NEXT macros, etc.? */ //h = NLMSG_NEXT(h, remain);
@@ -348,7 +360,7 @@ } } -return 0 ; +return quit; } int nfnl_talk(struct nfnl_handle *nfnlh, struct nlmsghdr *n, pid_t peer,
Quoted 12 lines · Amin Azez
Quoted 10 lines · Harald Welte
On Wed, Jul 13, 2005 at 09:23:56AM +0100, Amin Azez wrote:
I think this change is fine. Would you mind to re-submit the patch against current svn? Please also document the meaning of the return values, probably with a comment in the code or the header file?
Quoted 3 lines
Will do (Monday)
thanks for the feedback.
I haven't received an updated patch so far. Did I miss it somehow?
Signature · 5 lines
- Harald Welte <[email protected]> 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
Quoted 19 lines · Harald Welte
Quoted 16 lines · Amin Azez
Quoted 12 lines · Harald Welte
On Wed, Jul 13, 2005 at 09:23:56AM +0100, Amin Azez wrote:
I think this change is fine. Would you mind to re-submit the patch against current svn? Please also document the meaning of the return values, probably with a comment in the code or the header file?
Quoted 10 lines
Quoted 5 lines
Will do (Monday)
thanks for the feedback.
I haven't received an updated patch so far. Did I miss it somehow?
err... you must have, I sent it on 5th Sept.
Attached again.
Azez
libnfnetlink.c +14 -2
@@ -257,6 +257,16 @@* * nfnhl: libnfnetlink handle * handler: callback function to be called for every netlink message +* - the callback handler should normally return 0 +* - but may return a negative error code which will cause +* nfnl_listen to return immediately with the same error code +* - or return a postivie error code which will cause +* nfnl_listen to return after it has finished processing all +* the netlink messages in the current packet +* Thus a positive error code will terminate nfnl_listen "soon" +* without any loss of data, a negative error code will terminate +* nfnl_listen "very soon" and throw away data already read from +* the netlink socket. * jarg: opaque argument passed on to callback * */
@@ -270,6 +280,7 @@int remain;struct nlmsghdr *h;struct nlmsgerr *msgerr; +int quit=0 ;struct msghdr msg = { (void *)&nladdr,sizeof (nladdr),
@@ -283,7 +294,7 @@ iov.iov_base = buf; iov.iov_len =sizeof (buf); -while (1 ) { +while (! quit) { remain =recvmsg (nfnlh->fd, &msg,0 );if (remain <0 ) {if (errno ==EINTR )
@@ -332,6 +343,7 @@ err =handler (&nladdr, h, jarg);if (err <0 )return err; + quit |= err;/* FIXME: why not _NEXT macros, etc.? */ //h = NLMSG_NEXT(h, remain);
@@ -348,7 +360,7 @@ } } -return 0 ; +return quit; } int nfnl_talk(struct nfnl_handle *nfnlh, struct nlmsghdr *n, pid_t peer,
Quoted 1 line · Amin Azez
err... you must have, I sent it on 5th Sept.
sorry. I've applied it now (Committed revision 4258.)
Signature · 5 lines
- Harald Welte <[email protected]> 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