diff options
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 | ||