diff options
author | GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com> | 2018-03-21 09:37:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-03-22 14:43:35 -0400 |
commit | c30b70deb5f4861f590031c33fd3ec6cc63f1df1 (patch) | |
tree | e2c0d01bb5f748d9674e962f71c536c1ae03f0e5 /net/tipc/socket.c | |
parent | dfde331e757fd792e1c9579b72a8370ca665e5ed (diff) |
tipc: implement socket diagnostics for AF_TIPC
This commit adds socket diagnostics capability for AF_TIPC in netlink
family NETLINK_SOCK_DIAG in a new kernel module (diag.ko).
The following are key design considerations:
- config TIPC_DIAG has default y, like INET_DIAG.
- only requests with flag NLM_F_DUMP is supported (dump all).
- tipc_sock_diag_req message is introduced to send filter parameters.
- the response attributes are of TLV, some nested.
To avoid exposing data structures between diag and tipc modules and
avoid code duplication, the following additions are required:
- export tipc_nl_sk_walk function to reuse socket iterator.
- export tipc_sk_fill_sock_diag to fill the tipc diag attributes.
- create a sock_diag response message in __tipc_add_sock_diag defined
in diag.c and use the above exported tipc_sk_fill_sock_diag
to fill response.
Acked-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: GhantaKrishnamurthy MohanKrishna <mohan.krishna.ghanta.krishnamurthy@ericsson.com>
Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 35ac0f5b9529..07559ce4b8ba 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -3213,10 +3213,10 @@ msg_cancel: | |||
3213 | return -EMSGSIZE; | 3213 | return -EMSGSIZE; |
3214 | } | 3214 | } |
3215 | 3215 | ||
3216 | static int __tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, | 3216 | int tipc_nl_sk_walk(struct sk_buff *skb, struct netlink_callback *cb, |
3217 | int (*skb_handler)(struct sk_buff *skb, | 3217 | int (*skb_handler)(struct sk_buff *skb, |
3218 | struct netlink_callback *cb, | 3218 | struct netlink_callback *cb, |
3219 | struct tipc_sock *tsk)) | 3219 | struct tipc_sock *tsk)) |
3220 | { | 3220 | { |
3221 | struct net *net = sock_net(skb->sk); | 3221 | struct net *net = sock_net(skb->sk); |
3222 | struct tipc_net *tn = tipc_net(net); | 3222 | struct tipc_net *tn = tipc_net(net); |
@@ -3255,10 +3255,72 @@ out: | |||
3255 | 3255 | ||
3256 | return skb->len; | 3256 | return skb->len; |
3257 | } | 3257 | } |
3258 | EXPORT_SYMBOL(tipc_nl_sk_walk); | ||
3259 | |||
3260 | int tipc_sk_fill_sock_diag(struct sk_buff *skb, struct tipc_sock *tsk, | ||
3261 | u32 sk_filter_state, | ||
3262 | u64 (*tipc_diag_gen_cookie)(struct sock *sk)) | ||
3263 | { | ||
3264 | struct sock *sk = &tsk->sk; | ||
3265 | struct nlattr *attrs; | ||
3266 | struct nlattr *stat; | ||
3267 | |||
3268 | /*filter response w.r.t sk_state*/ | ||
3269 | if (!(sk_filter_state & (1 << sk->sk_state))) | ||
3270 | return 0; | ||
3271 | |||
3272 | attrs = nla_nest_start(skb, TIPC_NLA_SOCK); | ||
3273 | if (!attrs) | ||
3274 | goto msg_cancel; | ||
3275 | |||
3276 | if (__tipc_nl_add_sk_info(skb, tsk)) | ||
3277 | goto attr_msg_cancel; | ||
3278 | |||
3279 | if (nla_put_u32(skb, TIPC_NLA_SOCK_TYPE, (u32)sk->sk_type) || | ||
3280 | nla_put_u32(skb, TIPC_NLA_SOCK_TIPC_STATE, (u32)sk->sk_state) || | ||
3281 | nla_put_u32(skb, TIPC_NLA_SOCK_INO, sock_i_ino(sk)) || | ||
3282 | nla_put_u32(skb, TIPC_NLA_SOCK_UID, | ||
3283 | from_kuid_munged(sk_user_ns(sk), sock_i_uid(sk))) || | ||
3284 | nla_put_u64_64bit(skb, TIPC_NLA_SOCK_COOKIE, | ||
3285 | tipc_diag_gen_cookie(sk), | ||
3286 | TIPC_NLA_SOCK_PAD)) | ||
3287 | goto attr_msg_cancel; | ||
3288 | |||
3289 | stat = nla_nest_start(skb, TIPC_NLA_SOCK_STAT); | ||
3290 | if (!stat) | ||
3291 | goto attr_msg_cancel; | ||
3292 | |||
3293 | if (nla_put_u32(skb, TIPC_NLA_SOCK_STAT_RCVQ, | ||
3294 | skb_queue_len(&sk->sk_receive_queue)) || | ||
3295 | nla_put_u32(skb, TIPC_NLA_SOCK_STAT_SENDQ, | ||
3296 | skb_queue_len(&sk->sk_write_queue))) | ||
3297 | goto stat_msg_cancel; | ||
3298 | |||
3299 | if (tsk->cong_link_cnt && | ||
3300 | nla_put_flag(skb, TIPC_NLA_SOCK_STAT_LINK_CONG)) | ||
3301 | goto stat_msg_cancel; | ||
3302 | |||
3303 | if (tsk_conn_cong(tsk) && | ||
3304 | nla_put_flag(skb, TIPC_NLA_SOCK_STAT_CONN_CONG)) | ||
3305 | goto stat_msg_cancel; | ||
3306 | |||
3307 | nla_nest_end(skb, stat); | ||
3308 | nla_nest_end(skb, attrs); | ||
3309 | |||
3310 | return 0; | ||
3311 | |||
3312 | stat_msg_cancel: | ||
3313 | nla_nest_cancel(skb, stat); | ||
3314 | attr_msg_cancel: | ||
3315 | nla_nest_cancel(skb, attrs); | ||
3316 | msg_cancel: | ||
3317 | return -EMSGSIZE; | ||
3318 | } | ||
3319 | EXPORT_SYMBOL(tipc_sk_fill_sock_diag); | ||
3258 | 3320 | ||
3259 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) | 3321 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) |
3260 | { | 3322 | { |
3261 | return __tipc_nl_sk_walk(skb, cb, __tipc_nl_add_sk); | 3323 | return tipc_nl_sk_walk(skb, cb, __tipc_nl_add_sk); |
3262 | } | 3324 | } |
3263 | 3325 | ||
3264 | /* Caller should hold socket lock for the passed tipc socket. */ | 3326 | /* Caller should hold socket lock for the passed tipc socket. */ |