summaryrefslogtreecommitdiff
path: root/src/msg.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2010-03-19 14:55:32 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2010-03-19 14:55:32 +0100
commit74e7bb8b033640f7c4692c4ea0d5c231e3137b7b (patch)
tree4cc2125d00b83b5ac1b076da2c8e3eff7b08ddc3 /src/msg.c
downloadlibmnl-74e7bb8b033640f7c4692c4ea0d5c231e3137b7b.tar.gz
libmnl-74e7bb8b033640f7c4692c4ea0d5c231e3137b7b.zip
initial libmnl import
Diffstat (limited to 'src/msg.c')
-rw-r--r--src/msg.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/msg.c b/src/msg.c
new file mode 100644
index 0000000..02f812b
--- /dev/null
+++ b/src/msg.c
@@ -0,0 +1,213 @@
+/*
+ * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libmnl/libmnl.h>
+
+/**
+ * mnl_align - align a value to four bytes
+ * @value: the value that we want to get aligned
+ *
+ * This function returns the value passed aligned to four bytes. Netlink
+ * message headers and its attributes are always aligned to four bytes.
+ */
+int mnl_align(int value)
+{
+ return (value + MNL_ALIGNTO - 1) & ~(MNL_ALIGNTO - 1);
+}
+
+/**
+ * mnl_nlmsg_size - get size of the netlink messages (without alignment)
+ * @len: length of the netlink message
+ *
+ * This function returns the size of a netlink message (header plus payload)
+ * without alignment.
+ */
+size_t mnl_nlmsg_size(int len)
+{
+ return len + mnl_align(MNL_NLMSG_HDRLEN);
+}
+
+/**
+ * mnl_nlmsg_aligned_size - get size of the netlink messages (with alignment)
+ * @len: length of the netlink message
+ *
+ * This function returns the size of a netlink message (header plus payload)
+ * with alignment.
+ */
+size_t mnl_nlmsg_aligned_size(int len)
+{
+ return mnl_align(mnl_nlmsg_size(len));
+}
+
+/**
+ * mnl_nlmsg_payload_size - get the size of the payload
+ * @nlh: pointer to the header of the netlink message
+ *
+ * This function returns the size of the netlink payload
+ */
+size_t mnl_nlmsg_payload_size(const struct nlmsghdr *nlh)
+{
+ return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
+}
+
+/**
+ * mnl_nlmsg_put_header - prepare room for Netlink header
+ * @buf: memory already allocated to store the Netlink message
+ *
+ * This function sets to zero the room that is required to put a Netlink
+ * header in the memory buffer passed as parameter. This function also
+ * initializes the nlmsg_len field. This function returns a pointer to the
+ * Netlink header structure.
+ */
+struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
+{
+ int len = mnl_align(sizeof(struct nlmsghdr));
+ struct nlmsghdr *nlh = buf;
+
+ memset(buf, 0, len);
+ nlh->nlmsg_len = len;
+ return nlh;
+}
+
+/**
+ * mnl_nlmsg_put_extra_header - prepare room for an extra header
+ * @nlh: pointer to Netlink header
+ * @size: size of the extra header that we want to put
+ *
+ * This function sets to zero the room that is required to put the extra
+ * header after the initial Netlink header. This function also increases
+ * the nlmsg_len field. This function returns a pointer to the extra
+ * header.
+ */
+void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, int size)
+{
+ char *ptr = (char *)nlh + nlh->nlmsg_len;
+ nlh->nlmsg_len += mnl_align(size);
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+/**
+ * mnl_nlmsg_get_len - get the length field from the netlink message
+ * @nlh: pointer to a netlink header
+ *
+ * This function returns the length of the netlink message by return the field
+ * nlmsg_len of the message.
+ */
+u_int16_t mnl_nlmsg_get_len(const struct nlmsghdr *nlh)
+{
+ return nlh->nlmsg_len;
+}
+
+/**
+ * mnl_nlmsg_get_data - get a pointer to the payload of the netlink message
+ * @nlh: pointer to a netlink header
+ *
+ * This function returns a pointer to the payload of the netlink message.
+ */
+void *mnl_nlmsg_get_data(const struct nlmsghdr *nlh)
+{
+ return (void *)nlh + MNL_NLMSG_HDRLEN;
+}
+
+/**
+ * mnl_nlmsg_get_data_offset - get a pointer to the payload of the message
+ * @nlh: pointer to a netlink header
+ * @offset: offset to the payload of the attributes TLV set
+ *
+ * This function returns a pointer to the payload of the netlink message plus
+ * a given offset.
+ */
+void *mnl_nlmsg_get_data_offset(const struct nlmsghdr *nlh, int offset)
+{
+ return (void *)nlh + MNL_NLMSG_HDRLEN + mnl_align(offset);
+}
+
+/**
+ * mnl_nlmsg_ok - check a there is room for netlink message
+ * @nlh: netlink message that we want to check
+ * @len: remaining bytes in a buffer that contains the netlink message
+ *
+ * This function is used to check that a buffer that contains a netlink
+ * message has enough room for the netlink message that it stores, ie. this
+ * function can be used to verify that a netlink message is not malformed nor
+ * truncated.
+ */
+int mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
+{
+ return len >= sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len <= len;
+}
+
+/**
+ * mnl_nlmsg_next - get the next netlink message in a multipart message
+ * @nlh: current netlink message that we are handling
+ * @len: pointer to the current remaining bytes in the buffer
+ *
+ * This function returns a pointer to the next netlink message that is part
+ * of a multi-part netlink message. Netlink can batches messages into a buffer
+ * so that the receiver has to iterate over the whole set of netlink
+ * messages.
+ */
+struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
+{
+ *len -= mnl_align(nlh->nlmsg_len);
+ return (struct nlmsghdr *)((void *)nlh + mnl_align(nlh->nlmsg_len));
+}
+
+void *mnl_nlmsg_get_tail(const struct nlmsghdr *nlh)
+{
+ return (struct nlmsghdr *)((void *)nlh + mnl_align(nlh->nlmsg_len));
+}
+
+/**
+ * mnl_nlmsg_seq_ok - perform sequence tracking
+ * @nlh: current netlink message that we are handling
+ * @seq: last sequence number used to send a message
+ *
+ * This functions returns 1 if the sequence tracking is fulfilled, otherwise
+ * 0 is returned. If seq is 0, then the sequence tracking is skipped. This
+ * value is generally used by the kernel for asynchronous notifications,
+ * for that reason, this library consider that it is reserved.
+ */
+int mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
+{
+ return seq ? nlh->nlmsg_seq == seq : 1;
+}
+
+/* XXX: rework this, please */
+void mnl_nlmsg_print(const struct nlmsghdr *nlh)
+{
+ int i;
+
+ printf("========= netlink header ==========\n");
+ printf("length(32 bits)=%.08u\n", nlh->nlmsg_len);
+ printf("type(16 bits)=%.04u flags(16 bits)=%.04x\n",
+ nlh->nlmsg_type, nlh->nlmsg_flags);
+ printf("sequence number(32 bits)=%.08x\n", nlh->nlmsg_seq);
+ printf("port ID(32 bits)=%.08u\n", nlh->nlmsg_pid);
+ printf("===================================\n");
+
+ for (i=sizeof(struct nlmsghdr); i<mnl_nlmsg_get_len(nlh); i+=4) {
+ char *b = (char *) nlh;
+
+ printf("(%.3d) %.2x %.2x %.2x %.2x | ", i,
+ 0xff & b[i], 0xff & b[i+1],
+ 0xff & b[i+2], 0xff & b[i+3]);
+
+ printf("%c %c %c %c\n",
+ isalnum(b[i]) ? b[i] : 0,
+ isalnum(b[i+1]) ? b[i+1] : 0,
+ isalnum(b[i+2]) ? b[i+2] : 0,
+ isalnum(b[i+3]) ? b[i+3] : 0);
+ }
+}