@@ -24,11 +24,10 @@
struct command {
unsigned int id;
- uint32_t seq;
- uint32_t len;
l_netlink_command_func_t handler;
l_netlink_destroy_func_t destroy;
void *user_data;
+ struct l_netlink_message *message;
};
struct notify {
@@ -61,6 +60,7 @@ static void destroy_command(void *data)
if (command->destroy)
command->destroy(command->user_data);
+ l_netlink_message_unref(command->message);
l_free(command);
}
@@ -85,8 +85,8 @@ static bool can_write_data(struct l_io *io, void *user_data)
{
struct l_netlink *netlink = user_data;
struct command *command;
+ struct nlmsghdr *hdr;
struct sockaddr_nl addr;
- const void *data;
ssize_t written;
int sk;
@@ -94,28 +94,27 @@ static bool can_write_data(struct l_io *io, void *user_data)
if (!command)
return false;
+ hdr = command->message->hdr;
sk = l_io_get_fd(io);
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = 0;
- data = ((void *) command) + NLMSG_ALIGN(sizeof(struct command));
-
- written = sendto(sk, data, command->len, 0,
- (struct sockaddr *) &addr, sizeof(addr));
- if (written < 0 || (uint32_t) written != command->len) {
+ written = sendto(sk, hdr, hdr->nlmsg_len, 0,
+ (struct sockaddr *) &addr, sizeof(addr));
+ if (written < 0 || (uint32_t) written != hdr->nlmsg_len) {
l_hashmap_remove(netlink->command_lookup,
L_UINT_TO_PTR(command->id));
destroy_command(command);
return true;
}
- l_util_hexdump(false, data, command->len,
+ l_util_hexdump(false, hdr, hdr->nlmsg_len,
netlink->debug_handler, netlink->debug_data);
l_hashmap_insert(netlink->command_pending,
- L_UINT_TO_PTR(command->seq), command);
+ L_UINT_TO_PTR(hdr->nlmsg_seq), command);
return l_queue_length(netlink->command_queue) > 0;
}
@@ -399,70 +398,55 @@ LIB_EXPORT void l_netlink_destroy(struct l_netlink *netlink)
}
LIB_EXPORT unsigned int l_netlink_send(struct l_netlink *netlink,
- uint16_t type, uint16_t flags, const void *data,
- uint32_t len, l_netlink_command_func_t function,
- void *user_data, l_netlink_destroy_func_t destroy)
+ struct l_netlink_message *message,
+ l_netlink_command_func_t function,
+ void *user_data,
+ l_netlink_destroy_func_t destroy)
{
struct command *command;
+ uint16_t extra_flags = NLM_F_REQUEST;
struct nlmsghdr *nlmsg;
- size_t size;
if (unlikely(!netlink))
return 0;
- if (flags & 0xff)
+ if (unlikely(message->nest_level))
return 0;
if (function)
- flags |= NLM_F_ACK;
+ extra_flags |= NLM_F_ACK;
- size = NLMSG_ALIGN(sizeof(struct command)) +
- NLMSG_HDRLEN + NLMSG_ALIGN(len);
+ command = l_new(struct command, 1);
- command = l_malloc(size);
+ if (!l_hashmap_insert(netlink->command_lookup,
+ L_UINT_TO_PTR(netlink->next_command_id),
+ command)) {
+ l_free(command);
+ return 0;
+ }
- memset(command, 0, size);
command->handler = function;
command->destroy = destroy;
command->user_data = user_data;
+ command->id = netlink->next_command_id++;
+ command->message = message;
+ message->sealed = true;
- command->id = netlink->next_command_id;
-
- if (!l_hashmap_insert(netlink->command_lookup,
- L_UINT_TO_PTR(command->id), command))
- goto free_command;
-
- command->seq = netlink->next_seq++;
- command->len = NLMSG_HDRLEN + NLMSG_ALIGN(len);
-
- nlmsg = ((void *) command) + NLMSG_ALIGN(sizeof(struct command));
-
- nlmsg->nlmsg_len = command->len;
- nlmsg->nlmsg_type = type;
- nlmsg->nlmsg_flags = NLM_F_REQUEST | flags;
- nlmsg->nlmsg_seq = command->seq;
+ nlmsg = message->hdr;
+ nlmsg->nlmsg_flags |= extra_flags;
+ nlmsg->nlmsg_seq = netlink->next_seq++;
nlmsg->nlmsg_pid = netlink->pid;
- if (data && len > 0)
- memcpy(((void *) nlmsg) + NLMSG_HDRLEN, data, len);
-
l_queue_push_tail(netlink->command_queue, command);
-
l_io_set_write_handler(netlink->io, can_write_data, netlink, NULL);
- netlink->next_command_id++;
-
return command->id;
-
-free_command:
- l_free(command);
-
- return 0;
}
LIB_EXPORT bool l_netlink_cancel(struct l_netlink *netlink, unsigned int id)
{
struct command *command;
+ struct nlmsghdr *hdr;
if (unlikely(!netlink || !id))
return false;
@@ -471,9 +455,11 @@ LIB_EXPORT bool l_netlink_cancel(struct l_netlink *netlink, unsigned int id)
if (!command)
return false;
+ hdr = command->message->hdr;
+
if (!l_queue_remove(netlink->command_queue, command)) {
l_hashmap_remove(netlink->command_pending,
- L_UINT_TO_PTR(command->seq));
+ L_UINT_TO_PTR(hdr->nlmsg_seq));
}
destroy_command(command);
@@ -25,14 +25,16 @@ typedef void (*l_netlink_notify_func_t) (uint16_t type, const void *data,
typedef void (*l_netlink_destroy_func_t) (void *user_data);
struct l_netlink;
+struct l_netlink_message;
struct l_netlink *l_netlink_new(int protocol);
void l_netlink_destroy(struct l_netlink *netlink);
unsigned int l_netlink_send(struct l_netlink *netlink,
- uint16_t type, uint16_t flags, const void *data,
- uint32_t len, l_netlink_command_func_t function,
- void *user_data, l_netlink_destroy_func_t destroy);
+ struct l_netlink_message *message,
+ l_netlink_command_func_t function,
+ void *user_data,
+ l_netlink_destroy_func_t destroy);
bool l_netlink_cancel(struct l_netlink *netlink, unsigned int id);
unsigned int l_netlink_register(struct l_netlink *netlink,
@@ -641,63 +641,6 @@ LIB_EXPORT bool l_rtnl_route_set_scope(struct l_rtnl_route *rt, uint8_t scope)
return true;
}
-static size_t rta_add_u8(void *rta_buf, unsigned short type, uint8_t value)
-{
- struct rtattr *rta = rta_buf;
-
- rta->rta_len = RTA_LENGTH(sizeof(uint8_t));
- rta->rta_type = type;
- *((uint8_t *) RTA_DATA(rta)) = value;
-
- return RTA_SPACE(sizeof(uint8_t));
-}
-
-static size_t rta_add_u32(void *rta_buf, unsigned short type, uint32_t value)
-{
- struct rtattr *rta = rta_buf;
-
- rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
- rta->rta_type = type;
- *((uint32_t *) RTA_DATA(rta)) = value;
-
- return RTA_SPACE(sizeof(uint32_t));
-}
-
-static size_t rta_add_data(void *rta_buf, unsigned short type, const void *data,
- size_t data_len)
-{
- struct rtattr *rta = rta_buf;
-
- rta->rta_len = RTA_LENGTH(data_len);
- rta->rta_type = type;
- memcpy(RTA_DATA(rta), data, data_len);
-
- return RTA_SPACE(data_len);
-}
-
-static size_t rta_add_address(void *rta_buf, unsigned short type,
- uint8_t family,
- const struct in6_addr *v6,
- const struct in_addr *v4)
-{
- struct rtattr *rta = rta_buf;
-
- rta->rta_type = type;
-
- switch (family) {
- case AF_INET6:
- rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
- memcpy(RTA_DATA(rta), v6, sizeof(struct in6_addr));
- return RTA_SPACE(sizeof(struct in6_addr));
- case AF_INET:
- rta->rta_len = RTA_LENGTH(sizeof(struct in_addr));
- memcpy(RTA_DATA(rta), v4, sizeof(struct in_addr));
- return RTA_SPACE(sizeof(struct in_addr));
- }
-
- return 0;
-}
-
static int append_address(struct l_netlink_message *nlm, uint16_t type,
uint8_t family,
const struct in6_addr *v6,
@@ -786,31 +729,18 @@ LIB_EXPORT uint32_t l_rtnl_set_linkmode_and_operstate(struct l_netlink *rtnl,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct ifinfomsg *rtmmsg;
- void *rta_buf;
- size_t bufsize;
- uint32_t id;
-
- bufsize = NLMSG_ALIGN(sizeof(struct ifinfomsg)) +
- RTA_SPACE(sizeof(uint8_t)) + RTA_SPACE(sizeof(uint8_t));
-
- rtmmsg = l_malloc(bufsize);
- memset(rtmmsg, 0, bufsize);
-
- rtmmsg->ifi_family = AF_UNSPEC;
- rtmmsg->ifi_index = ifindex;
+ struct l_netlink_message *nlm = l_netlink_message_new(RTM_SETLINK, 0);
+ struct ifinfomsg ifi;
- rta_buf = (void *) rtmmsg + NLMSG_ALIGN(sizeof(struct ifinfomsg));
+ memset(&ifi, 0, sizeof(ifi));
+ ifi.ifi_family = AF_UNSPEC;
+ ifi.ifi_index = ifindex;
- rta_buf += rta_add_u8(rta_buf, IFLA_LINKMODE, linkmode);
- rta_buf += rta_add_u8(rta_buf, IFLA_OPERSTATE, operstate);
+ l_netlink_message_add_header(nlm, &ifi, sizeof(ifi));
+ l_netlink_message_append_u8(nlm, IFLA_LINKMODE, linkmode);
+ l_netlink_message_append_u8(nlm, IFLA_OPERSTATE, operstate);
- id = l_netlink_send(rtnl, RTM_SETLINK, 0, rtmmsg,
- rta_buf - (void *) rtmmsg,
- cb, user_data, destroy);
- l_free(rtmmsg);
-
- return id;
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_set_mac(struct l_netlink *rtnl, int ifindex,
@@ -820,34 +750,22 @@ LIB_EXPORT uint32_t l_rtnl_set_mac(struct l_netlink *rtnl, int ifindex,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct ifinfomsg *rtmmsg;
- void *rta_buf;
- size_t bufsize;
- uint32_t id;
-
- bufsize = NLMSG_ALIGN(sizeof(struct ifinfomsg)) + RTA_SPACE(6);
+ struct l_netlink_message *nlm = l_netlink_message_new(RTM_SETLINK, 0);
+ struct ifinfomsg ifi;
- rtmmsg = l_malloc(bufsize);
- memset(rtmmsg, 0, bufsize);
-
- rtmmsg->ifi_family = AF_UNSPEC;
- rtmmsg->ifi_index = ifindex;
+ memset(&ifi, 0, sizeof(ifi));
+ ifi.ifi_family = AF_UNSPEC;
+ ifi.ifi_index = ifindex;
if (power_up) {
- rtmmsg->ifi_change = IFF_UP;
- rtmmsg->ifi_flags = IFF_UP;
+ ifi.ifi_change = IFF_UP;
+ ifi.ifi_flags = IFF_UP;
}
- rta_buf = (void *) rtmmsg + NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
- rta_buf += rta_add_data(rta_buf, IFLA_ADDRESS, (void *) addr, 6);
+ l_netlink_message_add_header(nlm, &ifi, sizeof(ifi));
+ l_netlink_message_append_mac(nlm, IFLA_ADDRESS, addr);
- id = l_netlink_send(rtnl, RTM_SETLINK, 0, rtmmsg,
- rta_buf - (void *) rtmmsg,
- cb, user_data, destroy);
- l_free(rtmmsg);
-
- return id;
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_set_powered(struct l_netlink *rtnl, int ifindex,
@@ -855,25 +773,18 @@ LIB_EXPORT uint32_t l_rtnl_set_powered(struct l_netlink *rtnl, int ifindex,
l_netlink_command_func_t cb, void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct ifinfomsg *rtmmsg;
- size_t bufsize;
- uint32_t id;
-
- bufsize = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
- rtmmsg = l_malloc(bufsize);
- memset(rtmmsg, 0, bufsize);
+ struct l_netlink_message *nlm = l_netlink_message_new(RTM_SETLINK, 0);
+ struct ifinfomsg ifi;
- rtmmsg->ifi_family = AF_UNSPEC;
- rtmmsg->ifi_index = ifindex;
- rtmmsg->ifi_change = IFF_UP;
- rtmmsg->ifi_flags = powered ? IFF_UP : 0;
+ memset(&ifi, 0, sizeof(ifi));
+ ifi.ifi_family = AF_UNSPEC;
+ ifi.ifi_index = ifindex;
+ ifi.ifi_change = IFF_UP;
+ ifi.ifi_flags = powered ? IFF_UP : 0;
- id = l_netlink_send(rtnl, RTM_SETLINK, 0, rtmmsg, bufsize,
- cb, user_data, destroy);
- l_free(rtmmsg);
+ l_netlink_message_add_header(nlm, &ifi, sizeof(ifi));
- return id;
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT void l_rtnl_ifaddr4_extract(const struct ifaddrmsg *ifa, int bytes,
@@ -919,21 +830,17 @@ LIB_EXPORT uint32_t l_rtnl_ifaddr4_dump(struct l_netlink *rtnl,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct ifaddrmsg *rtmmsg;
- uint32_t id;
-
- rtmmsg = l_malloc(sizeof(struct ifaddrmsg));
- memset(rtmmsg, 0, sizeof(struct ifaddrmsg));
-
- rtmmsg->ifa_family = AF_INET;
+ struct ifaddrmsg ifa;
+ struct l_netlink_message *nlm =
+ l_netlink_message_new_sized(RTM_GETADDR,
+ NLM_F_DUMP, sizeof(ifa));
- id = l_netlink_send(rtnl, RTM_GETADDR, NLM_F_DUMP, rtmmsg,
- sizeof(struct ifaddrmsg), cb, user_data,
- destroy);
+ memset(&ifa, 0, sizeof(ifa));
+ ifa.ifa_family = AF_INET;
- l_free(rtmmsg);
+ l_netlink_message_add_header(nlm, &ifa, sizeof(ifa));
- return id;
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_ifaddr4_add(struct l_netlink *rtnl, int ifindex,
@@ -984,14 +891,17 @@ LIB_EXPORT uint32_t l_rtnl_route4_dump(struct l_netlink *rtnl,
l_netlink_command_func_t cb, void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct rtmsg rtmsg;
+ struct rtmsg rtm;
+ struct l_netlink_message *nlm =
+ l_netlink_message_new_sized(RTM_GETROUTE,
+ NLM_F_DUMP, sizeof(rtm));
- memset(&rtmsg, 0, sizeof(struct rtmsg));
- rtmsg.rtm_family = AF_INET;
+ memset(&rtm, 0, sizeof(rtm));
+ rtm.rtm_family = AF_INET;
- return l_netlink_send(rtnl, RTM_GETROUTE, NLM_F_DUMP, &rtmsg,
- sizeof(struct rtmsg), cb, user_data,
- destroy);
+ l_netlink_message_add_header(nlm, &rtm, sizeof(rtm));
+
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_route4_add_connected(struct l_netlink *rtnl,
@@ -1075,21 +985,17 @@ LIB_EXPORT uint32_t l_rtnl_ifaddr6_dump(struct l_netlink *rtnl,
l_netlink_command_func_t cb, void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct ifaddrmsg *rtmmsg;
- uint32_t id;
-
- rtmmsg = l_malloc(sizeof(struct ifaddrmsg));
- memset(rtmmsg, 0, sizeof(struct ifaddrmsg));
-
- rtmmsg->ifa_family = AF_INET6;
+ struct ifaddrmsg ifa;
+ struct l_netlink_message *nlm =
+ l_netlink_message_new_sized(RTM_GETADDR,
+ NLM_F_DUMP, sizeof(ifa));
- id = l_netlink_send(rtnl, RTM_GETADDR, NLM_F_DUMP, rtmmsg,
- sizeof(struct ifaddrmsg), cb, user_data,
- destroy);
+ memset(&ifa, 0, sizeof(ifa));
+ ifa.ifa_family = AF_INET6;
- l_free(rtmmsg);
+ l_netlink_message_add_header(nlm, &ifa, sizeof(ifa));
- return id;
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_ifaddr6_add(struct l_netlink *rtnl, int ifindex,
@@ -1131,14 +1037,17 @@ LIB_EXPORT uint32_t l_rtnl_route6_dump(struct l_netlink *rtnl,
l_netlink_command_func_t cb, void *user_data,
l_netlink_destroy_func_t destroy)
{
- struct rtmsg rtmsg;
+ struct rtmsg rtm;
+ struct l_netlink_message *nlm =
+ l_netlink_message_new_sized(RTM_GETROUTE,
+ NLM_F_DUMP, sizeof(rtm));
- memset(&rtmsg, 0, sizeof(struct rtmsg));
- rtmsg.rtm_family = AF_INET6;
+ memset(&rtm, 0, sizeof(rtm));
+ rtm.rtm_family = AF_INET6;
- return l_netlink_send(rtnl, RTM_GETROUTE, NLM_F_DUMP, &rtmsg,
- sizeof(struct rtmsg), cb, user_data,
- destroy);
+ l_netlink_message_add_header(nlm, &rtm, sizeof(rtm));
+
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_route6_add_gateway(struct l_netlink *rtnl,
@@ -1187,84 +1096,6 @@ LIB_EXPORT uint32_t l_rtnl_route6_delete_gateway(struct l_netlink *rtnl,
return r;
}
-static uint32_t _rtnl_ifaddr_change(struct l_netlink *rtnl, uint16_t nlmsg_type,
- int ifindex,
- const struct l_rtnl_address *addr,
- l_netlink_command_func_t cb,
- void *user_data,
- l_netlink_destroy_func_t destroy)
-{
- struct ifaddrmsg *ifamsg;
- void *buf;
- size_t bufsize;
- uint32_t id;
- int flags = 0;
- uint64_t now = l_time_now();
-
- if (nlmsg_type == RTM_NEWADDR)
- flags = NLM_F_CREATE | NLM_F_REPLACE;
-
- bufsize = NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
- RTA_SPACE(sizeof(struct in6_addr)) +
- RTA_SPACE(sizeof(struct in_addr)) +
- RTA_SPACE(sizeof(uint32_t)) +
- RTA_SPACE(IFNAMSIZ) +
- RTA_SPACE(sizeof(struct ifa_cacheinfo));
-
- ifamsg = l_malloc(bufsize);
- memset(ifamsg, 0, bufsize);
-
- ifamsg->ifa_index = ifindex;
- ifamsg->ifa_family = addr->family;
- ifamsg->ifa_scope = addr->scope;
- ifamsg->ifa_prefixlen = addr->prefix_len;
- /* Kernel ignores legacy flags in IFA_FLAGS, so set them here */
- ifamsg->ifa_flags = addr->flags & 0xff;
-
- buf = (void *) ifamsg + NLMSG_ALIGN(sizeof(struct ifaddrmsg));
-
- if (addr->family == AF_INET) {
- buf += rta_add_data(buf, IFA_LOCAL, &addr->in_addr,
- sizeof(struct in_addr));
- buf += rta_add_data(buf, IFA_BROADCAST, &addr->broadcast,
- sizeof(struct in_addr));
- } else
- buf += rta_add_data(buf, IFA_LOCAL, &addr->in6_addr,
- sizeof(struct in6_addr));
-
- /* Address & Prefix length are enough to perform deletions */
- if (nlmsg_type == RTM_DELADDR)
- goto done;
-
- if (addr->flags & 0xffffff00)
- buf += rta_add_u32(buf, IFA_FLAGS, addr->flags & 0xffffff00);
-
- if (addr->label[0])
- buf += rta_add_data(buf, IFA_LABEL,
- addr->label, strlen(addr->label) + 1);
-
- if (addr->preferred_expiry_time > now ||
- addr->valid_expiry_time > now) {
- struct ifa_cacheinfo cinfo;
-
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.ifa_prefered = addr->preferred_expiry_time > now ?
- l_time_to_secs(addr->preferred_expiry_time - now) : 0;
- cinfo.ifa_valid = addr->valid_expiry_time > now ?
- l_time_to_secs(addr->valid_expiry_time - now) : 0;
-
- buf += rta_add_data(buf, IFA_CACHEINFO, &cinfo, sizeof(cinfo));
- }
-
-done:
- id = l_netlink_send(rtnl, nlmsg_type, flags,
- ifamsg, buf - (void *) ifamsg,
- cb, user_data, destroy);
- l_free(ifamsg);
-
- return id;
-}
-
LIB_EXPORT struct l_rtnl_address *l_rtnl_ifaddr_extract(
const struct ifaddrmsg *ifa,
int bytes)
@@ -1324,8 +1155,12 @@ LIB_EXPORT uint32_t l_rtnl_ifaddr_add(struct l_netlink *rtnl, int ifindex,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- return _rtnl_ifaddr_change(rtnl, RTM_NEWADDR, ifindex, addr,
- cb, user_data, destroy);
+ struct l_netlink_message *nlm =
+ rtnl_message_from_address(RTM_NEWADDR,
+ NLM_F_CREATE | NLM_F_REPLACE,
+ ifindex, addr);
+
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_ifaddr_delete(struct l_netlink *rtnl, int ifindex,
@@ -1334,84 +1169,10 @@ LIB_EXPORT uint32_t l_rtnl_ifaddr_delete(struct l_netlink *rtnl, int ifindex,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- return _rtnl_ifaddr_change(rtnl, RTM_DELADDR, ifindex, addr,
- cb, user_data, destroy);
-}
+ struct l_netlink_message *nlm =
+ rtnl_message_from_address(RTM_DELADDR, 0, ifindex, addr);
-static uint32_t _rtnl_route_change(struct l_netlink *rtnl,
- uint16_t nlmsg_type, int ifindex,
- const struct l_rtnl_route *rt,
- l_netlink_command_func_t cb,
- void *user_data,
- l_netlink_destroy_func_t destroy)
-{
- L_AUTO_FREE_VAR(struct rtmsg *, rtmmsg) = NULL;
- size_t bufsize;
- void *rta_buf;
- uint16_t flags;
- uint64_t now = l_time_now();
-
- bufsize = NLMSG_ALIGN(sizeof(struct rtmsg)) +
- RTA_SPACE(sizeof(uint32_t)) + /* RTA_OIF */
- RTA_SPACE(sizeof(uint32_t)) + /* RTA_PRIORITY */
- RTA_SPACE(sizeof(struct in6_addr)) + /* RTA_GATEWAY */
- RTA_SPACE(sizeof(struct in6_addr)) + /* RTA_DST */
- RTA_SPACE(sizeof(struct in6_addr)) + /* RTA_PREFSRC */
- 256 + /* RTA_METRICS */
- RTA_SPACE(sizeof(uint8_t)) + /* RTA_PREF */
- RTA_SPACE(sizeof(uint32_t)); /* RTA_EXPIRES */
-
- rtmmsg = l_malloc(bufsize);
- memset(rtmmsg, 0, bufsize);
-
- rtmmsg->rtm_family = rt->family;
- rtmmsg->rtm_table = RT_TABLE_MAIN;
- rtmmsg->rtm_protocol = rt->protocol;
- rtmmsg->rtm_type = RTN_UNICAST;
- rtmmsg->rtm_scope = rt->scope;
-
- flags = NLM_F_CREATE | NLM_F_REPLACE;
-
- rta_buf = (void *) rtmmsg + NLMSG_ALIGN(sizeof(struct rtmsg));
- rta_buf += rta_add_u32(rta_buf, RTA_OIF, ifindex);
-
- if (rt->priority)
- rta_buf += rta_add_u32(rta_buf, RTA_PRIORITY,
- rt->priority + ifindex);
-
- if (!address_is_null(rt->family, &rt->gw.in_addr, &rt->gw.in6_addr))
- rta_buf += rta_add_address(rta_buf, RTA_GATEWAY, rt->family,
- &rt->gw.in6_addr, &rt->gw.in_addr);
-
- if (rt->dst_prefix_len) {
- rtmmsg->rtm_dst_len = rt->dst_prefix_len;
- rta_buf += rta_add_address(rta_buf, RTA_DST, rt->family,
- &rt->dst.in6_addr, &rt->dst.in_addr);
- }
-
- if (!address_is_null(rt->family, &rt->prefsrc.in_addr,
- &rt->prefsrc.in6_addr))
- rta_buf += rta_add_address(rta_buf, RTA_PREFSRC, rt->family,
- &rt->prefsrc.in6_addr,
- &rt->prefsrc.in_addr);
-
- if (rt->mtu) {
- uint8_t buf[256];
- size_t written = rta_add_u32(buf, RTAX_MTU, rt->mtu);
-
- rta_buf += rta_add_data(rta_buf, RTA_METRICS, buf, written);
- }
-
- if (rt->preference)
- rta_buf += rta_add_u8(rta_buf, RTA_PREF, rt->preference);
-
- if (rt->expiry_time > now)
- rta_buf += rta_add_u32(rta_buf, RTA_EXPIRES,
- l_time_to_secs(rt->expiry_time - now));
-
- return l_netlink_send(rtnl, nlmsg_type, flags, rtmmsg,
- rta_buf - (void *) rtmmsg, cb, user_data,
- destroy);
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_route_add(struct l_netlink *rtnl, int ifindex,
@@ -1420,8 +1181,12 @@ LIB_EXPORT uint32_t l_rtnl_route_add(struct l_netlink *rtnl, int ifindex,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- return _rtnl_route_change(rtnl, RTM_NEWROUTE, ifindex, rt,
- cb, user_data, destroy);
+ struct l_netlink_message *nlm =
+ rtnl_message_from_route(RTM_NEWROUTE,
+ NLM_F_CREATE | NLM_F_REPLACE,
+ ifindex, rt);
+
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
LIB_EXPORT uint32_t l_rtnl_route_delete(struct l_netlink *rtnl, int ifindex,
@@ -1430,8 +1195,10 @@ LIB_EXPORT uint32_t l_rtnl_route_delete(struct l_netlink *rtnl, int ifindex,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- return _rtnl_route_change(rtnl, RTM_DELROUTE, ifindex, rt,
- cb, user_data, destroy);
+ struct l_netlink_message *nlm =
+ rtnl_message_from_route(RTM_DELROUTE, 0, ifindex, rt);
+
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
struct rtnl_neighbor_get_data {
@@ -1500,25 +1267,21 @@ LIB_EXPORT uint32_t l_rtnl_neighbor_get_hwaddr(struct l_netlink *rtnl,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- size_t bufsize = NLMSG_ALIGN(sizeof(struct ndmsg)) +
- RTA_SPACE(16); /* NDA_DST */
- uint8_t buf[bufsize];
- struct ndmsg *ndmsg = (struct ndmsg *) buf;
- void *rta_buf = (void *) ndmsg + NLMSG_ALIGN(sizeof(struct ndmsg));
+ struct ndmsg ndm;
+ struct l_netlink_message *nlm = l_netlink_message_new(RTM_GETNEIGH, 0);
__auto_type cb_data = struct_alloc(rtnl_neighbor_get_data,
cb, user_data, destroy);
- uint32_t ret;
+ int ret;
- memset(buf, 0, bufsize);
- ndmsg->ndm_family = family;
- ndmsg->ndm_ifindex = ifindex;
- ndmsg->ndm_flags = 0;
+ memset(&ndm, 0, sizeof(ndm));
+ ndm.ndm_family = family;
+ ndm.ndm_ifindex = ifindex;
+ ndm.ndm_flags = 0;
- rta_buf += rta_add_address(rta_buf, NDA_DST, family, ip, ip);
+ l_netlink_message_add_header(nlm, &ndm, sizeof(ndm));
+ append_address(nlm, NDA_DST, family, ip, ip);
- ret = l_netlink_send(rtnl, RTM_GETNEIGH, 0, ndmsg,
- rta_buf - (void *) ndmsg,
- rtnl_neighbor_get_cb, cb_data,
+ ret = l_netlink_send(rtnl, nlm, rtnl_neighbor_get_cb, cb_data,
rtnl_neighbor_get_destroy_cb);
if (ret)
return ret;
@@ -1536,25 +1299,21 @@ LIB_EXPORT uint32_t l_rtnl_neighbor_set_hwaddr(struct l_netlink *rtnl,
void *user_data,
l_netlink_destroy_func_t destroy)
{
- size_t bufsize = NLMSG_ALIGN(sizeof(struct ndmsg)) +
- RTA_SPACE(16) + /* NDA_DST */
- RTA_SPACE(hwaddr_len); /* NDA_LLADDR */
- uint8_t buf[bufsize];
- struct ndmsg *ndmsg = (struct ndmsg *) buf;
- void *rta_buf = (void *) ndmsg + NLMSG_ALIGN(sizeof(struct ndmsg));
-
- memset(buf, 0, bufsize);
- ndmsg->ndm_family = family;
- ndmsg->ndm_ifindex = ifindex;
- ndmsg->ndm_flags = 0;
- ndmsg->ndm_state = NUD_REACHABLE;
-
- rta_buf += rta_add_address(rta_buf, NDA_DST, family, ip, ip);
- rta_buf += rta_add_data(rta_buf, NDA_LLADDR, hwaddr, hwaddr_len);
-
- return l_netlink_send(rtnl, RTM_NEWNEIGH, NLM_F_CREATE | NLM_F_REPLACE,
- ndmsg, rta_buf - (void *) ndmsg,
- cb, user_data, destroy);
+ struct ndmsg ndm;
+ struct l_netlink_message *nlm =
+ l_netlink_message_new(RTM_NEWNEIGH,
+ NLM_F_CREATE | NLM_F_REPLACE);
+ memset(&ndm, 0, sizeof(ndm));
+ ndm.ndm_family = family;
+ ndm.ndm_ifindex = ifindex;
+ ndm.ndm_flags = 0;
+ ndm.ndm_state = NUD_REACHABLE;
+
+ l_netlink_message_add_header(nlm, &ndm, sizeof(ndm));
+ append_address(nlm, NDA_DST, family, ip, ip);
+ l_netlink_message_append(nlm, NDA_LLADDR, hwaddr, hwaddr_len);
+
+ return l_netlink_send(rtnl, nlm, cb, user_data, destroy);
}
__attribute__((destructor(32000))) static void free_rtnl()
@@ -66,7 +66,10 @@ static void link_notification(uint16_t type, void const * data,
int main(int argc, char *argv[])
{
struct l_netlink *netlink;
- struct ifinfomsg msg;
+ struct ifinfomsg ifi;
+ struct l_netlink_message *nlm =
+ l_netlink_message_new_sized(RTM_GETLINK,
+ NLM_F_DUMP, sizeof(ifi));
unsigned int link_id;
if (!l_main_init())
@@ -78,10 +81,10 @@ int main(int argc, char *argv[])
l_netlink_set_debug(netlink, do_debug, "[NETLINK] ", NULL);
- memset(&msg, 0, sizeof(msg));
+ memset(&ifi, 0, sizeof(ifi));
+ l_netlink_message_add_header(nlm, &ifi, sizeof(ifi));
- l_netlink_send(netlink, RTM_GETLINK, NLM_F_DUMP, &msg, sizeof(msg),
- getlink_callback, NULL, NULL);
+ l_netlink_send(netlink, nlm, getlink_callback, NULL, NULL);
link_id = l_netlink_register(netlink, RTNLGRP_LINK,
link_notification, NULL, NULL);