2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "NetlinkProto.h"
24 #define OVS_DBG_MOD OVS_DBG_NETLINK
27 /* ==========================================================================
28 * This file provides simple netlink get, put and validation APIs.
29 * Most of the code is on similar lines as userspace netlink implementation.
31 * TODO: Convert these methods to inline.
32 * ==========================================================================
36 * ---------------------------------------------------------------------------
37 * Prepare netlink message headers. This API adds
38 * NL_MSG_HDR + GENL_HDR + OVS_HDR to the tail of input NLBuf.
39 * Attributes should be added by caller.
40 * ---------------------------------------------------------------------------
43 NlFillOvsMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType,
44 UINT16 nlmsgFlags, UINT32 nlmsgSeq,
45 UINT32 nlmsgPid, UINT8 genlCmd,
46 UINT8 genlVer, UINT32 dpNo)
50 UINT32 offset = NlBufSize(nlBuf);
52 /* To keep compiler happy for release build. */
53 UNREFERENCED_PARAMETER(offset);
54 ASSERT(NlBufAt(nlBuf, offset, 0) != 0);
56 msgOut.nlMsg.nlmsgType = nlmsgType;
57 msgOut.nlMsg.nlmsgFlags = nlmsgFlags;
58 msgOut.nlMsg.nlmsgSeq = nlmsgSeq;
59 msgOut.nlMsg.nlmsgPid = nlmsgPid;
60 msgOut.nlMsg.nlmsgLen = sizeof(struct _OVS_MESSAGE);
62 msgOut.genlMsg.cmd = genlCmd;
63 msgOut.genlMsg.version = genlVer;
64 msgOut.genlMsg.reserved = 0;
66 msgOut.ovsHdr.dp_ifindex = dpNo;
68 writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),
69 sizeof (struct _OVS_MESSAGE));
75 * ---------------------------------------------------------------------------
76 * Prepare NL_MSG_HDR only. This API appends a NL_MSG_HDR to the tail of
78 * ---------------------------------------------------------------------------
81 NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType,
82 UINT16 nlmsgFlags, UINT32 nlmsgSeq,
87 UINT32 offset = NlBufSize(nlBuf);
89 /* To keep compiler happy for release build. */
90 UNREFERENCED_PARAMETER(offset);
91 ASSERT(NlBufAt(nlBuf, offset, 0) != 0);
93 msgOut.nlmsgType = nlmsgType;
94 msgOut.nlmsgFlags = nlmsgFlags;
95 msgOut.nlmsgSeq = nlmsgSeq;
96 msgOut.nlmsgPid = nlmsgPid;
97 msgOut.nlmsgLen = sizeof(struct _NL_MSG_HDR);
99 writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),
100 sizeof(struct _NL_MSG_HDR));
106 * ---------------------------------------------------------------------------
107 * Prepare a 'OVS_MESSAGE_ERROR' message.
108 * ---------------------------------------------------------------------------
111 NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, UINT errorCode)
115 ASSERT(errorCode != NL_ERROR_PENDING);
117 NlBufInit(&nlBuffer, (PCHAR)msgError, sizeof *msgError);
118 NlFillNlHdr(&nlBuffer, NLMSG_ERROR, 0,
119 msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid);
121 msgError->errorMsg.error = errorCode;
122 msgError->errorMsg.nlMsg = msgIn->nlMsg;
123 msgError->nlMsg.nlmsgLen = sizeof(OVS_MESSAGE_ERROR);
127 * ---------------------------------------------------------------------------
128 * Adds Netlink Header to the NL_BUF.
129 * ---------------------------------------------------------------------------
132 NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg)
134 if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) {
142 * ---------------------------------------------------------------------------
143 * Adds Genl Header to the NL_BUF.
144 * ---------------------------------------------------------------------------
147 NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg)
149 if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) {
157 * ---------------------------------------------------------------------------
158 * Adds OVS Header to the NL_BUF.
159 * ---------------------------------------------------------------------------
162 NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr)
164 if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN,
165 GENL_HDRLEN + NLMSG_HDRLEN))) {
173 * ---------------------------------------------------------------------------
174 * Adds data of length 'len' to the tail end of NL_BUF.
175 * Refer nl_msg_put for more details.
176 * ---------------------------------------------------------------------------
179 NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len)
181 len = NLMSG_ALIGN(len);
182 if (NlBufCopyAtTail(buf, data, len)) {
190 * ---------------------------------------------------------------------------
191 * memsets length 'len' at tail end of NL_BUF.
192 * Refer nl_msg_put_uninit for more details.
193 * ---------------------------------------------------------------------------
196 NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len)
198 len = NLMSG_ALIGN(len);
199 return NlBufCopyAtTailUninit(buf, len);
203 * ---------------------------------------------------------------------------
204 * Adds an attribute to the tail end of buffer. It does
205 * not copy the attribute payload.
206 * Refer nl_msg_put_unspec_uninit for more details.
207 * ---------------------------------------------------------------------------
210 NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)
213 UINT16 totalLen = NLA_HDRLEN + len;
214 PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen));
220 ret = (PCHAR)(nla + 1);
221 nla->nlaLen = totalLen;
229 * ---------------------------------------------------------------------------
230 * Adds an attribute to the tail end of buffer. It copies attribute
232 * Refer nl_msg_put_unspec for more details.
233 * ---------------------------------------------------------------------------
236 NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)
239 PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len);
246 RtlCopyMemory(nlaData, data, len);
253 * ---------------------------------------------------------------------------
254 * Adds an attribute of 'type' and no payload at the tail end of buffer.
255 * Refer nl_msg_put_flag for more details.
256 * ---------------------------------------------------------------------------
259 NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type)
262 PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
272 * ---------------------------------------------------------------------------
273 * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer.
274 * Refer nl_msg_put_u8 for more details.
275 * ---------------------------------------------------------------------------
278 NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value)
280 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
284 * ---------------------------------------------------------------------------
285 * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer.
286 * Refer nl_msg_put_u16 for more details.
287 * ---------------------------------------------------------------------------
290 NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value)
292 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
296 * ---------------------------------------------------------------------------
297 * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer.
298 * Refer nl_msg_put_u32 for more details.
299 * ---------------------------------------------------------------------------
302 NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value)
304 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
308 * ---------------------------------------------------------------------------
309 * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer.
310 * Refer nl_msg_put_u64 for more details.
311 * ---------------------------------------------------------------------------
314 NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value)
316 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
320 * ---------------------------------------------------------------------------
321 * Adds an attribute of 'type' and string payload.
322 * Refer nl_msg_put_string for more details.
323 * ---------------------------------------------------------------------------
326 NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value)
328 size_t strLen = strlen(value) + 1;
330 /* Attribute length should come within 16 bits (NL_ATTR).
331 * Not a likely case, hence validation only in debug mode. */
332 if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {
337 /* typecast to keep compiler happy */
338 return (NlMsgPutTailUnspec(buf, type, value,
343 * ---------------------------------------------------------------------------
344 * Adds data of length 'len' to the head of NL_BUF.
345 * Refer nl_msg_push for more details.
346 * ---------------------------------------------------------------------------
349 NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len)
351 len = NLMSG_ALIGN(len);
352 if (NlBufCopyAtHead(buf, data, len)) {
360 * ---------------------------------------------------------------------------
361 * memsets length 'len' at head of NL_BUF.
362 * Refer nl_msg_push_uninit for more details.
363 * ---------------------------------------------------------------------------
366 NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len)
368 len = NLMSG_ALIGN(len);
369 return NlBufCopyAtHeadUninit(buf, len);
373 * ---------------------------------------------------------------------------
374 * Adds an attribute to the head of buffer. It does
375 * not copy the attribute payload.
376 * Refer nl_msg_push_unspec_uninit for more details.
377 * ---------------------------------------------------------------------------
380 NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)
383 UINT16 totalLen = NLA_HDRLEN + len;
384 PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen));
390 ret = (PCHAR)(nla + 1);
391 nla->nlaLen = totalLen;
399 * ---------------------------------------------------------------------------
400 * Adds an attribute to the head of buffer. It copies attribute
402 * Refer nl_msg_push_unspec for more details.
403 * ---------------------------------------------------------------------------
406 NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)
409 PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len);
416 RtlCopyMemory(nlaData, data, len);
423 * ---------------------------------------------------------------------------
424 * Adds an attribute of 'type' and no payload at the head of buffer.
425 * Refer nl_msg_push_flag for more details.
426 * ---------------------------------------------------------------------------
429 NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type)
432 PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0);
442 * ---------------------------------------------------------------------------
443 * Adds an attribute of 'type' and 8 bit payload at the head of buffer.
444 * Refer nl_msg_push_u8 for more details.
445 * ---------------------------------------------------------------------------
448 NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value)
450 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
454 * ---------------------------------------------------------------------------
455 * Adds an attribute of 'type' and 16 bit payload at the head of buffer.
456 * Refer nl_msg_push_u16 for more details.
457 * ---------------------------------------------------------------------------
460 NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value)
462 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
466 * ---------------------------------------------------------------------------
467 * Adds an attribute of 'type' and 32 bit payload at the head of buffer.
468 * Refer nl_msg_push_u32 for more details.
469 * ---------------------------------------------------------------------------
472 NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value)
474 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
478 * ---------------------------------------------------------------------------
479 * Adds an attribute of 'type' and 64 bit payload at the head of buffer.
480 * Refer nl_msg_push_u64 for more details.
481 * ---------------------------------------------------------------------------
484 NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value)
486 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
490 * ---------------------------------------------------------------------------
491 * Adds an attribute of 'type' and string payload.
492 * Refer nl_msg_push_string for more details.
493 * ---------------------------------------------------------------------------
496 NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value)
498 size_t strLen = strlen(value) + 1;
500 /* Attribute length should come within 16 bits (NL_ATTR).
501 * Not a likely case, hence validation only in debug mode. */
502 if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {
507 /* typecast to keep compiler happy */
508 return (NlMsgPutHeadUnspec(buf, type, value,
513 * ---------------------------------------------------------------------------
514 * Adds the header for nested netlink attributes. It
515 * returns the offset of this header. If addition of header fails
516 * then returned value of offset will be zero.
517 * Refer nl_msg_start_nested for more details.
518 * ---------------------------------------------------------------------------
521 NlMsgStartNested(PNL_BUFFER buf, UINT16 type)
523 UINT32 offset = NlBufSize(buf);
524 PCHAR nlaData = NULL;
526 nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
529 /* Value zero must be reated as error by the caller.
530 * This is because an attribute can never be added
531 * at offset zero, it will always come after NL_MSG_HDR,
532 * GENL_HDR and OVS_HEADER. */
540 * ---------------------------------------------------------------------------
541 * Finalizes the nested netlink attribute by updating the nla_len.
542 * offset should be the one returned by NlMsgStartNested.
543 * Refer nl_msg_end_nested for more details.
544 * ---------------------------------------------------------------------------
547 NlMsgEndNested(PNL_BUFFER buf, UINT32 offset)
549 PNL_ATTR attr = (PNL_ATTR)(NlBufAt(buf, offset, sizeof *attr));
551 /* Typecast to keep compiler happy.
552 * Attribute length would never exceed MAX UINT16.*/
553 attr->nlaLen = (UINT16)(NlBufSize(buf) - offset);
557 * --------------------------------------------------------------------------
558 * Appends a nested Netlink attribute of the given 'type', with the 'size'
559 * bytes of content starting at 'data', to 'msg'.
560 * Refer nl_msg_put_nested for more details.
561 * --------------------------------------------------------------------------
564 NlMsgPutNested(PNL_BUFFER buf, UINT16 type,
565 const PVOID data, UINT32 size)
567 UINT32 offset = NlMsgStartNested(buf, type);
572 ret = NlMsgPutTail(buf, data, size);
576 NlMsgEndNested(buf, offset);
581 /* Accessing netlink message payload */
584 * ---------------------------------------------------------------------------
585 * Netlink message accessing the payload.
586 * ---------------------------------------------------------------------------
589 NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset)
591 return ((PCHAR)nlh + offset);
595 * ---------------------------------------------------------------------------
596 * Returns the size of netlink message.
597 * ---------------------------------------------------------------------------
600 NlMsgSize(const PNL_MSG_HDR nlh)
602 return nlh->nlmsgLen;
606 * ---------------------------------------------------------------------------
607 * Aligns the size of Netlink message.
608 * ---------------------------------------------------------------------------
611 NlMsgAlignSize(const PNL_MSG_HDR nlh)
613 nlh->nlmsgLen = NLMSG_ALIGN(nlh->nlmsgLen);
618 * ---------------------------------------------------------------------------
619 * Sets the size of Netlink message.
620 * ---------------------------------------------------------------------------
623 NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen)
625 nlh->nlmsgLen = msgLen;
629 * ---------------------------------------------------------------------------
630 * Returns pointer to nlmsg payload.
631 * ---------------------------------------------------------------------------
634 NlHdrPayload(const PNL_MSG_HDR nlh)
636 return ((PCHAR)nlh + NLMSG_HDRLEN);
640 * ---------------------------------------------------------------------------
641 * Returns length of nlmsg payload.
642 * ---------------------------------------------------------------------------
645 NlHdrPayloadLen(const PNL_MSG_HDR nlh)
647 return nlh->nlmsgLen - NLMSG_HDRLEN;
651 * ---------------------------------------------------------------------------
652 * Returns pointer to nlmsg attributes.
653 * ---------------------------------------------------------------------------
656 NlMsgAttrs(const PNL_MSG_HDR nlh)
658 return (PNL_ATTR) (NlHdrPayload(nlh) + GENL_HDRLEN + OVS_HDRLEN);
662 * ---------------------------------------------------------------------------
663 * Returns size of to nlmsg attributes.
664 * ---------------------------------------------------------------------------
667 NlMsgAttrsLen(const PNL_MSG_HDR nlh)
669 return NlHdrPayloadLen(nlh) - GENL_HDRLEN - OVS_HDRLEN;
672 /* Netlink message parse. */
675 * ---------------------------------------------------------------------------
676 * Returns next netlink message in the stream.
677 * ---------------------------------------------------------------------------
680 NlMsgNext(const PNL_MSG_HDR nlh)
682 return (PNL_MSG_HDR)((PCHAR)nlh +
683 NLMSG_ALIGN(nlh->nlmsgLen));
687 * ---------------------------------------------------------------------------
688 * Netlink Attr helper APIs.
689 * ---------------------------------------------------------------------------
692 NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen)
694 return (maxlen >= sizeof *nla
695 && nla->nlaLen >= sizeof *nla
696 && nla->nlaLen <= maxlen);
700 * ---------------------------------------------------------------------------
701 * Returns alligned length of the attribute.
702 * ---------------------------------------------------------------------------
705 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen)
707 UINT32 len = NLA_ALIGN(nla->nlaLen);
709 return len <= maxlen ? len : nla->nlaLen;
713 * ---------------------------------------------------------------------------
714 * Default minimum payload size for each type of attribute.
715 * ---------------------------------------------------------------------------
718 NlAttrMinLen(NL_ATTR_TYPE type)
721 case NL_A_NO_ATTR: return 0;
722 case NL_A_UNSPEC: return 0;
723 case NL_A_U8: return 1;
724 case NL_A_U16: return 2;
725 case NL_A_U32: return 4;
726 case NL_A_U64: return 8;
727 case NL_A_STRING: return 1;
728 case NL_A_FLAG: return 0;
729 case NL_A_NESTED: return 0;
730 case N_NL_ATTR_TYPES:
732 OVS_LOG_WARN("Unsupprted attribute type: %d", type);
736 /* To keep compiler happy */
741 * ---------------------------------------------------------------------------
742 * Default maximum payload size for each type of attribute.
743 * ---------------------------------------------------------------------------
746 NlAttrMaxLen(NL_ATTR_TYPE type)
749 case NL_A_NO_ATTR: return SIZE_MAX;
750 case NL_A_UNSPEC: return SIZE_MAX;
751 case NL_A_U8: return 1;
752 case NL_A_U16: return 2;
753 case NL_A_U32: return 4;
754 case NL_A_U64: return 8;
755 case NL_A_STRING: return MAXUINT16;
756 case NL_A_FLAG: return SIZE_MAX;
757 case NL_A_NESTED: return SIZE_MAX;
758 case N_NL_ATTR_TYPES:
760 OVS_LOG_WARN("Unsupprted attribute type: %d", type);
764 /* To keep compiler happy */
768 /* Netlink attribute iteration. */
771 * ---------------------------------------------------------------------------
772 * Returns the next attribute.
773 * ---------------------------------------------------------------------------
776 NlAttrNext(const PNL_ATTR nla)
778 return (PNL_ATTR)((UINT8 *)nla + NLA_ALIGN(nla->nlaLen));
782 * --------------------------------------------------------------------------
783 * Returns the bits of 'nla->nlaType' that are significant for determining
785 * --------------------------------------------------------------------------
788 NlAttrType(const PNL_ATTR nla)
790 return nla->nlaType & NLA_TYPE_MASK;
794 * --------------------------------------------------------------------------
795 * Returns the netlink attribute data.
796 * --------------------------------------------------------------------------
799 NlAttrData(const PNL_ATTR nla)
801 return ((PCHAR)nla + NLA_HDRLEN);
805 * ---------------------------------------------------------------------------
806 * Returns the number of bytes in the payload of attribute 'nla'.
807 * ---------------------------------------------------------------------------
810 NlAttrGetSize(const PNL_ATTR nla)
812 return nla->nlaLen - NLA_HDRLEN;
816 * ---------------------------------------------------------------------------
817 * Returns the first byte in the payload of attribute 'nla'.
818 * ---------------------------------------------------------------------------
821 NlAttrGet(const PNL_ATTR nla)
823 ASSERT(nla->nlaLen >= NLA_HDRLEN);
828 * ---------------------------------------------------------------------------
829 * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the
830 * first byte of the payload.
831 * ---------------------------------------------------------------------------
834 PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size)
836 UNREFERENCED_PARAMETER(size);
837 ASSERT(nla->nlaLen >= NLA_HDRLEN + size);
842 * ---------------------------------------------------------------------------
843 * Returns the 64-bit network byte order value in 'nla''s payload.
845 * Asserts that 'nla''s payload is at least 8 bytes long.
846 * ---------------------------------------------------------------------------
849 NlAttrGetBe64(const PNL_ATTR nla)
851 return NL_ATTR_GET_AS(nla, BE64);
855 * ---------------------------------------------------------------------------
856 * Returns the 32-bit network byte order value in 'nla''s payload.
858 * Asserts that 'nla''s payload is at least 4 bytes long.
859 * ---------------------------------------------------------------------------
862 NlAttrGetBe32(const PNL_ATTR nla)
864 return NL_ATTR_GET_AS(nla, BE32);
868 * ---------------------------------------------------------------------------
869 * Returns the 16-bit network byte order value in 'nla''s payload.
871 * Asserts that 'nla''s payload is at least 2 bytes long.
872 * ---------------------------------------------------------------------------
875 NlAttrGetBe16(const PNL_ATTR nla)
877 return NL_ATTR_GET_AS(nla, BE16);
881 * ---------------------------------------------------------------------------
882 * Returns the 8-bit network byte order value in 'nla''s payload.
884 * Asserts that 'nla''s payload is at least 1 byte long.
885 * ---------------------------------------------------------------------------
888 NlAttrGetBe8(const PNL_ATTR nla)
890 return NL_ATTR_GET_AS(nla, BE8);
894 * ---------------------------------------------------------------------------
895 * Returns the 8-bit value in 'nla''s payload.
896 * ---------------------------------------------------------------------------
899 NlAttrGetU8(const PNL_ATTR nla)
901 return NL_ATTR_GET_AS(nla, UINT8);
905 * ---------------------------------------------------------------------------
906 * Returns the 16-bit host byte order value in 'nla''s payload.
907 * Asserts that 'nla''s payload is at least 2 bytes long.
908 * ---------------------------------------------------------------------------
911 NlAttrGetU16(const PNL_ATTR nla)
913 return NL_ATTR_GET_AS(nla, UINT16);
917 * ---------------------------------------------------------------------------
918 * Returns the 32-bit host byte order value in 'nla''s payload.
919 * Asserts that 'nla''s payload is at least 4 bytes long.
920 * ---------------------------------------------------------------------------
923 NlAttrGetU32(const PNL_ATTR nla)
925 return NL_ATTR_GET_AS(nla, UINT32);
929 * ---------------------------------------------------------------------------
930 * Returns the 64-bit host byte order value in 'nla''s payload.
931 * Asserts that 'nla''s payload is at least 8 bytes long.
932 * ---------------------------------------------------------------------------
935 NlAttrGetU64(const PNL_ATTR nla)
937 return NL_ATTR_GET_AS(nla, UINT64);
941 * ---------------------------------------------------------------------------
942 * Validate the netlink attribute against the policy
943 * ---------------------------------------------------------------------------
946 NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy)
953 if ((policy->type == NL_A_NO_ATTR) ||
954 (policy->type == NL_A_VAR_LEN) ||
955 (policy->type == NL_A_NESTED)) {
956 /* Do not validate anything for attributes of type var length */
961 /* Figure out min and max length. */
962 minLen = policy->minLen;
964 minLen = NlAttrMinLen(policy->type);
966 maxLen = policy->maxLen;
968 maxLen = NlAttrMaxLen(policy->type);
972 len = NlAttrGetSize(nla);
973 if (len < minLen || len > maxLen) {
974 OVS_LOG_WARN("Attribute: %p, len: %d, not in valid range, "
975 "min: %d, max: %d", nla, len, minLen, maxLen);
979 /* Strings must be null terminated and must not have embedded nulls. */
980 if (policy->type == NL_A_STRING) {
981 if (((PCHAR) nla)[nla->nlaLen - 1]) {
982 OVS_LOG_WARN("Attributes %p lacks null at the end", nla);
986 if (memchr(nla + 1, '\0', len - 1) != NULL) {
987 OVS_LOG_WARN("Attributes %p has bad length", nla);
999 * ---------------------------------------------------------------------------
1000 * Returns an attribute of type 'type' from a series of
1002 * ---------------------------------------------------------------------------
1005 NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type)
1007 PNL_ATTR iter = NULL;
1008 PNL_ATTR ret = NULL;
1011 NL_ATTR_FOR_EACH (iter, left, attrs, size) {
1012 if (NlAttrType(iter) == type) {
1023 * ---------------------------------------------------------------------------
1024 * Returns the first Netlink attribute within 'nla' with the specified
1027 * This function does not validate the attribute's length.
1028 * ---------------------------------------------------------------------------
1031 NlAttrFindNested(const PNL_ATTR nla, UINT16 type)
1033 return NlAttrFind__((const PNL_ATTR)(NlAttrGet(nla)),
1034 NlAttrGetSize(nla), type);
1038 *----------------------------------------------------------------------------
1039 * Parses the netlink message at a given offset (attrOffset)
1040 * as a series of attributes. A pointer to the attribute with type
1041 * 'type' is stored in attrs at index 'type'. policy is used to define the
1042 * attribute type validation parameters.
1043 * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER
1045 * Returns BOOLEAN to indicate success/failure.
1046 *----------------------------------------------------------------------------
1049 NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
1050 UINT32 totalAttrLen,
1051 const NL_POLICY policy[], const UINT32 numPolicy,
1052 PNL_ATTR attrs[], UINT32 numAttrs)
1057 BOOLEAN ret = FALSE;
1058 UINT32 numPolicyAttr = MIN(numPolicy, numAttrs);
1060 RtlZeroMemory(attrs, numAttrs * sizeof *attrs);
1063 /* There is nothing to parse */
1064 if (!(NlMsgAttrsLen(nlMsg))) {
1069 if ((NlMsgSize(nlMsg) < attrOffset)) {
1070 OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d",
1075 NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset),
1078 UINT16 type = NlAttrType(nla);
1079 if (type < numPolicyAttr && policy[type].type != NL_A_NO_ATTR) {
1080 /* Typecasting to keep the compiler happy */
1081 const PNL_POLICY e = (const PNL_POLICY)(&policy[type]);
1082 if (!NlAttrValidate(nla, e)) {
1087 OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, "
1088 "type: %u", nlMsg, type);
1096 OVS_LOG_ERROR("Attributes followed by garbage");
1100 for (iter = 0; iter < numPolicyAttr; iter++) {
1101 const PNL_POLICY e = (const PNL_POLICY)(&policy[iter]);
1102 if (!e->optional && e->type != NL_A_NO_ATTR && !attrs[iter]) {
1103 OVS_LOG_ERROR("Required attr:%d missing", iter);
1115 *----------------------------------------------------------------------------
1116 * Parses the netlink message for nested attributes. attrOffset must be the
1117 * offset of nla which is the header of the nested attribute series.
1118 * Refer nl_parse_nested for more details.
1120 * Returns BOOLEAN to indicate success/failure.
1121 *----------------------------------------------------------------------------
1124 NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
1125 UINT32 totalAttrLen,
1126 const NL_POLICY policy[], const UINT32 numPolicy,
1127 PNL_ATTR attrs[], UINT32 numAttrs)
1129 return NlAttrParse(nlMsg, attrOffset + NLA_HDRLEN,
1130 totalAttrLen - NLA_HDRLEN, policy, numPolicy,