2 * bearer.c TIPC bearer functionality.
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.
9 * Authors: Richard Alpe <richard.alpe@ericsson.com>
18 #include <linux/tipc_netlink.h>
19 #include <linux/tipc.h>
20 #include <linux/genetlink.h>
22 #include <libmnl/libmnl.h>
23 #include <sys/socket.h>
29 static void _print_bearer_opts(void)
33 " priority - Bearer link priority\n"
34 " tolerance - Bearer link tolerance\n"
35 " window - Bearer link window\n");
38 static void _print_bearer_media(void)
42 " udp - User Datagram Protocol\n"
47 static void cmd_bearer_enable_l2_help(struct cmdl
*cmdl
, char *media
)
50 "Usage: %s bearer enable media %s device DEVICE [OPTIONS]\n"
52 " domain DOMAIN - Discovery domain\n"
53 " priority PRIORITY - Bearer priority\n",
54 cmdl
->argv
[0], media
);
57 static void cmd_bearer_enable_udp_help(struct cmdl
*cmdl
, char *media
)
60 "Usage: %s bearer enable media %s name NAME localip IP [OPTIONS]\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], media
);
70 static int get_netid_cb(const struct nlmsghdr
*nlh
, void *data
)
72 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
73 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
74 struct nlattr
*attrs
[TIPC_NLA_NET_MAX
+ 1] = {};
75 int *netid
= (int*)data
;
77 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
78 if (!info
[TIPC_NLA_NET
])
80 mnl_attr_parse_nested(info
[TIPC_NLA_NET
], parse_attrs
, attrs
);
81 if (!attrs
[TIPC_NLA_NET_ID
])
83 *netid
= mnl_attr_get_u32(attrs
[TIPC_NLA_NET_ID
]);
88 static int generate_multicast(short af
, char *buf
, int bufsize
)
91 char mnl_msg
[MNL_SOCKET_BUFFER_SIZE
];
94 if (!(nlh
= msg_init(mnl_msg
, TIPC_NL_NET_GET
))) {
95 fprintf(stderr
, "error, message initialization failed\n");
98 if (msg_dumpit(nlh
, get_netid_cb
, &netid
)) {
99 fprintf(stderr
, "error, failed to fetch TIPC network id from kernel\n");
103 snprintf(buf
, bufsize
, "228.0.%u.%u", (netid
>>8) & 0xFF, netid
& 0xFF);
105 snprintf(buf
, bufsize
, "ff02::%u", netid
);
110 static int nl_add_udp_enable_opts(struct nlmsghdr
*nlh
, struct opt
*opts
,
116 char buf
[INET6_ADDRSTRLEN
];
117 char *locport
= "6118";
118 char *remport
= "6118";
121 struct addrinfo
*loc
= NULL
;
122 struct addrinfo
*rem
= NULL
;
123 struct addrinfo hints
= {
124 .ai_family
= AF_UNSPEC
,
125 .ai_socktype
= SOCK_DGRAM
128 if (!(opt
= get_opt(opts
, "localip"))) {
129 fprintf(stderr
, "error, udp bearer localip missing\n");
130 cmd_bearer_enable_udp_help(cmdl
, "udp");
135 if ((opt
= get_opt(opts
, "remoteip")))
138 if ((opt
= get_opt(opts
, "localport")))
141 if ((opt
= get_opt(opts
, "remoteport")))
144 if ((err
= getaddrinfo(locip
, locport
, &hints
, &loc
))) {
145 fprintf(stderr
, "UDP local address error: %s\n",
151 if (generate_multicast(loc
->ai_family
, buf
, sizeof(buf
))) {
152 fprintf(stderr
, "Failed to generate multicast address\n");
158 if ((err
= getaddrinfo(remip
, remport
, &hints
, &rem
))) {
159 fprintf(stderr
, "UDP remote address error: %s\n",
165 if (rem
->ai_family
!= loc
->ai_family
) {
166 fprintf(stderr
, "UDP local and remote AF mismatch\n");
170 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_UDP_OPTS
);
171 mnl_attr_put(nlh
, TIPC_NLA_UDP_LOCAL
, loc
->ai_addrlen
, loc
->ai_addr
);
172 mnl_attr_put(nlh
, TIPC_NLA_UDP_REMOTE
, rem
->ai_addrlen
, rem
->ai_addr
);
173 mnl_attr_nest_end(nlh
, nest
);
181 static int nl_add_bearer_name(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
182 struct cmdl
*cmdl
, struct opt
*opts
,
183 struct tipc_sup_media sup_media
[])
185 char id
[TIPC_MAX_BEARER_NAME
];
189 struct tipc_sup_media
*entry
;
191 if (!(opt
= get_opt(opts
, "media"))) {
195 fprintf(stderr
, "error, missing bearer media\n");
200 for (entry
= sup_media
; entry
->media
; entry
++) {
201 if (strcmp(entry
->media
, media
))
204 if (!(opt
= get_opt(opts
, entry
->identifier
))) {
206 (entry
->help
)(cmdl
, media
);
208 fprintf(stderr
, "error, missing bearer %s\n",
213 identifier
= opt
->val
;
214 snprintf(id
, sizeof(id
), "%s:%s", media
, identifier
);
215 mnl_attr_put_strz(nlh
, TIPC_NLA_BEARER_NAME
, id
);
220 fprintf(stderr
, "error, invalid media type %s\n", media
);
225 static void cmd_bearer_enable_help(struct cmdl
*cmdl
)
228 "Usage: %s bearer enable [OPTIONS] media MEDIA ARGS...\n\n"
230 " domain DOMAIN - Discovery domain\n"
231 " priority PRIORITY - Bearer priority\n",
233 _print_bearer_media();
236 static int cmd_bearer_enable(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
237 struct cmdl
*cmdl
, void *data
)
242 char buf
[MNL_SOCKET_BUFFER_SIZE
];
243 struct opt opts
[] = {
247 { "localport", NULL
},
250 { "priority", NULL
},
251 { "remoteip", NULL
},
252 { "remoteport", NULL
},
255 struct tipc_sup_media sup_media
[] = {
256 { "udp", "name", cmd_bearer_enable_udp_help
},
257 { "eth", "device", cmd_bearer_enable_l2_help
},
258 { "ib", "device", cmd_bearer_enable_l2_help
},
262 if (parse_opts(opts
, cmdl
) < 0) {
268 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_ENABLE
))) {
269 fprintf(stderr
, "error: message initialisation failed\n");
272 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
274 if ((opt
= get_opt(opts
, "domain")))
275 mnl_attr_put_u32(nlh
, TIPC_NLA_BEARER_DOMAIN
, atoi(opt
->val
));
277 if ((opt
= get_opt(opts
, "priority"))) {
278 struct nlattr
*props
;
280 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_PROP
);
281 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_PRIO
, atoi(opt
->val
));
282 mnl_attr_nest_end(nlh
, props
);
285 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
289 opt
= get_opt(opts
, "media");
290 if (strcmp(opt
->val
, "udp") == 0) {
291 err
= nl_add_udp_enable_opts(nlh
, opts
, cmdl
);
295 mnl_attr_nest_end(nlh
, nest
);
297 return msg_doit(nlh
, NULL
, NULL
);
300 static void cmd_bearer_disable_l2_help(struct cmdl
*cmdl
, char *media
)
302 fprintf(stderr
, "Usage: %s bearer disable media %s device DEVICE\n",
303 cmdl
->argv
[0], media
);
306 static void cmd_bearer_disable_udp_help(struct cmdl
*cmdl
, char *media
)
308 fprintf(stderr
, "Usage: %s bearer disable media %s name NAME\n",
309 cmdl
->argv
[0], media
);
312 static void cmd_bearer_disable_help(struct cmdl
*cmdl
)
314 fprintf(stderr
, "Usage: %s bearer disable media MEDIA ARGS...\n",
316 _print_bearer_media();
319 static int cmd_bearer_disable(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
320 struct cmdl
*cmdl
, void *data
)
323 char buf
[MNL_SOCKET_BUFFER_SIZE
];
325 struct opt opts
[] = {
331 struct tipc_sup_media sup_media
[] = {
332 { "udp", "name", cmd_bearer_disable_udp_help
},
333 { "eth", "device", cmd_bearer_disable_l2_help
},
334 { "ib", "device", cmd_bearer_disable_l2_help
},
338 if (parse_opts(opts
, cmdl
) < 0) {
344 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_DISABLE
))) {
345 fprintf(stderr
, "error, message initialisation failed\n");
349 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
350 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
353 mnl_attr_nest_end(nlh
, nest
);
355 return msg_doit(nlh
, NULL
, NULL
);
359 static void cmd_bearer_set_help(struct cmdl
*cmdl
)
361 fprintf(stderr
, "Usage: %s bearer set OPTION media MEDIA ARGS...\n",
363 _print_bearer_opts();
364 _print_bearer_media();
367 static void cmd_bearer_set_udp_help(struct cmdl
*cmdl
, char *media
)
369 fprintf(stderr
, "Usage: %s bearer set OPTION media %s name NAME\n\n",
370 cmdl
->argv
[0], media
);
371 _print_bearer_opts();
374 static void cmd_bearer_set_l2_help(struct cmdl
*cmdl
, char *media
)
377 "Usage: %s bearer set [OPTION]... media %s device DEVICE\n",
378 cmdl
->argv
[0], media
);
379 _print_bearer_opts();
382 static int cmd_bearer_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
383 struct cmdl
*cmdl
, void *data
)
388 char buf
[MNL_SOCKET_BUFFER_SIZE
];
389 struct nlattr
*props
;
390 struct nlattr
*attrs
;
391 struct opt opts
[] = {
397 struct tipc_sup_media sup_media
[] = {
398 { "udp", "name", cmd_bearer_set_udp_help
},
399 { "eth", "device", cmd_bearer_set_l2_help
},
400 { "ib", "device", cmd_bearer_set_l2_help
},
404 if (strcmp(cmd
->cmd
, "priority") == 0)
405 prop
= TIPC_NLA_PROP_PRIO
;
406 else if ((strcmp(cmd
->cmd
, "tolerance") == 0))
407 prop
= TIPC_NLA_PROP_TOL
;
408 else if ((strcmp(cmd
->cmd
, "window") == 0))
409 prop
= TIPC_NLA_PROP_WIN
;
413 if (cmdl
->optind
>= cmdl
->argc
) {
414 fprintf(stderr
, "error, missing value\n");
417 val
= atoi(shift_cmdl(cmdl
));
419 if (parse_opts(opts
, cmdl
) < 0)
422 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_SET
))) {
423 fprintf(stderr
, "error, message initialisation failed\n");
426 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
428 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_PROP
);
429 mnl_attr_put_u32(nlh
, prop
, val
);
430 mnl_attr_nest_end(nlh
, props
);
432 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
436 mnl_attr_nest_end(nlh
, attrs
);
438 return msg_doit(nlh
, NULL
, NULL
);
441 static int cmd_bearer_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
442 struct cmdl
*cmdl
, void *data
)
444 const struct cmd cmds
[] = {
445 { "priority", cmd_bearer_set_prop
, cmd_bearer_set_help
},
446 { "tolerance", cmd_bearer_set_prop
, cmd_bearer_set_help
},
447 { "window", cmd_bearer_set_prop
, cmd_bearer_set_help
},
451 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
454 static void cmd_bearer_get_help(struct cmdl
*cmdl
)
456 fprintf(stderr
, "Usage: %s bearer get OPTION media MEDIA ARGS...\n",
458 _print_bearer_opts();
459 _print_bearer_media();
462 static void cmd_bearer_get_udp_help(struct cmdl
*cmdl
, char *media
)
464 fprintf(stderr
, "Usage: %s bearer get OPTION media %s name NAME\n\n",
465 cmdl
->argv
[0], media
);
466 _print_bearer_opts();
469 static void cmd_bearer_get_l2_help(struct cmdl
*cmdl
, char *media
)
472 "Usage: %s bearer get OPTION media %s device DEVICE\n",
473 cmdl
->argv
[0], media
);
474 _print_bearer_opts();
477 static int bearer_get_cb(const struct nlmsghdr
*nlh
, void *data
)
480 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
481 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
482 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
483 struct nlattr
*props
[TIPC_NLA_PROP_MAX
+ 1] = {};
485 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
486 if (!info
[TIPC_NLA_BEARER
])
489 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
490 if (!attrs
[TIPC_NLA_BEARER_PROP
])
493 mnl_attr_parse_nested(attrs
[TIPC_NLA_BEARER_PROP
], parse_attrs
, props
);
497 printf("%u\n", mnl_attr_get_u32(props
[*prop
]));
502 static int cmd_bearer_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
503 struct cmdl
*cmdl
, void *data
)
507 char buf
[MNL_SOCKET_BUFFER_SIZE
];
508 struct nlattr
*attrs
;
509 struct opt opts
[] = {
515 struct tipc_sup_media sup_media
[] = {
516 { "udp", "name", cmd_bearer_get_udp_help
},
517 { "eth", "device", cmd_bearer_get_l2_help
},
518 { "ib", "device", cmd_bearer_get_l2_help
},
522 if (strcmp(cmd
->cmd
, "priority") == 0)
523 prop
= TIPC_NLA_PROP_PRIO
;
524 else if ((strcmp(cmd
->cmd
, "tolerance") == 0))
525 prop
= TIPC_NLA_PROP_TOL
;
526 else if ((strcmp(cmd
->cmd
, "window") == 0))
527 prop
= TIPC_NLA_PROP_WIN
;
531 if (parse_opts(opts
, cmdl
) < 0)
534 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
535 fprintf(stderr
, "error, message initialisation failed\n");
539 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
540 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
543 mnl_attr_nest_end(nlh
, attrs
);
545 return msg_doit(nlh
, bearer_get_cb
, &prop
);
548 static int cmd_bearer_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
549 struct cmdl
*cmdl
, void *data
)
551 const struct cmd cmds
[] = {
552 { "priority", cmd_bearer_get_prop
, cmd_bearer_get_help
},
553 { "tolerance", cmd_bearer_get_prop
, cmd_bearer_get_help
},
554 { "window", cmd_bearer_get_prop
, cmd_bearer_get_help
},
558 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
561 static int bearer_list_cb(const struct nlmsghdr
*nlh
, void *data
)
563 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
564 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
565 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
567 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
568 if (!info
[TIPC_NLA_BEARER
]) {
569 fprintf(stderr
, "No bearer in netlink response\n");
573 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
574 if (!attrs
[TIPC_NLA_BEARER_NAME
]) {
575 fprintf(stderr
, "Bearer name missing in netlink response\n");
579 printf("%s\n", mnl_attr_get_str(attrs
[TIPC_NLA_BEARER_NAME
]));
584 static int cmd_bearer_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
585 struct cmdl
*cmdl
, void *data
)
587 char buf
[MNL_SOCKET_BUFFER_SIZE
];
590 fprintf(stderr
, "Usage: %s bearer list\n", cmdl
->argv
[0]);
594 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
595 fprintf(stderr
, "error, message initialisation failed\n");
599 return msg_dumpit(nlh
, bearer_list_cb
, NULL
);
602 void cmd_bearer_help(struct cmdl
*cmdl
)
605 "Usage: %s bearer COMMAND [ARGS] ...\n"
608 " enable - Enable a bearer\n"
609 " disable - Disable a bearer\n"
610 " set - Set various bearer properties\n"
611 " get - Get various bearer properties\n"
612 " list - List bearers\n", cmdl
->argv
[0]);
615 int cmd_bearer(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
618 const struct cmd cmds
[] = {
619 { "disable", cmd_bearer_disable
, cmd_bearer_disable_help
},
620 { "enable", cmd_bearer_enable
, cmd_bearer_enable_help
},
621 { "get", cmd_bearer_get
, cmd_bearer_get_help
},
622 { "list", cmd_bearer_list
, NULL
},
623 { "set", cmd_bearer_set
, cmd_bearer_set_help
},
627 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);