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 NlBufInit(&nlBuffer
, (PCHAR
)msgError
, sizeof *msgError
);
116 NlFillNlHdr(&nlBuffer
, NLMSG_ERROR
, 0,
117 msgIn
->nlMsg
.nlmsgSeq
, msgIn
->nlMsg
.nlmsgPid
);
119 msgError
->errorMsg
.error
= errorCode
;
120 msgError
->errorMsg
.nlMsg
= msgIn
->nlMsg
;
121 msgError
->nlMsg
.nlmsgLen
= sizeof(OVS_MESSAGE_ERROR
);
125 * ---------------------------------------------------------------------------
126 * Adds Netlink Header to the NL_BUF.
127 * ---------------------------------------------------------------------------
130 NlMsgPutNlHdr(PNL_BUFFER buf
, PNL_MSG_HDR nlMsg
)
132 if ((NlBufCopyAtOffset(buf
, (PCHAR
)nlMsg
, NLMSG_HDRLEN
, 0))) {
140 * ---------------------------------------------------------------------------
141 * Adds Genl Header to the NL_BUF.
142 * ---------------------------------------------------------------------------
145 NlMsgPutGenlHdr(PNL_BUFFER buf
, PGENL_MSG_HDR genlMsg
)
147 if ((NlBufCopyAtOffset(buf
, (PCHAR
)genlMsg
, GENL_HDRLEN
, NLMSG_HDRLEN
))) {
155 * ---------------------------------------------------------------------------
156 * Adds OVS Header to the NL_BUF.
157 * ---------------------------------------------------------------------------
160 NlMsgPutOvsHdr(PNL_BUFFER buf
, POVS_HDR ovsHdr
)
162 if ((NlBufCopyAtOffset(buf
, (PCHAR
)ovsHdr
, OVS_HDRLEN
,
163 GENL_HDRLEN
+ NLMSG_HDRLEN
))) {
171 * ---------------------------------------------------------------------------
172 * Adds data of length 'len' to the tail end of NL_BUF.
173 * Refer nl_msg_put for more details.
174 * ---------------------------------------------------------------------------
177 NlMsgPutTail(PNL_BUFFER buf
, const PCHAR data
, UINT32 len
)
179 len
= NLMSG_ALIGN(len
);
180 if (NlBufCopyAtTail(buf
, data
, len
)) {
188 * ---------------------------------------------------------------------------
189 * memsets length 'len' at tail end of NL_BUF.
190 * Refer nl_msg_put_uninit for more details.
191 * ---------------------------------------------------------------------------
194 NlMsgPutTailUninit(PNL_BUFFER buf
, UINT32 len
)
196 len
= NLMSG_ALIGN(len
);
197 return NlBufCopyAtTailUninit(buf
, len
);
201 * ---------------------------------------------------------------------------
202 * Adds an attribute to the tail end of buffer. It does
203 * not copy the attribute payload.
204 * Refer nl_msg_put_unspec_uninit for more details.
205 * ---------------------------------------------------------------------------
208 NlMsgPutTailUnspecUninit(PNL_BUFFER buf
, UINT16 type
, UINT16 len
)
211 UINT16 totalLen
= NLA_HDRLEN
+ len
;
212 PNL_ATTR nla
= (PNL_ATTR
)(NlMsgPutTailUninit(buf
, totalLen
));
218 ret
= (PCHAR
)(nla
+ 1);
219 nla
->nlaLen
= totalLen
;
227 * ---------------------------------------------------------------------------
228 * Adds an attribute to the tail end of buffer. It copies attribute
230 * Refer nl_msg_put_unspec for more details.
231 * ---------------------------------------------------------------------------
234 NlMsgPutTailUnspec(PNL_BUFFER buf
, UINT16 type
, PCHAR data
, UINT16 len
)
237 PCHAR nlaData
= NlMsgPutTailUnspecUninit(buf
, type
, len
);
244 RtlCopyMemory(nlaData
, data
, len
);
251 * ---------------------------------------------------------------------------
252 * Adds an attribute of 'type' and no payload at the tail end of buffer.
253 * Refer nl_msg_put_flag for more details.
254 * ---------------------------------------------------------------------------
257 NlMsgPutTailFlag(PNL_BUFFER buf
, UINT16 type
)
260 PCHAR nlaData
= NlMsgPutTailUnspecUninit(buf
, type
, 0);
270 * ---------------------------------------------------------------------------
271 * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer.
272 * Refer nl_msg_put_u8 for more details.
273 * ---------------------------------------------------------------------------
276 NlMsgPutTailU8(PNL_BUFFER buf
, UINT16 type
, UINT8 value
)
278 return (NlMsgPutTailUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
282 * ---------------------------------------------------------------------------
283 * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer.
284 * Refer nl_msg_put_u16 for more details.
285 * ---------------------------------------------------------------------------
288 NlMsgPutTailU16(PNL_BUFFER buf
, UINT16 type
, UINT16 value
)
290 return (NlMsgPutTailUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
294 * ---------------------------------------------------------------------------
295 * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer.
296 * Refer nl_msg_put_u32 for more details.
297 * ---------------------------------------------------------------------------
300 NlMsgPutTailU32(PNL_BUFFER buf
, UINT16 type
, UINT32 value
)
302 return (NlMsgPutTailUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
306 * ---------------------------------------------------------------------------
307 * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer.
308 * Refer nl_msg_put_u64 for more details.
309 * ---------------------------------------------------------------------------
312 NlMsgPutTailU64(PNL_BUFFER buf
, UINT16 type
, UINT64 value
)
314 return (NlMsgPutTailUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
318 * ---------------------------------------------------------------------------
319 * Adds an attribute of 'type' and string payload.
320 * Refer nl_msg_put_string for more details.
321 * ---------------------------------------------------------------------------
324 NlMsgPutTailString(PNL_BUFFER buf
, UINT16 type
, PCHAR value
)
326 size_t strLen
= strlen(value
) + 1;
328 /* Attribute length should come within 16 bits (NL_ATTR).
329 * Not a likely case, hence validation only in debug mode. */
330 if ((strLen
+ PAD_SIZE(strLen
, NLA_ALIGNTO
)) > MAXUINT16
) {
335 /* typecast to keep compiler happy */
336 return (NlMsgPutTailUnspec(buf
, type
, value
,
341 * ---------------------------------------------------------------------------
342 * Adds data of length 'len' to the head of NL_BUF.
343 * Refer nl_msg_push for more details.
344 * ---------------------------------------------------------------------------
347 NlMsgPutHead(PNL_BUFFER buf
, const PCHAR data
, UINT32 len
)
349 len
= NLMSG_ALIGN(len
);
350 if (NlBufCopyAtHead(buf
, data
, len
)) {
358 * ---------------------------------------------------------------------------
359 * memsets length 'len' at head of NL_BUF.
360 * Refer nl_msg_push_uninit for more details.
361 * ---------------------------------------------------------------------------
364 NlMsgPutHeadUninit(PNL_BUFFER buf
, UINT32 len
)
366 len
= NLMSG_ALIGN(len
);
367 return NlBufCopyAtHeadUninit(buf
, len
);
371 * ---------------------------------------------------------------------------
372 * Adds an attribute to the head of buffer. It does
373 * not copy the attribute payload.
374 * Refer nl_msg_push_unspec_uninit for more details.
375 * ---------------------------------------------------------------------------
378 NlMsgPutHeadUnspecUninit(PNL_BUFFER buf
, UINT16 type
, UINT16 len
)
381 UINT16 totalLen
= NLA_HDRLEN
+ len
;
382 PNL_ATTR nla
= (PNL_ATTR
)(NlMsgPutHeadUninit(buf
, totalLen
));
388 ret
= (PCHAR
)(nla
+ 1);
389 nla
->nlaLen
= totalLen
;
397 * ---------------------------------------------------------------------------
398 * Adds an attribute to the head of buffer. It copies attribute
400 * Refer nl_msg_push_unspec for more details.
401 * ---------------------------------------------------------------------------
404 NlMsgPutHeadUnspec(PNL_BUFFER buf
, UINT16 type
, PCHAR data
, UINT16 len
)
407 PCHAR nlaData
= NlMsgPutHeadUnspecUninit(buf
, type
, len
);
414 RtlCopyMemory(nlaData
, data
, len
);
421 * ---------------------------------------------------------------------------
422 * Adds an attribute of 'type' and no payload at the head of buffer.
423 * Refer nl_msg_push_flag for more details.
424 * ---------------------------------------------------------------------------
427 NlMsgPutHeadFlag(PNL_BUFFER buf
, UINT16 type
)
430 PCHAR nlaData
= NlMsgPutHeadUnspecUninit(buf
, type
, 0);
440 * ---------------------------------------------------------------------------
441 * Adds an attribute of 'type' and 8 bit payload at the head of buffer.
442 * Refer nl_msg_push_u8 for more details.
443 * ---------------------------------------------------------------------------
446 NlMsgPutHeadU8(PNL_BUFFER buf
, UINT16 type
, UINT8 value
)
448 return (NlMsgPutHeadUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
452 * ---------------------------------------------------------------------------
453 * Adds an attribute of 'type' and 16 bit payload at the head of buffer.
454 * Refer nl_msg_push_u16 for more details.
455 * ---------------------------------------------------------------------------
458 NlMsgPutHeadU16(PNL_BUFFER buf
, UINT16 type
, UINT16 value
)
460 return (NlMsgPutHeadUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
464 * ---------------------------------------------------------------------------
465 * Adds an attribute of 'type' and 32 bit payload at the head of buffer.
466 * Refer nl_msg_push_u32 for more details.
467 * ---------------------------------------------------------------------------
470 NlMsgPutHeadU32(PNL_BUFFER buf
, UINT16 type
, UINT32 value
)
472 return (NlMsgPutHeadUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
476 * ---------------------------------------------------------------------------
477 * Adds an attribute of 'type' and 64 bit payload at the head of buffer.
478 * Refer nl_msg_push_u64 for more details.
479 * ---------------------------------------------------------------------------
482 NlMsgPutHeadU64(PNL_BUFFER buf
, UINT16 type
, UINT64 value
)
484 return (NlMsgPutHeadUnspec(buf
, type
, (PCHAR
)(&value
), sizeof(value
)));
488 * ---------------------------------------------------------------------------
489 * Adds an attribute of 'type' and string payload.
490 * Refer nl_msg_push_string for more details.
491 * ---------------------------------------------------------------------------
494 NlMsgPutHeadString(PNL_BUFFER buf
, UINT16 type
, PCHAR value
)
496 size_t strLen
= strlen(value
) + 1;
498 /* Attribute length should come within 16 bits (NL_ATTR).
499 * Not a likely case, hence validation only in debug mode. */
500 if ((strLen
+ PAD_SIZE(strLen
, NLA_ALIGNTO
)) > MAXUINT16
) {
505 /* typecast to keep compiler happy */
506 return (NlMsgPutHeadUnspec(buf
, type
, value
,
511 * ---------------------------------------------------------------------------
512 * Adds the header for nested netlink attributes. It
513 * returns the offset of this header. If addition of header fails
514 * then returned value of offset will be zero.
515 * Refer nl_msg_start_nested for more details.
516 * ---------------------------------------------------------------------------
519 NlMsgStartNested(PNL_BUFFER buf
, UINT16 type
)
521 UINT32 offset
= NlBufSize(buf
);
522 PCHAR nlaData
= NULL
;
524 nlaData
= NlMsgPutTailUnspecUninit(buf
, type
, 0);
527 /* Value zero must be reated as error by the caller.
528 * This is because an attribute can never be added
529 * at offset zero, it will always come after NL_MSG_HDR,
530 * GENL_HDR and OVS_HEADER. */
538 * ---------------------------------------------------------------------------
539 * Finalizes the nested netlink attribute by updating the nla_len.
540 * offset should be the one returned by NlMsgStartNested.
541 * Refer nl_msg_end_nested for more details.
542 * ---------------------------------------------------------------------------
545 NlMsgEndNested(PNL_BUFFER buf
, UINT32 offset
)
547 PNL_ATTR attr
= (PNL_ATTR
)(NlBufAt(buf
, offset
, sizeof *attr
));
549 /* Typecast to keep compiler happy.
550 * Attribute length would never exceed MAX UINT16.*/
551 attr
->nlaLen
= (UINT16
)(NlBufSize(buf
) - offset
);
555 * --------------------------------------------------------------------------
556 * Appends a nested Netlink attribute of the given 'type', with the 'size'
557 * bytes of content starting at 'data', to 'msg'.
558 * Refer nl_msg_put_nested for more details.
559 * --------------------------------------------------------------------------
562 NlMsgPutNested(PNL_BUFFER buf
, UINT16 type
,
563 const PVOID data
, UINT32 size
)
565 UINT32 offset
= NlMsgStartNested(buf
, type
);
570 ret
= NlMsgPutTail(buf
, data
, size
);
574 NlMsgEndNested(buf
, offset
);
577 /* Accessing netlink message payload */
580 * ---------------------------------------------------------------------------
581 * Netlink message accessing the payload.
582 * ---------------------------------------------------------------------------
585 NlMsgAt(const PNL_MSG_HDR nlh
, UINT32 offset
)
587 return ((PCHAR
)nlh
+ offset
);
591 * ---------------------------------------------------------------------------
592 * Returns the size of netlink message.
593 * ---------------------------------------------------------------------------
596 NlMsgSize(const PNL_MSG_HDR nlh
)
598 return nlh
->nlmsgLen
;
602 * ---------------------------------------------------------------------------
603 * Aligns the size of Netlink message.
604 * ---------------------------------------------------------------------------
607 NlMsgAlignSize(const PNL_MSG_HDR nlh
)
609 nlh
->nlmsgLen
= NLMSG_ALIGN(nlh
->nlmsgLen
);
614 * ---------------------------------------------------------------------------
615 * Sets the size of Netlink message.
616 * ---------------------------------------------------------------------------
619 NlMsgSetSize(const PNL_MSG_HDR nlh
, UINT32 msgLen
)
621 nlh
->nlmsgLen
= msgLen
;
625 * ---------------------------------------------------------------------------
626 * Returns pointer to nlmsg payload.
627 * ---------------------------------------------------------------------------
630 NlHdrPayload(const PNL_MSG_HDR nlh
)
632 return ((PCHAR
)nlh
+ NLMSG_HDRLEN
);
636 * ---------------------------------------------------------------------------
637 * Returns length of nlmsg payload.
638 * ---------------------------------------------------------------------------
641 NlHdrPayloadLen(const PNL_MSG_HDR nlh
)
643 return nlh
->nlmsgLen
- NLMSG_HDRLEN
;
647 * ---------------------------------------------------------------------------
648 * Returns pointer to nlmsg attributes.
649 * ---------------------------------------------------------------------------
652 NlMsgAttrs(const PNL_MSG_HDR nlh
)
654 return (PNL_ATTR
) (NlHdrPayload(nlh
) + GENL_HDRLEN
+ OVS_HDRLEN
);
658 * ---------------------------------------------------------------------------
659 * Returns size of to nlmsg attributes.
660 * ---------------------------------------------------------------------------
663 NlMsgAttrsLen(const PNL_MSG_HDR nlh
)
665 return NlHdrPayloadLen(nlh
) - GENL_HDRLEN
- OVS_HDRLEN
;
668 /* Netlink message parse. */
671 * ---------------------------------------------------------------------------
672 * Returns next netlink message in the stream.
673 * ---------------------------------------------------------------------------
676 NlMsgNext(const PNL_MSG_HDR nlh
)
678 return (PNL_MSG_HDR
)((PCHAR
)nlh
+
679 NLMSG_ALIGN(nlh
->nlmsgLen
));
683 * ---------------------------------------------------------------------------
684 * Netlink Attr helper APIs.
685 * ---------------------------------------------------------------------------
688 NlAttrIsValid(const PNL_ATTR nla
, UINT32 maxlen
)
690 return (maxlen
>= sizeof *nla
691 && nla
->nlaLen
>= sizeof *nla
692 && nla
->nlaLen
<= maxlen
);
696 * ---------------------------------------------------------------------------
697 * Returns alligned length of the attribute.
698 * ---------------------------------------------------------------------------
701 NlAttrLenPad(const PNL_ATTR nla
, UINT32 maxlen
)
703 UINT32 len
= NLA_ALIGN(nla
->nlaLen
);
705 return len
<= maxlen
? len
: nla
->nlaLen
;
709 * ---------------------------------------------------------------------------
710 * Default minimum payload size for each type of attribute.
711 * ---------------------------------------------------------------------------
714 NlAttrMinLen(NL_ATTR_TYPE type
)
717 case NL_A_NO_ATTR
: return 0;
718 case NL_A_UNSPEC
: return 0;
719 case NL_A_U8
: return 1;
720 case NL_A_U16
: return 2;
721 case NL_A_U32
: return 4;
722 case NL_A_U64
: return 8;
723 case NL_A_STRING
: return 1;
724 case NL_A_FLAG
: return 0;
725 case NL_A_NESTED
: return 0;
726 case N_NL_ATTR_TYPES
:
728 OVS_LOG_WARN("Unsupprted attribute type: %d", type
);
732 /* To keep compiler happy */
737 * ---------------------------------------------------------------------------
738 * Default maximum payload size for each type of attribute.
739 * ---------------------------------------------------------------------------
742 NlAttrMaxLen(NL_ATTR_TYPE type
)
745 case NL_A_NO_ATTR
: return SIZE_MAX
;
746 case NL_A_UNSPEC
: return SIZE_MAX
;
747 case NL_A_U8
: return 1;
748 case NL_A_U16
: return 2;
749 case NL_A_U32
: return 4;
750 case NL_A_U64
: return 8;
751 case NL_A_STRING
: return MAXUINT16
;
752 case NL_A_FLAG
: return SIZE_MAX
;
753 case NL_A_NESTED
: return SIZE_MAX
;
754 case N_NL_ATTR_TYPES
:
756 OVS_LOG_WARN("Unsupprted attribute type: %d", type
);
760 /* To keep compiler happy */
764 /* Netlink attribute iteration. */
767 * ---------------------------------------------------------------------------
768 * Returns the next attribute.
769 * ---------------------------------------------------------------------------
772 NlAttrNext(const PNL_ATTR nla
)
774 return (PNL_ATTR
)((UINT8
*)nla
+ NLA_ALIGN(nla
->nlaLen
));
778 * --------------------------------------------------------------------------
779 * Returns the bits of 'nla->nlaType' that are significant for determining
781 * --------------------------------------------------------------------------
784 NlAttrType(const PNL_ATTR nla
)
786 return nla
->nlaType
& NLA_TYPE_MASK
;
790 * --------------------------------------------------------------------------
791 * Returns the netlink attribute data.
792 * --------------------------------------------------------------------------
795 NlAttrData(const PNL_ATTR nla
)
797 return ((PCHAR
)nla
+ NLA_HDRLEN
);
801 * ---------------------------------------------------------------------------
802 * Returns the number of bytes in the payload of attribute 'nla'.
803 * ---------------------------------------------------------------------------
806 NlAttrGetSize(const PNL_ATTR nla
)
808 return nla
->nlaLen
- NLA_HDRLEN
;
812 * ---------------------------------------------------------------------------
813 * Returns the first byte in the payload of attribute 'nla'.
814 * ---------------------------------------------------------------------------
817 NlAttrGet(const PNL_ATTR nla
)
819 ASSERT(nla
->nlaLen
>= NLA_HDRLEN
);
824 * ---------------------------------------------------------------------------
825 * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the
826 * first byte of the payload.
827 * ---------------------------------------------------------------------------
830 PVOID
NlAttrGetUnspec(const PNL_ATTR nla
, UINT32 size
)
832 UNREFERENCED_PARAMETER(size
);
833 ASSERT(nla
->nlaLen
>= NLA_HDRLEN
+ size
);
838 * ---------------------------------------------------------------------------
839 * Returns the 64-bit network byte order value in 'nla''s payload.
841 * Asserts that 'nla''s payload is at least 8 bytes long.
842 * ---------------------------------------------------------------------------
845 NlAttrGetBe64(const PNL_ATTR nla
)
847 return NL_ATTR_GET_AS(nla
, BE64
);
851 * ---------------------------------------------------------------------------
852 * Returns the 32-bit network byte order value in 'nla''s payload.
854 * Asserts that 'nla''s payload is at least 4 bytes long.
855 * ---------------------------------------------------------------------------
858 NlAttrGetBe32(const PNL_ATTR nla
)
860 return NL_ATTR_GET_AS(nla
, BE32
);
864 * ---------------------------------------------------------------------------
865 * Returns the 16-bit network byte order value in 'nla''s payload.
867 * Asserts that 'nla''s payload is at least 2 bytes long.
868 * ---------------------------------------------------------------------------
871 NlAttrGetBe16(const PNL_ATTR nla
)
873 return NL_ATTR_GET_AS(nla
, BE16
);
877 * ---------------------------------------------------------------------------
878 * Returns the 8-bit network byte order value in 'nla''s payload.
880 * Asserts that 'nla''s payload is at least 1 byte long.
881 * ---------------------------------------------------------------------------
884 NlAttrGetBe8(const PNL_ATTR nla
)
886 return NL_ATTR_GET_AS(nla
, BE8
);
890 * ---------------------------------------------------------------------------
891 * Returns the 8-bit value in 'nla''s payload.
892 * ---------------------------------------------------------------------------
895 NlAttrGetU8(const PNL_ATTR nla
)
897 return NL_ATTR_GET_AS(nla
, UINT8
);
901 * ---------------------------------------------------------------------------
902 * Returns the 16-bit host byte order value in 'nla''s payload.
903 * Asserts that 'nla''s payload is at least 2 bytes long.
904 * ---------------------------------------------------------------------------
907 NlAttrGetU16(const PNL_ATTR nla
)
909 return NL_ATTR_GET_AS(nla
, UINT16
);
913 * ---------------------------------------------------------------------------
914 * Returns the 32-bit host byte order value in 'nla''s payload.
915 * Asserts that 'nla''s payload is at least 4 bytes long.
916 * ---------------------------------------------------------------------------
919 NlAttrGetU32(const PNL_ATTR nla
)
921 return NL_ATTR_GET_AS(nla
, UINT32
);
925 * ---------------------------------------------------------------------------
926 * Returns the 64-bit host byte order value in 'nla''s payload.
927 * Asserts that 'nla''s payload is at least 8 bytes long.
928 * ---------------------------------------------------------------------------
931 NlAttrGetU64(const PNL_ATTR nla
)
933 return NL_ATTR_GET_AS(nla
, UINT64
);
937 * ---------------------------------------------------------------------------
938 * Validate the netlink attribute against the policy
939 * ---------------------------------------------------------------------------
942 NlAttrValidate(const PNL_ATTR nla
, const PNL_POLICY policy
)
949 if ((policy
->type
== NL_A_NO_ATTR
) ||
950 (policy
->type
== NL_A_VAR_LEN
) ||
951 (policy
->type
== NL_A_NESTED
)) {
952 /* Do not validate anything for attributes of type var length */
957 /* Figure out min and max length. */
958 minLen
= policy
->minLen
;
960 minLen
= NlAttrMinLen(policy
->type
);
962 maxLen
= policy
->maxLen
;
964 maxLen
= NlAttrMaxLen(policy
->type
);
968 len
= NlAttrGetSize(nla
);
969 if (len
< minLen
|| len
> maxLen
) {
970 OVS_LOG_WARN("Attribute: %p, len: %d, not in valid range, "
971 "min: %d, max: %d", nla
, len
, minLen
, maxLen
);
975 /* Strings must be null terminated and must not have embedded nulls. */
976 if (policy
->type
== NL_A_STRING
) {
977 if (((PCHAR
) nla
)[nla
->nlaLen
- 1]) {
978 OVS_LOG_WARN("Attributes %p lacks null at the end", nla
);
982 if (memchr(nla
+ 1, '\0', len
- 1) != NULL
) {
983 OVS_LOG_WARN("Attributes %p has bad length", nla
);
995 * ---------------------------------------------------------------------------
996 * Returns an attribute of type 'type' from a series of
998 * ---------------------------------------------------------------------------
1001 NlAttrFind__(const PNL_ATTR attrs
, UINT32 size
, UINT16 type
)
1003 PNL_ATTR iter
= NULL
;
1004 PNL_ATTR ret
= NULL
;
1007 NL_ATTR_FOR_EACH (iter
, left
, attrs
, size
) {
1008 if (NlAttrType(iter
) == type
) {
1019 * ---------------------------------------------------------------------------
1020 * Returns the first Netlink attribute within 'nla' with the specified
1023 * This function does not validate the attribute's length.
1024 * ---------------------------------------------------------------------------
1027 NlAttrFindNested(const PNL_ATTR nla
, UINT16 type
)
1029 return NlAttrFind__((const PNL_ATTR
)(NlAttrGet(nla
)),
1030 NlAttrGetSize(nla
), type
);
1034 *----------------------------------------------------------------------------
1035 * Parses the netlink message at a given offset (attrOffset)
1036 * as a series of attributes. A pointer to the attribute with type
1037 * 'type' is stored in attrs at index 'type'. policy is used to define the
1038 * attribute type validation parameters.
1039 * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER
1041 * Returns BOOLEAN to indicate success/failure.
1042 *----------------------------------------------------------------------------
1045 NlAttrParse(const PNL_MSG_HDR nlMsg
, UINT32 attrOffset
,
1046 UINT32 totalAttrLen
,
1047 const NL_POLICY policy
[],
1048 PNL_ATTR attrs
[], UINT32 n_attrs
)
1053 BOOLEAN ret
= FALSE
;
1055 RtlZeroMemory(attrs
, n_attrs
* sizeof *attrs
);
1058 /* There is nothing to parse */
1059 if (!(NlMsgAttrsLen(nlMsg
))) {
1064 if ((NlMsgSize(nlMsg
) < attrOffset
)) {
1065 OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d",
1070 NL_ATTR_FOR_EACH (nla
, left
, NlMsgAt(nlMsg
, attrOffset
),
1073 UINT16 type
= NlAttrType(nla
);
1074 if (type
< n_attrs
&& policy
[type
].type
!= NL_A_NO_ATTR
) {
1075 /* Typecasting to keep the compiler happy */
1076 const PNL_POLICY e
= (const PNL_POLICY
)(&policy
[type
]);
1077 if (!NlAttrValidate(nla
, e
)) {
1082 OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, "
1083 "type: %u", nlMsg
, type
);
1091 OVS_LOG_ERROR("Attributes followed by garbage");
1095 for (iter
= 0; iter
< n_attrs
; iter
++) {
1096 const PNL_POLICY e
= (const PNL_POLICY
)(&policy
[iter
]);
1097 if (!e
->optional
&& e
->type
!= NL_A_NO_ATTR
&& !attrs
[iter
]) {
1098 OVS_LOG_ERROR("Required attr:%d missing", iter
);
1110 *----------------------------------------------------------------------------
1111 * Parses the netlink message for nested attributes. attrOffset must be the
1112 * offset of nla which is the header of the nested attribute series.
1113 * Refer nl_parse_nested for more details.
1115 * Returns BOOLEAN to indicate success/failure.
1116 *----------------------------------------------------------------------------
1119 NlAttrParseNested(const PNL_MSG_HDR nlMsg
, UINT32 attrOffset
,
1120 UINT32 totalAttrLen
,
1121 const NL_POLICY policy
[],
1122 PNL_ATTR attrs
[], UINT32 n_attrs
)
1124 return NlAttrParse(nlMsg
, attrOffset
+ NLA_HDRLEN
,
1125 totalAttrLen
- NLA_HDRLEN
, policy
, attrs
, n_attrs
);