diff options
author | Richard Alpe <richard.alpe@ericsson.com> | 2014-11-20 04:29:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-21 15:01:30 -0500 |
commit | 34b78a127c4fd57cf3d5c64031693d10a8e0fae1 (patch) | |
tree | fbba2542705341c45f9a270e46aca9b819ed17f7 /net/tipc/socket.c | |
parent | 315c00bc9f2bd17f7ad7ed8119ca49b1125af507 (diff) |
tipc: add sock dump to new netlink api
Add TIPC_NL_SOCK_GET command to the new tipc netlink API.
This command supports dumping of all available sockets with their
associated connection or publication(s). It could be extended to reply
with a single socket if the NLM_F_DUMP isn't set.
The information about a socket includes reference, address, connection
information / publication information.
Netlink logical layout of response message:
-> socket
-> reference
-> address
[
-> connection
-> node
-> socket
[
-> connected flag
-> type
-> instance
]
]
[
-> publication flag
]
Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 591bbfa082a0..9e95c1ea5564 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -2801,3 +2801,104 @@ void tipc_socket_stop(void) | |||
2801 | sock_unregister(tipc_family_ops.family); | 2801 | sock_unregister(tipc_family_ops.family); |
2802 | proto_unregister(&tipc_proto); | 2802 | proto_unregister(&tipc_proto); |
2803 | } | 2803 | } |
2804 | |||
2805 | /* Caller should hold socket lock for the passed tipc socket. */ | ||
2806 | int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk) | ||
2807 | { | ||
2808 | u32 peer_node; | ||
2809 | u32 peer_port; | ||
2810 | struct nlattr *nest; | ||
2811 | |||
2812 | peer_node = tsk_peer_node(tsk); | ||
2813 | peer_port = tsk_peer_port(tsk); | ||
2814 | |||
2815 | nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON); | ||
2816 | |||
2817 | if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node)) | ||
2818 | goto msg_full; | ||
2819 | if (nla_put_u32(skb, TIPC_NLA_CON_SOCK, peer_port)) | ||
2820 | goto msg_full; | ||
2821 | |||
2822 | if (tsk->conn_type != 0) { | ||
2823 | if (nla_put_flag(skb, TIPC_NLA_CON_FLAG)) | ||
2824 | goto msg_full; | ||
2825 | if (nla_put_u32(skb, TIPC_NLA_CON_TYPE, tsk->conn_type)) | ||
2826 | goto msg_full; | ||
2827 | if (nla_put_u32(skb, TIPC_NLA_CON_INST, tsk->conn_instance)) | ||
2828 | goto msg_full; | ||
2829 | } | ||
2830 | nla_nest_end(skb, nest); | ||
2831 | |||
2832 | return 0; | ||
2833 | |||
2834 | msg_full: | ||
2835 | nla_nest_cancel(skb, nest); | ||
2836 | |||
2837 | return -EMSGSIZE; | ||
2838 | } | ||
2839 | |||
2840 | /* Caller should hold socket lock for the passed tipc socket. */ | ||
2841 | int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb, | ||
2842 | struct tipc_sock *tsk) | ||
2843 | { | ||
2844 | int err; | ||
2845 | void *hdr; | ||
2846 | struct nlattr *attrs; | ||
2847 | |||
2848 | hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, | ||
2849 | &tipc_genl_v2_family, NLM_F_MULTI, TIPC_NL_SOCK_GET); | ||
2850 | if (!hdr) | ||
2851 | goto msg_cancel; | ||
2852 | |||
2853 | attrs = nla_nest_start(skb, TIPC_NLA_SOCK); | ||
2854 | if (!attrs) | ||
2855 | goto genlmsg_cancel; | ||
2856 | if (nla_put_u32(skb, TIPC_NLA_SOCK_REF, tsk->ref)) | ||
2857 | goto attr_msg_cancel; | ||
2858 | if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tipc_own_addr)) | ||
2859 | goto attr_msg_cancel; | ||
2860 | |||
2861 | if (tsk->connected) { | ||
2862 | err = __tipc_nl_add_sk_con(skb, tsk); | ||
2863 | if (err) | ||
2864 | goto attr_msg_cancel; | ||
2865 | } else if (!list_empty(&tsk->publications)) { | ||
2866 | if (nla_put_flag(skb, TIPC_NLA_SOCK_HAS_PUBL)) | ||
2867 | goto attr_msg_cancel; | ||
2868 | } | ||
2869 | nla_nest_end(skb, attrs); | ||
2870 | genlmsg_end(skb, hdr); | ||
2871 | |||
2872 | return 0; | ||
2873 | |||
2874 | attr_msg_cancel: | ||
2875 | nla_nest_cancel(skb, attrs); | ||
2876 | genlmsg_cancel: | ||
2877 | genlmsg_cancel(skb, hdr); | ||
2878 | msg_cancel: | ||
2879 | return -EMSGSIZE; | ||
2880 | } | ||
2881 | |||
2882 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
2883 | { | ||
2884 | int err; | ||
2885 | struct tipc_sock *tsk; | ||
2886 | u32 prev_ref = cb->args[0]; | ||
2887 | u32 ref = prev_ref; | ||
2888 | |||
2889 | tsk = tipc_sk_get_next(&ref); | ||
2890 | for (; tsk; tsk = tipc_sk_get_next(&ref)) { | ||
2891 | lock_sock(&tsk->sk); | ||
2892 | err = __tipc_nl_add_sk(skb, cb, tsk); | ||
2893 | release_sock(&tsk->sk); | ||
2894 | tipc_sk_put(tsk); | ||
2895 | if (err) | ||
2896 | break; | ||
2897 | |||
2898 | prev_ref = ref; | ||
2899 | } | ||
2900 | |||
2901 | cb->args[0] = prev_ref; | ||
2902 | |||
2903 | return skb->len; | ||
2904 | } | ||