In this change we have added the APIs for putting netlink headers, attributes in a buffer.
The buffer is managed through NetlinkBuf.[c|h]. --- datapath-windows/ovsext/Netlink/Netlink.c | 403 +++++++++++++++++++++++++++++- datapath-windows/ovsext/Netlink/Netlink.h | 28 +++ 2 files changed, 427 insertions(+), 4 deletions(-) diff --git a/datapath-windows/ovsext/Netlink/Netlink.c b/datapath-windows/ovsext/Netlink/Netlink.c index 90a633b..8c6b139 100644 --- a/datapath-windows/ovsext/Netlink/Netlink.c +++ b/datapath-windows/ovsext/Netlink/Netlink.c @@ -24,6 +24,402 @@ #define OVS_DBG_MOD OVS_DBG_NETLINK #include "Debug.h" +/* ========================================================================== + * This file provides simple netlink get, put and validation APIs. + * Most of the code is on similar lines as userspace netlink implementation. + * + * TODO: Convert these methods to inline. + * ========================================================================== + */ + +/* + * --------------------------------------------------------------------------- + * Adds Netlink Header to the NL_BUF. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutNlHdr(PNL_BUF buf, PNL_MSG_HDR nlMsg) +{ + if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) { + return TRUE; + } + + return FALSE; +} + +/* + * --------------------------------------------------------------------------- + * Adds Genl Header to the NL_BUF. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutGenlHdr(PNL_BUF buf, PGENL_MSG_HDR genlMsg) +{ + if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) { + return TRUE; + } + + return FALSE; +} + +/* + * --------------------------------------------------------------------------- + * Adds OVS Header to the NL_BUF. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutOvsHdr(PNL_BUF buf, POVS_HDR ovsHdr) +{ + if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN, + GENL_HDRLEN + NLMSG_HDRLEN))) { + return TRUE; + } + + return FALSE; +} + +/* + * --------------------------------------------------------------------------- + * Adds data of length 'len' to the tail end of NL_BUF. + * Refer nl_msg_put for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTail(PNL_BUF buf, const PCHAR data, UINT32 len) +{ + len = NLMSG_ALIGN(len); + if (NlBufCopyAtTail(buf, data, len)) { + return TRUE; + } + + return FALSE; +} + +/* + * --------------------------------------------------------------------------- + * memsets length 'len' at tail end of NL_BUF. + * Refer nl_msg_put_uninit for more details. + * --------------------------------------------------------------------------- + */ +PCHAR +NlMsgPutTailUninit(PNL_BUF buf, UINT32 len) +{ + len = NLMSG_ALIGN(len); + return NlBufCopyAtTailUninit(buf, len); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute to the tail end of buffer. It does + * not copy the attribute payload. + * Refer nl_msg_put_unspec_uninit for more details. + * --------------------------------------------------------------------------- + */ +PCHAR +NlMsgPutTailUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len) +{ + PCHAR ret = NULL; + UINT16 totalLen = NLA_HDRLEN + len; + PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen)); + + if (!nla) { + goto done; + } + + ret = (PCHAR)(nla + 1); + nla->nlaLen = totalLen; + nla->nlaType = type; + +done: + return ret; +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute to the tail end of buffer. It copies attribute + * payload as well. + * Refer nl_msg_put_unspec for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len) +{ + BOOLEAN ret = TRUE; + PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len); + + if (!nlaData) { + ret = FALSE; + goto done; + } + + RtlCopyMemory(nlaData, data, len); + +done: + return ret; +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and no payload at the tail end of buffer. + * Refer nl_msg_put_flag for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailFlag(PNL_BUF buf, UINT16 type) +{ + BOOLEAN ret = TRUE; + PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0); + + if (!nlaData) { + ret = FALSE; + } + + return ret; +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer. + * Refer nl_msg_put_u8 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailU8(PNL_BUF buf, UINT16 type, UINT8 value) +{ + return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer. + * Refer nl_msg_put_u16 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailU16(PNL_BUF buf, UINT16 type, UINT16 value) +{ + return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer. + * Refer nl_msg_put_u32 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailU32(PNL_BUF buf, UINT16 type, UINT32 value) +{ + return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer. + * Refer nl_msg_put_u64 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailU64(PNL_BUF buf, UINT16 type, UINT64 value) +{ + return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and string payload. + * Refer nl_msg_put_string for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutTailString(PNL_BUF buf, UINT16 type, PCHAR value) +{ + size_t strLen = strlen(value) + 1; +#ifdef DBG + /* Attribute length should come within 16 bits (NL_ATTR). + * Not a likely case, hence validation only in debug mode. */ + if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) { + return FALSE; + } +#endif + + /* typecast to keep compiler happy */ + return (NlMsgPutTailUnspec(buf, type, value, + (UINT16)strLen)); +} + +/* + * --------------------------------------------------------------------------- + * Adds data of length 'len' to the head of NL_BUF. + * Refer nl_msg_push for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHead(PNL_BUF buf, const PCHAR data, UINT32 len) +{ + len = NLMSG_ALIGN(len); + if (NlBufCopyAtHead(buf, data, len)) { + return TRUE; + } + + return FALSE; +} + +/* + * --------------------------------------------------------------------------- + * memsets length 'len' at head of NL_BUF. + * Refer nl_msg_push_uninit for more details. + * --------------------------------------------------------------------------- + */ +PCHAR +NlMsgPutHeadUninit(PNL_BUF buf, UINT32 len) +{ + len = NLMSG_ALIGN(len); + return NlBufCopyAtHeadUninit(buf, len); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute to the head of buffer. It does + * not copy the attribute payload. + * Refer nl_msg_push_unspec_uninit for more details. + * --------------------------------------------------------------------------- + */ +PCHAR +NlMsgPutHeadUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len) +{ + PCHAR ret = NULL; + UINT16 totalLen = NLA_HDRLEN + len; + PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen)); + + if (!nla) { + goto done; + } + + ret = (PCHAR)(nla + 1); + nla->nlaLen = totalLen; + nla->nlaType = type; + +done: + return ret; +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute to the head of buffer. It copies attribute + * payload as well. + * Refer nl_msg_push_unspec for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len) +{ + BOOLEAN ret = TRUE; + PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len); + + if (!nlaData) { + ret = FALSE; + goto done; + } + + RtlCopyMemory(nlaData, data, len); + +done: + return ret; +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and no payload at the head of buffer. + * Refer nl_msg_push_flag for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadFlag(PNL_BUF buf, UINT16 type) +{ + BOOLEAN ret = TRUE; + PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0); + + if (!nlaData) { + ret = FALSE; + } + + return ret; +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 8 bit payload at the head of buffer. + * Refer nl_msg_push_u8 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadU8(PNL_BUF buf, UINT16 type, UINT8 value) +{ + return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 16 bit payload at the head of buffer. + * Refer nl_msg_push_u16 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadU16(PNL_BUF buf, UINT16 type, UINT16 value) +{ + return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 32 bit payload at the head of buffer. + * Refer nl_msg_push_u32 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadU32(PNL_BUF buf, UINT16 type, UINT32 value) +{ + return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and 64 bit payload at the head of buffer. + * Refer nl_msg_push_u64 for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadU64(PNL_BUF buf, UINT16 type, UINT64 value) +{ + return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); +} + +/* + * --------------------------------------------------------------------------- + * Adds an attribute of 'type' and string payload. + * Refer nl_msg_push_string for more details. + * --------------------------------------------------------------------------- + */ +BOOLEAN +NlMsgPutHeadString(PNL_BUF buf, UINT16 type, PCHAR value) +{ + size_t strLen = strlen(value) + 1; +#ifdef DBG + /* Attribute length should come within 16 bits (NL_ATTR). + * Not a likely case, hence validation only in debug mode. */ + if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) { + return FALSE; + } +#endif + + /* typecast to keep compiler happy */ + return (NlMsgPutHeadUnspec(buf, type, value, + (UINT16)strLen)); +} + +/* Accessing netlink message payload */ + /* * --------------------------------------------------------------------------- * Netlink message accessing the payload. @@ -173,7 +569,7 @@ NlAttrMaxLen(NL_ATTR_TYPE type) 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_STRING: return MAXUINT16; case NL_A_FLAG: return SIZE_MAX; case NL_A_NESTED: return SIZE_MAX; case N_NL_ATTR_TYPES: @@ -408,8 +804,7 @@ NlAttrFindNested(const PNL_ATTR nla, UINT16 type) * attribute type validation parameters. * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER * - * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed - * (e.g. if Pkt_CopyBytesOut() returns an error). + * Returns BOOLEAN to indicate success/failure. *---------------------------------------------------------------------------- */ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, @@ -421,7 +816,7 @@ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 iter; BOOLEAN ret = FALSE; - memset(attrs, 0, n_attrs * sizeof *attrs); + RtlZeroMemory(attrs, n_attrs * sizeof *attrs); if ((NlMsgSize(nlMsg) < attrOffset) || (!(NlMsgAttrLen(nlMsg)))) { OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d", diff --git a/datapath-windows/ovsext/Netlink/Netlink.h b/datapath-windows/ovsext/Netlink/Netlink.h index 0edc2fa..04fd536 100644 --- a/datapath-windows/ovsext/Netlink/Netlink.h +++ b/datapath-windows/ovsext/Netlink/Netlink.h @@ -19,6 +19,7 @@ #include "Types.h" #include "NetlinkProto.h" +#include "NetlinkBuf.h" /* Netlink attribute types. */ typedef enum @@ -101,4 +102,31 @@ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, /* Netlink attribute validation */ BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY); +/* Put APis */ +BOOLEAN NlMsgPutNlHdr(PNL_BUF buf, PNL_MSG_HDR nlMsg); +BOOLEAN NlMsgPutGenlHdr(PNL_BUF buf, PGENL_MSG_HDR genlMsg); +BOOLEAN NlMsgPutOvsHdr(PNL_BUF buf, POVS_HDR ovsHdr); + +BOOLEAN NlMsgPutTail(PNL_BUF buf, const PCHAR data, UINT32 len); +PCHAR NlMsgPutTailUninit(PNL_BUF buf, UINT32 len); +PCHAR NlMsgPutTailUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len); +BOOLEAN NlMsgPutTailUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len); +BOOLEAN NlMsgPutTailFlag(PNL_BUF buf, UINT16 type); +BOOLEAN NlMsgPutTailU8(PNL_BUF buf, UINT16 type, UINT8 value); +BOOLEAN NlMsgPutTailU16(PNL_BUF buf, UINT16 type, UINT16 value); +BOOLEAN NlMsgPutTailU32(PNL_BUF buf, UINT16 type, UINT32 value); +BOOLEAN NlMsgPutTailU64(PNL_BUF buf, UINT16 type, UINT64 value); +BOOLEAN NlMsgPutTailString(PNL_BUF buf, UINT16 type, PCHAR value); + +BOOLEAN NlMsgPutHead(PNL_BUF buf, const PCHAR data, UINT32 len); +PCHAR NlMsgPutHeadUninit(PNL_BUF buf, UINT32 len); +PCHAR NlMsgPutHeadUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len); +BOOLEAN NlMsgPutHeadUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len); +BOOLEAN NlMsgPutHeadFlag(PNL_BUF buf, UINT16 type); +BOOLEAN NlMsgPutHeadU8(PNL_BUF buf, UINT16 type, UINT8 value); +BOOLEAN NlMsgPutHeadU16(PNL_BUF buf, UINT16 type, UINT16 value); +BOOLEAN NlMsgPutHeadU32(PNL_BUF buf, UINT16 type, UINT32 value); +BOOLEAN NlMsgPutHeadU64(PNL_BUF buf, UINT16 type, UINT64 value); +BOOLEAN NlMsgPutHeadString(PNL_BUF buf, UINT16 type, PCHAR value); + #endif /* __NETLINK_H_ */ -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev