diff options
author | Pavel Emelyanov <xemul@parallels.com> | 2011-12-06 02:58:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-06 13:58:02 -0500 |
commit | 25c4cd2b6dfd8e3d8efd8e85f167b66c032b80d9 (patch) | |
tree | e6942bb7b75eaa09867597f1efc9168626672342 /net/ipv4/inet_diag.c | |
parent | fe50ce284616c3131e353ff7158002aa47a41a81 (diff) |
inet_diag: Switch the _dump to work with new header
Make inet_diag_dumo work with given header instead of calculating
one from the nl message.
The SOCK_DIAG_BY_FAMILY just passes skb's one through, the compat code
converts the old header to new one.
Also fix the bytecode calculation to find one at proper offset.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/inet_diag.c')
-rw-r--r-- | net/ipv4/inet_diag.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index a68182223d57..57a1bd97ea35 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -502,10 +502,9 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) | |||
502 | static int inet_csk_diag_dump(struct sock *sk, | 502 | static int inet_csk_diag_dump(struct sock *sk, |
503 | struct sk_buff *skb, | 503 | struct sk_buff *skb, |
504 | struct netlink_callback *cb, | 504 | struct netlink_callback *cb, |
505 | struct inet_diag_req *r, | ||
505 | const struct nlattr *bc) | 506 | const struct nlattr *bc) |
506 | { | 507 | { |
507 | struct inet_diag_req_compat *r = NLMSG_DATA(cb->nlh); | ||
508 | |||
509 | if (bc != NULL) { | 508 | if (bc != NULL) { |
510 | struct inet_diag_entry entry; | 509 | struct inet_diag_entry entry; |
511 | struct inet_sock *inet = inet_sk(sk); | 510 | struct inet_sock *inet = inet_sk(sk); |
@@ -539,10 +538,9 @@ static int inet_csk_diag_dump(struct sock *sk, | |||
539 | static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, | 538 | static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, |
540 | struct sk_buff *skb, | 539 | struct sk_buff *skb, |
541 | struct netlink_callback *cb, | 540 | struct netlink_callback *cb, |
541 | struct inet_diag_req *r, | ||
542 | const struct nlattr *bc) | 542 | const struct nlattr *bc) |
543 | { | 543 | { |
544 | struct inet_diag_req_compat *r = NLMSG_DATA(cb->nlh); | ||
545 | |||
546 | if (bc != NULL) { | 544 | if (bc != NULL) { |
547 | struct inet_diag_entry entry; | 545 | struct inet_diag_entry entry; |
548 | 546 | ||
@@ -626,10 +624,10 @@ nlmsg_failure: | |||
626 | 624 | ||
627 | static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, | 625 | static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, |
628 | struct netlink_callback *cb, | 626 | struct netlink_callback *cb, |
627 | struct inet_diag_req *r, | ||
629 | const struct nlattr *bc) | 628 | const struct nlattr *bc) |
630 | { | 629 | { |
631 | struct inet_diag_entry entry; | 630 | struct inet_diag_entry entry; |
632 | struct inet_diag_req_compat *r = NLMSG_DATA(cb->nlh); | ||
633 | struct inet_connection_sock *icsk = inet_csk(sk); | 631 | struct inet_connection_sock *icsk = inet_csk(sk); |
634 | struct listen_sock *lopt; | 632 | struct listen_sock *lopt; |
635 | struct inet_sock *inet = inet_sk(sk); | 633 | struct inet_sock *inet = inet_sk(sk); |
@@ -708,19 +706,15 @@ out: | |||
708 | return err; | 706 | return err; |
709 | } | 707 | } |
710 | 708 | ||
711 | static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | 709 | static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, |
710 | struct inet_diag_req *r, struct nlattr *bc) | ||
712 | { | 711 | { |
713 | int i, num; | 712 | int i, num; |
714 | int s_i, s_num; | 713 | int s_i, s_num; |
715 | struct inet_diag_req_compat *r = NLMSG_DATA(cb->nlh); | ||
716 | const struct inet_diag_handler *handler; | 714 | const struct inet_diag_handler *handler; |
717 | struct inet_hashinfo *hashinfo; | 715 | struct inet_hashinfo *hashinfo; |
718 | const struct nlattr *bc = NULL; | ||
719 | 716 | ||
720 | if (nlmsg_attrlen(cb->nlh, sizeof(struct inet_diag_req_compat))) | 717 | handler = inet_diag_lock_handler(r->sdiag_protocol); |
721 | bc = nlmsg_find_attr(cb->nlh, sizeof(*r), INET_DIAG_REQ_BYTECODE); | ||
722 | |||
723 | handler = inet_diag_lock_handler(inet_diag_type2proto(cb->nlh->nlmsg_type)); | ||
724 | if (IS_ERR(handler)) | 718 | if (IS_ERR(handler)) |
725 | goto unlock; | 719 | goto unlock; |
726 | 720 | ||
@@ -758,7 +752,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
758 | cb->args[3] > 0) | 752 | cb->args[3] > 0) |
759 | goto syn_recv; | 753 | goto syn_recv; |
760 | 754 | ||
761 | if (inet_csk_diag_dump(sk, skb, cb, bc) < 0) { | 755 | if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) { |
762 | spin_unlock_bh(&ilb->lock); | 756 | spin_unlock_bh(&ilb->lock); |
763 | goto done; | 757 | goto done; |
764 | } | 758 | } |
@@ -767,7 +761,7 @@ syn_recv: | |||
767 | if (!(r->idiag_states & TCPF_SYN_RECV)) | 761 | if (!(r->idiag_states & TCPF_SYN_RECV)) |
768 | goto next_listen; | 762 | goto next_listen; |
769 | 763 | ||
770 | if (inet_diag_dump_reqs(skb, sk, cb, bc) < 0) { | 764 | if (inet_diag_dump_reqs(skb, sk, cb, r, bc) < 0) { |
771 | spin_unlock_bh(&ilb->lock); | 765 | spin_unlock_bh(&ilb->lock); |
772 | goto done; | 766 | goto done; |
773 | } | 767 | } |
@@ -820,7 +814,7 @@ skip_listen_ht: | |||
820 | if (r->id.idiag_dport != inet->inet_dport && | 814 | if (r->id.idiag_dport != inet->inet_dport && |
821 | r->id.idiag_dport) | 815 | r->id.idiag_dport) |
822 | goto next_normal; | 816 | goto next_normal; |
823 | if (inet_csk_diag_dump(sk, skb, cb, bc) < 0) { | 817 | if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) { |
824 | spin_unlock_bh(lock); | 818 | spin_unlock_bh(lock); |
825 | goto done; | 819 | goto done; |
826 | } | 820 | } |
@@ -842,7 +836,7 @@ next_normal: | |||
842 | if (r->id.idiag_dport != tw->tw_dport && | 836 | if (r->id.idiag_dport != tw->tw_dport && |
843 | r->id.idiag_dport) | 837 | r->id.idiag_dport) |
844 | goto next_dying; | 838 | goto next_dying; |
845 | if (inet_twsk_diag_dump(tw, skb, cb, bc) < 0) { | 839 | if (inet_twsk_diag_dump(tw, skb, cb, r, bc) < 0) { |
846 | spin_unlock_bh(lock); | 840 | spin_unlock_bh(lock); |
847 | goto done; | 841 | goto done; |
848 | } | 842 | } |
@@ -861,6 +855,36 @@ unlock: | |||
861 | return skb->len; | 855 | return skb->len; |
862 | } | 856 | } |
863 | 857 | ||
858 | static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
859 | { | ||
860 | struct nlattr *bc = NULL; | ||
861 | int hdrlen = sizeof(struct inet_diag_req); | ||
862 | |||
863 | if (nlmsg_attrlen(cb->nlh, hdrlen)) | ||
864 | bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE); | ||
865 | |||
866 | return __inet_diag_dump(skb, cb, (struct inet_diag_req *)NLMSG_DATA(cb->nlh), bc); | ||
867 | } | ||
868 | |||
869 | static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb) | ||
870 | { | ||
871 | struct inet_diag_req_compat *rc = NLMSG_DATA(cb->nlh); | ||
872 | struct inet_diag_req req; | ||
873 | struct nlattr *bc = NULL; | ||
874 | int hdrlen = sizeof(struct inet_diag_req_compat); | ||
875 | |||
876 | req.sdiag_family = rc->idiag_family; | ||
877 | req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type); | ||
878 | req.idiag_ext = rc->idiag_ext; | ||
879 | req.idiag_states = rc->idiag_states; | ||
880 | req.id = rc->id; | ||
881 | |||
882 | if (nlmsg_attrlen(cb->nlh, hdrlen)) | ||
883 | bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE); | ||
884 | |||
885 | return __inet_diag_dump(skb, cb, &req, bc); | ||
886 | } | ||
887 | |||
864 | static int inet_diag_get_exact_compat(struct sk_buff *in_skb, | 888 | static int inet_diag_get_exact_compat(struct sk_buff *in_skb, |
865 | const struct nlmsghdr *nlh) | 889 | const struct nlmsghdr *nlh) |
866 | { | 890 | { |
@@ -897,7 +921,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
897 | } | 921 | } |
898 | 922 | ||
899 | return netlink_dump_start(sdiagnl, skb, nlh, | 923 | return netlink_dump_start(sdiagnl, skb, nlh, |
900 | inet_diag_dump, NULL, 0); | 924 | inet_diag_dump_compat, NULL, 0); |
901 | } | 925 | } |
902 | 926 | ||
903 | return inet_diag_get_exact_compat(skb, nlh); | 927 | return inet_diag_get_exact_compat(skb, nlh); |
@@ -911,7 +935,18 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | |||
911 | return -EINVAL; | 935 | return -EINVAL; |
912 | 936 | ||
913 | if (h->nlmsg_flags & NLM_F_DUMP) { | 937 | if (h->nlmsg_flags & NLM_F_DUMP) { |
914 | return -EAFNOSUPPORT; | 938 | if (nlmsg_attrlen(h, hdrlen)) { |
939 | struct nlattr *attr; | ||
940 | attr = nlmsg_find_attr(h, hdrlen, | ||
941 | INET_DIAG_REQ_BYTECODE); | ||
942 | if (attr == NULL || | ||
943 | nla_len(attr) < sizeof(struct inet_diag_bc_op) || | ||
944 | inet_diag_bc_audit(nla_data(attr), nla_len(attr))) | ||
945 | return -EINVAL; | ||
946 | } | ||
947 | |||
948 | return netlink_dump_start(sdiagnl, skb, h, | ||
949 | inet_diag_dump, NULL, 0); | ||
915 | } | 950 | } |
916 | 951 | ||
917 | return inet_diag_get_exact(skb, h, (struct inet_diag_req *)NLMSG_DATA(h)); | 952 | return inet_diag_get_exact(skb, h, (struct inet_diag_req *)NLMSG_DATA(h)); |