Skip to content

Commit 1df1757

Browse files
Hoang Ledsahern
Hoang Le
authored andcommitted
tipc: support interface name when activating UDP bearer
Support for indicating interface name has an ip address in parallel with specifying ip address when activating UDP bearer. This liberates the user from keeping track of the current ip address for each device. Old command syntax: $tipc bearer enable media udp name NAME localip IP New command syntax: $tipc bearer enable media udp name NAME [localip IP|dev DEVICE] v2: - Removed initial value for fd - Fixed the returning value for cmd_bearer_validate_and_get_addr to make its consistent with using: zero or non-zero v3: - Switch to use helper 'get_ifname' to retrieve interface name v4: - Replace legacy SIOCGIFADDR by netlink v5: - Fix leaky rtnl_handle Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Hoang Le <hoang.h.le@dektech.com.au> Signed-off-by: David Ahern <dsahern@gmail.com>
1 parent f7eef91 commit 1df1757

File tree

1 file changed

+89
-5
lines changed

1 file changed

+89
-5
lines changed

tipc/bearer.c

+89-5
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
#include <linux/tipc_netlink.h>
2020
#include <linux/tipc.h>
2121
#include <linux/genetlink.h>
22+
#include <linux/if.h>
2223

2324
#include <libmnl/libmnl.h>
2425
#include <sys/socket.h>
2526

27+
#include "utils.h"
2628
#include "cmdl.h"
2729
#include "msg.h"
2830
#include "bearer.h"
@@ -68,7 +70,7 @@ static void cmd_bearer_enable_l2_help(struct cmdl *cmdl, char *media)
6870
static void cmd_bearer_enable_udp_help(struct cmdl *cmdl, char *media)
6971
{
7072
fprintf(stderr,
71-
"Usage: %s bearer enable [OPTIONS] media %s name NAME localip IP [UDP OPTIONS]\n\n"
73+
"Usage: %s bearer enable [OPTIONS] media %s name NAME [localip IP|device DEVICE] [UDP OPTIONS]\n\n"
7274
"OPTIONS\n"
7375
" domain DOMAIN - Discovery domain\n"
7476
" priority PRIORITY - Bearer priority\n\n"
@@ -119,6 +121,76 @@ static int generate_multicast(short af, char *buf, int bufsize)
119121
return 0;
120122
}
121123

124+
static struct ifreq ifr;
125+
static int nl_dump_req_filter(struct nlmsghdr *nlh, int reqlen)
126+
{
127+
struct ifaddrmsg *ifa = NLMSG_DATA(nlh);
128+
129+
ifa->ifa_index = ifr.ifr_ifindex;
130+
131+
return 0;
132+
}
133+
134+
static int nl_dump_addr_filter(struct nlmsghdr *nlh, void *arg)
135+
{
136+
struct ifaddrmsg *ifa = NLMSG_DATA(nlh);
137+
char *r_addr = (char *)arg;
138+
int len = nlh->nlmsg_len;
139+
struct rtattr *addr_attr;
140+
141+
if (ifr.ifr_ifindex != ifa->ifa_index)
142+
return 0;
143+
144+
if (strlen(r_addr) > 0)
145+
return 0;
146+
147+
addr_attr = parse_rtattr_one(IFA_ADDRESS, IFA_RTA(ifa),
148+
len - NLMSG_LENGTH(sizeof(*ifa)));
149+
if (!addr_attr)
150+
return 0;
151+
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,
157+
INET_ADDRSTRLEN);
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,
163+
INET6_ADDRSTRLEN);
164+
}
165+
return 0;
166+
}
167+
168+
static int cmd_bearer_validate_and_get_addr(const char *name, char *r_addr)
169+
{
170+
struct rtnl_handle rth = { .fd = -1 };
171+
int err = -1;
172+
173+
memset(&ifr, 0, sizeof(ifr));
174+
if (!name || !r_addr || get_ifname(ifr.ifr_name, name))
175+
return err;
176+
177+
ifr.ifr_ifindex = ll_name_to_index(ifr.ifr_name);
178+
if (!ifr.ifr_ifindex)
179+
return err;
180+
181+
/* remove from cache */
182+
ll_drop_by_index(ifr.ifr_ifindex);
183+
184+
if ((err = rtnl_open(&rth, 0)) < 0)
185+
return err;
186+
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);
189+
190+
rtnl_close(&rth);
191+
return err;
192+
}
193+
122194
static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
123195
struct cmdl *cmdl)
124196
{
@@ -136,13 +208,25 @@ static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
136208
.ai_family = AF_UNSPEC,
137209
.ai_socktype = SOCK_DGRAM
138210
};
211+
char addr[INET6_ADDRSTRLEN] = {0};
139212

140-
if (!(opt = get_opt(opts, "localip"))) {
141-
fprintf(stderr, "error, udp bearer localip missing\n");
142-
cmd_bearer_enable_udp_help(cmdl, "udp");
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");
143216
return -EINVAL;
144217
}
145-
locip = opt->val;
218+
219+
if (strlen(addr) > 0) {
220+
locip = addr;
221+
} else {
222+
opt = get_opt(opts, "localip");
223+
if (!opt) {
224+
fprintf(stderr, "error, udp bearer localip/device missing\n");
225+
cmd_bearer_enable_udp_help(cmdl, "udp");
226+
return -EINVAL;
227+
}
228+
locip = opt->val;
229+
}
146230

147231
if ((opt = get_opt(opts, "remoteip")))
148232
remip = opt->val;

0 commit comments

Comments
 (0)