diff options
author | Julius Volz <juliusv@google.com> | 2008-09-02 09:55:40 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2008-09-04 21:17:06 -0400 |
commit | 51ef348b14183789e4cb3444d05ce83b1b69d8fb (patch) | |
tree | e14e54ce262073b63a3343c764b8174b1041b577 /net | |
parent | b14198f6c1bea1687d20723db35d8effecd9d899 (diff) |
IPVS: Add 'af' args to protocol handler functions
Add 'af' arguments to conn_schedule(), conn_in_get(), conn_out_get() and
csum_check() function pointers in struct ip_vs_protocol. Extend the
respective functions for TCP, UDP, AH and ESP and adjust the callers.
The changes in the callers need to be somewhat extensive, since they now
need to pass a filled out struct ip_vs_iphdr * to the modified functions
instead of a struct iphdr *.
Signed-off-by: Julius Volz <juliusv@google.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ipvs/ip_vs_core.c | 64 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_proto_ah_esp.c | 56 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_proto_tcp.c | 79 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_proto_udp.c | 81 |
4 files changed, 162 insertions, 118 deletions
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 4a54f33b60d4..34aaa1480d90 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
@@ -572,6 +572,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related) | |||
572 | struct iphdr *iph; | 572 | struct iphdr *iph; |
573 | struct icmphdr _icmph, *ic; | 573 | struct icmphdr _icmph, *ic; |
574 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ | 574 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
575 | struct ip_vs_iphdr ciph; | ||
575 | struct ip_vs_conn *cp; | 576 | struct ip_vs_conn *cp; |
576 | struct ip_vs_protocol *pp; | 577 | struct ip_vs_protocol *pp; |
577 | unsigned int offset, ihl, verdict; | 578 | unsigned int offset, ihl, verdict; |
@@ -627,8 +628,9 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related) | |||
627 | 628 | ||
628 | offset += cih->ihl * 4; | 629 | offset += cih->ihl * 4; |
629 | 630 | ||
631 | ip_vs_fill_iphdr(AF_INET, cih, &ciph); | ||
630 | /* The embedded headers contain source and dest in reverse order */ | 632 | /* The embedded headers contain source and dest in reverse order */ |
631 | cp = pp->conn_out_get(skb, pp, cih, offset, 1); | 633 | cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1); |
632 | if (!cp) | 634 | if (!cp) |
633 | return NF_ACCEPT; | 635 | return NF_ACCEPT; |
634 | 636 | ||
@@ -686,43 +688,41 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
686 | const struct net_device *in, const struct net_device *out, | 688 | const struct net_device *in, const struct net_device *out, |
687 | int (*okfn)(struct sk_buff *)) | 689 | int (*okfn)(struct sk_buff *)) |
688 | { | 690 | { |
689 | struct iphdr *iph; | 691 | struct ip_vs_iphdr iph; |
690 | struct ip_vs_protocol *pp; | 692 | struct ip_vs_protocol *pp; |
691 | struct ip_vs_conn *cp; | 693 | struct ip_vs_conn *cp; |
692 | int ihl; | ||
693 | 694 | ||
694 | EnterFunction(11); | 695 | EnterFunction(11); |
695 | 696 | ||
696 | if (skb->ipvs_property) | 697 | if (skb->ipvs_property) |
697 | return NF_ACCEPT; | 698 | return NF_ACCEPT; |
698 | 699 | ||
699 | iph = ip_hdr(skb); | 700 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); |
700 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { | 701 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
701 | int related, verdict = ip_vs_out_icmp(skb, &related); | 702 | int related, verdict = ip_vs_out_icmp(skb, &related); |
702 | 703 | ||
703 | if (related) | 704 | if (related) |
704 | return verdict; | 705 | return verdict; |
705 | iph = ip_hdr(skb); | 706 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); |
706 | } | 707 | } |
707 | 708 | ||
708 | pp = ip_vs_proto_get(iph->protocol); | 709 | pp = ip_vs_proto_get(iph.protocol); |
709 | if (unlikely(!pp)) | 710 | if (unlikely(!pp)) |
710 | return NF_ACCEPT; | 711 | return NF_ACCEPT; |
711 | 712 | ||
712 | /* reassemble IP fragments */ | 713 | /* reassemble IP fragments */ |
713 | if (unlikely(iph->frag_off & htons(IP_MF|IP_OFFSET) && | 714 | if (unlikely(ip_hdr(skb)->frag_off & htons(IP_MF|IP_OFFSET) && |
714 | !pp->dont_defrag)) { | 715 | !pp->dont_defrag)) { |
715 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) | 716 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) |
716 | return NF_STOLEN; | 717 | return NF_STOLEN; |
717 | iph = ip_hdr(skb); | ||
718 | } | ||
719 | 718 | ||
720 | ihl = iph->ihl << 2; | 719 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); |
720 | } | ||
721 | 721 | ||
722 | /* | 722 | /* |
723 | * Check if the packet belongs to an existing entry | 723 | * Check if the packet belongs to an existing entry |
724 | */ | 724 | */ |
725 | cp = pp->conn_out_get(skb, pp, iph, ihl, 0); | 725 | cp = pp->conn_out_get(AF_INET, skb, pp, &iph, iph.len, 0); |
726 | 726 | ||
727 | if (unlikely(!cp)) { | 727 | if (unlikely(!cp)) { |
728 | if (sysctl_ip_vs_nat_icmp_send && | 728 | if (sysctl_ip_vs_nat_icmp_send && |
@@ -730,18 +730,18 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
730 | pp->protocol == IPPROTO_UDP)) { | 730 | pp->protocol == IPPROTO_UDP)) { |
731 | __be16 _ports[2], *pptr; | 731 | __be16 _ports[2], *pptr; |
732 | 732 | ||
733 | pptr = skb_header_pointer(skb, ihl, | 733 | pptr = skb_header_pointer(skb, iph.len, |
734 | sizeof(_ports), _ports); | 734 | sizeof(_ports), _ports); |
735 | if (pptr == NULL) | 735 | if (pptr == NULL) |
736 | return NF_ACCEPT; /* Not for me */ | 736 | return NF_ACCEPT; /* Not for me */ |
737 | if (ip_vs_lookup_real_service(iph->protocol, | 737 | if (ip_vs_lookup_real_service(iph.protocol, |
738 | iph->saddr, pptr[0])) { | 738 | iph.saddr.ip, pptr[0])) { |
739 | /* | 739 | /* |
740 | * Notify the real server: there is no | 740 | * Notify the real server: there is no |
741 | * existing entry if it is not RST | 741 | * existing entry if it is not RST |
742 | * packet or not TCP packet. | 742 | * packet or not TCP packet. |
743 | */ | 743 | */ |
744 | if (iph->protocol != IPPROTO_TCP | 744 | if (iph.protocol != IPPROTO_TCP |
745 | || !is_tcp_reset(skb)) { | 745 | || !is_tcp_reset(skb)) { |
746 | icmp_send(skb,ICMP_DEST_UNREACH, | 746 | icmp_send(skb,ICMP_DEST_UNREACH, |
747 | ICMP_PORT_UNREACH, 0); | 747 | ICMP_PORT_UNREACH, 0); |
@@ -756,7 +756,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
756 | 756 | ||
757 | IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); | 757 | IP_VS_DBG_PKT(11, pp, skb, 0, "Outgoing packet"); |
758 | 758 | ||
759 | if (!skb_make_writable(skb, ihl)) | 759 | if (!skb_make_writable(skb, iph.len)) |
760 | goto drop; | 760 | goto drop; |
761 | 761 | ||
762 | /* mangle the packet */ | 762 | /* mangle the packet */ |
@@ -804,6 +804,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
804 | struct iphdr *iph; | 804 | struct iphdr *iph; |
805 | struct icmphdr _icmph, *ic; | 805 | struct icmphdr _icmph, *ic; |
806 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ | 806 | struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ |
807 | struct ip_vs_iphdr ciph; | ||
807 | struct ip_vs_conn *cp; | 808 | struct ip_vs_conn *cp; |
808 | struct ip_vs_protocol *pp; | 809 | struct ip_vs_protocol *pp; |
809 | unsigned int offset, ihl, verdict; | 810 | unsigned int offset, ihl, verdict; |
@@ -860,8 +861,9 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
860 | 861 | ||
861 | offset += cih->ihl * 4; | 862 | offset += cih->ihl * 4; |
862 | 863 | ||
864 | ip_vs_fill_iphdr(AF_INET, cih, &ciph); | ||
863 | /* The embedded headers contain source and dest in reverse order */ | 865 | /* The embedded headers contain source and dest in reverse order */ |
864 | cp = pp->conn_in_get(skb, pp, cih, offset, 1); | 866 | cp = pp->conn_in_get(AF_INET, skb, pp, &ciph, offset, 1); |
865 | if (!cp) | 867 | if (!cp) |
866 | return NF_ACCEPT; | 868 | return NF_ACCEPT; |
867 | 869 | ||
@@ -897,11 +899,12 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, | |||
897 | const struct net_device *in, const struct net_device *out, | 899 | const struct net_device *in, const struct net_device *out, |
898 | int (*okfn)(struct sk_buff *)) | 900 | int (*okfn)(struct sk_buff *)) |
899 | { | 901 | { |
900 | struct iphdr *iph; | 902 | struct ip_vs_iphdr iph; |
901 | struct ip_vs_protocol *pp; | 903 | struct ip_vs_protocol *pp; |
902 | struct ip_vs_conn *cp; | 904 | struct ip_vs_conn *cp; |
903 | int ret, restart; | 905 | int ret, restart; |
904 | int ihl; | 906 | |
907 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); | ||
905 | 908 | ||
906 | /* | 909 | /* |
907 | * Big tappo: only PACKET_HOST (neither loopback nor mcasts) | 910 | * Big tappo: only PACKET_HOST (neither loopback nor mcasts) |
@@ -909,38 +912,35 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, | |||
909 | */ | 912 | */ |
910 | if (unlikely(skb->pkt_type != PACKET_HOST | 913 | if (unlikely(skb->pkt_type != PACKET_HOST |
911 | || skb->dev->flags & IFF_LOOPBACK || skb->sk)) { | 914 | || skb->dev->flags & IFF_LOOPBACK || skb->sk)) { |
912 | IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n", | 915 | IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s ignored\n", |
913 | skb->pkt_type, | 916 | skb->pkt_type, |
914 | ip_hdr(skb)->protocol, | 917 | iph.protocol, |
915 | NIPQUAD(ip_hdr(skb)->daddr)); | 918 | IP_VS_DBG_ADDR(AF_INET, &iph.daddr)); |
916 | return NF_ACCEPT; | 919 | return NF_ACCEPT; |
917 | } | 920 | } |
918 | 921 | ||
919 | iph = ip_hdr(skb); | 922 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
920 | if (unlikely(iph->protocol == IPPROTO_ICMP)) { | ||
921 | int related, verdict = ip_vs_in_icmp(skb, &related, hooknum); | 923 | int related, verdict = ip_vs_in_icmp(skb, &related, hooknum); |
922 | 924 | ||
923 | if (related) | 925 | if (related) |
924 | return verdict; | 926 | return verdict; |
925 | iph = ip_hdr(skb); | 927 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); |
926 | } | 928 | } |
927 | 929 | ||
928 | /* Protocol supported? */ | 930 | /* Protocol supported? */ |
929 | pp = ip_vs_proto_get(iph->protocol); | 931 | pp = ip_vs_proto_get(iph.protocol); |
930 | if (unlikely(!pp)) | 932 | if (unlikely(!pp)) |
931 | return NF_ACCEPT; | 933 | return NF_ACCEPT; |
932 | 934 | ||
933 | ihl = iph->ihl << 2; | ||
934 | |||
935 | /* | 935 | /* |
936 | * Check if the packet belongs to an existing connection entry | 936 | * Check if the packet belongs to an existing connection entry |
937 | */ | 937 | */ |
938 | cp = pp->conn_in_get(skb, pp, iph, ihl, 0); | 938 | cp = pp->conn_in_get(AF_INET, skb, pp, &iph, iph.len, 0); |
939 | 939 | ||
940 | if (unlikely(!cp)) { | 940 | if (unlikely(!cp)) { |
941 | int v; | 941 | int v; |
942 | 942 | ||
943 | if (!pp->conn_schedule(skb, pp, &v, &cp)) | 943 | if (!pp->conn_schedule(AF_INET, skb, pp, &v, &cp)) |
944 | return v; | 944 | return v; |
945 | } | 945 | } |
946 | 946 | ||
diff --git a/net/ipv4/ipvs/ip_vs_proto_ah_esp.c b/net/ipv4/ipvs/ip_vs_proto_ah_esp.c index 3f9ebd7639ae..2a361a991745 100644 --- a/net/ipv4/ipvs/ip_vs_proto_ah_esp.c +++ b/net/ipv4/ipvs/ip_vs_proto_ah_esp.c | |||
@@ -39,25 +39,23 @@ struct isakmp_hdr { | |||
39 | 39 | ||
40 | 40 | ||
41 | static struct ip_vs_conn * | 41 | static struct ip_vs_conn * |
42 | ah_esp_conn_in_get(const struct sk_buff *skb, | 42 | ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, |
43 | struct ip_vs_protocol *pp, | 43 | const struct ip_vs_iphdr *iph, unsigned int proto_off, |
44 | const struct iphdr *iph, | ||
45 | unsigned int proto_off, | ||
46 | int inverse) | 44 | int inverse) |
47 | { | 45 | { |
48 | struct ip_vs_conn *cp; | 46 | struct ip_vs_conn *cp; |
49 | 47 | ||
50 | if (likely(!inverse)) { | 48 | if (likely(!inverse)) { |
51 | cp = ip_vs_conn_in_get(IPPROTO_UDP, | 49 | cp = ip_vs_conn_in_get(IPPROTO_UDP, |
52 | iph->saddr, | 50 | iph->saddr.ip, |
53 | htons(PORT_ISAKMP), | 51 | htons(PORT_ISAKMP), |
54 | iph->daddr, | 52 | iph->daddr.ip, |
55 | htons(PORT_ISAKMP)); | 53 | htons(PORT_ISAKMP)); |
56 | } else { | 54 | } else { |
57 | cp = ip_vs_conn_in_get(IPPROTO_UDP, | 55 | cp = ip_vs_conn_in_get(IPPROTO_UDP, |
58 | iph->daddr, | 56 | iph->daddr.ip, |
59 | htons(PORT_ISAKMP), | 57 | htons(PORT_ISAKMP), |
60 | iph->saddr, | 58 | iph->saddr.ip, |
61 | htons(PORT_ISAKMP)); | 59 | htons(PORT_ISAKMP)); |
62 | } | 60 | } |
63 | 61 | ||
@@ -66,12 +64,12 @@ ah_esp_conn_in_get(const struct sk_buff *skb, | |||
66 | * We are not sure if the packet is from our | 64 | * We are not sure if the packet is from our |
67 | * service, so our conn_schedule hook should return NF_ACCEPT | 65 | * service, so our conn_schedule hook should return NF_ACCEPT |
68 | */ | 66 | */ |
69 | IP_VS_DBG(12, "Unknown ISAKMP entry for outin packet " | 67 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " |
70 | "%s%s %u.%u.%u.%u->%u.%u.%u.%u\n", | 68 | "%s%s %s->%s\n", |
71 | inverse ? "ICMP+" : "", | 69 | inverse ? "ICMP+" : "", |
72 | pp->name, | 70 | pp->name, |
73 | NIPQUAD(iph->saddr), | 71 | IP_VS_DBG_ADDR(af, &iph->saddr), |
74 | NIPQUAD(iph->daddr)); | 72 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
75 | } | 73 | } |
76 | 74 | ||
77 | return cp; | 75 | return cp; |
@@ -79,32 +77,35 @@ ah_esp_conn_in_get(const struct sk_buff *skb, | |||
79 | 77 | ||
80 | 78 | ||
81 | static struct ip_vs_conn * | 79 | static struct ip_vs_conn * |
82 | ah_esp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | 80 | ah_esp_conn_out_get(int af, const struct sk_buff *skb, |
83 | const struct iphdr *iph, unsigned int proto_off, int inverse) | 81 | struct ip_vs_protocol *pp, |
82 | const struct ip_vs_iphdr *iph, | ||
83 | unsigned int proto_off, | ||
84 | int inverse) | ||
84 | { | 85 | { |
85 | struct ip_vs_conn *cp; | 86 | struct ip_vs_conn *cp; |
86 | 87 | ||
87 | if (likely(!inverse)) { | 88 | if (likely(!inverse)) { |
88 | cp = ip_vs_conn_out_get(IPPROTO_UDP, | 89 | cp = ip_vs_conn_out_get(IPPROTO_UDP, |
89 | iph->saddr, | 90 | iph->saddr.ip, |
90 | htons(PORT_ISAKMP), | 91 | htons(PORT_ISAKMP), |
91 | iph->daddr, | 92 | iph->daddr.ip, |
92 | htons(PORT_ISAKMP)); | 93 | htons(PORT_ISAKMP)); |
93 | } else { | 94 | } else { |
94 | cp = ip_vs_conn_out_get(IPPROTO_UDP, | 95 | cp = ip_vs_conn_out_get(IPPROTO_UDP, |
95 | iph->daddr, | 96 | iph->daddr.ip, |
96 | htons(PORT_ISAKMP), | 97 | htons(PORT_ISAKMP), |
97 | iph->saddr, | 98 | iph->saddr.ip, |
98 | htons(PORT_ISAKMP)); | 99 | htons(PORT_ISAKMP)); |
99 | } | 100 | } |
100 | 101 | ||
101 | if (!cp) { | 102 | if (!cp) { |
102 | IP_VS_DBG(12, "Unknown ISAKMP entry for inout packet " | 103 | IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " |
103 | "%s%s %u.%u.%u.%u->%u.%u.%u.%u\n", | 104 | "%s%s %s->%s\n", |
104 | inverse ? "ICMP+" : "", | 105 | inverse ? "ICMP+" : "", |
105 | pp->name, | 106 | pp->name, |
106 | NIPQUAD(iph->saddr), | 107 | IP_VS_DBG_ADDR(af, &iph->saddr), |
107 | NIPQUAD(iph->daddr)); | 108 | IP_VS_DBG_ADDR(af, &iph->daddr)); |
108 | } | 109 | } |
109 | 110 | ||
110 | return cp; | 111 | return cp; |
@@ -112,8 +113,7 @@ ah_esp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
112 | 113 | ||
113 | 114 | ||
114 | static int | 115 | static int |
115 | ah_esp_conn_schedule(struct sk_buff *skb, | 116 | ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
116 | struct ip_vs_protocol *pp, | ||
117 | int *verdict, struct ip_vs_conn **cpp) | 117 | int *verdict, struct ip_vs_conn **cpp) |
118 | { | 118 | { |
119 | /* | 119 | /* |
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index fe93c9e6ff63..9211afa8f303 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c | |||
@@ -25,8 +25,9 @@ | |||
25 | 25 | ||
26 | 26 | ||
27 | static struct ip_vs_conn * | 27 | static struct ip_vs_conn * |
28 | tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | 28 | tcp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, |
29 | const struct iphdr *iph, unsigned int proto_off, int inverse) | 29 | const struct ip_vs_iphdr *iph, unsigned int proto_off, |
30 | int inverse) | ||
30 | { | 31 | { |
31 | __be16 _ports[2], *pptr; | 32 | __be16 _ports[2], *pptr; |
32 | 33 | ||
@@ -36,18 +37,19 @@ tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
36 | 37 | ||
37 | if (likely(!inverse)) { | 38 | if (likely(!inverse)) { |
38 | return ip_vs_conn_in_get(iph->protocol, | 39 | return ip_vs_conn_in_get(iph->protocol, |
39 | iph->saddr, pptr[0], | 40 | iph->saddr.ip, pptr[0], |
40 | iph->daddr, pptr[1]); | 41 | iph->daddr.ip, pptr[1]); |
41 | } else { | 42 | } else { |
42 | return ip_vs_conn_in_get(iph->protocol, | 43 | return ip_vs_conn_in_get(iph->protocol, |
43 | iph->daddr, pptr[1], | 44 | iph->daddr.ip, pptr[1], |
44 | iph->saddr, pptr[0]); | 45 | iph->saddr.ip, pptr[0]); |
45 | } | 46 | } |
46 | } | 47 | } |
47 | 48 | ||
48 | static struct ip_vs_conn * | 49 | static struct ip_vs_conn * |
49 | tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | 50 | tcp_conn_out_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, |
50 | const struct iphdr *iph, unsigned int proto_off, int inverse) | 51 | const struct ip_vs_iphdr *iph, unsigned int proto_off, |
52 | int inverse) | ||
51 | { | 53 | { |
52 | __be16 _ports[2], *pptr; | 54 | __be16 _ports[2], *pptr; |
53 | 55 | ||
@@ -57,26 +59,25 @@ tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
57 | 59 | ||
58 | if (likely(!inverse)) { | 60 | if (likely(!inverse)) { |
59 | return ip_vs_conn_out_get(iph->protocol, | 61 | return ip_vs_conn_out_get(iph->protocol, |
60 | iph->saddr, pptr[0], | 62 | iph->saddr.ip, pptr[0], |
61 | iph->daddr, pptr[1]); | 63 | iph->daddr.ip, pptr[1]); |
62 | } else { | 64 | } else { |
63 | return ip_vs_conn_out_get(iph->protocol, | 65 | return ip_vs_conn_out_get(iph->protocol, |
64 | iph->daddr, pptr[1], | 66 | iph->daddr.ip, pptr[1], |
65 | iph->saddr, pptr[0]); | 67 | iph->saddr.ip, pptr[0]); |
66 | } | 68 | } |
67 | } | 69 | } |
68 | 70 | ||
69 | 71 | ||
70 | static int | 72 | static int |
71 | tcp_conn_schedule(struct sk_buff *skb, | 73 | tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
72 | struct ip_vs_protocol *pp, | ||
73 | int *verdict, struct ip_vs_conn **cpp) | 74 | int *verdict, struct ip_vs_conn **cpp) |
74 | { | 75 | { |
75 | struct ip_vs_service *svc; | 76 | struct ip_vs_service *svc; |
76 | struct tcphdr _tcph, *th; | 77 | struct tcphdr _tcph, *th; |
77 | struct ip_vs_iphdr iph; | 78 | struct ip_vs_iphdr iph; |
78 | 79 | ||
79 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); | 80 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
80 | 81 | ||
81 | th = skb_header_pointer(skb, iph.len, sizeof(_tcph), &_tcph); | 82 | th = skb_header_pointer(skb, iph.len, sizeof(_tcph), &_tcph); |
82 | if (th == NULL) { | 83 | if (th == NULL) { |
@@ -85,8 +86,8 @@ tcp_conn_schedule(struct sk_buff *skb, | |||
85 | } | 86 | } |
86 | 87 | ||
87 | if (th->syn && | 88 | if (th->syn && |
88 | (svc = ip_vs_service_get(AF_INET, skb->mark, iph.protocol, | 89 | (svc = ip_vs_service_get(af, skb->mark, iph.protocol, &iph.daddr, |
89 | &iph.daddr, th->dest))) { | 90 | th->dest))) { |
90 | if (ip_vs_todrop()) { | 91 | if (ip_vs_todrop()) { |
91 | /* | 92 | /* |
92 | * It seems that we are very loaded. | 93 | * It seems that we are very loaded. |
@@ -136,7 +137,7 @@ tcp_snat_handler(struct sk_buff *skb, | |||
136 | 137 | ||
137 | if (unlikely(cp->app != NULL)) { | 138 | if (unlikely(cp->app != NULL)) { |
138 | /* Some checks before mangling */ | 139 | /* Some checks before mangling */ |
139 | if (pp->csum_check && !pp->csum_check(skb, pp)) | 140 | if (pp->csum_check && !pp->csum_check(AF_INET, skb, pp)) |
140 | return 0; | 141 | return 0; |
141 | 142 | ||
142 | /* Call application helper if needed */ | 143 | /* Call application helper if needed */ |
@@ -182,7 +183,7 @@ tcp_dnat_handler(struct sk_buff *skb, | |||
182 | 183 | ||
183 | if (unlikely(cp->app != NULL)) { | 184 | if (unlikely(cp->app != NULL)) { |
184 | /* Some checks before mangling */ | 185 | /* Some checks before mangling */ |
185 | if (pp->csum_check && !pp->csum_check(skb, pp)) | 186 | if (pp->csum_check && !pp->csum_check(AF_INET, skb, pp)) |
186 | return 0; | 187 | return 0; |
187 | 188 | ||
188 | /* | 189 | /* |
@@ -219,21 +220,43 @@ tcp_dnat_handler(struct sk_buff *skb, | |||
219 | 220 | ||
220 | 221 | ||
221 | static int | 222 | static int |
222 | tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) | 223 | tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) |
223 | { | 224 | { |
224 | const unsigned int tcphoff = ip_hdrlen(skb); | 225 | unsigned int tcphoff; |
226 | |||
227 | #ifdef CONFIG_IP_VS_IPV6 | ||
228 | if (af == AF_INET6) | ||
229 | tcphoff = sizeof(struct ipv6hdr); | ||
230 | else | ||
231 | #endif | ||
232 | tcphoff = ip_hdrlen(skb); | ||
225 | 233 | ||
226 | switch (skb->ip_summed) { | 234 | switch (skb->ip_summed) { |
227 | case CHECKSUM_NONE: | 235 | case CHECKSUM_NONE: |
228 | skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); | 236 | skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); |
229 | case CHECKSUM_COMPLETE: | 237 | case CHECKSUM_COMPLETE: |
230 | if (csum_tcpudp_magic(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, | 238 | #ifdef CONFIG_IP_VS_IPV6 |
231 | skb->len - tcphoff, | 239 | if (af == AF_INET6) { |
232 | ip_hdr(skb)->protocol, skb->csum)) { | 240 | if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, |
233 | IP_VS_DBG_RL_PKT(0, pp, skb, 0, | 241 | &ipv6_hdr(skb)->daddr, |
234 | "Failed checksum for"); | 242 | skb->len - tcphoff, |
235 | return 0; | 243 | ipv6_hdr(skb)->nexthdr, |
236 | } | 244 | skb->csum)) { |
245 | IP_VS_DBG_RL_PKT(0, pp, skb, 0, | ||
246 | "Failed checksum for"); | ||
247 | return 0; | ||
248 | } | ||
249 | } else | ||
250 | #endif | ||
251 | if (csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
252 | ip_hdr(skb)->daddr, | ||
253 | skb->len - tcphoff, | ||
254 | ip_hdr(skb)->protocol, | ||
255 | skb->csum)) { | ||
256 | IP_VS_DBG_RL_PKT(0, pp, skb, 0, | ||
257 | "Failed checksum for"); | ||
258 | return 0; | ||
259 | } | ||
237 | break; | 260 | break; |
238 | default: | 261 | default: |
239 | /* No need to checksum. */ | 262 | /* No need to checksum. */ |
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index d208ed6eb9fc..d3a1b1f2d10d 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c | |||
@@ -24,8 +24,9 @@ | |||
24 | #include <net/ip.h> | 24 | #include <net/ip.h> |
25 | 25 | ||
26 | static struct ip_vs_conn * | 26 | static struct ip_vs_conn * |
27 | udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | 27 | udp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, |
28 | const struct iphdr *iph, unsigned int proto_off, int inverse) | 28 | const struct ip_vs_iphdr *iph, unsigned int proto_off, |
29 | int inverse) | ||
29 | { | 30 | { |
30 | struct ip_vs_conn *cp; | 31 | struct ip_vs_conn *cp; |
31 | __be16 _ports[2], *pptr; | 32 | __be16 _ports[2], *pptr; |
@@ -36,12 +37,12 @@ udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
36 | 37 | ||
37 | if (likely(!inverse)) { | 38 | if (likely(!inverse)) { |
38 | cp = ip_vs_conn_in_get(iph->protocol, | 39 | cp = ip_vs_conn_in_get(iph->protocol, |
39 | iph->saddr, pptr[0], | 40 | iph->saddr.ip, pptr[0], |
40 | iph->daddr, pptr[1]); | 41 | iph->daddr.ip, pptr[1]); |
41 | } else { | 42 | } else { |
42 | cp = ip_vs_conn_in_get(iph->protocol, | 43 | cp = ip_vs_conn_in_get(iph->protocol, |
43 | iph->daddr, pptr[1], | 44 | iph->daddr.ip, pptr[1], |
44 | iph->saddr, pptr[0]); | 45 | iph->saddr.ip, pptr[0]); |
45 | } | 46 | } |
46 | 47 | ||
47 | return cp; | 48 | return cp; |
@@ -49,25 +50,25 @@ udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
49 | 50 | ||
50 | 51 | ||
51 | static struct ip_vs_conn * | 52 | static struct ip_vs_conn * |
52 | udp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | 53 | udp_conn_out_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, |
53 | const struct iphdr *iph, unsigned int proto_off, int inverse) | 54 | const struct ip_vs_iphdr *iph, unsigned int proto_off, |
55 | int inverse) | ||
54 | { | 56 | { |
55 | struct ip_vs_conn *cp; | 57 | struct ip_vs_conn *cp; |
56 | __be16 _ports[2], *pptr; | 58 | __be16 _ports[2], *pptr; |
57 | 59 | ||
58 | pptr = skb_header_pointer(skb, ip_hdrlen(skb), | 60 | pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); |
59 | sizeof(_ports), _ports); | ||
60 | if (pptr == NULL) | 61 | if (pptr == NULL) |
61 | return NULL; | 62 | return NULL; |
62 | 63 | ||
63 | if (likely(!inverse)) { | 64 | if (likely(!inverse)) { |
64 | cp = ip_vs_conn_out_get(iph->protocol, | 65 | cp = ip_vs_conn_out_get(iph->protocol, |
65 | iph->saddr, pptr[0], | 66 | iph->saddr.ip, pptr[0], |
66 | iph->daddr, pptr[1]); | 67 | iph->daddr.ip, pptr[1]); |
67 | } else { | 68 | } else { |
68 | cp = ip_vs_conn_out_get(iph->protocol, | 69 | cp = ip_vs_conn_out_get(iph->protocol, |
69 | iph->daddr, pptr[1], | 70 | iph->daddr.ip, pptr[1], |
70 | iph->saddr, pptr[0]); | 71 | iph->saddr.ip, pptr[0]); |
71 | } | 72 | } |
72 | 73 | ||
73 | return cp; | 74 | return cp; |
@@ -75,14 +76,14 @@ udp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
75 | 76 | ||
76 | 77 | ||
77 | static int | 78 | static int |
78 | udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, | 79 | udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, |
79 | int *verdict, struct ip_vs_conn **cpp) | 80 | int *verdict, struct ip_vs_conn **cpp) |
80 | { | 81 | { |
81 | struct ip_vs_service *svc; | 82 | struct ip_vs_service *svc; |
82 | struct udphdr _udph, *uh; | 83 | struct udphdr _udph, *uh; |
83 | struct ip_vs_iphdr iph; | 84 | struct ip_vs_iphdr iph; |
84 | 85 | ||
85 | ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph); | 86 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
86 | 87 | ||
87 | uh = skb_header_pointer(skb, iph.len, sizeof(_udph), &_udph); | 88 | uh = skb_header_pointer(skb, iph.len, sizeof(_udph), &_udph); |
88 | if (uh == NULL) { | 89 | if (uh == NULL) { |
@@ -90,7 +91,7 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
90 | return 0; | 91 | return 0; |
91 | } | 92 | } |
92 | 93 | ||
93 | svc = ip_vs_service_get(AF_INET, skb->mark, iph.protocol, | 94 | svc = ip_vs_service_get(af, skb->mark, iph.protocol, |
94 | &iph.daddr, uh->dest); | 95 | &iph.daddr, uh->dest); |
95 | if (svc) { | 96 | if (svc) { |
96 | if (ip_vs_todrop()) { | 97 | if (ip_vs_todrop()) { |
@@ -143,7 +144,7 @@ udp_snat_handler(struct sk_buff *skb, | |||
143 | 144 | ||
144 | if (unlikely(cp->app != NULL)) { | 145 | if (unlikely(cp->app != NULL)) { |
145 | /* Some checks before mangling */ | 146 | /* Some checks before mangling */ |
146 | if (pp->csum_check && !pp->csum_check(skb, pp)) | 147 | if (pp->csum_check && !pp->csum_check(AF_INET, skb, pp)) |
147 | return 0; | 148 | return 0; |
148 | 149 | ||
149 | /* | 150 | /* |
@@ -195,7 +196,7 @@ udp_dnat_handler(struct sk_buff *skb, | |||
195 | 196 | ||
196 | if (unlikely(cp->app != NULL)) { | 197 | if (unlikely(cp->app != NULL)) { |
197 | /* Some checks before mangling */ | 198 | /* Some checks before mangling */ |
198 | if (pp->csum_check && !pp->csum_check(skb, pp)) | 199 | if (pp->csum_check && !pp->csum_check(AF_INET, skb, pp)) |
199 | return 0; | 200 | return 0; |
200 | 201 | ||
201 | /* | 202 | /* |
@@ -234,10 +235,17 @@ udp_dnat_handler(struct sk_buff *skb, | |||
234 | 235 | ||
235 | 236 | ||
236 | static int | 237 | static int |
237 | udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) | 238 | udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) |
238 | { | 239 | { |
239 | struct udphdr _udph, *uh; | 240 | struct udphdr _udph, *uh; |
240 | const unsigned int udphoff = ip_hdrlen(skb); | 241 | unsigned int udphoff; |
242 | |||
243 | #ifdef CONFIG_IP_VS_IPV6 | ||
244 | if (af == AF_INET6) | ||
245 | udphoff = sizeof(struct ipv6hdr); | ||
246 | else | ||
247 | #endif | ||
248 | udphoff = ip_hdrlen(skb); | ||
241 | 249 | ||
242 | uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph); | 250 | uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph); |
243 | if (uh == NULL) | 251 | if (uh == NULL) |
@@ -249,15 +257,28 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) | |||
249 | skb->csum = skb_checksum(skb, udphoff, | 257 | skb->csum = skb_checksum(skb, udphoff, |
250 | skb->len - udphoff, 0); | 258 | skb->len - udphoff, 0); |
251 | case CHECKSUM_COMPLETE: | 259 | case CHECKSUM_COMPLETE: |
252 | if (csum_tcpudp_magic(ip_hdr(skb)->saddr, | 260 | #ifdef CONFIG_IP_VS_IPV6 |
253 | ip_hdr(skb)->daddr, | 261 | if (af == AF_INET6) { |
254 | skb->len - udphoff, | 262 | if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, |
255 | ip_hdr(skb)->protocol, | 263 | &ipv6_hdr(skb)->daddr, |
256 | skb->csum)) { | 264 | skb->len - udphoff, |
257 | IP_VS_DBG_RL_PKT(0, pp, skb, 0, | 265 | ipv6_hdr(skb)->nexthdr, |
258 | "Failed checksum for"); | 266 | skb->csum)) { |
259 | return 0; | 267 | IP_VS_DBG_RL_PKT(0, pp, skb, 0, |
260 | } | 268 | "Failed checksum for"); |
269 | return 0; | ||
270 | } | ||
271 | } else | ||
272 | #endif | ||
273 | if (csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
274 | ip_hdr(skb)->daddr, | ||
275 | skb->len - udphoff, | ||
276 | ip_hdr(skb)->protocol, | ||
277 | skb->csum)) { | ||
278 | IP_VS_DBG_RL_PKT(0, pp, skb, 0, | ||
279 | "Failed checksum for"); | ||
280 | return 0; | ||
281 | } | ||
261 | break; | 282 | break; |
262 | default: | 283 | default: |
263 | /* No need to checksum. */ | 284 | /* No need to checksum. */ |