diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c index 4014d3cbe..f1a9f7aaa 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c @@ -1,7 +1,8 @@ /* * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG - * Copyright (C) 2008 Tobias Brunner + * + * Copyright (C) 2008-2019 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -687,8 +688,8 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, return &this->public; } -/** - * Described in header. +/* + * Described in header */ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, size_t buflen) @@ -709,9 +710,10 @@ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, } /** - * Described in header. + * Add an attribute to the given Netlink message */ -void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len) +static struct rtattr *add_rtattr(struct nlmsghdr *hdr, int buflen, int type, + int len) { struct rtattr *rta; @@ -725,6 +727,43 @@ void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len) rta->rta_type = type; rta->rta_len = RTA_LENGTH(len); hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); + return rta; +} +/* + * Described in header + */ +void *netlink_nested_start(struct nlmsghdr *hdr, size_t buflen, int type) +{ + return add_rtattr(hdr, buflen, type, 0); +} + +/* + * Described in header + */ +void netlink_nested_end(struct nlmsghdr *hdr, void *attr) +{ + struct rtattr *rta = attr; + void *end; + + if (attr) + { + end = (char*)hdr + NLMSG_ALIGN(hdr->nlmsg_len); + rta->rta_len = end - attr; + } +} + +/* + * Described in header + */ +void *netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len) +{ + struct rtattr *rta; + + rta = add_rtattr(hdr, buflen, type, len); + if (!rta) + { + return NULL; + } return RTA_DATA(rta); } diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h index 82dce4c5c..d68a013de 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008-2019 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -90,6 +90,28 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, size_t buflen); +/** + * Creates an rtattr under which other rtattrs are nested to the given netlink + * message. + * + * The returned pointer has to be passed to netlink_nested_end() after the + * nested attributes have been added to the message. + * + * @param hdr netlink message + * @param buflen size of full netlink buffer + * @param type RTA type + * @return attribute pointer + */ +void *netlink_nested_start(struct nlmsghdr *hdr, size_t buflen, int type); + +/** + * Updates the length of the given attribute after nested attributes were added. + * + * @param hdr netlink message + * @param attr attribute returned from netlink_nested_start() + */ +void netlink_nested_end(struct nlmsghdr *hdr, void *attr); + /** * Reserve space in a netlink message for given size and type, returning buffer. *