tipc: add the ability to get UDP options via netlink
authorRichard Alpe <richard.alpe@ericsson.com>
Fri, 26 Aug 2016 08:52:55 +0000 (10:52 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 27 Aug 2016 04:38:41 +0000 (21:38 -0700)
Add UDP bearer options to netlink bearer get message. This is used by
the tipc user space tool to display UDP options.

The UDP bearer information is passed using either a sockaddr_in or
sockaddr_in6 structs. This means the user space receiver should
intermediately store the retrieved data in a large enough struct
(sockaddr_strage) before casting to the proper IP version type.

Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/tipc_netlink.h
net/tipc/bearer.c
net/tipc/udp_media.c
net/tipc/udp_media.h

index b15664c362194021cc62cde481ca77ff02f5d3a3..f9edd20fe9ba8930ad9f6de83e81f4ee97f74893 100644 (file)
@@ -61,6 +61,7 @@ enum {
        TIPC_NL_MON_PEER_GET,
        TIPC_NL_PEER_REMOVE,
        TIPC_NL_BEARER_ADD,
+       TIPC_NL_UDP_GET_REMOTEIP,
 
        __TIPC_NL_CMD_MAX,
        TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
@@ -100,6 +101,7 @@ enum {
        TIPC_NLA_UDP_UNSPEC,
        TIPC_NLA_UDP_LOCAL,             /* sockaddr_storage */
        TIPC_NLA_UDP_REMOTE,            /* sockaddr_storage */
+       TIPC_NLA_UDP_MULTI_REMOTEIP,    /* flag */
 
        __TIPC_NLA_UDP_MAX,
        TIPC_NLA_UDP_MAX = __TIPC_NLA_UDP_MAX - 1
index d7b442dd666966cb4be00cee1c079e324d4cffe5..975dbeb60ab0461ba16094099382ec98cec945d7 100644 (file)
@@ -712,6 +712,14 @@ static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
                goto prop_msg_full;
 
        nla_nest_end(msg->skb, prop);
+
+#ifdef CONFIG_TIPC_MEDIA_UDP
+       if (bearer->media->type_id == TIPC_MEDIA_TYPE_UDP) {
+               if (tipc_udp_nl_add_bearer_data(msg, bearer))
+                       goto attr_msg_full;
+       }
+#endif
+
        nla_nest_end(msg->skb, attrs);
        genlmsg_end(msg->skb, hdr);
 
index 6ece3c9ccf82e57feb4226cae54168f25acaa864..a6cdd9895653e13cf44435b497fdb58817ef7c89 100644 (file)
@@ -401,6 +401,67 @@ static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote)
        return err;
 }
 
+static int __tipc_nl_add_udp_addr(struct sk_buff *skb,
+                                 struct udp_media_addr *addr, int nla_t)
+{
+       if (ntohs(addr->proto) == ETH_P_IP) {
+               struct sockaddr_in ip4;
+
+               ip4.sin_family = AF_INET;
+               ip4.sin_port = addr->port;
+               ip4.sin_addr.s_addr = addr->ipv4.s_addr;
+               if (nla_put(skb, nla_t, sizeof(ip4), &ip4))
+                       return -EMSGSIZE;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       } else if (ntohs(addr->proto) == ETH_P_IPV6) {
+               struct sockaddr_in6 ip6;
+
+               ip6.sin6_family = AF_INET6;
+               ip6.sin6_port  = addr->port;
+               memcpy(&ip6.sin6_addr, &addr->ipv6, sizeof(struct in6_addr));
+               if (nla_put(skb, nla_t, sizeof(ip6), &ip6))
+                       return -EMSGSIZE;
+#endif
+       }
+
+       return 0;
+}
+
+int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b)
+{
+       struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value;
+       struct udp_media_addr *dst;
+       struct udp_bearer *ub;
+       struct nlattr *nest;
+
+       ub = rcu_dereference_rtnl(b->media_ptr);
+       if (!ub)
+               return -ENODEV;
+
+       nest = nla_nest_start(msg->skb, TIPC_NLA_BEARER_UDP_OPTS);
+       if (!nest)
+               goto msg_full;
+
+       if (__tipc_nl_add_udp_addr(msg->skb, src, TIPC_NLA_UDP_LOCAL))
+               goto msg_full;
+
+       dst = (struct udp_media_addr *)&b->bcast_addr.value;
+       if (__tipc_nl_add_udp_addr(msg->skb, dst, TIPC_NLA_UDP_REMOTE))
+               goto msg_full;
+
+       if (!list_empty(&ub->rcast.list)) {
+               if (nla_put_flag(msg->skb, TIPC_NLA_UDP_MULTI_REMOTEIP))
+                       goto msg_full;
+       }
+
+       nla_nest_end(msg->skb, nest);
+       return 0;
+msg_full:
+       nla_nest_cancel(msg->skb, nest);
+       return -EMSGSIZE;
+}
+
 /**
  * tipc_parse_udp_addr - build udp media address from netlink data
  * @nlattr:    netlink attribute containing sockaddr storage aligned address
index 4dcb54880aa6ee69e032a6b74380281f78393db7..c06326a134db5f3c1936606e81a29d838d64ceac 100644 (file)
@@ -39,6 +39,7 @@
 #define _TIPC_UDP_MEDIA_H
 
 int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr);
+int tipc_udp_nl_add_bearer_data(struct tipc_nl_msg *msg, struct tipc_bearer *b);
 
 #endif
 #endif