From 5cc6fec28591227c5159217d237054412ecda071 Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 30 Jan 2001 09:28:04 +0000 Subject: added support for multipart netlink messages (new ULOG target) --- ulogd/libipulog/Makefile | 2 +- ulogd/libipulog/include/libipulog/libipulog.h | 4 +- ulogd/libipulog/libipulog.c | 56 +++++++++++++++++++++++---- ulogd/libipulog/ulog_test.c | 15 +++---- 4 files changed, 61 insertions(+), 16 deletions(-) (limited to 'ulogd/libipulog') diff --git a/ulogd/libipulog/Makefile b/ulogd/libipulog/Makefile index e737363..ea6b27a 100644 --- a/ulogd/libipulog/Makefile +++ b/ulogd/libipulog/Makefile @@ -2,7 +2,7 @@ CC = gcc CFLAGS = -I./include # -g ulog_test: ulog_test.c libipulog.a - $(CC) $(CFLAGS) -i ulog_test.c libipulog.a -o ulog_test + $(CC) $(CFLAGS) ulog_test.c libipulog.a -o ulog_test libipulog.o: libipulog.c $(CC) $(CFLAGS) -c libipulog.c -o libipulog.o diff --git a/ulogd/libipulog/include/libipulog/libipulog.h b/ulogd/libipulog/include/libipulog/libipulog.h index 9f920dd..9b0c277 100644 --- a/ulogd/libipulog/include/libipulog/libipulog.h +++ b/ulogd/libipulog/include/libipulog/libipulog.h @@ -23,7 +23,9 @@ void ipulog_destroy_handle(struct ipulog_handle *h); ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf, size_t len, int timeout); -ulog_packet_msg_t *ipulog_get_packet(const unsigned char *buf); +ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h, + const unsigned char *buf, + size_t len); void ipulog_perror(const char *s); diff --git a/ulogd/libipulog/libipulog.c b/ulogd/libipulog/libipulog.c index d7838b6..4aa12e5 100644 --- a/ulogd/libipulog/libipulog.c +++ b/ulogd/libipulog/libipulog.c @@ -1,5 +1,5 @@ /* - * libipulog.c, $Revision: 1.4 $ + * libipulog.c, $Revision: 1.5 $ * * netfilter ULOG userspace library. * @@ -9,7 +9,7 @@ * This library is still under development, so be aware of sudden interface * changes * - * $Id: libipulog.c,v 1.4 2000/08/12 07:11:29 laforge Exp $ + * $Id: libipulog.c,v 1.5 2000/09/22 06:57:16 laforge Exp $ */ #include @@ -25,6 +25,7 @@ struct ipulog_handle u_int8_t blocking; struct sockaddr_nl local; struct sockaddr_nl peer; + struct nlmsghdr* last_nlhdr; }; /* internal */ @@ -41,9 +42,10 @@ enum IPULOG_ERR_NLEOF, IPULOG_ERR_TRUNC, IPULOG_ERR_INVGR, + IPULOG_ERR_INVNL, }; -#define IPULOG_MAXERR IPULOG_ERR_INVGR +#define IPULOG_MAXERR IPULOG_ERR_INVNL static int ipulog_errno = IPULOG_ERR_NONE; @@ -59,10 +61,11 @@ struct ipulog_errmap_t { IPULOG_ERR_SOCKET, "Unable to create netlink socket" }, { IPULOG_ERR_BIND, "Unable to bind netlink socket" }, { IPULOG_ERR_RECVBUF, "Receive buffer size invalid" }, - { IPULOG_ERR_RECV, "Receive buffer size invalid" }, + { IPULOG_ERR_RECV, "Error during netlink receive" }, { IPULOG_ERR_NLEOF, "Received EOF on netlink socket" }, { IPULOG_ERR_TRUNC, "Receive message truncated" }, { IPULOG_ERR_INVGR, "Invalid group specified" }, + { IPULOG_ERR_INVNL, "Invalid netlink message" }, }; static ssize_t ipulog_netlink_recvfrom(const struct ipulog_handle *h, @@ -94,7 +97,7 @@ static ssize_t ipulog_netlink_recvfrom(const struct ipulog_handle *h, return -1; } nlh = (struct nlmsghdr *)buf; - if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > status) + if (nlh->nlmsg_flags & MSG_TRUNC || status > len) { ipulog_errno = IPULOG_ERR_TRUNC; return -1; @@ -186,9 +189,48 @@ ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf, /* get a pointer to the actual start of the ipulog packet, use this to strip netlink header */ -ulog_packet_msg_t *ipulog_get_packet(const unsigned char *buf) +ulog_packet_msg_t *ipulog_get_packet(struct ipulog_handle *h, + const unsigned char *buf, + size_t len) { - return NLMSG_DATA((struct nlmsghdr *) buf); + struct nlmsghdr *nlh; + size_t remain_len; + + /* if last header in handle not inside this buffer, + * drop reference to last header */ + if ((unsigned char *)h->last_nlhdr > (buf + len) || + (unsigned char *)h->last_nlhdr < buf) { + h->last_nlhdr = NULL; + } + + if (!h->last_nlhdr) { + /* fist message in buffer */ + nlh = (struct nlmsghdr *) buf; + if (!NLMSG_OK(nlh, len)) { + /* ERROR */ + ipulog_errno = IPULOG_ERR_INVNL; + return NULL; + } + } else { + /* we are in n-th part of multilink message */ + if (h->last_nlhdr->nlmsg_type == NLMSG_DONE) { + /* if last part in multilink message, return */ + h->last_nlhdr = NULL; + return NULL; + } + + /* calculate remaining lenght from lasthdr to end of buffer */ + remain_len = (len - + ((unsigned char *)h->last_nlhdr - buf)); + nlh = NLMSG_NEXT(h->last_nlhdr, remain_len); + } + + /* update last_nlhdr field */ + if (nlh->nlmsg_flags & NLM_F_MULTI) { + h->last_nlhdr = nlh; + } + + return NLMSG_DATA(nlh); } /* print a human readable description of the last error to stderr */ diff --git a/ulogd/libipulog/ulog_test.c b/ulogd/libipulog/ulog_test.c index 71238b6..c9ef9b7 100644 --- a/ulogd/libipulog/ulog_test.c +++ b/ulogd/libipulog/ulog_test.c @@ -1,4 +1,4 @@ -/* ulog_test, $Revision: 1.2 $ +/* ulog_test, $Revision: 1.3 $ * * small testing program for libipulog, part of the netfilter ULOG target * for the linux 2.4 netfilter subsystem. @@ -7,7 +7,7 @@ * * this code is released under the terms of GNU GPL * - * $Id: ulog_test.c,v 1.2 2000/07/31 15:02:33 laforge Exp $ + * $Id: ulog_test.c,v 1.3 2000/09/22 06:57:16 laforge Exp $ */ #include @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) { struct ipulog_handle *h; unsigned char* buf; - size_t len; + int len; ulog_packet_msg_t *upkt; int i; @@ -67,14 +67,15 @@ int main(int argc, char *argv[]) /* loop receiving packets and handling them over to handle_packet */ for (i = 0; i < atoi(argv[1]); i++) { - len = ipulog_read(h, buf, BUFSIZ, 1); + len = ipulog_read(h, buf, MYBUFSIZ, 1); if (len < 0) { ipulog_perror("ulog_test: short read"); exit(1); } - upkt = ipulog_get_packet(buf); - printf("%d: ", len); - handle_packet(upkt); + printf("%d bytes received\n", len); + while (upkt = ipulog_get_packet(h, buf, len)) { + handle_packet(upkt); + } } /* just to give it a cleaner look */ -- cgit v1.2.3