diff options
author | Tom Gundersen <teg@jklm.no> | 2015-06-23 13:13:20 +0200 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2015-06-30 23:14:53 +0200 |
commit | 4c641e99fa1b32385b941cccccb566f5ddc9daed (patch) | |
tree | 344112b5974bb559377a82742d9a5e39604879c8 /src/libsystemd/sd-netlink/netlink-message.c | |
parent | 64ea3f926dfd43b52d7ef0399e44ce00587b5993 (diff) | |
download | systemd-4c641e99fa1b32385b941cccccb566f5ddc9daed.tar.gz |
sd-netlink: respect attribute type flags
Though currently unused by us, netlink attribute types support embedding flags to indicate
if the type is encoded in network byte-order and if it is a nested attribute. Read out
these flags when parsing the message.
We will now swap the byteorder in case it is non-native when reading out integers (though
this is not needed by any of the types we currently support). We do not enforce the NESTED
flag, as the kernel gets this wrong in many cases.
Diffstat (limited to 'src/libsystemd/sd-netlink/netlink-message.c')
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 13573dcea8..b0ed2f2882 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -38,6 +38,7 @@ #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) +#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) { sd_netlink_message *m; @@ -475,7 +476,7 @@ int sd_netlink_message_close_container(sd_netlink_message *m) { return 0; } -static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) { +static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) { struct netlink_attribute *attribute; struct rtattr *rta; @@ -495,6 +496,9 @@ static int netlink_message_read_internal(sd_netlink_message *m, unsigned short t *data = RTA_DATA(rta); + if (net_byteorder) + *net_byteorder = attribute->net_byteorder; + return RTA_PAYLOAD(rta); } @@ -508,7 +512,7 @@ int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, c if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if (strnlen(attr_data, r) >= (size_t) r) @@ -530,7 +534,7 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8 if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t) r < sizeof(uint8_t)) @@ -543,8 +547,9 @@ int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8 } int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) { - int r; void *attr_data; + bool net_byteorder; + int r; assert_return(m, -EINVAL); @@ -552,21 +557,26 @@ int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); if (r < 0) return r; else if ((size_t) r < sizeof(uint16_t)) return -EIO; - if (data) - *data = *(uint16_t *) attr_data; + if (data) { + if (net_byteorder) + *data = be16toh(*(uint16_t *) attr_data); + else + *data = *(uint16_t *) attr_data; + } return 0; } int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) { - int r; void *attr_data; + bool net_byteorder; + int r; assert_return(m, -EINVAL); @@ -574,14 +584,18 @@ int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); if (r < 0) return r; else if ((size_t)r < sizeof(uint32_t)) return -EIO; - if (data) - *data = *(uint32_t *) attr_data; + if (data) { + if (net_byteorder) + *data = be32toh(*(uint32_t *) attr_data); + else + *data = *(uint32_t *) attr_data; + } return 0; } @@ -596,7 +610,7 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct ether_addr)) @@ -618,7 +632,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct ifa_cacheinfo)) @@ -640,7 +654,7 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct in_addr)) @@ -662,7 +676,7 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, if (r < 0) return r; - r = netlink_message_read_internal(m, type, &attr_data); + r = netlink_message_read_internal(m, type, &attr_data, NULL); if (r < 0) return r; else if ((size_t)r < sizeof(struct in6_addr)) @@ -699,6 +713,8 @@ static int netlink_container_parse(sd_netlink_message *m, log_debug("rtnl: message parse - overwriting repeated attribute"); attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr; + attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED; + attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER; } container->attributes = attributes; @@ -781,7 +797,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ } else return -EINVAL; - r = netlink_message_read_internal(m, type_id, &container); + r = netlink_message_read_internal(m, type_id, &container, NULL); if (r < 0) return r; else |