diff options
author | Davide Caratti <dcaratti@redhat.com> | 2019-08-30 06:25:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-09-01 02:44:28 -0400 |
commit | 61723b393292f1e4ea27f8d123384d50b176c29d (patch) | |
tree | 6ccca332feeef8a908c4ec63f865048cde4b88ea /net/ipv4/tcp_diag.c | |
parent | 15a7dea750e0162f273c6e61a94f96944b75b31e (diff) |
tcp: ulp: add functions to dump ulp-specific information
currently, only getsockopt(TCP_ULP) can be invoked to know if a ULP is on
top of a TCP socket. Extend idiag_get_aux() and idiag_get_aux_size(),
introduced by commit b37e88407c1d ("inet_diag: allow protocols to provide
additional data"), to report the ULP name and other information that can
be made available by the ULP through optional functions.
Users having CAP_NET_ADMIN privileges will then be able to retrieve this
information through inet_diag_handler, if they specify INET_DIAG_INFO in
the request.
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_diag.c')
-rw-r--r-- | net/ipv4/tcp_diag.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index a3a386236d93..babc156deabb 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c | |||
@@ -81,13 +81,42 @@ static int tcp_diag_put_md5sig(struct sk_buff *skb, | |||
81 | } | 81 | } |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | static int tcp_diag_put_ulp(struct sk_buff *skb, struct sock *sk, | ||
85 | const struct tcp_ulp_ops *ulp_ops) | ||
86 | { | ||
87 | struct nlattr *nest; | ||
88 | int err; | ||
89 | |||
90 | nest = nla_nest_start_noflag(skb, INET_DIAG_ULP_INFO); | ||
91 | if (!nest) | ||
92 | return -EMSGSIZE; | ||
93 | |||
94 | err = nla_put_string(skb, INET_ULP_INFO_NAME, ulp_ops->name); | ||
95 | if (err) | ||
96 | goto nla_failure; | ||
97 | |||
98 | if (ulp_ops->get_info) | ||
99 | err = ulp_ops->get_info(sk, skb); | ||
100 | if (err) | ||
101 | goto nla_failure; | ||
102 | |||
103 | nla_nest_end(skb, nest); | ||
104 | return 0; | ||
105 | |||
106 | nla_failure: | ||
107 | nla_nest_cancel(skb, nest); | ||
108 | return err; | ||
109 | } | ||
110 | |||
84 | static int tcp_diag_get_aux(struct sock *sk, bool net_admin, | 111 | static int tcp_diag_get_aux(struct sock *sk, bool net_admin, |
85 | struct sk_buff *skb) | 112 | struct sk_buff *skb) |
86 | { | 113 | { |
114 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
115 | int err = 0; | ||
116 | |||
87 | #ifdef CONFIG_TCP_MD5SIG | 117 | #ifdef CONFIG_TCP_MD5SIG |
88 | if (net_admin) { | 118 | if (net_admin) { |
89 | struct tcp_md5sig_info *md5sig; | 119 | struct tcp_md5sig_info *md5sig; |
90 | int err = 0; | ||
91 | 120 | ||
92 | rcu_read_lock(); | 121 | rcu_read_lock(); |
93 | md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info); | 122 | md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info); |
@@ -99,11 +128,21 @@ static int tcp_diag_get_aux(struct sock *sk, bool net_admin, | |||
99 | } | 128 | } |
100 | #endif | 129 | #endif |
101 | 130 | ||
131 | if (net_admin) { | ||
132 | const struct tcp_ulp_ops *ulp_ops; | ||
133 | |||
134 | ulp_ops = icsk->icsk_ulp_ops; | ||
135 | if (ulp_ops) | ||
136 | err = tcp_diag_put_ulp(skb, sk, ulp_ops); | ||
137 | if (err) | ||
138 | return err; | ||
139 | } | ||
102 | return 0; | 140 | return 0; |
103 | } | 141 | } |
104 | 142 | ||
105 | static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin) | 143 | static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin) |
106 | { | 144 | { |
145 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
107 | size_t size = 0; | 146 | size_t size = 0; |
108 | 147 | ||
109 | #ifdef CONFIG_TCP_MD5SIG | 148 | #ifdef CONFIG_TCP_MD5SIG |
@@ -124,6 +163,17 @@ static size_t tcp_diag_get_aux_size(struct sock *sk, bool net_admin) | |||
124 | } | 163 | } |
125 | #endif | 164 | #endif |
126 | 165 | ||
166 | if (net_admin) { | ||
167 | const struct tcp_ulp_ops *ulp_ops; | ||
168 | |||
169 | ulp_ops = icsk->icsk_ulp_ops; | ||
170 | if (ulp_ops) { | ||
171 | size += nla_total_size(0) + | ||
172 | nla_total_size(TCP_ULP_NAME_MAX); | ||
173 | if (ulp_ops->get_info_size) | ||
174 | size += ulp_ops->get_info_size(sk); | ||
175 | } | ||
176 | } | ||
127 | return size; | 177 | return size; |
128 | } | 178 | } |
129 | 179 | ||