Commit | Line | Data |
---|---|---|
01b39b50 AG |
1 | #include <linux/kernel.h> |
2 | #include <net/netlink.h> | |
3 | #include <linux/drbd_genl_api.h> | |
4 | #include "drbd_nla.h" | |
5 | ||
6 | static int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla) | |
7 | { | |
8 | struct nlattr *head = nla_data(nla); | |
9 | int len = nla_len(nla); | |
10 | int rem; | |
11 | ||
12 | /* | |
13 | * validate_nla (called from nla_parse_nested) ignores attributes | |
14 | * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag. | |
15 | * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY | |
16 | * flag set also, check and remove that flag before calling | |
17 | * nla_parse_nested. | |
18 | */ | |
19 | ||
20 | nla_for_each_attr(nla, head, len, rem) { | |
21 | if (nla->nla_type & DRBD_GENLA_F_MANDATORY) { | |
22 | nla->nla_type &= ~DRBD_GENLA_F_MANDATORY; | |
23 | if (nla_type(nla) > maxtype) | |
24 | return -EOPNOTSUPP; | |
25 | } | |
26 | } | |
27 | return 0; | |
28 | } | |
29 | ||
30 | int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, | |
31 | const struct nla_policy *policy) | |
32 | { | |
33 | int err; | |
34 | ||
35 | err = drbd_nla_check_mandatory(maxtype, nla); | |
36 | if (!err) | |
37 | err = nla_parse_nested(tb, maxtype, nla, policy); | |
38 | ||
39 | return err; | |
40 | } | |
41 | ||
42 | struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype) | |
43 | { | |
44 | int err; | |
45 | /* | |
46 | * If any nested attribute has the DRBD_GENLA_F_MANDATORY flag set and | |
47 | * we don't know about that attribute, reject all the nested | |
48 | * attributes. | |
49 | */ | |
50 | err = drbd_nla_check_mandatory(maxtype, nla); | |
51 | if (err) | |
52 | return ERR_PTR(err); | |
53 | return nla_find_nested(nla, attrtype); | |
54 | } |