aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 95cc78b51532..21974191e425 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1928,3 +1928,168 @@ out:
1928 1928
1929 return skb->len; 1929 return skb->len;
1930} 1930}
1931
1932int tipc_nl_node_set_monitor(struct sk_buff *skb, struct genl_info *info)
1933{
1934 struct nlattr *attrs[TIPC_NLA_MON_MAX + 1];
1935 struct net *net = sock_net(skb->sk);
1936 int err;
1937
1938 if (!info->attrs[TIPC_NLA_MON])
1939 return -EINVAL;
1940
1941 err = nla_parse_nested(attrs, TIPC_NLA_MON_MAX,
1942 info->attrs[TIPC_NLA_MON],
1943 tipc_nl_monitor_policy);
1944 if (err)
1945 return err;
1946
1947 if (attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]) {
1948 u32 val;
1949
1950 val = nla_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]);
1951 err = tipc_nl_monitor_set_threshold(net, val);
1952 if (err)
1953 return err;
1954 }
1955
1956 return 0;
1957}
1958
1959static int __tipc_nl_add_monitor_prop(struct net *net, struct tipc_nl_msg *msg)
1960{
1961 struct nlattr *attrs;
1962 void *hdr;
1963 u32 val;
1964
1965 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
1966 0, TIPC_NL_MON_GET);
1967 if (!hdr)
1968 return -EMSGSIZE;
1969
1970 attrs = nla_nest_start(msg->skb, TIPC_NLA_MON);
1971 if (!attrs)
1972 goto msg_full;
1973
1974 val = tipc_nl_monitor_get_threshold(net);
1975
1976 if (nla_put_u32(msg->skb, TIPC_NLA_MON_ACTIVATION_THRESHOLD, val))
1977 goto attr_msg_full;
1978
1979 nla_nest_end(msg->skb, attrs);
1980 genlmsg_end(msg->skb, hdr);
1981
1982 return 0;
1983
1984attr_msg_full:
1985 nla_nest_cancel(msg->skb, attrs);
1986msg_full:
1987 genlmsg_cancel(msg->skb, hdr);
1988
1989 return -EMSGSIZE;
1990}
1991
1992int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info)
1993{
1994 struct net *net = sock_net(skb->sk);
1995 struct tipc_nl_msg msg;
1996 int err;
1997
1998 msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1999 msg.portid = info->snd_portid;
2000 msg.seq = info->snd_seq;
2001
2002 err = __tipc_nl_add_monitor_prop(net, &msg);
2003 if (err) {
2004 nlmsg_free(msg.skb);
2005 return err;
2006 }
2007
2008 return genlmsg_reply(msg.skb, info);
2009}
2010
2011int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb)
2012{
2013 struct net *net = sock_net(skb->sk);
2014 u32 prev_bearer = cb->args[0];
2015 struct tipc_nl_msg msg;
2016 int err;
2017 int i;
2018
2019 if (prev_bearer == MAX_BEARERS)
2020 return 0;
2021
2022 msg.skb = skb;
2023 msg.portid = NETLINK_CB(cb->skb).portid;
2024 msg.seq = cb->nlh->nlmsg_seq;
2025
2026 rtnl_lock();
2027 for (i = prev_bearer; i < MAX_BEARERS; i++) {
2028 prev_bearer = i;
2029 err = __tipc_nl_add_monitor(net, &msg, prev_bearer);
2030 if (err)
2031 goto out;
2032 }
2033
2034out:
2035 rtnl_unlock();
2036 cb->args[0] = prev_bearer;
2037
2038 return skb->len;
2039}
2040
2041int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
2042 struct netlink_callback *cb)
2043{
2044 struct net *net = sock_net(skb->sk);
2045 u32 prev_node = cb->args[1];
2046 u32 bearer_id = cb->args[2];
2047 int done = cb->args[0];
2048 struct tipc_nl_msg msg;
2049 int err;
2050
2051 if (!prev_node) {
2052 struct nlattr **attrs;
2053 struct nlattr *mon[TIPC_NLA_MON_MAX + 1];
2054
2055 err = tipc_nlmsg_parse(cb->nlh, &attrs);
2056 if (err)
2057 return err;
2058
2059 if (!attrs[TIPC_NLA_MON])
2060 return -EINVAL;
2061
2062 err = nla_parse_nested(mon, TIPC_NLA_MON_MAX,
2063 attrs[TIPC_NLA_MON],
2064 tipc_nl_monitor_policy);
2065 if (err)
2066 return err;
2067
2068 if (!mon[TIPC_NLA_MON_REF])
2069 return -EINVAL;
2070
2071 bearer_id = nla_get_u32(mon[TIPC_NLA_MON_REF]);
2072
2073 if (bearer_id >= MAX_BEARERS)
2074 return -EINVAL;
2075 }
2076
2077 if (done)
2078 return 0;
2079
2080 msg.skb = skb;
2081 msg.portid = NETLINK_CB(cb->skb).portid;
2082 msg.seq = cb->nlh->nlmsg_seq;
2083
2084 rtnl_lock();
2085 err = tipc_nl_add_monitor_peer(net, &msg, bearer_id, &prev_node);
2086 if (!err)
2087 done = 1;
2088
2089 rtnl_unlock();
2090 cb->args[0] = done;
2091 cb->args[1] = prev_node;
2092 cb->args[2] = bearer_id;
2093
2094 return skb->len;
2095}