Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
core: support receiving multipart objects
In order to support an upcoming patch implementing support for
requesting bridge vlan information for a single interface, a
modification to the pickup code is needed to allow handling of multipart
messages.

Based on the implementation of the bridge vlan dumping code in the
kernel, information relating to a single interface may not all be
contained within a single message. If the maximum message size is
exceeded before all entries can be filled in, a new message will be
started with the same ifindex but containing the remaining entries.

The code is currently only designed for handling netlink responses where
the provided parser function will be called a maximum of one time. This
is based on the assumption that all data relating to an object will be
contained within a single response message. If multiple messages are
received and the parser function is invoked multiple times, previously
stored objects will be leaked and the resulting object will only contain
information from the last parsed message.

In order to handle the case where multiple messages need to be parsed to
construct a single object, use the already existing oo_update function
that may be defined for an object. The function will be called to merge
partial objects (that are the result of each invocation of the parser
function) together into a single object that is returned at the end.
  • Loading branch information
ronand-atl committed Nov 12, 2024
commit 1ee03764bd660ad4f67365257c2e935e2843d7ca
3 changes: 2 additions & 1 deletion include/netlink/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ extern "C" {
#define NLE_IMMUTABLE 32
#define NLE_DUMP_INTR 33
#define NLE_ATTRSIZE 34
#define NLE_MERGE_FAILURE 35

#define NLE_MAX NLE_ATTRSIZE
#define NLE_MAX NLE_MERGE_FAILURE

extern const char * nl_geterror(int);
extern void nl_perror(int, const char *);
Expand Down
1 change: 1 addition & 0 deletions lib/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static const char *errmsg[NLE_MAX+1] = {
[NLE_IMMUTABLE] = "Immutable attribute",
[NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted",
[NLE_ATTRSIZE] = "Attribute max length exceeded",
[NLE_MERGE_FAILURE] = "Unable to merge objects",
};

/**
Expand Down
41 changes: 31 additions & 10 deletions lib/nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,12 +1137,21 @@ struct pickup_param
static int __store_answer(struct nl_object *obj, struct nl_parser_param *p)
{
struct pickup_param *pp = p->pp_arg;
/*
* the parser will put() the object at the end, expecting the cache
* to take the reference.
*/
nl_object_get(obj);
pp->result = obj;

if (pp->result == NULL) {
/* The parser will put() the object at the end, expecting the
* cache to take the reference. This line ensures the object
* won't get deleted when that happens.
*/
nl_object_get(obj);

pp->result = obj;

return 0;
}

if (nl_object_update(pp->result, obj) < 0)
return -NLE_MERGE_FAILURE;

return 0;
}
Expand All @@ -1168,11 +1177,15 @@ static int __pickup_answer_syserr(struct sockaddr_nl *nla, struct nlmsgerr *nler
/** @endcond */

/**
* Pickup netlink answer, parse is and return object
* Pickup netlink answer, parse it and return an object
* @arg sk Netlink socket
* @arg parser Parser function to parse answer
* @arg result Result pointer to return parsed object
*
* @note If this function returns success, result may be NULL, so the caller
* should check that before accessing the result. This can happen if the
* kernel doesn't return any object data and reports success.
*
* @return 0 on success or a negative error code.
*/
int nl_pickup(struct nl_sock *sk,
Expand All @@ -1184,11 +1197,17 @@ int nl_pickup(struct nl_sock *sk,
}

/**
* Pickup netlink answer, parse is and return object with preserving system error
* Pickup netlink answer, parse it and return the object while preserving the
* system error
* @arg sk Netlink socket
* @arg parser Parser function to parse answer
* @arg result Result pointer to return parsed object
* @arg syserr Result pointer for the system error in case of failure
* @arg syserror Result pointer for the system error in case of failure
* (optional)
*
* @note If this function returns success, result may be NULL, so the caller
* should check that before accessing the result. This can happen if the
* kernel doesn't return any object data and reports success.
*
* @return 0 on success or a negative error code.
*/
Expand Down Expand Up @@ -1216,8 +1235,10 @@ int nl_pickup_keep_syserr(struct nl_sock *sk,
}

err = nl_recvmsgs(sk, cb);
if (err < 0)
if (err < 0) {
nl_object_put(pp.result);
goto errout;
}

*result = pp.result;
errout:
Expand Down