/* * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETLINK_H_ #define __NETLINK_H_ 1 #include "Types.h" #include "NetlinkProto.h" #include "NetlinkBuf.h" #include "..\..\include\OvsDpInterface.h" /* * Structure of any message passed between userspace and kernel. */ typedef struct _OVS_MESSAGE { NL_MSG_HDR nlMsg; union { GENL_MSG_HDR genlMsg; NF_GEN_MSG_HDR nfGenMsg; }; OVS_HDR ovsHdr; /* Variable length nl_attrs follow. */ } OVS_MESSAGE, *POVS_MESSAGE; BUILD_ASSERT_DECL(sizeof(GENL_MSG_HDR) == sizeof(NF_GEN_MSG_HDR)); /* * Structure of an error message sent as a reply from kernel. */ typedef struct _OVS_MESSAGE_ERROR { NL_MSG_HDR nlMsg; NL_MSG_ERR errorMsg; } OVS_MESSAGE_ERROR, *POVS_MESSAGE_ERROR; /* Netlink attribute types. */ typedef enum { NL_A_NO_ATTR = 0, NL_A_VAR_LEN, NL_A_UNSPEC, NL_A_U8, NL_A_U16, NL_A_BE16 = NL_A_U16, NL_A_U32, NL_A_BE32 = NL_A_U32, NL_A_U64, NL_A_BE64 = NL_A_U64, NL_A_STRING, NL_A_FLAG, NL_A_NESTED, N_NL_ATTR_TYPES } NL_ATTR_TYPE; /* Netlink attribute policy. * Specifies the policy for parsing for netlink attribute. */ typedef struct _NL_POLICY { NL_ATTR_TYPE type; UINT32 minLen; UINT32 maxLen; BOOLEAN optional; } NL_POLICY, *PNL_POLICY; /* This macro is careful to check for attributes with bad lengths. */ #define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \ for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ ((INT)LEFT) >= (INT)NLA_ALIGN(sizeof(NL_ATTR)) && \ NlAttrIsValid(ITER, LEFT); \ (LEFT) -= NlAttrLenPad(ITER, LEFT), (ITER) = NlAttrNext(ITER)) /* This macro does not check for attributes with bad lengths. It should only * be used with messages from trusted sources or with messages that have * already been validated (e.g. with NL_ATTR_FOR_EACH). */ #define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \ for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ ((INT)LEFT) >= (INT)NLA_ALIGN(sizeof(NL_ATTR)); \ (LEFT) -= NLA_ALIGN((ITER)->nlaLen), (ITER) = NlAttrNext(ITER)) #define NL_ATTR_GET_AS(NLA, TYPE) \ (*(TYPE*) NlAttrGetUnspec(nla, sizeof(TYPE))) BOOLEAN NlFillOvsMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid, UINT8 genlCmd, UINT8 genlVer, UINT32 dpNo); BOOLEAN NlFillOvsMsgForNfGenMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid, UINT8 nfgenFamily, UINT8 nfGenVersion, UINT32 dpNo); BOOLEAN NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid); VOID NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, UINT errorCode, UINT32 *msgLen); /* Netlink message accessing the payload */ PVOID NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset); UINT32 NlMsgSize(const PNL_MSG_HDR nlh); VOID NlMsgAlignSize(const PNL_MSG_HDR nlh); VOID NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen); PCHAR NlHdrPayload(const PNL_MSG_HDR nlh); UINT32 NlHdrPayloadLen(const PNL_MSG_HDR nlh); PNL_ATTR NlMsgAttrs(const PNL_MSG_HDR nlh); UINT32 NlMsgAttrsLen(const PNL_MSG_HDR nlh); UINT32 NlNfMsgAttrsLen(const PNL_MSG_HDR nlh); /* Netlink message parse */ PNL_MSG_HDR NlMsgNext(const PNL_MSG_HDR nlh); INT NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen); UINT32 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen); /* Netlink attribute parsing. */ UINT32 NlAttrMinLen(NL_ATTR_TYPE type); UINT32 NlAttrMinLen(NL_ATTR_TYPE type); PNL_ATTR NlAttrNext(const PNL_ATTR nla); UINT16 NlAttrType(const PNL_ATTR nla); PVOID NlAttrData(const PNL_ATTR nla); UINT32 NlAttrGetSize(const PNL_ATTR nla); const PVOID NlAttrGet(const PNL_ATTR nla); const PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size); BE64 NlAttrGetBe64(const PNL_ATTR nla); BE32 NlAttrGetBe32(const PNL_ATTR nla); BE16 NlAttrGetBe16(const PNL_ATTR nla); UINT8 NlAttrGetU8(const PNL_ATTR nla); UINT16 NlAttrGetU16(const PNL_ATTR nla); UINT32 NlAttrGetU32(const PNL_ATTR nla); UINT64 NlAttrGetU64(const PNL_ATTR nla); PCHAR NlAttrGetString(const PNL_ATTR nla); const PNL_ATTR NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type); const PNL_ATTR NlAttrFindNested(const PNL_ATTR nla, UINT16 type); BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy, PNL_ATTR attrs[], UINT32 numAttrs); BOOLEAN NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy, PNL_ATTR attrs[], UINT32 numAttrs); /* * -------------------------------------------------------------------------- * Returns the length of attribute. * -------------------------------------------------------------------------- */ static __inline UINT16 NlAttrLen(const PNL_ATTR nla) { return nla->nlaLen; } /* * --------------------------------------------------------------------------- * Default maximum payload size for each type of attribute. * --------------------------------------------------------------------------- */ UINT32 static __inline NlAttrSize(UINT32 payloadSize) { return NLA_HDRLEN + payloadSize; } /* * --------------------------------------------------------------------------- * Total length including padding. * --------------------------------------------------------------------------- */ UINT32 static __inline NlAttrTotalSize(UINT32 payloadSize) { return NLA_ALIGN(NlAttrSize(payloadSize)); } /* * --------------------------------------------------------------------------- * Returns true if the last attribute is reached. * --------------------------------------------------------------------------- */ BOOLEAN static __inline NlAttrIsLast(const PNL_ATTR nla, int rem) { return nla->nlaLen == rem; } /* Netlink attribute validation */ BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY); /* Netlink attribute stream validation */ BOOLEAN NlValidateAllAttrs(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy); /* Put APis */ BOOLEAN NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg); BOOLEAN NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg); BOOLEAN NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr); BOOLEAN NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len); PCHAR NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len); PCHAR NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len); BOOLEAN NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len); BOOLEAN NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type); BOOLEAN NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value); BOOLEAN NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value); BOOLEAN NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value); BOOLEAN NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value); BOOLEAN NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value); BOOLEAN NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len); PCHAR NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len); PCHAR NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len); BOOLEAN NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len); BOOLEAN NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type); BOOLEAN NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value); BOOLEAN NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value); BOOLEAN NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value); BOOLEAN NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value); BOOLEAN NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value); UINT32 NlMsgStartNested(PNL_BUFFER buf, UINT16 type); VOID NlMsgEndNested(PNL_BUFFER buf, UINT32 offset); BOOLEAN NlMsgPutNested(PNL_BUFFER buf, UINT16 type, const PVOID data, UINT32 size); /* These variants are convenient for iterating nested attributes. */ #define NL_NESTED_FOR_EACH(ITER, LEFT, A) \ NL_ATTR_FOR_EACH(ITER, LEFT, NlAttrGet(A), NlAttrGetSize(A)) #define NL_NESTED_FOR_EACH_UNSAFE(ITER, LEFT, A) \ NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, NlAttrGet(A), NlAttrGetSize(A)) #endif /* __NETLINK_H_ */