{
size_t total_size = NLA_HDRLEN + size;
struct nlattr* nla = nl_msg_push_uninit(msg, total_size);
- ovs_assert(NLA_ALIGN(total_size) <= UINT16_MAX);
+ ovs_assert(!nl_attr_oversized(size));
nla->nla_len = total_size;
nla->nla_type = type;
return nla + 1;
msg->size = 0;
return NULL;
}
+
+/* Returns true if a Netlink attribute with a payload that is 'payload_size'
+ * bytes long would be oversized, that is, if it's not possible to create an
+ * nlattr of that size because its size wouldn't fit in the 16-bit nla_len
+ * field. */
+bool
+nl_attr_oversized(size_t payload_size)
+{
+ return NL_ATTR_SIZE(payload_size) > UINT16_MAX;
+}
\f
/* Attributes. */
ofpbuf_use_const(nested, nl_attr_get(nla), nl_attr_get_size(nla));
}
-/* Default minimum and maximum payload sizes for each type of attribute. */
-static const size_t attr_len_range[][2] = {
- [0 ... N_NL_ATTR_TYPES - 1] = { 0, SIZE_MAX },
- [NL_A_U8] = { 1, 1 },
- [NL_A_U16] = { 2, 2 },
- [NL_A_U32] = { 4, 4 },
- [NL_A_U64] = { 8, 8 },
- [NL_A_STRING] = { 1, SIZE_MAX },
- [NL_A_FLAG] = { 0, SIZE_MAX },
- [NL_A_NESTED] = { 0, SIZE_MAX },
-};
+/* Default minimum payload size for each type of attribute. */
+static size_t
+min_attr_len(enum nl_attr_type type)
+{
+ switch (type) {
+ case NL_A_NO_ATTR: return 0;
+ case NL_A_UNSPEC: return 0;
+ case NL_A_U8: return 1;
+ case NL_A_U16: return 2;
+ case NL_A_U32: return 4;
+ case NL_A_U64: return 8;
+ case NL_A_STRING: return 1;
+ case NL_A_FLAG: return 0;
+ case NL_A_NESTED: return 0;
+ case N_NL_ATTR_TYPES: default: NOT_REACHED();
+ }
+}
+
+/* Default maximum payload size for each type of attribute. */
+static size_t
+max_attr_len(enum nl_attr_type type)
+{
+ switch (type) {
+ case NL_A_NO_ATTR: return SIZE_MAX;
+ case NL_A_UNSPEC: return SIZE_MAX;
+ case NL_A_U8: return 1;
+ case NL_A_U16: return 2;
+ case NL_A_U32: return 4;
+ case NL_A_U64: return 8;
+ case NL_A_STRING: return SIZE_MAX;
+ case NL_A_FLAG: return SIZE_MAX;
+ case NL_A_NESTED: return SIZE_MAX;
+ case N_NL_ATTR_TYPES: default: NOT_REACHED();
+ }
+}
bool
nl_attr_validate(const struct nlattr *nla, const struct nl_policy *policy)
/* Figure out min and max length. */
min_len = policy->min_len;
if (!min_len) {
- min_len = attr_len_range[policy->type][0];
+ min_len = min_attr_len(policy->type);
}
max_len = policy->max_len;
if (!max_len) {
- max_len = attr_len_range[policy->type][1];
+ max_len = max_attr_len(policy->type);
}
/* Verify length. */
return false;
}
- NL_ATTR_FOR_EACH (nla, left,
- (struct nlattr *) ((char *) msg->data + nla_offset),
+ NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, nla_offset, 0),
msg->size - nla_offset)
{
uint16_t type = nl_attr_type(nla);
const struct nlattr *
nl_attr_find(const struct ofpbuf *buf, size_t hdr_len, uint16_t type)
{
- const uint8_t *start = (const uint8_t *) buf->data + hdr_len;
- return nl_attr_find__((const struct nlattr *) start, buf->size - hdr_len,
+ return nl_attr_find__(ofpbuf_at(buf, hdr_len, 0), buf->size - hdr_len,
type);
}