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