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