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
28 * ---------------------------------------------------------------------------
29 * Netlink message accessing the payload.
30 * ---------------------------------------------------------------------------
33 NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset)
35 return ((PCHAR)nlh + offset);
39 * ---------------------------------------------------------------------------
40 * Returns the size of netlink message.
41 * ---------------------------------------------------------------------------
44 NlMsgSize(const PNL_MSG_HDR nlh)
50 * ---------------------------------------------------------------------------
51 * Returns pointer to nlmsg payload.
52 * ---------------------------------------------------------------------------
55 NlMsgPayload(const PNL_MSG_HDR nlh)
57 return ((PCHAR)nlh + NLMSG_HDRLEN);
61 * ---------------------------------------------------------------------------
62 * Returns length of nlmsg payload.
63 * ---------------------------------------------------------------------------
66 NlMsgPayloadLen(const PNL_MSG_HDR nlh)
68 return nlh->nlmsgLen - NLMSG_HDRLEN;
72 * ---------------------------------------------------------------------------
73 * Returns pointer to nlmsg attributes.
74 * ---------------------------------------------------------------------------
77 NlMsgAttrs(const PNL_MSG_HDR nlh)
79 return (PNL_ATTR) (NlMsgPayload(nlh) + GENL_HDRLEN + OVS_HDRLEN);
83 * ---------------------------------------------------------------------------
84 * Returns size of to nlmsg attributes.
85 * ---------------------------------------------------------------------------
88 NlMsgAttrLen(const PNL_MSG_HDR nlh)
90 return NlMsgPayloadLen(nlh) - GENL_HDRLEN - OVS_HDRLEN;
93 /* Netlink message parse. */
96 * ---------------------------------------------------------------------------
97 * Returns next netlink message in the stream.
98 * ---------------------------------------------------------------------------
101 NlMsgNext(const PNL_MSG_HDR nlh)
103 return (PNL_MSG_HDR)((PCHAR)nlh +
104 NLMSG_ALIGN(nlh->nlmsgLen));
108 * ---------------------------------------------------------------------------
109 * Netlink Attr helper APIs.
110 * ---------------------------------------------------------------------------
113 NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen)
115 return (maxlen >= sizeof *nla
116 && nla->nlaLen >= sizeof *nla
117 && nla->nlaLen <= maxlen);
121 * ---------------------------------------------------------------------------
122 * Returns alligned length of the attribute.
123 * ---------------------------------------------------------------------------
126 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen)
128 UINT32 len = NLA_ALIGN(nla->nlaLen);
130 return len <= maxlen ? len : nla->nlaLen;
134 * ---------------------------------------------------------------------------
135 * Default minimum payload size for each type of attribute.
136 * ---------------------------------------------------------------------------
139 NlAttrMinLen(NL_ATTR_TYPE type)
142 case NL_A_NO_ATTR: return 0;
143 case NL_A_UNSPEC: return 0;
144 case NL_A_U8: return 1;
145 case NL_A_U16: return 2;
146 case NL_A_U32: return 4;
147 case NL_A_U64: return 8;
148 case NL_A_STRING: return 1;
149 case NL_A_FLAG: return 0;
150 case NL_A_NESTED: return 0;
151 case N_NL_ATTR_TYPES:
153 OVS_LOG_WARN("Unsupprted attribute type: %d", type);
157 /* To keep compiler happy */
162 * ---------------------------------------------------------------------------
163 * Default maximum payload size for each type of attribute.
164 * ---------------------------------------------------------------------------
167 NlAttrMaxLen(NL_ATTR_TYPE type)
170 case NL_A_NO_ATTR: return SIZE_MAX;
171 case NL_A_UNSPEC: return SIZE_MAX;
172 case NL_A_U8: return 1;
173 case NL_A_U16: return 2;
174 case NL_A_U32: return 4;
175 case NL_A_U64: return 8;
176 case NL_A_STRING: return SIZE_MAX;
177 case NL_A_FLAG: return SIZE_MAX;
178 case NL_A_NESTED: return SIZE_MAX;
179 case N_NL_ATTR_TYPES:
181 OVS_LOG_WARN("Unsupprted attribute type: %d", type);
185 /* To keep compiler happy */
189 /* Netlink attribute iteration. */
192 * ---------------------------------------------------------------------------
193 * Returns the next attribute.
194 * ---------------------------------------------------------------------------
197 NlAttrNext(const PNL_ATTR nla)
199 return (PNL_ATTR)((UINT8 *)nla + NLA_ALIGN(nla->nlaLen));
203 * --------------------------------------------------------------------------
204 * Returns the bits of 'nla->nlaType' that are significant for determining
206 * --------------------------------------------------------------------------
209 NlAttrType(const PNL_ATTR nla)
211 return nla->nlaType & NLA_TYPE_MASK;
215 * --------------------------------------------------------------------------
216 * Returns the netlink attribute data.
217 * --------------------------------------------------------------------------
220 NlAttrData(const PNL_ATTR nla)
222 return ((PCHAR)nla + NLA_HDRLEN);
226 * ---------------------------------------------------------------------------
227 * Returns the number of bytes in the payload of attribute 'nla'.
228 * ---------------------------------------------------------------------------
231 NlAttrGetSize(const PNL_ATTR nla)
233 return nla->nlaLen - NLA_HDRLEN;
237 * ---------------------------------------------------------------------------
238 * Returns the first byte in the payload of attribute 'nla'.
239 * ---------------------------------------------------------------------------
242 NlAttrGet(const PNL_ATTR nla)
244 ASSERT(nla->nlaLen >= NLA_HDRLEN);
249 * ---------------------------------------------------------------------------
250 * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the
251 * first byte of the payload.
252 * ---------------------------------------------------------------------------
255 PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size)
257 UNREFERENCED_PARAMETER(size);
258 ASSERT(nla->nlaLen >= NLA_HDRLEN + size);
263 * ---------------------------------------------------------------------------
264 * Returns the 64-bit network byte order value in 'nla''s payload.
266 * Asserts that 'nla''s payload is at least 8 bytes long.
267 * ---------------------------------------------------------------------------
270 NlAttrGetBe64(const PNL_ATTR nla)
272 return NL_ATTR_GET_AS(nla, BE64);
276 * ---------------------------------------------------------------------------
277 * Returns the 32-bit network byte order value in 'nla''s payload.
279 * Asserts that 'nla''s payload is at least 4 bytes long.
280 * ---------------------------------------------------------------------------
283 NlAttrGetBe32(const PNL_ATTR nla)
285 return NL_ATTR_GET_AS(nla, BE32);
289 * ---------------------------------------------------------------------------
290 * Returns the 8-bit value in 'nla''s payload.
291 * ---------------------------------------------------------------------------
294 NlAttrGetU8(const PNL_ATTR nla)
296 return NL_ATTR_GET_AS(nla, UINT8);
300 * ---------------------------------------------------------------------------
301 * Returns the 32-bit host byte order value in 'nla''s payload.
302 * Asserts that 'nla''s payload is at least 4 bytes long.
303 * ---------------------------------------------------------------------------
306 NlAttrGetU32(const PNL_ATTR nla)
308 return NL_ATTR_GET_AS(nla, UINT32);
312 * ---------------------------------------------------------------------------
313 * Validate the netlink attribute against the policy
314 * ---------------------------------------------------------------------------
317 NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy)
324 if (policy->type == NL_A_NO_ATTR) {
329 /* Figure out min and max length. */
330 minLen = policy->minLen;
332 minLen = NlAttrMinLen(policy->type);
334 maxLen = policy->maxLen;
336 maxLen = NlAttrMaxLen(policy->type);
340 len = NlAttrGetSize(nla);
341 if (len < minLen || len > maxLen) {
342 OVS_LOG_WARN("Attribute: %p, len: %d, not in valid range, "
343 "min: %d, max: %d", nla, len, minLen, maxLen);
347 /* Strings must be null terminated and must not have embedded nulls. */
348 if (policy->type == NL_A_STRING) {
349 if (((PCHAR) nla)[nla->nlaLen - 1]) {
350 OVS_LOG_WARN("Attributes %p lacks null at the end", nla);
354 if (memchr(nla + 1, '\0', len - 1) != NULL) {
355 OVS_LOG_WARN("Attributes %p has bad length", nla);
365 * ---------------------------------------------------------------------------
366 * Returns an attribute of type 'type' from a series of
368 * ---------------------------------------------------------------------------
371 NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type)
373 PNL_ATTR iter = NULL;
377 NL_ATTR_FOR_EACH (iter, left, attrs, size) {
378 if (NlAttrType(iter) == type) {
389 * ---------------------------------------------------------------------------
390 * Returns the first Netlink attribute within 'nla' with the specified
393 * This function does not validate the attribute's length.
394 * ---------------------------------------------------------------------------
397 NlAttrFindNested(const PNL_ATTR nla, UINT16 type)
399 return NlAttrFind__((const PNL_ATTR)(NlAttrGet(nla)),
400 NlAttrGetSize(nla), type);
404 *----------------------------------------------------------------------------
405 * Parses the netlink message at a given offset (attrOffset)
406 * as a series of attributes. A pointer to the attribute with type
407 * 'type' is stored in attrs at index 'type'. policy is used to define the
408 * attribute type validation parameters.
409 * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER
411 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
412 * (e.g. if Pkt_CopyBytesOut() returns an error).
413 *----------------------------------------------------------------------------
415 BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
416 const NL_POLICY policy[],
417 PNL_ATTR attrs[], UINT32 n_attrs)
424 memset(attrs, 0, n_attrs * sizeof *attrs);
426 if ((NlMsgSize(nlMsg) < attrOffset) || (!(NlMsgAttrLen(nlMsg)))) {
427 OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d",
432 NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset),
433 NlMsgSize(nlMsg) - attrOffset)
435 UINT16 type = NlAttrType(nla);
436 if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) {
437 /* Typecasting to keep the compiler happy */
438 const PNL_POLICY e = (const PNL_POLICY)(&policy[type]);
439 if (!NlAttrValidate(nla, e)) {
444 OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, "
445 "type: %u", nlMsg, type);
453 OVS_LOG_ERROR("Attributes followed by garbage");
457 for (iter = 0; iter < n_attrs; iter++) {
458 const PNL_POLICY e = (const PNL_POLICY)(&policy[iter]);
459 if (e->type != NL_A_NO_ATTR && !attrs[iter]) {
460 OVS_LOG_ERROR("Required attr:%d missing", iter);