summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org>2005-07-30 16:39:46 +0000
committer/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org>2005-07-30 16:39:46 +0000
commita3c179d2af76c658dbeac434118d85b8630d000a (patch)
treea2c63f24077e7775069821e0dfe66560de1a73a2
parentb1304ebe83504fa38d087c12a1f8772142f57440 (diff)
Add nfnl_rcvbufsiz(), nfnl_msg_get_first(), nfnl_msg_get_next()
-rw-r--r--libnfnetlink.c77
-rw-r--r--libnfnetlink.h12
2 files changed, 87 insertions, 2 deletions
diff --git a/libnfnetlink.c b/libnfnetlink.c
index 80cb0c4..ef7a18e 100644
--- a/libnfnetlink.c
+++ b/libnfnetlink.c
@@ -17,6 +17,7 @@
#include <time.h>
#include <netinet/in.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include "libnfnetlink.h"
@@ -187,7 +188,8 @@ void nfnl_fill_hdr(struct nfnl_handle *nfnlh,
}
struct nfattr *
-nfnl_parse_hdr(struct nfnl_handle *nfnlh, const struct nlmsghdr *nlh,
+nfnl_parse_hdr(const struct nfnl_handle *nfnlh,
+ const struct nlmsghdr *nlh,
struct nfgenmsg **genmsg)
{
if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg)))
@@ -550,3 +552,76 @@ void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa,
iov[1].iov_base = val;
iov[1].iov_len = NFA_ALIGN(len);
}
+
+#ifndef SO_RCVBUFFORCE
+#define SO_RCVBUFFORCE (33)
+#endif
+
+unsigned int nfnl_rcvbufsiz(struct nfnl_handle *h, unsigned int size)
+{
+ int status;
+ socklen_t socklen = sizeof(size);
+ unsigned int read_size = 0;
+
+ /* first we try the FORCE option, which is introduced in kernel
+ * 2.6.14 to give "root" the ability to override the system wide
+ * maximum */
+ status = setsockopt(h->fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, socklen);
+ if (status < 0) {
+ /* if this didn't work, we try at least to get the system
+ * wide maximum (or whatever the user requested) */
+ setsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &size, socklen);
+ }
+ getsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &read_size, &socklen);
+
+ return read_size;
+}
+
+
+struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h,
+ const unsigned char *buf,
+ size_t len)
+{
+ struct nlmsghdr *nlh;
+
+ /* first message in buffer */
+ nlh = (struct nlmsghdr *)buf;
+ if (!NLMSG_OK(nlh, len))
+ return NULL;
+ h->last_nlhdr = nlh;
+
+ return nlh;
+}
+
+struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h,
+ const unsigned char *buf,
+ size_t len)
+{
+ struct nlmsghdr *nlh;
+ size_t remain_len;
+
+ /* if last header in handle not inside this buffer,
+ * drop reference to last header */
+ if (!h->last_nlhdr ||
+ (unsigned char *)h->last_nlhdr > (buf + len) ||
+ (unsigned char *)h->last_nlhdr < buf) {
+ h->last_nlhdr = NULL;
+ return NULL;
+ }
+
+ /* n-th part of multipart message */
+ if (h->last_nlhdr->nlmsg_type == NLMSG_DONE ||
+ h->last_nlhdr->nlmsg_flags & NLM_F_MULTI) {
+ /* if last part in multipart message or no
+ * multipart message at all, return */
+ h->last_nlhdr = NULL;
+ return NULL;
+ }
+
+ remain_len = (len - ((unsigned char *)h->last_nlhdr - buf));
+ nlh = NLMSG_NEXT(h->last_nlhdr, remain_len);
+
+ h->last_nlhdr = nlh;
+
+ return nlh;
+}
diff --git a/libnfnetlink.h b/libnfnetlink.h
index 43ed151..95ec004 100644
--- a/libnfnetlink.h
+++ b/libnfnetlink.h
@@ -23,6 +23,7 @@ struct nfnl_handle {
u_int8_t subsys_id;
u_int32_t seq;
u_int32_t dump;
+ struct nlmsghdr *last_nlhdr;
};
/* get a new library handle */
@@ -39,7 +40,7 @@ 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 struct nfattr *nfnl_parse_hdr(struct nfnl_handle *nfnlh,
+extern struct nfattr *nfnl_parse_hdr(const struct nfnl_handle *nfnlh,
const struct nlmsghdr *nlh,
struct nfgenmsg **genmsg);
@@ -70,6 +71,15 @@ extern int nfnl_parse_attr(struct nfattr **, int, struct nfattr *, int);
extern void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa,
u_int16_t type, u_int32_t len,
unsigned char *val);
+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 */