Signed-off-by: Hoang Le <[email protected]>
---
 tipc/bearer.c | 82 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 72 insertions(+), 10 deletions(-)

diff --git a/tipc/bearer.c b/tipc/bearer.c
index 05dc84aa8ded..25bc85be980d 100644
--- a/tipc/bearer.c
+++ b/tipc/bearer.c
@@ -19,6 +19,8 @@
 #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>
@@ -68,7 +70,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 +123,48 @@ 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 = 0;
+
+       if (!name || !straddr)
+               return 0;
+
+       fd = socket(PF_INET, SOCK_DGRAM, 0);
+       if (fd <= 0) {
+               fprintf(stderr, "Failed to create socket\n");
+               return 0;
+       }
+
+       ifc.ifr_name[0] = 0;
+       memcpy(ifc.ifr_name, name, strlen(name));
+       ifc.ifr_name[strlen(name)] = 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");
+                        return -EINVAL;
+                }
+        }
+       close(fd);
+       return 1;
+}
+
 static int nl_add_udp_enable_opts(struct nlmsghdr *nlh, struct opt *opts,
                                  struct cmdl *cmdl)
 {
@@ -138,13 +182,27 @@ 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");
-               return -EINVAL;
+       opt = get_opt(opts, "device");
+       if (opt) {
+               if (!cmd_bearer_validate_and_get_addr(opt->val, addr)) {
+                       fprintf(stderr, "error, no device name available\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (strlen(addr) > 0)
+               locip = addr;
+       else {
+               opt = get_opt(opts, "localip");
+               if (!opt) {
+                       fprintf(stderr, "error, udp bearer localip missing\n");
+                       cmd_bearer_enable_udp_help(cmdl, "udp");
+                       return -EINVAL;
+               }
+               locip = opt->val;
        }
-       locip = opt->val;
 
        if ((opt = get_opt(opts, "remoteip")))
                remip = opt->val;
@@ -262,13 +320,13 @@ int cmd_get_unique_bearer_name(const struct cmd *cmd, 
struct cmdl *cmdl,
 
 static void cmd_bearer_add_udp_help(struct cmdl *cmdl, char *media)
 {
-       fprintf(stderr, "Usage: %s bearer add media %s name NAME remoteip 
REMOTEIP\n\n",
+       fprintf(stderr, "Usage: %s bearer add media %s [name NAME|device 
DEVICE]\n\nremoteip REMOTEIP\n\n",
                cmdl->argv[0], media);
 }
 
 static void cmd_bearer_add_help(struct cmdl *cmdl)
 {
-       fprintf(stderr, "Usage: %s bearer add media udp name NAME remoteip 
REMOTEIP\n",
+       fprintf(stderr, "Usage: %s bearer add media udp [name NAME|device 
DEVICE] remoteip REMOTEIP\n",
                cmdl->argv[0]);
 }
 
@@ -325,6 +383,7 @@ static int cmd_bearer_add_media(struct nlmsghdr *nlh, const 
struct cmd *cmd,
                { "remoteport",         OPT_KEYVAL,     NULL },
                { "name",               OPT_KEYVAL,     NULL },
                { "media",              OPT_KEYVAL,     NULL },
+               { "device",             OPT_KEYVAL,     NULL },
                { NULL }
        };
        const struct tipc_sup_media sup_media[] = {
@@ -349,8 +408,10 @@ static int cmd_bearer_add_media(struct nlmsghdr *nlh, 
const struct cmd *cmd,
                return -EINVAL;
        }
        if (!(opt = get_opt(opts, "name"))) {
-               fprintf(stderr, "error, missing media name\n");
-               return -EINVAL;
+               if (!(opt = get_opt(opts, "device"))) {
+                       fprintf(stderr, "error, missing media name\n");
+                       return -EINVAL;
+               }
        }
 
        if (!(nlh = msg_init(buf, TIPC_NL_BEARER_ADD))) {
@@ -557,6 +618,7 @@ static int cmd_bearer_set_prop(struct nlmsghdr *nlh, const 
struct cmd *cmd,
        };
        struct tipc_sup_media sup_media[] = {
                { "udp",        "name",         cmd_bearer_set_udp_help},
+               { "udp",        "device",       cmd_bearer_set_udp_help},
                { "eth",        "device",       cmd_bearer_set_l2_help },
                { "ib",         "device",       cmd_bearer_set_l2_help },
                { NULL, },
-- 
2.17.1



_______________________________________________
tipc-discussion mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to