diff options
-rw-r--r-- | net/ipv4/inet_diag.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index c3b334871707..4c4ae4aaf8f6 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -51,8 +51,8 @@ static struct sock *idiagnl; | |||
51 | RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) | 51 | RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) |
52 | 52 | ||
53 | static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, | 53 | static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, |
54 | int ext, u32 pid, u32 seq, u16 nlmsg_flags, | 54 | int ext, u32 pid, u32 seq, u16 nlmsg_flags, |
55 | const struct nlmsghdr *unlh) | 55 | const struct nlmsghdr *unlh) |
56 | { | 56 | { |
57 | const struct inet_sock *inet = inet_sk(sk); | 57 | const struct inet_sock *inet = inet_sk(sk); |
58 | const struct inet_connection_sock *icsk = inet_csk(sk); | 58 | const struct inet_connection_sock *icsk = inet_csk(sk); |
@@ -77,7 +77,7 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, | |||
77 | if (ext & (1 << (INET_DIAG_INFO - 1))) | 77 | if (ext & (1 << (INET_DIAG_INFO - 1))) |
78 | info = INET_DIAG_PUT(skb, INET_DIAG_INFO, | 78 | info = INET_DIAG_PUT(skb, INET_DIAG_INFO, |
79 | handler->idiag_info_size); | 79 | handler->idiag_info_size); |
80 | 80 | ||
81 | if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { | 81 | if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { |
82 | size_t len = strlen(icsk->icsk_ca_ops->name); | 82 | size_t len = strlen(icsk->icsk_ca_ops->name); |
83 | strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), | 83 | strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), |
@@ -185,7 +185,8 @@ nlmsg_failure: | |||
185 | return -1; | 185 | return -1; |
186 | } | 186 | } |
187 | 187 | ||
188 | static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) | 188 | static int inet_diag_get_exact(struct sk_buff *in_skb, |
189 | const struct nlmsghdr *nlh) | ||
189 | { | 190 | { |
190 | int err; | 191 | int err; |
191 | struct sock *sk; | 192 | struct sock *sk; |
@@ -283,7 +284,7 @@ static int bitstring_match(const u32 *a1, const u32 *a2, int bits) | |||
283 | 284 | ||
284 | 285 | ||
285 | static int inet_diag_bc_run(const void *bc, int len, | 286 | static int inet_diag_bc_run(const void *bc, int len, |
286 | const struct inet_diag_entry *entry) | 287 | const struct inet_diag_entry *entry) |
287 | { | 288 | { |
288 | while (len > 0) { | 289 | while (len > 0) { |
289 | int yes = 1; | 290 | int yes = 1; |
@@ -322,7 +323,7 @@ static int inet_diag_bc_run(const void *bc, int len, | |||
322 | yes = 0; | 323 | yes = 0; |
323 | break; | 324 | break; |
324 | } | 325 | } |
325 | 326 | ||
326 | if (cond->prefix_len == 0) | 327 | if (cond->prefix_len == 0) |
327 | break; | 328 | break; |
328 | 329 | ||
@@ -331,7 +332,8 @@ static int inet_diag_bc_run(const void *bc, int len, | |||
331 | else | 332 | else |
332 | addr = entry->daddr; | 333 | addr = entry->daddr; |
333 | 334 | ||
334 | if (bitstring_match(addr, cond->addr, cond->prefix_len)) | 335 | if (bitstring_match(addr, cond->addr, |
336 | cond->prefix_len)) | ||
335 | break; | 337 | break; |
336 | if (entry->family == AF_INET6 && | 338 | if (entry->family == AF_INET6 && |
337 | cond->family == AF_INET) { | 339 | cond->family == AF_INET) { |
@@ -346,7 +348,7 @@ static int inet_diag_bc_run(const void *bc, int len, | |||
346 | } | 348 | } |
347 | } | 349 | } |
348 | 350 | ||
349 | if (yes) { | 351 | if (yes) { |
350 | len -= op->yes; | 352 | len -= op->yes; |
351 | bc += op->yes; | 353 | bc += op->yes; |
352 | } else { | 354 | } else { |
@@ -407,14 +409,14 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) | |||
407 | default: | 409 | default: |
408 | return -EINVAL; | 410 | return -EINVAL; |
409 | } | 411 | } |
410 | bc += op->yes; | 412 | bc += op->yes; |
411 | len -= op->yes; | 413 | len -= op->yes; |
412 | } | 414 | } |
413 | return len == 0 ? 0 : -EINVAL; | 415 | return len == 0 ? 0 : -EINVAL; |
414 | } | 416 | } |
415 | 417 | ||
416 | static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, | 418 | static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, |
417 | struct netlink_callback *cb) | 419 | struct netlink_callback *cb) |
418 | { | 420 | { |
419 | struct inet_diag_req *r = NLMSG_DATA(cb->nlh); | 421 | struct inet_diag_req *r = NLMSG_DATA(cb->nlh); |
420 | 422 | ||
@@ -445,13 +447,12 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, | |||
445 | } | 447 | } |
446 | 448 | ||
447 | return inet_diag_fill(skb, sk, r->idiag_ext, NETLINK_CB(cb->skb).pid, | 449 | return inet_diag_fill(skb, sk, r->idiag_ext, NETLINK_CB(cb->skb).pid, |
448 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 450 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
449 | } | 451 | } |
450 | 452 | ||
451 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | 453 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, |
452 | struct request_sock *req, | 454 | struct request_sock *req, u32 pid, u32 seq, |
453 | u32 pid, u32 seq, | 455 | const struct nlmsghdr *unlh) |
454 | const struct nlmsghdr *unlh) | ||
455 | { | 456 | { |
456 | const struct inet_request_sock *ireq = inet_rsk(req); | 457 | const struct inet_request_sock *ireq = inet_rsk(req); |
457 | struct inet_sock *inet = inet_sk(sk); | 458 | struct inet_sock *inet = inet_sk(sk); |
@@ -504,7 +505,7 @@ nlmsg_failure: | |||
504 | } | 505 | } |
505 | 506 | ||
506 | static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, | 507 | static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, |
507 | struct netlink_callback *cb) | 508 | struct netlink_callback *cb) |
508 | { | 509 | { |
509 | struct inet_diag_entry entry; | 510 | struct inet_diag_entry entry; |
510 | struct inet_diag_req *r = NLMSG_DATA(cb->nlh); | 511 | struct inet_diag_req *r = NLMSG_DATA(cb->nlh); |
@@ -556,7 +557,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, | |||
556 | inet6_rsk(req)->loc_addr.s6_addr32 : | 557 | inet6_rsk(req)->loc_addr.s6_addr32 : |
557 | #endif | 558 | #endif |
558 | &ireq->loc_addr; | 559 | &ireq->loc_addr; |
559 | entry.daddr = | 560 | entry.daddr = |
560 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) | 561 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
561 | (entry.family == AF_INET6) ? | 562 | (entry.family == AF_INET6) ? |
562 | inet6_rsk(req)->rmt_addr.s6_addr32 : | 563 | inet6_rsk(req)->rmt_addr.s6_addr32 : |
@@ -599,7 +600,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
599 | handler = inet_diag_table[cb->nlh->nlmsg_type]; | 600 | handler = inet_diag_table[cb->nlh->nlmsg_type]; |
600 | BUG_ON(handler == NULL); | 601 | BUG_ON(handler == NULL); |
601 | hashinfo = handler->idiag_hashinfo; | 602 | hashinfo = handler->idiag_hashinfo; |
602 | 603 | ||
603 | s_i = cb->args[1]; | 604 | s_i = cb->args[1]; |
604 | s_num = num = cb->args[2]; | 605 | s_num = num = cb->args[2]; |
605 | 606 | ||
@@ -672,7 +673,6 @@ skip_listen_ht: | |||
672 | s_num = 0; | 673 | s_num = 0; |
673 | 674 | ||
674 | read_lock_bh(&head->lock); | 675 | read_lock_bh(&head->lock); |
675 | |||
676 | num = 0; | 676 | num = 0; |
677 | sk_for_each(sk, node, &head->chain) { | 677 | sk_for_each(sk, node, &head->chain) { |
678 | struct inet_sock *inet = inet_sk(sk); | 678 | struct inet_sock *inet = inet_sk(sk); |
@@ -684,7 +684,8 @@ skip_listen_ht: | |||
684 | if (r->id.idiag_sport != inet->sport && | 684 | if (r->id.idiag_sport != inet->sport && |
685 | r->id.idiag_sport) | 685 | r->id.idiag_sport) |
686 | goto next_normal; | 686 | goto next_normal; |
687 | if (r->id.idiag_dport != inet->dport && r->id.idiag_dport) | 687 | if (r->id.idiag_dport != inet->dport && |
688 | r->id.idiag_dport) | ||
688 | goto next_normal; | 689 | goto next_normal; |
689 | if (inet_diag_dump_sock(skb, sk, cb) < 0) { | 690 | if (inet_diag_dump_sock(skb, sk, cb) < 0) { |
690 | read_unlock_bh(&head->lock); | 691 | read_unlock_bh(&head->lock); |
@@ -724,8 +725,7 @@ done: | |||
724 | return skb->len; | 725 | return skb->len; |
725 | } | 726 | } |
726 | 727 | ||
727 | static __inline__ int | 728 | static inline int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
728 | inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | ||
729 | { | 729 | { |
730 | if (!(nlh->nlmsg_flags&NLM_F_REQUEST)) | 730 | if (!(nlh->nlmsg_flags&NLM_F_REQUEST)) |
731 | return 0; | 731 | return 0; |
@@ -755,9 +755,8 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
755 | } | 755 | } |
756 | return netlink_dump_start(idiagnl, skb, nlh, | 756 | return netlink_dump_start(idiagnl, skb, nlh, |
757 | inet_diag_dump, NULL); | 757 | inet_diag_dump, NULL); |
758 | } else { | 758 | } else |
759 | return inet_diag_get_exact(skb, nlh); | 759 | return inet_diag_get_exact(skb, nlh); |
760 | } | ||
761 | 760 | ||
762 | err_inval: | 761 | err_inval: |
763 | return -EINVAL; | 762 | return -EINVAL; |
@@ -766,15 +765,15 @@ err_inval: | |||
766 | 765 | ||
767 | static inline void inet_diag_rcv_skb(struct sk_buff *skb) | 766 | static inline void inet_diag_rcv_skb(struct sk_buff *skb) |
768 | { | 767 | { |
769 | int err; | ||
770 | struct nlmsghdr * nlh; | ||
771 | |||
772 | if (skb->len >= NLMSG_SPACE(0)) { | 768 | if (skb->len >= NLMSG_SPACE(0)) { |
773 | nlh = (struct nlmsghdr *)skb->data; | 769 | int err; |
774 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) | 770 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; |
771 | |||
772 | if (nlh->nlmsg_len < sizeof(*nlh) || | ||
773 | skb->len < nlh->nlmsg_len) | ||
775 | return; | 774 | return; |
776 | err = inet_diag_rcv_msg(skb, nlh); | 775 | err = inet_diag_rcv_msg(skb, nlh); |
777 | if (err || nlh->nlmsg_flags & NLM_F_ACK) | 776 | if (err || nlh->nlmsg_flags & NLM_F_ACK) |
778 | netlink_ack(skb, nlh, err); | 777 | netlink_ack(skb, nlh, err); |
779 | } | 778 | } |
780 | } | 779 | } |