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>
24 #include <libmnl/libmnl.h>
25 #include <sys/socket.h>
33 #define UDP_PROP_PORT 2
41 static void _print_bearer_opts(void)
45 " priority - Bearer link priority\n"
46 " tolerance - Bearer link tolerance\n"
47 " window - Bearer link window\n"
48 " mtu - Bearer link mtu\n");
51 void print_bearer_media(void)
55 " udp - User Datagram Protocol\n"
60 static void cmd_bearer_enable_l2_help(struct cmdl
*cmdl
, char *media
)
63 "Usage: %s bearer enable media %s device DEVICE [OPTIONS]\n"
65 " domain DOMAIN - Discovery domain\n"
66 " priority PRIORITY - Bearer priority\n",
67 cmdl
->argv
[0], media
);
70 static void cmd_bearer_enable_udp_help(struct cmdl
*cmdl
, char *media
)
73 "Usage: %s bearer enable [OPTIONS] media %s name NAME [localip IP|device DEVICE] [UDP OPTIONS]\n\n"
75 " domain DOMAIN - Discovery domain\n"
76 " 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",
81 cmdl
->argv
[0], media
);
84 static int get_netid_cb(const struct nlmsghdr
*nlh
, void *data
)
86 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
87 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
88 struct nlattr
*attrs
[TIPC_NLA_NET_MAX
+ 1] = {};
89 int *netid
= (int*)data
;
91 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
92 if (!info
[TIPC_NLA_NET
])
94 mnl_attr_parse_nested(info
[TIPC_NLA_NET
], parse_attrs
, attrs
);
95 if (!attrs
[TIPC_NLA_NET_ID
])
97 *netid
= mnl_attr_get_u32(attrs
[TIPC_NLA_NET_ID
]);
102 static int generate_multicast(short af
, char *buf
, int bufsize
)
105 char mnl_msg
[MNL_SOCKET_BUFFER_SIZE
];
106 struct nlmsghdr
*nlh
;
108 if (!(nlh
= msg_init(mnl_msg
, TIPC_NL_NET_GET
))) {
109 fprintf(stderr
, "error, message initialization failed\n");
112 if (msg_dumpit(nlh
, get_netid_cb
, &netid
)) {
113 fprintf(stderr
, "error, failed to fetch TIPC network id from kernel\n");
117 snprintf(buf
, bufsize
, "228.0.%u.%u", (netid
>>8) & 0xFF, netid
& 0xFF);
119 snprintf(buf
, bufsize
, "ff02::%u", netid
);
124 static struct ifreq ifr
;
125 static int nl_dump_req_filter(struct nlmsghdr
*nlh
, int reqlen
)
127 struct ifaddrmsg
*ifa
= NLMSG_DATA(nlh
);
129 ifa
->ifa_index
= ifr
.ifr_ifindex
;
134 static int nl_dump_addr_filter(struct nlmsghdr
*nlh
, void *arg
)
136 struct ifaddrmsg
*ifa
= NLMSG_DATA(nlh
);
137 char *r_addr
= (char *)arg
;
138 int len
= nlh
->nlmsg_len
;
139 struct rtattr
*addr_attr
;
141 if (ifr
.ifr_ifindex
!= ifa
->ifa_index
)
144 if (strlen(r_addr
) > 0)
147 addr_attr
= parse_rtattr_one(IFA_ADDRESS
, IFA_RTA(ifa
),
148 len
- NLMSG_LENGTH(sizeof(*ifa
)));
152 if (ifa
->ifa_family
== AF_INET
) {
153 struct sockaddr_in ip4addr
;
154 memcpy(&ip4addr
.sin_addr
, RTA_DATA(addr_attr
),
155 sizeof(struct in_addr
));
156 inet_ntop(AF_INET
, &ip4addr
.sin_addr
, r_addr
,
158 } else if (ifa
->ifa_family
== AF_INET6
) {
159 struct sockaddr_in6 ip6addr
;
160 memcpy(&ip6addr
.sin6_addr
, RTA_DATA(addr_attr
),
161 sizeof(struct in6_addr
));
162 inet_ntop(AF_INET6
, &ip6addr
.sin6_addr
, r_addr
,
168 static int cmd_bearer_validate_and_get_addr(const char *name
, char *r_addr
)
170 struct rtnl_handle rth
= { .fd
= -1 };
173 memset(&ifr
, 0, sizeof(ifr
));
174 if (!name
|| !r_addr
|| get_ifname(ifr
.ifr_name
, name
))
177 ifr
.ifr_ifindex
= ll_name_to_index(ifr
.ifr_name
);
178 if (!ifr
.ifr_ifindex
)
181 /* remove from cache */
182 ll_drop_by_index(ifr
.ifr_ifindex
);
184 if ((err
= rtnl_open(&rth
, 0)) < 0)
187 if ((err
= rtnl_addrdump_req(&rth
, AF_UNSPEC
, nl_dump_req_filter
)) > 0)
188 err
= rtnl_dump_filter(&rth
, nl_dump_addr_filter
, r_addr
);
194 static int nl_add_udp_enable_opts(struct nlmsghdr
*nlh
, struct opt
*opts
,
200 char buf
[INET6_ADDRSTRLEN
];
201 char *locport
= "6118";
202 char *remport
= "6118";
205 struct addrinfo
*loc
= NULL
;
206 struct addrinfo
*rem
= NULL
;
207 struct addrinfo hints
= {
208 .ai_family
= AF_UNSPEC
,
209 .ai_socktype
= SOCK_DGRAM
211 char addr
[INET6_ADDRSTRLEN
] = {0};
213 opt
= get_opt(opts
, "device");
214 if (opt
&& cmd_bearer_validate_and_get_addr(opt
->val
, addr
) < 0) {
215 fprintf(stderr
, "error, no device name available\n");
219 if (strlen(addr
) > 0) {
222 opt
= get_opt(opts
, "localip");
224 fprintf(stderr
, "error, udp bearer localip/device missing\n");
225 cmd_bearer_enable_udp_help(cmdl
, "udp");
231 if ((opt
= get_opt(opts
, "remoteip")))
234 if ((opt
= get_opt(opts
, "localport")))
237 if ((opt
= get_opt(opts
, "remoteport")))
240 if ((err
= getaddrinfo(locip
, locport
, &hints
, &loc
))) {
241 fprintf(stderr
, "UDP local address error: %s\n",
247 if (generate_multicast(loc
->ai_family
, buf
, sizeof(buf
))) {
248 fprintf(stderr
, "Failed to generate multicast address\n");
255 if ((err
= getaddrinfo(remip
, remport
, &hints
, &rem
))) {
256 fprintf(stderr
, "UDP remote address error: %s\n",
262 if (rem
->ai_family
!= loc
->ai_family
) {
263 fprintf(stderr
, "UDP local and remote AF mismatch\n");
269 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_UDP_OPTS
);
270 mnl_attr_put(nlh
, TIPC_NLA_UDP_LOCAL
, loc
->ai_addrlen
, loc
->ai_addr
);
271 mnl_attr_put(nlh
, TIPC_NLA_UDP_REMOTE
, rem
->ai_addrlen
, rem
->ai_addr
);
272 mnl_attr_nest_end(nlh
, nest
);
280 static char *cmd_get_media_type(const struct cmd
*cmd
, struct cmdl
*cmdl
,
283 struct opt
*opt
= get_opt(opts
, "media");
289 fprintf(stderr
, "error, missing bearer media\n");
295 static int nl_add_bearer_name(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
296 struct cmdl
*cmdl
, struct opt
*opts
,
297 const struct tipc_sup_media
*sup_media
)
299 char bname
[TIPC_MAX_BEARER_NAME
];
302 if ((err
= cmd_get_unique_bearer_name(cmd
, cmdl
, opts
, bname
, sup_media
)))
305 mnl_attr_put_strz(nlh
, TIPC_NLA_BEARER_NAME
, bname
);
309 int cmd_get_unique_bearer_name(const struct cmd
*cmd
, struct cmdl
*cmdl
,
310 struct opt
*opts
, char *bname
,
311 const struct tipc_sup_media
*sup_media
)
316 const struct tipc_sup_media
*entry
;
318 if (!(media
= cmd_get_media_type(cmd
, cmdl
, opts
)))
321 for (entry
= sup_media
; entry
->media
; entry
++) {
322 if (strcmp(entry
->media
, media
))
325 if (!(opt
= get_opt(opts
, entry
->identifier
))) {
327 (entry
->help
)(cmdl
, media
);
329 fprintf(stderr
, "error, missing bearer %s\n",
334 identifier
= opt
->val
;
335 snprintf(bname
, TIPC_MAX_BEARER_NAME
, "%s:%s", media
, identifier
);
340 fprintf(stderr
, "error, invalid media type %s\n", media
);
345 static void cmd_bearer_add_udp_help(struct cmdl
*cmdl
, char *media
)
347 fprintf(stderr
, "Usage: %s bearer add media %s name NAME remoteip REMOTEIP\n\n",
348 cmdl
->argv
[0], media
);
351 static void cmd_bearer_add_help(struct cmdl
*cmdl
)
353 fprintf(stderr
, "Usage: %s bearer add media udp name NAME remoteip REMOTEIP\n",
357 static int udp_bearer_add(struct nlmsghdr
*nlh
, struct opt
*opts
,
362 struct nlattr
*opts_nest
;
363 char *remport
= "6118";
365 opts_nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_UDP_OPTS
);
367 if ((opt
= get_opt(opts
, "remoteport")))
370 if ((opt
= get_opt(opts
, "remoteip"))) {
372 struct addrinfo
*addr
= NULL
;
373 struct addrinfo hints
= {
374 .ai_family
= AF_UNSPEC
,
375 .ai_socktype
= SOCK_DGRAM
378 if ((err
= getaddrinfo(ip
, remport
, &hints
, &addr
))) {
379 fprintf(stderr
, "UDP address error: %s\n",
385 mnl_attr_put(nlh
, TIPC_NLA_UDP_REMOTE
, addr
->ai_addrlen
,
389 fprintf(stderr
, "error, missing remoteip\n");
392 mnl_attr_nest_end(nlh
, opts_nest
);
397 static int cmd_bearer_add_media(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
398 struct cmdl
*cmdl
, void *data
)
402 char buf
[MNL_SOCKET_BUFFER_SIZE
];
404 struct nlattr
*attrs
;
405 struct opt opts
[] = {
406 { "remoteip", OPT_KEYVAL
, NULL
},
407 { "remoteport", OPT_KEYVAL
, NULL
},
408 { "name", OPT_KEYVAL
, NULL
},
409 { "media", OPT_KEYVAL
, NULL
},
412 const struct tipc_sup_media sup_media
[] = {
413 { "udp", "name", cmd_bearer_add_udp_help
},
417 /* Rewind optind to include media in the option list */
419 if (parse_opts(opts
, cmdl
) < 0)
422 if (!(opt
= get_opt(opts
, "media"))) {
423 fprintf(stderr
, "error, missing media value\n");
428 if (strcmp(media
, "udp") != 0) {
429 fprintf(stderr
, "error, no \"%s\" media specific options available\n",
433 if (!(opt
= get_opt(opts
, "name"))) {
434 fprintf(stderr
, "error, missing media name\n");
438 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_ADD
))) {
439 fprintf(stderr
, "error, message initialisation failed\n");
443 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
444 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
448 err
= udp_bearer_add(nlh
, opts
, cmdl
);
452 mnl_attr_nest_end(nlh
, attrs
);
454 return msg_doit(nlh
, NULL
, NULL
);
457 static int cmd_bearer_add(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
458 struct cmdl
*cmdl
, void *data
)
460 const struct cmd cmds
[] = {
461 { "media", cmd_bearer_add_media
, cmd_bearer_add_help
},
465 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
468 static void cmd_bearer_enable_help(struct cmdl
*cmdl
)
471 "Usage: %s bearer enable [OPTIONS] media MEDIA ARGS...\n\n"
473 " domain DOMAIN - Discovery domain\n"
474 " priority PRIORITY - Bearer priority\n",
476 print_bearer_media();
479 static int cmd_bearer_enable(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
480 struct cmdl
*cmdl
, void *data
)
485 char buf
[MNL_SOCKET_BUFFER_SIZE
];
486 struct opt opts
[] = {
487 { "device", OPT_KEYVAL
, NULL
},
488 { "domain", OPT_KEYVAL
, NULL
},
489 { "localip", OPT_KEYVAL
, NULL
},
490 { "localport", OPT_KEYVAL
, NULL
},
491 { "media", OPT_KEYVAL
, NULL
},
492 { "name", OPT_KEYVAL
, NULL
},
493 { "priority", OPT_KEYVAL
, NULL
},
494 { "remoteip", OPT_KEYVAL
, NULL
},
495 { "remoteport", OPT_KEYVAL
, NULL
},
498 struct tipc_sup_media sup_media
[] = {
499 { "udp", "name", cmd_bearer_enable_udp_help
},
500 { "eth", "device", cmd_bearer_enable_l2_help
},
501 { "ib", "device", cmd_bearer_enable_l2_help
},
505 if (parse_opts(opts
, cmdl
) < 0) {
511 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_ENABLE
))) {
512 fprintf(stderr
, "error: message initialisation failed\n");
515 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
517 if ((opt
= get_opt(opts
, "domain")))
518 mnl_attr_put_u32(nlh
, TIPC_NLA_BEARER_DOMAIN
, atoi(opt
->val
));
520 if ((opt
= get_opt(opts
, "priority"))) {
521 struct nlattr
*props
;
523 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_PROP
);
524 mnl_attr_put_u32(nlh
, TIPC_NLA_PROP_PRIO
, atoi(opt
->val
));
525 mnl_attr_nest_end(nlh
, props
);
528 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
532 opt
= get_opt(opts
, "media");
533 if (opt
&& strcmp(opt
->val
, "udp") == 0) {
534 err
= nl_add_udp_enable_opts(nlh
, opts
, cmdl
);
538 mnl_attr_nest_end(nlh
, nest
);
540 return msg_doit(nlh
, NULL
, NULL
);
543 static void cmd_bearer_disable_l2_help(struct cmdl
*cmdl
, char *media
)
545 fprintf(stderr
, "Usage: %s bearer disable media %s device DEVICE\n",
546 cmdl
->argv
[0], media
);
549 static void cmd_bearer_disable_udp_help(struct cmdl
*cmdl
, char *media
)
551 fprintf(stderr
, "Usage: %s bearer disable media %s name NAME\n",
552 cmdl
->argv
[0], media
);
555 static void cmd_bearer_disable_help(struct cmdl
*cmdl
)
557 fprintf(stderr
, "Usage: %s bearer disable media MEDIA ARGS...\n",
559 print_bearer_media();
562 static int cmd_bearer_disable(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
563 struct cmdl
*cmdl
, void *data
)
566 char buf
[MNL_SOCKET_BUFFER_SIZE
];
568 struct opt opts
[] = {
569 { "device", OPT_KEYVAL
, NULL
},
570 { "name", OPT_KEYVAL
, NULL
},
571 { "media", OPT_KEYVAL
, NULL
},
574 struct tipc_sup_media sup_media
[] = {
575 { "udp", "name", cmd_bearer_disable_udp_help
},
576 { "eth", "device", cmd_bearer_disable_l2_help
},
577 { "ib", "device", cmd_bearer_disable_l2_help
},
581 if (parse_opts(opts
, cmdl
) < 0) {
587 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_DISABLE
))) {
588 fprintf(stderr
, "error, message initialisation failed\n");
592 nest
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
593 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
596 mnl_attr_nest_end(nlh
, nest
);
598 return msg_doit(nlh
, NULL
, NULL
);
602 static void cmd_bearer_set_help(struct cmdl
*cmdl
)
604 fprintf(stderr
, "Usage: %s bearer set OPTION media MEDIA ARGS...\n",
606 _print_bearer_opts();
607 print_bearer_media();
610 static void cmd_bearer_set_udp_help(struct cmdl
*cmdl
, char *media
)
612 fprintf(stderr
, "Usage: %s bearer set OPTION media %s name NAME\n\n",
613 cmdl
->argv
[0], media
);
614 _print_bearer_opts();
617 static void cmd_bearer_set_l2_help(struct cmdl
*cmdl
, char *media
)
620 "Usage: %s bearer set [OPTION]... media %s device DEVICE\n",
621 cmdl
->argv
[0], media
);
622 _print_bearer_opts();
625 static int cmd_bearer_set_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
626 struct cmdl
*cmdl
, void *data
)
631 char buf
[MNL_SOCKET_BUFFER_SIZE
];
632 struct nlattr
*props
;
633 struct nlattr
*attrs
;
634 struct opt opts
[] = {
635 { "device", OPT_KEYVAL
, NULL
},
636 { "media", OPT_KEYVAL
, NULL
},
637 { "name", OPT_KEYVAL
, NULL
},
640 struct tipc_sup_media sup_media
[] = {
641 { "udp", "name", cmd_bearer_set_udp_help
},
642 { "eth", "device", cmd_bearer_set_l2_help
},
643 { "ib", "device", cmd_bearer_set_l2_help
},
647 if (strcmp(cmd
->cmd
, "priority") == 0)
648 prop
= TIPC_NLA_PROP_PRIO
;
649 else if ((strcmp(cmd
->cmd
, "tolerance") == 0))
650 prop
= TIPC_NLA_PROP_TOL
;
651 else if ((strcmp(cmd
->cmd
, "window") == 0))
652 prop
= TIPC_NLA_PROP_WIN
;
653 else if ((strcmp(cmd
->cmd
, "mtu") == 0))
654 prop
= TIPC_NLA_PROP_MTU
;
658 if (cmdl
->optind
>= cmdl
->argc
) {
659 fprintf(stderr
, "error, missing value\n");
662 val
= atoi(shift_cmdl(cmdl
));
664 if (parse_opts(opts
, cmdl
) < 0)
667 if (prop
== TIPC_NLA_PROP_MTU
) {
668 char *media
= cmd_get_media_type(cmd
, cmdl
, opts
);
672 else if (strcmp(media
, "udp")) {
673 fprintf(stderr
, "error, not supported for media\n");
678 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_SET
))) {
679 fprintf(stderr
, "error, message initialisation failed\n");
682 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
684 props
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER_PROP
);
685 mnl_attr_put_u32(nlh
, prop
, val
);
686 mnl_attr_nest_end(nlh
, props
);
688 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
692 mnl_attr_nest_end(nlh
, attrs
);
694 return msg_doit(nlh
, NULL
, NULL
);
697 static int cmd_bearer_set(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
698 struct cmdl
*cmdl
, void *data
)
700 const struct cmd cmds
[] = {
701 { "priority", cmd_bearer_set_prop
, cmd_bearer_set_help
},
702 { "tolerance", cmd_bearer_set_prop
, cmd_bearer_set_help
},
703 { "window", cmd_bearer_set_prop
, cmd_bearer_set_help
},
704 { "mtu", cmd_bearer_set_prop
, cmd_bearer_set_help
},
708 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
711 static void cmd_bearer_get_help(struct cmdl
*cmdl
)
713 fprintf(stderr
, "Usage: %s bearer get [OPTION] media MEDIA ARGS...\n",
715 _print_bearer_opts();
716 print_bearer_media();
719 static void cmd_bearer_get_udp_help(struct cmdl
*cmdl
, char *media
)
721 fprintf(stderr
, "Usage: %s bearer get [OPTION] media %s name NAME [UDP OPTIONS]\n\n",
722 cmdl
->argv
[0], media
);
725 " remoteip - Remote ip address\n"
726 " remoteport - Remote port\n"
727 " localip - Local ip address\n"
728 " localport - Local port\n\n");
729 _print_bearer_opts();
732 static void cmd_bearer_get_l2_help(struct cmdl
*cmdl
, char *media
)
735 "Usage: %s bearer get OPTION media %s device DEVICE\n",
736 cmdl
->argv
[0], media
);
737 _print_bearer_opts();
741 static int bearer_dump_udp_cb(const struct nlmsghdr
*nlh
, void *data
)
743 struct sockaddr_storage
*addr
;
744 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
745 struct nlattr
*info
[TIPC_NLA_UDP_MAX
+ 1] = {};
747 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
749 if (!info
[TIPC_NLA_UDP_REMOTE
])
752 addr
= mnl_attr_get_payload(info
[TIPC_NLA_UDP_REMOTE
]);
754 if (addr
->ss_family
== AF_INET
) {
755 struct sockaddr_in
*ipv4
= (struct sockaddr_in
*) addr
;
757 printf("%s\n", inet_ntoa(ipv4
->sin_addr
));
758 } else if (addr
->ss_family
== AF_INET6
) {
759 char straddr
[INET6_ADDRSTRLEN
];
760 struct sockaddr_in6
*ipv6
= (struct sockaddr_in6
*) addr
;
762 if (!inet_ntop(AF_INET6
, &ipv6
->sin6_addr
, straddr
,
764 fprintf(stderr
, "error, parsing IPv6 addr\n");
767 printf("%s\n", straddr
);
776 static int bearer_get_udp_cb(const struct nlmsghdr
*nlh
, void *data
)
778 struct cb_data
*cb_data
= (struct cb_data
*) data
;
779 struct sockaddr_storage
*addr
;
780 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
781 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
782 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
783 struct nlattr
*opts
[TIPC_NLA_UDP_MAX
+ 1] = {};
785 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
786 if (!info
[TIPC_NLA_BEARER
])
789 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
790 if (!attrs
[TIPC_NLA_BEARER_UDP_OPTS
])
793 mnl_attr_parse_nested(attrs
[TIPC_NLA_BEARER_UDP_OPTS
], parse_attrs
, opts
);
794 if (!opts
[TIPC_NLA_UDP_LOCAL
])
797 if ((cb_data
->attr
== TIPC_NLA_UDP_REMOTE
) &&
798 (cb_data
->prop
== UDP_PROP_IP
) &&
799 opts
[TIPC_NLA_UDP_MULTI_REMOTEIP
]) {
800 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(cb_data
->nlh
);
802 genl
->cmd
= TIPC_NL_UDP_GET_REMOTEIP
;
803 return msg_dumpit(cb_data
->nlh
, bearer_dump_udp_cb
, NULL
);
806 addr
= mnl_attr_get_payload(opts
[cb_data
->attr
]);
808 if (addr
->ss_family
== AF_INET
) {
809 struct sockaddr_in
*ipv4
= (struct sockaddr_in
*) addr
;
811 switch (cb_data
->prop
) {
813 printf("%s\n", inet_ntoa(ipv4
->sin_addr
));
816 printf("%u\n", ntohs(ipv4
->sin_port
));
822 } else if (addr
->ss_family
== AF_INET6
) {
823 char straddr
[INET6_ADDRSTRLEN
];
824 struct sockaddr_in6
*ipv6
= (struct sockaddr_in6
*) addr
;
826 switch (cb_data
->prop
) {
828 if (!inet_ntop(AF_INET6
, &ipv6
->sin6_addr
, straddr
,
830 fprintf(stderr
, "error, parsing IPv6 addr\n");
833 printf("%s\n", straddr
);
836 printf("%u\n", ntohs(ipv6
->sin6_port
));
849 static int bearer_get_cb(const struct nlmsghdr
*nlh
, void *data
)
852 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
853 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
854 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
855 struct nlattr
*props
[TIPC_NLA_PROP_MAX
+ 1] = {};
857 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
858 if (!info
[TIPC_NLA_BEARER
])
861 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
862 if (!attrs
[TIPC_NLA_BEARER_PROP
])
865 mnl_attr_parse_nested(attrs
[TIPC_NLA_BEARER_PROP
], parse_attrs
, props
);
869 printf("%u\n", mnl_attr_get_u32(props
[*prop
]));
874 static int cmd_bearer_get_media(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
875 struct cmdl
*cmdl
, void *data
)
879 char buf
[MNL_SOCKET_BUFFER_SIZE
];
881 struct cb_data cb_data
= {0};
882 struct nlattr
*attrs
;
883 struct opt opts
[] = {
884 { "localip", OPT_KEY
, NULL
},
885 { "localport", OPT_KEY
, NULL
},
886 { "remoteip", OPT_KEY
, NULL
},
887 { "remoteport", OPT_KEY
, NULL
},
888 { "name", OPT_KEYVAL
, NULL
},
889 { "media", OPT_KEYVAL
, NULL
},
892 struct tipc_sup_media sup_media
[] = {
893 { "udp", "name", cmd_bearer_get_udp_help
},
897 /* Rewind optind to include media in the option list */
899 if (parse_opts(opts
, cmdl
) < 0)
902 if (!(opt
= get_opt(opts
, "media"))) {
903 fprintf(stderr
, "error, missing media value\n");
909 cmd_bearer_get_udp_help(cmdl
, media
);
912 if (strcmp(media
, "udp") != 0) {
913 fprintf(stderr
, "error, no \"%s\" media specific options\n", media
);
916 if (!(opt
= get_opt(opts
, "name"))) {
917 fprintf(stderr
, "error, missing media name\n");
921 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
922 fprintf(stderr
, "error, message initialisation failed\n");
926 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
927 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
930 mnl_attr_nest_end(nlh
, attrs
);
933 if (has_opt(opts
, "localip")) {
934 cb_data
.attr
= TIPC_NLA_UDP_LOCAL
;
935 cb_data
.prop
= UDP_PROP_IP
;
936 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
937 } else if (has_opt(opts
, "localport")) {
938 cb_data
.attr
= TIPC_NLA_UDP_LOCAL
;
939 cb_data
.prop
= UDP_PROP_PORT
;
940 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
941 } else if (has_opt(opts
, "remoteip")) {
942 cb_data
.attr
= TIPC_NLA_UDP_REMOTE
;
943 cb_data
.prop
= UDP_PROP_IP
;
944 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
945 } else if (has_opt(opts
, "remoteport")) {
946 cb_data
.attr
= TIPC_NLA_UDP_REMOTE
;
947 cb_data
.prop
= UDP_PROP_PORT
;
948 return msg_doit(nlh
, bearer_get_udp_cb
, &cb_data
);
950 fprintf(stderr
, "error, missing UDP option\n");
954 static int cmd_bearer_get_prop(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
955 struct cmdl
*cmdl
, void *data
)
959 char buf
[MNL_SOCKET_BUFFER_SIZE
];
960 struct nlattr
*attrs
;
961 struct opt opts
[] = {
962 { "device", OPT_KEYVAL
, NULL
},
963 { "media", OPT_KEYVAL
, NULL
},
964 { "name", OPT_KEYVAL
, NULL
},
967 struct tipc_sup_media sup_media
[] = {
968 { "udp", "name", cmd_bearer_get_udp_help
},
969 { "eth", "device", cmd_bearer_get_l2_help
},
970 { "ib", "device", cmd_bearer_get_l2_help
},
979 if (strcmp(cmd
->cmd
, "priority") == 0)
980 prop
= TIPC_NLA_PROP_PRIO
;
981 else if ((strcmp(cmd
->cmd
, "tolerance") == 0))
982 prop
= TIPC_NLA_PROP_TOL
;
983 else if ((strcmp(cmd
->cmd
, "window") == 0))
984 prop
= TIPC_NLA_PROP_WIN
;
985 else if ((strcmp(cmd
->cmd
, "mtu") == 0))
986 prop
= TIPC_NLA_PROP_MTU
;
990 if (parse_opts(opts
, cmdl
) < 0)
993 if (prop
== TIPC_NLA_PROP_MTU
) {
994 char *media
= cmd_get_media_type(cmd
, cmdl
, opts
);
998 else if (strcmp(media
, "udp")) {
999 fprintf(stderr
, "error, not supported for media\n");
1004 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
1005 fprintf(stderr
, "error, message initialisation failed\n");
1009 attrs
= mnl_attr_nest_start(nlh
, TIPC_NLA_BEARER
);
1010 err
= nl_add_bearer_name(nlh
, cmd
, cmdl
, opts
, sup_media
);
1013 mnl_attr_nest_end(nlh
, attrs
);
1015 return msg_doit(nlh
, bearer_get_cb
, &prop
);
1018 static int cmd_bearer_get(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1019 struct cmdl
*cmdl
, void *data
)
1021 const struct cmd cmds
[] = {
1022 { "priority", cmd_bearer_get_prop
, cmd_bearer_get_help
},
1023 { "tolerance", cmd_bearer_get_prop
, cmd_bearer_get_help
},
1024 { "window", cmd_bearer_get_prop
, cmd_bearer_get_help
},
1025 { "mtu", cmd_bearer_get_prop
, cmd_bearer_get_help
},
1026 { "media", cmd_bearer_get_media
, cmd_bearer_get_help
},
1030 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);
1033 static int bearer_list_cb(const struct nlmsghdr
*nlh
, void *data
)
1035 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1036 struct nlattr
*info
[TIPC_NLA_MAX
+ 1] = {};
1037 struct nlattr
*attrs
[TIPC_NLA_BEARER_MAX
+ 1] = {};
1039 mnl_attr_parse(nlh
, sizeof(*genl
), parse_attrs
, info
);
1040 if (!info
[TIPC_NLA_BEARER
]) {
1041 fprintf(stderr
, "No bearer in netlink response\n");
1042 return MNL_CB_ERROR
;
1045 mnl_attr_parse_nested(info
[TIPC_NLA_BEARER
], parse_attrs
, attrs
);
1046 if (!attrs
[TIPC_NLA_BEARER_NAME
]) {
1047 fprintf(stderr
, "Bearer name missing in netlink response\n");
1048 return MNL_CB_ERROR
;
1051 printf("%s\n", mnl_attr_get_str(attrs
[TIPC_NLA_BEARER_NAME
]));
1056 static int cmd_bearer_list(struct nlmsghdr
*nlh
, const struct cmd
*cmd
,
1057 struct cmdl
*cmdl
, void *data
)
1059 char buf
[MNL_SOCKET_BUFFER_SIZE
];
1062 fprintf(stderr
, "Usage: %s bearer list\n", cmdl
->argv
[0]);
1066 if (!(nlh
= msg_init(buf
, TIPC_NL_BEARER_GET
))) {
1067 fprintf(stderr
, "error, message initialisation failed\n");
1071 return msg_dumpit(nlh
, bearer_list_cb
, NULL
);
1074 void cmd_bearer_help(struct cmdl
*cmdl
)
1077 "Usage: %s bearer COMMAND [ARGS] ...\n"
1080 " add - Add data to existing bearer\n"
1081 " enable - Enable a bearer\n"
1082 " disable - Disable a bearer\n"
1083 " set - Set various bearer properties\n"
1084 " get - Get various bearer properties\n"
1085 " list - List bearers\n", cmdl
->argv
[0]);
1088 int cmd_bearer(struct nlmsghdr
*nlh
, const struct cmd
*cmd
, struct cmdl
*cmdl
,
1091 const struct cmd cmds
[] = {
1092 { "add", cmd_bearer_add
, cmd_bearer_add_help
},
1093 { "disable", cmd_bearer_disable
, cmd_bearer_disable_help
},
1094 { "enable", cmd_bearer_enable
, cmd_bearer_enable_help
},
1095 { "get", cmd_bearer_get
, cmd_bearer_get_help
},
1096 { "list", cmd_bearer_list
, NULL
},
1097 { "set", cmd_bearer_set
, cmd_bearer_set_help
},
1101 return run_cmd(nlh
, cmd
, cmds
, cmdl
, NULL
);