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@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
_print_bearer_opts(void)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
_print_bearer_media(void)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
cmd_bearer_enable_l2_help(struct cmdl * cmdl)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
cmd_bearer_enable_udp_help(struct cmdl * cmdl)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
enable_l2_bearer(struct nlmsghdr * nlh,struct opt * opts,struct cmdl * cmdl)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
get_netid_cb(const struct nlmsghdr * nlh,void * data)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
generate_multicast(short af,char * buf,int bufsize)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
enable_udp_bearer(struct nlmsghdr * nlh,struct opt * opts,struct cmdl * cmdl)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
cmd_bearer_enable_help(struct cmdl * cmdl)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
cmd_bearer_enable(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
add_l2_bearer(struct nlmsghdr * nlh,struct opt * opts)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
add_udp_bearer(struct nlmsghdr * nlh,struct opt * opts)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
cmd_bearer_disable_l2_help(struct cmdl * cmdl)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
cmd_bearer_disable_udp_help(struct cmdl * cmdl)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
cmd_bearer_disable_help(struct cmdl * cmdl)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
cmd_bearer_disable(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
cmd_bearer_set_help(struct cmdl * cmdl)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
cmd_bearer_set_udp_help(struct cmdl * cmdl)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
cmd_bearer_set_l2_help(struct cmdl * cmdl,char * media)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
cmd_bearer_set_prop(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
cmd_bearer_set(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
cmd_bearer_get_help(struct cmdl * cmdl)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
cmd_bearer_get_udp_help(struct cmdl * cmdl)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
cmd_bearer_get_l2_help(struct cmdl * cmdl,char * media)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
bearer_get_cb(const struct nlmsghdr * nlh,void * data)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
cmd_bearer_get_prop(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
cmd_bearer_get(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
bearer_list_cb(const struct nlmsghdr * nlh,void * data)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
cmd_bearer_list(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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
cmd_bearer_help(struct cmdl * cmdl)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
cmd_bearer(struct nlmsghdr * nlh,const struct cmd * cmd,struct cmdl * cmdl,void * data)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