aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_diag.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2012-06-26 19:36:12 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-27 18:36:44 -0400
commit6e277ed59a45544786f4c4643a69527138c24fc1 (patch)
tree272ab01155287f9b6156c48c0c19c562ea5a5fcd /net/ipv4/inet_diag.c
parent7b46866dd0a6fe38ecee523eb27eda9c8f484dc5 (diff)
inet_diag: Do not use RTA_PUT() macros
Also, no need to trim on nlmsg_put() failure, nothing has been added yet. We also want to use nlmsg_end(), nlmsg_new() and nlmsg_free(). Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/inet_diag.c')
-rw-r--r--net/ipv4/inet_diag.c112
1 files changed, 53 insertions, 59 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 27640e734cfd..38064a285cca 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -46,9 +46,6 @@ struct inet_diag_entry {
46 u16 userlocks; 46 u16 userlocks;
47}; 47};
48 48
49#define INET_DIAG_PUT(skb, attrtype, attrlen) \
50 RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
51
52static DEFINE_MUTEX(inet_diag_table_mutex); 49static DEFINE_MUTEX(inet_diag_table_mutex);
53 50
54static const struct inet_diag_handler *inet_diag_lock_handler(int proto) 51static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
@@ -78,28 +75,22 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
78 const struct inet_sock *inet = inet_sk(sk); 75 const struct inet_sock *inet = inet_sk(sk);
79 struct inet_diag_msg *r; 76 struct inet_diag_msg *r;
80 struct nlmsghdr *nlh; 77 struct nlmsghdr *nlh;
78 struct nlattr *attr;
81 void *info = NULL; 79 void *info = NULL;
82 struct inet_diag_meminfo *minfo = NULL;
83 unsigned char *b = skb_tail_pointer(skb);
84 const struct inet_diag_handler *handler; 80 const struct inet_diag_handler *handler;
85 int ext = req->idiag_ext; 81 int ext = req->idiag_ext;
86 82
87 handler = inet_diag_table[req->sdiag_protocol]; 83 handler = inet_diag_table[req->sdiag_protocol];
88 BUG_ON(handler == NULL); 84 BUG_ON(handler == NULL);
89 85
90 nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), 0); 86 nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r),
91 if (!nlh) { 87 nlmsg_flags);
92 nlmsg_trim(skb, b); 88 if (!nlh)
93 return -EMSGSIZE; 89 return -EMSGSIZE;
94 }
95 nlh->nlmsg_flags = nlmsg_flags;
96 90
97 r = nlmsg_data(nlh); 91 r = nlmsg_data(nlh);
98 BUG_ON(sk->sk_state == TCP_TIME_WAIT); 92 BUG_ON(sk->sk_state == TCP_TIME_WAIT);
99 93
100 if (ext & (1 << (INET_DIAG_MEMINFO - 1)))
101 minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo));
102
103 r->idiag_family = sk->sk_family; 94 r->idiag_family = sk->sk_family;
104 r->idiag_state = sk->sk_state; 95 r->idiag_state = sk->sk_state;
105 r->idiag_timer = 0; 96 r->idiag_timer = 0;
@@ -117,7 +108,8 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
117 * hence this needs to be included regardless of socket family. 108 * hence this needs to be included regardless of socket family.
118 */ 109 */
119 if (ext & (1 << (INET_DIAG_TOS - 1))) 110 if (ext & (1 << (INET_DIAG_TOS - 1)))
120 RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos); 111 if (nla_put_u8(skb, INET_DIAG_TOS, inet->tos) < 0)
112 goto errout;
121 113
122#if IS_ENABLED(CONFIG_IPV6) 114#if IS_ENABLED(CONFIG_IPV6)
123 if (r->idiag_family == AF_INET6) { 115 if (r->idiag_family == AF_INET6) {
@@ -125,24 +117,31 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
125 117
126 *(struct in6_addr *)r->id.idiag_src = np->rcv_saddr; 118 *(struct in6_addr *)r->id.idiag_src = np->rcv_saddr;
127 *(struct in6_addr *)r->id.idiag_dst = np->daddr; 119 *(struct in6_addr *)r->id.idiag_dst = np->daddr;
120
128 if (ext & (1 << (INET_DIAG_TCLASS - 1))) 121 if (ext & (1 << (INET_DIAG_TCLASS - 1)))
129 RTA_PUT_U8(skb, INET_DIAG_TCLASS, np->tclass); 122 if (nla_put_u8(skb, INET_DIAG_TCLASS, np->tclass) < 0)
123 goto errout;
130 } 124 }
131#endif 125#endif
132 126
133 r->idiag_uid = sock_i_uid(sk); 127 r->idiag_uid = sock_i_uid(sk);
134 r->idiag_inode = sock_i_ino(sk); 128 r->idiag_inode = sock_i_ino(sk);
135 129
136 if (minfo) { 130 if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
137 minfo->idiag_rmem = sk_rmem_alloc_get(sk); 131 struct inet_diag_meminfo minfo = {
138 minfo->idiag_wmem = sk->sk_wmem_queued; 132 .idiag_rmem = sk_rmem_alloc_get(sk),
139 minfo->idiag_fmem = sk->sk_forward_alloc; 133 .idiag_wmem = sk->sk_wmem_queued,
140 minfo->idiag_tmem = sk_wmem_alloc_get(sk); 134 .idiag_fmem = sk->sk_forward_alloc,
135 .idiag_tmem = sk_wmem_alloc_get(sk),
136 };
137
138 if (nla_put(skb, INET_DIAG_MEMINFO, sizeof(minfo), &minfo) < 0)
139 goto errout;
141 } 140 }
142 141
143 if (ext & (1 << (INET_DIAG_SKMEMINFO - 1))) 142 if (ext & (1 << (INET_DIAG_SKMEMINFO - 1)))
144 if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO)) 143 if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
145 goto rtattr_failure; 144 goto errout;
146 145
147 if (icsk == NULL) { 146 if (icsk == NULL) {
148 handler->idiag_get_info(sk, r, NULL); 147 handler->idiag_get_info(sk, r, NULL);
@@ -169,16 +168,20 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
169 } 168 }
170#undef EXPIRES_IN_MS 169#undef EXPIRES_IN_MS
171 170
172 if (ext & (1 << (INET_DIAG_INFO - 1))) 171 if (ext & (1 << (INET_DIAG_INFO - 1))) {
173 info = INET_DIAG_PUT(skb, INET_DIAG_INFO, sizeof(struct tcp_info)); 172 attr = nla_reserve(skb, INET_DIAG_INFO,
173 sizeof(struct tcp_info));
174 if (!attr)
175 goto errout;
174 176
175 if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { 177 info = nla_data(attr);
176 const size_t len = strlen(icsk->icsk_ca_ops->name);
177
178 strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1),
179 icsk->icsk_ca_ops->name);
180 } 178 }
181 179
180 if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops)
181 if (nla_put_string(skb, INET_DIAG_CONG,
182 icsk->icsk_ca_ops->name) < 0)
183 goto errout;
184
182 handler->idiag_get_info(sk, r, info); 185 handler->idiag_get_info(sk, r, info);
183 186
184 if (sk->sk_state < TCP_TIME_WAIT && 187 if (sk->sk_state < TCP_TIME_WAIT &&
@@ -186,11 +189,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
186 icsk->icsk_ca_ops->get_info(sk, ext, skb); 189 icsk->icsk_ca_ops->get_info(sk, ext, skb);
187 190
188out: 191out:
189 nlh->nlmsg_len = skb_tail_pointer(skb) - b; 192 return nlmsg_end(skb, nlh);
190 return skb->len;
191 193
192rtattr_failure: 194errout:
193 nlmsg_trim(skb, b); 195 nlmsg_cancel(skb, nlh);
194 return -EMSGSIZE; 196 return -EMSGSIZE;
195} 197}
196EXPORT_SYMBOL_GPL(inet_sk_diag_fill); 198EXPORT_SYMBOL_GPL(inet_sk_diag_fill);
@@ -211,20 +213,16 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
211{ 213{
212 long tmo; 214 long tmo;
213 struct inet_diag_msg *r; 215 struct inet_diag_msg *r;
214 const unsigned char *previous_tail = skb_tail_pointer(skb); 216 struct nlmsghdr *nlh;
215 struct nlmsghdr *nlh = nlmsg_put(skb, pid, seq,
216 unlh->nlmsg_type, sizeof(*r), 0);
217 217
218 if (!nlh) { 218 nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r),
219 nlmsg_trim(skb, previous_tail); 219 nlmsg_flags);
220 if (!nlh)
220 return -EMSGSIZE; 221 return -EMSGSIZE;
221 }
222 222
223 r = nlmsg_data(nlh); 223 r = nlmsg_data(nlh);
224 BUG_ON(tw->tw_state != TCP_TIME_WAIT); 224 BUG_ON(tw->tw_state != TCP_TIME_WAIT);
225 225
226 nlh->nlmsg_flags = nlmsg_flags;
227
228 tmo = tw->tw_ttd - jiffies; 226 tmo = tw->tw_ttd - jiffies;
229 if (tmo < 0) 227 if (tmo < 0)
230 tmo = 0; 228 tmo = 0;
@@ -253,8 +251,8 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
253 *(struct in6_addr *)r->id.idiag_dst = tw6->tw_v6_daddr; 251 *(struct in6_addr *)r->id.idiag_dst = tw6->tw_v6_daddr;
254 } 252 }
255#endif 253#endif
256 nlh->nlmsg_len = skb_tail_pointer(skb) - previous_tail; 254
257 return skb->len; 255 return nlmsg_end(skb, nlh);
258} 256}
259 257
260static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, 258static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
@@ -303,20 +301,20 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
303 if (err) 301 if (err)
304 goto out; 302 goto out;
305 303
306 err = -ENOMEM; 304 rep = nlmsg_new(sizeof(struct inet_diag_msg) +
307 rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) + 305 sizeof(struct inet_diag_meminfo) +
308 sizeof(struct inet_diag_meminfo) + 306 sizeof(struct tcp_info) + 64, GFP_KERNEL);
309 sizeof(struct tcp_info) + 64)), 307 if (!rep) {
310 GFP_KERNEL); 308 err = -ENOMEM;
311 if (!rep)
312 goto out; 309 goto out;
310 }
313 311
314 err = sk_diag_fill(sk, rep, req, 312 err = sk_diag_fill(sk, rep, req,
315 NETLINK_CB(in_skb).pid, 313 NETLINK_CB(in_skb).pid,
316 nlh->nlmsg_seq, 0, nlh); 314 nlh->nlmsg_seq, 0, nlh);
317 if (err < 0) { 315 if (err < 0) {
318 WARN_ON(err == -EMSGSIZE); 316 WARN_ON(err == -EMSGSIZE);
319 kfree_skb(rep); 317 nlmsg_free(rep);
320 goto out; 318 goto out;
321 } 319 }
322 err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, 320 err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
@@ -597,19 +595,16 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
597{ 595{
598 const struct inet_request_sock *ireq = inet_rsk(req); 596 const struct inet_request_sock *ireq = inet_rsk(req);
599 struct inet_sock *inet = inet_sk(sk); 597 struct inet_sock *inet = inet_sk(sk);
600 unsigned char *b = skb_tail_pointer(skb);
601 struct inet_diag_msg *r; 598 struct inet_diag_msg *r;
602 struct nlmsghdr *nlh; 599 struct nlmsghdr *nlh;
603 long tmo; 600 long tmo;
604 601
605 nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), 0); 602 nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r),
606 if (!nlh) { 603 NLM_F_MULTI);
607 nlmsg_trim(skb, b); 604 if (!nlh)
608 return -1; 605 return -EMSGSIZE;
609 }
610 nlh->nlmsg_flags = NLM_F_MULTI;
611 r = nlmsg_data(nlh);
612 606
607 r = nlmsg_data(nlh);
613 r->idiag_family = sk->sk_family; 608 r->idiag_family = sk->sk_family;
614 r->idiag_state = TCP_SYN_RECV; 609 r->idiag_state = TCP_SYN_RECV;
615 r->idiag_timer = 1; 610 r->idiag_timer = 1;
@@ -637,9 +632,8 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
637 *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr; 632 *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr;
638 } 633 }
639#endif 634#endif
640 nlh->nlmsg_len = skb_tail_pointer(skb) - b;
641 635
642 return skb->len; 636 return nlmsg_end(skb, nlh);
643} 637}
644 638
645static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, 639static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,