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 { 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 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