Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 487d2a3a authored by Richard Alpe's avatar Richard Alpe Committed by David S. Miller
Browse files

tipc: convert legacy nl socket dump to nl compat



Convert socket (port) listing to compat dumpit call. If a socket
(port) has publications a second dumpit call is issued to collect them
and format then into the legacy buffer before continuing to process
the sockets (ports).

Command converted in this patch:
TIPC_CMD_SHOW_PORTS

Signed-off-by: default avatarRichard Alpe <richard.alpe@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarYing Xue <ying.xue@windriver.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44a8ae94
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -212,9 +212,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd,
	case TIPC_CMD_GET_MEDIA_NAMES:
		rep_tlv_buf = tipc_media_get_names();
		break;
	case TIPC_CMD_SHOW_PORTS:
		rep_tlv_buf = tipc_sk_socks_show(net);
		break;
	case TIPC_CMD_SHOW_STATS:
		rep_tlv_buf = tipc_show_stats();
		break;
+111 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "bearer.h"
#include "link.h"
#include "name_table.h"
#include "socket.h"
#include <net/genetlink.h>
#include <linux/tipc_config.h>

@@ -718,6 +719,109 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg,
	return 0;
}

static int __tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg,
				      struct nlattr **attrs)
{
	u32 type, lower, upper;
	struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1];

	nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL], NULL);

	type = nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]);
	lower = nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]);
	upper = nla_get_u32(publ[TIPC_NLA_PUBL_UPPER]);

	if (lower == upper)
		tipc_tlv_sprintf(msg->rep, " {%u,%u}", type, lower);
	else
		tipc_tlv_sprintf(msg->rep, " {%u,%u,%u}", type, lower, upper);

	return 0;
}

static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock)
{
	int err;
	void *hdr;
	struct nlattr *nest;
	struct sk_buff *args;
	struct tipc_nl_compat_cmd_dump dump;

	args = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!args)
		return -ENOMEM;

	hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI,
			  TIPC_NL_PUBL_GET);

	nest = nla_nest_start(args, TIPC_NLA_SOCK);
	if (!nest) {
		kfree_skb(args);
		return -EMSGSIZE;
	}

	if (nla_put_u32(args, TIPC_NLA_SOCK_REF, sock)) {
		kfree_skb(args);
		return -EMSGSIZE;
	}

	nla_nest_end(args, nest);
	genlmsg_end(args, hdr);

	dump.dumpit = tipc_nl_publ_dump;
	dump.format = __tipc_nl_compat_publ_dump;

	err = __tipc_nl_compat_dumpit(&dump, msg, args);

	kfree_skb(args);

	return err;
}

static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg,
				  struct nlattr **attrs)
{
	int err;
	u32 sock_ref;
	struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1];

	nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], NULL);

	sock_ref = nla_get_u32(sock[TIPC_NLA_SOCK_REF]);
	tipc_tlv_sprintf(msg->rep, "%u:", sock_ref);

	if (sock[TIPC_NLA_SOCK_CON]) {
		u32 node;
		struct nlattr *con[TIPC_NLA_CON_MAX + 1];

		nla_parse_nested(con, TIPC_NLA_CON_MAX, sock[TIPC_NLA_SOCK_CON],
				 NULL);

		node = nla_get_u32(con[TIPC_NLA_CON_NODE]);
		tipc_tlv_sprintf(msg->rep, "  connected to <%u.%u.%u:%u>",
				 tipc_zone(node),
				 tipc_cluster(node),
				 tipc_node(node),
				 nla_get_u32(con[TIPC_NLA_CON_SOCK]));

		if (con[TIPC_NLA_CON_FLAG])
			tipc_tlv_sprintf(msg->rep, " via {%u,%u}\n",
					 nla_get_u32(con[TIPC_NLA_CON_TYPE]),
					 nla_get_u32(con[TIPC_NLA_CON_INST]));
		else
			tipc_tlv_sprintf(msg->rep, "\n");
	} else if (sock[TIPC_NLA_SOCK_HAS_PUBL]) {
		tipc_tlv_sprintf(msg->rep, " bound to");

		err = tipc_nl_compat_publ_dump(msg, sock_ref);
		if (err)
			return err;
	}
	tipc_tlv_sprintf(msg->rep, "\n");

	return 0;
}

static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg)
{
	struct tipc_nl_compat_cmd_dump dump;
@@ -775,6 +879,12 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg)
		dump.dumpit = tipc_nl_name_table_dump;
		dump.format = tipc_nl_compat_name_table_dump;
		return tipc_nl_compat_dumpit(&dump, msg);
	case TIPC_CMD_SHOW_PORTS:
		msg->rep_size = ULTRA_STRING_MAX_LEN;
		msg->rep_type = TIPC_TLV_ULTRA_STRING;
		dump.dumpit = tipc_nl_sk_dump;
		dump.format = tipc_nl_compat_sk_dump;
		return tipc_nl_compat_dumpit(&dump, msg);
	}

	return -EOPNOTSUPP;
@@ -881,6 +991,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info)
	case TIPC_CMD_SET_LINK_WINDOW:
	case TIPC_CMD_RESET_LINK_STATS:
	case TIPC_CMD_SHOW_NAME_TABLE:
	case TIPC_CMD_SHOW_PORTS:
		return tipc_nl_compat_recv(skb, info);
	}

+0 −85
Original line number Diff line number Diff line
@@ -2281,91 +2281,6 @@ static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
	return rc;
}

static int tipc_sk_show(struct tipc_sock *tsk, char *buf,
			int len, int full_id)
{
	struct net *net = sock_net(&tsk->sk);
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct publication *publ;
	int ret;

	if (full_id)
		ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
				    tipc_zone(tn->own_addr),
				    tipc_cluster(tn->own_addr),
				    tipc_node(tn->own_addr), tsk->portid);
	else
		ret = tipc_snprintf(buf, len, "%-10u:", tsk->portid);

	if (tsk->connected) {
		u32 dport = tsk_peer_port(tsk);
		u32 destnode = tsk_peer_node(tsk);

		ret += tipc_snprintf(buf + ret, len - ret,
				     " connected to <%u.%u.%u:%u>",
				     tipc_zone(destnode),
				     tipc_cluster(destnode),
				     tipc_node(destnode), dport);
		if (tsk->conn_type != 0)
			ret += tipc_snprintf(buf + ret, len - ret,
					     " via {%u,%u}", tsk->conn_type,
					     tsk->conn_instance);
	} else if (tsk->published) {
		ret += tipc_snprintf(buf + ret, len - ret, " bound to");
		list_for_each_entry(publ, &tsk->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(struct net *net)
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	const struct bucket_table *tbl;
	struct rhash_head *pos;
	struct sk_buff *buf;
	struct tlv_desc *rep_tlv;
	char *pb;
	int pb_len;
	struct tipc_sock *tsk;
	int str_len = 0;
	int i;

	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;

	rcu_read_lock();
	tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht);
	for (i = 0; i < tbl->size; i++) {
		rht_for_each_entry_rcu(tsk, pos, tbl, i, node) {
			spin_lock_bh(&tsk->sk.sk_lock.slock);
			str_len += tipc_sk_show(tsk, pb + str_len,
						pb_len - str_len, 0);
			spin_unlock_bh(&tsk->sk.sk_lock.slock);
		}
	}
	rcu_read_unlock();

	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.
 */
+0 −1
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@ void tipc_sock_release_local(struct socket *sock);
int tipc_sock_accept_local(struct socket *sock, struct socket **newsock,
			   int flags);
int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq);
struct sk_buff *tipc_sk_socks_show(struct net *net);
void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
		       struct sk_buff_head *inputq);
void tipc_sk_reinit(struct net *net);