Skip to contentSkip to conversation

genl: Implement message nesting

PATCH New Denis Kenzior 1 participant 2 messages Mar 24, 2015

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 genl: Implement message nesting

---
 ell/genl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 ell/genl.h |  2 ++
 2 files changed, 50 insertions(+)
ell/genl.c +48 -0
index 1b1afab..290325f 100644
@@ -37,6 +37,8 @@
 #include "genl-private.h"
 #include "private.h"
 
+#define MAX_NESTING_LEVEL 4
+
 struct l_genl {
 	int ref_count;
 	int fd;
@@ -65,6 +67,8 @@ struct l_genl_msg {
 	void *data;
 	uint32_t size;
 	uint32_t len;
+	struct nlattr *nests[MAX_NESTING_LEVEL];
+	uint8_t nesting_level;
 };
 
 struct genl_request {
@@ -241,6 +245,7 @@ static struct l_genl_msg *msg_alloc(uint8_t cmd, uint8_t version, uint32_t size)
 	msg->size = msg->len + NLMSG_ALIGN(size);
 
 	msg->data = l_new(unsigned char, msg->size);
+	msg->nesting_level = 0;
 
 	return l_genl_msg_ref(msg);
 }
@@ -737,6 +742,49 @@ LIB_EXPORT bool l_genl_msg_append_attr(struct l_genl_msg *msg, uint16_t type,
 	return true;
 }
 
+LIB_EXPORT bool l_genl_msg_enter_nested(struct l_genl_msg *msg, uint16_t type)
+{
+	struct nlattr *nla;
+
+	if (unlikely(!msg))
+		return false;
+
+	if (unlikely(msg->nesting_level == MAX_NESTING_LEVEL))
+		return false;
+
+	if (msg->len + NLA_HDRLEN > msg->size)
+		return false;
+
+	nla = msg->data + msg->len;
+	nla->nla_type = type;
+	nla->nla_len = msg->len; /* Save position */
+
+	msg->nests[msg->nesting_level] = nla;
+	msg->nesting_level += 1;
+
+	msg->len += NLA_HDRLEN;
+
+	return true;
+}
+
+LIB_EXPORT bool l_genl_msg_leave_nested(struct l_genl_msg *msg)
+{
+	struct nlattr *nla;
+
+	if (unlikely(!msg))
+		return false;
+
+	if (unlikely(msg->nesting_level == 0))
+		return false;
+
+	nla = msg->nests[msg->nesting_level - 1];
+	nla->nla_len = msg->len - nla->nla_len;
+
+	msg->nesting_level -= 1;
+
+	return true;
+}
+
 #define NLA_OK(nla,len)         ((len) >= (int) sizeof(struct nlattr) && \
 				(nla)->nla_len >= sizeof(struct nlattr) && \
 				(nla)->nla_len <= (len))
ell/genl.h +2 -0
index c628b8c..8f5fd52 100644
@@ -71,6 +71,8 @@ int l_genl_msg_get_error(struct l_genl_msg *msg);
 
 bool l_genl_msg_append_attr(struct l_genl_msg *msg, uint16_t type,
 					uint16_t len, const void *data);
+bool l_genl_msg_enter_nested(struct l_genl_msg *msg, uint16_t type);
+bool l_genl_msg_leave_nested(struct l_genl_msg *msg);
 
 bool l_genl_attr_init(struct l_genl_attr *attr, struct l_genl_msg *msg);
 bool l_genl_attr_next(struct l_genl_attr *attr, uint16_t *type,
Signature · 1 line
2.0.4
#1 lore raw

PATCH 2/2 unit: Add unit test to build set rekey offload

---
 unit/test-genl-msg.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)
unit/test-genl-msg.c +43 -1
index f9ebf21..e052f33 100644
@@ -31,7 +31,7 @@
 
 #include "ell/genl-private.h"
 
-static bool do_print = false;
+static bool do_print = true;
 
 static void do_debug(const char *str, void *user_data)
 {
@@ -204,6 +204,46 @@ static void parse_set_rekey_offload(const void *data)
 	l_genl_msg_unref(msg);
 }
 
+static void build_set_rekey_offload(const void *data)
+{
+	static uint32_t index = 3;
+	static const unsigned char kek[] = {
+		0x2f, 0x82, 0xbb, 0x0d, 0x93, 0x56, 0x60, 0x4b,
+		0xb1, 0x55, 0x1c, 0x85, 0xc0, 0xeb, 0x32, 0x8b };
+	static const unsigned char kck[] = {
+		0x43, 0x25, 0xcf, 0x08, 0x0b, 0x92, 0xa7, 0x2d,
+		0x86, 0xdc, 0x43, 0x21, 0xd6, 0x0c, 0x12, 0x03 };
+	static const unsigned char replay_counter[] = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
+	struct l_genl_msg *msg;
+	const void *raw;
+	size_t size;
+
+	msg = l_genl_msg_new_sized(79, 512);
+	assert(msg);
+
+	assert(l_genl_msg_append_attr(msg, 3, 4, &index));
+
+	assert(l_genl_msg_enter_nested(msg, 122));
+	assert(l_genl_msg_append_attr(msg, 1, 16, kek));
+	assert(l_genl_msg_append_attr(msg, 2, 16, kck));
+	assert(l_genl_msg_append_attr(msg, 3, 8, replay_counter));
+	assert(l_genl_msg_leave_nested(msg));
+
+	raw = _genl_msg_as_bytes(msg, 0x1b, 0x05, 0x53e1a359, 0xe74002ba,
+					&size);
+	if (do_print) {
+		l_util_hexdump(false, raw, size, do_debug, "[MSG] ");
+		l_util_hexdump(true, set_rekey_offload_request, size,
+					do_debug, "[MSG] ");
+	}
+
+	assert(size == sizeof(set_rekey_offload_request));
+	assert(!memcmp(raw, set_rekey_offload_request, size));
+
+	l_genl_msg_unref(msg);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_add("Parse Set Station Request", parse_set_station, NULL);
@@ -211,6 +251,8 @@ int main(int argc, char *argv[])
 				parse_set_rekey_offload, NULL);
 
 	l_test_add("Build Set Station Request", build_set_station, NULL);
+	l_test_add("Build Set Rekey Offload Request",
+				build_set_rekey_offload, NULL);
 
 	return l_test_run();
 }
Signature · 1 line
2.0.4