diff --git a/sys/netlink/netlink_message_parser.h b/sys/netlink/netlink_message_parser.h --- a/sys/netlink/netlink_message_parser.h +++ b/sys/netlink/netlink_message_parser.h @@ -187,14 +187,20 @@ const void *arg, void *target); int nlattr_get_ipvia(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_chara(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); int nlattr_get_string(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_stringn(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_bytes(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); int nlattr_get_nla(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); int nlattr_get_nested(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target); +int nlattr_get_nested_ptr(struct nlattr *nla, struct nl_pstate *npt, + const void *arg, void *target); bool nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...); diff --git a/sys/netlink/netlink_message_parser.c b/sys/netlink/netlink_message_parser.c --- a/sys/netlink/netlink_message_parser.c +++ b/sys/netlink/netlink_message_parser.c @@ -428,6 +428,23 @@ return (nlattr_get_ifp_internal(nla, npt, target, true)); } +int +nlattr_get_chara(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target) +{ + int maxlen = NLA_DATA_LEN(nla); + int target_size = (size_t)arg; + int len = strnlen((char *)NLA_DATA(nla), maxlen); + + if (__predict_false(len >= maxlen) || __predict_false(len >= target_size)) { + NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not NULL-terminated or longer than %u", + nla->nla_type, maxlen, target_size); + return (EINVAL); + } + + strncpy((char *)target, (char *)NLA_DATA(nla), target_size); + return (0); +} + int nlattr_get_string(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target) { @@ -457,6 +474,20 @@ *((char **)target) = buf; return (0); } + +int +nlattr_get_bytes(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target) +{ + size_t size = (size_t)arg; + + if (NLA_DATA_LEN(nla) != size) + return (EINVAL); + + memcpy(target, NLA_DATA(nla), size); + + return (0); +} + int nlattr_get_nla(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target) { @@ -476,6 +507,17 @@ return (error); } +int +nlattr_get_nested_ptr(struct nlattr *nla, struct nl_pstate *npt, const void *arg, void *target) +{ + const struct nlhdr_parser *p = (const struct nlhdr_parser *)arg; + int error; + + /* Assumes target points to the beginning of the structure */ + error = nl_parse_header(NLA_DATA(nla), NLA_DATA_LEN(nla), p, npt, *(void **)target); + return (error); +} + int nlf_get_ifp(void *src, struct nl_pstate *npt, void *target) {