diff options
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. */ |