diff options
| author | Julian Anastasov <ja@ssi.bg> | 2010-10-17 09:32:29 -0400 |
|---|---|---|
| committer | Simon Horman <horms@verge.net.au> | 2010-10-21 04:51:28 -0400 |
| commit | 1ca5bb5450aa2401fa272efeb741ebb260d0fbb0 (patch) | |
| tree | 93b8fa7478bb1f04e2bd443932d29590ce0e623c | |
| parent | 4256f1aaa662697c1faa0984b7a698c2c8c57735 (diff) | |
ipvs: create ip_vs_defrag_user
Create new function ip_vs_defrag_user to return correct
IP_DEFRAG_xxx user depending on the hooknum. It will be needed
when we add handlers in LOCAL_OUT.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 27ecb258ea70..f7f52831c4a6 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -543,6 +543,15 @@ __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) | |||
| 543 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); | 543 | return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); |
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | static inline enum ip_defrag_users ip_vs_defrag_user(unsigned int hooknum) | ||
| 547 | { | ||
| 548 | if (NF_INET_LOCAL_IN == hooknum) | ||
| 549 | return IP_DEFRAG_VS_IN; | ||
| 550 | if (NF_INET_FORWARD == hooknum) | ||
| 551 | return IP_DEFRAG_VS_FWD; | ||
| 552 | return IP_DEFRAG_VS_OUT; | ||
| 553 | } | ||
| 554 | |||
| 546 | static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) | 555 | static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) |
| 547 | { | 556 | { |
| 548 | int err = ip_defrag(skb, user); | 557 | int err = ip_defrag(skb, user); |
| @@ -714,7 +723,8 @@ out: | |||
| 714 | * Find any that might be relevant, check against existing connections. | 723 | * Find any that might be relevant, check against existing connections. |
| 715 | * Currently handles error types - unreachable, quench, ttl exceeded. | 724 | * Currently handles error types - unreachable, quench, ttl exceeded. |
| 716 | */ | 725 | */ |
| 717 | static int ip_vs_out_icmp(struct sk_buff *skb, int *related) | 726 | static int ip_vs_out_icmp(struct sk_buff *skb, int *related, |
| 727 | unsigned int hooknum) | ||
| 718 | { | 728 | { |
| 719 | struct iphdr *iph; | 729 | struct iphdr *iph; |
| 720 | struct icmphdr _icmph, *ic; | 730 | struct icmphdr _icmph, *ic; |
| @@ -729,7 +739,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related) | |||
| 729 | 739 | ||
| 730 | /* reassemble IP fragments */ | 740 | /* reassemble IP fragments */ |
| 731 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 741 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 732 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) | 742 | if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum))) |
| 733 | return NF_STOLEN; | 743 | return NF_STOLEN; |
| 734 | } | 744 | } |
| 735 | 745 | ||
| @@ -788,7 +798,8 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related) | |||
| 788 | } | 798 | } |
| 789 | 799 | ||
| 790 | #ifdef CONFIG_IP_VS_IPV6 | 800 | #ifdef CONFIG_IP_VS_IPV6 |
| 791 | static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related) | 801 | static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, |
| 802 | unsigned int hooknum) | ||
| 792 | { | 803 | { |
| 793 | struct ipv6hdr *iph; | 804 | struct ipv6hdr *iph; |
| 794 | struct icmp6hdr _icmph, *ic; | 805 | struct icmp6hdr _icmph, *ic; |
| @@ -804,7 +815,7 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related) | |||
| 804 | 815 | ||
| 805 | /* reassemble IP fragments */ | 816 | /* reassemble IP fragments */ |
| 806 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) { | 817 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) { |
| 807 | if (ip_vs_gather_frags_v6(skb, IP_DEFRAG_VS_OUT)) | 818 | if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum))) |
| 808 | return NF_STOLEN; | 819 | return NF_STOLEN; |
| 809 | } | 820 | } |
| 810 | 821 | ||
| @@ -986,7 +997,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
| 986 | #ifdef CONFIG_IP_VS_IPV6 | 997 | #ifdef CONFIG_IP_VS_IPV6 |
| 987 | if (af == AF_INET6) { | 998 | if (af == AF_INET6) { |
| 988 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { | 999 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { |
| 989 | int related, verdict = ip_vs_out_icmp_v6(skb, &related); | 1000 | int related; |
| 1001 | int verdict = ip_vs_out_icmp_v6(skb, &related, | ||
| 1002 | hooknum); | ||
| 990 | 1003 | ||
| 991 | if (related) { | 1004 | if (related) { |
| 992 | if (sysctl_ip_vs_snat_reroute && | 1005 | if (sysctl_ip_vs_snat_reroute && |
| @@ -1000,7 +1013,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
| 1000 | } else | 1013 | } else |
| 1001 | #endif | 1014 | #endif |
| 1002 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { | 1015 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
| 1003 | int related, verdict = ip_vs_out_icmp(skb, &related); | 1016 | int related; |
| 1017 | int verdict = ip_vs_out_icmp(skb, &related, hooknum); | ||
| 1004 | 1018 | ||
| 1005 | if (related) { | 1019 | if (related) { |
| 1006 | if (sysctl_ip_vs_snat_reroute && | 1020 | if (sysctl_ip_vs_snat_reroute && |
| @@ -1019,19 +1033,19 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
| 1019 | /* reassemble IP fragments */ | 1033 | /* reassemble IP fragments */ |
| 1020 | #ifdef CONFIG_IP_VS_IPV6 | 1034 | #ifdef CONFIG_IP_VS_IPV6 |
| 1021 | if (af == AF_INET6) { | 1035 | if (af == AF_INET6) { |
| 1022 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { | 1036 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) { |
| 1023 | int related, verdict = ip_vs_out_icmp_v6(skb, &related); | 1037 | if (ip_vs_gather_frags_v6(skb, |
| 1024 | 1038 | ip_vs_defrag_user(hooknum))) | |
| 1025 | if (related) | 1039 | return NF_STOLEN; |
| 1026 | return verdict; | ||
| 1027 | |||
| 1028 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | ||
| 1029 | } | 1040 | } |
| 1041 | |||
| 1042 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | ||
| 1030 | } else | 1043 | } else |
| 1031 | #endif | 1044 | #endif |
| 1032 | if (unlikely(ip_hdr(skb)->frag_off & htons(IP_MF|IP_OFFSET) && | 1045 | if (unlikely(ip_hdr(skb)->frag_off & htons(IP_MF|IP_OFFSET) && |
| 1033 | !pp->dont_defrag)) { | 1046 | !pp->dont_defrag)) { |
| 1034 | if (ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT)) | 1047 | if (ip_vs_gather_frags(skb, |
| 1048 | ip_vs_defrag_user(hooknum))) | ||
| 1035 | return NF_STOLEN; | 1049 | return NF_STOLEN; |
| 1036 | 1050 | ||
| 1037 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1051 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
| @@ -1114,8 +1128,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1114 | 1128 | ||
| 1115 | /* reassemble IP fragments */ | 1129 | /* reassemble IP fragments */ |
| 1116 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | 1130 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { |
| 1117 | if (ip_vs_gather_frags(skb, hooknum == NF_INET_LOCAL_IN ? | 1131 | if (ip_vs_gather_frags(skb, ip_vs_defrag_user(hooknum))) |
| 1118 | IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD)) | ||
| 1119 | return NF_STOLEN; | 1132 | return NF_STOLEN; |
| 1120 | } | 1133 | } |
| 1121 | 1134 | ||
| @@ -1226,9 +1239,7 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1226 | 1239 | ||
| 1227 | /* reassemble IP fragments */ | 1240 | /* reassemble IP fragments */ |
| 1228 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) { | 1241 | if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) { |
| 1229 | if (ip_vs_gather_frags_v6(skb, hooknum == NF_INET_LOCAL_IN ? | 1242 | if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum))) |
| 1230 | IP_DEFRAG_VS_IN : | ||
| 1231 | IP_DEFRAG_VS_FWD)) | ||
| 1232 | return NF_STOLEN; | 1243 | return NF_STOLEN; |
| 1233 | } | 1244 | } |
| 1234 | 1245 | ||
| @@ -1349,7 +1360,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, | |||
| 1349 | #ifdef CONFIG_IP_VS_IPV6 | 1360 | #ifdef CONFIG_IP_VS_IPV6 |
| 1350 | if (af == AF_INET6) { | 1361 | if (af == AF_INET6) { |
| 1351 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { | 1362 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { |
| 1352 | int related, verdict = ip_vs_in_icmp_v6(skb, &related, hooknum); | 1363 | int related; |
| 1364 | int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum); | ||
| 1353 | 1365 | ||
| 1354 | if (related) | 1366 | if (related) |
| 1355 | return verdict; | 1367 | return verdict; |
| @@ -1358,7 +1370,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, | |||
| 1358 | } else | 1370 | } else |
| 1359 | #endif | 1371 | #endif |
| 1360 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { | 1372 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
| 1361 | int related, verdict = ip_vs_in_icmp(skb, &related, hooknum); | 1373 | int related; |
| 1374 | int verdict = ip_vs_in_icmp(skb, &related, hooknum); | ||
| 1362 | 1375 | ||
| 1363 | if (related) | 1376 | if (related) |
| 1364 | return verdict; | 1377 | return verdict; |
