aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c118
1 files changed, 107 insertions, 11 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index f2be4c2e20bb..ddc2f8c6fced 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -40,6 +40,7 @@
#include "node.h"
#include "link.h"
#include <linux/export.h>
+#include "config.h"
#define SS_LISTENING -1 /* socket is listening */
#define SS_READY -2 /* socket is connectionless */
@@ -63,9 +64,6 @@ static const struct proto_ops msg_ops;
static struct proto tipc_proto;
static struct proto tipc_proto_kern;
-DEFINE_SPINLOCK(tipc_port_list_lock);
-LIST_HEAD(tipc_socks);
-
/*
* Revised TIPC socket locking policy:
*
@@ -113,6 +111,17 @@ LIST_HEAD(tipc_socks);
#include "socket.h"
+/* tipc_sk_lock_next: find & lock next socket in registry from given port number
+*/
+static struct tipc_sock *tipc_sk_lock_next(u32 *ref)
+{
+ struct tipc_port *port = (struct tipc_port *)tipc_ref_lock_next(ref);
+
+ if (!port)
+ return NULL;
+ return tipc_port_to_sock(port);
+}
+
/**
* advance_rx_queue - discard first buffer in socket receive queue
*
@@ -203,16 +212,11 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
port->max_pkt = MAX_PKT_DEFAULT;
port->ref = ref;
INIT_LIST_HEAD(&port->publications);
- INIT_LIST_HEAD(&port->port_list);
- /* Guard against race during node address update */
- spin_lock_bh(&tipc_port_list_lock);
msg = &port->phdr;
tipc_msg_init(msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG,
NAMED_H_SIZE, 0);
msg_set_origport(msg, ref);
- list_add_tail(&port->port_list, &tipc_socks);
- spin_unlock_bh(&tipc_port_list_lock);
/* Finish initializing socket data structures */
sock->ops = ops;
@@ -377,9 +381,6 @@ static int tipc_release(struct socket *sock)
tipc_link_xmit(buf, dnode, port->ref);
tipc_node_remove_conn(dnode, port->ref);
}
- spin_lock_bh(&tipc_port_list_lock);
- list_del(&port->port_list);
- spin_unlock_bh(&tipc_port_list_lock);
k_term_timer(&port->timer);
/* Discard any remaining (connection-based) messages in receive queue */
@@ -2043,6 +2044,101 @@ static void tipc_sk_timeout(unsigned long ref)
tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg));
}
+static int tipc_sk_show(struct tipc_port *port, char *buf,
+ int len, int full_id)
+{
+ struct publication *publ;
+ int ret;
+
+ if (full_id)
+ ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
+ tipc_zone(tipc_own_addr),
+ tipc_cluster(tipc_own_addr),
+ tipc_node(tipc_own_addr), port->ref);
+ else
+ ret = tipc_snprintf(buf, len, "%-10u:", port->ref);
+
+ if (port->connected) {
+ u32 dport = tipc_port_peerport(port);
+ u32 destnode = tipc_port_peernode(port);
+
+ ret += tipc_snprintf(buf + ret, len - ret,
+ " connected to <%u.%u.%u:%u>",
+ tipc_zone(destnode),
+ tipc_cluster(destnode),
+ tipc_node(destnode), dport);
+ if (port->conn_type != 0)
+ ret += tipc_snprintf(buf + ret, len - ret,
+ " via {%u,%u}", port->conn_type,
+ port->conn_instance);
+ } else if (port->published) {
+ ret += tipc_snprintf(buf + ret, len - ret, " bound to");
+ list_for_each_entry(publ, &port->publications, pport_list) {
+ if (publ->lower == publ->upper)
+ ret += tipc_snprintf(buf + ret, len - ret,
+ " {%u,%u}", publ->type,
+ publ->lower);
+ else
+ ret += tipc_snprintf(buf + ret, len - ret,
+ " {%u,%u,%u}", publ->type,
+ publ->lower, publ->upper);
+ }
+ }
+ ret += tipc_snprintf(buf + ret, len - ret, "\n");
+ return ret;
+}
+
+struct sk_buff *tipc_sk_socks_show(void)
+{
+ struct sk_buff *buf;
+ struct tlv_desc *rep_tlv;
+ char *pb;
+ int pb_len;
+ struct tipc_sock *tsk;
+ int str_len = 0;
+ u32 ref = 0;
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
+ if (!buf)
+ return NULL;
+ rep_tlv = (struct tlv_desc *)buf->data;
+ pb = TLV_DATA(rep_tlv);
+ pb_len = ULTRA_STRING_MAX_LEN;
+
+ tsk = tipc_sk_lock_next(&ref);
+ for (; tsk; tsk = tipc_sk_lock_next(&ref)) {
+ bh_lock_sock(&tsk->sk);
+ str_len += tipc_sk_show(&tsk->port, pb + str_len,
+ pb_len - str_len, 0);
+ bh_unlock_sock(&tsk->sk);
+ tipc_port_unlock(&tsk->port);
+ }
+ str_len += 1; /* for "\0" */
+ skb_put(buf, TLV_SPACE(str_len));
+ TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
+
+ return buf;
+}
+
+/* tipc_sk_reinit: set non-zero address in all existing sockets
+ * when we go from standalone to network mode.
+ */
+void tipc_sk_reinit(void)
+{
+ struct tipc_msg *msg;
+ u32 ref = 0;
+ struct tipc_sock *tsk = tipc_sk_lock_next(&ref);
+
+ for (; tsk; tsk = tipc_sk_lock_next(&ref)) {
+ bh_lock_sock(&tsk->sk);
+ msg = &tsk->port.phdr;
+ msg_set_prevnode(msg, tipc_own_addr);
+ msg_set_orignode(msg, tipc_own_addr);
+ bh_unlock_sock(&tsk->sk);
+ tipc_port_unlock(&tsk->port);
+ }
+}
+
/**
* tipc_setsockopt - set socket option
* @sock: socket structure