Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/ynl/lib/ynl.c
29271 views
1
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
#include <errno.h>
3
#include <poll.h>
4
#include <string.h>
5
#include <stdlib.h>
6
#include <stdio.h>
7
#include <unistd.h>
8
#include <linux/types.h>
9
#include <linux/genetlink.h>
10
#include <sys/socket.h>
11
12
#include "ynl.h"
13
14
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*arr))
15
16
#define __yerr_msg(yse, _msg...) \
17
({ \
18
struct ynl_error *_yse = (yse); \
19
\
20
if (_yse) { \
21
snprintf(_yse->msg, sizeof(_yse->msg) - 1, _msg); \
22
_yse->msg[sizeof(_yse->msg) - 1] = 0; \
23
} \
24
})
25
26
#define __yerr_code(yse, _code...) \
27
({ \
28
struct ynl_error *_yse = (yse); \
29
\
30
if (_yse) { \
31
_yse->code = _code; \
32
} \
33
})
34
35
#define __yerr(yse, _code, _msg...) \
36
({ \
37
__yerr_msg(yse, _msg); \
38
__yerr_code(yse, _code); \
39
})
40
41
#define __perr(yse, _msg) __yerr(yse, errno, _msg)
42
43
#define yerr_msg(_ys, _msg...) __yerr_msg(&(_ys)->err, _msg)
44
#define yerr(_ys, _code, _msg...) __yerr(&(_ys)->err, _code, _msg)
45
#define perr(_ys, _msg) __yerr(&(_ys)->err, errno, _msg)
46
47
/* -- Netlink boiler plate */
48
static bool
49
ynl_err_walk_is_sel(const struct ynl_policy_nest *policy,
50
const struct nlattr *attr)
51
{
52
unsigned int type = ynl_attr_type(attr);
53
54
return policy && type <= policy->max_attr &&
55
policy->table[type].is_selector;
56
}
57
58
static const struct ynl_policy_nest *
59
ynl_err_walk_sel_policy(const struct ynl_policy_attr *policy_attr,
60
const struct nlattr *selector)
61
{
62
const struct ynl_policy_nest *policy = policy_attr->nest;
63
const char *sel;
64
unsigned int i;
65
66
if (!policy_attr->is_submsg)
67
return policy;
68
69
sel = ynl_attr_get_str(selector);
70
for (i = 0; i <= policy->max_attr; i++) {
71
if (!strcmp(sel, policy->table[i].name))
72
return policy->table[i].nest;
73
}
74
75
return NULL;
76
}
77
78
static int
79
ynl_err_walk_report_one(const struct ynl_policy_nest *policy,
80
const struct nlattr *selector, unsigned int type,
81
char *str, int str_sz, int *n)
82
{
83
if (!policy) {
84
if (*n < str_sz)
85
*n += snprintf(str, str_sz, "!policy");
86
return 1;
87
}
88
89
if (type > policy->max_attr) {
90
if (*n < str_sz)
91
*n += snprintf(str, str_sz, "!oob");
92
return 1;
93
}
94
95
if (!policy->table[type].name) {
96
if (*n < str_sz)
97
*n += snprintf(str, str_sz, "!name");
98
return 1;
99
}
100
101
if (*n < str_sz) {
102
int sz;
103
104
sz = snprintf(str, str_sz - *n,
105
".%s", policy->table[type].name);
106
*n += sz;
107
str += sz;
108
}
109
110
if (policy->table[type].is_submsg) {
111
if (!selector) {
112
if (*n < str_sz)
113
*n += snprintf(str, str_sz, "(!selector)");
114
return 1;
115
}
116
117
if (ynl_attr_type(selector) !=
118
policy->table[type].selector_type) {
119
if (*n < str_sz)
120
*n += snprintf(str, str_sz, "(!=selector)");
121
return 1;
122
}
123
124
if (*n < str_sz)
125
*n += snprintf(str, str_sz - *n, "(%s)",
126
ynl_attr_get_str(selector));
127
}
128
129
return 0;
130
}
131
132
static int
133
ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
134
const struct ynl_policy_nest *policy, char *str, int str_sz,
135
const struct ynl_policy_nest **nest_pol)
136
{
137
const struct ynl_policy_nest *next_pol;
138
const struct nlattr *selector = NULL;
139
unsigned int astart_off, aend_off;
140
const struct nlattr *attr;
141
unsigned int data_len;
142
unsigned int type;
143
bool found = false;
144
int n = 0;
145
146
if (!policy) {
147
if (n < str_sz)
148
n += snprintf(str, str_sz, "!policy");
149
return n;
150
}
151
152
data_len = end - start;
153
154
ynl_attr_for_each_payload(start, data_len, attr) {
155
astart_off = (char *)attr - (char *)start;
156
aend_off = (char *)ynl_attr_data_end(attr) - (char *)start;
157
158
if (ynl_err_walk_is_sel(policy, attr))
159
selector = attr;
160
161
if (aend_off <= off)
162
continue;
163
164
found = true;
165
break;
166
}
167
if (!found)
168
return 0;
169
170
off -= astart_off;
171
172
type = ynl_attr_type(attr);
173
174
if (ynl_err_walk_report_one(policy, selector, type, str, str_sz, &n))
175
return n;
176
177
next_pol = ynl_err_walk_sel_policy(&policy->table[type], selector);
178
if (!next_pol)
179
return n;
180
181
if (!off) {
182
if (nest_pol)
183
*nest_pol = next_pol;
184
return n;
185
}
186
187
if (!next_pol) {
188
if (n < str_sz)
189
n += snprintf(str, str_sz, "!nest");
190
return n;
191
}
192
193
off -= sizeof(struct nlattr);
194
start = ynl_attr_data(attr);
195
end = start + ynl_attr_data_len(attr);
196
197
return n + ynl_err_walk(ys, start, end, off, next_pol,
198
&str[n], str_sz - n, nest_pol);
199
}
200
201
#define NLMSGERR_ATTR_MISS_TYPE (NLMSGERR_ATTR_POLICY + 1)
202
#define NLMSGERR_ATTR_MISS_NEST (NLMSGERR_ATTR_POLICY + 2)
203
#define NLMSGERR_ATTR_MAX (NLMSGERR_ATTR_MAX + 2)
204
205
static int
206
ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
207
unsigned int hlen)
208
{
209
const struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
210
char miss_attr[sizeof(ys->err.msg)];
211
char bad_attr[sizeof(ys->err.msg)];
212
const struct nlattr *attr;
213
const char *str = NULL;
214
215
if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) {
216
yerr_msg(ys, "%s", strerror(ys->err.code));
217
return YNL_PARSE_CB_OK;
218
}
219
220
ynl_attr_for_each(attr, nlh, hlen) {
221
unsigned int len, type;
222
223
len = ynl_attr_data_len(attr);
224
type = ynl_attr_type(attr);
225
226
if (type > NLMSGERR_ATTR_MAX)
227
continue;
228
229
tb[type] = attr;
230
231
switch (type) {
232
case NLMSGERR_ATTR_OFFS:
233
case NLMSGERR_ATTR_MISS_TYPE:
234
case NLMSGERR_ATTR_MISS_NEST:
235
if (len != sizeof(__u32))
236
return YNL_PARSE_CB_ERROR;
237
break;
238
case NLMSGERR_ATTR_MSG:
239
str = ynl_attr_get_str(attr);
240
if (str[len - 1])
241
return YNL_PARSE_CB_ERROR;
242
break;
243
default:
244
break;
245
}
246
}
247
248
bad_attr[0] = '\0';
249
miss_attr[0] = '\0';
250
251
if (tb[NLMSGERR_ATTR_OFFS]) {
252
unsigned int n, off;
253
void *start, *end;
254
255
ys->err.attr_offs = ynl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
256
257
n = snprintf(bad_attr, sizeof(bad_attr), "%sbad attribute: ",
258
str ? " (" : "");
259
260
start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
261
end = ynl_nlmsg_end_addr(ys->nlh);
262
263
off = ys->err.attr_offs;
264
off -= sizeof(struct nlmsghdr);
265
off -= ys->req_hdr_len;
266
267
n += ynl_err_walk(ys, start, end, off, ys->req_policy,
268
&bad_attr[n], sizeof(bad_attr) - n, NULL);
269
270
if (n >= sizeof(bad_attr))
271
n = sizeof(bad_attr) - 1;
272
bad_attr[n] = '\0';
273
}
274
if (tb[NLMSGERR_ATTR_MISS_TYPE]) {
275
const struct ynl_policy_nest *nest_pol = NULL;
276
unsigned int n, off, type;
277
void *start, *end;
278
int n2;
279
280
type = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_TYPE]);
281
282
n = snprintf(miss_attr, sizeof(miss_attr), "%smissing attribute: ",
283
bad_attr[0] ? ", " : (str ? " (" : ""));
284
285
start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
286
end = ynl_nlmsg_end_addr(ys->nlh);
287
288
nest_pol = ys->req_policy;
289
if (tb[NLMSGERR_ATTR_MISS_NEST]) {
290
off = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
291
off -= sizeof(struct nlmsghdr);
292
off -= ys->req_hdr_len;
293
294
n += ynl_err_walk(ys, start, end, off, ys->req_policy,
295
&miss_attr[n], sizeof(miss_attr) - n,
296
&nest_pol);
297
}
298
299
n2 = 0;
300
ynl_err_walk_report_one(nest_pol, NULL, type, &miss_attr[n],
301
sizeof(miss_attr) - n, &n2);
302
n += n2;
303
304
if (n >= sizeof(miss_attr))
305
n = sizeof(miss_attr) - 1;
306
miss_attr[n] = '\0';
307
}
308
309
/* Implicitly depend on ys->err.code already set */
310
if (str)
311
yerr_msg(ys, "Kernel %s: '%s'%s%s%s",
312
ys->err.code ? "error" : "warning",
313
str, bad_attr, miss_attr,
314
bad_attr[0] || miss_attr[0] ? ")" : "");
315
else if (bad_attr[0] || miss_attr[0])
316
yerr_msg(ys, "Kernel %s: %s%s",
317
ys->err.code ? "error" : "warning",
318
bad_attr, miss_attr);
319
else
320
yerr_msg(ys, "%s", strerror(ys->err.code));
321
322
return YNL_PARSE_CB_OK;
323
}
324
325
static int
326
ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
327
{
328
const struct nlmsgerr *err = ynl_nlmsg_data(nlh);
329
unsigned int hlen;
330
int code;
331
332
code = err->error >= 0 ? err->error : -err->error;
333
yarg->ys->err.code = code;
334
errno = code;
335
336
hlen = sizeof(*err);
337
if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
338
hlen += ynl_nlmsg_data_len(&err->msg);
339
340
ynl_ext_ack_check(yarg->ys, nlh, hlen);
341
342
return code ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_STOP;
343
}
344
345
static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
346
{
347
int err;
348
349
err = *(int *)NLMSG_DATA(nlh);
350
if (err < 0) {
351
yarg->ys->err.code = -err;
352
errno = -err;
353
354
ynl_ext_ack_check(yarg->ys, nlh, sizeof(int));
355
356
return YNL_PARSE_CB_ERROR;
357
}
358
return YNL_PARSE_CB_STOP;
359
}
360
361
/* Attribute validation */
362
363
int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
364
unsigned int type)
365
{
366
const struct ynl_policy_attr *policy;
367
unsigned char *data;
368
unsigned int len;
369
370
data = ynl_attr_data(attr);
371
len = ynl_attr_data_len(attr);
372
if (type > yarg->rsp_policy->max_attr) {
373
yerr(yarg->ys, YNL_ERROR_INTERNAL,
374
"Internal error, validating unknown attribute");
375
return -1;
376
}
377
378
policy = &yarg->rsp_policy->table[type];
379
380
switch (policy->type) {
381
case YNL_PT_REJECT:
382
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
383
"Rejected attribute (%s)", policy->name);
384
return -1;
385
case YNL_PT_IGNORE:
386
break;
387
case YNL_PT_U8:
388
if (len == sizeof(__u8))
389
break;
390
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
391
"Invalid attribute (u8 %s)", policy->name);
392
return -1;
393
case YNL_PT_U16:
394
if (len == sizeof(__u16))
395
break;
396
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
397
"Invalid attribute (u16 %s)", policy->name);
398
return -1;
399
case YNL_PT_U32:
400
if (len == sizeof(__u32))
401
break;
402
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
403
"Invalid attribute (u32 %s)", policy->name);
404
return -1;
405
case YNL_PT_U64:
406
if (len == sizeof(__u64))
407
break;
408
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
409
"Invalid attribute (u64 %s)", policy->name);
410
return -1;
411
case YNL_PT_UINT:
412
if (len == sizeof(__u32) || len == sizeof(__u64))
413
break;
414
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
415
"Invalid attribute (uint %s)", policy->name);
416
return -1;
417
case YNL_PT_FLAG:
418
/* Let flags grow into real attrs, why not.. */
419
break;
420
case YNL_PT_NEST:
421
if (!len || len >= sizeof(*attr))
422
break;
423
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
424
"Invalid attribute (nest %s)", policy->name);
425
return -1;
426
case YNL_PT_BINARY:
427
if (!policy->len || len == policy->len)
428
break;
429
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
430
"Invalid attribute (binary %s)", policy->name);
431
return -1;
432
case YNL_PT_NUL_STR:
433
if (len && (!policy->len || len <= policy->len) && !data[len - 1])
434
break;
435
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
436
"Invalid attribute (string %s)", policy->name);
437
return -1;
438
case YNL_PT_BITFIELD32:
439
if (len == sizeof(struct nla_bitfield32))
440
break;
441
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
442
"Invalid attribute (bitfield32 %s)", policy->name);
443
return -1;
444
default:
445
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
446
"Invalid attribute (unknown %s)", policy->name);
447
return -1;
448
}
449
450
return 0;
451
}
452
453
int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
454
const char *sel_name)
455
{
456
yerr(yarg->ys, YNL_ERROR_SUBMSG_KEY,
457
"Parsing error: Sub-message key not set (msg %s, key %s)",
458
field_name, sel_name);
459
return YNL_PARSE_CB_ERROR;
460
}
461
462
/* Generic code */
463
464
static void ynl_err_reset(struct ynl_sock *ys)
465
{
466
ys->err.code = 0;
467
ys->err.attr_offs = 0;
468
ys->err.msg[0] = 0;
469
}
470
471
struct nlmsghdr *ynl_msg_start(struct ynl_sock *ys, __u32 id, __u16 flags)
472
{
473
struct nlmsghdr *nlh;
474
475
ynl_err_reset(ys);
476
477
nlh = ys->nlh = ynl_nlmsg_put_header(ys->tx_buf);
478
nlh->nlmsg_type = id;
479
nlh->nlmsg_flags = flags;
480
nlh->nlmsg_seq = ++ys->seq;
481
482
/* This is a local YNL hack for length checking, we put the buffer
483
* length in nlmsg_pid, since messages sent to the kernel always use
484
* PID 0. Message needs to be terminated with ynl_msg_end().
485
*/
486
nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZE;
487
488
return nlh;
489
}
490
491
static int ynl_msg_end(struct ynl_sock *ys, struct nlmsghdr *nlh)
492
{
493
/* We stash buffer length in nlmsg_pid. */
494
if (nlh->nlmsg_pid == 0) {
495
yerr(ys, YNL_ERROR_INPUT_INVALID,
496
"Unknown input buffer length");
497
return -EINVAL;
498
}
499
if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW) {
500
yerr(ys, YNL_ERROR_INPUT_TOO_BIG,
501
"Constructed message longer than internal buffer");
502
return -EMSGSIZE;
503
}
504
505
nlh->nlmsg_pid = 0;
506
return 0;
507
}
508
509
struct nlmsghdr *
510
ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags,
511
__u8 cmd, __u8 version)
512
{
513
struct genlmsghdr gehdr;
514
struct nlmsghdr *nlh;
515
void *data;
516
517
nlh = ynl_msg_start(ys, id, flags);
518
519
memset(&gehdr, 0, sizeof(gehdr));
520
gehdr.cmd = cmd;
521
gehdr.version = version;
522
523
data = ynl_nlmsg_put_extra_header(nlh, sizeof(gehdr));
524
memcpy(data, &gehdr, sizeof(gehdr));
525
526
return nlh;
527
}
528
529
struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags)
530
{
531
return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | flags);
532
}
533
534
struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id)
535
{
536
return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
537
}
538
539
struct nlmsghdr *
540
ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
541
{
542
return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK, cmd, version);
543
}
544
545
struct nlmsghdr *
546
ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
547
{
548
return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,
549
cmd, version);
550
}
551
552
static int ynl_cb_null(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
553
{
554
yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG,
555
"Received a message when none were expected");
556
557
return YNL_PARSE_CB_ERROR;
558
}
559
560
static int
561
__ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb, int flags)
562
{
563
struct ynl_sock *ys = yarg->ys;
564
const struct nlmsghdr *nlh;
565
ssize_t len, rem;
566
int ret;
567
568
len = recv(ys->socket, ys->rx_buf, YNL_SOCKET_BUFFER_SIZE, flags);
569
if (len < 0) {
570
if (flags & MSG_DONTWAIT && errno == EAGAIN)
571
return YNL_PARSE_CB_STOP;
572
return len;
573
}
574
575
ret = YNL_PARSE_CB_STOP;
576
for (rem = len; rem > 0; NLMSG_NEXT(nlh, rem)) {
577
nlh = (struct nlmsghdr *)&ys->rx_buf[len - rem];
578
if (!NLMSG_OK(nlh, rem)) {
579
yerr(yarg->ys, YNL_ERROR_INV_RESP,
580
"Invalid message or trailing data in the response.");
581
return YNL_PARSE_CB_ERROR;
582
}
583
584
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
585
/* TODO: handle this better */
586
yerr(yarg->ys, YNL_ERROR_DUMP_INTER,
587
"Dump interrupted / inconsistent, please retry.");
588
return YNL_PARSE_CB_ERROR;
589
}
590
591
switch (nlh->nlmsg_type) {
592
case 0:
593
yerr(yarg->ys, YNL_ERROR_INV_RESP,
594
"Invalid message type in the response.");
595
return YNL_PARSE_CB_ERROR;
596
case NLMSG_NOOP:
597
case NLMSG_OVERRUN ... NLMSG_MIN_TYPE - 1:
598
ret = YNL_PARSE_CB_OK;
599
break;
600
case NLMSG_ERROR:
601
ret = ynl_cb_error(nlh, yarg);
602
break;
603
case NLMSG_DONE:
604
ret = ynl_cb_done(nlh, yarg);
605
break;
606
default:
607
ret = cb(nlh, yarg);
608
break;
609
}
610
}
611
612
return ret;
613
}
614
615
static int ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb)
616
{
617
return __ynl_sock_read_msgs(yarg, cb, 0);
618
}
619
620
static int ynl_recv_ack(struct ynl_sock *ys, int ret)
621
{
622
struct ynl_parse_arg yarg = { .ys = ys, };
623
624
if (!ret) {
625
yerr(ys, YNL_ERROR_EXPECT_ACK,
626
"Expecting an ACK but nothing received");
627
return -1;
628
}
629
630
return ynl_sock_read_msgs(&yarg, ynl_cb_null);
631
}
632
633
/* Init/fini and genetlink boiler plate */
634
static int
635
ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts)
636
{
637
const struct nlattr *entry, *attr;
638
unsigned int i;
639
640
ynl_attr_for_each_nested(attr, mcasts)
641
ys->n_mcast_groups++;
642
643
if (!ys->n_mcast_groups)
644
return 0;
645
646
ys->mcast_groups = calloc(ys->n_mcast_groups,
647
sizeof(*ys->mcast_groups));
648
if (!ys->mcast_groups)
649
return YNL_PARSE_CB_ERROR;
650
651
i = 0;
652
ynl_attr_for_each_nested(entry, mcasts) {
653
ynl_attr_for_each_nested(attr, entry) {
654
if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_ID)
655
ys->mcast_groups[i].id = ynl_attr_get_u32(attr);
656
if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_NAME) {
657
strncpy(ys->mcast_groups[i].name,
658
ynl_attr_get_str(attr),
659
GENL_NAMSIZ - 1);
660
ys->mcast_groups[i].name[GENL_NAMSIZ - 1] = 0;
661
}
662
}
663
i++;
664
}
665
666
return 0;
667
}
668
669
static int
670
ynl_get_family_info_cb(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
671
{
672
struct ynl_sock *ys = yarg->ys;
673
const struct nlattr *attr;
674
bool found_id = true;
675
676
ynl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
677
if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GROUPS)
678
if (ynl_get_family_info_mcast(ys, attr))
679
return YNL_PARSE_CB_ERROR;
680
681
if (ynl_attr_type(attr) != CTRL_ATTR_FAMILY_ID)
682
continue;
683
684
if (ynl_attr_data_len(attr) != sizeof(__u16)) {
685
yerr(ys, YNL_ERROR_ATTR_INVALID, "Invalid family ID");
686
return YNL_PARSE_CB_ERROR;
687
}
688
689
ys->family_id = ynl_attr_get_u16(attr);
690
found_id = true;
691
}
692
693
if (!found_id) {
694
yerr(ys, YNL_ERROR_ATTR_MISSING, "Family ID missing");
695
return YNL_PARSE_CB_ERROR;
696
}
697
return YNL_PARSE_CB_OK;
698
}
699
700
static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name)
701
{
702
struct ynl_parse_arg yarg = { .ys = ys, };
703
struct nlmsghdr *nlh;
704
int err;
705
706
nlh = ynl_gemsg_start_req(ys, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1);
707
ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
708
709
err = ynl_msg_end(ys, nlh);
710
if (err < 0)
711
return err;
712
713
err = send(ys->socket, nlh, nlh->nlmsg_len, 0);
714
if (err < 0) {
715
perr(ys, "failed to request socket family info");
716
return err;
717
}
718
719
err = ynl_sock_read_msgs(&yarg, ynl_get_family_info_cb);
720
if (err < 0) {
721
free(ys->mcast_groups);
722
perr(ys, "failed to receive the socket family info - no such family?");
723
return err;
724
}
725
726
err = ynl_recv_ack(ys, err);
727
if (err < 0) {
728
free(ys->mcast_groups);
729
return err;
730
}
731
732
return 0;
733
}
734
735
struct ynl_sock *
736
ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse)
737
{
738
struct sockaddr_nl addr;
739
struct ynl_sock *ys;
740
socklen_t addrlen;
741
int sock_type;
742
int one = 1;
743
744
ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE);
745
if (!ys)
746
return NULL;
747
memset(ys, 0, sizeof(*ys));
748
749
ys->family = yf;
750
ys->tx_buf = &ys->raw_buf[0];
751
ys->rx_buf = &ys->raw_buf[YNL_SOCKET_BUFFER_SIZE];
752
ys->ntf_last_next = &ys->ntf_first;
753
754
sock_type = yf->is_classic ? yf->classic_id : NETLINK_GENERIC;
755
756
ys->socket = socket(AF_NETLINK, SOCK_RAW, sock_type);
757
if (ys->socket < 0) {
758
__perr(yse, "failed to create a netlink socket");
759
goto err_free_sock;
760
}
761
762
if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_CAP_ACK,
763
&one, sizeof(one))) {
764
__perr(yse, "failed to enable netlink ACK");
765
goto err_close_sock;
766
}
767
if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_EXT_ACK,
768
&one, sizeof(one))) {
769
__perr(yse, "failed to enable netlink ext ACK");
770
goto err_close_sock;
771
}
772
773
memset(&addr, 0, sizeof(addr));
774
addr.nl_family = AF_NETLINK;
775
if (bind(ys->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
776
__perr(yse, "unable to bind to a socket address");
777
goto err_close_sock;
778
}
779
780
memset(&addr, 0, sizeof(addr));
781
addrlen = sizeof(addr);
782
if (getsockname(ys->socket, (struct sockaddr *)&addr, &addrlen) < 0) {
783
__perr(yse, "unable to read socket address");
784
goto err_close_sock;
785
}
786
ys->portid = addr.nl_pid;
787
ys->seq = random();
788
789
if (yf->is_classic) {
790
ys->family_id = yf->classic_id;
791
} else if (ynl_sock_read_family(ys, yf->name)) {
792
if (yse)
793
memcpy(yse, &ys->err, sizeof(*yse));
794
goto err_close_sock;
795
}
796
797
return ys;
798
799
err_close_sock:
800
close(ys->socket);
801
err_free_sock:
802
free(ys);
803
return NULL;
804
}
805
806
void ynl_sock_destroy(struct ynl_sock *ys)
807
{
808
struct ynl_ntf_base_type *ntf;
809
810
close(ys->socket);
811
while ((ntf = ynl_ntf_dequeue(ys)))
812
ynl_ntf_free(ntf);
813
free(ys->mcast_groups);
814
free(ys);
815
}
816
817
/* YNL multicast handling */
818
819
void ynl_ntf_free(struct ynl_ntf_base_type *ntf)
820
{
821
ntf->free(ntf);
822
}
823
824
int ynl_subscribe(struct ynl_sock *ys, const char *grp_name)
825
{
826
unsigned int i;
827
int err;
828
829
for (i = 0; i < ys->n_mcast_groups; i++)
830
if (!strcmp(ys->mcast_groups[i].name, grp_name))
831
break;
832
if (i == ys->n_mcast_groups) {
833
yerr(ys, ENOENT, "Multicast group '%s' not found", grp_name);
834
return -1;
835
}
836
837
err = setsockopt(ys->socket, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
838
&ys->mcast_groups[i].id,
839
sizeof(ys->mcast_groups[i].id));
840
if (err < 0) {
841
perr(ys, "Subscribing to multicast group failed");
842
return -1;
843
}
844
845
return 0;
846
}
847
848
int ynl_socket_get_fd(struct ynl_sock *ys)
849
{
850
return ys->socket;
851
}
852
853
struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys)
854
{
855
struct ynl_ntf_base_type *ntf;
856
857
if (!ynl_has_ntf(ys))
858
return NULL;
859
860
ntf = ys->ntf_first;
861
ys->ntf_first = ntf->next;
862
if (ys->ntf_last_next == &ntf->next)
863
ys->ntf_last_next = &ys->ntf_first;
864
865
return ntf;
866
}
867
868
static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
869
{
870
struct ynl_parse_arg yarg = { .ys = ys, };
871
const struct ynl_ntf_info *info;
872
struct ynl_ntf_base_type *rsp;
873
__u32 cmd;
874
int ret;
875
876
if (ys->family->is_classic) {
877
cmd = nlh->nlmsg_type;
878
} else {
879
struct genlmsghdr *gehdr;
880
881
gehdr = ynl_nlmsg_data(nlh);
882
cmd = gehdr->cmd;
883
}
884
885
if (cmd >= ys->family->ntf_info_size)
886
return YNL_PARSE_CB_ERROR;
887
info = &ys->family->ntf_info[cmd];
888
if (!info->cb)
889
return YNL_PARSE_CB_ERROR;
890
891
rsp = calloc(1, info->alloc_sz);
892
rsp->free = info->free;
893
yarg.data = rsp->data;
894
yarg.rsp_policy = info->policy;
895
896
ret = info->cb(nlh, &yarg);
897
if (ret <= YNL_PARSE_CB_STOP)
898
goto err_free;
899
900
rsp->family = nlh->nlmsg_type;
901
rsp->cmd = cmd;
902
903
*ys->ntf_last_next = rsp;
904
ys->ntf_last_next = &rsp->next;
905
906
return YNL_PARSE_CB_OK;
907
908
err_free:
909
info->free(rsp);
910
return YNL_PARSE_CB_ERROR;
911
}
912
913
static int
914
ynl_ntf_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
915
{
916
return ynl_ntf_parse(yarg->ys, nlh);
917
}
918
919
int ynl_ntf_check(struct ynl_sock *ys)
920
{
921
struct ynl_parse_arg yarg = { .ys = ys, };
922
int err;
923
924
do {
925
err = __ynl_sock_read_msgs(&yarg, ynl_ntf_trampoline,
926
MSG_DONTWAIT);
927
if (err < 0)
928
return err;
929
} while (err > 0);
930
931
return 0;
932
}
933
934
/* YNL specific helpers used by the auto-generated code */
935
936
struct ynl_dump_list_type *YNL_LIST_END = (void *)(0xb4d123);
937
938
void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd)
939
{
940
yerr(ys, YNL_ERROR_UNKNOWN_NTF,
941
"Unknown notification message type '%d'", cmd);
942
}
943
944
int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg)
945
{
946
yerr(yarg->ys, YNL_ERROR_INV_RESP, "Error parsing response: %s", msg);
947
return YNL_PARSE_CB_ERROR;
948
}
949
950
static int
951
ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd)
952
{
953
if (ys->family->is_classic) {
954
if (nlh->nlmsg_type != rsp_cmd)
955
return ynl_ntf_parse(ys, nlh);
956
} else {
957
struct genlmsghdr *gehdr;
958
959
if (ynl_nlmsg_data_len(nlh) < sizeof(*gehdr)) {
960
yerr(ys, YNL_ERROR_INV_RESP,
961
"Kernel responded with truncated message");
962
return -1;
963
}
964
965
gehdr = ynl_nlmsg_data(nlh);
966
if (gehdr->cmd != rsp_cmd)
967
return ynl_ntf_parse(ys, nlh);
968
}
969
970
return 0;
971
}
972
973
static
974
int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
975
{
976
struct ynl_req_state *yrs = (void *)yarg;
977
int ret;
978
979
ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd);
980
if (ret)
981
return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
982
983
return yrs->cb(nlh, &yrs->yarg);
984
}
985
986
int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
987
struct ynl_req_state *yrs)
988
{
989
int err;
990
991
err = ynl_msg_end(ys, req_nlh);
992
if (err < 0)
993
return err;
994
995
err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
996
if (err < 0)
997
return err;
998
999
do {
1000
err = ynl_sock_read_msgs(&yrs->yarg, ynl_req_trampoline);
1001
} while (err > 0);
1002
1003
return err;
1004
}
1005
1006
static int
1007
ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data)
1008
{
1009
struct ynl_dump_state *ds = (void *)data;
1010
struct ynl_dump_list_type *obj;
1011
struct ynl_parse_arg yarg = {};
1012
int ret;
1013
1014
ret = ynl_check_alien(ds->yarg.ys, nlh, ds->rsp_cmd);
1015
if (ret)
1016
return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
1017
1018
obj = calloc(1, ds->alloc_sz);
1019
if (!obj)
1020
return YNL_PARSE_CB_ERROR;
1021
1022
if (!ds->first)
1023
ds->first = obj;
1024
if (ds->last)
1025
ds->last->next = obj;
1026
ds->last = obj;
1027
1028
yarg = ds->yarg;
1029
yarg.data = &obj->data;
1030
1031
return ds->cb(nlh, &yarg);
1032
}
1033
1034
static void *ynl_dump_end(struct ynl_dump_state *ds)
1035
{
1036
if (!ds->first)
1037
return YNL_LIST_END;
1038
1039
ds->last->next = YNL_LIST_END;
1040
return ds->first;
1041
}
1042
1043
int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
1044
struct ynl_dump_state *yds)
1045
{
1046
int err;
1047
1048
err = ynl_msg_end(ys, req_nlh);
1049
if (err < 0)
1050
return err;
1051
1052
err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
1053
if (err < 0)
1054
return err;
1055
1056
do {
1057
err = ynl_sock_read_msgs(&yds->yarg, ynl_dump_trampoline);
1058
if (err < 0)
1059
goto err_close_list;
1060
} while (err > 0);
1061
1062
yds->first = ynl_dump_end(yds);
1063
return 0;
1064
1065
err_close_list:
1066
yds->first = ynl_dump_end(yds);
1067
return -1;
1068
}
1069
1070