diff options
-rw-r--r-- | zebra/kernel_netlink.c | 67 | ||||
-rw-r--r-- | zebra/kernel_netlink.h | 37 |
2 files changed, 104 insertions, 0 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 35f3274c6..aa31883de 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -587,6 +587,21 @@ void netlink_parse_rtattr_nested(struct rtattr **tb, int max, netlink_parse_rtattr(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta)); } +bool nl_addraw_l(struct nlmsghdr *n, unsigned int maxlen, const void *data, + unsigned int len) +{ + if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { + zlog_err("ERROR message exceeded bound of %d\n", maxlen); + return false; + } + + memcpy(NLMSG_TAIL(n), data, len); + memset((uint8_t *)NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); + + return true; +} + bool nl_attr_put(struct nlmsghdr *n, unsigned int maxlen, int type, const void *data, unsigned int alen) { @@ -667,6 +682,58 @@ void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh) rtnh->rtnh_len = (uint8_t *)NLMSG_TAIL(n) - (uint8_t *)rtnh; } +bool nl_rta_put(struct rtattr *rta, unsigned int maxlen, int type, + const void *data, int alen) +{ + struct rtattr *subrta; + int len = RTA_LENGTH(alen); + + if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { + zlog_err("ERROR max allowed bound %d exceeded for rtattr", + maxlen); + return false; + } + subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; + if (alen) + memcpy(RTA_DATA(subrta), data, alen); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); + + return true; +} + +bool nl_rta_put16(struct rtattr *rta, unsigned int maxlen, int type, + uint16_t data) +{ + return nl_rta_put(rta, maxlen, type, &data, sizeof(uint16_t)); +} + +bool nl_rta_put64(struct rtattr *rta, unsigned int maxlen, int type, + uint64_t data) +{ + return nl_rta_put(rta, maxlen, type, &data, sizeof(uint64_t)); +} + +struct rtattr *nl_rta_nest(struct rtattr *rta, unsigned int maxlen, int type) +{ + struct rtattr *nest = RTA_TAIL(rta); + + if (nl_rta_put(rta, maxlen, type, NULL, 0)) + return NULL; + + nest->rta_type |= NLA_F_NESTED; + + return nest; +} + +int nl_rta_nest_end(struct rtattr *rta, struct rtattr *nest) +{ + nest->rta_len = (uint8_t *)RTA_TAIL(rta) - (uint8_t *)nest; + + return rta->rta_len; +} + const char *nl_msg_type_to_str(uint16_t msg_type) { return lookup_msg(nlmsg_str, msg_type, ""); diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 9421ea1c6..08cd706a9 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -90,6 +90,43 @@ extern void netlink_parse_rtattr_flags(struct rtattr **tb, int max, unsigned short flags); extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max, struct rtattr *rta); +/* + * nl_addraw_l copies raw form the netlink message buffer into netlink + * message header pointer. It ensures the aligned data buffer does not + * override past max length. + * return value is 0 if its successful + */ +extern bool nl_addraw_l(struct nlmsghdr *n, unsigned int maxlen, + const void *data, unsigned int len); +/* + * nl_rta_put - add an additional optional attribute(rtattr) to the + * Netlink message buffer. + * + * Returns true if the attribute could be added to the message (fits into the + * buffer), otherwise false is returned. + */ +extern bool nl_rta_put(struct rtattr *rta, unsigned int maxlen, int type, + const void *data, int alen); +extern bool nl_rta_put16(struct rtattr *rta, unsigned int maxlen, int type, + uint16_t data); +extern bool nl_rta_put64(struct rtattr *rta, unsigned int maxlen, int type, + uint64_t data); +/* + * nl_rta_nest - start an additional optional attribute (rtattr) nest. + * + * Returns a valid pointer to the beginning of the nest if the attribute + * describing the nest could be added to the message (fits into the buffer), + * otherwise NULL is returned. + */ +extern struct rtattr *nl_rta_nest(struct rtattr *rta, unsigned int maxlen, + int type); +/* + * nl_rta_nest_end - finalize nesting of an aditionl optionl attributes. + * + * Updates the length field of the attribute header to include the appeneded + * attributes. Returns a total length of the Netlink message. + */ +extern int nl_rta_nest_end(struct rtattr *rta, struct rtattr *nest); extern const char *nl_msg_type_to_str(uint16_t msg_type); extern const char *nl_rtproto_to_str(uint8_t rtproto); extern const char *nl_family_to_str(uint8_t family); |