blob: 0d84570150624dd9a6ee945edf1d9f54a8f90856 [file] [log] [blame]
Richard Alpef0437592015-05-07 15:07:36 +02001/*
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>
Richard Alpeed81dea2016-08-30 10:37:00 +020017#include <arpa/inet.h>
Richard Alpef0437592015-05-07 15:07:36 +020018
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
Richard Alpeed81dea2016-08-30 10:37:00 +020030#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
Richard Alpef0437592015-05-07 15:07:36 +020039static void _print_bearer_opts(void)
40{
41 fprintf(stderr,
Richard Alpe50afc4d2016-08-15 10:24:32 +020042 "OPTIONS\n"
Richard Alpef0437592015-05-07 15:07:36 +020043 " priority - Bearer link priority\n"
44 " tolerance - Bearer link tolerance\n"
45 " window - Bearer link window\n");
46}
47
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +020048void print_bearer_media(void)
Richard Alpef0437592015-05-07 15:07:36 +020049{
50 fprintf(stderr,
51 "\nMEDIA\n"
52 " udp - User Datagram Protocol\n"
53 " ib - Infiniband\n"
54 " eth - Ethernet\n");
55}
56
Richard Alpe50afc4d2016-08-15 10:24:32 +020057static void cmd_bearer_enable_l2_help(struct cmdl *cmdl, char *media)
Richard Alpef0437592015-05-07 15:07:36 +020058{
59 fprintf(stderr,
Richard Alpe50afc4d2016-08-15 10:24:32 +020060 "Usage: %s bearer enable media %s device DEVICE [OPTIONS]\n"
Richard Alpef0437592015-05-07 15:07:36 +020061 "\nOPTIONS\n"
62 " domain DOMAIN - Discovery domain\n"
63 " priority PRIORITY - Bearer priority\n",
Richard Alpe50afc4d2016-08-15 10:24:32 +020064 cmdl->argv[0], media);
Richard Alpef0437592015-05-07 15:07:36 +020065}
66
Richard Alpe50afc4d2016-08-15 10:24:32 +020067static void cmd_bearer_enable_udp_help(struct cmdl *cmdl, char *media)
Richard Alpef0437592015-05-07 15:07:36 +020068{
69 fprintf(stderr,
Richard Alpeed81dea2016-08-30 10:37:00 +020070 "Usage: %s bearer enable [OPTIONS] media %s name NAME localip IP [UDP OPTIONS]\n\n",
71 cmdl->argv[0], media);
72 fprintf(stderr,
73 "OPTIONS\n"
Richard Alpef0437592015-05-07 15:07:36 +020074 " domain DOMAIN - Discovery domain\n"
Richard Alpeed81dea2016-08-30 10:37:00 +020075 " priority PRIORITY - Bearer priority\n\n");
76 fprintf(stderr,
77 "UDP OPTIONS\n"
Richard Alpef0437592015-05-07 15:07:36 +020078 " localport PORT - Local UDP port (default 6118)\n"
79 " remoteip IP - Remote IP address\n"
Richard Alpeed81dea2016-08-30 10:37:00 +020080 " remoteport PORT - Remote UDP port (default 6118)\n");
Richard Alpef0437592015-05-07 15:07:36 +020081}
82
83static int get_netid_cb(const struct nlmsghdr *nlh, void *data)
84{
85 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
86 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
87 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {};
88 int *netid = (int*)data;
89
90 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
91 if (!info[TIPC_NLA_NET])
92 return MNL_CB_ERROR;
93 mnl_attr_parse_nested(info[TIPC_NLA_NET], parse_attrs, attrs);
94 if (!attrs[TIPC_NLA_NET_ID])
95 return MNL_CB_ERROR;
96 *netid = mnl_attr_get_u32(attrs[TIPC_NLA_NET_ID]);
97
98 return MNL_CB_OK;
99}
100
101static int generate_multicast(short af, char *buf, int bufsize)
102{
103 int netid;
104 char mnl_msg[MNL_SOCKET_BUFFER_SIZE];
105 struct nlmsghdr *nlh;
106
107 if (!(nlh = msg_init(mnl_msg, TIPC_NL_NET_GET))) {
108 fprintf(stderr, "error, message initialization failed\n");
109 return -1;
110 }
111 if (msg_dumpit(nlh, get_netid_cb, &netid)) {
112 fprintf(stderr, "error, failed to fetch TIPC network id from kernel\n");
113 return -EINVAL;
114 }
115 if (af == AF_INET)
116 snprintf(buf, bufsize, "228.0.%u.%u", (netid>>8) & 0xFF, netid & 0xFF);
117 else
118 snprintf(buf, bufsize, "ff02::%u", netid);
119
120 return 0;
121}
122
Richard Alpe50afc4d2016-08-15 10:24:32 +0200123static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
124 struct cmdl *cmdl)
Richard Alpef0437592015-05-07 15:07:36 +0200125{
126 int err;
127 struct opt *opt;
128 struct nlattr *nest;
129 char buf[INET6_ADDRSTRLEN];
130 char *locport = "6118";
131 char *remport = "6118";
132 char *locip = NULL;
133 char *remip = NULL;
Richard Alpef0437592015-05-07 15:07:36 +0200134 struct addrinfo *loc = NULL;
135 struct addrinfo *rem = NULL;
136 struct addrinfo hints = {
137 .ai_family = AF_UNSPEC,
138 .ai_socktype = SOCK_DGRAM
139 };
140
Richard Alpef0437592015-05-07 15:07:36 +0200141 if (!(opt = get_opt(opts, "localip"))) {
142 fprintf(stderr, "error, udp bearer localip missing\n");
Richard Alpe50afc4d2016-08-15 10:24:32 +0200143 cmd_bearer_enable_udp_help(cmdl, "udp");
Richard Alpef0437592015-05-07 15:07:36 +0200144 return -EINVAL;
145 }
146 locip = opt->val;
147
148 if ((opt = get_opt(opts, "remoteip")))
149 remip = opt->val;
150
151 if ((opt = get_opt(opts, "localport")))
152 locport = opt->val;
153
154 if ((opt = get_opt(opts, "remoteport")))
155 remport = opt->val;
156
157 if ((err = getaddrinfo(locip, locport, &hints, &loc))) {
158 fprintf(stderr, "UDP local address error: %s\n",
159 gai_strerror(err));
160 return err;
161 }
162
163 if (!remip) {
164 if (generate_multicast(loc->ai_family, buf, sizeof(buf))) {
165 fprintf(stderr, "Failed to generate multicast address\n");
Phil Sutterbe554162017-08-17 19:09:31 +0200166 freeaddrinfo(loc);
Richard Alpef0437592015-05-07 15:07:36 +0200167 return -EINVAL;
168 }
169 remip = buf;
170 }
171
172 if ((err = getaddrinfo(remip, remport, &hints, &rem))) {
173 fprintf(stderr, "UDP remote address error: %s\n",
174 gai_strerror(err));
175 freeaddrinfo(loc);
176 return err;
177 }
178
179 if (rem->ai_family != loc->ai_family) {
180 fprintf(stderr, "UDP local and remote AF mismatch\n");
Phil Sutterbe554162017-08-17 19:09:31 +0200181 freeaddrinfo(rem);
182 freeaddrinfo(loc);
Richard Alpef0437592015-05-07 15:07:36 +0200183 return -EINVAL;
184 }
185
Richard Alpef0437592015-05-07 15:07:36 +0200186 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_UDP_OPTS);
187 mnl_attr_put(nlh, TIPC_NLA_UDP_LOCAL, loc->ai_addrlen, loc->ai_addr);
188 mnl_attr_put(nlh, TIPC_NLA_UDP_REMOTE, rem->ai_addrlen, rem->ai_addr);
189 mnl_attr_nest_end(nlh, nest);
190
191 freeaddrinfo(rem);
192 freeaddrinfo(loc);
193
194 return 0;
195}
196
Richard Alpe50afc4d2016-08-15 10:24:32 +0200197static int nl_add_bearer_name(struct nlmsghdr *nlh, const struct cmd *cmd,
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200198 struct cmdl *cmdl, struct opt *opts,
199 const struct tipc_sup_media *sup_media)
Richard Alpe50afc4d2016-08-15 10:24:32 +0200200{
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200201 char bname[TIPC_MAX_BEARER_NAME];
202 int err;
203
204 if ((err = cmd_get_unique_bearer_name(cmd, cmdl, opts, bname, sup_media)))
205 return err;
206
207 mnl_attr_put_strz(nlh, TIPC_NLA_BEARER_NAME, bname);
208 return 0;
209}
210
211int cmd_get_unique_bearer_name(const struct cmd *cmd, struct cmdl *cmdl,
212 struct opt *opts, char *bname,
213 const struct tipc_sup_media *sup_media)
214{
Richard Alpe50afc4d2016-08-15 10:24:32 +0200215 char *media;
216 char *identifier;
217 struct opt *opt;
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200218 const struct tipc_sup_media *entry;
219
Richard Alpe50afc4d2016-08-15 10:24:32 +0200220
221 if (!(opt = get_opt(opts, "media"))) {
222 if (help_flag)
223 (cmd->help)(cmdl);
224 else
225 fprintf(stderr, "error, missing bearer media\n");
226 return -EINVAL;
227 }
228 media = opt->val;
229
230 for (entry = sup_media; entry->media; entry++) {
231 if (strcmp(entry->media, media))
232 continue;
233
234 if (!(opt = get_opt(opts, entry->identifier))) {
235 if (help_flag)
236 (entry->help)(cmdl, media);
237 else
238 fprintf(stderr, "error, missing bearer %s\n",
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200239 entry->identifier);
Richard Alpe50afc4d2016-08-15 10:24:32 +0200240 return -EINVAL;
241 }
242
243 identifier = opt->val;
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200244 snprintf(bname, TIPC_MAX_BEARER_NAME, "%s:%s", media, identifier);
Richard Alpe50afc4d2016-08-15 10:24:32 +0200245
246 return 0;
247 }
248
249 fprintf(stderr, "error, invalid media type %s\n", media);
250
251 return -EINVAL;
252}
253
Richard Alpef1f40cf2016-08-30 10:36:59 +0200254static void cmd_bearer_add_udp_help(struct cmdl *cmdl, char *media)
255{
256 fprintf(stderr, "Usage: %s bearer add media %s name NAME remoteip REMOTEIP\n\n",
257 cmdl->argv[0], media);
258}
259
260static void cmd_bearer_add_help(struct cmdl *cmdl)
261{
262 fprintf(stderr, "Usage: %s bearer add media udp name NAME remoteip REMOTEIP\n",
263 cmdl->argv[0]);
264}
265
266static int udp_bearer_add(struct nlmsghdr *nlh, struct opt *opts,
267 struct cmdl *cmdl)
268{
269 int err;
270 struct opt *opt;
271 struct nlattr *opts_nest;
272 char *remport = "6118";
273
274 opts_nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_UDP_OPTS);
275
276 if ((opt = get_opt(opts, "remoteport")))
277 remport = opt->val;
278
279 if ((opt = get_opt(opts, "remoteip"))) {
280 char *ip = opt->val;
281 struct addrinfo *addr = NULL;
282 struct addrinfo hints = {
283 .ai_family = AF_UNSPEC,
284 .ai_socktype = SOCK_DGRAM
285 };
286
287 if ((err = getaddrinfo(ip, remport, &hints, &addr))) {
288 fprintf(stderr, "UDP address error: %s\n",
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200289 gai_strerror(err));
Richard Alpef1f40cf2016-08-30 10:36:59 +0200290 freeaddrinfo(addr);
291 return err;
292 }
293
294 mnl_attr_put(nlh, TIPC_NLA_UDP_REMOTE, addr->ai_addrlen,
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200295 addr->ai_addr);
Richard Alpef1f40cf2016-08-30 10:36:59 +0200296 freeaddrinfo(addr);
297 } else {
298 fprintf(stderr, "error, missing remoteip\n");
299 return -EINVAL;
300 }
301 mnl_attr_nest_end(nlh, opts_nest);
302
303 return 0;
304}
305
306static int cmd_bearer_add_media(struct nlmsghdr *nlh, const struct cmd *cmd,
307 struct cmdl *cmdl, void *data)
308{
309 int err;
310 char *media;
311 char buf[MNL_SOCKET_BUFFER_SIZE];
312 struct opt *opt;
313 struct nlattr *attrs;
314 struct opt opts[] = {
Richard Alpeed81dea2016-08-30 10:37:00 +0200315 { "remoteip", OPT_KEYVAL, NULL },
316 { "remoteport", OPT_KEYVAL, NULL },
317 { "name", OPT_KEYVAL, NULL },
318 { "media", OPT_KEYVAL, NULL },
Richard Alpef1f40cf2016-08-30 10:36:59 +0200319 { NULL }
320 };
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200321 const struct tipc_sup_media sup_media[] = {
Richard Alpef1f40cf2016-08-30 10:36:59 +0200322 { "udp", "name", cmd_bearer_add_udp_help},
323 { NULL, },
324 };
325
326 /* Rewind optind to include media in the option list */
327 cmdl->optind--;
328 if (parse_opts(opts, cmdl) < 0)
329 return -EINVAL;
330
331 if (!(opt = get_opt(opts, "media"))) {
332 fprintf(stderr, "error, missing media value\n");
333 return -EINVAL;
334 }
335 media = opt->val;
336
337 if (strcmp(media, "udp") != 0) {
338 fprintf(stderr, "error, no \"%s\" media specific options available\n",
339 media);
340 return -EINVAL;
341 }
342 if (!(opt = get_opt(opts, "name"))) {
343 fprintf(stderr, "error, missing media name\n");
344 return -EINVAL;
345 }
346
347 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_ADD))) {
348 fprintf(stderr, "error, message initialisation failed\n");
349 return -1;
350 }
351
352 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
353 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
354 if (err)
355 return err;
356
357 err = udp_bearer_add(nlh, opts, cmdl);
358 if (err)
359 return err;
360
361 mnl_attr_nest_end(nlh, attrs);
362
363 return msg_doit(nlh, NULL, NULL);
364}
365
366static int cmd_bearer_add(struct nlmsghdr *nlh, const struct cmd *cmd,
367 struct cmdl *cmdl, void *data)
368{
369 const struct cmd cmds[] = {
370 { "media", cmd_bearer_add_media, cmd_bearer_add_help },
371 { NULL }
372 };
373
374 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
375}
376
Richard Alpef0437592015-05-07 15:07:36 +0200377static void cmd_bearer_enable_help(struct cmdl *cmdl)
378{
379 fprintf(stderr,
380 "Usage: %s bearer enable [OPTIONS] media MEDIA ARGS...\n\n"
381 "OPTIONS\n"
382 " domain DOMAIN - Discovery domain\n"
383 " priority PRIORITY - Bearer priority\n",
384 cmdl->argv[0]);
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200385 print_bearer_media();
Richard Alpef0437592015-05-07 15:07:36 +0200386}
387
388static int cmd_bearer_enable(struct nlmsghdr *nlh, const struct cmd *cmd,
389 struct cmdl *cmdl, void *data)
390{
391 int err;
392 struct opt *opt;
393 struct nlattr *nest;
394 char buf[MNL_SOCKET_BUFFER_SIZE];
Richard Alpef0437592015-05-07 15:07:36 +0200395 struct opt opts[] = {
Richard Alpeed81dea2016-08-30 10:37:00 +0200396 { "device", OPT_KEYVAL, NULL },
397 { "domain", OPT_KEYVAL, NULL },
398 { "localip", OPT_KEYVAL, NULL },
399 { "localport", OPT_KEYVAL, NULL },
400 { "media", OPT_KEYVAL, NULL },
401 { "name", OPT_KEYVAL, NULL },
402 { "priority", OPT_KEYVAL, NULL },
403 { "remoteip", OPT_KEYVAL, NULL },
404 { "remoteport", OPT_KEYVAL, NULL },
Richard Alpef0437592015-05-07 15:07:36 +0200405 { NULL }
406 };
Richard Alpe50afc4d2016-08-15 10:24:32 +0200407 struct tipc_sup_media sup_media[] = {
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200408 { "udp", "name", cmd_bearer_enable_udp_help},
409 { "eth", "device", cmd_bearer_enable_l2_help },
410 { "ib", "device", cmd_bearer_enable_l2_help },
Richard Alpe50afc4d2016-08-15 10:24:32 +0200411 { NULL, },
412 };
Richard Alpef0437592015-05-07 15:07:36 +0200413
414 if (parse_opts(opts, cmdl) < 0) {
415 if (help_flag)
416 (cmd->help)(cmdl);
417 return -EINVAL;
418 }
419
Richard Alpef0437592015-05-07 15:07:36 +0200420 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_ENABLE))) {
421 fprintf(stderr, "error: message initialisation failed\n");
422 return -1;
423 }
424 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
425
426 if ((opt = get_opt(opts, "domain")))
427 mnl_attr_put_u32(nlh, TIPC_NLA_BEARER_DOMAIN, atoi(opt->val));
428
429 if ((opt = get_opt(opts, "priority"))) {
430 struct nlattr *props;
431
432 props = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_PROP);
433 mnl_attr_put_u32(nlh, TIPC_NLA_PROP_PRIO, atoi(opt->val));
434 mnl_attr_nest_end(nlh, props);
435 }
436
Richard Alpe50afc4d2016-08-15 10:24:32 +0200437 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
438 if (err)
439 return err;
Richard Alpef0437592015-05-07 15:07:36 +0200440
Richard Alpe50afc4d2016-08-15 10:24:32 +0200441 opt = get_opt(opts, "media");
Phil Sutter70a6df32017-08-24 11:46:34 +0200442 if (opt && strcmp(opt->val, "udp") == 0) {
Richard Alpe50afc4d2016-08-15 10:24:32 +0200443 err = nl_add_udp_enable_opts(nlh, opts, cmdl);
444 if (err)
445 return err;
446 }
Richard Alpef0437592015-05-07 15:07:36 +0200447 mnl_attr_nest_end(nlh, nest);
448
449 return msg_doit(nlh, NULL, NULL);
450}
451
Richard Alpe50afc4d2016-08-15 10:24:32 +0200452static void cmd_bearer_disable_l2_help(struct cmdl *cmdl, char *media)
Richard Alpef0437592015-05-07 15:07:36 +0200453{
Richard Alpe50afc4d2016-08-15 10:24:32 +0200454 fprintf(stderr, "Usage: %s bearer disable media %s device DEVICE\n",
455 cmdl->argv[0], media);
Richard Alpef0437592015-05-07 15:07:36 +0200456}
457
Richard Alpe50afc4d2016-08-15 10:24:32 +0200458static void cmd_bearer_disable_udp_help(struct cmdl *cmdl, char *media)
Richard Alpef0437592015-05-07 15:07:36 +0200459{
Richard Alpe50afc4d2016-08-15 10:24:32 +0200460 fprintf(stderr, "Usage: %s bearer disable media %s name NAME\n",
461 cmdl->argv[0], media);
Richard Alpef0437592015-05-07 15:07:36 +0200462}
463
464static void cmd_bearer_disable_help(struct cmdl *cmdl)
465{
466 fprintf(stderr, "Usage: %s bearer disable media MEDIA ARGS...\n",
467 cmdl->argv[0]);
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200468 print_bearer_media();
Richard Alpef0437592015-05-07 15:07:36 +0200469}
470
471static int cmd_bearer_disable(struct nlmsghdr *nlh, const struct cmd *cmd,
472 struct cmdl *cmdl, void *data)
473{
474 int err;
Richard Alpef0437592015-05-07 15:07:36 +0200475 char buf[MNL_SOCKET_BUFFER_SIZE];
476 struct nlattr *nest;
Richard Alpef0437592015-05-07 15:07:36 +0200477 struct opt opts[] = {
Richard Alpeed81dea2016-08-30 10:37:00 +0200478 { "device", OPT_KEYVAL, NULL },
479 { "name", OPT_KEYVAL, NULL },
480 { "media", OPT_KEYVAL, NULL },
Richard Alpef0437592015-05-07 15:07:36 +0200481 { NULL }
482 };
Richard Alpe50afc4d2016-08-15 10:24:32 +0200483 struct tipc_sup_media sup_media[] = {
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200484 { "udp", "name", cmd_bearer_disable_udp_help},
485 { "eth", "device", cmd_bearer_disable_l2_help },
486 { "ib", "device", cmd_bearer_disable_l2_help },
Richard Alpe50afc4d2016-08-15 10:24:32 +0200487 { NULL, },
488 };
Richard Alpef0437592015-05-07 15:07:36 +0200489
490 if (parse_opts(opts, cmdl) < 0) {
491 if (help_flag)
492 (cmd->help)(cmdl);
493 return -EINVAL;
494 }
495
Richard Alpef0437592015-05-07 15:07:36 +0200496 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_DISABLE))) {
497 fprintf(stderr, "error, message initialisation failed\n");
498 return -1;
499 }
500
501 nest = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
Richard Alpe50afc4d2016-08-15 10:24:32 +0200502 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
503 if (err)
504 return err;
Richard Alpef0437592015-05-07 15:07:36 +0200505 mnl_attr_nest_end(nlh, nest);
506
507 return msg_doit(nlh, NULL, NULL);
508
509}
510
511static void cmd_bearer_set_help(struct cmdl *cmdl)
512{
Richard Alpeee262ed2015-08-07 09:55:09 +0200513 fprintf(stderr, "Usage: %s bearer set OPTION media MEDIA ARGS...\n",
Richard Alpef0437592015-05-07 15:07:36 +0200514 cmdl->argv[0]);
515 _print_bearer_opts();
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200516 print_bearer_media();
Richard Alpef0437592015-05-07 15:07:36 +0200517}
518
Richard Alpe50afc4d2016-08-15 10:24:32 +0200519static void cmd_bearer_set_udp_help(struct cmdl *cmdl, char *media)
Richard Alpef0437592015-05-07 15:07:36 +0200520{
Richard Alpe50afc4d2016-08-15 10:24:32 +0200521 fprintf(stderr, "Usage: %s bearer set OPTION media %s name NAME\n\n",
522 cmdl->argv[0], media);
Richard Alpef0437592015-05-07 15:07:36 +0200523 _print_bearer_opts();
524}
525
526static void cmd_bearer_set_l2_help(struct cmdl *cmdl, char *media)
527{
528 fprintf(stderr,
529 "Usage: %s bearer set [OPTION]... media %s device DEVICE\n",
530 cmdl->argv[0], media);
531 _print_bearer_opts();
532}
533
534static int cmd_bearer_set_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200535 struct cmdl *cmdl, void *data)
Richard Alpef0437592015-05-07 15:07:36 +0200536{
537 int err;
538 int val;
539 int prop;
Richard Alpef0437592015-05-07 15:07:36 +0200540 char buf[MNL_SOCKET_BUFFER_SIZE];
541 struct nlattr *props;
542 struct nlattr *attrs;
Richard Alpef0437592015-05-07 15:07:36 +0200543 struct opt opts[] = {
Richard Alpeed81dea2016-08-30 10:37:00 +0200544 { "device", OPT_KEYVAL, NULL },
545 { "media", OPT_KEYVAL, NULL },
546 { "name", OPT_KEYVAL, NULL },
Richard Alpef0437592015-05-07 15:07:36 +0200547 { NULL }
548 };
Richard Alpe50afc4d2016-08-15 10:24:32 +0200549 struct tipc_sup_media sup_media[] = {
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200550 { "udp", "name", cmd_bearer_set_udp_help},
551 { "eth", "device", cmd_bearer_set_l2_help },
552 { "ib", "device", cmd_bearer_set_l2_help },
Richard Alpe50afc4d2016-08-15 10:24:32 +0200553 { NULL, },
554 };
Richard Alpef0437592015-05-07 15:07:36 +0200555
556 if (strcmp(cmd->cmd, "priority") == 0)
557 prop = TIPC_NLA_PROP_PRIO;
558 else if ((strcmp(cmd->cmd, "tolerance") == 0))
559 prop = TIPC_NLA_PROP_TOL;
560 else if ((strcmp(cmd->cmd, "window") == 0))
561 prop = TIPC_NLA_PROP_WIN;
562 else
563 return -EINVAL;
564
Richard Alpef0437592015-05-07 15:07:36 +0200565 if (cmdl->optind >= cmdl->argc) {
566 fprintf(stderr, "error, missing value\n");
567 return -EINVAL;
568 }
569 val = atoi(shift_cmdl(cmdl));
570
571 if (parse_opts(opts, cmdl) < 0)
572 return -EINVAL;
573
574 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_SET))) {
575 fprintf(stderr, "error, message initialisation failed\n");
576 return -1;
577 }
578 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
579
580 props = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER_PROP);
581 mnl_attr_put_u32(nlh, prop, val);
582 mnl_attr_nest_end(nlh, props);
583
Richard Alpe50afc4d2016-08-15 10:24:32 +0200584 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
585 if (err)
586 return err;
Richard Alpef0437592015-05-07 15:07:36 +0200587
Richard Alpef0437592015-05-07 15:07:36 +0200588 mnl_attr_nest_end(nlh, attrs);
589
590 return msg_doit(nlh, NULL, NULL);
591}
592
593static int cmd_bearer_set(struct nlmsghdr *nlh, const struct cmd *cmd,
594 struct cmdl *cmdl, void *data)
595{
596 const struct cmd cmds[] = {
597 { "priority", cmd_bearer_set_prop, cmd_bearer_set_help },
598 { "tolerance", cmd_bearer_set_prop, cmd_bearer_set_help },
599 { "window", cmd_bearer_set_prop, cmd_bearer_set_help },
600 { NULL }
601 };
602
603 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
604}
605
606static void cmd_bearer_get_help(struct cmdl *cmdl)
607{
Richard Alpeed81dea2016-08-30 10:37:00 +0200608 fprintf(stderr, "Usage: %s bearer get [OPTION] media MEDIA ARGS...\n",
Richard Alpef0437592015-05-07 15:07:36 +0200609 cmdl->argv[0]);
610 _print_bearer_opts();
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200611 print_bearer_media();
Richard Alpef0437592015-05-07 15:07:36 +0200612}
613
Richard Alpe50afc4d2016-08-15 10:24:32 +0200614static void cmd_bearer_get_udp_help(struct cmdl *cmdl, char *media)
Richard Alpef0437592015-05-07 15:07:36 +0200615{
Richard Alpeed81dea2016-08-30 10:37:00 +0200616 fprintf(stderr, "Usage: %s bearer get [OPTION] media %s name NAME [UDP OPTIONS]\n\n",
Richard Alpe50afc4d2016-08-15 10:24:32 +0200617 cmdl->argv[0], media);
Richard Alpeed81dea2016-08-30 10:37:00 +0200618 fprintf(stderr,
619 "UDP OPTIONS\n"
620 " remoteip - Remote ip address\n"
621 " remoteport - Remote port\n"
622 " localip - Local ip address\n"
623 " localport - Local port\n\n");
Richard Alpef0437592015-05-07 15:07:36 +0200624 _print_bearer_opts();
625}
626
627static void cmd_bearer_get_l2_help(struct cmdl *cmdl, char *media)
628{
629 fprintf(stderr,
Richard Alpe50afc4d2016-08-15 10:24:32 +0200630 "Usage: %s bearer get OPTION media %s device DEVICE\n",
Richard Alpef0437592015-05-07 15:07:36 +0200631 cmdl->argv[0], media);
632 _print_bearer_opts();
633}
634
Richard Alpeed81dea2016-08-30 10:37:00 +0200635
636static int bearer_dump_udp_cb(const struct nlmsghdr *nlh, void *data)
637{
638 struct sockaddr_storage *addr;
639 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
640 struct nlattr *info[TIPC_NLA_UDP_MAX + 1] = {};
641
642 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
643
644 if (!info[TIPC_NLA_UDP_REMOTE])
645 return MNL_CB_ERROR;
646
647 addr = mnl_attr_get_payload(info[TIPC_NLA_UDP_REMOTE]);
648
649 if (addr->ss_family == AF_INET) {
650 struct sockaddr_in *ipv4 = (struct sockaddr_in *) addr;
651
652 printf("%s\n", inet_ntoa(ipv4->sin_addr));
653 } else if (addr->ss_family == AF_INET6) {
654 char straddr[INET6_ADDRSTRLEN];
655 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) addr;
656
657 if (!inet_ntop(AF_INET6, &ipv6->sin6_addr, straddr,
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200658 sizeof(straddr))) {
Richard Alpeed81dea2016-08-30 10:37:00 +0200659 fprintf(stderr, "error, parsing IPv6 addr\n");
660 return MNL_CB_ERROR;
661 }
662 printf("%s\n", straddr);
663
664 } else {
665 return MNL_CB_ERROR;
666 }
667
668 return MNL_CB_OK;
669}
670
671static int bearer_get_udp_cb(const struct nlmsghdr *nlh, void *data)
672{
673 struct cb_data *cb_data = (struct cb_data *) data;
674 struct sockaddr_storage *addr;
675 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
676 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
677 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {};
678 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1] = {};
679
680 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
681 if (!info[TIPC_NLA_BEARER])
682 return MNL_CB_ERROR;
683
684 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs);
685 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
686 return MNL_CB_ERROR;
687
688 mnl_attr_parse_nested(attrs[TIPC_NLA_BEARER_UDP_OPTS], parse_attrs, opts);
689 if (!opts[TIPC_NLA_UDP_LOCAL])
690 return MNL_CB_ERROR;
691
692 if ((cb_data->attr == TIPC_NLA_UDP_REMOTE) &&
693 (cb_data->prop == UDP_PROP_IP) &&
694 opts[TIPC_NLA_UDP_MULTI_REMOTEIP]) {
695 struct genlmsghdr *genl = mnl_nlmsg_get_payload(cb_data->nlh);
696
697 genl->cmd = TIPC_NL_UDP_GET_REMOTEIP;
698 return msg_dumpit(cb_data->nlh, bearer_dump_udp_cb, NULL);
699 }
700
701 addr = mnl_attr_get_payload(opts[cb_data->attr]);
702
703 if (addr->ss_family == AF_INET) {
704 struct sockaddr_in *ipv4 = (struct sockaddr_in *) addr;
705
706 switch (cb_data->prop) {
707 case UDP_PROP_IP:
708 printf("%s\n", inet_ntoa(ipv4->sin_addr));
709 break;
710 case UDP_PROP_PORT:
711 printf("%u\n", ntohs(ipv4->sin_port));
712 break;
713 default:
714 return MNL_CB_ERROR;
715 }
716
717 } else if (addr->ss_family == AF_INET6) {
718 char straddr[INET6_ADDRSTRLEN];
719 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) addr;
720
721 switch (cb_data->prop) {
722 case UDP_PROP_IP:
723 if (!inet_ntop(AF_INET6, &ipv6->sin6_addr, straddr,
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200724 sizeof(straddr))) {
Richard Alpeed81dea2016-08-30 10:37:00 +0200725 fprintf(stderr, "error, parsing IPv6 addr\n");
726 return MNL_CB_ERROR;
727 }
728 printf("%s\n", straddr);
729 break;
730 case UDP_PROP_PORT:
731 printf("%u\n", ntohs(ipv6->sin6_port));
732 break;
733 default:
734 return MNL_CB_ERROR;
735 }
736
737 } else {
738 return MNL_CB_ERROR;
739 }
740
741 return MNL_CB_OK;
742}
743
Richard Alpef0437592015-05-07 15:07:36 +0200744static int bearer_get_cb(const struct nlmsghdr *nlh, void *data)
745{
746 int *prop = data;
747 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
748 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
749 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {};
750 struct nlattr *props[TIPC_NLA_PROP_MAX + 1] = {};
751
752 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
753 if (!info[TIPC_NLA_BEARER])
754 return MNL_CB_ERROR;
755
756 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs);
757 if (!attrs[TIPC_NLA_BEARER_PROP])
758 return MNL_CB_ERROR;
759
760 mnl_attr_parse_nested(attrs[TIPC_NLA_BEARER_PROP], parse_attrs, props);
761 if (!props[*prop])
762 return MNL_CB_ERROR;
763
764 printf("%u\n", mnl_attr_get_u32(props[*prop]));
765
766 return MNL_CB_OK;
767}
768
Richard Alpeed81dea2016-08-30 10:37:00 +0200769static int cmd_bearer_get_media(struct nlmsghdr *nlh, const struct cmd *cmd,
770 struct cmdl *cmdl, void *data)
771{
772 int err;
773 char *media;
774 char buf[MNL_SOCKET_BUFFER_SIZE];
775 struct opt *opt;
776 struct cb_data cb_data = {0};
777 struct nlattr *attrs;
778 struct opt opts[] = {
779 { "localip", OPT_KEY, NULL },
780 { "localport", OPT_KEY, NULL },
781 { "remoteip", OPT_KEY, NULL },
782 { "remoteport", OPT_KEY, NULL },
783 { "name", OPT_KEYVAL, NULL },
784 { "media", OPT_KEYVAL, NULL },
785 { NULL }
786 };
787 struct tipc_sup_media sup_media[] = {
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200788 { "udp", "name", cmd_bearer_get_udp_help},
Richard Alpeed81dea2016-08-30 10:37:00 +0200789 { NULL, },
790 };
791
792 /* Rewind optind to include media in the option list */
793 cmdl->optind--;
794 if (parse_opts(opts, cmdl) < 0)
795 return -EINVAL;
796
797 if (!(opt = get_opt(opts, "media"))) {
798 fprintf(stderr, "error, missing media value\n");
799 return -EINVAL;
800 }
801 media = opt->val;
802
803 if (help_flag) {
804 cmd_bearer_get_udp_help(cmdl, media);
805 return -EINVAL;
806 }
807 if (strcmp(media, "udp") != 0) {
808 fprintf(stderr, "error, no \"%s\" media specific options\n", media);
809 return -EINVAL;
810 }
811 if (!(opt = get_opt(opts, "name"))) {
812 fprintf(stderr, "error, missing media name\n");
813 return -EINVAL;
814 }
815
816 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) {
817 fprintf(stderr, "error, message initialisation failed\n");
818 return -1;
819 }
820
821 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
822 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
823 if (err)
824 return err;
825 mnl_attr_nest_end(nlh, attrs);
826 cb_data.nlh = nlh;
827
828 if (has_opt(opts, "localip")) {
829 cb_data.attr = TIPC_NLA_UDP_LOCAL;
830 cb_data.prop = UDP_PROP_IP;
831 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
832 } else if (has_opt(opts, "localport")) {
833 cb_data.attr = TIPC_NLA_UDP_LOCAL;
834 cb_data.prop = UDP_PROP_PORT;
835 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
836 } else if (has_opt(opts, "remoteip")) {
837 cb_data.attr = TIPC_NLA_UDP_REMOTE;
838 cb_data.prop = UDP_PROP_IP;
839 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
840 } else if (has_opt(opts, "remoteport")) {
841 cb_data.attr = TIPC_NLA_UDP_REMOTE;
842 cb_data.prop = UDP_PROP_PORT;
843 return msg_doit(nlh, bearer_get_udp_cb, &cb_data);
844 }
845 fprintf(stderr, "error, missing UDP option\n");
846 return -EINVAL;
847}
848
Richard Alpef0437592015-05-07 15:07:36 +0200849static int cmd_bearer_get_prop(struct nlmsghdr *nlh, const struct cmd *cmd,
850 struct cmdl *cmdl, void *data)
851{
852 int err;
853 int prop;
Richard Alpef0437592015-05-07 15:07:36 +0200854 char buf[MNL_SOCKET_BUFFER_SIZE];
855 struct nlattr *attrs;
Richard Alpef0437592015-05-07 15:07:36 +0200856 struct opt opts[] = {
Richard Alpeed81dea2016-08-30 10:37:00 +0200857 { "device", OPT_KEYVAL, NULL },
858 { "media", OPT_KEYVAL, NULL },
859 { "name", OPT_KEYVAL, NULL },
Richard Alpef0437592015-05-07 15:07:36 +0200860 { NULL }
861 };
Richard Alpe50afc4d2016-08-15 10:24:32 +0200862 struct tipc_sup_media sup_media[] = {
Parthasarathy Bhuvaragand2ba0b02016-09-12 17:17:19 +0200863 { "udp", "name", cmd_bearer_get_udp_help},
864 { "eth", "device", cmd_bearer_get_l2_help },
865 { "ib", "device", cmd_bearer_get_l2_help },
Richard Alpe50afc4d2016-08-15 10:24:32 +0200866 { NULL, },
867 };
Richard Alpef0437592015-05-07 15:07:36 +0200868
Richard Alpeed81dea2016-08-30 10:37:00 +0200869 if (help_flag) {
870 (cmd->help)(cmdl);
871 return -EINVAL;
872 }
873
Richard Alpef0437592015-05-07 15:07:36 +0200874 if (strcmp(cmd->cmd, "priority") == 0)
875 prop = TIPC_NLA_PROP_PRIO;
876 else if ((strcmp(cmd->cmd, "tolerance") == 0))
877 prop = TIPC_NLA_PROP_TOL;
878 else if ((strcmp(cmd->cmd, "window") == 0))
879 prop = TIPC_NLA_PROP_WIN;
880 else
881 return -EINVAL;
882
Richard Alpef0437592015-05-07 15:07:36 +0200883 if (parse_opts(opts, cmdl) < 0)
884 return -EINVAL;
885
886 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) {
887 fprintf(stderr, "error, message initialisation failed\n");
888 return -1;
889 }
890
Richard Alpef0437592015-05-07 15:07:36 +0200891 attrs = mnl_attr_nest_start(nlh, TIPC_NLA_BEARER);
Richard Alpe50afc4d2016-08-15 10:24:32 +0200892 err = nl_add_bearer_name(nlh, cmd, cmdl, opts, sup_media);
893 if (err)
894 return err;
Richard Alpef0437592015-05-07 15:07:36 +0200895 mnl_attr_nest_end(nlh, attrs);
896
897 return msg_doit(nlh, bearer_get_cb, &prop);
898}
899
900static int cmd_bearer_get(struct nlmsghdr *nlh, const struct cmd *cmd,
901 struct cmdl *cmdl, void *data)
902{
903 const struct cmd cmds[] = {
904 { "priority", cmd_bearer_get_prop, cmd_bearer_get_help },
905 { "tolerance", cmd_bearer_get_prop, cmd_bearer_get_help },
906 { "window", cmd_bearer_get_prop, cmd_bearer_get_help },
Richard Alpeed81dea2016-08-30 10:37:00 +0200907 { "media", cmd_bearer_get_media, cmd_bearer_get_help },
Richard Alpef0437592015-05-07 15:07:36 +0200908 { NULL }
909 };
910
911 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
912}
913
914static int bearer_list_cb(const struct nlmsghdr *nlh, void *data)
915{
916 struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
917 struct nlattr *info[TIPC_NLA_MAX + 1] = {};
918 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1] = {};
919
920 mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
921 if (!info[TIPC_NLA_BEARER]) {
922 fprintf(stderr, "No bearer in netlink response\n");
923 return MNL_CB_ERROR;
924 }
925
926 mnl_attr_parse_nested(info[TIPC_NLA_BEARER], parse_attrs, attrs);
927 if (!attrs[TIPC_NLA_BEARER_NAME]) {
928 fprintf(stderr, "Bearer name missing in netlink response\n");
929 return MNL_CB_ERROR;
930 }
931
932 printf("%s\n", mnl_attr_get_str(attrs[TIPC_NLA_BEARER_NAME]));
933
934 return MNL_CB_OK;
935}
936
937static int cmd_bearer_list(struct nlmsghdr *nlh, const struct cmd *cmd,
938 struct cmdl *cmdl, void *data)
939{
940 char buf[MNL_SOCKET_BUFFER_SIZE];
941
942 if (help_flag) {
943 fprintf(stderr, "Usage: %s bearer list\n", cmdl->argv[0]);
944 return -EINVAL;
945 }
946
947 if (!(nlh = msg_init(buf, TIPC_NL_BEARER_GET))) {
948 fprintf(stderr, "error, message initialisation failed\n");
949 return -1;
950 }
951
952 return msg_dumpit(nlh, bearer_list_cb, NULL);
953}
954
955void cmd_bearer_help(struct cmdl *cmdl)
956{
957 fprintf(stderr,
958 "Usage: %s bearer COMMAND [ARGS] ...\n"
959 "\n"
960 "COMMANDS\n"
Richard Alpef1f40cf2016-08-30 10:36:59 +0200961 " add - Add data to existing bearer\n"
Richard Alpef0437592015-05-07 15:07:36 +0200962 " enable - Enable a bearer\n"
963 " disable - Disable a bearer\n"
964 " set - Set various bearer properties\n"
965 " get - Get various bearer properties\n"
966 " list - List bearers\n", cmdl->argv[0]);
967}
968
969int cmd_bearer(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
970 void *data)
971{
972 const struct cmd cmds[] = {
Richard Alpef1f40cf2016-08-30 10:36:59 +0200973 { "add", cmd_bearer_add, cmd_bearer_add_help },
Richard Alpef0437592015-05-07 15:07:36 +0200974 { "disable", cmd_bearer_disable, cmd_bearer_disable_help },
975 { "enable", cmd_bearer_enable, cmd_bearer_enable_help },
976 { "get", cmd_bearer_get, cmd_bearer_get_help },
977 { "list", cmd_bearer_list, NULL },
978 { "set", cmd_bearer_set, cmd_bearer_set_help },
979 { NULL }
980 };
981
982 return run_cmd(nlh, cmd, cmds, cmdl, NULL);
983}