X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=lib%2Fnetlink.c;h=a2be59d02ad02bb7b598706e4bf271085192b303;hb=19b58f3cbcb3191432eefba3a504376399cc07a7;hp=c08a5574e020049b95a90c8add7942e90abd199f;hpb=e5e4b47cc244c0d7ee404d105a2f22d0b327ee23;p=cascardo%2Fovs.git diff --git a/lib/netlink.c b/lib/netlink.c index c08a5574e..a2be59d02 100644 --- a/lib/netlink.c +++ b/lib/netlink.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ #include "ofpbuf.h" #include "timeval.h" #include "unaligned.h" -#include "vlog.h" +#include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(netlink); @@ -67,7 +67,7 @@ nl_msg_nlmsgerr(const struct ofpbuf *msg, int *errorp) int code = EPROTO; if (!err) { VLOG_ERR_RL(&rl, "received invalid nlmsgerr (%"PRIu32" bytes < %"PRIuSIZE")", - ofpbuf_size(msg), NLMSG_HDRLEN + sizeof *err); + msg->size, NLMSG_HDRLEN + sizeof *err); } else if (err->error <= 0 && err->error > INT_MIN) { code = -err->error; } @@ -113,7 +113,7 @@ nl_msg_put_nlmsghdr(struct ofpbuf *msg, { struct nlmsghdr *nlmsghdr; - ovs_assert(ofpbuf_size(msg) == 0); + ovs_assert(msg->size == 0); nl_msg_reserve(msg, NLMSG_HDRLEN + expected_payload); nlmsghdr = nl_msg_put_uninit(msg, NLMSG_HDRLEN); @@ -152,7 +152,7 @@ nl_msg_put_genlmsghdr(struct ofpbuf *msg, size_t expected_payload, struct genlmsghdr *genlmsghdr; nl_msg_put_nlmsghdr(msg, GENL_HDRLEN + expected_payload, family, flags); - ovs_assert(ofpbuf_size(msg) == NLMSG_HDRLEN); + ovs_assert(msg->size == NLMSG_HDRLEN); genlmsghdr = nl_msg_put_uninit(msg, GENL_HDRLEN); genlmsghdr->cmd = cmd; genlmsghdr->version = version; @@ -214,7 +214,7 @@ nl_msg_put_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size) { size_t total_size = NLA_HDRLEN + size; struct nlattr* nla = nl_msg_put_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; @@ -308,6 +308,15 @@ nl_msg_put_be64(struct ofpbuf *msg, uint16_t type, ovs_be64 value) nl_msg_put_unspec(msg, type, &value, sizeof value); } +/* Appends a Netlink attribute of the given 'type' and the given IPv6 + * address order 'value' to 'msg'. */ +void +nl_msg_put_in6_addr(struct ofpbuf *msg, uint16_t type, + const struct in6_addr *value) +{ + nl_msg_put_unspec(msg, type, value, sizeof *value); +} + /* Appends a Netlink attribute of the given 'type' and the given odp_port_t * 'value' to 'msg'. */ void @@ -316,6 +325,17 @@ nl_msg_put_odp_port(struct ofpbuf *msg, uint16_t type, odp_port_t value) nl_msg_put_u32(msg, type, odp_to_u32(value)); } +/* Appends a Netlink attribute of the given 'type' with the 'len' characters + * of 'value', followed by the null byte to 'msg'. */ +void +nl_msg_put_string__(struct ofpbuf *msg, uint16_t type, const char *value, + size_t len) +{ + char *data = nl_msg_put_unspec_uninit(msg, type, len + 1); + + memcpy(data, value, len); + data[len] = '\0'; +} /* Appends a Netlink attribute of the given 'type' and the given * null-terminated string 'value' to 'msg'. */ @@ -432,7 +452,7 @@ nl_msg_push_string(struct ofpbuf *msg, uint16_t type, const char *value) size_t nl_msg_start_nested(struct ofpbuf *msg, uint16_t type) { - size_t offset = ofpbuf_size(msg); + size_t offset = msg->size; nl_msg_put_unspec(msg, type, NULL, 0); return offset; } @@ -443,7 +463,7 @@ void nl_msg_end_nested(struct ofpbuf *msg, size_t offset) { struct nlattr *attr = ofpbuf_at_assert(msg, offset, sizeof *attr); - attr->nla_len = ofpbuf_size(msg) - offset; + attr->nla_len = msg->size - offset; } /* Appends a nested Netlink attribute of the given 'type', with the 'size' @@ -459,25 +479,26 @@ nl_msg_put_nested(struct ofpbuf *msg, /* If 'buffer' begins with a valid "struct nlmsghdr", pulls the header and its * payload off 'buffer', stores header and payload in 'msg->data' and - * 'ofpbuf_size(msg)', and returns a pointer to the header. + * 'msg->size', and returns a pointer to the header. * * If 'buffer' does not begin with a "struct nlmsghdr" or begins with one that - * is invalid, returns NULL without modifying 'buffer'. */ + * is invalid, returns NULL and clears 'buffer' and 'msg'. */ struct nlmsghdr * nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg) { - if (ofpbuf_size(buffer) >= sizeof(struct nlmsghdr)) { + if (buffer->size >= sizeof(struct nlmsghdr)) { struct nlmsghdr *nlmsghdr = nl_msg_nlmsghdr(buffer); size_t len = nlmsghdr->nlmsg_len; - if (len >= sizeof *nlmsghdr && len <= ofpbuf_size(buffer)) { + if (len >= sizeof *nlmsghdr && len <= buffer->size) { ofpbuf_use_const(msg, nlmsghdr, len); ofpbuf_pull(buffer, len); return nlmsghdr; } } - ofpbuf_set_data(msg, NULL); - ofpbuf_set_size(msg, 0); + ofpbuf_clear(buffer); + msg->data = NULL; + msg->size = 0; return NULL; } @@ -488,7 +509,7 @@ nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg) bool nl_attr_oversized(size_t payload_size) { - return NL_ATTR_SIZE(payload_size) > UINT16_MAX; + return payload_size > UINT16_MAX - NLA_HDRLEN; } /* Attributes. */ @@ -602,6 +623,15 @@ nl_attr_get_be64(const struct nlattr *nla) return get_32aligned_be64(x); } +/* Returns the IPv6 address value in 'nla''s payload. + * + * Asserts that 'nla''s payload is at least 16 bytes long. */ +struct in6_addr +nl_attr_get_in6_addr(const struct nlattr *nla) +{ + return NL_ATTR_GET_AS(nla, struct in6_addr); +} + /* Returns the 32-bit odp_port_t value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 4 bytes long. */ @@ -642,6 +672,7 @@ min_attr_len(enum nl_attr_type type) case NL_A_U64: return 8; case NL_A_STRING: return 1; case NL_A_FLAG: return 0; + case NL_A_IPV6: return 16; case NL_A_NESTED: return 0; case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED(); } @@ -660,6 +691,7 @@ max_attr_len(enum nl_attr_type type) case NL_A_U64: return 8; case NL_A_STRING: return SIZE_MAX; case NL_A_FLAG: return SIZE_MAX; + case NL_A_IPV6: return 16; case NL_A_NESTED: return SIZE_MAX; case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED(); } @@ -728,13 +760,13 @@ nl_policy_parse(const struct ofpbuf *msg, size_t nla_offset, memset(attrs, 0, n_attrs * sizeof *attrs); - if (ofpbuf_size(msg) < nla_offset) { + if (msg->size < nla_offset) { VLOG_DBG_RL(&rl, "missing headers in nl_policy_parse"); return false; } NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, nla_offset, 0), - ofpbuf_size(msg) - nla_offset) + msg->size - nla_offset) { uint16_t type = nl_attr_type(nla); if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) { @@ -798,7 +830,7 @@ nl_attr_find__(const struct nlattr *attrs, size_t size, uint16_t type) const struct nlattr * nl_attr_find(const struct ofpbuf *buf, size_t hdr_len, uint16_t type) { - return nl_attr_find__(ofpbuf_at(buf, hdr_len, 0), ofpbuf_size(buf) - hdr_len, + return nl_attr_find__(ofpbuf_at(buf, hdr_len, 0), buf->size - hdr_len, type); }