@@ -19,10 +19,13 @@
#include <linux/tipc_netlink.h>
#include <linux/tipc.h>
#include <linux/genetlink.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
#include <libmnl/libmnl.h>
#include <sys/socket.h>
+#include "utils.h"
#include "cmdl.h"
#include "msg.h"
#include "bearer.h"
@@ -68,7 +71,7 @@ static void cmd_bearer_enable_l2_help(struct cmdl *cmdl, char *media)
static void cmd_bearer_enable_udp_help(struct cmdl *cmdl, char *media)
{
fprintf(stderr,
- "Usage: %s bearer enable [OPTIONS] media %s name NAME localip IP [UDP OPTIONS]\n\n",
+ "Usage: %s bearer enable [OPTIONS] media %s name NAME [localip IP|device DEVICE] [UDP OPTIONS]\n\n",
cmdl->argv[0], media);
fprintf(stderr,
"OPTIONS\n"
@@ -121,6 +124,43 @@ static int generate_multicast(short af, char *buf, int bufsize)
return 0;
}
+static int cmd_bearer_validate_and_get_addr(const char *name, char *straddr)
+{
+ struct ifreq ifc = {};
+ struct sockaddr_in *ip4addr;
+ struct sockaddr_in6 *ip6addr;
+ int fd;
+
+ if (!name || !straddr || get_ifname(ifc.ifr_name, name))
+ return 0;
+
+ fd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (fd <= 0) {
+ fprintf(stderr, "Failed to create socket\n");
+ return 0;
+ }
+
+ if (ioctl(fd, SIOCGIFADDR, &ifc) < 0) {
+ fprintf(stderr, "ioctl failed: %s\n", strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ ip4addr = (struct sockaddr_in *)&ifc.ifr_addr;
+ if (inet_ntop(AF_INET, &ip4addr->sin_addr, straddr,
+ INET_ADDRSTRLEN) == NULL) {
+ ip6addr = (struct sockaddr_in6 *)&ifc.ifr_addr;
+ if (inet_ntop(AF_INET6, &ip6addr->sin6_addr, straddr,
+ INET6_ADDRSTRLEN) == NULL) {
+ fprintf(stderr, "UDP local address error\n");
+ close(fd);
+ return 0;
+ }
+ }
+ close(fd);
+ return 1;
+}
+
static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
struct cmdl *cmdl)
{
@@ -138,13 +178,25 @@ static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_DGRAM
};
+ char addr[INET6_ADDRSTRLEN] = {0};
- if (!(opt = get_opt(opts, "localip"))) {
- fprintf(stderr, "error, udp bearer localip missing\n");
- cmd_bearer_enable_udp_help(cmdl, "udp");
+ opt = get_opt(opts, "device");
+ if (opt && !cmd_bearer_validate_and_get_addr(opt->val, addr)) {
+ fprintf(stderr, "error, no device name available\n");
return -EINVAL;
}
- locip = opt->val;
+
+ if (strlen(addr) > 0) {
+ locip = addr;
+ } else {
+ opt = get_opt(opts, "localip");
+ if (!opt) {
+ fprintf(stderr, "error, udp bearer localip/device missing\n");
+ cmd_bearer_enable_udp_help(cmdl, "udp");
+ return -EINVAL;
+ }
+ locip = opt->val;
+ }
if ((opt = get_opt(opts, "remoteip")))
remip = opt->val;