Skip to content

Commit 1ee0376

Browse files
committed
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.
1 parent f9383d7 commit 1ee0376

File tree

3 files changed

+34
-11
lines changed

3 files changed

+34
-11
lines changed

include/netlink/errno.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ extern "C" {
4545
#define NLE_IMMUTABLE 32
4646
#define NLE_DUMP_INTR 33
4747
#define NLE_ATTRSIZE 34
48+
#define NLE_MERGE_FAILURE 35
4849

49-
#define NLE_MAX NLE_ATTRSIZE
50+
#define NLE_MAX NLE_MERGE_FAILURE
5051

5152
extern const char * nl_geterror(int);
5253
extern void nl_perror(int, const char *);

lib/error.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static const char *errmsg[NLE_MAX+1] = {
4343
[NLE_IMMUTABLE] = "Immutable attribute",
4444
[NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted",
4545
[NLE_ATTRSIZE] = "Attribute max length exceeded",
46+
[NLE_MERGE_FAILURE] = "Unable to merge objects",
4647
};
4748

4849
/**

lib/nl.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,12 +1137,21 @@ struct pickup_param
11371137
static int __store_answer(struct nl_object *obj, struct nl_parser_param *p)
11381138
{
11391139
struct pickup_param *pp = p->pp_arg;
1140-
/*
1141-
* the parser will put() the object at the end, expecting the cache
1142-
* to take the reference.
1143-
*/
1144-
nl_object_get(obj);
1145-
pp->result = obj;
1140+
1141+
if (pp->result == NULL) {
1142+
/* The parser will put() the object at the end, expecting the
1143+
* cache to take the reference. This line ensures the object
1144+
* won't get deleted when that happens.
1145+
*/
1146+
nl_object_get(obj);
1147+
1148+
pp->result = obj;
1149+
1150+
return 0;
1151+
}
1152+
1153+
if (nl_object_update(pp->result, obj) < 0)
1154+
return -NLE_MERGE_FAILURE;
11461155

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

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

11861199
/**
1187-
* Pickup netlink answer, parse is and return object with preserving system error
1200+
* Pickup netlink answer, parse it and return the object while preserving the
1201+
* system error
11881202
* @arg sk Netlink socket
11891203
* @arg parser Parser function to parse answer
11901204
* @arg result Result pointer to return parsed object
1191-
* @arg syserr Result pointer for the system error in case of failure
1205+
* @arg syserror Result pointer for the system error in case of failure
1206+
* (optional)
1207+
*
1208+
* @note If this function returns success, result may be NULL, so the caller
1209+
* should check that before accessing the result. This can happen if the
1210+
* kernel doesn't return any object data and reports success.
11921211
*
11931212
* @return 0 on success or a negative error code.
11941213
*/
@@ -1216,8 +1235,10 @@ int nl_pickup_keep_syserr(struct nl_sock *sk,
12161235
}
12171236

12181237
err = nl_recvmsgs(sk, cb);
1219-
if (err < 0)
1238+
if (err < 0) {
1239+
nl_object_put(pp.result);
12201240
goto errout;
1241+
}
12211242

12221243
*result = pp.result;
12231244
errout:

0 commit comments

Comments
 (0)