diff options
Diffstat (limited to 'lib/msg.c')
-rw-r--r-- | lib/msg.c | 68 |
1 files changed, 43 insertions, 25 deletions
@@ -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); |