]> git.proxmox.com Git - mirror_iproute2.git/blame - tipc/bearer.c
treewide: refactor help messages
[mirror_iproute2.git] / tipc / bearer.c
CommitLineData
f043759d
RA
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>
ed81deab 17#include <arpa/inet.h>
f043759d
RA
18
19#include <linux/tipc_netlink.h>
20#include <linux/tipc.h>
21#include <linux/genetlink.h>
22
23#include <libmnl/libmnl.h>
24#include <sys/socket.h>
25
26#include "cmdl.h"
27#include "msg.h"
28#include "bearer.h"
29
ed81deab
RA
30#define UDP_PROP_IP 1
31#define UDP_PROP_PORT 2
32
33struct cb_data {
34 int attr;
35 int prop;
36 struct nlmsghdr *nlh;
37};
38
f043759d
RA
39static void _print_bearer_opts(void)
40{
41 fprintf(stderr,
50afc4db 42 "OPTIONS\n"
8589eb4e
MC
43 " priority - Bearer link priority\n"
44 " tolerance - Bearer link tolerance\n"
45 " window - Bearer link window\n"
46 " mtu - Bearer link mtu\n");
f043759d
RA
47}
48
d2ba0b0b 49void print_bearer_media(void)
f043759d
RA
50{
51 fprintf(stderr,
52 "\nMEDIA\n"
8589eb4e
MC
53 " udp - User Datagram Protocol\n"
54 " ib - Infiniband\n"
55 " eth - Ethernet\n");
f043759d
RA
56}
57
50afc4db 58static void cmd_bearer_enable_l2_help(struct cmdl *cmdl, char *media)
f043759d
RA
59{
60 fprintf(stderr,
50afc4db 61 "Usage: %s bearer enable media %s device DEVICE [OPTIONS]\n"
f043759d 62 "\nOPTIONS\n"
8589eb4e
MC
63 " domain DOMAIN - Discovery domain\n"
64 " priority PRIORITY - Bearer priority\n",
50afc4db 65 cmdl->argv[0], media);
f043759d
RA
66}
67
50afc4db 68static void cmd_bearer_enable_udp_help(struct cmdl *cmdl, char *media)
f043759d
RA
69{
70 fprintf(stderr,
8589eb4e 71 "Usage: %s bearer enable [OPTIONS] media %s name NAME localip IP [UDP OPTIONS]\n\n"
ed81deab 72 "OPTIONS\n"
8589eb4e
MC
73 " domain DOMAIN - Discovery domain\n"
74 " priority PRIORITY - Bearer priority\n\n"
ed81deab 75 "UDP OPTIONS\n"
8589eb4e
MC
76 " localport PORT - Local UDP port (default 6118)\n"
77 " remoteip IP - Remote IP address\n"
78 " remoteport PORT - Remote UDP port (default 6118)\n",
79 cmdl->argv[0], media);
f043759d
RA
80}
81
82static int get_netid_cb(const struct nlmsghdr *nlh, void *data)
83{
84 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
85 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
86 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
87 int *netid = (int*)data;
88
89 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
90 if (!info[TIPC_NLA_NET])
91 return MNL_CB_ERROR;
92 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
93 if (!attrs[TIPC_NLA_NET_ID])
94 return MNL_CB_ERROR;
95 *netid = mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]);
96
97 return MNL_CB_OK;
98}
99
100static int generate_multicast(short af, char *buf, int bufsize)
101{
102 int netid;
103 char mnl_msg[MNL_SOCKET_BUFFER_SIZE];
104 struct nlmsghdr *nlh;
105
106 if (!(nlh = msg_init(mnl_msg, TIPC_NL_NET_GET))) {
107 fprintf(stderr, "error, message initialization failed\n");
108 return -1;
109 }
110 if (msg_dumpit(nlh, get_netid_cb, &netid)) {
111 fprintf(stderr, "error, failed to fetch TIPC network id from kernel\n");
112 return -EINVAL;
113 }
114 if (af == AF_INET)
115 snprintf(buf, bufsize, "228.0.%u.%u", (netid>>8) & 0xFF, netid & 0xFF);
116 else
117 snprintf(buf, bufsize, "ff02::%u", netid);
118
119 return 0;
120}
121
50afc4db
RA
122static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
123 struct cmdl *cmdl)
f043759d
RA
124{
125 int err;
126 struct opt *opt;
127 struct nlattr *nest;
128 char buf[INET6_ADDRSTRLEN];
129 char *locport = "6118";
130 char *remport = "6118";
131 char *locip = NULL;
132 char *remip = NULL;
f043759d
RA
133 struct addrinfo *loc = NULL;
134 struct addrinfo *rem = NULL;
135 struct addrinfo hints = {
136 .ai_family = AF_UNSPEC,
137 .ai_socktype = SOCK_DGRAM
138 };
139
f043759d
RA
140 if (!(opt = get_opt(opts, "localip"))) {
141 fprintf(stderr, "error, udp bearer localip missing\n");
50afc4db 142 cmd_bearer_enable_udp_help(cmdl, "udp");
f043759d
RA
143 return -EINVAL;
144 }
145 locip = opt->val;
146
147 if ((opt = get_opt(opts, "remoteip")))
148 remip = opt->val;
149
150 if ((opt = get_opt(opts, "localport")))
151 locport = opt->val;
152
153 if ((opt = get_opt(opts, "remoteport")))
154 remport = opt->val;
155
156 if ((err = getaddrinfo(locip, locport, &hints, &loc))) {
157 fprintf(stderr, "UDP local address error: %s\n",
158 gai_strerror(err));
159 return err;
160 }
161
162 if (!remip) {
163 if (generate_multicast(loc->ai_family, buf, sizeof(buf))) {
164 fprintf(stderr, "Failed to generate multicast address\n");
be55416a 165 freeaddrinfo(loc);
f043759d
RA
166 return -EINVAL;
167 }
168 remip = buf;
169 }
170
171 if ((err = getaddrinfo(remip, remport, &hints, &rem))) {
172 fprintf(stderr, "UDP remote address error: %s\n",
173 gai_strerror(err));
174 freeaddrinfo(loc);
175 return err;
176 }
177
178 if (rem->ai_family != loc->ai_family) {
179 fprintf(stderr, "UDP local and remote AF mismatch\n");
be55416a
PS
180 freeaddrinfo(rem);
181 freeaddrinfo(loc);
f043759d
RA
182 return -EINVAL;
183 }
184
f043759d
RA
185 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_UDP_OPTS);
186 mnl_attr_put(nlh, TIPC_NLA_UDP_LOCAL, loc->ai_addrlen, loc->ai_addr);
187 mnl_attr_put(nlh, TIPC_NLA_UDP_REMOTE, rem->ai_addrlen, rem->ai_addr);
188 mnl_attr_nest_end(nlh, nest);
189
190 freeaddrinfo(rem);
191 freeaddrinfo(loc);
192
193 return 0;
194}
195
7d40bdbc
GM
196static char *cmd_get_media_type(const struct cmd *cmd, struct cmdl *cmdl,
197 struct opt *opts)
198{
199 struct opt *opt = get_opt(opts, "media");
200
201 if (!opt) {
202 if (help_flag)
203 (cmd->help)(cmdl);
204 else
205 fprintf(stderr, "error, missing bearer media\n");
206 return NULL;
207 }
208 return opt->val;
209}
210
50afc4db 211static int nl_add_bearer_name(struct nlmsghdr *nlh, const struct cmd *cmd,
d2ba0b0b
PB
212 struct cmdl *cmdl, struct opt *opts,
213 const struct tipc_sup_media *sup_media)
214{
215 char bname[TIPC_MAX_BEARER_NAME];
216 int err;
217
218 if ((err = cmd_get_unique_bearer_name(cmd, cmdl, opts, bname, sup_media)))
219 return err;
220
221 mnl_attr_put_strz(nlh, TIPC_NLA_BEARER_NAME, bname);
222 return 0;
223}
224
225int cmd_get_unique_bearer_name(const struct cmd *cmd, struct cmdl *cmdl,
226 struct opt *opts, char *bname,
227 const struct tipc_sup_media *sup_media)
50afc4db 228{
50afc4db
RA
229 char *media;
230 char *identifier;
231 struct opt *opt;
d2ba0b0b
PB
232 const struct tipc_sup_media *entry;
233
7d40bdbc 234 if (!(media = cmd_get_media_type(cmd, cmdl, opts)))
50afc4db 235 return -EINVAL;
50afc4db
RA
236
237 for (entry = sup_media; entry->media; entry++) {
238 if (strcmp(entry->media, media))
239 continue;
240
241 if (!(opt = get_opt(opts, entry->identifier))) {
242 if (help_flag)
243 (entry->help)(cmdl, media);
244 else
245 fprintf(stderr, "error, missing bearer %s\n",
d2ba0b0b 246 entry->identifier);
50afc4db
RA
247 return -EINVAL;
248 }
249
250 identifier = opt->val;
d2ba0b0b 251 snprintf(bname, TIPC_MAX_BEARER_NAME, "%s:%s", media, identifier);
50afc4db
RA
252
253 return 0;
254 }
255
256 fprintf(stderr, "error, invalid media type %s\n", media);
257
258 return -EINVAL;
259}
260
f1f40cf7
RA
261static void cmd_bearer_add_udp_help(struct cmdl *cmdl, char *media)
262{
263 fprintf(stderr, "Usage: %s bearer add media %s name NAME remoteip REMOTEIP\n\n",
264 cmdl->argv[0], media);
265}
266
267static void cmd_bearer_add_help(struct cmdl *cmdl)
268{
269 fprintf(stderr, "Usage: %s bearer add media udp name NAME remoteip REMOTEIP\n",
270 cmdl->argv[0]);
271}
272
273static int udp_bearer_add(struct nlmsghdr *nlh, struct opt *opts,
274 struct cmdl *cmdl)
275{
276 int err;
277 struct opt *opt;
278 struct nlattr *opts_nest;
279 char *remport = "6118";
280
281 opts_nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_UDP_OPTS);
282
283 if ((opt = get_opt(opts, "remoteport")))
284 remport = opt->val;
285
286 if ((opt = get_opt(opts, "remoteip"))) {
287 char *ip = opt->val;
288 struct addrinfo *addr = NULL;
289 struct addrinfo hints = {
290 .ai_family = AF_UNSPEC,
291 .ai_socktype = SOCK_DGRAM
292 };
293
294 if ((err = getaddrinfo(ip, remport, &hints, &addr))) {
295 fprintf(stderr, "UDP address error: %s\n",
d2ba0b0b 296 gai_strerror(err));
f1f40cf7
RA
297 freeaddrinfo(addr);
298 return err;
299 }
300
301 mnl_attr_put(nlh, TIPC_NLA_UDP_REMOTE, addr->ai_addrlen,
d2ba0b0b 302 addr->ai_addr);
f1f40cf7
RA
303 freeaddrinfo(addr);
304 } else {
305 fprintf(stderr, "error, missing remoteip\n");
306 return -EINVAL;
307 }
308 mnl_attr_nest_end(nlh, opts_nest);
309
310 return 0;
311}
312
313static int cmd_bearer_add_media(struct nlmsghdr *nlh, const struct cmd *cmd,
314 struct cmdl *cmdl, void *data)
315{
316 int err;
317 char *media;
318 char buf[MNL_SOCKET_BUFFER_SIZE];
319 struct opt *opt;
320 struct nlattr *attrs;
321 struct opt opts[] = {
ed81deab
RA
322 { "remoteip", OPT_KEYVAL, NULL },
323 { "remoteport", OPT_KEYVAL, NULL },
324 { "name", OPT_KEYVAL, NULL },
325 { "media", OPT_KEYVAL, NULL },
f1f40cf7
RA
326 { NULL }
327 };
d2ba0b0b 328 const struct tipc_sup_media sup_media[] = {
f1f40cf7
RA
329 { "udp", "name", cmd_bearer_add_udp_help},
330 { NULL, },
331 };
332
333 /* Rewind optind to include media in the option list */
334 cmdl->optind--;
335 if (parse_opts(opts, cmdl) < 0)
336 return -EINVAL;
337
338 if (!(opt = get_opt(opts, "media"))) {
339 fprintf(stderr, "error, missing media value\n");
340 return -EINVAL;
341 }
342 media = opt->val;
343
344 if (strcmp(media, "udp") != 0) {
345 fprintf(stderr, "error, no \"%s\" media specific options available\n",
346 media);
347 return -EINVAL;
348 }
349 if (!(opt = get_opt(opts, "name"))) {
350 fprintf(stderr, "error, missing media name\n");
351 return -EINVAL;
352 }
353
354 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_ADD))) {
355 fprintf(stderr, "error, message initialisation failed\n");
356 return -1;
357 }
358
359 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
360 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
361 if (err)
362 return err;
363
364 err = udp_bearer_add(nlh, opts, cmdl);
365 if (err)
366 return err;
367
368 mnl_attr_nest_end(nlh, attrs);
369
370 return msg_doit(nlh, NULL, NULL);
371}
372
373static int cmd_bearer_add(struct nlmsghdr *nlh, const struct cmd *cmd,
374 struct cmdl *cmdl, void *data)
375{
376 const struct cmd cmds[] = {
377 { "media", cmd_bearer_add_media, cmd_bearer_add_help },
378 { NULL }
379 };
380
381 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
382}
383
f043759d
RA
384static void cmd_bearer_enable_help(struct cmdl *cmdl)
385{
386 fprintf(stderr,
387 "Usage: %s bearer enable [OPTIONS] media MEDIA ARGS...\n\n"
388 "OPTIONS\n"
389 " domain DOMAIN - Discovery domain\n"
390 " priority PRIORITY - Bearer priority\n",
391 cmdl->argv[0]);
d2ba0b0b 392 print_bearer_media();
f043759d
RA
393}
394
395static int cmd_bearer_enable(struct nlmsghdr *nlh, const struct cmd *cmd,
396 struct cmdl *cmdl, void *data)
397{
398 int err;
399 struct opt *opt;
400 struct nlattr *nest;
401 char buf[MNL_SOCKET_BUFFER_SIZE];
f043759d 402 struct opt opts[] = {
ed81deab
RA
403 { "device", OPT_KEYVAL, NULL },
404 { "domain", OPT_KEYVAL, NULL },
405 { "localip", OPT_KEYVAL, NULL },
406 { "localport", OPT_KEYVAL, NULL },
407 { "media", OPT_KEYVAL, NULL },
408 { "name", OPT_KEYVAL, NULL },
409 { "priority", OPT_KEYVAL, NULL },
410 { "remoteip", OPT_KEYVAL, NULL },
411 { "remoteport", OPT_KEYVAL, NULL },
f043759d
RA
412 { NULL }
413 };
50afc4db 414 struct tipc_sup_media sup_media[] = {
d2ba0b0b
PB
415 { "udp", "name", cmd_bearer_enable_udp_help},
416 { "eth", "device", cmd_bearer_enable_l2_help },
417 { "ib", "device", cmd_bearer_enable_l2_help },
50afc4db
RA
418 { NULL, },
419 };
f043759d
RA
420
421 if (parse_opts(opts, cmdl) < 0) {
422 if (help_flag)
423 (cmd->help)(cmdl);
424 return -EINVAL;
425 }
426
f043759d
RA
427 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_ENABLE))) {
428 fprintf(stderr, "error: message initialisation failed\n");
429 return -1;
430 }
431 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
432
433 if ((opt = get_opt(opts, "domain")))
434 mnl_attr_put_u32(nlh, TIPC_NLA_BEARER_DOMAIN, atoi(opt->val));
435
436 if ((opt = get_opt(opts, "priority"))) {
437 struct nlattr *props;
438
439 props = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_PROP);
440 mnl_attr_put_u32(nlh, TIPC_NLA_PROP_PRIO, atoi(opt->val));
441 mnl_attr_nest_end(nlh, props);
442 }
443
50afc4db
RA
444 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
445 if (err)
446 return err;
447
448 opt = get_opt(opts, "media");
70a6df39 449 if (opt && strcmp(opt->val, "udp") == 0) {
50afc4db
RA
450 err = nl_add_udp_enable_opts(nlh, opts, cmdl);
451 if (err)
f043759d 452 return err;
f043759d 453 }
f043759d
RA
454 mnl_attr_nest_end(nlh, nest);
455
456 return msg_doit(nlh, NULL, NULL);
457}
458
50afc4db 459static void cmd_bearer_disable_l2_help(struct cmdl *cmdl, char *media)
f043759d 460{
50afc4db
RA
461 fprintf(stderr, "Usage: %s bearer disable media %s device DEVICE\n",
462 cmdl->argv[0], media);
f043759d
RA
463}
464
50afc4db 465static void cmd_bearer_disable_udp_help(struct cmdl *cmdl, char *media)
f043759d 466{
50afc4db
RA
467 fprintf(stderr, "Usage: %s bearer disable media %s name NAME\n",
468 cmdl->argv[0], media);
f043759d
RA
469}
470
471static void cmd_bearer_disable_help(struct cmdl *cmdl)
472{
473 fprintf(stderr, "Usage: %s bearer disable media MEDIA ARGS...\n",
474 cmdl->argv[0]);
d2ba0b0b 475 print_bearer_media();
f043759d
RA
476}
477
478static int cmd_bearer_disable(struct nlmsghdr *nlh, const struct cmd *cmd,
479 struct cmdl *cmdl, void *data)
480{
481 int err;
f043759d
RA
482 char buf[MNL_SOCKET_BUFFER_SIZE];
483 struct nlattr *nest;
f043759d 484 struct opt opts[] = {
ed81deab
RA
485 { "device", OPT_KEYVAL, NULL },
486 { "name", OPT_KEYVAL, NULL },
487 { "media", OPT_KEYVAL, NULL },
f043759d
RA
488 { NULL }
489 };
50afc4db 490 struct tipc_sup_media sup_media[] = {
d2ba0b0b
PB
491 { "udp", "name", cmd_bearer_disable_udp_help},
492 { "eth", "device", cmd_bearer_disable_l2_help },
493 { "ib", "device", cmd_bearer_disable_l2_help },
50afc4db
RA
494 { NULL, },
495 };
f043759d
RA
496
497 if (parse_opts(opts, cmdl) < 0) {
498 if (help_flag)
499 (cmd->help)(cmdl);
500 return -EINVAL;
501 }
502
f043759d
RA
503 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_DISABLE))) {
504 fprintf(stderr, "error, message initialisation failed\n");
505 return -1;
506 }
507
508 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
50afc4db
RA
509 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
510 if (err)
511 return err;
f043759d
RA
512 mnl_attr_nest_end(nlh, nest);
513
514 return msg_doit(nlh, NULL, NULL);
515
516}
517
518static void cmd_bearer_set_help(struct cmdl *cmdl)
519{
ee262ed2 520 fprintf(stderr, "Usage: %s bearer set OPTION media MEDIA ARGS...\n",
f043759d
RA
521 cmdl->argv[0]);
522 _print_bearer_opts();
d2ba0b0b 523 print_bearer_media();
f043759d
RA
524}
525
50afc4db 526static void cmd_bearer_set_udp_help(struct cmdl *cmdl, char *media)
f043759d 527{
50afc4db
RA
528 fprintf(stderr, "Usage: %s bearer set OPTION media %s name NAME\n\n",
529 cmdl->argv[0], media);
f043759d
RA
530 _print_bearer_opts();
531}
532
533static void cmd_bearer_set_l2_help(struct cmdl *cmdl, char *media)
534{
535 fprintf(stderr,
536 "Usage: %s bearer set [OPTION]... media %s device DEVICE\n",
537 cmdl->argv[0], media);
538 _print_bearer_opts();
539}
540
541static int cmd_bearer_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
d2ba0b0b 542 struct cmdl *cmdl, void *data)
f043759d
RA
543{
544 int err;
545 int val;
546 int prop;
f043759d
RA
547 char buf[MNL_SOCKET_BUFFER_SIZE];
548 struct nlattr *props;
549 struct nlattr *attrs;
f043759d 550 struct opt opts[] = {
ed81deab
RA
551 { "device", OPT_KEYVAL, NULL },
552 { "media", OPT_KEYVAL, NULL },
553 { "name", OPT_KEYVAL, NULL },
f043759d
RA
554 { NULL }
555 };
50afc4db 556 struct tipc_sup_media sup_media[] = {
d2ba0b0b
PB
557 { "udp", "name", cmd_bearer_set_udp_help},
558 { "eth", "device", cmd_bearer_set_l2_help },
559 { "ib", "device", cmd_bearer_set_l2_help },
50afc4db
RA
560 { NULL, },
561 };
f043759d
RA
562
563 if (strcmp(cmd->cmd, "priority") == 0)
564 prop = TIPC_NLA_PROP_PRIO;
565 else if ((strcmp(cmd->cmd, "tolerance") == 0))
566 prop = TIPC_NLA_PROP_TOL;
567 else if ((strcmp(cmd->cmd, "window") == 0))
568 prop = TIPC_NLA_PROP_WIN;
7d40bdbc
GM
569 else if ((strcmp(cmd->cmd, "mtu") == 0))
570 prop = TIPC_NLA_PROP_MTU;
f043759d
RA
571 else
572 return -EINVAL;
573
f043759d
RA
574 if (cmdl->optind >= cmdl->argc) {
575 fprintf(stderr, "error, missing value\n");
576 return -EINVAL;
577 }
578 val = atoi(shift_cmdl(cmdl));
579
580 if (parse_opts(opts, cmdl) < 0)
581 return -EINVAL;
582
7d40bdbc
GM
583 if (prop == TIPC_NLA_PROP_MTU) {
584 char *media = cmd_get_media_type(cmd, cmdl, opts);
585
586 if (!media)
587 return -EINVAL;
588 else if (strcmp(media, "udp")) {
589 fprintf(stderr, "error, not supported for media\n");
590 return -EINVAL;
591 }
592 }
593
f043759d
RA
594 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_SET))) {
595 fprintf(stderr, "error, message initialisation failed\n");
596 return -1;
597 }
598 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
599
600 props = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_PROP);
601 mnl_attr_put_u32(nlh, prop, val);
602 mnl_attr_nest_end(nlh, props);
603
50afc4db
RA
604 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
605 if (err)
606 return err;
f043759d 607
f043759d
RA
608 mnl_attr_nest_end(nlh, attrs);
609
610 return msg_doit(nlh, NULL, NULL);
611}
612
613static int cmd_bearer_set(struct nlmsghdr *nlh, const struct cmd *cmd,
614 struct cmdl *cmdl, void *data)
615{
616 const struct cmd cmds[] = {
617 { "priority", cmd_bearer_set_prop, cmd_bearer_set_help },
618 { "tolerance", cmd_bearer_set_prop, cmd_bearer_set_help },
619 { "window", cmd_bearer_set_prop, cmd_bearer_set_help },
7d40bdbc 620 { "mtu", cmd_bearer_set_prop, cmd_bearer_set_help },
f043759d
RA
621 { NULL }
622 };
623
624 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
625}
626
627static void cmd_bearer_get_help(struct cmdl *cmdl)
628{
ed81deab 629 fprintf(stderr, "Usage: %s bearer get [OPTION] media MEDIA ARGS...\n",
f043759d
RA
630 cmdl->argv[0]);
631 _print_bearer_opts();
d2ba0b0b 632 print_bearer_media();
f043759d
RA
633}
634
50afc4db 635static void cmd_bearer_get_udp_help(struct cmdl *cmdl, char *media)
f043759d 636{
ed81deab 637 fprintf(stderr, "Usage: %s bearer get [OPTION] media %s name NAME [UDP OPTIONS]\n\n",
50afc4db 638 cmdl->argv[0], media);
ed81deab
RA
639 fprintf(stderr,
640 "UDP OPTIONS\n"
641 " remoteip - Remote ip address\n"
642 " remoteport - Remote port\n"
643 " localip - Local ip address\n"
644 " localport - Local port\n\n");
f043759d
RA
645 _print_bearer_opts();
646}
647
648static void cmd_bearer_get_l2_help(struct cmdl *cmdl, char *media)
649{
650 fprintf(stderr,
50afc4db 651 "Usage: %s bearer get OPTION media %s device DEVICE\n",
f043759d
RA
652 cmdl->argv[0], media);
653 _print_bearer_opts();
654}
655
ed81deab
RA
656
657static int bearer_dump_udp_cb(const struct nlmsghdr *nlh, void *data)
658{
659 struct sockaddr_storage *addr;
660 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
661 struct nlattr *info[TIPC_NLA_UDP_MAX + 1] = {};
662
663 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
664
665 if (!info[TIPC_NLA_UDP_REMOTE])
666 return MNL_CB_ERROR;
667
668 addr = mnl_attr_get_payload(info[TIPC_NLA_UDP_REMOTE]);
669
670 if (addr->ss_family == AF_INET) {
671 struct sockaddr_in *ipv4 = (struct sockaddr_in *) addr;
672
673 printf("%s\n", inet_ntoa(ipv4->sin_addr));
674 } else if (addr->ss_family == AF_INET6) {
675 char straddr[INET6_ADDRSTRLEN];
676 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) addr;
677
678 if (!inet_ntop(AF_INET6, &ipv6->sin6_addr, straddr,
d2ba0b0b 679 sizeof(straddr))) {
ed81deab
RA
680 fprintf(stderr, "error, parsing IPv6 addr\n");
681 return MNL_CB_ERROR;
682 }
683 printf("%s\n", straddr);
684
685 } else {
686 return MNL_CB_ERROR;
687 }
688
689 return MNL_CB_OK;
690}
691
692static int bearer_get_udp_cb(const struct nlmsghdr *nlh, void *data)
693{
694 struct cb_data *cb_data = (struct cb_data *) data;
695 struct sockaddr_storage *addr;
696 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
697 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
698 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {};
699 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1] = {};
700
701 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
702 if (!info[TIPC_NLA_BEARER])
703 return MNL_CB_ERROR;
704
705 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs);
706 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
707 return MNL_CB_ERROR;
708
709 mnl_attr_parse_nested(attrs[TIPC_NLA_BEARER_UDP_OPTS], parse_attrs, opts);
710 if (!opts[TIPC_NLA_UDP_LOCAL])
711 return MNL_CB_ERROR;
712
713 if ((cb_data->attr == TIPC_NLA_UDP_REMOTE) &&
714 (cb_data->prop == UDP_PROP_IP) &&
715 opts[TIPC_NLA_UDP_MULTI_REMOTEIP]) {
716 struct genlmsghdr *genl = mnl_nlmsg_get_payload(cb_data->nlh);
717
718 genl->cmd = TIPC_NL_UDP_GET_REMOTEIP;
719 return msg_dumpit(cb_data->nlh, bearer_dump_udp_cb, NULL);
720 }
721
722 addr = mnl_attr_get_payload(opts[cb_data->attr]);
723
724 if (addr->ss_family == AF_INET) {
725 struct sockaddr_in *ipv4 = (struct sockaddr_in *) addr;
726
727 switch (cb_data->prop) {
728 case UDP_PROP_IP:
729 printf("%s\n", inet_ntoa(ipv4->sin_addr));
730 break;
731 case UDP_PROP_PORT:
732 printf("%u\n", ntohs(ipv4->sin_port));
733 break;
734 default:
735 return MNL_CB_ERROR;
736 }
737
738 } else if (addr->ss_family == AF_INET6) {
739 char straddr[INET6_ADDRSTRLEN];
740 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) addr;
741
742 switch (cb_data->prop) {
743 case UDP_PROP_IP:
744 if (!inet_ntop(AF_INET6, &ipv6->sin6_addr, straddr,
d2ba0b0b 745 sizeof(straddr))) {
ed81deab
RA
746 fprintf(stderr, "error, parsing IPv6 addr\n");
747 return MNL_CB_ERROR;
748 }
749 printf("%s\n", straddr);
750 break;
751 case UDP_PROP_PORT:
752 printf("%u\n", ntohs(ipv6->sin6_port));
753 break;
754 default:
755 return MNL_CB_ERROR;
756 }
757
758 } else {
759 return MNL_CB_ERROR;
760 }
761
762 return MNL_CB_OK;
763}
764
f043759d
RA
765static int bearer_get_cb(const struct nlmsghdr *nlh, void *data)
766{
767 int *prop = data;
768 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
769 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
770 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {};
771 struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
772
773 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
774 if (!info[TIPC_NLA_BEARER])
775 return MNL_CB_ERROR;
776
777 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs);
778 if (!attrs[TIPC_NLA_BEARER_PROP])
779 return MNL_CB_ERROR;
780
781 mnl_attr_parse_nested(attrs[TIPC_NLA_BEARER_PROP], parse_attrs, props);
782 if (!props[*prop])
783 return MNL_CB_ERROR;
784
785 printf("%u\n", mnl_attr_get_u32(props[*prop]));
786
787 return MNL_CB_OK;
788}
789
ed81deab
RA
790static int cmd_bearer_get_media(struct nlmsghdr *nlh, const struct cmd *cmd,
791 struct cmdl *cmdl, void *data)
792{
793 int err;
794 char *media;
795 char buf[MNL_SOCKET_BUFFER_SIZE];
796 struct opt *opt;
797 struct cb_data cb_data = {0};
798 struct nlattr *attrs;
799 struct opt opts[] = {
800 { "localip", OPT_KEY, NULL },
801 { "localport", OPT_KEY, NULL },
802 { "remoteip", OPT_KEY, NULL },
803 { "remoteport", OPT_KEY, NULL },
804 { "name", OPT_KEYVAL, NULL },
805 { "media", OPT_KEYVAL, NULL },
806 { NULL }
807 };
808 struct tipc_sup_media sup_media[] = {
d2ba0b0b 809 { "udp", "name", cmd_bearer_get_udp_help},
ed81deab
RA
810 { NULL, },
811 };
812
813 /* Rewind optind to include media in the option list */
814 cmdl->optind--;
815 if (parse_opts(opts, cmdl) < 0)
816 return -EINVAL;
817
818 if (!(opt = get_opt(opts, "media"))) {
819 fprintf(stderr, "error, missing media value\n");
820 return -EINVAL;
821 }
822 media = opt->val;
823
824 if (help_flag) {
825 cmd_bearer_get_udp_help(cmdl, media);
826 return -EINVAL;
827 }
828 if (strcmp(media, "udp") != 0) {
829 fprintf(stderr, "error, no \"%s\" media specific options\n", media);
830 return -EINVAL;
831 }
832 if (!(opt = get_opt(opts, "name"))) {
833 fprintf(stderr, "error, missing media name\n");
834 return -EINVAL;
835 }
836
837 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) {
838 fprintf(stderr, "error, message initialisation failed\n");
839 return -1;
840 }
841
842 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
843 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
844 if (err)
845 return err;
846 mnl_attr_nest_end(nlh, attrs);
847 cb_data.nlh = nlh;
848
849 if (has_opt(opts, "localip")) {
850 cb_data.attr = TIPC_NLA_UDP_LOCAL;
851 cb_data.prop = UDP_PROP_IP;
852 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
853 } else if (has_opt(opts, "localport")) {
854 cb_data.attr = TIPC_NLA_UDP_LOCAL;
855 cb_data.prop = UDP_PROP_PORT;
856 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
857 } else if (has_opt(opts, "remoteip")) {
858 cb_data.attr = TIPC_NLA_UDP_REMOTE;
859 cb_data.prop = UDP_PROP_IP;
860 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
861 } else if (has_opt(opts, "remoteport")) {
862 cb_data.attr = TIPC_NLA_UDP_REMOTE;
863 cb_data.prop = UDP_PROP_PORT;
864 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
865 }
866 fprintf(stderr, "error, missing UDP option\n");
867 return -EINVAL;
868}
869
f043759d
RA
870static int cmd_bearer_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
871 struct cmdl *cmdl, void *data)
872{
873 int err;
874 int prop;
f043759d
RA
875 char buf[MNL_SOCKET_BUFFER_SIZE];
876 struct nlattr *attrs;
f043759d 877 struct opt opts[] = {
ed81deab
RA
878 { "device", OPT_KEYVAL, NULL },
879 { "media", OPT_KEYVAL, NULL },
880 { "name", OPT_KEYVAL, NULL },
f043759d
RA
881 { NULL }
882 };
50afc4db 883 struct tipc_sup_media sup_media[] = {
d2ba0b0b
PB
884 { "udp", "name", cmd_bearer_get_udp_help},
885 { "eth", "device", cmd_bearer_get_l2_help },
886 { "ib", "device", cmd_bearer_get_l2_help },
50afc4db
RA
887 { NULL, },
888 };
f043759d 889
ed81deab
RA
890 if (help_flag) {
891 (cmd->help)(cmdl);
892 return -EINVAL;
893 }
894
f043759d
RA
895 if (strcmp(cmd->cmd, "priority") == 0)
896 prop = TIPC_NLA_PROP_PRIO;
897 else if ((strcmp(cmd->cmd, "tolerance") == 0))
898 prop = TIPC_NLA_PROP_TOL;
899 else if ((strcmp(cmd->cmd, "window") == 0))
900 prop = TIPC_NLA_PROP_WIN;
7d40bdbc
GM
901 else if ((strcmp(cmd->cmd, "mtu") == 0))
902 prop = TIPC_NLA_PROP_MTU;
f043759d
RA
903 else
904 return -EINVAL;
905
f043759d
RA
906 if (parse_opts(opts, cmdl) < 0)
907 return -EINVAL;
908
7d40bdbc
GM
909 if (prop == TIPC_NLA_PROP_MTU) {
910 char *media = cmd_get_media_type(cmd, cmdl, opts);
911
912 if (!media)
913 return -EINVAL;
914 else if (strcmp(media, "udp")) {
915 fprintf(stderr, "error, not supported for media\n");
916 return -EINVAL;
917 }
918 }
919
f043759d
RA
920 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) {
921 fprintf(stderr, "error, message initialisation failed\n");
922 return -1;
923 }
924
f043759d 925 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
50afc4db
RA
926 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
927 if (err)
928 return err;
f043759d
RA
929 mnl_attr_nest_end(nlh, attrs);
930
931 return msg_doit(nlh, bearer_get_cb, &prop);
932}
933
934static int cmd_bearer_get(struct nlmsghdr *nlh, const struct cmd *cmd,
935 struct cmdl *cmdl, void *data)
936{
937 const struct cmd cmds[] = {
938 { "priority", cmd_bearer_get_prop, cmd_bearer_get_help },
939 { "tolerance", cmd_bearer_get_prop, cmd_bearer_get_help },
940 { "window", cmd_bearer_get_prop, cmd_bearer_get_help },
7d40bdbc 941 { "mtu", cmd_bearer_get_prop, cmd_bearer_get_help },
ed81deab 942 { "media", cmd_bearer_get_media, cmd_bearer_get_help },
f043759d
RA
943 { NULL }
944 };
945
946 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
947}
948
949static int bearer_list_cb(const struct nlmsghdr *nlh, void *data)
950{
951 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
952 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
953 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {};
954
955 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
956 if (!info[TIPC_NLA_BEARER]) {
957 fprintf(stderr, "No bearer in netlink response\n");
958 return MNL_CB_ERROR;
959 }
960
961 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs);
962 if (!attrs[TIPC_NLA_BEARER_NAME]) {
963 fprintf(stderr, "Bearer name missing in netlink response\n");
964 return MNL_CB_ERROR;
965 }
966
967 printf("%s\n", mnl_attr_get_str(attrs[TIPC_NLA_BEARER_NAME]));
968
969 return MNL_CB_OK;
970}
971
972static int cmd_bearer_list(struct nlmsghdr *nlh, const struct cmd *cmd,
973 struct cmdl *cmdl, void *data)
974{
975 char buf[MNL_SOCKET_BUFFER_SIZE];
976
977 if (help_flag) {
978 fprintf(stderr, "Usage: %s bearer list\n", cmdl->argv[0]);
979 return -EINVAL;
980 }
981
982 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) {
983 fprintf(stderr, "error, message initialisation failed\n");
984 return -1;
985 }
986
987 return msg_dumpit(nlh, bearer_list_cb, NULL);
988}
989
990void cmd_bearer_help(struct cmdl *cmdl)
991{
992 fprintf(stderr,
993 "Usage: %s bearer COMMAND [ARGS] ...\n"
994 "\n"
995 "COMMANDS\n"
f1f40cf7 996 " add - Add data to existing bearer\n"
8589eb4e
MC
997 " enable - Enable a bearer\n"
998 " disable - Disable a bearer\n"
999 " set - Set various bearer properties\n"
1000 " get - Get various bearer properties\n"
1001 " list - List bearers\n", cmdl->argv[0]);
f043759d
RA
1002}
1003
1004int cmd_bearer(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
1005 void *data)
1006{
1007 const struct cmd cmds[] = {
f1f40cf7 1008 { "add", cmd_bearer_add, cmd_bearer_add_help },
f043759d
RA
1009 { "disable", cmd_bearer_disable, cmd_bearer_disable_help },
1010 { "enable", cmd_bearer_enable, cmd_bearer_enable_help },
1011 { "get", cmd_bearer_get, cmd_bearer_get_help },
1012 { "list", cmd_bearer_list, NULL },
1013 { "set", cmd_bearer_set, cmd_bearer_set_help },
1014 { NULL }
1015 };
1016
1017 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
1018}