tipc: add ioctl to fetch link names
authorErik Hugne <erik.hugne@ericsson.com>
Thu, 24 Apr 2014 14:26:47 +0000 (16:26 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 26 Apr 2014 16:13:24 +0000 (12:13 -0400)
We add a new ioctl for AF_TIPC that can be used to fetch the
logical name for a link to a remote node on a given bearer. This
should be used in combination with link state subscriptions.
The logical name size limit definitions are moved to tipc.h, as
they are now also needed by the new ioctl.

Signed-off-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/tipc.h
include/uapi/linux/tipc_config.h
net/tipc/node.c
net/tipc/node.h
net/tipc/socket.c

index 53cd7902d34e3f9bbd6a9a16a8c28a19c834e617..6f71b9b4159581eac01241f9c443948584f30f6e 100644 (file)
@@ -38,6 +38,7 @@
 #define _LINUX_TIPC_H_
 
 #include <linux/types.h>
+#include <linux/sockios.h>
 
 /*
  * TIPC addressing primitives
@@ -207,4 +208,25 @@ struct sockaddr_tipc {
 #define TIPC_NODE_RECVQ_DEPTH  131     /* Default: none (read only) */
 #define TIPC_SOCK_RECVQ_DEPTH  132     /* Default: none (read only) */
 
+/*
+ * Maximum sizes of TIPC bearer-related names (including terminating NULL)
+ * The string formatting for each name element is:
+ * media: media
+ * interface: media:interface name
+ * link: Z.C.N:interface-Z.C.N:interface
+ *
+ */
+
+#define TIPC_MAX_MEDIA_NAME    16
+#define TIPC_MAX_IF_NAME       16
+#define TIPC_MAX_BEARER_NAME   32
+#define TIPC_MAX_LINK_NAME     60
+
+#define SIOCGETLINKNAME                SIOCPROTOPRIVATE
+
+struct tipc_sioc_ln_req {
+       __u32 peer;
+       __u32 bearer_id;
+       char linkname[TIPC_MAX_LINK_NAME];
+};
 #endif
index 6b0bff09b3a7ced5dc7cf2c1a07dd4f82112b088..41a76acbb305f85cb4cb0ec6dfab9cab1e20e1d4 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/tipc.h>
 #include <asm/byteorder.h>
 
 #ifndef __KERNEL__
 #define TIPC_TLV_NAME_TBL_QUERY        25      /* struct tipc_name_table_query */
 #define TIPC_TLV_PORT_REF      26      /* 32-bit port reference */
 
-/*
- * Maximum sizes of TIPC bearer-related names (including terminating NUL)
- */
-
-#define TIPC_MAX_MEDIA_NAME    16      /* format = media */
-#define TIPC_MAX_IF_NAME       16      /* format = interface */
-#define TIPC_MAX_BEARER_NAME   32      /* format = media:interface */
-#define TIPC_MAX_LINK_NAME     60      /* format = Z.C.N:interface-Z.C.N:interface */
-
 /*
  * Link priority limits (min, default, max, media default)
  */
index 3b86a74cb31f74a8cd5956cc941aa5bf6c1297a5..1f938f3dba4b63fb2c16741796bf8c5e0990606a 100644 (file)
@@ -438,3 +438,30 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
        rcu_read_unlock();
        return buf;
 }
+
+/**
+ * tipc_node_get_linkname - get the name of a link
+ *
+ * @bearer_id: id of the bearer
+ * @node: peer node address
+ * @linkname: link name output buffer
+ *
+ * Returns 0 on success
+ */
+int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len)
+{
+       struct tipc_link *link;
+       struct tipc_node *node = tipc_node_find(addr);
+
+       if ((bearer_id > MAX_BEARERS) || !node)
+               return -EINVAL;
+       tipc_node_lock(node);
+       link = node->links[bearer_id];
+       if (link) {
+               strncpy(linkname, link->name, len);
+               tipc_node_unlock(node);
+               return 0;
+       }
+       tipc_node_unlock(node);
+       return -EINVAL;
+}
index 7cbb8cec1a932f881cd636a71edb0342070530ae..411b1911406442ee90a1d0449e03e4db59101e34 100644 (file)
@@ -118,6 +118,7 @@ int tipc_node_active_links(struct tipc_node *n_ptr);
 int tipc_node_is_up(struct tipc_node *n_ptr);
 struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
 struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
+int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len);
 
 static inline void tipc_node_lock(struct tipc_node *n_ptr)
 {
index 3c0256962f7dafa4ee3b11d69aed963822c888c2..3f9912f87d0d1744a14ac3dbd9dd61cf9aa545c1 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "core.h"
 #include "port.h"
+#include "node.h"
 
 #include <linux/export.h>
 
@@ -1905,6 +1906,28 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt,
        return put_user(sizeof(value), ol);
 }
 
+int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg)
+{
+       struct tipc_sioc_ln_req lnr;
+       void __user *argp = (void __user *)arg;
+
+       switch (cmd) {
+       case SIOCGETLINKNAME:
+               if (copy_from_user(&lnr, argp, sizeof(lnr)))
+                       return -EFAULT;
+               if (!tipc_node_get_linkname(lnr.bearer_id, lnr.peer,
+                                           lnr.linkname, TIPC_MAX_LINK_NAME)) {
+                       if (copy_to_user(argp, &lnr, sizeof(lnr)))
+                               return -EFAULT;
+                       return 0;
+               }
+               return -EADDRNOTAVAIL;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
 /* Protocol switches for the various types of TIPC sockets */
 
 static const struct proto_ops msg_ops = {
@@ -1917,7 +1940,7 @@ static const struct proto_ops msg_ops = {
        .accept         = sock_no_accept,
        .getname        = tipc_getname,
        .poll           = tipc_poll,
-       .ioctl          = sock_no_ioctl,
+       .ioctl          = tipc_ioctl,
        .listen         = sock_no_listen,
        .shutdown       = tipc_shutdown,
        .setsockopt     = tipc_setsockopt,
@@ -1938,7 +1961,7 @@ static const struct proto_ops packet_ops = {
        .accept         = tipc_accept,
        .getname        = tipc_getname,
        .poll           = tipc_poll,
-       .ioctl          = sock_no_ioctl,
+       .ioctl          = tipc_ioctl,
        .listen         = tipc_listen,
        .shutdown       = tipc_shutdown,
        .setsockopt     = tipc_setsockopt,
@@ -1959,7 +1982,7 @@ static const struct proto_ops stream_ops = {
        .accept         = tipc_accept,
        .getname        = tipc_getname,
        .poll           = tipc_poll,
-       .ioctl          = sock_no_ioctl,
+       .ioctl          = tipc_ioctl,
        .listen         = tipc_listen,
        .shutdown       = tipc_shutdown,
        .setsockopt     = tipc_setsockopt,