From 64f17e85b4783b1a34f6d46dd8aed2745ed0c583 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 10 Aug 2011 15:25:51 -0700 Subject: [PATCH] libnl_2: Fix nested attribute setting Change-Id: I9dbf72a25e8a939ab6aa35eaf4adbf86d9ed97a1 Signed-off-by: Dmitry Shmidt --- libnl_2/Android.mk | 3 +- libnl_2/attr.c | 90 ++++++++++++++++++---------------------------- libnl_2/dbg.c | 12 +++++++ libnl_2/msg.c | 34 ++++++++---------- 4 files changed, 64 insertions(+), 75 deletions(-) create mode 100644 libnl_2/dbg.c diff --git a/libnl_2/Android.mk b/libnl_2/Android.mk index 800c2b2a4..302b4dd1f 100644 --- a/libnl_2/Android.mk +++ b/libnl_2/Android.mk @@ -11,7 +11,8 @@ LOCAL_SRC_FILES := \ msg.c \ netlink.c \ object.c \ - socket.c + socket.c \ + dbg.c LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/include diff --git a/libnl_2/attr.c b/libnl_2/attr.c index d416350e2..f3a2b58c4 100644 --- a/libnl_2/attr.c +++ b/libnl_2/attr.c @@ -66,38 +66,30 @@ int nla_len(const struct nlattr *nla) return nla->nla_len - NLA_HDRLEN; } +int nla_padlen(int payload) +{ + return NLA_ALIGN(payload) - payload; +} + /* Start a new level of nested attributes. */ struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) { - if (!nla_put(msg, attrtype, 0, NULL)) { - /* Get ref to last (nested start) attr */ - int padding; - struct nlattr *nla; + struct nlattr *start = (struct nlattr *)nlmsg_tail(msg->nm_nlh); + int rc; - padding = nlmsg_padlen(nlmsg_datalen(nlmsg_hdr(msg))); - nla = (struct nlattr *) \ - ((char *) nlmsg_tail(msg->nm_nlh) - padding); - return nla; - - } else + rc = nla_put(msg, attrtype, 0, NULL); + if (rc < 0) return NULL; + return start; } /* Finalize nesting of attributes. */ int nla_nest_end(struct nl_msg *msg, struct nlattr *start) { - struct nlattr *container; - - /* Adjust nested attribute container size */ - container = (unsigned char *) start - sizeof(struct nlattr); - container->nla_len = (unsigned char *) \ - nlmsg_tail(nlmsg_hdr(msg)) - (unsigned char *)container; - - /* Fix attribute size */ - start->nla_len = (unsigned char *) \ - nlmsg_tail(nlmsg_hdr(msg)) - (unsigned char *)start; - + /* Set attribute size */ + start->nla_len = (unsigned char *)nlmsg_tail(nlmsg_hdr(msg)) - + (unsigned char *)start; return 0; } @@ -134,14 +126,13 @@ int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int rem; /* First clear table */ - memset(tb, 0, (maxtype+1) * sizeof(struct nlattr *)); + memset(tb, 0, (maxtype + 1) * sizeof(struct nlattr *)); nla_for_each_attr(pos, head, len, rem) { - const int type = nla_type(pos); + int type = nla_type(pos); - if (type <= maxtype) + if ((type <= maxtype) && (type != 0)) tb[type] = pos; - } return 0; @@ -179,15 +170,10 @@ int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) * nested message may not have a family specific header */ int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) { - int rc = -1; - const int NO_HEADER = 0; + int rc; - rc = nla_put( - msg, - attrtype, - nlmsg_attrlen(nlmsg_hdr(nested), NO_HEADER), - (const void *) nlmsg_attrdata(nlmsg_hdr(nested), NO_HEADER) - ); + rc = nla_put(msg, attrtype, nlmsg_attrlen(nlmsg_hdr(nested), 0), + nlmsg_attrdata(nlmsg_hdr(nested), 0)); return rc; } @@ -195,43 +181,37 @@ int nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) /* Return type of the attribute. */ int nla_type(const struct nlattr *nla) { - return (int) nla->nla_type; + return (int)nla->nla_type & NLA_TYPE_MASK; } /* Reserves room for an attribute in specified netlink message and fills * in the attribute header (type,length). Return NULL if insufficient space */ -struct nlattr *nla_reserve(struct nl_msg * msg, int attrtype, int data_len) +struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int data_len) { struct nlattr *nla; - const unsigned int NEW_SIZE = \ - msg->nm_nlh->nlmsg_len + NLA_ALIGN(NLA_HDRLEN + data_len); + const unsigned int NEW_SIZE = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + + NLA_ALIGN(NLA_HDRLEN + data_len); /* Check enough space for attribute */ - if (NEW_SIZE <= msg->nm_size) { - const int fam_hdrlen = msg->nm_nlh->nlmsg_len - NLMSG_HDRLEN; - msg->nm_nlh->nlmsg_len = NEW_SIZE; - nla = nlmsg_attrdata(msg->nm_nlh, fam_hdrlen); - nla->nla_type = attrtype; - nla->nla_len = NLA_HDRLEN + data_len; - } else - goto fail; + if (NEW_SIZE > msg->nm_size) + return NULL; + nla = (struct nlattr *)nlmsg_tail(msg->nm_nlh); + nla->nla_type = attrtype; + nla->nla_len = NLA_HDRLEN + data_len; + memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(data_len)); + msg->nm_nlh->nlmsg_len = NEW_SIZE; return nla; -fail: - return NULL; - } /* Copy attribute payload to another memory area. */ int nla_memcpy(void *dest, struct nlattr *src, int count) { - int rc; - void *ret_dest = memcpy(dest, nla_data(src), count); - if (!ret_dest) - return count; - else + if (!src || !dest) return 0; + if (count > nla_len(src)) + count = nla_len(src); + memcpy(dest, nla_data(src), count); + return count; } - - diff --git a/libnl_2/dbg.c b/libnl_2/dbg.c new file mode 100644 index 000000000..9764de6e7 --- /dev/null +++ b/libnl_2/dbg.c @@ -0,0 +1,12 @@ +#include "netlink/netlink.h" +#include + +void libnl_printf(int level, char *format, ...) +{ + va_list ap; + + level = ANDROID_LOG_ERROR; + va_start(ap, format); + __android_log_vprint(level, "libnl_2", format, ap); + va_end(ap); +} diff --git a/libnl_2/msg.c b/libnl_2/msg.c index d7276b7dd..283da6e94 100644 --- a/libnl_2/msg.c +++ b/libnl_2/msg.c @@ -91,39 +91,41 @@ struct nlmsghdr *nlmsg_hdr(struct nl_msg *n) struct nlattr *nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen) { unsigned char *data = nlmsg_data(nlh); - return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen)); + return (struct nlattr *)(data + NLMSG_ALIGN(hdrlen)); } /* Returns pointer to end of netlink message */ void *nlmsg_tail(const struct nlmsghdr *nlh) { - return (void *)((char *) nlh + nlh->nlmsg_len); + return (void *)((char *)nlh + NLMSG_ALIGN(nlh->nlmsg_len)); } /* Next netlink message in message stream */ struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining) { struct nlmsghdr *next_nlh = NULL; - if (*remaining > 0 && - nlmsg_len(nlh) <= *remaining && - nlmsg_len(nlh) >= (int) sizeof(struct nlmsghdr)) { - next_nlh = (struct nlmsghdr *) \ - ((char *) nlh + nlmsg_len(nlh)); + int len = nlmsg_len(nlh); - if (next_nlh && nlmsg_len(nlh) <= *remaining) { - *remaining -= nlmsg_len(nlh); - next_nlh = (struct nlmsghdr *) \ - ((char *) nlh + nlmsg_len(nlh)); - } + len = NLMSG_ALIGN(len); + if (*remaining > 0 && + len <= *remaining && + len >= (int) sizeof(struct nlmsghdr)) { + next_nlh = (struct nlmsghdr *)((char *)nlh + len); + *remaining -= len; } return next_nlh; } +int nlmsg_datalen(const struct nlmsghdr *nlh) +{ + return nlh->nlmsg_len - NLMSG_HDRLEN; +} + /* Length of attributes data */ int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen) { - return nlmsg_len(nlh) - NLMSG_HDRLEN - hdrlen; + return nlmsg_datalen(nlh) - NLMSG_ALIGN(hdrlen); } /* Length of netlink message */ @@ -145,9 +147,3 @@ int nlmsg_padlen(int payload) { return NLMSG_ALIGN(payload) - payload; } - -int nlmsg_datalen(const struct nlmsghdr *nlh) -{ - return nlh->nlmsg_len - NLMSG_HDRLEN; -} -