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
ynl_err_walk_is_sel(const struct ynl_policy_nest * policy,const struct nlattr * attr)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 *
ynl_err_walk_sel_policy(const struct ynl_policy_attr * policy_attr,const struct nlattr * selector)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
ynl_err_walk_report_one(const struct ynl_policy_nest * policy,const struct nlattr * selector,unsigned int type,char * str,int str_sz,int * n)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
ynl_err_walk(struct ynl_sock * ys,void * start,void * end,unsigned int off,const struct ynl_policy_nest * policy,char * str,int str_sz,const struct ynl_policy_nest ** nest_pol)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
ynl_ext_ack_check(struct ynl_sock * ys,const struct nlmsghdr * nlh,unsigned int hlen)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
ynl_cb_error(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)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
ynl_cb_done(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)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
ynl_attr_validate(struct ynl_parse_arg * yarg,const struct nlattr * attr)363 int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
364 {
365 const struct ynl_policy_attr *policy;
366 unsigned int type, len;
367 unsigned char *data;
368
369 data = ynl_attr_data(attr);
370 len = ynl_attr_data_len(attr);
371 type = ynl_attr_type(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
ynl_submsg_failed(struct ynl_parse_arg * yarg,const char * field_name,const char * sel_name)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
ynl_err_reset(struct ynl_sock * ys)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
ynl_msg_start(struct ynl_sock * ys,__u32 id,__u16 flags)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
ynl_msg_end(struct ynl_sock * ys,struct nlmsghdr * nlh)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 *
ynl_gemsg_start(struct ynl_sock * ys,__u32 id,__u16 flags,__u8 cmd,__u8 version)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
ynl_msg_start_req(struct ynl_sock * ys,__u32 id,__u16 flags)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
ynl_msg_start_dump(struct ynl_sock * ys,__u32 id)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 *
ynl_gemsg_start_req(struct ynl_sock * ys,__u32 id,__u8 cmd,__u8 version)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 *
ynl_gemsg_start_dump(struct ynl_sock * ys,__u32 id,__u8 cmd,__u8 version)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
ynl_cb_null(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)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
__ynl_sock_read_msgs(struct ynl_parse_arg * yarg,ynl_parse_cb_t cb,int flags)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
ynl_sock_read_msgs(struct ynl_parse_arg * yarg,ynl_parse_cb_t cb)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
ynl_recv_ack(struct ynl_sock * ys,int ret)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
ynl_get_family_info_mcast(struct ynl_sock * ys,const struct nlattr * mcasts)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
ynl_get_family_info_cb(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)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
ynl_sock_read_family(struct ynl_sock * ys,const char * family_name)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 *
ynl_sock_create(const struct ynl_family * yf,struct ynl_error * yse)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
ynl_sock_destroy(struct ynl_sock * ys)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
ynl_ntf_free(struct ynl_ntf_base_type * ntf)819 void ynl_ntf_free(struct ynl_ntf_base_type *ntf)
820 {
821 ntf->free(ntf);
822 }
823
ynl_subscribe(struct ynl_sock * ys,const char * grp_name)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
ynl_socket_get_fd(struct ynl_sock * ys)848 int ynl_socket_get_fd(struct ynl_sock *ys)
849 {
850 return ys->socket;
851 }
852
ynl_ntf_dequeue(struct ynl_sock * ys)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
ynl_ntf_parse(struct ynl_sock * ys,const struct nlmsghdr * nlh)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
ynl_ntf_trampoline(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)914 ynl_ntf_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
915 {
916 return ynl_ntf_parse(yarg->ys, nlh);
917 }
918
ynl_ntf_check(struct ynl_sock * ys)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
ynl_error_unknown_notification(struct ynl_sock * ys,__u8 cmd)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
ynl_error_parse(struct ynl_parse_arg * yarg,const char * msg)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
ynl_check_alien(struct ynl_sock * ys,const struct nlmsghdr * nlh,__u32 rsp_cmd)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
ynl_req_trampoline(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)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
ynl_exec(struct ynl_sock * ys,struct nlmsghdr * req_nlh,struct ynl_req_state * yrs)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
ynl_dump_trampoline(const struct nlmsghdr * nlh,struct ynl_parse_arg * data)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
ynl_dump_end(struct ynl_dump_state * ds)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
ynl_exec_dump(struct ynl_sock * ys,struct nlmsghdr * req_nlh,struct ynl_dump_state * yds)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