1 /* 2 * bearer.c TIPC bearer functionality. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Richard Alpe <richard.alpe (at) ericsson.com> 10 */ 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <netdb.h> 16 #include <errno.h> 17 18 #include <linux/tipc_netlink.h> 19 #include <linux/tipc.h> 20 #include <linux/genetlink.h> 21 22 #include <libmnl/libmnl.h> 23 #include <sys/socket.h> 24 25 #include "cmdl.h" 26 #include "msg.h" 27 #include "bearer.h" 28 29 static void _print_bearer_opts(void) 30 { 31 fprintf(stderr, 32 "\nOPTIONS\n" 33 " priority - Bearer link priority\n" 34 " tolerance - Bearer link tolerance\n" 35 " window - Bearer link window\n"); 36 } 37 38 static void _print_bearer_media(void) 39 { 40 fprintf(stderr, 41 "\nMEDIA\n" 42 " udp - User Datagram Protocol\n" 43 " ib - Infiniband\n" 44 " eth - Ethernet\n"); 45 } 46 47 static void cmd_bearer_enable_l2_help(struct cmdl *cmdl) 48 { 49 fprintf(stderr, 50 "Usage: %s bearer enable media MEDIA device DEVICE [OPTIONS]\n" 51 "\nOPTIONS\n" 52 " domain DOMAIN - Discovery domain\n" 53 " priority PRIORITY - Bearer priority\n", 54 cmdl->argv[0]); 55 } 56 57 static void cmd_bearer_enable_udp_help(struct cmdl *cmdl) 58 { 59 fprintf(stderr, 60 "Usage: %s bearer enable media udp name NAME localip IP [OPTIONS]\n" 61 "\nOPTIONS\n" 62 " domain DOMAIN - Discovery domain\n" 63 " priority PRIORITY - Bearer priority\n" 64 " localport PORT - Local UDP port (default 6118)\n" 65 " remoteip IP - Remote IP address\n" 66 " remoteport IP - Remote UDP port (default 6118)\n", 67 cmdl->argv[0]); 68 } 69 70 static int enable_l2_bearer(struct nlmsghdr *nlh, struct opt *opts, 71 struct cmdl *cmdl) 72 { 73 struct opt *opt; 74 char id[TIPC_MAX_BEARER_NAME]; 75 76 if (!(opt = get_opt(opts, "device"))) { 77 fprintf(stderr, "error: missing bearer device\n"); 78 return -EINVAL; 79 } 80 snprintf(id, sizeof(id), "eth:%s", opt->val); 81 mnl_attr_put_strz(nlh, TIPC_NLA_BEARER_NAME, id); 82 83 return 0; 84 } 85 86 static int get_netid_cb(const struct nlmsghdr *nlh, void *data) 87 { 88 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); 89 struct nlattr *info[TIPC_NLA_MAX + 1] = {}; 90 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {}; 91 int *netid = (int*)data; 92 93 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); 94 if (!info[TIPC_NLA_NET]) 95 return MNL_CB_ERROR; 96 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs); 97 if (!attrs[TIPC_NLA_NET_ID]) 98 return MNL_CB_ERROR; 99 *netid = mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]); 100 101 return MNL_CB_OK; 102 } 103 104 static int generate_multicast(short af, char *buf, int bufsize) 105 { 106 int netid; 107 char mnl_msg[MNL_SOCKET_BUFFER_SIZE]; 108 struct nlmsghdr *nlh; 109 110 if (!(nlh = msg_init(mnl_msg, TIPC_NL_NET_GET))) { 111 fprintf(stderr, "error, message initialization failed\n"); 112 return -1; 113 } 114 if (msg_dumpit(nlh, get_netid_cb, &netid)) { 115 fprintf(stderr, "error, failed to fetch TIPC network id from kernel\n"); 116 return -EINVAL; 117 } 118 if (af == AF_INET) 119 snprintf(buf, bufsize, "228.0.%u.%u", (netid>>8) & 0xFF, netid & 0xFF); 120 else 121 snprintf(buf, bufsize, "ff02::%u", netid); 122 123 return 0; 124 } 125 126 static int enable_udp_bearer(struct nlmsghdr *nlh, struct opt *opts, 127 struct cmdl *cmdl) 128 { 129 int err; 130 struct opt *opt; 131 struct nlattr *nest; 132 char buf[INET6_ADDRSTRLEN]; 133 char *locport = "6118"; 134 char *remport = "6118"; 135 char *locip = NULL; 136 char *remip = NULL; 137 char name[TIPC_MAX_BEARER_NAME]; 138 struct addrinfo *loc = NULL; 139 struct addrinfo *rem = NULL; 140 struct addrinfo hints = { 141 .ai_family = AF_UNSPEC, 142 .ai_socktype = SOCK_DGRAM 143 }; 144 145 if (help_flag) { 146 cmd_bearer_enable_udp_help(cmdl); 147 /* TODO find a better error code? */ 148 return -EINVAL; 149 } 150 151 if (!(opt = get_opt(opts, "name"))) { 152 fprintf(stderr, "error, udp bearer name missing\n"); 153 cmd_bearer_enable_udp_help(cmdl); 154 return -EINVAL; 155 } 156 snprintf(name, sizeof(name), "udp:%s", opt->val); 157 158 if (!(opt = get_opt(opts, "localip"))) { 159 fprintf(stderr, "error, udp bearer localip missing\n"); 160 cmd_bearer_enable_udp_help(cmdl); 161 return -EINVAL; 162 } 163 locip = opt->val; 164 165 if ((opt = get_opt(opts, "remoteip"))) 166 remip = opt->val; 167 168 if ((opt = get_opt(opts, "localport"))) 169 locport = opt->val; 170 171 if ((opt = get_opt(opts, "remoteport"))) 172 remport = opt->val; 173 174 if ((err = getaddrinfo(locip, locport, &hints, &loc))) { 175 fprintf(stderr, "UDP local address error: %s\n", 176 gai_strerror(err)); 177 return err; 178 } 179 180 if (!remip) { 181 if (generate_multicast(loc->ai_family, buf, sizeof(buf))) { 182 fprintf(stderr, "Failed to generate multicast address\n"); 183 return -EINVAL; 184 } 185 remip = buf; 186 } 187 188 if ((err = getaddrinfo(remip, remport, &hints, &rem))) { 189 fprintf(stderr, "UDP remote address error: %s\n", 190 gai_strerror(err)); 191 freeaddrinfo(loc); 192 return err; 193 } 194 195 if (rem->ai_family != loc->ai_family) { 196 fprintf(stderr, "UDP local and remote AF mismatch\n"); 197 return -EINVAL; 198 } 199 200 mnl_attr_put_strz(nlh, TIPC_NLA_BEARER_NAME, name); 201 202 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_UDP_OPTS); 203 mnl_attr_put(nlh, TIPC_NLA_UDP_LOCAL, loc->ai_addrlen, loc->ai_addr); 204 mnl_attr_put(nlh, TIPC_NLA_UDP_REMOTE, rem->ai_addrlen, rem->ai_addr); 205 mnl_attr_nest_end(nlh, nest); 206 207 freeaddrinfo(rem); 208 freeaddrinfo(loc); 209 210 return 0; 211 } 212 213 static void cmd_bearer_enable_help(struct cmdl *cmdl) 214 { 215 fprintf(stderr, 216 "Usage: %s bearer enable [OPTIONS] media MEDIA ARGS...\n\n" 217 "OPTIONS\n" 218 " domain DOMAIN - Discovery domain\n" 219 " priority PRIORITY - Bearer priority\n", 220 cmdl->argv[0]); 221 _print_bearer_media(); 222 } 223 224 static int cmd_bearer_enable(struct nlmsghdr *nlh, const struct cmd *cmd, 225 struct cmdl *cmdl, void *data) 226 { 227 int err; 228 struct opt *opt; 229 struct nlattr *nest; 230 char buf[MNL_SOCKET_BUFFER_SIZE]; 231 char *media; 232 struct opt opts[] = { 233 { "device", NULL }, 234 { "domain", NULL }, 235 { "localip", NULL }, 236 { "localport", NULL }, 237 { "media", NULL }, 238 { "name", NULL }, 239 { "priority", NULL }, 240 { "remoteip", NULL }, 241 { "remoteport", NULL }, 242 { NULL } 243 }; 244 245 if (parse_opts(opts, cmdl) < 0) { 246 if (help_flag) 247 (cmd->help)(cmdl); 248 return -EINVAL; 249 } 250 251 if (!(opt = get_opt(opts, "media"))) { 252 if (help_flag) 253 (cmd->help)(cmdl); 254 else 255 fprintf(stderr, "error, missing bearer media\n"); 256 return -EINVAL; 257 } 258 media = opt->val; 259 260 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_ENABLE))) { 261 fprintf(stderr, "error: message initialisation failed\n"); 262 return -1; 263 } 264 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER); 265 266 if ((opt = get_opt(opts, "domain"))) 267 mnl_attr_put_u32(nlh, TIPC_NLA_BEARER_DOMAIN, atoi(opt->val)); 268 269 if ((opt = get_opt(opts, "priority"))) { 270 struct nlattr *props; 271 272 props = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_PROP); 273 mnl_attr_put_u32(nlh, TIPC_NLA_PROP_PRIO, atoi(opt->val)); 274 mnl_attr_nest_end(nlh, props); 275 } 276 277 if (strcmp(media, "udp") == 0) { 278 if (help_flag) { 279 cmd_bearer_enable_udp_help(cmdl); 280 return -EINVAL; 281 } 282 if ((err = enable_udp_bearer(nlh, opts, cmdl))) 283 return err; 284 } else if ((strcmp(media, "eth") == 0) || (strcmp(media, "udp") == 0)) { 285 if (help_flag) { 286 cmd_bearer_enable_l2_help(cmdl); 287 return -EINVAL; 288 } 289 if ((err = enable_l2_bearer(nlh, opts, cmdl))) 290 return err; 291 } else { 292 fprintf(stderr, "error, invalid media type \"%s\"\n", media); 293 return -EINVAL; 294 } 295 296 mnl_attr_nest_end(nlh, nest); 297 298 return msg_doit(nlh, NULL, NULL); 299 } 300 301 static int add_l2_bearer(struct nlmsghdr *nlh, struct opt *opts) 302 { 303 struct opt *opt; 304 char id[TIPC_MAX_BEARER_NAME]; 305 306 if (!(opt = get_opt(opts, "device"))) { 307 fprintf(stderr, "error: missing bearer device\n"); 308 return -EINVAL; 309 } 310 snprintf(id, sizeof(id), "eth:%s", opt->val); 311 312 mnl_attr_put_strz(nlh, TIPC_NLA_BEARER_NAME, id); 313 314 return 0; 315 } 316 317 static int add_udp_bearer(struct nlmsghdr *nlh, struct opt *opts) 318 { 319 struct opt *opt; 320 char id[TIPC_MAX_BEARER_NAME]; 321 322 if (!(opt = get_opt(opts, "name"))) { 323 fprintf(stderr, "error: missing bearer name\n"); 324 return -EINVAL; 325 } 326 snprintf(id, sizeof(id), "udp:%s", opt->val); 327 328 mnl_attr_put_strz(nlh, TIPC_NLA_BEARER_NAME, id); 329 330 return 0; 331 } 332 333 static void cmd_bearer_disable_l2_help(struct cmdl *cmdl) 334 { 335 fprintf(stderr, "Usage: %s bearer disable media udp device DEVICE\n", 336 cmdl->argv[0]); 337 } 338 339 static void cmd_bearer_disable_udp_help(struct cmdl *cmdl) 340 { 341 fprintf(stderr, "Usage: %s bearer disable media udp name NAME\n", 342 cmdl->argv[0]); 343 } 344 345 static void cmd_bearer_disable_help(struct cmdl *cmdl) 346 { 347 fprintf(stderr, "Usage: %s bearer disable media MEDIA ARGS...\n", 348 cmdl->argv[0]); 349 _print_bearer_media(); 350 } 351 352 static int cmd_bearer_disable(struct nlmsghdr *nlh, const struct cmd *cmd, 353 struct cmdl *cmdl, void *data) 354 { 355 int err; 356 char *media; 357 char buf[MNL_SOCKET_BUFFER_SIZE]; 358 struct nlattr *nest; 359 struct opt *opt; 360 struct opt opts[] = { 361 { "device", NULL }, 362 { "name", NULL }, 363 { "media", NULL }, 364 { NULL } 365 }; 366 367 if (parse_opts(opts, cmdl) < 0) { 368 if (help_flag) 369 (cmd->help)(cmdl); 370 return -EINVAL; 371 } 372 373 if (!(opt = get_opt(opts, "media"))) { 374 if (help_flag) 375 (cmd->help)(cmdl); 376 else 377 fprintf(stderr, "error, missing bearer media\n"); 378 return -EINVAL; 379 } 380 media = opt->val; 381 382 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_DISABLE))) { 383 fprintf(stderr, "error, message initialisation failed\n"); 384 return -1; 385 } 386 387 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER); 388 389 if (strcmp(media, "udp") == 0) { 390 if (help_flag) { 391 cmd_bearer_disable_udp_help(cmdl); 392 return -EINVAL; 393 } 394 if ((err = add_udp_bearer(nlh, opts))) 395 return err; 396 } else if ((strcmp(media, "eth") == 0) || (strcmp(media, "udp") == 0)) { 397 if (help_flag) { 398 cmd_bearer_disable_l2_help(cmdl); 399 return -EINVAL; 400 } 401 if ((err = add_l2_bearer(nlh, opts))) 402 return err; 403 } else { 404 fprintf(stderr, "error, invalid media type \"%s\"\n", media); 405 return -EINVAL; 406 } 407 mnl_attr_nest_end(nlh, nest); 408 409 return msg_doit(nlh, NULL, NULL); 410 411 } 412 413 static void cmd_bearer_set_help(struct cmdl *cmdl) 414 { 415 fprintf(stderr, "Usage: %s bearer set OPTION media MEDIA ARGS...\n", 416 cmdl->argv[0]); 417 _print_bearer_opts(); 418 _print_bearer_media(); 419 } 420 421 static void cmd_bearer_set_udp_help(struct cmdl *cmdl) 422 { 423 fprintf(stderr, "Usage: %s bearer set OPTION media udp name NAME\n\n", 424 cmdl->argv[0]); 425 _print_bearer_opts(); 426 } 427 428 static void cmd_bearer_set_l2_help(struct cmdl *cmdl, char *media) 429 { 430 fprintf(stderr, 431 "Usage: %s bearer set [OPTION]... media %s device DEVICE\n", 432 cmdl->argv[0], media); 433 _print_bearer_opts(); 434 } 435 436 static int cmd_bearer_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd, 437 struct cmdl *cmdl, void *data) 438 { 439 int err; 440 int val; 441 int prop; 442 char *media; 443 char buf[MNL_SOCKET_BUFFER_SIZE]; 444 struct nlattr *props; 445 struct nlattr *attrs; 446 struct opt *opt; 447 struct opt opts[] = { 448 { "device", NULL }, 449 { "media", NULL }, 450 { "name", NULL }, 451 { NULL } 452 }; 453 454 if (strcmp(cmd->cmd, "priority") == 0) 455 prop = TIPC_NLA_PROP_PRIO; 456 else if ((strcmp(cmd->cmd, "tolerance") == 0)) 457 prop = TIPC_NLA_PROP_TOL; 458 else if ((strcmp(cmd->cmd, "window") == 0)) 459 prop = TIPC_NLA_PROP_WIN; 460 else 461 return -EINVAL; 462 463 if (help_flag) { 464 (cmd->help)(cmdl); 465 return -EINVAL; 466 } 467 468 if (cmdl->optind >= cmdl->argc) { 469 fprintf(stderr, "error, missing value\n"); 470 return -EINVAL; 471 } 472 val = atoi(shift_cmdl(cmdl)); 473 474 if (parse_opts(opts, cmdl) < 0) 475 return -EINVAL; 476 477 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_SET))) { 478 fprintf(stderr, "error, message initialisation failed\n"); 479 return -1; 480 } 481 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER); 482 483 props = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_PROP); 484 mnl_attr_put_u32(nlh, prop, val); 485 mnl_attr_nest_end(nlh, props); 486 487 if (!(opt = get_opt(opts, "media"))) { 488 fprintf(stderr, "error, missing media\n"); 489 return -EINVAL; 490 } 491 media = opt->val; 492 493 if (strcmp(media, "udp") == 0) { 494 if (help_flag) { 495 cmd_bearer_set_udp_help(cmdl); 496 return -EINVAL; 497 } 498 if ((err = add_udp_bearer(nlh, opts))) 499 return err; 500 } else if ((strcmp(media, "eth") == 0) || (strcmp(media, "udp") == 0)) { 501 if (help_flag) { 502 cmd_bearer_set_l2_help(cmdl, media); 503 return -EINVAL; 504 } 505 if ((err = add_l2_bearer(nlh, opts))) 506 return err; 507 } else { 508 fprintf(stderr, "error, invalid media type \"%s\"\n", media); 509 return -EINVAL; 510 } 511 mnl_attr_nest_end(nlh, attrs); 512 513 return msg_doit(nlh, NULL, NULL); 514 } 515 516 static int cmd_bearer_set(struct nlmsghdr *nlh, const struct cmd *cmd, 517 struct cmdl *cmdl, void *data) 518 { 519 const struct cmd cmds[] = { 520 { "priority", cmd_bearer_set_prop, cmd_bearer_set_help }, 521 { "tolerance", cmd_bearer_set_prop, cmd_bearer_set_help }, 522 { "window", cmd_bearer_set_prop, cmd_bearer_set_help }, 523 { NULL } 524 }; 525 526 return run_cmd(nlh, cmd, cmds, cmdl, NULL); 527 } 528 529 static void cmd_bearer_get_help(struct cmdl *cmdl) 530 { 531 fprintf(stderr, "Usage: %s bearer get OPTION media MEDIA ARGS...\n", 532 cmdl->argv[0]); 533 _print_bearer_opts(); 534 _print_bearer_media(); 535 } 536 537 static void cmd_bearer_get_udp_help(struct cmdl *cmdl) 538 { 539 fprintf(stderr, "Usage: %s bearer get OPTION media udp name NAME\n\n", 540 cmdl->argv[0]); 541 _print_bearer_opts(); 542 } 543 544 static void cmd_bearer_get_l2_help(struct cmdl *cmdl, char *media) 545 { 546 fprintf(stderr, 547 "Usage: %s bearer get [OPTION]... media %s device DEVICE\n", 548 cmdl->argv[0], media); 549 _print_bearer_opts(); 550 } 551 552 static int bearer_get_cb(const struct nlmsghdr *nlh, void *data) 553 { 554 int *prop = data; 555 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); 556 struct nlattr *info[TIPC_NLA_MAX + 1] = {}; 557 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {}; 558 struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {}; 559 560 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); 561 if (!info[TIPC_NLA_BEARER]) 562 return MNL_CB_ERROR; 563 564 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs); 565 if (!attrs[TIPC_NLA_BEARER_PROP]) 566 return MNL_CB_ERROR; 567 568 mnl_attr_parse_nested(attrs[TIPC_NLA_BEARER_PROP], parse_attrs, props); 569 if (!props[*prop]) 570 return MNL_CB_ERROR; 571 572 printf("%u\n", mnl_attr_get_u32(props[*prop])); 573 574 return MNL_CB_OK; 575 } 576 577 static int cmd_bearer_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd, 578 struct cmdl *cmdl, void *data) 579 { 580 int err; 581 int prop; 582 char *media; 583 char buf[MNL_SOCKET_BUFFER_SIZE]; 584 struct nlattr *attrs; 585 struct opt *opt; 586 struct opt opts[] = { 587 { "device", NULL }, 588 { "media", NULL }, 589 { "name", NULL }, 590 { NULL } 591 }; 592 593 if (strcmp(cmd->cmd, "priority") == 0) 594 prop = TIPC_NLA_PROP_PRIO; 595 else if ((strcmp(cmd->cmd, "tolerance") == 0)) 596 prop = TIPC_NLA_PROP_TOL; 597 else if ((strcmp(cmd->cmd, "window") == 0)) 598 prop = TIPC_NLA_PROP_WIN; 599 else 600 return -EINVAL; 601 602 if (help_flag) { 603 (cmd->help)(cmdl); 604 return -EINVAL; 605 } 606 607 if (parse_opts(opts, cmdl) < 0) 608 return -EINVAL; 609 610 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) { 611 fprintf(stderr, "error, message initialisation failed\n"); 612 return -1; 613 } 614 615 if (!(opt = get_opt(opts, "media"))) { 616 fprintf(stderr, "error, missing media\n"); 617 return -EINVAL; 618 } 619 media = opt->val; 620 621 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER); 622 if (strcmp(media, "udp") == 0) { 623 if (help_flag) { 624 cmd_bearer_get_udp_help(cmdl); 625 return -EINVAL; 626 } 627 if ((err = add_udp_bearer(nlh, opts))) 628 return err; 629 } else if ((strcmp(media, "eth") == 0) || (strcmp(media, "udp") == 0)) { 630 if (help_flag) { 631 cmd_bearer_get_l2_help(cmdl, media); 632 return -EINVAL; 633 } 634 if ((err = add_l2_bearer(nlh, opts))) 635 return err; 636 } else { 637 fprintf(stderr, "error, invalid media type \"%s\"\n", media); 638 return -EINVAL; 639 } 640 mnl_attr_nest_end(nlh, attrs); 641 642 return msg_doit(nlh, bearer_get_cb, &prop); 643 } 644 645 static int cmd_bearer_get(struct nlmsghdr *nlh, const struct cmd *cmd, 646 struct cmdl *cmdl, void *data) 647 { 648 const struct cmd cmds[] = { 649 { "priority", cmd_bearer_get_prop, cmd_bearer_get_help }, 650 { "tolerance", cmd_bearer_get_prop, cmd_bearer_get_help }, 651 { "window", cmd_bearer_get_prop, cmd_bearer_get_help }, 652 { NULL } 653 }; 654 655 return run_cmd(nlh, cmd, cmds, cmdl, NULL); 656 } 657 658 static int bearer_list_cb(const struct nlmsghdr *nlh, void *data) 659 { 660 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); 661 struct nlattr *info[TIPC_NLA_MAX + 1] = {}; 662 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {}; 663 664 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); 665 if (!info[TIPC_NLA_BEARER]) { 666 fprintf(stderr, "No bearer in netlink response\n"); 667 return MNL_CB_ERROR; 668 } 669 670 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs); 671 if (!attrs[TIPC_NLA_BEARER_NAME]) { 672 fprintf(stderr, "Bearer name missing in netlink response\n"); 673 return MNL_CB_ERROR; 674 } 675 676 printf("%s\n", mnl_attr_get_str(attrs[TIPC_NLA_BEARER_NAME])); 677 678 return MNL_CB_OK; 679 } 680 681 static int cmd_bearer_list(struct nlmsghdr *nlh, const struct cmd *cmd, 682 struct cmdl *cmdl, void *data) 683 { 684 char buf[MNL_SOCKET_BUFFER_SIZE]; 685 686 if (help_flag) { 687 fprintf(stderr, "Usage: %s bearer list\n", cmdl->argv[0]); 688 return -EINVAL; 689 } 690 691 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) { 692 fprintf(stderr, "error, message initialisation failed\n"); 693 return -1; 694 } 695 696 return msg_dumpit(nlh, bearer_list_cb, NULL); 697 } 698 699 void cmd_bearer_help(struct cmdl *cmdl) 700 { 701 fprintf(stderr, 702 "Usage: %s bearer COMMAND [ARGS] ...\n" 703 "\n" 704 "COMMANDS\n" 705 " enable - Enable a bearer\n" 706 " disable - Disable a bearer\n" 707 " set - Set various bearer properties\n" 708 " get - Get various bearer properties\n" 709 " list - List bearers\n", cmdl->argv[0]); 710 } 711 712 int cmd_bearer(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl, 713 void *data) 714 { 715 const struct cmd cmds[] = { 716 { "disable", cmd_bearer_disable, cmd_bearer_disable_help }, 717 { "enable", cmd_bearer_enable, cmd_bearer_enable_help }, 718 { "get", cmd_bearer_get, cmd_bearer_get_help }, 719 { "list", cmd_bearer_list, NULL }, 720 { "set", cmd_bearer_set, cmd_bearer_set_help }, 721 { NULL } 722 }; 723 724 return run_cmd(nlh, cmd, cmds, cmdl, NULL); 725 } 726