summaryrefslogtreecommitdiffstats
path: root/lib/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/msg.c')
-rw-r--r--lib/msg.c68
1 files changed, 43 insertions, 25 deletions
diff --git a/lib/msg.c b/lib/msg.c
index 3d4fbc6..9fe9d54 100644
--- a/lib/msg.c
+++ b/lib/msg.c
@@ -6,11 +6,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup nl
+ * @ingroup core
* @defgroup msg Messages
* Netlink Message Construction/Parsing Interface
*
@@ -284,7 +284,7 @@ int nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen)
*/
int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
{
- return (remaining >= sizeof(struct nlmsghdr) &&
+ return (remaining >= (int)sizeof(struct nlmsghdr) &&
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
nlh->nlmsg_len <= remaining);
}
@@ -320,7 +320,7 @@ int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[],
int maxtype, struct nla_policy *policy)
{
if (!nlmsg_valid_hdr(nlh, hdrlen))
- return nl_errno(EINVAL);
+ return -NLE_MSG_TOOSHORT;
return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
nlmsg_attrlen(nlh, hdrlen), policy);
@@ -351,7 +351,7 @@ int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
struct nla_policy *policy)
{
if (!nlmsg_valid_hdr(nlh, hdrlen))
- return nl_errno(EINVAL);
+ return -NLE_MSG_TOOSHORT;
return nla_validate(nlmsg_attrdata(nlh, hdrlen),
nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
@@ -372,10 +372,14 @@ static struct nl_msg *__nlmsg_alloc(size_t len)
if (!nm)
goto errout;
- nm->nm_nlh = calloc(1, len);
+ nm->nm_refcnt = 1;
+
+ nm->nm_nlh = malloc(len);
if (!nm->nm_nlh)
goto errout;
+ memset(nm->nm_nlh, 0, sizeof(struct nlmsghdr));
+
nm->nm_protocol = -1;
nm->nm_size = len;
nm->nm_nlh->nlmsg_len = nlmsg_total_size(0);
@@ -385,7 +389,6 @@ static struct nl_msg *__nlmsg_alloc(size_t len)
return nm;
errout:
free(nm);
- nl_errno(ENOMEM);
return NULL;
}
@@ -517,10 +520,8 @@ void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
- if ((tlen + nlmsg_len) > n->nm_size) {
- nl_errno(ENOBUFS);
+ if ((tlen + nlmsg_len) > n->nm_size)
return NULL;
- }
buf += nlmsg_len;
n->nm_nlh->nlmsg_len += tlen;
@@ -552,7 +553,7 @@ int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
tmp = nlmsg_reserve(n, len, pad);
if (tmp == NULL)
- return nl_errno(ENOMEM);
+ return -NLE_NOMEM;
memcpy(tmp, data, len);
NL_DBG(2, "msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
@@ -579,11 +580,11 @@ int nlmsg_expand(struct nl_msg *n, size_t newlen)
void *tmp;
if (newlen <= n->nm_size)
- return nl_errno(EINVAL);
+ return -NLE_INVAL;
tmp = realloc(n->nm_nlh, newlen);
if (tmp == NULL)
- return nl_errno(ENOMEM);
+ return -NLE_NOMEM;
n->nm_nlh = tmp;
n->nm_size = newlen;
@@ -646,21 +647,39 @@ struct nlmsghdr *nlmsg_hdr(struct nl_msg *n)
}
/**
- * Free a netlink message
- * @arg n netlink message
- *
- * Destroys a netlink message and frees up all used memory.
+ * Acquire a reference on a netlink message
+ * @arg msg message to acquire reference from
+ */
+void nlmsg_get(struct nl_msg *msg)
+{
+ msg->nm_refcnt++;
+ NL_DBG(4, "New reference to message %p, total %d\n",
+ msg, msg->nm_refcnt);
+}
+
+/**
+ * Release a reference from an netlink message
+ * @arg msg message to release reference from
*
- * @pre The message must be unused.
+ * Frees memory after the last reference has been released.
*/
-void nlmsg_free(struct nl_msg *n)
+void nlmsg_free(struct nl_msg *msg)
{
- if (!n)
+ if (!msg)
return;
- free(n->nm_nlh);
- free(n);
- NL_DBG(2, "msg %p: Freed\n", n);
+ msg->nm_refcnt--;
+ NL_DBG(4, "Returned message reference %p, %d remaining\n",
+ msg, msg->nm_refcnt);
+
+ if (msg->nm_refcnt < 0)
+ BUG();
+
+ if (msg->nm_refcnt <= 0) {
+ free(msg->nm_nlh);
+ free(msg);
+ NL_DBG(2, "msg %p: Freed\n", msg);
+ }
}
/** @} */
@@ -821,8 +840,7 @@ int nl_msg_parse(struct nl_msg *msg, void (*cb)(struct nl_object *, void *),
ops = nl_cache_ops_associate(nlmsg_get_proto(msg),
nlmsg_hdr(msg)->nlmsg_type);
if (ops == NULL)
- return nl_error(ENOENT, "Unknown message type %d",
- nlmsg_hdr(msg)->nlmsg_type);
+ return -NLE_MSGTYPE_NOSUPPORT;
p.pp_arg = &x;
return nl_cache_parse(ops, NULL, nlmsg_hdr(msg), &p);