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(const 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 const struct ynl_policy_nest *policy, char *str, int str_sz, 79 const 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 = (char *)ynl_attr_data_end(attr) - (char *)start; 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 const 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 const 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 /* This is a local YNL hack for length checking, we put the buffer 408 * length in nlmsg_pid, since messages sent to the kernel always use 409 * PID 0. Message needs to be terminated with ynl_msg_end(). 410 */ 411 nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZE; 412 413 return nlh; 414 } 415 416 static int ynl_msg_end(struct ynl_sock *ys, struct nlmsghdr *nlh) 417 { 418 /* We stash buffer length in nlmsg_pid. */ 419 if (nlh->nlmsg_pid == 0) { 420 yerr(ys, YNL_ERROR_INPUT_INVALID, 421 "Unknown input buffer length"); 422 return -EINVAL; 423 } 424 if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW) { 425 yerr(ys, YNL_ERROR_INPUT_TOO_BIG, 426 "Constructed message longer than internal buffer"); 427 return -EMSGSIZE; 428 } 429 430 nlh->nlmsg_pid = 0; 431 return 0; 432 } 433 434 struct nlmsghdr * 435 ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags, 436 __u8 cmd, __u8 version) 437 { 438 struct genlmsghdr gehdr; 439 struct nlmsghdr *nlh; 440 void *data; 441 442 nlh = ynl_msg_start(ys, id, flags); 443 444 memset(&gehdr, 0, sizeof(gehdr)); 445 gehdr.cmd = cmd; 446 gehdr.version = version; 447 448 data = ynl_nlmsg_put_extra_header(nlh, sizeof(gehdr)); 449 memcpy(data, &gehdr, sizeof(gehdr)); 450 451 return nlh; 452 } 453 454 struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id) 455 { 456 return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK); 457 } 458 459 struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id) 460 { 461 return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); 462 } 463 464 struct nlmsghdr * 465 ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version) 466 { 467 return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK, cmd, version); 468 } 469 470 struct nlmsghdr * 471 ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version) 472 { 473 return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, 474 cmd, version); 475 } 476 477 static int ynl_cb_null(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) 478 { 479 yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG, 480 "Received a message when none were expected"); 481 482 return YNL_PARSE_CB_ERROR; 483 } 484 485 static int 486 __ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb, int flags) 487 { 488 struct ynl_sock *ys = yarg->ys; 489 const struct nlmsghdr *nlh; 490 ssize_t len, rem; 491 int ret; 492 493 len = recv(ys->socket, ys->rx_buf, YNL_SOCKET_BUFFER_SIZE, flags); 494 if (len < 0) { 495 if (flags & MSG_DONTWAIT && errno == EAGAIN) 496 return YNL_PARSE_CB_STOP; 497 return len; 498 } 499 500 ret = YNL_PARSE_CB_STOP; 501 for (rem = len; rem > 0; NLMSG_NEXT(nlh, rem)) { 502 nlh = (struct nlmsghdr *)&ys->rx_buf[len - rem]; 503 if (!NLMSG_OK(nlh, rem)) { 504 yerr(yarg->ys, YNL_ERROR_INV_RESP, 505 "Invalid message or trailing data in the response."); 506 return YNL_PARSE_CB_ERROR; 507 } 508 509 if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) { 510 /* TODO: handle this better */ 511 yerr(yarg->ys, YNL_ERROR_DUMP_INTER, 512 "Dump interrupted / inconsistent, please retry."); 513 return YNL_PARSE_CB_ERROR; 514 } 515 516 switch (nlh->nlmsg_type) { 517 case 0: 518 yerr(yarg->ys, YNL_ERROR_INV_RESP, 519 "Invalid message type in the response."); 520 return YNL_PARSE_CB_ERROR; 521 case NLMSG_NOOP: 522 case NLMSG_OVERRUN ... NLMSG_MIN_TYPE - 1: 523 ret = YNL_PARSE_CB_OK; 524 break; 525 case NLMSG_ERROR: 526 ret = ynl_cb_error(nlh, yarg); 527 break; 528 case NLMSG_DONE: 529 ret = ynl_cb_done(nlh, yarg); 530 break; 531 default: 532 ret = cb(nlh, yarg); 533 break; 534 } 535 } 536 537 return ret; 538 } 539 540 static int ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb) 541 { 542 return __ynl_sock_read_msgs(yarg, cb, 0); 543 } 544 545 static int ynl_recv_ack(struct ynl_sock *ys, int ret) 546 { 547 struct ynl_parse_arg yarg = { .ys = ys, }; 548 549 if (!ret) { 550 yerr(ys, YNL_ERROR_EXPECT_ACK, 551 "Expecting an ACK but nothing received"); 552 return -1; 553 } 554 555 return ynl_sock_read_msgs(&yarg, ynl_cb_null); 556 } 557 558 /* Init/fini and genetlink boiler plate */ 559 static int 560 ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts) 561 { 562 const struct nlattr *entry, *attr; 563 unsigned int i; 564 565 ynl_attr_for_each_nested(attr, mcasts) 566 ys->n_mcast_groups++; 567 568 if (!ys->n_mcast_groups) 569 return 0; 570 571 ys->mcast_groups = calloc(ys->n_mcast_groups, 572 sizeof(*ys->mcast_groups)); 573 if (!ys->mcast_groups) 574 return YNL_PARSE_CB_ERROR; 575 576 i = 0; 577 ynl_attr_for_each_nested(entry, mcasts) { 578 ynl_attr_for_each_nested(attr, entry) { 579 if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_ID) 580 ys->mcast_groups[i].id = ynl_attr_get_u32(attr); 581 if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_NAME) { 582 strncpy(ys->mcast_groups[i].name, 583 ynl_attr_get_str(attr), 584 GENL_NAMSIZ - 1); 585 ys->mcast_groups[i].name[GENL_NAMSIZ - 1] = 0; 586 } 587 } 588 i++; 589 } 590 591 return 0; 592 } 593 594 static int 595 ynl_get_family_info_cb(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) 596 { 597 struct ynl_sock *ys = yarg->ys; 598 const struct nlattr *attr; 599 bool found_id = true; 600 601 ynl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { 602 if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GROUPS) 603 if (ynl_get_family_info_mcast(ys, attr)) 604 return YNL_PARSE_CB_ERROR; 605 606 if (ynl_attr_type(attr) != CTRL_ATTR_FAMILY_ID) 607 continue; 608 609 if (ynl_attr_data_len(attr) != sizeof(__u16)) { 610 yerr(ys, YNL_ERROR_ATTR_INVALID, "Invalid family ID"); 611 return YNL_PARSE_CB_ERROR; 612 } 613 614 ys->family_id = ynl_attr_get_u16(attr); 615 found_id = true; 616 } 617 618 if (!found_id) { 619 yerr(ys, YNL_ERROR_ATTR_MISSING, "Family ID missing"); 620 return YNL_PARSE_CB_ERROR; 621 } 622 return YNL_PARSE_CB_OK; 623 } 624 625 static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name) 626 { 627 struct ynl_parse_arg yarg = { .ys = ys, }; 628 struct nlmsghdr *nlh; 629 int err; 630 631 nlh = ynl_gemsg_start_req(ys, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1); 632 ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY_NAME, family_name); 633 634 err = ynl_msg_end(ys, nlh); 635 if (err < 0) 636 return err; 637 638 err = send(ys->socket, nlh, nlh->nlmsg_len, 0); 639 if (err < 0) { 640 perr(ys, "failed to request socket family info"); 641 return err; 642 } 643 644 err = ynl_sock_read_msgs(&yarg, ynl_get_family_info_cb); 645 if (err < 0) { 646 free(ys->mcast_groups); 647 perr(ys, "failed to receive the socket family info - no such family?"); 648 return err; 649 } 650 651 err = ynl_recv_ack(ys, err); 652 if (err < 0) { 653 free(ys->mcast_groups); 654 return err; 655 } 656 657 return 0; 658 } 659 660 struct ynl_sock * 661 ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse) 662 { 663 struct sockaddr_nl addr; 664 struct ynl_sock *ys; 665 socklen_t addrlen; 666 int sock_type; 667 int one = 1; 668 669 ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE); 670 if (!ys) 671 return NULL; 672 memset(ys, 0, sizeof(*ys)); 673 674 ys->family = yf; 675 ys->tx_buf = &ys->raw_buf[0]; 676 ys->rx_buf = &ys->raw_buf[YNL_SOCKET_BUFFER_SIZE]; 677 ys->ntf_last_next = &ys->ntf_first; 678 679 sock_type = yf->is_classic ? yf->classic_id : NETLINK_GENERIC; 680 681 ys->socket = socket(AF_NETLINK, SOCK_RAW, sock_type); 682 if (ys->socket < 0) { 683 __perr(yse, "failed to create a netlink socket"); 684 goto err_free_sock; 685 } 686 687 if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_CAP_ACK, 688 &one, sizeof(one))) { 689 __perr(yse, "failed to enable netlink ACK"); 690 goto err_close_sock; 691 } 692 if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_EXT_ACK, 693 &one, sizeof(one))) { 694 __perr(yse, "failed to enable netlink ext ACK"); 695 goto err_close_sock; 696 } 697 698 memset(&addr, 0, sizeof(addr)); 699 addr.nl_family = AF_NETLINK; 700 if (bind(ys->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 701 __perr(yse, "unable to bind to a socket address"); 702 goto err_close_sock; 703 } 704 705 memset(&addr, 0, sizeof(addr)); 706 addrlen = sizeof(addr); 707 if (getsockname(ys->socket, (struct sockaddr *)&addr, &addrlen) < 0) { 708 __perr(yse, "unable to read socket address"); 709 goto err_close_sock; 710 } 711 ys->portid = addr.nl_pid; 712 ys->seq = random(); 713 714 if (yf->is_classic) { 715 ys->family_id = yf->classic_id; 716 } else if (ynl_sock_read_family(ys, yf->name)) { 717 if (yse) 718 memcpy(yse, &ys->err, sizeof(*yse)); 719 goto err_close_sock; 720 } 721 722 return ys; 723 724 err_close_sock: 725 close(ys->socket); 726 err_free_sock: 727 free(ys); 728 return NULL; 729 } 730 731 void ynl_sock_destroy(struct ynl_sock *ys) 732 { 733 struct ynl_ntf_base_type *ntf; 734 735 close(ys->socket); 736 while ((ntf = ynl_ntf_dequeue(ys))) 737 ynl_ntf_free(ntf); 738 free(ys->mcast_groups); 739 free(ys); 740 } 741 742 /* YNL multicast handling */ 743 744 void ynl_ntf_free(struct ynl_ntf_base_type *ntf) 745 { 746 ntf->free(ntf); 747 } 748 749 int ynl_subscribe(struct ynl_sock *ys, const char *grp_name) 750 { 751 unsigned int i; 752 int err; 753 754 for (i = 0; i < ys->n_mcast_groups; i++) 755 if (!strcmp(ys->mcast_groups[i].name, grp_name)) 756 break; 757 if (i == ys->n_mcast_groups) { 758 yerr(ys, ENOENT, "Multicast group '%s' not found", grp_name); 759 return -1; 760 } 761 762 err = setsockopt(ys->socket, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, 763 &ys->mcast_groups[i].id, 764 sizeof(ys->mcast_groups[i].id)); 765 if (err < 0) { 766 perr(ys, "Subscribing to multicast group failed"); 767 return -1; 768 } 769 770 return 0; 771 } 772 773 int ynl_socket_get_fd(struct ynl_sock *ys) 774 { 775 return ys->socket; 776 } 777 778 struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys) 779 { 780 struct ynl_ntf_base_type *ntf; 781 782 if (!ynl_has_ntf(ys)) 783 return NULL; 784 785 ntf = ys->ntf_first; 786 ys->ntf_first = ntf->next; 787 if (ys->ntf_last_next == &ntf->next) 788 ys->ntf_last_next = &ys->ntf_first; 789 790 return ntf; 791 } 792 793 static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh) 794 { 795 struct ynl_parse_arg yarg = { .ys = ys, }; 796 const struct ynl_ntf_info *info; 797 struct ynl_ntf_base_type *rsp; 798 __u32 cmd; 799 int ret; 800 801 if (ys->family->is_classic) { 802 cmd = nlh->nlmsg_type; 803 } else { 804 struct genlmsghdr *gehdr; 805 806 gehdr = ynl_nlmsg_data(nlh); 807 cmd = gehdr->cmd; 808 } 809 810 if (cmd >= ys->family->ntf_info_size) 811 return YNL_PARSE_CB_ERROR; 812 info = &ys->family->ntf_info[cmd]; 813 if (!info->cb) 814 return YNL_PARSE_CB_ERROR; 815 816 rsp = calloc(1, info->alloc_sz); 817 rsp->free = info->free; 818 yarg.data = rsp->data; 819 yarg.rsp_policy = info->policy; 820 821 ret = info->cb(nlh, &yarg); 822 if (ret <= YNL_PARSE_CB_STOP) 823 goto err_free; 824 825 rsp->family = nlh->nlmsg_type; 826 rsp->cmd = cmd; 827 828 *ys->ntf_last_next = rsp; 829 ys->ntf_last_next = &rsp->next; 830 831 return YNL_PARSE_CB_OK; 832 833 err_free: 834 info->free(rsp); 835 return YNL_PARSE_CB_ERROR; 836 } 837 838 static int 839 ynl_ntf_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) 840 { 841 return ynl_ntf_parse(yarg->ys, nlh); 842 } 843 844 int ynl_ntf_check(struct ynl_sock *ys) 845 { 846 struct ynl_parse_arg yarg = { .ys = ys, }; 847 int err; 848 849 do { 850 err = __ynl_sock_read_msgs(&yarg, ynl_ntf_trampoline, 851 MSG_DONTWAIT); 852 if (err < 0) 853 return err; 854 } while (err > 0); 855 856 return 0; 857 } 858 859 /* YNL specific helpers used by the auto-generated code */ 860 861 struct ynl_dump_list_type *YNL_LIST_END = (void *)(0xb4d123); 862 863 void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd) 864 { 865 yerr(ys, YNL_ERROR_UNKNOWN_NTF, 866 "Unknown notification message type '%d'", cmd); 867 } 868 869 int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg) 870 { 871 yerr(yarg->ys, YNL_ERROR_INV_RESP, "Error parsing response: %s", msg); 872 return YNL_PARSE_CB_ERROR; 873 } 874 875 static int 876 ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd) 877 { 878 if (ys->family->is_classic) { 879 if (nlh->nlmsg_type != rsp_cmd) 880 return ynl_ntf_parse(ys, nlh); 881 } else { 882 struct genlmsghdr *gehdr; 883 884 if (ynl_nlmsg_data_len(nlh) < sizeof(*gehdr)) { 885 yerr(ys, YNL_ERROR_INV_RESP, 886 "Kernel responded with truncated message"); 887 return -1; 888 } 889 890 gehdr = ynl_nlmsg_data(nlh); 891 if (gehdr->cmd != rsp_cmd) 892 return ynl_ntf_parse(ys, nlh); 893 } 894 895 return 0; 896 } 897 898 static 899 int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) 900 { 901 struct ynl_req_state *yrs = (void *)yarg; 902 int ret; 903 904 ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd); 905 if (ret) 906 return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK; 907 908 return yrs->cb(nlh, &yrs->yarg); 909 } 910 911 int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh, 912 struct ynl_req_state *yrs) 913 { 914 int err; 915 916 err = ynl_msg_end(ys, req_nlh); 917 if (err < 0) 918 return err; 919 920 err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0); 921 if (err < 0) 922 return err; 923 924 do { 925 err = ynl_sock_read_msgs(&yrs->yarg, ynl_req_trampoline); 926 } while (err > 0); 927 928 return err; 929 } 930 931 static int 932 ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data) 933 { 934 struct ynl_dump_state *ds = (void *)data; 935 struct ynl_dump_list_type *obj; 936 struct ynl_parse_arg yarg = {}; 937 int ret; 938 939 ret = ynl_check_alien(ds->yarg.ys, nlh, ds->rsp_cmd); 940 if (ret) 941 return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK; 942 943 obj = calloc(1, ds->alloc_sz); 944 if (!obj) 945 return YNL_PARSE_CB_ERROR; 946 947 if (!ds->first) 948 ds->first = obj; 949 if (ds->last) 950 ds->last->next = obj; 951 ds->last = obj; 952 953 yarg = ds->yarg; 954 yarg.data = &obj->data; 955 956 return ds->cb(nlh, &yarg); 957 } 958 959 static void *ynl_dump_end(struct ynl_dump_state *ds) 960 { 961 if (!ds->first) 962 return YNL_LIST_END; 963 964 ds->last->next = YNL_LIST_END; 965 return ds->first; 966 } 967 968 int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh, 969 struct ynl_dump_state *yds) 970 { 971 int err; 972 973 err = ynl_msg_end(ys, req_nlh); 974 if (err < 0) 975 return err; 976 977 err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0); 978 if (err < 0) 979 return err; 980 981 do { 982 err = ynl_sock_read_msgs(&yds->yarg, ynl_dump_trampoline); 983 if (err < 0) 984 goto err_close_list; 985 } while (err > 0); 986 987 yds->first = ynl_dump_end(yds); 988 return 0; 989 990 err_close_list: 991 yds->first = ynl_dump_end(yds); 992 return -1; 993 } 994