datapath-windows: Append flow attribute key
[cascardo/ovs.git] / datapath-windows / ovsext / Netlink / Netlink.c
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
3  *
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:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "precomp.h"
18 #include "NetlinkProto.h"
19 #include "Netlink.h"
20
21 #ifdef OVS_DBG_MOD
22 #undef OVS_DBG_MOD
23 #endif
24 #define OVS_DBG_MOD OVS_DBG_NETLINK
25 #include "Debug.h"
26
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.
30  *
31  * TODO: Convert these methods to inline.
32  * ==========================================================================
33  */
34
35 /*
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  * ---------------------------------------------------------------------------
41  */
42 BOOLEAN
43 NlFillOvsMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType,
44              UINT16 nlmsgFlags, UINT32 nlmsgSeq,
45              UINT32 nlmsgPid, UINT8 genlCmd,
46              UINT8 genlVer, UINT32 dpNo)
47 {
48     BOOLEAN writeOk;
49     OVS_MESSAGE msgOut;
50     UINT32 offset = NlBufSize(nlBuf);
51
52     /* To keep compiler happy for release build. */
53     UNREFERENCED_PARAMETER(offset);
54     ASSERT(NlBufAt(nlBuf, offset, 0) != 0);
55
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);
61
62     msgOut.genlMsg.cmd = genlCmd;
63     msgOut.genlMsg.version = genlVer;
64     msgOut.genlMsg.reserved = 0;
65
66     msgOut.ovsHdr.dp_ifindex = dpNo;
67
68     writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),
69                            sizeof (struct _OVS_MESSAGE));
70
71     return writeOk;
72 }
73
74 /*
75  * ---------------------------------------------------------------------------
76  * Prepare NL_MSG_HDR only. This API appends a NL_MSG_HDR to the tail of
77  * input NlBuf.
78  * ---------------------------------------------------------------------------
79  */
80 BOOLEAN
81 NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType,
82             UINT16 nlmsgFlags, UINT32 nlmsgSeq,
83             UINT32 nlmsgPid)
84 {
85     BOOLEAN writeOk;
86     NL_MSG_HDR msgOut;
87     UINT32 offset = NlBufSize(nlBuf);
88
89     /* To keep compiler happy for release build. */
90     UNREFERENCED_PARAMETER(offset);
91     ASSERT(NlBufAt(nlBuf, offset, 0) != 0);
92
93     msgOut.nlmsgType = nlmsgType;
94     msgOut.nlmsgFlags = nlmsgFlags;
95     msgOut.nlmsgSeq = nlmsgSeq;
96     msgOut.nlmsgPid = nlmsgPid;
97     msgOut.nlmsgLen = sizeof(struct _NL_MSG_HDR);
98
99     writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),
100                            sizeof(struct _NL_MSG_HDR));
101
102     return writeOk;
103 }
104
105 /*
106  * ---------------------------------------------------------------------------
107  * Prepare a 'OVS_MESSAGE_ERROR' message.
108  * ---------------------------------------------------------------------------
109  */
110 VOID
111 NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, UINT errorCode)
112 {
113     NL_BUFFER nlBuffer;
114
115     ASSERT(errorCode != NL_ERROR_PENDING);
116
117     NlBufInit(&nlBuffer, (PCHAR)msgError, sizeof *msgError);
118     NlFillNlHdr(&nlBuffer, NLMSG_ERROR, 0,
119                 msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid);
120
121     msgError->errorMsg.error = errorCode;
122     msgError->errorMsg.nlMsg = msgIn->nlMsg;
123     msgError->nlMsg.nlmsgLen = sizeof(OVS_MESSAGE_ERROR);
124 }
125
126 /*
127  * ---------------------------------------------------------------------------
128  * Adds Netlink Header to the NL_BUF.
129  * ---------------------------------------------------------------------------
130  */
131 BOOLEAN
132 NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg)
133 {
134     if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) {
135         return TRUE;
136     }
137
138     return FALSE;
139 }
140
141 /*
142  * ---------------------------------------------------------------------------
143  * Adds Genl Header to the NL_BUF.
144  * ---------------------------------------------------------------------------
145  */
146 BOOLEAN
147 NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg)
148 {
149     if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) {
150         return TRUE;
151     }
152
153     return FALSE;
154 }
155
156 /*
157  * ---------------------------------------------------------------------------
158  * Adds OVS Header to the NL_BUF.
159  * ---------------------------------------------------------------------------
160  */
161 BOOLEAN
162 NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr)
163 {
164     if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN,
165                            GENL_HDRLEN + NLMSG_HDRLEN))) {
166         return TRUE;
167     }
168
169     return FALSE;
170 }
171
172 /*
173  * ---------------------------------------------------------------------------
174  * Adds data of length 'len' to the tail end of NL_BUF.
175  * Refer nl_msg_put for more details.
176  * ---------------------------------------------------------------------------
177  */
178 BOOLEAN
179 NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len)
180 {
181     len = NLMSG_ALIGN(len);
182     if (NlBufCopyAtTail(buf, data, len)) {
183         return TRUE;
184     }
185
186     return FALSE;
187 }
188
189 /*
190  * ---------------------------------------------------------------------------
191  * memsets length 'len' at tail end of NL_BUF.
192  * Refer nl_msg_put_uninit for more details.
193  * ---------------------------------------------------------------------------
194  */
195 PCHAR
196 NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len)
197 {
198     len = NLMSG_ALIGN(len);
199     return NlBufCopyAtTailUninit(buf, len);
200 }
201
202 /*
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  * ---------------------------------------------------------------------------
208  */
209 PCHAR
210 NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)
211 {
212     PCHAR ret = NULL;
213     UINT16 totalLen = NLA_HDRLEN + len;
214     PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen));
215
216     if (!nla) {
217         goto done;
218     }
219
220     ret = (PCHAR)(nla + 1);
221     nla->nlaLen = totalLen;
222     nla->nlaType = type;
223
224 done:
225     return ret;
226 }
227
228 /*
229  * ---------------------------------------------------------------------------
230  * Adds an attribute to the tail end of buffer. It copies attribute
231  * payload as well.
232  * Refer nl_msg_put_unspec for more details.
233  * ---------------------------------------------------------------------------
234  */
235 BOOLEAN
236 NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)
237 {
238     BOOLEAN ret = TRUE;
239     PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len);
240
241     if (!nlaData) {
242         ret = FALSE;
243         goto done;
244     }
245
246     RtlCopyMemory(nlaData, data, len);
247
248 done:
249     return ret;
250 }
251
252 /*
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  * ---------------------------------------------------------------------------
257  */
258 BOOLEAN
259 NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type)
260 {
261     BOOLEAN ret = TRUE;
262     PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
263
264     if (!nlaData) {
265         ret = FALSE;
266     }
267
268     return ret;
269 }
270
271 /*
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  * ---------------------------------------------------------------------------
276  */
277 BOOLEAN
278 NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value)
279 {
280     return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
281 }
282
283 /*
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  * ---------------------------------------------------------------------------
288  */
289 BOOLEAN
290 NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value)
291 {
292     return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
293 }
294
295 /*
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  * ---------------------------------------------------------------------------
300  */
301 BOOLEAN
302 NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value)
303 {
304     return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
305 }
306
307 /*
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  * ---------------------------------------------------------------------------
312  */
313 BOOLEAN
314 NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value)
315 {
316     return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
317 }
318
319 /*
320  * ---------------------------------------------------------------------------
321  * Adds an attribute of 'type' and string payload.
322  * Refer nl_msg_put_string for more details.
323  * ---------------------------------------------------------------------------
324  */
325 BOOLEAN
326 NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value)
327 {
328     size_t strLen = strlen(value) + 1;
329 #ifdef DBG
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) {
333         return FALSE;
334     }
335 #endif
336
337     /* typecast to keep compiler happy */
338     return (NlMsgPutTailUnspec(buf, type, value,
339                                (UINT16)strLen));
340 }
341
342 /*
343  * ---------------------------------------------------------------------------
344  * Adds data of length 'len' to the head of NL_BUF.
345  * Refer nl_msg_push for more details.
346  * ---------------------------------------------------------------------------
347  */
348 BOOLEAN
349 NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len)
350 {
351     len = NLMSG_ALIGN(len);
352     if (NlBufCopyAtHead(buf, data, len)) {
353         return TRUE;
354     }
355
356     return FALSE;
357 }
358
359 /*
360  * ---------------------------------------------------------------------------
361  * memsets length 'len' at head of NL_BUF.
362  * Refer nl_msg_push_uninit for more details.
363  * ---------------------------------------------------------------------------
364  */
365 PCHAR
366 NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len)
367 {
368     len = NLMSG_ALIGN(len);
369     return NlBufCopyAtHeadUninit(buf, len);
370 }
371
372 /*
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  * ---------------------------------------------------------------------------
378  */
379 PCHAR
380 NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)
381 {
382     PCHAR ret = NULL;
383     UINT16 totalLen = NLA_HDRLEN + len;
384     PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen));
385
386     if (!nla) {
387         goto done;
388     }
389
390     ret = (PCHAR)(nla + 1);
391     nla->nlaLen = totalLen;
392     nla->nlaType = type;
393
394 done:
395     return ret;
396 }
397
398 /*
399  * ---------------------------------------------------------------------------
400  * Adds an attribute to the head of buffer. It copies attribute
401  * payload as well.
402  * Refer nl_msg_push_unspec for more details.
403  * ---------------------------------------------------------------------------
404  */
405 BOOLEAN
406 NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)
407 {
408     BOOLEAN ret = TRUE;
409     PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len);
410
411     if (!nlaData) {
412         ret = FALSE;
413         goto done;
414     }
415
416     RtlCopyMemory(nlaData, data, len);
417
418 done:
419     return ret;
420 }
421
422 /*
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  * ---------------------------------------------------------------------------
427  */
428 BOOLEAN
429 NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type)
430 {
431     BOOLEAN ret = TRUE;
432     PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0);
433
434     if (!nlaData) {
435         ret = FALSE;
436     }
437
438     return ret;
439 }
440
441 /*
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  * ---------------------------------------------------------------------------
446  */
447 BOOLEAN
448 NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value)
449 {
450     return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
451 }
452
453 /*
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  * ---------------------------------------------------------------------------
458  */
459 BOOLEAN
460 NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value)
461 {
462     return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
463 }
464
465 /*
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  * ---------------------------------------------------------------------------
470  */
471 BOOLEAN
472 NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value)
473 {
474     return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
475 }
476
477 /*
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  * ---------------------------------------------------------------------------
482  */
483 BOOLEAN
484 NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value)
485 {
486     return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
487 }
488
489 /*
490  * ---------------------------------------------------------------------------
491  * Adds an attribute of 'type' and string payload.
492  * Refer nl_msg_push_string for more details.
493  * ---------------------------------------------------------------------------
494  */
495 BOOLEAN
496 NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value)
497 {
498     size_t strLen = strlen(value) + 1;
499 #ifdef DBG
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) {
503         return FALSE;
504     }
505 #endif
506
507     /* typecast to keep compiler happy */
508     return (NlMsgPutHeadUnspec(buf, type, value,
509                                (UINT16)strLen));
510 }
511
512 /*
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  * ---------------------------------------------------------------------------
519  */
520 UINT32
521 NlMsgStartNested(PNL_BUFFER buf, UINT16 type)
522 {
523     UINT32 offset = NlBufSize(buf);
524     PCHAR nlaData = NULL;
525
526     nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
527
528     if (!nlaData) {
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. */
533         offset = 0;
534     }
535
536     return offset;
537 }
538
539 /*
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  * ---------------------------------------------------------------------------
545  */
546 VOID
547 NlMsgEndNested(PNL_BUFFER buf, UINT32 offset)
548 {
549     PNL_ATTR attr = (PNL_ATTR)(NlBufAt(buf, offset, sizeof *attr));
550
551     /* Typecast to keep compiler happy.
552      * Attribute length would never exceed MAX UINT16.*/
553     attr->nlaLen = (UINT16)(NlBufSize(buf) - offset);
554 }
555
556 /*
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  * --------------------------------------------------------------------------
562  */
563 BOOLEAN
564 NlMsgPutNested(PNL_BUFFER buf, UINT16 type,
565                const PVOID data, UINT32 size)
566 {
567     UINT32 offset = NlMsgStartNested(buf, type);
568     BOOLEAN ret = FALSE;
569
570     ASSERT(offset);
571
572     ret = NlMsgPutTail(buf, data, size);
573
574     ASSERT(ret);
575
576     NlMsgEndNested(buf, offset);
577
578     return ret;
579 }
580
581 /* Accessing netlink message payload */
582
583 /*
584  * ---------------------------------------------------------------------------
585  * Netlink message accessing the payload.
586  * ---------------------------------------------------------------------------
587  */
588 PVOID
589 NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset)
590 {
591     return ((PCHAR)nlh + offset);
592 }
593
594 /*
595  * ---------------------------------------------------------------------------
596  * Returns the size of netlink message.
597  * ---------------------------------------------------------------------------
598  */
599 UINT32
600 NlMsgSize(const PNL_MSG_HDR nlh)
601 {
602     return nlh->nlmsgLen;
603 }
604
605 /*
606  * ---------------------------------------------------------------------------
607  * Aligns the size of Netlink message.
608  * ---------------------------------------------------------------------------
609  */
610 VOID
611 NlMsgAlignSize(const PNL_MSG_HDR nlh)
612 {
613     nlh->nlmsgLen = NLMSG_ALIGN(nlh->nlmsgLen);
614     return;
615 }
616
617 /*
618  * ---------------------------------------------------------------------------
619  * Sets the size of Netlink message.
620  * ---------------------------------------------------------------------------
621  */
622 VOID
623 NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen)
624 {
625     nlh->nlmsgLen = msgLen;
626 }
627
628 /*
629  * ---------------------------------------------------------------------------
630  * Returns pointer to nlmsg payload.
631  * ---------------------------------------------------------------------------
632  */
633 PCHAR
634 NlHdrPayload(const PNL_MSG_HDR nlh)
635 {
636     return ((PCHAR)nlh + NLMSG_HDRLEN);
637 }
638
639 /*
640  * ---------------------------------------------------------------------------
641  * Returns length of nlmsg payload.
642  * ---------------------------------------------------------------------------
643  */
644 UINT32
645 NlHdrPayloadLen(const PNL_MSG_HDR nlh)
646 {
647     return nlh->nlmsgLen - NLMSG_HDRLEN;
648 }
649
650 /*
651  * ---------------------------------------------------------------------------
652  * Returns pointer to nlmsg attributes.
653  * ---------------------------------------------------------------------------
654  */
655 PNL_ATTR
656 NlMsgAttrs(const PNL_MSG_HDR nlh)
657 {
658     return (PNL_ATTR) (NlHdrPayload(nlh) + GENL_HDRLEN + OVS_HDRLEN);
659 }
660
661 /*
662  * ---------------------------------------------------------------------------
663  * Returns size of to nlmsg attributes.
664  * ---------------------------------------------------------------------------
665  */
666 UINT32
667 NlMsgAttrsLen(const PNL_MSG_HDR nlh)
668 {
669     return NlHdrPayloadLen(nlh) - GENL_HDRLEN - OVS_HDRLEN;
670 }
671
672 /* Netlink message parse. */
673
674 /*
675  * ---------------------------------------------------------------------------
676  * Returns next netlink message in the stream.
677  * ---------------------------------------------------------------------------
678  */
679 PNL_MSG_HDR
680 NlMsgNext(const PNL_MSG_HDR nlh)
681 {
682     return (PNL_MSG_HDR)((PCHAR)nlh +
683             NLMSG_ALIGN(nlh->nlmsgLen));
684 }
685
686 /*
687  * ---------------------------------------------------------------------------
688  * Netlink Attr helper APIs.
689  * ---------------------------------------------------------------------------
690  */
691 INT
692 NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen)
693 {
694     return (maxlen >= sizeof *nla
695             && nla->nlaLen >= sizeof *nla
696             && nla->nlaLen <= maxlen);
697 }
698
699 /*
700  * ---------------------------------------------------------------------------
701  * Returns alligned length of the attribute.
702  * ---------------------------------------------------------------------------
703  */
704 UINT32
705 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen)
706 {
707     UINT32 len = NLA_ALIGN(nla->nlaLen);
708
709     return len <= maxlen ? len : nla->nlaLen;
710 }
711
712 /*
713  * ---------------------------------------------------------------------------
714  * Default minimum payload size for each type of attribute.
715  * ---------------------------------------------------------------------------
716  */
717 UINT32
718 NlAttrMinLen(NL_ATTR_TYPE type)
719 {
720     switch (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:
731     default:
732     OVS_LOG_WARN("Unsupprted attribute type: %d", type);
733     ASSERT(0);
734     }
735
736     /* To keep compiler happy */
737     return 0;
738 }
739
740 /*
741  * ---------------------------------------------------------------------------
742  * Default maximum payload size for each type of attribute.
743  * ---------------------------------------------------------------------------
744  */
745 UINT32
746 NlAttrMaxLen(NL_ATTR_TYPE type)
747 {
748     switch (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:
759     default:
760     OVS_LOG_WARN("Unsupprted attribute type: %d", type);
761     ASSERT(0);
762     }
763
764     /* To keep compiler happy */
765     return 0;
766 }
767
768 /* Netlink attribute iteration. */
769
770 /*
771  * ---------------------------------------------------------------------------
772  * Returns the next attribute.
773  * ---------------------------------------------------------------------------
774  */
775 PNL_ATTR
776 NlAttrNext(const PNL_ATTR nla)
777 {
778     return (PNL_ATTR)((UINT8 *)nla + NLA_ALIGN(nla->nlaLen));
779 }
780
781 /*
782  * --------------------------------------------------------------------------
783  * Returns the bits of 'nla->nlaType' that are significant for determining
784  * its type.
785  * --------------------------------------------------------------------------
786  */
787 UINT16
788 NlAttrType(const PNL_ATTR nla)
789 {
790    return nla->nlaType & NLA_TYPE_MASK;
791 }
792
793 /*
794  * --------------------------------------------------------------------------
795  * Returns the netlink attribute data.
796  * --------------------------------------------------------------------------
797  */
798 PVOID
799 NlAttrData(const PNL_ATTR nla)
800 {
801     return ((PCHAR)nla + NLA_HDRLEN);
802 }
803
804 /*
805  * ---------------------------------------------------------------------------
806  * Returns the number of bytes in the payload of attribute 'nla'.
807  * ---------------------------------------------------------------------------
808  */
809 UINT32
810 NlAttrGetSize(const PNL_ATTR nla)
811 {
812     return nla->nlaLen - NLA_HDRLEN;
813 }
814
815 /*
816  * ---------------------------------------------------------------------------
817  * Returns the first byte in the payload of attribute 'nla'.
818  * ---------------------------------------------------------------------------
819  */
820 const PVOID
821 NlAttrGet(const PNL_ATTR nla)
822 {
823     ASSERT(nla->nlaLen >= NLA_HDRLEN);
824     return nla + 1;
825 }
826
827 /*
828  * ---------------------------------------------------------------------------
829  * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the
830  * first byte of the payload.
831  * ---------------------------------------------------------------------------
832  */
833 const
834 PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size)
835 {
836     UNREFERENCED_PARAMETER(size);
837     ASSERT(nla->nlaLen >= NLA_HDRLEN + size);
838     return nla + 1;
839 }
840
841 /*
842  * ---------------------------------------------------------------------------
843  * Returns the 64-bit network byte order value in 'nla''s payload.
844  *
845  * Asserts that 'nla''s payload is at least 8 bytes long.
846  * ---------------------------------------------------------------------------
847  */
848 BE64
849 NlAttrGetBe64(const PNL_ATTR nla)
850 {
851     return NL_ATTR_GET_AS(nla, BE64);
852 }
853
854 /*
855  * ---------------------------------------------------------------------------
856  * Returns the 32-bit network byte order value in 'nla''s payload.
857  *
858  * Asserts that 'nla''s payload is at least 4 bytes long.
859  * ---------------------------------------------------------------------------
860  */
861 BE32
862 NlAttrGetBe32(const PNL_ATTR nla)
863 {
864     return NL_ATTR_GET_AS(nla, BE32);
865 }
866
867 /*
868  * ---------------------------------------------------------------------------
869  * Returns the 16-bit network byte order value in 'nla''s payload.
870  *
871  * Asserts that 'nla''s payload is at least 2 bytes long.
872  * ---------------------------------------------------------------------------
873  */
874 BE16
875 NlAttrGetBe16(const PNL_ATTR nla)
876 {
877     return NL_ATTR_GET_AS(nla, BE16);
878 }
879
880 /*
881  * ---------------------------------------------------------------------------
882  * Returns the 8-bit network byte order value in 'nla''s payload.
883  *
884  * Asserts that 'nla''s payload is at least 1 byte long.
885  * ---------------------------------------------------------------------------
886  */
887 BE8
888 NlAttrGetBe8(const PNL_ATTR nla)
889 {
890     return NL_ATTR_GET_AS(nla, BE8);
891 }
892
893 /*
894  * ---------------------------------------------------------------------------
895  * Returns the 8-bit value in 'nla''s payload.
896  * ---------------------------------------------------------------------------
897  */
898 UINT8
899 NlAttrGetU8(const PNL_ATTR nla)
900 {
901     return NL_ATTR_GET_AS(nla, UINT8);
902 }
903
904 /*
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  * ---------------------------------------------------------------------------
909  */
910 UINT16
911 NlAttrGetU16(const PNL_ATTR nla)
912 {
913     return NL_ATTR_GET_AS(nla, UINT16);
914 }
915
916 /*
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  * ---------------------------------------------------------------------------
921  */
922 UINT32
923 NlAttrGetU32(const PNL_ATTR nla)
924 {
925     return NL_ATTR_GET_AS(nla, UINT32);
926 }
927
928 /*
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  * ---------------------------------------------------------------------------
933  */
934 UINT64
935 NlAttrGetU64(const PNL_ATTR nla)
936 {
937     return NL_ATTR_GET_AS(nla, UINT64);
938 }
939
940 /*
941  * ---------------------------------------------------------------------------
942  * Validate the netlink attribute against the policy
943  * ---------------------------------------------------------------------------
944  */
945 BOOLEAN
946 NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy)
947 {
948     UINT32 minLen;
949     UINT32 maxLen;
950     UINT32 len;
951     BOOLEAN ret = FALSE;
952
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 */
957         ret = TRUE;
958         goto done;
959     }
960
961     /* Figure out min and max length. */
962     minLen = policy->minLen;
963     if (!minLen) {
964         minLen = NlAttrMinLen(policy->type);
965     }
966     maxLen = policy->maxLen;
967     if (!maxLen) {
968         maxLen = NlAttrMaxLen(policy->type);
969     }
970
971     /* Verify length. */
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);
976         goto done;
977     }
978
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);
983             goto done;
984         }
985
986         if (memchr(nla + 1, '\0', len - 1) != NULL) {
987             OVS_LOG_WARN("Attributes %p has bad length", nla);
988             goto done;
989         }
990     }
991
992     ret = TRUE;
993
994 done:
995     return ret;
996 }
997
998 /*
999  * ---------------------------------------------------------------------------
1000  * Returns an attribute of type 'type' from a series of
1001  * attributes.
1002  * ---------------------------------------------------------------------------
1003  */
1004 const PNL_ATTR
1005 NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type)
1006 {
1007     PNL_ATTR iter = NULL;
1008     PNL_ATTR ret = NULL;
1009     UINT32 left;
1010
1011     NL_ATTR_FOR_EACH (iter, left, attrs, size) {
1012         if (NlAttrType(iter) == type) {
1013             ret = iter;
1014             goto done;
1015         }
1016     }
1017
1018 done:
1019     return ret;
1020 }
1021
1022 /*
1023  * ---------------------------------------------------------------------------
1024  * Returns the first Netlink attribute within 'nla' with the specified
1025  * 'type'.
1026  *
1027  * This function does not validate the attribute's length.
1028  * ---------------------------------------------------------------------------
1029  */
1030 const PNL_ATTR
1031 NlAttrFindNested(const PNL_ATTR nla, UINT16 type)
1032 {
1033     return NlAttrFind__((const PNL_ATTR)(NlAttrGet(nla)),
1034                          NlAttrGetSize(nla), type);
1035 }
1036
1037 /*
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
1044  *
1045  * Returns BOOLEAN to indicate success/failure.
1046  *----------------------------------------------------------------------------
1047  */
1048 BOOLEAN
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)
1053 {
1054     PNL_ATTR nla;
1055     UINT32 left;
1056     UINT32 iter;
1057     BOOLEAN ret = FALSE;
1058     UINT32 numPolicyAttr = MIN(numPolicy, numAttrs);
1059
1060     RtlZeroMemory(attrs, numAttrs * sizeof *attrs);
1061
1062
1063     /* There is nothing to parse */
1064     if (!(NlMsgAttrsLen(nlMsg))) {
1065         ret = TRUE;
1066         goto done;
1067     }
1068
1069     if ((NlMsgSize(nlMsg) < attrOffset)) {
1070         OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d",
1071                      nlMsg, attrOffset);
1072         goto done;
1073     }
1074
1075     NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset),
1076                       totalAttrLen)
1077     {
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)) {
1083                 goto done;
1084             }
1085
1086             if (attrs[type]) {
1087                 OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, "
1088                              "type: %u", nlMsg, type);
1089             }
1090
1091             attrs[type] = nla;
1092         }
1093     }
1094
1095     if (left) {
1096         OVS_LOG_ERROR("Attributes followed by garbage");
1097         goto done;
1098     }
1099
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);
1104             goto done;
1105         }
1106     }
1107
1108     ret = TRUE;
1109
1110 done:
1111     return ret;
1112 }
1113
1114 /*
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.
1119  *
1120  * Returns BOOLEAN to indicate success/failure.
1121  *----------------------------------------------------------------------------
1122  */
1123 BOOLEAN
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)
1128 {
1129     return NlAttrParse(nlMsg, attrOffset + NLA_HDRLEN,
1130                        totalAttrLen - NLA_HDRLEN, policy, numPolicy,
1131                        attrs, numAttrs);
1132 }