Coverage Report

Created: 2025-07-11 06:11

/src/openvswitch/lib/netlink.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 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 <config.h>
18
#include "netlink.h"
19
#include <errno.h>
20
#include <inttypes.h>
21
#include <sys/types.h>
22
#include <unistd.h>
23
#include "coverage.h"
24
#include "flow.h"
25
#include "netlink-protocol.h"
26
#include "openvswitch/ofpbuf.h"
27
#include "timeval.h"
28
#include "unaligned.h"
29
#include "openvswitch/vlog.h"
30
#include "util.h"
31
32
#ifdef HAVE_NETLINK
33
#include <linux/rtnetlink.h>
34
#else
35
/* RTA_VIA */
36
struct rtvia {
37
    sa_family_t    rtvia_family;
38
    uint8_t        rtvia_addr[];
39
};
40
#endif
41
42
VLOG_DEFINE_THIS_MODULE(netlink);
43
44
/* A single (bad) Netlink message can in theory dump out many, many log
45
 * messages, so the burst size is set quite high here to avoid missing useful
46
 * information.  Also, at high logging levels we log *all* Netlink messages. */
47
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 600);
48
49
/* Returns the nlmsghdr at the head of 'msg'.
50
 *
51
 * 'msg' must be at least as large as a nlmsghdr. */
52
struct nlmsghdr *
53
nl_msg_nlmsghdr(const struct ofpbuf *msg)
54
0
{
55
0
    return ofpbuf_at_assert(msg, 0, NLMSG_HDRLEN);
56
0
}
57
58
/* Returns the genlmsghdr just past 'msg''s nlmsghdr.
59
 *
60
 * Returns a null pointer if 'msg' is not large enough to contain an nlmsghdr
61
 * and a genlmsghdr. */
62
struct genlmsghdr *
63
nl_msg_genlmsghdr(const struct ofpbuf *msg)
64
0
{
65
0
    return ofpbuf_at(msg, NLMSG_HDRLEN, GENL_HDRLEN);
66
0
}
67
68
/* Parses the ext ack netlink attributes and, if successful, a pointer
69
 * to the error message, if included, is stored in '*errmsg'. */
70
static void
71
nl_parse_ext_ack(const struct ofpbuf *msg, size_t offset, const char **errmsg)
72
0
{
73
0
    static const struct nl_policy policy[] = {
74
0
        [NLMSGERR_ATTR_MSG]  = { .type = NL_A_STRING, .optional = true },
75
0
    };
76
0
    struct nlattr *attrs[ARRAY_SIZE(policy)];
77
78
0
    if (!nl_policy_parse(msg, offset, policy, attrs, ARRAY_SIZE(policy))) {
79
0
        VLOG_ERR_RL(&rl, "Failed to parse extended ack data");
80
0
        return;
81
0
    }
82
83
0
    if (attrs[NLMSGERR_ATTR_MSG]) {
84
0
        *errmsg = nl_attr_get_string(attrs[NLMSGERR_ATTR_MSG]);
85
0
    }
86
0
}
87
88
/* If 'buffer' is a NLMSG_ERROR message, stores 0 in '*errorp' if it is an ACK
89
 * message, otherwise a positive errno value, and returns true.  If 'buffer' is
90
 * not an NLMSG_ERROR message, returns false.
91
 *
92
 * 'msg' must be at least as large as a nlmsghdr. */
93
bool
94
nl_msg_nlmsgerr(const struct ofpbuf *msg, int *errorp, const char **attr_msg)
95
0
{
96
0
    struct nlmsghdr *nlh = nl_msg_nlmsghdr(msg);
97
98
0
    if (nlh->nlmsg_type == NLMSG_ERROR) {
99
0
        struct nlmsgerr *err = ofpbuf_at(msg, NLMSG_HDRLEN, sizeof *err);
100
0
        int code = EPROTO;
101
0
        if (!err) {
102
0
            VLOG_ERR_RL(&rl, "received invalid nlmsgerr (%"PRIu32" bytes < %"PRIuSIZE")",
103
0
                        msg->size, NLMSG_HDRLEN + sizeof *err);
104
0
        } else if (err->error <= 0 && err->error > INT_MIN) {
105
0
            code = -err->error;
106
0
            if (attr_msg && err->error != 0 &&
107
0
                (nlh->nlmsg_flags & NLM_F_ACK_TLVS)) {
108
0
                size_t offt =  NLMSG_HDRLEN + sizeof *err;
109
110
0
                if (!(nlh->nlmsg_flags & NLM_F_CAPPED)) {
111
0
                    offt += (err->msg.nlmsg_len - NLMSG_HDRLEN);
112
0
                }
113
0
                nl_parse_ext_ack(msg, offt, attr_msg);
114
0
            }
115
0
        }
116
0
        if (errorp) {
117
0
            *errorp = code;
118
0
        }
119
0
        return true;
120
0
    } else {
121
0
        return false;
122
0
    }
123
0
}
124
125
/* Ensures that 'b' has room for at least 'size' bytes plus netlink padding at
126
 * its tail end, reallocating and copying its data if necessary. */
127
void
128
nl_msg_reserve(struct ofpbuf *msg, size_t size)
129
0
{
130
0
    ofpbuf_prealloc_tailroom(msg, NLMSG_ALIGN(size));
131
0
}
132
133
/* Puts a nlmsghdr at the beginning of 'msg', which must be initially empty.
134
 * Uses the given 'type' and 'flags'.  'expected_payload' should be
135
 * an estimate of the number of payload bytes to be supplied; if the size of
136
 * the payload is unknown a value of 0 is acceptable.
137
 *
138
 * 'type' is ordinarily an enumerated value specific to the Netlink protocol
139
 * (e.g. RTM_NEWLINK, for NETLINK_ROUTE protocol).  For Generic Netlink, 'type'
140
 * is the family number obtained via nl_lookup_genl_family().
141
 *
142
 * 'flags' is a bit-mask that indicates what kind of request is being made.  It
143
 * is often NLM_F_REQUEST indicating that a request is being made, commonly
144
 * or'd with NLM_F_ACK to request an acknowledgement.
145
 *
146
 * Sets the new nlmsghdr's nlmsg_len, nlmsg_seq, and nlmsg_pid fields to 0 for
147
 * now.  Functions that send Netlink messages will fill these in just before
148
 * sending the message.
149
 *
150
 * nl_msg_put_genlmsghdr() is more convenient for composing a Generic Netlink
151
 * message. */
152
void
153
nl_msg_put_nlmsghdr(struct ofpbuf *msg,
154
                    size_t expected_payload, uint32_t type, uint32_t flags)
155
0
{
156
0
    struct nlmsghdr *nlmsghdr;
157
158
0
    ovs_assert(msg->size == 0);
159
160
0
    nl_msg_reserve(msg, NLMSG_HDRLEN + expected_payload);
161
0
    nlmsghdr = nl_msg_put_uninit(msg, NLMSG_HDRLEN);
162
0
    nlmsghdr->nlmsg_len = 0;
163
0
    nlmsghdr->nlmsg_type = type;
164
0
    nlmsghdr->nlmsg_flags = flags;
165
0
    nlmsghdr->nlmsg_seq = 0;
166
0
    nlmsghdr->nlmsg_pid = 0;
167
0
}
168
169
/* Puts a nlmsghdr and genlmsghdr at the beginning of 'msg', which must be
170
 * initially empty.  'expected_payload' should be an estimate of the number of
171
 * payload bytes to be supplied; if the size of the payload is unknown a value
172
 * of 0 is acceptable.
173
 *
174
 * 'family' is the family number obtained via nl_lookup_genl_family().
175
 *
176
 * 'flags' is a bit-mask that indicates what kind of request is being made.  It
177
 * is often NLM_F_REQUEST indicating that a request is being made, commonly
178
 * or'd with NLM_F_ACK to request an acknowledgement.
179
 *
180
 * 'cmd' is an enumerated value specific to the Generic Netlink family
181
 * (e.g. CTRL_CMD_NEWFAMILY for the GENL_ID_CTRL family).
182
 *
183
 * 'version' is a version number specific to the family and command (often 1).
184
 *
185
 * Sets the new nlmsghdr's nlmsg_pid field to 0 for now.  nl_sock_send() will
186
 * fill it in just before sending the message.
187
 *
188
 * nl_msg_put_nlmsghdr() should be used to compose Netlink messages that are
189
 * not Generic Netlink messages. */
190
void
191
nl_msg_put_genlmsghdr(struct ofpbuf *msg, size_t expected_payload,
192
                      int family, uint32_t flags, uint8_t cmd, uint8_t version)
193
0
{
194
0
    struct genlmsghdr *genlmsghdr;
195
196
0
    nl_msg_put_nlmsghdr(msg, GENL_HDRLEN + expected_payload, family, flags);
197
0
    ovs_assert(msg->size == NLMSG_HDRLEN);
198
0
    genlmsghdr = nl_msg_put_uninit(msg, GENL_HDRLEN);
199
0
    genlmsghdr->cmd = cmd;
200
0
    genlmsghdr->version = version;
201
0
    genlmsghdr->reserved = 0;
202
0
}
203
204
/* Appends the 'size' bytes of data in 'p', plus Netlink padding if needed, to
205
 * the tail end of 'msg'.  Data in 'msg' is reallocated and copied if
206
 * necessary. */
207
void
208
nl_msg_put(struct ofpbuf *msg, const void *data, size_t size)
209
0
{
210
0
    memcpy(nl_msg_put_uninit(msg, size), data, size);
211
0
}
212
213
/* Appends 'size' bytes of data, plus Netlink padding if needed, to the tail
214
 * end of 'msg', reallocating and copying its data if necessary.  Returns a
215
 * pointer to the first byte of the new data, which is left uninitialized. */
216
void *
217
nl_msg_put_uninit(struct ofpbuf *msg, size_t size)
218
0
{
219
0
    size_t pad = PAD_SIZE(size, NLMSG_ALIGNTO);
220
0
    char *p = ofpbuf_put_uninit(msg, size + pad);
221
0
    if (pad) {
222
0
        memset(p + size, 0, pad);
223
0
    }
224
0
    return p;
225
0
}
226
227
/* Prepends the 'size' bytes of data in 'p', plus Netlink padding if needed, to
228
 * the head end of 'msg'.  Data in 'msg' is reallocated and copied if
229
 * necessary. */
230
void
231
nl_msg_push(struct ofpbuf *msg, const void *data, size_t size)
232
0
{
233
0
    memcpy(nl_msg_push_uninit(msg, size), data, size);
234
0
}
235
236
/* Prepends 'size' bytes of data, plus Netlink padding if needed, to the head
237
 * end of 'msg', reallocating and copying its data if necessary.  Returns a
238
 * pointer to the first byte of the new data, which is left uninitialized. */
239
void *
240
nl_msg_push_uninit(struct ofpbuf *msg, size_t size)
241
0
{
242
0
    size_t pad = PAD_SIZE(size, NLMSG_ALIGNTO);
243
0
    char *p = ofpbuf_push_uninit(msg, size + pad);
244
0
    if (pad) {
245
0
        memset(p + size, 0, pad);
246
0
    }
247
0
    return p;
248
0
}
249
250
/* Appends a Netlink attribute of the given 'type' and room for 'size' bytes of
251
 * data as its payload, plus Netlink padding if needed, to the tail end of
252
 * 'msg', reallocating and copying its data if necessary.  Returns a pointer to
253
 * the first byte of data in the attribute, which is left uninitialized. */
254
void *
255
nl_msg_put_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size)
256
0
{
257
0
    size_t total_size = NLA_HDRLEN + size;
258
0
    struct nlattr* nla = nl_msg_put_uninit(msg, total_size);
259
0
    ovs_assert(!nl_attr_oversized(size));
260
0
    nla->nla_len = total_size;
261
0
    nla->nla_type = type;
262
0
    return nla + 1;
263
0
}
264
265
/* Appends a Netlink attribute of the given 'type' and room for 'size' bytes of
266
 * data as its payload, plus Netlink padding if needed, to the tail end of
267
 * 'msg', reallocating and copying its data if necessary.  Returns a pointer to
268
 * the first byte of data in the attribute, which is zeroed. */
269
void *
270
nl_msg_put_unspec_zero(struct ofpbuf *msg, uint16_t type, size_t size)
271
0
{
272
0
    void *data = nl_msg_put_unspec_uninit(msg, type, size);
273
0
    memset(data, 0, size);
274
0
    return data;
275
0
}
276
277
/* Appends a Netlink attribute of the given 'type' and the 'size' bytes of
278
 * 'data' as its payload, to the tail end of 'msg', reallocating and copying
279
 * its data if necessary. */
280
void
281
nl_msg_put_unspec(struct ofpbuf *msg, uint16_t type,
282
                  const void *data, size_t size)
283
0
{
284
0
    void *ptr;
285
286
0
    ptr = nl_msg_put_unspec_uninit(msg, type, size);
287
0
    nullable_memcpy(ptr, data, size);
288
0
}
289
290
/* Appends a Netlink attribute of the given 'type' and no payload to 'msg'.
291
 * (Some Netlink protocols use the presence or absence of an attribute as a
292
 * Boolean flag.) */
293
void
294
nl_msg_put_flag(struct ofpbuf *msg, uint16_t type)
295
0
{
296
0
    nl_msg_put_unspec(msg, type, NULL, 0);
297
0
}
298
299
/* Appends a Netlink attribute of the given 'type' and the given 8-bit 'value'
300
 * to 'msg'. */
301
void
302
nl_msg_put_u8(struct ofpbuf *msg, uint16_t type, uint8_t value)
303
0
{
304
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
305
0
}
306
307
/* Appends a Netlink attribute of the given 'type' and the given 16-bit host
308
 * byte order 'value' to 'msg'. */
309
void
310
nl_msg_put_u16(struct ofpbuf *msg, uint16_t type, uint16_t value)
311
0
{
312
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
313
0
}
314
315
/* Appends a Netlink attribute of the given 'type' and the given 32-bit host
316
 * byte order 'value' to 'msg'. */
317
void
318
nl_msg_put_u32(struct ofpbuf *msg, uint16_t type, uint32_t value)
319
0
{
320
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
321
0
}
322
323
/* Appends a Netlink attribute of the given 'type' and the given 64-bit host
324
 * byte order 'value' to 'msg'. */
325
void
326
nl_msg_put_u64(struct ofpbuf *msg, uint16_t type, uint64_t value)
327
0
{
328
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
329
0
}
330
331
/* Appends a Netlink attribute of the given 'type' and the given 128-bit host
332
 * byte order 'value' to 'msg'. */
333
void
334
nl_msg_put_u128(struct ofpbuf *msg, uint16_t type, ovs_u128 value)
335
0
{
336
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
337
0
}
338
339
/* Appends a Netlink attribute of the given 'type' and the given 16-bit network
340
 * byte order 'value' to 'msg'. */
341
void
342
nl_msg_put_be16(struct ofpbuf *msg, uint16_t type, ovs_be16 value)
343
0
{
344
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
345
0
}
346
347
/* Appends a Netlink attribute of the given 'type' and the given 32-bit network
348
 * byte order 'value' to 'msg'. */
349
void
350
nl_msg_put_be32(struct ofpbuf *msg, uint16_t type, ovs_be32 value)
351
0
{
352
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
353
0
}
354
355
/* Appends a Netlink attribute of the given 'type' and the given 64-bit network
356
 * byte order 'value' to 'msg'. */
357
void
358
nl_msg_put_be64(struct ofpbuf *msg, uint16_t type, ovs_be64 value)
359
0
{
360
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
361
0
}
362
363
/* Appends a Netlink attribute of the given 'type' and the given 128-bit
364
 * network byte order 'value' to 'msg'. */
365
void
366
nl_msg_put_be128(struct ofpbuf *msg, uint16_t type, ovs_be128 value)
367
0
{
368
0
    nl_msg_put_unspec(msg, type, &value, sizeof value);
369
0
}
370
371
/* Appends a Netlink attribute of the given 'type' and the given IPv6
372
 * address order 'value' to 'msg'. */
373
void
374
nl_msg_put_in6_addr(struct ofpbuf *msg, uint16_t type,
375
                    const struct in6_addr *value)
376
0
{
377
0
    nl_msg_put_unspec(msg, type, value, sizeof *value);
378
0
}
379
380
/* Appends a Netlink attribute of the given 'type' and the given odp_port_t
381
 * 'value' to 'msg'. */
382
void
383
nl_msg_put_odp_port(struct ofpbuf *msg, uint16_t type, odp_port_t value)
384
0
{
385
0
    nl_msg_put_u32(msg, type, odp_to_u32(value));
386
0
}
387
388
/* Appends a Netlink attribute of the given 'type' with the 'len' characters
389
 * of 'value', followed by the null byte to 'msg'. */
390
void
391
nl_msg_put_string__(struct ofpbuf *msg, uint16_t type, const char *value,
392
                    size_t len)
393
0
{
394
0
    char *data = nl_msg_put_unspec_uninit(msg, type, len + 1);
395
396
0
    memcpy(data, value, len);
397
0
    data[len] = '\0';
398
0
}
399
400
/* Appends a Netlink attribute of the given 'type' and the given
401
 * null-terminated string 'value' to 'msg'. */
402
void
403
nl_msg_put_string(struct ofpbuf *msg, uint16_t type, const char *value)
404
0
{
405
0
    nl_msg_put_unspec(msg, type, value, strlen(value) + 1);
406
0
}
407
408
/* Prepends a Netlink attribute of the given 'type' and room for 'size' bytes
409
 * of data as its payload, plus Netlink padding if needed, to the head end of
410
 * 'msg', reallocating and copying its data if necessary.  Returns a pointer to
411
 * the first byte of data in the attribute, which is left uninitialized. */
412
void *
413
nl_msg_push_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size)
414
0
{
415
0
    size_t total_size = NLA_HDRLEN + size;
416
0
    struct nlattr* nla = nl_msg_push_uninit(msg, total_size);
417
0
    ovs_assert(!nl_attr_oversized(size));
418
0
    nla->nla_len = total_size;
419
0
    nla->nla_type = type;
420
0
    return nla + 1;
421
0
}
422
423
/* Prepends a Netlink attribute of the given 'type' and the 'size' bytes of
424
 * 'data' as its payload, to the head end of 'msg', reallocating and copying
425
 * its data if necessary.  Returns a pointer to the first byte of data in the
426
 * attribute, which is left uninitialized. */
427
void
428
nl_msg_push_unspec(struct ofpbuf *msg, uint16_t type,
429
                  const void *data, size_t size)
430
0
{
431
0
    memcpy(nl_msg_push_unspec_uninit(msg, type, size), data, size);
432
0
}
433
434
/* Prepends a Netlink attribute of the given 'type' and no payload to 'msg'.
435
 * (Some Netlink protocols use the presence or absence of an attribute as a
436
 * Boolean flag.) */
437
void
438
nl_msg_push_flag(struct ofpbuf *msg, uint16_t type)
439
0
{
440
0
    nl_msg_push_unspec_uninit(msg, type, 0);
441
0
}
442
443
/* Prepends a Netlink attribute of the given 'type' and the given 8-bit 'value'
444
 * to 'msg'. */
445
void
446
nl_msg_push_u8(struct ofpbuf *msg, uint16_t type, uint8_t value)
447
0
{
448
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
449
0
}
450
451
/* Prepends a Netlink attribute of the given 'type' and the given 16-bit host
452
 * byte order 'value' to 'msg'. */
453
void
454
nl_msg_push_u16(struct ofpbuf *msg, uint16_t type, uint16_t value)
455
0
{
456
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
457
0
}
458
459
/* Prepends a Netlink attribute of the given 'type' and the given 32-bit host
460
 * byte order 'value' to 'msg'. */
461
void
462
nl_msg_push_u32(struct ofpbuf *msg, uint16_t type, uint32_t value)
463
0
{
464
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
465
0
}
466
467
/* Prepends a Netlink attribute of the given 'type' and the given 64-bit host
468
 * byte order 'value' to 'msg'. */
469
void
470
nl_msg_push_u64(struct ofpbuf *msg, uint16_t type, uint64_t value)
471
0
{
472
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
473
0
}
474
475
/* Prepends a Netlink attribute of the given 'type' and the given 128-bit host
476
 * byte order 'value' to 'msg'. */
477
void
478
nl_msg_push_u128(struct ofpbuf *msg, uint16_t type, ovs_u128 value)
479
0
{
480
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
481
0
}
482
483
/* Prepends a Netlink attribute of the given 'type' and the given 16-bit
484
 * network byte order 'value' to 'msg'. */
485
void
486
nl_msg_push_be16(struct ofpbuf *msg, uint16_t type, ovs_be16 value)
487
0
{
488
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
489
0
}
490
491
/* Prepends a Netlink attribute of the given 'type' and the given 32-bit
492
 * network byte order 'value' to 'msg'. */
493
void
494
nl_msg_push_be32(struct ofpbuf *msg, uint16_t type, ovs_be32 value)
495
0
{
496
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
497
0
}
498
499
/* Prepends a Netlink attribute of the given 'type' and the given 64-bit
500
 * network byte order 'value' to 'msg'. */
501
void
502
nl_msg_push_be64(struct ofpbuf *msg, uint16_t type, ovs_be64 value)
503
0
{
504
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
505
0
}
506
507
/* Prepends a Netlink attribute of the given 'type' and the given 128-bit
508
 * network byte order 'value' to 'msg'. */
509
void
510
nl_msg_push_be128(struct ofpbuf *msg, uint16_t type, ovs_be128 value)
511
0
{
512
0
    nl_msg_push_unspec(msg, type, &value, sizeof value);
513
0
}
514
515
/* Prepends a Netlink attribute of the given 'type' and the given
516
 * null-terminated string 'value' to 'msg'. */
517
void
518
nl_msg_push_string(struct ofpbuf *msg, uint16_t type, const char *value)
519
0
{
520
0
    nl_msg_push_unspec(msg, type, value, strlen(value) + 1);
521
0
}
522
523
/* Adds the header for nested Netlink attributes to 'msg', with the specified
524
 * 'type', and returns the header's offset within 'msg'.  The caller should add
525
 * the content for the nested Netlink attribute to 'msg' (e.g. using the other
526
 * nl_msg_*() functions), and then pass the returned offset to
527
 * nl_msg_end_nested() to finish up the nested attributes. */
528
size_t
529
nl_msg_start_nested(struct ofpbuf *msg, uint16_t type)
530
0
{
531
0
    size_t offset = msg->size;
532
0
    nl_msg_put_unspec_uninit(msg, type, 0);
533
0
    return offset;
534
0
}
535
536
/* Adds the header for nested Netlink attributes to 'msg', with the specified
537
 * 'type', and returns the header's offset within 'msg'. It's similar to
538
 * nl_msg_start_nested() and uses NLA_F_NESTED flag mandatorily. */
539
size_t
540
nl_msg_start_nested_with_flag(struct ofpbuf *msg, uint16_t type)
541
0
{
542
0
    return nl_msg_start_nested(msg, type | NLA_F_NESTED);
543
0
}
544
545
/* Finalizes a nested Netlink attribute in 'msg'.  'offset' should be the value
546
 * returned by nl_msg_start_nested(). */
547
void
548
nl_msg_end_nested(struct ofpbuf *msg, size_t offset)
549
0
{
550
0
    struct nlattr *attr = ofpbuf_at_assert(msg, offset, sizeof *attr);
551
0
    ovs_assert(!nl_attr_oversized(msg->size - offset - NLA_HDRLEN));
552
0
    attr->nla_len = msg->size - offset;
553
0
}
554
555
/* Cancel a nested Netlink attribute in 'msg'.  'offset' should be the value
556
 * returned by nl_msg_start_nested(). */
557
void
558
nl_msg_cancel_nested(struct ofpbuf *msg, size_t offset)
559
0
{
560
0
    msg->size = offset;
561
0
}
562
563
/* Same as nls_msg_end_nested() when the nested Netlink contains non empty
564
 * message. Otherwise, drop the nested message header from 'msg'.
565
 *
566
 * Return true if the nested message has been dropped.  */
567
bool
568
nl_msg_end_non_empty_nested(struct ofpbuf *msg, size_t offset)
569
0
{
570
0
    nl_msg_end_nested(msg, offset);
571
572
0
    struct nlattr *attr = ofpbuf_at_assert(msg, offset, sizeof *attr);
573
0
    if (!nl_attr_get_size(attr)) {
574
0
        nl_msg_cancel_nested(msg, offset);
575
0
        return true;
576
0
    } else {
577
0
        return false;
578
0
    }
579
0
}
580
581
/* Appends a nested Netlink attribute of the given 'type', with the 'size'
582
 * bytes of content starting at 'data', to 'msg'. */
583
void
584
nl_msg_put_nested(struct ofpbuf *msg,
585
                  uint16_t type, const void *data, size_t size)
586
0
{
587
0
    size_t offset = nl_msg_start_nested(msg, type);
588
0
    nl_msg_put(msg, data, size);
589
0
    nl_msg_end_nested(msg, offset);
590
0
}
591
592
/* Reset message size to offset. */
593
void
594
nl_msg_reset_size(struct ofpbuf *msg, size_t offset)
595
0
{
596
0
    msg->size = offset;
597
0
}
598
599
/* If 'buffer' begins with a valid "struct nlmsghdr", pulls the header and its
600
 * payload off 'buffer', stores header and payload in 'msg->data' and
601
 * 'msg->size', and returns a pointer to the header.
602
 *
603
 * If 'buffer' does not begin with a "struct nlmsghdr" or begins with one that
604
 * is invalid, returns NULL and clears 'buffer' and 'msg'. */
605
struct nlmsghdr *
606
nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg)
607
0
{
608
0
    if (buffer->size >= sizeof(struct nlmsghdr)) {
609
0
        struct nlmsghdr *nlmsghdr = nl_msg_nlmsghdr(buffer);
610
0
        size_t len = nlmsghdr->nlmsg_len;
611
0
        if (len >= sizeof *nlmsghdr && len <= buffer->size) {
612
0
            ofpbuf_use_const(msg, nlmsghdr, len);
613
0
            ofpbuf_pull(buffer, len);
614
0
            return nlmsghdr;
615
0
        }
616
0
    }
617
618
0
    ofpbuf_clear(buffer);
619
0
    msg->data = NULL;
620
0
    msg->size = 0;
621
0
    return NULL;
622
0
}
623
624
/* Returns true if a Netlink attribute with a payload that is 'payload_size'
625
 * bytes long would be oversized, that is, if it's not possible to create an
626
 * nlattr of that size because its size wouldn't fit in the 16-bit nla_len
627
 * field. */
628
bool
629
nl_attr_oversized(size_t payload_size)
630
0
{
631
0
    return payload_size > UINT16_MAX - NLA_HDRLEN;
632
0
}
633

634
/* Attributes. */
635
636
/* Returns the bits of 'nla->nla_type' that are significant for determining its
637
 * type. */
638
int
639
nl_attr_type(const struct nlattr *nla)
640
0
{
641
0
    return nla->nla_type & NLA_TYPE_MASK;
642
0
}
643
644
/* Returns the first byte in the payload of attribute 'nla'. */
645
const void *
646
nl_attr_get(const struct nlattr *nla)
647
0
{
648
0
    ovs_assert(nla->nla_len >= NLA_HDRLEN);
649
0
    return nla + 1;
650
0
}
651
652
/* Returns the number of bytes in the payload of attribute 'nla'. */
653
size_t
654
nl_attr_get_size(const struct nlattr *nla)
655
0
{
656
0
    ovs_assert(nla->nla_len >= NLA_HDRLEN);
657
0
    return nla->nla_len - NLA_HDRLEN;
658
0
}
659
660
/* Asserts that 'nla''s payload is at least 'size' bytes long, and returns the
661
 * first byte of the payload. */
662
const void *
663
nl_attr_get_unspec(const struct nlattr *nla, size_t size)
664
0
{
665
0
    ovs_assert(nla->nla_len >= NLA_HDRLEN + size);
666
0
    return nla + 1;
667
0
}
668
669
/* Returns true if 'nla' is nonnull.  (Some Netlink protocols use the presence
670
 * or absence of an attribute as a Boolean flag.) */
671
bool
672
nl_attr_get_flag(const struct nlattr *nla)
673
0
{
674
0
    return nla != NULL;
675
0
}
676
677
#define NL_ATTR_GET_AS(NLA, TYPE) \
678
0
        (*(TYPE*) nl_attr_get_unspec(nla, sizeof(TYPE)))
679
680
/* Returns the 8-bit value in 'nla''s payload.
681
 *
682
 * Asserts that 'nla''s payload is at least 1 byte long. */
683
uint8_t
684
nl_attr_get_u8(const struct nlattr *nla)
685
0
{
686
0
    return NL_ATTR_GET_AS(nla, uint8_t);
687
0
}
688
689
/* Returns the 16-bit host byte order value in 'nla''s payload.
690
 *
691
 * Asserts that 'nla''s payload is at least 2 bytes long. */
692
uint16_t
693
nl_attr_get_u16(const struct nlattr *nla)
694
0
{
695
0
    return NL_ATTR_GET_AS(nla, uint16_t);
696
0
}
697
698
/* Returns the 32-bit host byte order value in 'nla''s payload.
699
 *
700
 * Asserts that 'nla''s payload is at least 4 bytes long. */
701
uint32_t
702
nl_attr_get_u32(const struct nlattr *nla)
703
0
{
704
0
    return NL_ATTR_GET_AS(nla, uint32_t);
705
0
}
706
707
/* Returns the 64-bit host byte order value in 'nla''s payload.
708
 *
709
 * Asserts that 'nla''s payload is at least 8 bytes long. */
710
uint64_t
711
nl_attr_get_u64(const struct nlattr *nla)
712
0
{
713
0
    const ovs_32aligned_u64 *x = nl_attr_get_unspec(nla, sizeof *x);
714
0
    return get_32aligned_u64(x);
715
0
}
716
717
/* Returns the 128-bit host byte order value in 'nla''s payload.
718
 *
719
 * Asserts that 'nla''s payload is at least 16 bytes long. */
720
ovs_u128
721
nl_attr_get_u128(const struct nlattr *nla)
722
0
{
723
0
    const ovs_32aligned_u128 *x = nl_attr_get_unspec(nla, sizeof *x);
724
0
    return get_32aligned_u128(x);
725
0
}
726
727
/* Returns the 16-bit network byte order value in 'nla''s payload.
728
 *
729
 * Asserts that 'nla''s payload is at least 2 bytes long. */
730
ovs_be16
731
nl_attr_get_be16(const struct nlattr *nla)
732
0
{
733
0
    return NL_ATTR_GET_AS(nla, ovs_be16);
734
0
}
735
736
/* Returns the 32-bit network byte order value in 'nla''s payload.
737
 *
738
 * Asserts that 'nla''s payload is at least 4 bytes long. */
739
ovs_be32
740
nl_attr_get_be32(const struct nlattr *nla)
741
0
{
742
0
    return NL_ATTR_GET_AS(nla, ovs_be32);
743
0
}
744
745
/* Returns the 64-bit network byte order value in 'nla''s payload.
746
 *
747
 * Asserts that 'nla''s payload is at least 8 bytes long. */
748
ovs_be64
749
nl_attr_get_be64(const struct nlattr *nla)
750
0
{
751
0
    const ovs_32aligned_be64 *x = nl_attr_get_unspec(nla, sizeof *x);
752
0
    return get_32aligned_be64(x);
753
0
}
754
755
/* Returns the 128-bit network byte order value in 'nla''s payload.
756
 *
757
 * Asserts that 'nla''s payload is at least 16 bytes long. */
758
ovs_be128
759
nl_attr_get_be128(const struct nlattr *nla)
760
0
{
761
0
    const ovs_32aligned_be128 *x = nl_attr_get_unspec(nla, sizeof *x);
762
0
    return get_32aligned_be128(x);
763
0
}
764
765
/* Returns the IPv6 address value in 'nla''s payload.
766
 *
767
 * Asserts that 'nla''s payload is at least 16 bytes long. */
768
struct in6_addr
769
nl_attr_get_in6_addr(const struct nlattr *nla)
770
0
{
771
0
    return NL_ATTR_GET_AS(nla, struct in6_addr);
772
0
}
773
774
/* Returns the 32-bit odp_port_t value in 'nla''s payload.
775
 *
776
 * Asserts that 'nla''s payload is at least 4 bytes long. */
777
odp_port_t
778
nl_attr_get_odp_port(const struct nlattr *nla)
779
0
{
780
0
    return u32_to_odp(nl_attr_get_u32(nla));
781
0
}
782
783
/* Returns the null-terminated string value in 'nla''s payload.
784
 *
785
 * Asserts that 'nla''s payload contains a null-terminated string. */
786
const char *
787
nl_attr_get_string(const struct nlattr *nla)
788
0
{
789
0
    ovs_assert(nla->nla_len > NLA_HDRLEN);
790
0
    ovs_assert(memchr(nl_attr_get(nla), '\0', nla->nla_len - NLA_HDRLEN));
791
0
    return nl_attr_get(nla);
792
0
}
793
794
/* Initializes 'nested' to the payload of 'nla'. */
795
void
796
nl_attr_get_nested(const struct nlattr *nla, struct ofpbuf *nested)
797
0
{
798
0
    ofpbuf_use_const(nested, nl_attr_get(nla), nl_attr_get_size(nla));
799
0
}
800
801
/* Returns the Ethernet Address value in 'nla''s payload. */
802
struct eth_addr
803
nl_attr_get_eth_addr(const struct nlattr *nla)
804
0
{
805
0
    return NL_ATTR_GET_AS(nla, struct eth_addr);
806
0
}
807
808
/* Returns the Infiniband LL Address value in 'nla''s payload. */
809
struct ib_addr
810
nl_attr_get_ib_addr(const struct nlattr *nla)
811
0
{
812
0
    return NL_ATTR_GET_AS(nla, struct ib_addr);
813
0
}
814
815
/* Default minimum payload size for each type of attribute. */
816
static size_t
817
min_attr_len(enum nl_attr_type type)
818
0
{
819
0
    switch (type) {
820
0
    case NL_A_NO_ATTR: return 0;
821
0
    case NL_A_UNSPEC: return 0;
822
0
    case NL_A_U8: return 1;
823
0
    case NL_A_U16: return 2;
824
0
    case NL_A_U32: return 4;
825
0
    case NL_A_U64: return 8;
826
0
    case NL_A_U128: return 16;
827
0
    case NL_A_STRING: return 1;
828
0
    case NL_A_FLAG: return 0;
829
0
    case NL_A_IPV6: return 16;
830
0
    case NL_A_NESTED: return 0;
831
0
    case NL_A_LL_ADDR: return 6; /* ETH_ALEN */
832
0
    case NL_A_RTA_VIA: return sizeof(struct rtvia) + sizeof(struct in_addr);
833
0
    case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED();
834
0
    }
835
0
}
836
837
/* Default maximum payload size for each type of attribute. */
838
static size_t
839
max_attr_len(enum nl_attr_type type)
840
0
{
841
0
    switch (type) {
842
0
    case NL_A_NO_ATTR: return SIZE_MAX;
843
0
    case NL_A_UNSPEC: return SIZE_MAX;
844
0
    case NL_A_U8: return 1;
845
0
    case NL_A_U16: return 2;
846
0
    case NL_A_U32: return 4;
847
0
    case NL_A_U64: return 8;
848
0
    case NL_A_U128: return 16;
849
0
    case NL_A_STRING: return SIZE_MAX;
850
0
    case NL_A_FLAG: return SIZE_MAX;
851
0
    case NL_A_IPV6: return 16;
852
0
    case NL_A_NESTED: return SIZE_MAX;
853
0
    case NL_A_LL_ADDR: return 20; /* INFINIBAND_ALEN */
854
0
    case NL_A_RTA_VIA: return sizeof(struct rtvia) + sizeof(struct in6_addr);
855
0
    case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED();
856
0
    }
857
0
}
858
859
bool
860
nl_attr_validate(const struct nlattr *nla, const struct nl_policy *policy)
861
0
{
862
0
    uint16_t type = nl_attr_type(nla);
863
0
    size_t min_len;
864
0
    size_t max_len;
865
0
    size_t len;
866
867
0
    if (policy->type == NL_A_NO_ATTR) {
868
0
        return true;
869
0
    }
870
871
    /* Figure out min and max length. */
872
0
    min_len = policy->min_len;
873
0
    if (!min_len) {
874
0
        min_len = min_attr_len(policy->type);
875
0
    }
876
0
    max_len = policy->max_len;
877
0
    if (!max_len) {
878
0
        max_len = max_attr_len(policy->type);
879
0
    }
880
881
    /* Verify length. */
882
0
    len = nl_attr_get_size(nla);
883
0
    if (len < min_len || len > max_len) {
884
0
        VLOG_DBG_RL(&rl, "attr %"PRIu16" length %"PRIuSIZE" not in "
885
0
                    "allowed range %"PRIuSIZE"...%"PRIuSIZE, type, len, min_len, max_len);
886
0
        return false;
887
0
    }
888
889
    /* Strings must be null terminated and must not have embedded nulls. */
890
0
    if (policy->type == NL_A_STRING) {
891
0
        if (((char *) nla)[nla->nla_len - 1]) {
892
0
            VLOG_DBG_RL(&rl, "attr %"PRIu16" lacks null at end", type);
893
0
            return false;
894
0
        }
895
0
        if (memchr(nla + 1, '\0', len - 1) != NULL) {
896
0
            VLOG_DBG_RL(&rl, "attr %"PRIu16" has bad length", type);
897
0
            return false;
898
0
        }
899
0
    }
900
901
0
    return true;
902
0
}
903
904
/* Parses the 'msg' starting at the given 'nla_offset' as a sequence of Netlink
905
 * attributes.  'policy[i]', for 0 <= i < n_attrs, specifies how the attribute
906
 * with nla_type == i is parsed; a pointer to attribute i is stored in
907
 * attrs[i].  Returns true if successful, false on failure.
908
 *
909
 * If the Netlink attributes in 'msg' follow a Netlink header and a Generic
910
 * Netlink header, then 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN. */
911
bool
912
nl_policy_parse(const struct ofpbuf *msg, size_t nla_offset,
913
                const struct nl_policy policy[],
914
                struct nlattr *attrs[], size_t n_attrs)
915
0
{
916
0
    struct nlattr *nla;
917
0
    size_t left;
918
0
    size_t i;
919
920
0
    memset(attrs, 0, n_attrs * sizeof *attrs);
921
922
0
    if (msg->size < nla_offset) {
923
0
        VLOG_DBG_RL(&rl, "missing headers in nl_policy_parse");
924
0
        return false;
925
0
    }
926
927
0
    NL_ATTR_FOR_EACH (nla, left, ofpbuf_at(msg, nla_offset, 0),
928
0
                      msg->size - nla_offset)
929
0
    {
930
0
        uint16_t type = nl_attr_type(nla);
931
0
        if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) {
932
0
            const struct nl_policy *e = &policy[type];
933
0
            if (!nl_attr_validate(nla, e)) {
934
0
                return false;
935
0
            }
936
0
            if (attrs[type]) {
937
0
                VLOG_DBG_RL(&rl, "duplicate attr %"PRIu16, type);
938
0
            }
939
0
            attrs[type] = nla;
940
0
        }
941
0
    }
942
0
    if (left) {
943
0
        VLOG_DBG_RL(&rl, "attributes followed by garbage");
944
0
        return false;
945
0
    }
946
947
0
    for (i = 0; i < n_attrs; i++) {
948
0
        const struct nl_policy *e = &policy[i];
949
0
        if (!e->optional && e->type != NL_A_NO_ATTR && !attrs[i]) {
950
0
            VLOG_DBG_RL(&rl, "required attr %"PRIuSIZE" missing", i);
951
0
            return false;
952
0
        }
953
0
    }
954
0
    return true;
955
0
}
956
957
/* Parses the Netlink attributes within 'nla'.  'policy[i]', for 0 <= i <
958
 * n_attrs, specifies how the attribute with nla_type == i is parsed; a pointer
959
 * to attribute i is stored in attrs[i].  Returns true if successful, false on
960
 * failure. */
961
bool
962
nl_parse_nested(const struct nlattr *nla, const struct nl_policy policy[],
963
                struct nlattr *attrs[], size_t n_attrs)
964
0
{
965
0
    struct ofpbuf buf;
966
967
0
    nl_attr_get_nested(nla, &buf);
968
0
    return nl_policy_parse(&buf, 0, policy, attrs, n_attrs);
969
0
}
970
971
const struct nlattr *
972
nl_attr_find__(const struct nlattr *attrs, size_t size, uint16_t type)
973
0
{
974
0
    const struct nlattr *nla;
975
0
    size_t left;
976
977
0
    NL_ATTR_FOR_EACH (nla, left, attrs, size) {
978
0
        if (nl_attr_type(nla) == type) {
979
0
            return nla;
980
0
        }
981
0
    }
982
0
    return NULL;
983
0
}
984
985
/* Returns the first Netlink attribute within 'buf' with the specified 'type',
986
 * skipping a header of 'hdr_len' bytes at the beginning of 'buf'.
987
 *
988
 * This function does not validate the attribute's length. */
989
const struct nlattr *
990
nl_attr_find(const struct ofpbuf *buf, size_t hdr_len, uint16_t type)
991
0
{
992
0
    return nl_attr_find__(ofpbuf_at(buf, hdr_len, 0), buf->size - hdr_len,
993
0
                          type);
994
0
}
995
996
/* Returns the first Netlink attribute within 'nla' with the specified
997
 * 'type'.
998
 *
999
 * This function does not validate the attribute's length. */
1000
const struct nlattr *
1001
nl_attr_find_nested(const struct nlattr *nla, uint16_t type)
1002
0
{
1003
0
    return nl_attr_find__(nl_attr_get(nla), nl_attr_get_size(nla), type);
1004
0
}