diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 165 |
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 | |||
1932 | int 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 | |||
1959 | static 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 | |||
1984 | attr_msg_full: | ||
1985 | nla_nest_cancel(msg->skb, attrs); | ||
1986 | msg_full: | ||
1987 | genlmsg_cancel(msg->skb, hdr); | ||
1988 | |||
1989 | return -EMSGSIZE; | ||
1990 | } | ||
1991 | |||
1992 | int 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 | |||
2011 | int 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 | |||
2034 | out: | ||
2035 | rtnl_unlock(); | ||
2036 | cb->args[0] = prev_bearer; | ||
2037 | |||
2038 | return skb->len; | ||
2039 | } | ||
2040 | |||
2041 | int 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 | } | ||