35ac838a9b
This get_info handler will simply dispatch to the appropriate existing inet protocol handler. This patch also includes a new netlink attribute (INET_DIAG_PROTOCOL). This attribute is currently only used for multicast messages. Without this attribute, there is no way of knowing the IP protocol used by the socket information being broadcast. This attribute is not necessary in the 'dump' variant of this protocol (though it could easily be added) because dump requests are issued for specific family/protocol pairs. Tested: ss -E (note, the -E option has not yet been merged into the upstream version of ss). Signed-off-by: Craig Gallek <kraig@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
71 lines
1.9 KiB
C
71 lines
1.9 KiB
C
/*
|
|
* tcp_diag.c Module for monitoring TCP transport protocols sockets.
|
|
*
|
|
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/inet_diag.h>
|
|
|
|
#include <linux/tcp.h>
|
|
|
|
#include <net/tcp.h>
|
|
|
|
static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
|
|
void *_info)
|
|
{
|
|
struct tcp_info *info = _info;
|
|
|
|
if (sk->sk_state == TCP_LISTEN) {
|
|
r->idiag_rqueue = sk->sk_ack_backlog;
|
|
r->idiag_wqueue = sk->sk_max_ack_backlog;
|
|
} else if (sk->sk_type == SOCK_STREAM) {
|
|
const struct tcp_sock *tp = tcp_sk(sk);
|
|
|
|
r->idiag_rqueue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
|
|
r->idiag_wqueue = tp->write_seq - tp->snd_una;
|
|
}
|
|
if (info)
|
|
tcp_get_info(sk, info);
|
|
}
|
|
|
|
static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|
const struct inet_diag_req_v2 *r, struct nlattr *bc)
|
|
{
|
|
inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r, bc);
|
|
}
|
|
|
|
static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh,
|
|
const struct inet_diag_req_v2 *req)
|
|
{
|
|
return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req);
|
|
}
|
|
|
|
static const struct inet_diag_handler tcp_diag_handler = {
|
|
.dump = tcp_diag_dump,
|
|
.dump_one = tcp_diag_dump_one,
|
|
.idiag_get_info = tcp_diag_get_info,
|
|
.idiag_type = IPPROTO_TCP,
|
|
.idiag_info_size = sizeof(struct tcp_info),
|
|
};
|
|
|
|
static int __init tcp_diag_init(void)
|
|
{
|
|
return inet_diag_register(&tcp_diag_handler);
|
|
}
|
|
|
|
static void __exit tcp_diag_exit(void)
|
|
{
|
|
inet_diag_unregister(&tcp_diag_handler);
|
|
}
|
|
|
|
module_init(tcp_diag_init);
|
|
module_exit(tcp_diag_exit);
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-6 /* AF_INET - IPPROTO_TCP */);
|