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, sizeof(struct _OVS_MESSAGE)) != 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));
71 return writeOk ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE;
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, sizeof(struct _NL_MSG_HDR)) != 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));
102 return writeOk ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE;
106 * ---------------------------------------------------------------------------
107 * Adds Netlink Header to the NL_BUF.
108 * ---------------------------------------------------------------------------
111 NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg)
113 if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) {
121 * ---------------------------------------------------------------------------
122 * Adds Genl Header to the NL_BUF.
123 * ---------------------------------------------------------------------------
126 NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg)
128 if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) {
136 * ---------------------------------------------------------------------------
137 * Adds OVS Header to the NL_BUF.
138 * ---------------------------------------------------------------------------
141 NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr)
143 if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN,
144 GENL_HDRLEN + NLMSG_HDRLEN))) {
152 * ---------------------------------------------------------------------------
153 * Adds data of length 'len' to the tail end of NL_BUF.
154 * Refer nl_msg_put for more details.
155 * ---------------------------------------------------------------------------
158 NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len)
160 len = NLMSG_ALIGN(len);
161 if (NlBufCopyAtTail(buf, data, len)) {
169 * ---------------------------------------------------------------------------
170 * memsets length 'len' at tail end of NL_BUF.
171 * Refer nl_msg_put_uninit for more details.
172 * ---------------------------------------------------------------------------
175 NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len)
177 len = NLMSG_ALIGN(len);
178 return NlBufCopyAtTailUninit(buf, len);
182 * ---------------------------------------------------------------------------
183 * Adds an attribute to the tail end of buffer. It does
184 * not copy the attribute payload.
185 * Refer nl_msg_put_unspec_uninit for more details.
186 * ---------------------------------------------------------------------------
189 NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)
192 UINT16 totalLen = NLA_HDRLEN + len;
193 PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen));
199 ret = (PCHAR)(nla + 1);
200 nla->nlaLen = totalLen;
208 * ---------------------------------------------------------------------------
209 * Adds an attribute to the tail end of buffer. It copies attribute
211 * Refer nl_msg_put_unspec for more details.
212 * ---------------------------------------------------------------------------
215 NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)
218 PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len);
225 RtlCopyMemory(nlaData, data, len);
232 * ---------------------------------------------------------------------------
233 * Adds an attribute of 'type' and no payload at the tail end of buffer.
234 * Refer nl_msg_put_flag for more details.
235 * ---------------------------------------------------------------------------
238 NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type)
241 PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
251 * ---------------------------------------------------------------------------
252 * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer.
253 * Refer nl_msg_put_u8 for more details.
254 * ---------------------------------------------------------------------------
257 NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value)
259 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
263 * ---------------------------------------------------------------------------
264 * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer.
265 * Refer nl_msg_put_u16 for more details.
266 * ---------------------------------------------------------------------------
269 NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value)
271 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
275 * ---------------------------------------------------------------------------
276 * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer.
277 * Refer nl_msg_put_u32 for more details.
278 * ---------------------------------------------------------------------------
281 NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value)
283 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
287 * ---------------------------------------------------------------------------
288 * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer.
289 * Refer nl_msg_put_u64 for more details.
290 * ---------------------------------------------------------------------------
293 NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value)
295 return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
299 * ---------------------------------------------------------------------------
300 * Adds an attribute of 'type' and string payload.
301 * Refer nl_msg_put_string for more details.
302 * ---------------------------------------------------------------------------
305 NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value)
307 size_t strLen = strlen(value) + 1;
309 /* Attribute length should come within 16 bits (NL_ATTR).
310 * Not a likely case, hence validation only in debug mode. */
311 if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {
316 /* typecast to keep compiler happy */
317 return (NlMsgPutTailUnspec(buf, type, value,
322 * ---------------------------------------------------------------------------
323 * Adds data of length 'len' to the head of NL_BUF.
324 * Refer nl_msg_push for more details.
325 * ---------------------------------------------------------------------------
328 NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len)
330 len = NLMSG_ALIGN(len);
331 if (NlBufCopyAtHead(buf, data, len)) {
339 * ---------------------------------------------------------------------------
340 * memsets length 'len' at head of NL_BUF.
341 * Refer nl_msg_push_uninit for more details.
342 * ---------------------------------------------------------------------------
345 NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len)
347 len = NLMSG_ALIGN(len);
348 return NlBufCopyAtHeadUninit(buf, len);
352 * ---------------------------------------------------------------------------
353 * Adds an attribute to the head of buffer. It does
354 * not copy the attribute payload.
355 * Refer nl_msg_push_unspec_uninit for more details.
356 * ---------------------------------------------------------------------------
359 NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)
362 UINT16 totalLen = NLA_HDRLEN + len;
363 PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen));
369 ret = (PCHAR)(nla + 1);
370 nla->nlaLen = totalLen;
378 * ---------------------------------------------------------------------------
379 * Adds an attribute to the head of buffer. It copies attribute
381 * Refer nl_msg_push_unspec for more details.
382 * ---------------------------------------------------------------------------
385 NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)
388 PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len);
395 RtlCopyMemory(nlaData, data, len);
402 * ---------------------------------------------------------------------------
403 * Adds an attribute of 'type' and no payload at the head of buffer.
404 * Refer nl_msg_push_flag for more details.
405 * ---------------------------------------------------------------------------
408 NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type)
411 PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0);
421 * ---------------------------------------------------------------------------
422 * Adds an attribute of 'type' and 8 bit payload at the head of buffer.
423 * Refer nl_msg_push_u8 for more details.
424 * ---------------------------------------------------------------------------
427 NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value)
429 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
433 * ---------------------------------------------------------------------------
434 * Adds an attribute of 'type' and 16 bit payload at the head of buffer.
435 * Refer nl_msg_push_u16 for more details.
436 * ---------------------------------------------------------------------------
439 NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value)
441 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
445 * ---------------------------------------------------------------------------
446 * Adds an attribute of 'type' and 32 bit payload at the head of buffer.
447 * Refer nl_msg_push_u32 for more details.
448 * ---------------------------------------------------------------------------
451 NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value)
453 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
457 * ---------------------------------------------------------------------------
458 * Adds an attribute of 'type' and 64 bit payload at the head of buffer.
459 * Refer nl_msg_push_u64 for more details.
460 * ---------------------------------------------------------------------------
463 NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value)
465 return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
469 * ---------------------------------------------------------------------------
470 * Adds an attribute of 'type' and string payload.
471 * Refer nl_msg_push_string for more details.
472 * ---------------------------------------------------------------------------
475 NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value)
477 size_t strLen = strlen(value) + 1;
479 /* Attribute length should come within 16 bits (NL_ATTR).
480 * Not a likely case, hence validation only in debug mode. */
481 if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {
486 /* typecast to keep compiler happy */
487 return (NlMsgPutHeadUnspec(buf, type, value,
492 * ---------------------------------------------------------------------------
493 * Adds the header for nested netlink attributes. It
494 * returns the offset of this header. If addition of header fails
495 * then returned value of offset will be zero.
496 * Refer nl_msg_start_nested for more details.
497 * ---------------------------------------------------------------------------
500 NlMsgStartNested(PNL_BUFFER buf, UINT16 type)
502 UINT32 offset = NlBufSize(buf);
503 PCHAR nlaData = NULL;
505 nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
508 /* Value zero must be reated as error by the caller.
509 * This is because an attribute can never be added
510 * at offset zero, it will always come after NL_MSG_HDR,
511 * GENL_HDR and OVS_HEADER. */
519 * ---------------------------------------------------------------------------
520 * Finalizes the nested netlink attribute by updating the nla_len.
521 * offset should be the one returned by NlMsgStartNested.
522 * Refer nl_msg_end_nested for more details.
523 * ---------------------------------------------------------------------------
526 NlMsgEndNested(PNL_BUFFER buf, UINT32 offset)
528 PNL_ATTR attr = (PNL_ATTR)(NlBufAt(buf, offset, sizeof *attr));
530 /* Typecast to keep compiler happy.
531 * Attribute length would never exceed MAX UINT16.*/
532 attr->nlaLen = (UINT16)(NlBufSize(buf) - offset);
536 * --------------------------------------------------------------------------
537 * Appends a nested Netlink attribute of the given 'type', with the 'size'
538 * bytes of content starting at 'data', to 'msg'.
539 * Refer nl_msg_put_nested for more details.
540 * --------------------------------------------------------------------------
543 NlMsgPutNested(PNL_BUFFER buf, UINT16 type,
544 const PVOID data, UINT32 size)
546 UINT32 offset = NlMsgStartNested(buf, type);
551 ret = NlMsgPutTail(buf, data, size);
555 NlMsgEndNested(buf, offset);
558 /* Accessing netlink message payload */
561 * ---------------------------------------------------------------------------
562 * Netlink message accessing the payload.
563 * ---------------------------------------------------------------------------
566 NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset)
568 return ((PCHAR)nlh + offset);
572 * ---------------------------------------------------------------------------
573 * Returns the size of netlink message.
574 * ---------------------------------------------------------------------------
577 NlMsgSize(const PNL_MSG_HDR nlh)
579 return nlh->nlmsgLen;
583 * ---------------------------------------------------------------------------
584 * Aligns the size of Netlink message.
585 * ---------------------------------------------------------------------------
588 NlMsgAlignSize(const PNL_MSG_HDR nlh)
590 nlh->nlmsgLen = NLMSG_ALIGN(nlh->nlmsgLen);
595 * ---------------------------------------------------------------------------
596 * Sets the size of Netlink message.
597 * ---------------------------------------------------------------------------
600 NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen)
602 nlh->nlmsgLen = msgLen;
606 * ---------------------------------------------------------------------------
607 * Returns pointer to nlmsg payload.
608 * ---------------------------------------------------------------------------
611 NlHdrPayload(const PNL_MSG_HDR nlh)
613 return ((PCHAR)nlh + NLMSG_HDRLEN);
617 * ---------------------------------------------------------------------------
618 * Returns length of nlmsg payload.
619 * ---------------------------------------------------------------------------
622 NlHdrPayloadLen(const PNL_MSG_HDR nlh)
624 return nlh->nlmsgLen - NLMSG_HDRLEN;
628 * ---------------------------------------------------------------------------
629 * Returns pointer to nlmsg attributes.
630 * ---------------------------------------------------------------------------
633 NlMsgAttrs(const PNL_MSG_HDR nlh)
635 return (PNL_ATTR) (NlHdrPayload(nlh) + GENL_HDRLEN + OVS_HDRLEN);
639 * ---------------------------------------------------------------------------
640 * Returns size of to nlmsg attributes.
641 * ---------------------------------------------------------------------------
644 NlMsgAttrsLen(const PNL_MSG_HDR nlh)
646 return NlHdrPayloadLen(nlh) - GENL_HDRLEN - OVS_HDRLEN;
649 /* Netlink message parse. */
652 * ---------------------------------------------------------------------------
653 * Returns next netlink message in the stream.
654 * ---------------------------------------------------------------------------
657 NlMsgNext(const PNL_MSG_HDR nlh)
659 return (PNL_MSG_HDR)((PCHAR)nlh +
660 NLMSG_ALIGN(nlh->nlmsgLen));
664 * ---------------------------------------------------------------------------
665 * Netlink Attr helper APIs.
666 * ---------------------------------------------------------------------------
669 NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen)
671 return (maxlen >= sizeof *nla
672 && nla->nlaLen >= sizeof *nla
673 && nla->nlaLen <= maxlen);
677 * ---------------------------------------------------------------------------
678 * Returns alligned length of the attribute.
679 * ---------------------------------------------------------------------------
682 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen)
684 UINT32 len = NLA_ALIGN(nla->nlaLen);
686 return len <= maxlen ? len : nla->nlaLen;
690 * ---------------------------------------------------------------------------
691 * Default minimum payload size for each type of attribute.
692 * ---------------------------------------------------------------------------
695 NlAttrMinLen(NL_ATTR_TYPE type)
698 case NL_A_NO_ATTR: return 0;
699 case NL_A_UNSPEC: return 0;
700 case NL_A_U8: return 1;
701 case NL_A_U16: return 2;
702 case NL_A_U32: return 4;
703 case NL_A_U64: return 8;
704 case NL_A_STRING: return 1;
705 case NL_A_FLAG: return 0;
706 case NL_A_NESTED: return 0;
707 case N_NL_ATTR_TYPES:
709 OVS_LOG_WARN("Unsupprted attribute type: %d", type);
713 /* To keep compiler happy */
718 * ---------------------------------------------------------------------------
719 * Default maximum payload size for each type of attribute.
720 * ---------------------------------------------------------------------------
723 NlAttrMaxLen(NL_ATTR_TYPE type)
726 case NL_A_NO_ATTR: return SIZE_MAX;
727 case NL_A_UNSPEC: return SIZE_MAX;
728 case NL_A_U8: return 1;
729 case NL_A_U16: return 2;
730 case NL_A_U32: return 4;
731 case NL_A_U64: return 8;
732 case NL_A_STRING: return MAXUINT16;
733 case NL_A_FLAG: return SIZE_MAX;
734 case NL_A_NESTED: return SIZE_MAX;
735 case N_NL_ATTR_TYPES:
737 OVS_LOG_WARN("Unsupprted attribute type: %d", type);
741 /* To keep compiler happy */
745 /* Netlink attribute iteration. */
748 * ---------------------------------------------------------------------------
749 * Returns the next attribute.
750 * ---------------------------------------------------------------------------
753 NlAttrNext(const PNL_ATTR nla)
755 return (PNL_ATTR)((UINT8 *)nla + NLA_ALIGN(nla->nlaLen));
759 * --------------------------------------------------------------------------
760 * Returns the bits of 'nla->nlaType' that are significant for determining
762 * --------------------------------------------------------------------------
765 NlAttrType(const PNL_ATTR nla)
767 return nla->nlaType & NLA_TYPE_MASK;
771 * --------------------------------------------------------------------------
772 * Returns the netlink attribute data.
773 * --------------------------------------------------------------------------
776 NlAttrData(const PNL_ATTR nla)
778 return ((PCHAR)nla + NLA_HDRLEN);
782 * ---------------------------------------------------------------------------
783 * Returns the number of bytes in the payload of attribute 'nla'.
784 * ---------------------------------------------------------------------------
787 NlAttrGetSize(const PNL_ATTR nla)
789 return nla->nlaLen - NLA_HDRLEN;
793 * ---------------------------------------------------------------------------
794 * Returns the first byte in the payload of attribute 'nla'.
795 * ---------------------------------------------------------------------------
798 NlAttrGet(const PNL_ATTR nla)
800 ASSERT(nla->nlaLen >= NLA_HDRLEN);
805 * ---------------------------------------------------------------------------
806 * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the
807 * first byte of the payload.
808 * ---------------------------------------------------------------------------
811 PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size)
813 UNREFERENCED_PARAMETER(size);
814 ASSERT(nla->nlaLen >= NLA_HDRLEN + size);
819 * ---------------------------------------------------------------------------
820 * Returns the 64-bit network byte order value in 'nla''s payload.
822 * Asserts that 'nla''s payload is at least 8 bytes long.
823 * ---------------------------------------------------------------------------
826 NlAttrGetBe64(const PNL_ATTR nla)
828 return NL_ATTR_GET_AS(nla, BE64);
832 * ---------------------------------------------------------------------------
833 * Returns the 32-bit network byte order value in 'nla''s payload.
835 * Asserts that 'nla''s payload is at least 4 bytes long.
836 * ---------------------------------------------------------------------------
839 NlAttrGetBe32(const PNL_ATTR nla)
841 return NL_ATTR_GET_AS(nla, BE32);
845 * ---------------------------------------------------------------------------
846 * Returns the 16-bit network byte order value in 'nla''s payload.
848 * Asserts that 'nla''s payload is at least 2 bytes long.
849 * ---------------------------------------------------------------------------
852 NlAttrGetBe16(const PNL_ATTR nla)
854 return NL_ATTR_GET_AS(nla, BE16);
858 * ---------------------------------------------------------------------------
859 * Returns the 8-bit network byte order value in 'nla''s payload.
861 * Asserts that 'nla''s payload is at least 1 byte long.
862 * ---------------------------------------------------------------------------
865 NlAttrGetBe8(const PNL_ATTR nla)
867 return NL_ATTR_GET_AS(nla, BE8);
871 * ---------------------------------------------------------------------------
872 * Returns the 8-bit value in 'nla''s payload.
873 * ---------------------------------------------------------------------------
876 NlAttrGetU8(const PNL_ATTR nla)
878 return NL_ATTR_GET_AS(nla, UINT8);
882 * ---------------------------------------------------------------------------
883 * Returns the 16-bit host byte order value in 'nla''s payload.
884 * Asserts that 'nla''s payload is at least 2 bytes long.
885 * ---------------------------------------------------------------------------
888 NlAttrGetU16(const PNL_ATTR nla)
890 return NL_ATTR_GET_AS(nla, UINT16);
894 * ---------------------------------------------------------------------------
895 * Returns the 32-bit host byte order value in 'nla''s payload.
896 * Asserts that 'nla''s payload is at least 4 bytes long.
897 * ---------------------------------------------------------------------------
900 NlAttrGetU32(const PNL_ATTR nla)
902 return NL_ATTR_GET_AS(nla, UINT32);
906 * ---------------------------------------------------------------------------
907 * Returns the 64-bit host byte order value in 'nla''s payload.
908 * Asserts that 'nla''s payload is at least 8 bytes long.
909 * ---------------------------------------------------------------------------
912 NlAttrGetU64(const PNL_ATTR nla)
914 return NL_ATTR_GET_AS(nla, UINT64);
918 * ---------------------------------------------------------------------------
919 * Validate the netlink attribute against the policy
920 * ---------------------------------------------------------------------------
923 NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy)
930 if ((policy->type == NL_A_NO_ATTR) ||
931 (policy->type == NL_A_VAR_LEN) ||
932 (policy->type == NL_A_NESTED)) {
933 /* Do not validate anything for attributes of type var length */
938 /* Figure out min and max length. */
939 minLen = policy->minLen;
941 minLen = NlAttrMinLen(policy->type);
943 maxLen = policy->maxLen;
945 maxLen = NlAttrMaxLen(policy->type);
949 len = NlAttrGetSize(nla);
950 if (len < minLen || len > maxLen) {
951 OVS_LOG_WARN("Attribute: %p, len: %d, not in valid range, "
952 "min: %d, max: %d", nla, len, minLen, maxLen);
956 /* Strings must be null terminated and must not have embedded nulls. */
957 if (policy->type == NL_A_STRING) {
958 if (((PCHAR) nla)[nla->nlaLen - 1]) {
959 OVS_LOG_WARN("Attributes %p lacks null at the end", nla);
963 if (memchr(nla + 1, '\0', len - 1) != NULL) {
964 OVS_LOG_WARN("Attributes %p has bad length", nla);
976 * ---------------------------------------------------------------------------
977 * Returns an attribute of type 'type' from a series of
979 * ---------------------------------------------------------------------------
982 NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type)
984 PNL_ATTR iter = NULL;
988 NL_ATTR_FOR_EACH (iter, left, attrs, size) {
989 if (NlAttrType(iter) == type) {
1000 * ---------------------------------------------------------------------------
1001 * Returns the first Netlink attribute within 'nla' with the specified
1004 * This function does not validate the attribute's length.
1005 * ---------------------------------------------------------------------------
1008 NlAttrFindNested(const PNL_ATTR nla, UINT16 type)
1010 return NlAttrFind__((const PNL_ATTR)(NlAttrGet(nla)),
1011 NlAttrGetSize(nla), type);
1015 *----------------------------------------------------------------------------
1016 * Parses the netlink message at a given offset (attrOffset)
1017 * as a series of attributes. A pointer to the attribute with type
1018 * 'type' is stored in attrs at index 'type'. policy is used to define the
1019 * attribute type validation parameters.
1020 * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER
1022 * Returns BOOLEAN to indicate success/failure.
1023 *----------------------------------------------------------------------------
1026 NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
1027 UINT32 totalAttrLen,
1028 const NL_POLICY policy[],
1029 PNL_ATTR attrs[], UINT32 n_attrs)
1034 BOOLEAN ret = FALSE;
1036 RtlZeroMemory(attrs, n_attrs * sizeof *attrs);
1039 /* There is nothing to parse */
1040 if (!(NlMsgAttrsLen(nlMsg))) {
1045 if ((NlMsgSize(nlMsg) < attrOffset)) {
1046 OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d",
1051 NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset),
1054 UINT16 type = NlAttrType(nla);
1055 if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) {
1056 /* Typecasting to keep the compiler happy */
1057 const PNL_POLICY e = (const PNL_POLICY)(&policy[type]);
1058 if (!NlAttrValidate(nla, e)) {
1063 OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, "
1064 "type: %u", nlMsg, type);
1072 OVS_LOG_ERROR("Attributes followed by garbage");
1076 for (iter = 0; iter < n_attrs; iter++) {
1077 const PNL_POLICY e = (const PNL_POLICY)(&policy[iter]);
1078 if (!e->optional && e->type != NL_A_NO_ATTR && !attrs[iter]) {
1079 OVS_LOG_ERROR("Required attr:%d missing", iter);
1091 *----------------------------------------------------------------------------
1092 * Parses the netlink message for nested attributes. attrOffset must be the
1093 * offset of nla which is the header of the nested attribute series.
1094 * Refer nl_parse_nested for more details.
1096 * Returns BOOLEAN to indicate success/failure.
1097 *----------------------------------------------------------------------------
1100 NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
1101 UINT32 totalAttrLen,
1102 const NL_POLICY policy[],
1103 PNL_ATTR attrs[], UINT32 n_attrs)
1105 return NlAttrParse(nlMsg, attrOffset + NLA_HDRLEN,
1106 totalAttrLen - NLA_HDRLEN, policy, attrs, n_attrs);