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>
17 #include <arpa/inet.h>
19 #include <linux/tipc_netlink.h>
20 #include <linux/tipc.h>
21 #include <linux/genetlink.h>
23 #include <libmnl/libmnl.h>
24 #include <sys/socket.h>
31 #define UDP_PROP_PORT 2
39 static void _print_bearer_opts(void)
43 " priority - Bearer link priority\n"
44 " tolerance - Bearer link tolerance\n"
45 " window - Bearer link window\n");
48 static void _print_bearer_media(void)
52 " udp - User Datagram Protocol\n"
57 static void cmd_bearer_enable_l2_help(struct cmdl
*cmdl
, char *media
)
60 "Usage: %s bearer enable media %s device DEVICE [OPTIONS]\n"
62 " domain DOMAIN - Discovery domain\n"
63 " priority PRIORITY - Bearer priority\n",
64 cmdl
->argv
[0], media
);
67 static void cmd_bearer_enable_udp_help(struct cmdl
*cmdl
, char *media
)
70 "Usage: %s bearer enable [OPTIONS] media %s name NAME localip IP [UDP OPTIONS]\n\n",
71 cmdl
->argv
[0], media
);
74 " domain DOMAIN - Discovery domain\n"
75 " priority PRIORITY - Bearer priority\n\n");
78 " localport PORT - Local UDP port (default 6118)\n"
79 " remoteip IP - Remote IP address\n"
80 " remoteport PORT - Remote UDP port (default 6118)\n");
83 static int get_netid_cb(const struct nlmsghdr
*nlh
, void *data
)
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
;
90 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
91 if (!info
[TIPC_NLA_NET
])
93 mnl_attr_parse_nested(info
[TIPC_NLA_NET
], parse_attrs
, attrs
);
94 if (!attrs
[TIPC_NLA_NET_ID
])
96 *netid
= mnl_attr_get_u32(attrs
[TIPC_NLA_NET_ID
]);
101 static int generate_multicast(short af
, char *buf
, int bufsize
)
104 char mnl_msg
[MNL_SOCKET_BUFFER_SIZE
];
105 struct nlmsghdr
*nlh
;
107 if (!(nlh
= msg_init(mnl_msg
, TIPC_NL_NET_GET
))) {
108 fprintf(stderr
, "error, message initialization failed\n");
111 if (msg_dumpit(nlh
, get_netid_cb
, &netid
)) {
112 fprintf(stderr
, "error, failed to fetch TIPC network id from kernel\n");
116 snprintf(buf
, bufsize
, "228.0.%u.%u", (netid
>>8) & 0xFF, netid
& 0xFF);
118 snprintf(buf
, bufsize
, "ff02::%u", netid
);
123 static int nl_add_udp_enable_opts(struct nlmsghdr
*nlh
, struct opt
*opts
,
129 char buf
[INET6_ADDRSTRLEN
];
130 char *locport
= "6118";
131 char *remport
= "6118";
134 struct addrinfo
*loc
= NULL
;
135 struct addrinfo
*rem
= NULL
;
136 struct addrinfo hints
= {
137 .ai_family
= AF_UNSPEC
,
138 .ai_socktype
= SOCK_DGRAM
141 if (!(opt
= get_opt(opts
, "localip"))) {
142 fprintf(stderr
, "error, udp bearer localip missing\n");
143 cmd_bearer_enable_udp_help(cmdl
, "udp");
148 if ((opt
= get_opt(opts
, "remoteip")))
151 if ((opt
= get_opt(opts
, "localport")))
154 if ((opt
= get_opt(opts
, "remoteport")))
157 if ((err
= getaddrinfo(locip
, locport
, &hints
, &loc
))) {
158 fprintf(stderr
, "UDP local address error: %s\n",
164 if (generate_multicast(loc
->ai_family
, buf
, sizeof(buf
))) {
165 fprintf(stderr
, "Failed to generate multicast address\n");
171 if ((err
= getaddrinfo(remip
, remport
, &hints
, &rem
))) {
172 fprintf(stderr
, "UDP remote address error: %s\n",
178 if (rem
->ai_family
!= loc
->ai_family
) {
179 fprintf(stderr
, "UDP local and remote AF mismatch\n");
183 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_UDP_OPTS
);
184 mnl_attr_put(nlh
, TIPC_NLA_UDP_LOCAL
, loc
->ai_addrlen
, loc
->ai_addr
);
185 mnl_attr_put(nlh
, TIPC_NLA_UDP_REMOTE
, rem
->ai_addrlen
, rem
->ai_addr
);
186 mnl_attr_nest_end(nlh
, nest
);
194 static int nl_add_bearer_name(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
195 struct cmdl
*cmdl
, struct opt
*opts
,
196 struct tipc_sup_media sup_media
[])
198 char id
[TIPC_MAX_BEARER_NAME
];
202 struct tipc_sup_media
*entry
;
204 if (!(opt
= get_opt(opts
, "media"))) {
208 fprintf(stderr
, "error, missing bearer media\n");
213 for (entry
= sup_media
; entry
->media
; entry
++) {
214 if (strcmp(entry
->media
, media
))
217 if (!(opt
= get_opt(opts
, entry
->identifier
))) {
219 (entry
->help
)(cmdl
, media
);
221 fprintf(stderr
, "error, missing bearer %s\n",
226 identifier
= opt
->val
;
227 snprintf(id
, sizeof(id
), "%s:%s", media
, identifier
);
228 mnl_attr_put_strz(nlh
, TIPC_NLA_BEARER_NAME
, id
);
233 fprintf(stderr
, "error, invalid media type %s\n", media
);
238 static void cmd_bearer_add_udp_help(struct cmdl
*cmdl
, char *media
)
240 fprintf(stderr
, "Usage: %s bearer add media %s name NAME remoteip REMOTEIP\n\n",
241 cmdl
->argv
[0], media
);
244 static void cmd_bearer_add_help(struct cmdl
*cmdl
)
246 fprintf(stderr
, "Usage: %s bearer add media udp name NAME remoteip REMOTEIP\n",
250 static int udp_bearer_add(struct nlmsghdr
*nlh
, struct opt
*opts
,
255 struct nlattr
*opts_nest
;
256 char *remport
= "6118";
258 opts_nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_UDP_OPTS
);
260 if ((opt
= get_opt(opts
, "remoteport")))
263 if ((opt
= get_opt(opts
, "remoteip"))) {
265 struct addrinfo
*addr
= NULL
;
266 struct addrinfo hints
= {
267 .ai_family
= AF_UNSPEC
,
268 .ai_socktype
= SOCK_DGRAM
271 if ((err
= getaddrinfo(ip
, remport
, &hints
, &addr
))) {
272 fprintf(stderr
, "UDP address error: %s\n",
278 mnl_attr_put(nlh
, TIPC_NLA_UDP_REMOTE
, addr
->ai_addrlen
,
282 fprintf(stderr
, "error, missing remoteip\n");
285 mnl_attr_nest_end(nlh
, opts_nest
);
290 static int cmd_bearer_add_media(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
291 struct cmdl
*cmdl
, void *data
)
295 char buf
[MNL_SOCKET_BUFFER_SIZE
];
297 struct nlattr
*attrs
;
298 struct opt opts
[] = {
299 { "remoteip", OPT_KEYVAL
, NULL
},
300 { "remoteport", OPT_KEYVAL
, NULL
},
301 { "name", OPT_KEYVAL
, NULL
},
302 { "media", OPT_KEYVAL
, NULL
},
305 struct tipc_sup_media sup_media
[] = {
306 { "udp", "name", cmd_bearer_add_udp_help
},
310 /* Rewind optind to include media in the option list */
312 if (parse_opts(opts
, cmdl
) < 0)
315 if (!(opt
= get_opt(opts
, "media"))) {
316 fprintf(stderr
, "error, missing media value\n");
321 if (strcmp(media
, "udp") != 0) {
322 fprintf(stderr
, "error, no \"%s\" media specific options available\n",
326 if (!(opt
= get_opt(opts
, "name"))) {
327 fprintf(stderr
, "error, missing media name\n");
331 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_ADD
))) {
332 fprintf(stderr
, "error, message initialisation failed\n");
336 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
337 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
341 err
= udp_bearer_add(nlh
, opts
, cmdl
);
345 mnl_attr_nest_end(nlh
, attrs
);
347 return msg_doit(nlh
, NULL
, NULL
);
350 static int cmd_bearer_add(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
351 struct cmdl
*cmdl
, void *data
)
353 const struct cmd cmds
[] = {
354 { "media", cmd_bearer_add_media
, cmd_bearer_add_help
},
358 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
361 static void cmd_bearer_enable_help(struct cmdl
*cmdl
)
364 "Usage: %s bearer enable [OPTIONS] media MEDIA ARGS...\n\n"
366 " domain DOMAIN - Discovery domain\n"
367 " priority PRIORITY - Bearer priority\n",
369 _print_bearer_media();
372 static int cmd_bearer_enable(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
373 struct cmdl
*cmdl
, void *data
)
378 char buf
[MNL_SOCKET_BUFFER_SIZE
];
379 struct opt opts
[] = {
380 { "device", OPT_KEYVAL
, NULL
},
381 { "domain", OPT_KEYVAL
, NULL
},
382 { "localip", OPT_KEYVAL
, NULL
},
383 { "localport", OPT_KEYVAL
, NULL
},
384 { "media", OPT_KEYVAL
, NULL
},
385 { "name", OPT_KEYVAL
, NULL
},
386 { "priority", OPT_KEYVAL
, NULL
},
387 { "remoteip", OPT_KEYVAL
, NULL
},
388 { "remoteport", OPT_KEYVAL
, NULL
},
391 struct tipc_sup_media sup_media
[] = {
392 { "udp", "name", cmd_bearer_enable_udp_help
},
393 { "eth", "device", cmd_bearer_enable_l2_help
},
394 { "ib", "device", cmd_bearer_enable_l2_help
},
398 if (parse_opts(opts
, cmdl
) < 0) {
404 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_ENABLE
))) {
405 fprintf(stderr
, "error: message initialisation failed\n");
408 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
410 if ((opt
= get_opt(opts
, "domain")))
411 mnl_attr_put_u32(nlh
, TIPC_NLA_BEARER_DOMAIN
, atoi(opt
->val
));
413 if ((opt
= get_opt(opts
, "priority"))) {
414 struct nlattr
*props
;
416 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_PROP
);
417 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_PRIO
, atoi(opt
->val
));
418 mnl_attr_nest_end(nlh
, props
);
421 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
425 opt
= get_opt(opts
, "media");
426 if (strcmp(opt
->val
, "udp") == 0) {
427 err
= nl_add_udp_enable_opts(nlh
, opts
, cmdl
);
431 mnl_attr_nest_end(nlh
, nest
);
433 return msg_doit(nlh
, NULL
, NULL
);
436 static void cmd_bearer_disable_l2_help(struct cmdl
*cmdl
, char *media
)
438 fprintf(stderr
, "Usage: %s bearer disable media %s device DEVICE\n",
439 cmdl
->argv
[0], media
);
442 static void cmd_bearer_disable_udp_help(struct cmdl
*cmdl
, char *media
)
444 fprintf(stderr
, "Usage: %s bearer disable media %s name NAME\n",
445 cmdl
->argv
[0], media
);
448 static void cmd_bearer_disable_help(struct cmdl
*cmdl
)
450 fprintf(stderr
, "Usage: %s bearer disable media MEDIA ARGS...\n",
452 _print_bearer_media();
455 static int cmd_bearer_disable(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
456 struct cmdl
*cmdl
, void *data
)
459 char buf
[MNL_SOCKET_BUFFER_SIZE
];
461 struct opt opts
[] = {
462 { "device", OPT_KEYVAL
, NULL
},
463 { "name", OPT_KEYVAL
, NULL
},
464 { "media", OPT_KEYVAL
, NULL
},
467 struct tipc_sup_media sup_media
[] = {
468 { "udp", "name", cmd_bearer_disable_udp_help
},
469 { "eth", "device", cmd_bearer_disable_l2_help
},
470 { "ib", "device", cmd_bearer_disable_l2_help
},
474 if (parse_opts(opts
, cmdl
) < 0) {
480 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_DISABLE
))) {
481 fprintf(stderr
, "error, message initialisation failed\n");
485 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
486 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
489 mnl_attr_nest_end(nlh
, nest
);
491 return msg_doit(nlh
, NULL
, NULL
);
495 static void cmd_bearer_set_help(struct cmdl
*cmdl
)
497 fprintf(stderr
, "Usage: %s bearer set OPTION media MEDIA ARGS...\n",
499 _print_bearer_opts();
500 _print_bearer_media();
503 static void cmd_bearer_set_udp_help(struct cmdl
*cmdl
, char *media
)
505 fprintf(stderr
, "Usage: %s bearer set OPTION media %s name NAME\n\n",
506 cmdl
->argv
[0], media
);
507 _print_bearer_opts();
510 static void cmd_bearer_set_l2_help(struct cmdl
*cmdl
, char *media
)
513 "Usage: %s bearer set [OPTION]... media %s device DEVICE\n",
514 cmdl
->argv
[0], media
);
515 _print_bearer_opts();
518 static int cmd_bearer_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
519 struct cmdl
*cmdl
, void *data
)
524 char buf
[MNL_SOCKET_BUFFER_SIZE
];
525 struct nlattr
*props
;
526 struct nlattr
*attrs
;
527 struct opt opts
[] = {
528 { "device", OPT_KEYVAL
, NULL
},
529 { "media", OPT_KEYVAL
, NULL
},
530 { "name", OPT_KEYVAL
, NULL
},
533 struct tipc_sup_media sup_media
[] = {
534 { "udp", "name", cmd_bearer_set_udp_help
},
535 { "eth", "device", cmd_bearer_set_l2_help
},
536 { "ib", "device", cmd_bearer_set_l2_help
},
540 if (strcmp(cmd
->cmd
, "priority") == 0)
541 prop
= TIPC_NLA_PROP_PRIO
;
542 else if ((strcmp(cmd
->cmd
, "tolerance") == 0))
543 prop
= TIPC_NLA_PROP_TOL
;
544 else if ((strcmp(cmd
->cmd
, "window") == 0))
545 prop
= TIPC_NLA_PROP_WIN
;
549 if (cmdl
->optind
>= cmdl
->argc
) {
550 fprintf(stderr
, "error, missing value\n");
553 val
= atoi(shift_cmdl(cmdl
));
555 if (parse_opts(opts
, cmdl
) < 0)
558 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_SET
))) {
559 fprintf(stderr
, "error, message initialisation failed\n");
562 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
564 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_PROP
);
565 mnl_attr_put_u32(nlh
, prop
, val
);
566 mnl_attr_nest_end(nlh
, props
);
568 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
572 mnl_attr_nest_end(nlh
, attrs
);
574 return msg_doit(nlh
, NULL
, NULL
);
577 static int cmd_bearer_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
578 struct cmdl
*cmdl
, void *data
)
580 const struct cmd cmds
[] = {
581 { "priority", cmd_bearer_set_prop
, cmd_bearer_set_help
},
582 { "tolerance", cmd_bearer_set_prop
, cmd_bearer_set_help
},
583 { "window", cmd_bearer_set_prop
, cmd_bearer_set_help
},
587 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
590 static void cmd_bearer_get_help(struct cmdl
*cmdl
)
592 fprintf(stderr
, "Usage: %s bearer get [OPTION] media MEDIA ARGS...\n",
594 _print_bearer_opts();
595 _print_bearer_media();
598 static void cmd_bearer_get_udp_help(struct cmdl
*cmdl
, char *media
)
600 fprintf(stderr
, "Usage: %s bearer get [OPTION] media %s name NAME [UDP OPTIONS]\n\n",
601 cmdl
->argv
[0], media
);
604 " remoteip - Remote ip address\n"
605 " remoteport - Remote port\n"
606 " localip - Local ip address\n"
607 " localport - Local port\n\n");
608 _print_bearer_opts();
611 static void cmd_bearer_get_l2_help(struct cmdl
*cmdl
, char *media
)
614 "Usage: %s bearer get OPTION media %s device DEVICE\n",
615 cmdl
->argv
[0], media
);
616 _print_bearer_opts();
620 static int bearer_dump_udp_cb(const struct nlmsghdr
*nlh
, void *data
)
622 struct sockaddr_storage
*addr
;
623 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
624 struct nlattr
*info
[TIPC_NLA_UDP_MAX
+ 1] = {};
626 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
628 if (!info
[TIPC_NLA_UDP_REMOTE
])
631 addr
= mnl_attr_get_payload(info
[TIPC_NLA_UDP_REMOTE
]);
633 if (addr
->ss_family
== AF_INET
) {
634 struct sockaddr_in
*ipv4
= (struct sockaddr_in
*) addr
;
636 printf("%s\n", inet_ntoa(ipv4
->sin_addr
));
637 } else if (addr
->ss_family
== AF_INET6
) {
638 char straddr
[INET6_ADDRSTRLEN
];
639 struct sockaddr_in6
*ipv6
= (struct sockaddr_in6
*) addr
;
641 if (!inet_ntop(AF_INET6
, &ipv6
->sin6_addr
, straddr
,
643 fprintf(stderr
, "error, parsing IPv6 addr\n");
646 printf("%s\n", straddr
);
655 static int bearer_get_udp_cb(const struct nlmsghdr
*nlh
, void *data
)
657 struct cb_data
*cb_data
= (struct cb_data
*) data
;
658 struct sockaddr_storage
*addr
;
659 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
660 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
661 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
662 struct nlattr
*opts
[TIPC_NLA_UDP_MAX
+ 1] = {};
664 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
665 if (!info
[TIPC_NLA_BEARER
])
668 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
669 if (!attrs
[TIPC_NLA_BEARER_UDP_OPTS
])
672 mnl_attr_parse_nested(attrs
[TIPC_NLA_BEARER_UDP_OPTS
], parse_attrs
, opts
);
673 if (!opts
[TIPC_NLA_UDP_LOCAL
])
676 if ((cb_data
->attr
== TIPC_NLA_UDP_REMOTE
) &&
677 (cb_data
->prop
== UDP_PROP_IP
) &&
678 opts
[TIPC_NLA_UDP_MULTI_REMOTEIP
]) {
679 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(cb_data
->nlh
);
681 genl
->cmd
= TIPC_NL_UDP_GET_REMOTEIP
;
682 return msg_dumpit(cb_data
->nlh
, bearer_dump_udp_cb
, NULL
);
685 addr
= mnl_attr_get_payload(opts
[cb_data
->attr
]);
687 if (addr
->ss_family
== AF_INET
) {
688 struct sockaddr_in
*ipv4
= (struct sockaddr_in
*) addr
;
690 switch (cb_data
->prop
) {
692 printf("%s\n", inet_ntoa(ipv4
->sin_addr
));
695 printf("%u\n", ntohs(ipv4
->sin_port
));
701 } else if (addr
->ss_family
== AF_INET6
) {
702 char straddr
[INET6_ADDRSTRLEN
];
703 struct sockaddr_in6
*ipv6
= (struct sockaddr_in6
*) addr
;
705 switch (cb_data
->prop
) {
707 if (!inet_ntop(AF_INET6
, &ipv6
->sin6_addr
, straddr
,
709 fprintf(stderr
, "error, parsing IPv6 addr\n");
712 printf("%s\n", straddr
);
715 printf("%u\n", ntohs(ipv6
->sin6_port
));
728 static int bearer_get_cb(const struct nlmsghdr
*nlh
, void *data
)
731 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
732 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
733 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
734 struct nlattr
*props
[TIPC_NLA_PROP_MAX
+ 1] = {};
736 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
737 if (!info
[TIPC_NLA_BEARER
])
740 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
741 if (!attrs
[TIPC_NLA_BEARER_PROP
])
744 mnl_attr_parse_nested(attrs
[TIPC_NLA_BEARER_PROP
], parse_attrs
, props
);
748 printf("%u\n", mnl_attr_get_u32(props
[*prop
]));
753 static int cmd_bearer_get_media(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
754 struct cmdl
*cmdl
, void *data
)
758 char buf
[MNL_SOCKET_BUFFER_SIZE
];
760 struct cb_data cb_data
= {0};
761 struct nlattr
*attrs
;
762 struct opt opts
[] = {
763 { "localip", OPT_KEY
, NULL
},
764 { "localport", OPT_KEY
, NULL
},
765 { "remoteip", OPT_KEY
, NULL
},
766 { "remoteport", OPT_KEY
, NULL
},
767 { "name", OPT_KEYVAL
, NULL
},
768 { "media", OPT_KEYVAL
, NULL
},
771 struct tipc_sup_media sup_media
[] = {
772 { "udp", "name", cmd_bearer_get_udp_help
},
776 /* Rewind optind to include media in the option list */
778 if (parse_opts(opts
, cmdl
) < 0)
781 if (!(opt
= get_opt(opts
, "media"))) {
782 fprintf(stderr
, "error, missing media value\n");
788 cmd_bearer_get_udp_help(cmdl
, media
);
791 if (strcmp(media
, "udp") != 0) {
792 fprintf(stderr
, "error, no \"%s\" media specific options\n", media
);
795 if (!(opt
= get_opt(opts
, "name"))) {
796 fprintf(stderr
, "error, missing media name\n");
800 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
801 fprintf(stderr
, "error, message initialisation failed\n");
805 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
806 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
809 mnl_attr_nest_end(nlh
, attrs
);
812 if (has_opt(opts
, "localip")) {
813 cb_data
.attr
= TIPC_NLA_UDP_LOCAL
;
814 cb_data
.prop
= UDP_PROP_IP
;
815 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
816 } else if (has_opt(opts
, "localport")) {
817 cb_data
.attr
= TIPC_NLA_UDP_LOCAL
;
818 cb_data
.prop
= UDP_PROP_PORT
;
819 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
820 } else if (has_opt(opts
, "remoteip")) {
821 cb_data
.attr
= TIPC_NLA_UDP_REMOTE
;
822 cb_data
.prop
= UDP_PROP_IP
;
823 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
824 } else if (has_opt(opts
, "remoteport")) {
825 cb_data
.attr
= TIPC_NLA_UDP_REMOTE
;
826 cb_data
.prop
= UDP_PROP_PORT
;
827 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
829 fprintf(stderr
, "error, missing UDP option\n");
833 static int cmd_bearer_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
834 struct cmdl
*cmdl
, void *data
)
838 char buf
[MNL_SOCKET_BUFFER_SIZE
];
839 struct nlattr
*attrs
;
840 struct opt opts
[] = {
841 { "device", OPT_KEYVAL
, NULL
},
842 { "media", OPT_KEYVAL
, NULL
},
843 { "name", OPT_KEYVAL
, NULL
},
846 struct tipc_sup_media sup_media
[] = {
847 { "udp", "name", cmd_bearer_get_udp_help
},
848 { "eth", "device", cmd_bearer_get_l2_help
},
849 { "ib", "device", cmd_bearer_get_l2_help
},
858 if (strcmp(cmd
->cmd
, "priority") == 0)
859 prop
= TIPC_NLA_PROP_PRIO
;
860 else if ((strcmp(cmd
->cmd
, "tolerance") == 0))
861 prop
= TIPC_NLA_PROP_TOL
;
862 else if ((strcmp(cmd
->cmd
, "window") == 0))
863 prop
= TIPC_NLA_PROP_WIN
;
867 if (parse_opts(opts
, cmdl
) < 0)
870 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
871 fprintf(stderr
, "error, message initialisation failed\n");
875 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
876 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
879 mnl_attr_nest_end(nlh
, attrs
);
881 return msg_doit(nlh
, bearer_get_cb
, &prop
);
884 static int cmd_bearer_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
885 struct cmdl
*cmdl
, void *data
)
887 const struct cmd cmds
[] = {
888 { "priority", cmd_bearer_get_prop
, cmd_bearer_get_help
},
889 { "tolerance", cmd_bearer_get_prop
, cmd_bearer_get_help
},
890 { "window", cmd_bearer_get_prop
, cmd_bearer_get_help
},
891 { "media", cmd_bearer_get_media
, cmd_bearer_get_help
},
895 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
898 static int bearer_list_cb(const struct nlmsghdr
*nlh
, void *data
)
900 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
901 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
902 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
904 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
905 if (!info
[TIPC_NLA_BEARER
]) {
906 fprintf(stderr
, "No bearer in netlink response\n");
910 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
911 if (!attrs
[TIPC_NLA_BEARER_NAME
]) {
912 fprintf(stderr
, "Bearer name missing in netlink response\n");
916 printf("%s\n", mnl_attr_get_str(attrs
[TIPC_NLA_BEARER_NAME
]));
921 static int cmd_bearer_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
922 struct cmdl
*cmdl
, void *data
)
924 char buf
[MNL_SOCKET_BUFFER_SIZE
];
927 fprintf(stderr
, "Usage: %s bearer list\n", cmdl
->argv
[0]);
931 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
932 fprintf(stderr
, "error, message initialisation failed\n");
936 return msg_dumpit(nlh
, bearer_list_cb
, NULL
);
939 void cmd_bearer_help(struct cmdl
*cmdl
)
942 "Usage: %s bearer COMMAND [ARGS] ...\n"
945 " add - Add data to existing bearer\n"
946 " enable - Enable a bearer\n"
947 " disable - Disable a bearer\n"
948 " set - Set various bearer properties\n"
949 " get - Get various bearer properties\n"
950 " list - List bearers\n", cmdl
->argv
[0]);
953 int cmd_bearer(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
956 const struct cmd cmds
[] = {
957 { "add", cmd_bearer_add
, cmd_bearer_add_help
},
958 { "disable", cmd_bearer_disable
, cmd_bearer_disable_help
},
959 { "enable", cmd_bearer_enable
, cmd_bearer_enable_help
},
960 { "get", cmd_bearer_get
, cmd_bearer_get_help
},
961 { "list", cmd_bearer_list
, NULL
},
962 { "set", cmd_bearer_set
, cmd_bearer_set_help
},
966 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);