diff options
29 files changed, 529 insertions, 820 deletions
diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt index 9573d0c48c6e..7a3c04729591 100644 --- a/Documentation/networking/ipvs-sysctl.txt +++ b/Documentation/networking/ipvs-sysctl.txt | |||
@@ -181,6 +181,19 @@ snat_reroute - BOOLEAN | |||
181 | always be the same as the original route so it is an optimisation | 181 | always be the same as the original route so it is an optimisation |
182 | to disable snat_reroute and avoid the recalculation. | 182 | to disable snat_reroute and avoid the recalculation. |
183 | 183 | ||
184 | sync_persist_mode - INTEGER | ||
185 | default 0 | ||
186 | |||
187 | Controls the synchronisation of connections when using persistence | ||
188 | |||
189 | 0: All types of connections are synchronised | ||
190 | 1: Attempt to reduce the synchronisation traffic depending on | ||
191 | the connection type. For persistent services avoid synchronisation | ||
192 | for normal connections, do it only for persistence templates. | ||
193 | In such case, for TCP and SCTP it may need enabling sloppy_tcp and | ||
194 | sloppy_sctp flags on backup servers. For non-persistent services | ||
195 | such optimization is not applied, mode 0 is assumed. | ||
196 | |||
184 | sync_version - INTEGER | 197 | sync_version - INTEGER |
185 | default 1 | 198 | default 1 |
186 | 199 | ||
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4405886980c7..f0d70f066f3d 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -197,31 +197,6 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) | |||
197 | } | 197 | } |
198 | } | 198 | } |
199 | 199 | ||
200 | /* This function is a faster version of ip_vs_fill_iph_skb(). | ||
201 | * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()). | ||
202 | * This is used by the some of the ip_vs_*_schedule() functions. | ||
203 | * (Mostly done to avoid ABI breakage of external schedulers) | ||
204 | */ | ||
205 | static inline void | ||
206 | ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb, | ||
207 | struct ip_vs_iphdr *iphdr) | ||
208 | { | ||
209 | #ifdef CONFIG_IP_VS_IPV6 | ||
210 | if (af == AF_INET6) { | ||
211 | const struct ipv6hdr *iph = | ||
212 | (struct ipv6hdr *)skb_network_header(skb); | ||
213 | iphdr->saddr.in6 = iph->saddr; | ||
214 | iphdr->daddr.in6 = iph->daddr; | ||
215 | } else | ||
216 | #endif | ||
217 | { | ||
218 | const struct iphdr *iph = | ||
219 | (struct iphdr *)skb_network_header(skb); | ||
220 | iphdr->saddr.ip = iph->saddr; | ||
221 | iphdr->daddr.ip = iph->daddr; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst, | 200 | static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst, |
226 | const union nf_inet_addr *src) | 201 | const union nf_inet_addr *src) |
227 | { | 202 | { |
@@ -405,17 +380,18 @@ enum { | |||
405 | */ | 380 | */ |
406 | enum ip_vs_sctp_states { | 381 | enum ip_vs_sctp_states { |
407 | IP_VS_SCTP_S_NONE, | 382 | IP_VS_SCTP_S_NONE, |
408 | IP_VS_SCTP_S_INIT_CLI, | 383 | IP_VS_SCTP_S_INIT1, |
409 | IP_VS_SCTP_S_INIT_SER, | 384 | IP_VS_SCTP_S_INIT, |
410 | IP_VS_SCTP_S_INIT_ACK_CLI, | 385 | IP_VS_SCTP_S_COOKIE_SENT, |
411 | IP_VS_SCTP_S_INIT_ACK_SER, | 386 | IP_VS_SCTP_S_COOKIE_REPLIED, |
412 | IP_VS_SCTP_S_ECHO_CLI, | 387 | IP_VS_SCTP_S_COOKIE_WAIT, |
413 | IP_VS_SCTP_S_ECHO_SER, | 388 | IP_VS_SCTP_S_COOKIE, |
389 | IP_VS_SCTP_S_COOKIE_ECHOED, | ||
414 | IP_VS_SCTP_S_ESTABLISHED, | 390 | IP_VS_SCTP_S_ESTABLISHED, |
415 | IP_VS_SCTP_S_SHUT_CLI, | 391 | IP_VS_SCTP_S_SHUTDOWN_SENT, |
416 | IP_VS_SCTP_S_SHUT_SER, | 392 | IP_VS_SCTP_S_SHUTDOWN_RECEIVED, |
417 | IP_VS_SCTP_S_SHUT_ACK_CLI, | 393 | IP_VS_SCTP_S_SHUTDOWN_ACK_SENT, |
418 | IP_VS_SCTP_S_SHUT_ACK_SER, | 394 | IP_VS_SCTP_S_REJECTED, |
419 | IP_VS_SCTP_S_CLOSED, | 395 | IP_VS_SCTP_S_CLOSED, |
420 | IP_VS_SCTP_S_LAST | 396 | IP_VS_SCTP_S_LAST |
421 | }; | 397 | }; |
@@ -814,7 +790,8 @@ struct ip_vs_scheduler { | |||
814 | 790 | ||
815 | /* selecting a server from the given service */ | 791 | /* selecting a server from the given service */ |
816 | struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc, | 792 | struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc, |
817 | const struct sk_buff *skb); | 793 | const struct sk_buff *skb, |
794 | struct ip_vs_iphdr *iph); | ||
818 | }; | 795 | }; |
819 | 796 | ||
820 | /* The persistence engine object */ | 797 | /* The persistence engine object */ |
@@ -998,10 +975,13 @@ struct netns_ipvs { | |||
998 | int sysctl_snat_reroute; | 975 | int sysctl_snat_reroute; |
999 | int sysctl_sync_ver; | 976 | int sysctl_sync_ver; |
1000 | int sysctl_sync_ports; | 977 | int sysctl_sync_ports; |
978 | int sysctl_sync_persist_mode; | ||
1001 | unsigned long sysctl_sync_qlen_max; | 979 | unsigned long sysctl_sync_qlen_max; |
1002 | int sysctl_sync_sock_size; | 980 | int sysctl_sync_sock_size; |
1003 | int sysctl_cache_bypass; | 981 | int sysctl_cache_bypass; |
1004 | int sysctl_expire_nodest_conn; | 982 | int sysctl_expire_nodest_conn; |
983 | int sysctl_sloppy_tcp; | ||
984 | int sysctl_sloppy_sctp; | ||
1005 | int sysctl_expire_quiescent_template; | 985 | int sysctl_expire_quiescent_template; |
1006 | int sysctl_sync_threshold[2]; | 986 | int sysctl_sync_threshold[2]; |
1007 | unsigned int sysctl_sync_refresh_period; | 987 | unsigned int sysctl_sync_refresh_period; |
@@ -1044,6 +1024,8 @@ struct netns_ipvs { | |||
1044 | #define DEFAULT_SYNC_THRESHOLD 3 | 1024 | #define DEFAULT_SYNC_THRESHOLD 3 |
1045 | #define DEFAULT_SYNC_PERIOD 50 | 1025 | #define DEFAULT_SYNC_PERIOD 50 |
1046 | #define DEFAULT_SYNC_VER 1 | 1026 | #define DEFAULT_SYNC_VER 1 |
1027 | #define DEFAULT_SLOPPY_TCP 0 | ||
1028 | #define DEFAULT_SLOPPY_SCTP 0 | ||
1047 | #define DEFAULT_SYNC_REFRESH_PERIOD (0U * HZ) | 1029 | #define DEFAULT_SYNC_REFRESH_PERIOD (0U * HZ) |
1048 | #define DEFAULT_SYNC_RETRIES 0 | 1030 | #define DEFAULT_SYNC_RETRIES 0 |
1049 | #define IPVS_SYNC_WAKEUP_RATE 8 | 1031 | #define IPVS_SYNC_WAKEUP_RATE 8 |
@@ -1080,11 +1062,26 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) | |||
1080 | return ipvs->sysctl_sync_ver; | 1062 | return ipvs->sysctl_sync_ver; |
1081 | } | 1063 | } |
1082 | 1064 | ||
1065 | static inline int sysctl_sloppy_tcp(struct netns_ipvs *ipvs) | ||
1066 | { | ||
1067 | return ipvs->sysctl_sloppy_tcp; | ||
1068 | } | ||
1069 | |||
1070 | static inline int sysctl_sloppy_sctp(struct netns_ipvs *ipvs) | ||
1071 | { | ||
1072 | return ipvs->sysctl_sloppy_sctp; | ||
1073 | } | ||
1074 | |||
1083 | static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) | 1075 | static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) |
1084 | { | 1076 | { |
1085 | return ACCESS_ONCE(ipvs->sysctl_sync_ports); | 1077 | return ACCESS_ONCE(ipvs->sysctl_sync_ports); |
1086 | } | 1078 | } |
1087 | 1079 | ||
1080 | static inline int sysctl_sync_persist_mode(struct netns_ipvs *ipvs) | ||
1081 | { | ||
1082 | return ipvs->sysctl_sync_persist_mode; | ||
1083 | } | ||
1084 | |||
1088 | static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) | 1085 | static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) |
1089 | { | 1086 | { |
1090 | return ipvs->sysctl_sync_qlen_max; | 1087 | return ipvs->sysctl_sync_qlen_max; |
@@ -1133,11 +1130,26 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) | |||
1133 | return DEFAULT_SYNC_VER; | 1130 | return DEFAULT_SYNC_VER; |
1134 | } | 1131 | } |
1135 | 1132 | ||
1133 | static inline int sysctl_sloppy_tcp(struct netns_ipvs *ipvs) | ||
1134 | { | ||
1135 | return DEFAULT_SLOPPY_TCP; | ||
1136 | } | ||
1137 | |||
1138 | static inline int sysctl_sloppy_sctp(struct netns_ipvs *ipvs) | ||
1139 | { | ||
1140 | return DEFAULT_SLOPPY_SCTP; | ||
1141 | } | ||
1142 | |||
1136 | static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) | 1143 | static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) |
1137 | { | 1144 | { |
1138 | return 1; | 1145 | return 1; |
1139 | } | 1146 | } |
1140 | 1147 | ||
1148 | static inline int sysctl_sync_persist_mode(struct netns_ipvs *ipvs) | ||
1149 | { | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1141 | static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) | 1153 | static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) |
1142 | { | 1154 | { |
1143 | return IPVS_SYNC_QLEN_MAX; | 1155 | return IPVS_SYNC_QLEN_MAX; |
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 495bc57f292c..84e37b1ca9e1 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -115,7 +115,9 @@ struct net { | |||
115 | #ifdef CONFIG_XFRM | 115 | #ifdef CONFIG_XFRM |
116 | struct netns_xfrm xfrm; | 116 | struct netns_xfrm xfrm; |
117 | #endif | 117 | #endif |
118 | #if IS_ENABLED(CONFIG_IP_VS) | ||
118 | struct netns_ipvs *ipvs; | 119 | struct netns_ipvs *ipvs; |
120 | #endif | ||
119 | struct sock *diag_nlsk; | 121 | struct sock *diag_nlsk; |
120 | atomic_t rt_genid; | 122 | atomic_t rt_genid; |
121 | atomic_t fnhe_genid; | 123 | atomic_t fnhe_genid; |
diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h index a24537725e80..29458223d044 100644 --- a/include/uapi/linux/ip_vs.h +++ b/include/uapi/linux/ip_vs.h | |||
@@ -20,6 +20,12 @@ | |||
20 | #define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */ | 20 | #define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */ |
21 | #define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */ | 21 | #define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */ |
22 | #define IP_VS_SVC_F_ONEPACKET 0x0004 /* one-packet scheduling */ | 22 | #define IP_VS_SVC_F_ONEPACKET 0x0004 /* one-packet scheduling */ |
23 | #define IP_VS_SVC_F_SCHED1 0x0008 /* scheduler flag 1 */ | ||
24 | #define IP_VS_SVC_F_SCHED2 0x0010 /* scheduler flag 2 */ | ||
25 | #define IP_VS_SVC_F_SCHED3 0x0020 /* scheduler flag 3 */ | ||
26 | |||
27 | #define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */ | ||
28 | #define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */ | ||
23 | 29 | ||
24 | /* | 30 | /* |
25 | * Destination Server Flags | 31 | * Destination Server Flags |
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h index a2308ae5a73d..3a9b92147339 100644 --- a/include/uapi/linux/netfilter/nfnetlink_queue.h +++ b/include/uapi/linux/netfilter/nfnetlink_queue.h | |||
@@ -105,5 +105,7 @@ enum nfqnl_attr_config { | |||
105 | #define NFQA_SKB_CSUMNOTREADY (1 << 0) | 105 | #define NFQA_SKB_CSUMNOTREADY (1 << 0) |
106 | /* packet is GSO (i.e., exceeds device mtu) */ | 106 | /* packet is GSO (i.e., exceeds device mtu) */ |
107 | #define NFQA_SKB_GSO (1 << 1) | 107 | #define NFQA_SKB_GSO (1 << 1) |
108 | /* csum not validated (incoming device doesn't support hw checksum, etc.) */ | ||
109 | #define NFQA_SKB_CSUM_NOTVERIFIED (1 << 2) | ||
108 | 110 | ||
109 | #endif /* _NFNETLINK_QUEUE_H */ | 111 | #endif /* _NFNETLINK_QUEUE_H */ |
diff --git a/include/uapi/linux/netfilter/xt_socket.h b/include/uapi/linux/netfilter/xt_socket.h index 26d7217bd4f1..6315e2ac3474 100644 --- a/include/uapi/linux/netfilter/xt_socket.h +++ b/include/uapi/linux/netfilter/xt_socket.h | |||
@@ -5,10 +5,17 @@ | |||
5 | 5 | ||
6 | enum { | 6 | enum { |
7 | XT_SOCKET_TRANSPARENT = 1 << 0, | 7 | XT_SOCKET_TRANSPARENT = 1 << 0, |
8 | XT_SOCKET_NOWILDCARD = 1 << 1, | ||
8 | }; | 9 | }; |
9 | 10 | ||
10 | struct xt_socket_mtinfo1 { | 11 | struct xt_socket_mtinfo1 { |
11 | __u8 flags; | 12 | __u8 flags; |
12 | }; | 13 | }; |
14 | #define XT_SOCKET_FLAGS_V1 XT_SOCKET_TRANSPARENT | ||
15 | |||
16 | struct xt_socket_mtinfo2 { | ||
17 | __u8 flags; | ||
18 | }; | ||
19 | #define XT_SOCKET_FLAGS_V2 (XT_SOCKET_TRANSPARENT | XT_SOCKET_NOWILDCARD) | ||
13 | 20 | ||
14 | #endif /* _XT_SOCKET_H */ | 21 | #endif /* _XT_SOCKET_H */ |
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index aea4a9ea6fc8..b609213ca9a2 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include "../fs/xfs/xfs_sysctl.h" | 3 | #include "../fs/xfs/xfs_sysctl.h" |
4 | #include <linux/sunrpc/debug.h> | 4 | #include <linux/sunrpc/debug.h> |
5 | #include <linux/string.h> | 5 | #include <linux/string.h> |
6 | #include <net/ip_vs.h> | ||
7 | #include <linux/syscalls.h> | 6 | #include <linux/syscalls.h> |
8 | #include <linux/namei.h> | 7 | #include <linux/namei.h> |
9 | #include <linux/mount.h> | 8 | #include <linux/mount.h> |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index c8c52a98590b..4c8e5c0aa1ab 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
@@ -1231,6 +1231,18 @@ void ip_vs_random_dropentry(struct net *net) | |||
1231 | default: | 1231 | default: |
1232 | continue; | 1232 | continue; |
1233 | } | 1233 | } |
1234 | } else if (cp->protocol == IPPROTO_SCTP) { | ||
1235 | switch (cp->state) { | ||
1236 | case IP_VS_SCTP_S_INIT1: | ||
1237 | case IP_VS_SCTP_S_INIT: | ||
1238 | break; | ||
1239 | case IP_VS_SCTP_S_ESTABLISHED: | ||
1240 | if (todrop_entry(cp)) | ||
1241 | break; | ||
1242 | continue; | ||
1243 | default: | ||
1244 | continue; | ||
1245 | } | ||
1234 | } else { | 1246 | } else { |
1235 | if (!todrop_entry(cp)) | 1247 | if (!todrop_entry(cp)) |
1236 | continue; | 1248 | continue; |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 05565d2b3a61..e9b0330f220d 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -305,7 +305,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc, | |||
305 | * return *ignored=0 i.e. ICMP and NF_DROP | 305 | * return *ignored=0 i.e. ICMP and NF_DROP |
306 | */ | 306 | */ |
307 | sched = rcu_dereference(svc->scheduler); | 307 | sched = rcu_dereference(svc->scheduler); |
308 | dest = sched->schedule(svc, skb); | 308 | dest = sched->schedule(svc, skb, iph); |
309 | if (!dest) { | 309 | if (!dest) { |
310 | IP_VS_DBG(1, "p-schedule: no dest found.\n"); | 310 | IP_VS_DBG(1, "p-schedule: no dest found.\n"); |
311 | kfree(param.pe_data); | 311 | kfree(param.pe_data); |
@@ -452,7 +452,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, | |||
452 | } | 452 | } |
453 | 453 | ||
454 | sched = rcu_dereference(svc->scheduler); | 454 | sched = rcu_dereference(svc->scheduler); |
455 | dest = sched->schedule(svc, skb); | 455 | dest = sched->schedule(svc, skb, iph); |
456 | if (dest == NULL) { | 456 | if (dest == NULL) { |
457 | IP_VS_DBG(1, "Schedule: no dest found.\n"); | 457 | IP_VS_DBG(1, "Schedule: no dest found.\n"); |
458 | return NULL; | 458 | return NULL; |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 47e510819f54..c8148e487386 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -1715,6 +1715,12 @@ static struct ctl_table vs_vars[] = { | |||
1715 | .proc_handler = &proc_do_sync_ports, | 1715 | .proc_handler = &proc_do_sync_ports, |
1716 | }, | 1716 | }, |
1717 | { | 1717 | { |
1718 | .procname = "sync_persist_mode", | ||
1719 | .maxlen = sizeof(int), | ||
1720 | .mode = 0644, | ||
1721 | .proc_handler = proc_dointvec, | ||
1722 | }, | ||
1723 | { | ||
1718 | .procname = "sync_qlen_max", | 1724 | .procname = "sync_qlen_max", |
1719 | .maxlen = sizeof(unsigned long), | 1725 | .maxlen = sizeof(unsigned long), |
1720 | .mode = 0644, | 1726 | .mode = 0644, |
@@ -1739,6 +1745,18 @@ static struct ctl_table vs_vars[] = { | |||
1739 | .proc_handler = proc_dointvec, | 1745 | .proc_handler = proc_dointvec, |
1740 | }, | 1746 | }, |
1741 | { | 1747 | { |
1748 | .procname = "sloppy_tcp", | ||
1749 | .maxlen = sizeof(int), | ||
1750 | .mode = 0644, | ||
1751 | .proc_handler = proc_dointvec, | ||
1752 | }, | ||
1753 | { | ||
1754 | .procname = "sloppy_sctp", | ||
1755 | .maxlen = sizeof(int), | ||
1756 | .mode = 0644, | ||
1757 | .proc_handler = proc_dointvec, | ||
1758 | }, | ||
1759 | { | ||
1742 | .procname = "expire_quiescent_template", | 1760 | .procname = "expire_quiescent_template", |
1743 | .maxlen = sizeof(int), | 1761 | .maxlen = sizeof(int), |
1744 | .mode = 0644, | 1762 | .mode = 0644, |
@@ -3717,12 +3735,15 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) | |||
3717 | tbl[idx++].data = &ipvs->sysctl_sync_ver; | 3735 | tbl[idx++].data = &ipvs->sysctl_sync_ver; |
3718 | ipvs->sysctl_sync_ports = 1; | 3736 | ipvs->sysctl_sync_ports = 1; |
3719 | tbl[idx++].data = &ipvs->sysctl_sync_ports; | 3737 | tbl[idx++].data = &ipvs->sysctl_sync_ports; |
3738 | tbl[idx++].data = &ipvs->sysctl_sync_persist_mode; | ||
3720 | ipvs->sysctl_sync_qlen_max = nr_free_buffer_pages() / 32; | 3739 | ipvs->sysctl_sync_qlen_max = nr_free_buffer_pages() / 32; |
3721 | tbl[idx++].data = &ipvs->sysctl_sync_qlen_max; | 3740 | tbl[idx++].data = &ipvs->sysctl_sync_qlen_max; |
3722 | ipvs->sysctl_sync_sock_size = 0; | 3741 | ipvs->sysctl_sync_sock_size = 0; |
3723 | tbl[idx++].data = &ipvs->sysctl_sync_sock_size; | 3742 | tbl[idx++].data = &ipvs->sysctl_sync_sock_size; |
3724 | tbl[idx++].data = &ipvs->sysctl_cache_bypass; | 3743 | tbl[idx++].data = &ipvs->sysctl_cache_bypass; |
3725 | tbl[idx++].data = &ipvs->sysctl_expire_nodest_conn; | 3744 | tbl[idx++].data = &ipvs->sysctl_expire_nodest_conn; |
3745 | tbl[idx++].data = &ipvs->sysctl_sloppy_tcp; | ||
3746 | tbl[idx++].data = &ipvs->sysctl_sloppy_sctp; | ||
3726 | tbl[idx++].data = &ipvs->sysctl_expire_quiescent_template; | 3747 | tbl[idx++].data = &ipvs->sysctl_expire_quiescent_template; |
3727 | ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD; | 3748 | ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD; |
3728 | ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD; | 3749 | ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD; |
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c index ccab120df45e..c3b84546ea9e 100644 --- a/net/netfilter/ipvs/ip_vs_dh.c +++ b/net/netfilter/ipvs/ip_vs_dh.c | |||
@@ -214,18 +214,16 @@ static inline int is_overloaded(struct ip_vs_dest *dest) | |||
214 | * Destination hashing scheduling | 214 | * Destination hashing scheduling |
215 | */ | 215 | */ |
216 | static struct ip_vs_dest * | 216 | static struct ip_vs_dest * |
217 | ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 217 | ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
218 | struct ip_vs_iphdr *iph) | ||
218 | { | 219 | { |
219 | struct ip_vs_dest *dest; | 220 | struct ip_vs_dest *dest; |
220 | struct ip_vs_dh_state *s; | 221 | struct ip_vs_dh_state *s; |
221 | struct ip_vs_iphdr iph; | ||
222 | |||
223 | ip_vs_fill_iph_addr_only(svc->af, skb, &iph); | ||
224 | 222 | ||
225 | IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); | 223 | IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); |
226 | 224 | ||
227 | s = (struct ip_vs_dh_state *) svc->sched_data; | 225 | s = (struct ip_vs_dh_state *) svc->sched_data; |
228 | dest = ip_vs_dh_get(svc->af, s, &iph.daddr); | 226 | dest = ip_vs_dh_get(svc->af, s, &iph->daddr); |
229 | if (!dest | 227 | if (!dest |
230 | || !(dest->flags & IP_VS_DEST_F_AVAILABLE) | 228 | || !(dest->flags & IP_VS_DEST_F_AVAILABLE) |
231 | || atomic_read(&dest->weight) <= 0 | 229 | || atomic_read(&dest->weight) <= 0 |
@@ -235,7 +233,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
235 | } | 233 | } |
236 | 234 | ||
237 | IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n", | 235 | IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n", |
238 | IP_VS_DBG_ADDR(svc->af, &iph.daddr), | 236 | IP_VS_DBG_ADDR(svc->af, &iph->daddr), |
239 | IP_VS_DBG_ADDR(svc->af, &dest->addr), | 237 | IP_VS_DBG_ADDR(svc->af, &dest->addr), |
240 | ntohs(dest->port)); | 238 | ntohs(dest->port)); |
241 | 239 | ||
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 44595b8ae37f..1383b0eadc0e 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c | |||
@@ -487,19 +487,17 @@ is_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc) | |||
487 | * Locality-Based (weighted) Least-Connection scheduling | 487 | * Locality-Based (weighted) Least-Connection scheduling |
488 | */ | 488 | */ |
489 | static struct ip_vs_dest * | 489 | static struct ip_vs_dest * |
490 | ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 490 | ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
491 | struct ip_vs_iphdr *iph) | ||
491 | { | 492 | { |
492 | struct ip_vs_lblc_table *tbl = svc->sched_data; | 493 | struct ip_vs_lblc_table *tbl = svc->sched_data; |
493 | struct ip_vs_iphdr iph; | ||
494 | struct ip_vs_dest *dest = NULL; | 494 | struct ip_vs_dest *dest = NULL; |
495 | struct ip_vs_lblc_entry *en; | 495 | struct ip_vs_lblc_entry *en; |
496 | 496 | ||
497 | ip_vs_fill_iph_addr_only(svc->af, skb, &iph); | ||
498 | |||
499 | IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); | 497 | IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); |
500 | 498 | ||
501 | /* First look in our cache */ | 499 | /* First look in our cache */ |
502 | en = ip_vs_lblc_get(svc->af, tbl, &iph.daddr); | 500 | en = ip_vs_lblc_get(svc->af, tbl, &iph->daddr); |
503 | if (en) { | 501 | if (en) { |
504 | /* We only hold a read lock, but this is atomic */ | 502 | /* We only hold a read lock, but this is atomic */ |
505 | en->lastuse = jiffies; | 503 | en->lastuse = jiffies; |
@@ -529,12 +527,12 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
529 | /* If we fail to create a cache entry, we'll just use the valid dest */ | 527 | /* If we fail to create a cache entry, we'll just use the valid dest */ |
530 | spin_lock_bh(&svc->sched_lock); | 528 | spin_lock_bh(&svc->sched_lock); |
531 | if (!tbl->dead) | 529 | if (!tbl->dead) |
532 | ip_vs_lblc_new(tbl, &iph.daddr, dest); | 530 | ip_vs_lblc_new(tbl, &iph->daddr, dest); |
533 | spin_unlock_bh(&svc->sched_lock); | 531 | spin_unlock_bh(&svc->sched_lock); |
534 | 532 | ||
535 | out: | 533 | out: |
536 | IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n", | 534 | IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n", |
537 | IP_VS_DBG_ADDR(svc->af, &iph.daddr), | 535 | IP_VS_DBG_ADDR(svc->af, &iph->daddr), |
538 | IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); | 536 | IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); |
539 | 537 | ||
540 | return dest; | 538 | return dest; |
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index 876937db0bf4..3cd85b2fc67c 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c | |||
@@ -655,19 +655,17 @@ is_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc) | |||
655 | * Locality-Based (weighted) Least-Connection scheduling | 655 | * Locality-Based (weighted) Least-Connection scheduling |
656 | */ | 656 | */ |
657 | static struct ip_vs_dest * | 657 | static struct ip_vs_dest * |
658 | ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 658 | ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
659 | struct ip_vs_iphdr *iph) | ||
659 | { | 660 | { |
660 | struct ip_vs_lblcr_table *tbl = svc->sched_data; | 661 | struct ip_vs_lblcr_table *tbl = svc->sched_data; |
661 | struct ip_vs_iphdr iph; | ||
662 | struct ip_vs_dest *dest; | 662 | struct ip_vs_dest *dest; |
663 | struct ip_vs_lblcr_entry *en; | 663 | struct ip_vs_lblcr_entry *en; |
664 | 664 | ||
665 | ip_vs_fill_iph_addr_only(svc->af, skb, &iph); | ||
666 | |||
667 | IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); | 665 | IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); |
668 | 666 | ||
669 | /* First look in our cache */ | 667 | /* First look in our cache */ |
670 | en = ip_vs_lblcr_get(svc->af, tbl, &iph.daddr); | 668 | en = ip_vs_lblcr_get(svc->af, tbl, &iph->daddr); |
671 | if (en) { | 669 | if (en) { |
672 | en->lastuse = jiffies; | 670 | en->lastuse = jiffies; |
673 | 671 | ||
@@ -718,12 +716,12 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
718 | /* If we fail to create a cache entry, we'll just use the valid dest */ | 716 | /* If we fail to create a cache entry, we'll just use the valid dest */ |
719 | spin_lock_bh(&svc->sched_lock); | 717 | spin_lock_bh(&svc->sched_lock); |
720 | if (!tbl->dead) | 718 | if (!tbl->dead) |
721 | ip_vs_lblcr_new(tbl, &iph.daddr, dest); | 719 | ip_vs_lblcr_new(tbl, &iph->daddr, dest); |
722 | spin_unlock_bh(&svc->sched_lock); | 720 | spin_unlock_bh(&svc->sched_lock); |
723 | 721 | ||
724 | out: | 722 | out: |
725 | IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n", | 723 | IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n", |
726 | IP_VS_DBG_ADDR(svc->af, &iph.daddr), | 724 | IP_VS_DBG_ADDR(svc->af, &iph->daddr), |
727 | IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); | 725 | IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); |
728 | 726 | ||
729 | return dest; | 727 | return dest; |
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c index 5128e338a749..2bdcb1cf2127 100644 --- a/net/netfilter/ipvs/ip_vs_lc.c +++ b/net/netfilter/ipvs/ip_vs_lc.c | |||
@@ -26,7 +26,8 @@ | |||
26 | * Least Connection scheduling | 26 | * Least Connection scheduling |
27 | */ | 27 | */ |
28 | static struct ip_vs_dest * | 28 | static struct ip_vs_dest * |
29 | ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 29 | ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
30 | struct ip_vs_iphdr *iph) | ||
30 | { | 31 | { |
31 | struct ip_vs_dest *dest, *least = NULL; | 32 | struct ip_vs_dest *dest, *least = NULL; |
32 | unsigned int loh = 0, doh; | 33 | unsigned int loh = 0, doh; |
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c index 646cfd4baa73..d8d9860934fe 100644 --- a/net/netfilter/ipvs/ip_vs_nq.c +++ b/net/netfilter/ipvs/ip_vs_nq.c | |||
@@ -55,7 +55,8 @@ ip_vs_nq_dest_overhead(struct ip_vs_dest *dest) | |||
55 | * Weighted Least Connection scheduling | 55 | * Weighted Least Connection scheduling |
56 | */ | 56 | */ |
57 | static struct ip_vs_dest * | 57 | static struct ip_vs_dest * |
58 | ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 58 | ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
59 | struct ip_vs_iphdr *iph) | ||
59 | { | 60 | { |
60 | struct ip_vs_dest *dest, *least = NULL; | 61 | struct ip_vs_dest *dest, *least = NULL; |
61 | unsigned int loh = 0, doh; | 62 | unsigned int loh = 0, doh; |
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index 86464881cd20..3c0da8728036 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c | |||
@@ -15,6 +15,7 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
15 | { | 15 | { |
16 | struct net *net; | 16 | struct net *net; |
17 | struct ip_vs_service *svc; | 17 | struct ip_vs_service *svc; |
18 | struct netns_ipvs *ipvs; | ||
18 | sctp_chunkhdr_t _schunkh, *sch; | 19 | sctp_chunkhdr_t _schunkh, *sch; |
19 | sctp_sctphdr_t *sh, _sctph; | 20 | sctp_sctphdr_t *sh, _sctph; |
20 | 21 | ||
@@ -27,13 +28,14 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
27 | if (sch == NULL) | 28 | if (sch == NULL) |
28 | return 0; | 29 | return 0; |
29 | net = skb_net(skb); | 30 | net = skb_net(skb); |
31 | ipvs = net_ipvs(net); | ||
30 | rcu_read_lock(); | 32 | rcu_read_lock(); |
31 | if ((sch->type == SCTP_CID_INIT) && | 33 | if ((sch->type == SCTP_CID_INIT || sysctl_sloppy_sctp(ipvs)) && |
32 | (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol, | 34 | (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol, |
33 | &iph->daddr, sh->dest))) { | 35 | &iph->daddr, sh->dest))) { |
34 | int ignored; | 36 | int ignored; |
35 | 37 | ||
36 | if (ip_vs_todrop(net_ipvs(net))) { | 38 | if (ip_vs_todrop(ipvs)) { |
37 | /* | 39 | /* |
38 | * It seems that we are very loaded. | 40 | * It seems that we are very loaded. |
39 | * We have to drop this packet :( | 41 | * We have to drop this packet :( |
@@ -183,710 +185,159 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) | |||
183 | return 1; | 185 | return 1; |
184 | } | 186 | } |
185 | 187 | ||
186 | struct ipvs_sctp_nextstate { | ||
187 | int next_state; | ||
188 | }; | ||
189 | enum ipvs_sctp_event_t { | 188 | enum ipvs_sctp_event_t { |
190 | IP_VS_SCTP_EVE_DATA_CLI, | 189 | IP_VS_SCTP_DATA = 0, /* DATA, SACK, HEARTBEATs */ |
191 | IP_VS_SCTP_EVE_DATA_SER, | 190 | IP_VS_SCTP_INIT, |
192 | IP_VS_SCTP_EVE_INIT_CLI, | 191 | IP_VS_SCTP_INIT_ACK, |
193 | IP_VS_SCTP_EVE_INIT_SER, | 192 | IP_VS_SCTP_COOKIE_ECHO, |
194 | IP_VS_SCTP_EVE_INIT_ACK_CLI, | 193 | IP_VS_SCTP_COOKIE_ACK, |
195 | IP_VS_SCTP_EVE_INIT_ACK_SER, | 194 | IP_VS_SCTP_SHUTDOWN, |
196 | IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, | 195 | IP_VS_SCTP_SHUTDOWN_ACK, |
197 | IP_VS_SCTP_EVE_COOKIE_ECHO_SER, | 196 | IP_VS_SCTP_SHUTDOWN_COMPLETE, |
198 | IP_VS_SCTP_EVE_COOKIE_ACK_CLI, | 197 | IP_VS_SCTP_ERROR, |
199 | IP_VS_SCTP_EVE_COOKIE_ACK_SER, | 198 | IP_VS_SCTP_ABORT, |
200 | IP_VS_SCTP_EVE_ABORT_CLI, | 199 | IP_VS_SCTP_EVENT_LAST |
201 | IP_VS_SCTP_EVE__ABORT_SER, | ||
202 | IP_VS_SCTP_EVE_SHUT_CLI, | ||
203 | IP_VS_SCTP_EVE_SHUT_SER, | ||
204 | IP_VS_SCTP_EVE_SHUT_ACK_CLI, | ||
205 | IP_VS_SCTP_EVE_SHUT_ACK_SER, | ||
206 | IP_VS_SCTP_EVE_SHUT_COM_CLI, | ||
207 | IP_VS_SCTP_EVE_SHUT_COM_SER, | ||
208 | IP_VS_SCTP_EVE_LAST | ||
209 | }; | 200 | }; |
210 | 201 | ||
211 | static enum ipvs_sctp_event_t sctp_events[256] = { | 202 | /* RFC 2960, 3.2 Chunk Field Descriptions */ |
212 | IP_VS_SCTP_EVE_DATA_CLI, | 203 | static __u8 sctp_events[] = { |
213 | IP_VS_SCTP_EVE_INIT_CLI, | 204 | [SCTP_CID_DATA] = IP_VS_SCTP_DATA, |
214 | IP_VS_SCTP_EVE_INIT_ACK_CLI, | 205 | [SCTP_CID_INIT] = IP_VS_SCTP_INIT, |
215 | IP_VS_SCTP_EVE_DATA_CLI, | 206 | [SCTP_CID_INIT_ACK] = IP_VS_SCTP_INIT_ACK, |
216 | IP_VS_SCTP_EVE_DATA_CLI, | 207 | [SCTP_CID_SACK] = IP_VS_SCTP_DATA, |
217 | IP_VS_SCTP_EVE_DATA_CLI, | 208 | [SCTP_CID_HEARTBEAT] = IP_VS_SCTP_DATA, |
218 | IP_VS_SCTP_EVE_ABORT_CLI, | 209 | [SCTP_CID_HEARTBEAT_ACK] = IP_VS_SCTP_DATA, |
219 | IP_VS_SCTP_EVE_SHUT_CLI, | 210 | [SCTP_CID_ABORT] = IP_VS_SCTP_ABORT, |
220 | IP_VS_SCTP_EVE_SHUT_ACK_CLI, | 211 | [SCTP_CID_SHUTDOWN] = IP_VS_SCTP_SHUTDOWN, |
221 | IP_VS_SCTP_EVE_DATA_CLI, | 212 | [SCTP_CID_SHUTDOWN_ACK] = IP_VS_SCTP_SHUTDOWN_ACK, |
222 | IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, | 213 | [SCTP_CID_ERROR] = IP_VS_SCTP_ERROR, |
223 | IP_VS_SCTP_EVE_COOKIE_ACK_CLI, | 214 | [SCTP_CID_COOKIE_ECHO] = IP_VS_SCTP_COOKIE_ECHO, |
224 | IP_VS_SCTP_EVE_DATA_CLI, | 215 | [SCTP_CID_COOKIE_ACK] = IP_VS_SCTP_COOKIE_ACK, |
225 | IP_VS_SCTP_EVE_DATA_CLI, | 216 | [SCTP_CID_ECN_ECNE] = IP_VS_SCTP_DATA, |
226 | IP_VS_SCTP_EVE_SHUT_COM_CLI, | 217 | [SCTP_CID_ECN_CWR] = IP_VS_SCTP_DATA, |
218 | [SCTP_CID_SHUTDOWN_COMPLETE] = IP_VS_SCTP_SHUTDOWN_COMPLETE, | ||
227 | }; | 219 | }; |
228 | 220 | ||
229 | static struct ipvs_sctp_nextstate | 221 | /* SCTP States: |
230 | sctp_states_table[IP_VS_SCTP_S_LAST][IP_VS_SCTP_EVE_LAST] = { | 222 | * See RFC 2960, 4. SCTP Association State Diagram |
231 | /* | 223 | * |
232 | * STATE : IP_VS_SCTP_S_NONE | 224 | * New states (not in diagram): |
233 | */ | 225 | * - INIT1 state: use shorter timeout for dropped INIT packets |
234 | /*next state *//*event */ | 226 | * - REJECTED state: use shorter timeout if INIT is rejected with ABORT |
235 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | 227 | * - INIT, COOKIE_SENT, COOKIE_REPLIED, COOKIE states: for better debugging |
236 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | 228 | * |
237 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | 229 | * The states are as seen in real server. In the diagram, INIT1, INIT, |
238 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | 230 | * COOKIE_SENT and COOKIE_REPLIED processing happens in CLOSED state. |
239 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | 231 | * |
240 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | 232 | * States as per packets from client (C) and server (S): |
241 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | 233 | * |
242 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | 234 | * Setup of client connection: |
243 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | 235 | * IP_VS_SCTP_S_INIT1: First C:INIT sent, wait for S:INIT-ACK |
244 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | 236 | * IP_VS_SCTP_S_INIT: Next C:INIT sent, wait for S:INIT-ACK |
245 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | 237 | * IP_VS_SCTP_S_COOKIE_SENT: S:INIT-ACK sent, wait for C:COOKIE-ECHO |
246 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | 238 | * IP_VS_SCTP_S_COOKIE_REPLIED: C:COOKIE-ECHO sent, wait for S:COOKIE-ACK |
247 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | 239 | * |
248 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | 240 | * Setup of server connection: |
249 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | 241 | * IP_VS_SCTP_S_COOKIE_WAIT: S:INIT sent, wait for C:INIT-ACK |
250 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | 242 | * IP_VS_SCTP_S_COOKIE: C:INIT-ACK sent, wait for S:COOKIE-ECHO |
251 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | 243 | * IP_VS_SCTP_S_COOKIE_ECHOED: S:COOKIE-ECHO sent, wait for C:COOKIE-ACK |
252 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ }, | 244 | */ |
253 | }, | ||
254 | /* | ||
255 | * STATE : IP_VS_SCTP_S_INIT_CLI | ||
256 | * Cient sent INIT and is waiting for reply from server(In ECHO_WAIT) | ||
257 | */ | ||
258 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
259 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
260 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
261 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
262 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
263 | {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
264 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ECHO_CLI */ }, | ||
265 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_ECHO_SER */ }, | ||
266 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
267 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
268 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
269 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
270 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
271 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
272 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
273 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
274 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
275 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
276 | }, | ||
277 | /* | ||
278 | * State : IP_VS_SCTP_S_INIT_SER | ||
279 | * Server sent INIT and waiting for INIT ACK from the client | ||
280 | */ | ||
281 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
282 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
283 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
284 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
285 | {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
286 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
287 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
288 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
289 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
290 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
291 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
292 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
293 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
294 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
295 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
296 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
297 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
298 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
299 | }, | ||
300 | /* | ||
301 | * State : IP_VS_SCTP_S_INIT_ACK_CLI | ||
302 | * Client sent INIT ACK and waiting for ECHO from the server | ||
303 | */ | ||
304 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
305 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
306 | /* | ||
307 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
308 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
309 | * an INIT ACK using the same parameters it sent in its original | ||
310 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
311 | */ | ||
312 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
313 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
314 | /* | ||
315 | * INIT_ACK has been resent by the client, let us stay is in | ||
316 | * the same state | ||
317 | */ | ||
318 | {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
319 | /* | ||
320 | * INIT_ACK sent by the server, close the connection | ||
321 | */ | ||
322 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
323 | /* | ||
324 | * ECHO by client, it should not happen, close the connection | ||
325 | */ | ||
326 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
327 | /* | ||
328 | * ECHO by server, this is what we are expecting, move to ECHO_SER | ||
329 | */ | ||
330 | {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
331 | /* | ||
332 | * COOKIE ACK from client, it should not happen, close the connection | ||
333 | */ | ||
334 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
335 | /* | ||
336 | * Unexpected COOKIE ACK from server, staty in the same state | ||
337 | */ | ||
338 | {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
339 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
340 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
341 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
342 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
343 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
344 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
345 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
346 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
347 | }, | ||
348 | /* | ||
349 | * State : IP_VS_SCTP_S_INIT_ACK_SER | ||
350 | * Server sent INIT ACK and waiting for ECHO from the client | ||
351 | */ | ||
352 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
353 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
354 | /* | ||
355 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
356 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
357 | * an INIT ACK using the same parameters it sent in its original | ||
358 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
359 | */ | ||
360 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
361 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
362 | /* | ||
363 | * Unexpected INIT_ACK by the client, let us close the connection | ||
364 | */ | ||
365 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
366 | /* | ||
367 | * INIT_ACK resent by the server, let us move to same state | ||
368 | */ | ||
369 | {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
370 | /* | ||
371 | * Client send the ECHO, this is what we are expecting, | ||
372 | * move to ECHO_CLI | ||
373 | */ | ||
374 | {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
375 | /* | ||
376 | * ECHO received from the server, Not sure what to do, | ||
377 | * let us close it | ||
378 | */ | ||
379 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
380 | /* | ||
381 | * COOKIE ACK from client, let us stay in the same state | ||
382 | */ | ||
383 | {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
384 | /* | ||
385 | * COOKIE ACK from server, hmm... this should not happen, lets close | ||
386 | * the connection. | ||
387 | */ | ||
388 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
389 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
390 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
391 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
392 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
393 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
394 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
395 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
396 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
397 | }, | ||
398 | /* | ||
399 | * State : IP_VS_SCTP_S_ECHO_CLI | ||
400 | * Cient sent ECHO and waiting COOKEI ACK from the Server | ||
401 | */ | ||
402 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
403 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
404 | /* | ||
405 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
406 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
407 | * an INIT ACK using the same parameters it sent in its original | ||
408 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
409 | */ | ||
410 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
411 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
412 | /* | ||
413 | * INIT_ACK has been by the client, let us close the connection | ||
414 | */ | ||
415 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
416 | /* | ||
417 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | ||
418 | * “If an INIT ACK is received by an endpoint in any state other | ||
419 | * than the COOKIE-WAIT state, the endpoint should discard the | ||
420 | * INIT ACK chunk”. Stay in the same state | ||
421 | */ | ||
422 | {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
423 | /* | ||
424 | * Client resent the ECHO, let us stay in the same state | ||
425 | */ | ||
426 | {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
427 | /* | ||
428 | * ECHO received from the server, Not sure what to do, | ||
429 | * let us close it | ||
430 | */ | ||
431 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
432 | /* | ||
433 | * COOKIE ACK from client, this shoud not happen, let's close the | ||
434 | * connection | ||
435 | */ | ||
436 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
437 | /* | ||
438 | * COOKIE ACK from server, this is what we are awaiting,lets move to | ||
439 | * ESTABLISHED. | ||
440 | */ | ||
441 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
442 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
443 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
444 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
445 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
446 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
447 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
448 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
449 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
450 | }, | ||
451 | /* | ||
452 | * State : IP_VS_SCTP_S_ECHO_SER | ||
453 | * Server sent ECHO and waiting COOKEI ACK from the client | ||
454 | */ | ||
455 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
456 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
457 | /* | ||
458 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
459 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
460 | * an INIT ACK using the same parameters it sent in its original | ||
461 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
462 | */ | ||
463 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
464 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
465 | /* | ||
466 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | ||
467 | * “If an INIT ACK is received by an endpoint in any state other | ||
468 | * than the COOKIE-WAIT state, the endpoint should discard the | ||
469 | * INIT ACK chunk”. Stay in the same state | ||
470 | */ | ||
471 | {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
472 | /* | ||
473 | * INIT_ACK has been by the server, let us close the connection | ||
474 | */ | ||
475 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
476 | /* | ||
477 | * Client sent the ECHO, not sure what to do, let's close the | ||
478 | * connection. | ||
479 | */ | ||
480 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
481 | /* | ||
482 | * ECHO resent by the server, stay in the same state | ||
483 | */ | ||
484 | {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
485 | /* | ||
486 | * COOKIE ACK from client, this is what we are expecting, let's move | ||
487 | * to ESTABLISHED. | ||
488 | */ | ||
489 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
490 | /* | ||
491 | * COOKIE ACK from server, this should not happen, lets close the | ||
492 | * connection. | ||
493 | */ | ||
494 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
495 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
496 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
497 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
498 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
499 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
500 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
501 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
502 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
503 | }, | ||
504 | /* | ||
505 | * State : IP_VS_SCTP_S_ESTABLISHED | ||
506 | * Association established | ||
507 | */ | ||
508 | {{IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
509 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
510 | /* | ||
511 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
512 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
513 | * an INIT ACK using the same parameters it sent in its original | ||
514 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
515 | */ | ||
516 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
517 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
518 | /* | ||
519 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | ||
520 | * “If an INIT ACK is received by an endpoint in any state other | ||
521 | * than the COOKIE-WAIT state, the endpoint should discard the | ||
522 | * INIT ACK chunk”. Stay in the same state | ||
523 | */ | ||
524 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
525 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
526 | /* | ||
527 | * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the | ||
528 | * peer and peer shall move to the ESTABISHED. if it doesn't handle | ||
529 | * it will send ERROR chunk. So, stay in the same state | ||
530 | */ | ||
531 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
532 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
533 | /* | ||
534 | * COOKIE ACK from client, not sure what to do stay in the same state | ||
535 | */ | ||
536 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
537 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
538 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
539 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
540 | /* | ||
541 | * SHUTDOWN from the client, move to SHUDDOWN_CLI | ||
542 | */ | ||
543 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
544 | /* | ||
545 | * SHUTDOWN from the server, move to SHUTDOWN_SER | ||
546 | */ | ||
547 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
548 | /* | ||
549 | * client sent SHUDTDOWN_ACK, this should not happen, let's close | ||
550 | * the connection | ||
551 | */ | ||
552 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
553 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
554 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
555 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
556 | }, | ||
557 | /* | ||
558 | * State : IP_VS_SCTP_S_SHUT_CLI | ||
559 | * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server | ||
560 | */ | ||
561 | /* | ||
562 | * We received the data chuck, keep the state unchanged. I assume | ||
563 | * that still data chuncks can be received by both the peers in | ||
564 | * SHUDOWN state | ||
565 | */ | ||
566 | |||
567 | {{IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
568 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
569 | /* | ||
570 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
571 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
572 | * an INIT ACK using the same parameters it sent in its original | ||
573 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
574 | */ | ||
575 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
576 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
577 | /* | ||
578 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | ||
579 | * “If an INIT ACK is received by an endpoint in any state other | ||
580 | * than the COOKIE-WAIT state, the endpoint should discard the | ||
581 | * INIT ACK chunk”. Stay in the same state | ||
582 | */ | ||
583 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
584 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
585 | /* | ||
586 | * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the | ||
587 | * peer and peer shall move to the ESTABISHED. if it doesn't handle | ||
588 | * it will send ERROR chunk. So, stay in the same state | ||
589 | */ | ||
590 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
591 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
592 | /* | ||
593 | * COOKIE ACK from client, not sure what to do stay in the same state | ||
594 | */ | ||
595 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
596 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
597 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
598 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
599 | /* | ||
600 | * SHUTDOWN resent from the client, move to SHUDDOWN_CLI | ||
601 | */ | ||
602 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
603 | /* | ||
604 | * SHUTDOWN from the server, move to SHUTDOWN_SER | ||
605 | */ | ||
606 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
607 | /* | ||
608 | * client sent SHUDTDOWN_ACK, this should not happen, let's close | ||
609 | * the connection | ||
610 | */ | ||
611 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
612 | /* | ||
613 | * Server sent SHUTDOWN ACK, this is what we are expecting, let's move | ||
614 | * to SHUDOWN_ACK_SER | ||
615 | */ | ||
616 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
617 | /* | ||
618 | * SHUTDOWN COM from client, this should not happen, let's close the | ||
619 | * connection | ||
620 | */ | ||
621 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
622 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
623 | }, | ||
624 | /* | ||
625 | * State : IP_VS_SCTP_S_SHUT_SER | ||
626 | * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client | ||
627 | */ | ||
628 | /* | ||
629 | * We received the data chuck, keep the state unchanged. I assume | ||
630 | * that still data chuncks can be received by both the peers in | ||
631 | * SHUDOWN state | ||
632 | */ | ||
633 | |||
634 | {{IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
635 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
636 | /* | ||
637 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
638 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
639 | * an INIT ACK using the same parameters it sent in its original | ||
640 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
641 | */ | ||
642 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
643 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
644 | /* | ||
645 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | ||
646 | * “If an INIT ACK is received by an endpoint in any state other | ||
647 | * than the COOKIE-WAIT state, the endpoint should discard the | ||
648 | * INIT ACK chunk”. Stay in the same state | ||
649 | */ | ||
650 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
651 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
652 | /* | ||
653 | * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the | ||
654 | * peer and peer shall move to the ESTABISHED. if it doesn't handle | ||
655 | * it will send ERROR chunk. So, stay in the same state | ||
656 | */ | ||
657 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
658 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
659 | /* | ||
660 | * COOKIE ACK from client, not sure what to do stay in the same state | ||
661 | */ | ||
662 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
663 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
664 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
665 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
666 | /* | ||
667 | * SHUTDOWN resent from the client, move to SHUDDOWN_CLI | ||
668 | */ | ||
669 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
670 | /* | ||
671 | * SHUTDOWN resent from the server, move to SHUTDOWN_SER | ||
672 | */ | ||
673 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
674 | /* | ||
675 | * client sent SHUDTDOWN_ACK, this is what we are expecting, let's | ||
676 | * move to SHUT_ACK_CLI | ||
677 | */ | ||
678 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
679 | /* | ||
680 | * Server sent SHUTDOWN ACK, this should not happen, let's close the | ||
681 | * connection | ||
682 | */ | ||
683 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
684 | /* | ||
685 | * SHUTDOWN COM from client, this should not happen, let's close the | ||
686 | * connection | ||
687 | */ | ||
688 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
689 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
690 | }, | ||
691 | |||
692 | /* | ||
693 | * State : IP_VS_SCTP_S_SHUT_ACK_CLI | ||
694 | * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server | ||
695 | */ | ||
696 | /* | ||
697 | * We received the data chuck, keep the state unchanged. I assume | ||
698 | * that still data chuncks can be received by both the peers in | ||
699 | * SHUDOWN state | ||
700 | */ | ||
701 | |||
702 | {{IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
703 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
704 | /* | ||
705 | * We have got an INIT from client. From the spec.“Upon receipt of | ||
706 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | ||
707 | * an INIT ACK using the same parameters it sent in its original | ||
708 | * INIT chunk (including its Initiate Tag, unchanged”). | ||
709 | */ | ||
710 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
711 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
712 | /* | ||
713 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | ||
714 | * “If an INIT ACK is received by an endpoint in any state other | ||
715 | * than the COOKIE-WAIT state, the endpoint should discard the | ||
716 | * INIT ACK chunk”. Stay in the same state | ||
717 | */ | ||
718 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
719 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
720 | /* | ||
721 | * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the | ||
722 | * peer and peer shall move to the ESTABISHED. if it doesn't handle | ||
723 | * it will send ERROR chunk. So, stay in the same state | ||
724 | */ | ||
725 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
726 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
727 | /* | ||
728 | * COOKIE ACK from client, not sure what to do stay in the same state | ||
729 | */ | ||
730 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
731 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
732 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
733 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
734 | /* | ||
735 | * SHUTDOWN sent from the client, move to SHUDDOWN_CLI | ||
736 | */ | ||
737 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
738 | /* | ||
739 | * SHUTDOWN sent from the server, move to SHUTDOWN_SER | ||
740 | */ | ||
741 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
742 | /* | ||
743 | * client resent SHUDTDOWN_ACK, let's stay in the same state | ||
744 | */ | ||
745 | {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
746 | /* | ||
747 | * Server sent SHUTDOWN ACK, this should not happen, let's close the | ||
748 | * connection | ||
749 | */ | ||
750 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
751 | /* | ||
752 | * SHUTDOWN COM from client, this should not happen, let's close the | ||
753 | * connection | ||
754 | */ | ||
755 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
756 | /* | ||
757 | * SHUTDOWN COMPLETE from server this is what we are expecting. | ||
758 | */ | ||
759 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
760 | }, | ||
761 | |||
762 | /* | ||
763 | * State : IP_VS_SCTP_S_SHUT_ACK_SER | ||
764 | * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client | ||
765 | */ | ||
766 | /* | ||
767 | * We received the data chuck, keep the state unchanged. I assume | ||
768 | * that still data chuncks can be received by both the peers in | ||
769 | * SHUDOWN state | ||
770 | */ | ||
771 | 245 | ||
772 | {{IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, | 246 | #define sNO IP_VS_SCTP_S_NONE |
773 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, | 247 | #define sI1 IP_VS_SCTP_S_INIT1 |
774 | /* | 248 | #define sIN IP_VS_SCTP_S_INIT |
775 | * We have got an INIT from client. From the spec.“Upon receipt of | 249 | #define sCS IP_VS_SCTP_S_COOKIE_SENT |
776 | * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with | 250 | #define sCR IP_VS_SCTP_S_COOKIE_REPLIED |
777 | * an INIT ACK using the same parameters it sent in its original | 251 | #define sCW IP_VS_SCTP_S_COOKIE_WAIT |
778 | * INIT chunk (including its Initiate Tag, unchanged”). | 252 | #define sCO IP_VS_SCTP_S_COOKIE |
779 | */ | 253 | #define sCE IP_VS_SCTP_S_COOKIE_ECHOED |
780 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | 254 | #define sES IP_VS_SCTP_S_ESTABLISHED |
781 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | 255 | #define sSS IP_VS_SCTP_S_SHUTDOWN_SENT |
782 | /* | 256 | #define sSR IP_VS_SCTP_S_SHUTDOWN_RECEIVED |
783 | * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, | 257 | #define sSA IP_VS_SCTP_S_SHUTDOWN_ACK_SENT |
784 | * “If an INIT ACK is received by an endpoint in any state other | 258 | #define sRJ IP_VS_SCTP_S_REJECTED |
785 | * than the COOKIE-WAIT state, the endpoint should discard the | 259 | #define sCL IP_VS_SCTP_S_CLOSED |
786 | * INIT ACK chunk”. Stay in the same state | 260 | |
787 | */ | 261 | static const __u8 sctp_states |
788 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | 262 | [IP_VS_DIR_LAST][IP_VS_SCTP_EVENT_LAST][IP_VS_SCTP_S_LAST] = { |
789 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | 263 | { /* INPUT */ |
790 | /* | 264 | /* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/ |
791 | * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the | 265 | /* d */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
792 | * peer and peer shall move to the ESTABISHED. if it doesn't handle | 266 | /* i */{sI1, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sIN, sIN}, |
793 | * it will send ERROR chunk. So, stay in the same state | 267 | /* i_a */{sCW, sCW, sCW, sCS, sCR, sCO, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
794 | */ | 268 | /* c_e */{sCR, sIN, sIN, sCR, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
795 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | 269 | /* c_a */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sES, sES, sSS, sSR, sSA, sRJ, sCL}, |
796 | {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | 270 | /* s */{sSR, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sSR, sSS, sSR, sSA, sRJ, sCL}, |
797 | /* | 271 | /* s_a */{sCL, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sES, sCL, sSR, sCL, sRJ, sCL}, |
798 | * COOKIE ACK from client, not sure what to do stay in the same state | 272 | /* s_c */{sCL, sCL, sCL, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sCL, sRJ, sCL}, |
799 | */ | 273 | /* err */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCL, sES, sSS, sSR, sSA, sRJ, sCL}, |
800 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | 274 | /* ab */{sCL, sCL, sCL, sCL, sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
801 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | 275 | }, |
802 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | 276 | { /* OUTPUT */ |
803 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | 277 | /* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/ |
804 | /* | 278 | /* d */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
805 | * SHUTDOWN sent from the client, move to SHUDDOWN_CLI | 279 | /* i */{sCW, sCW, sCW, sCW, sCW, sCW, sCW, sCW, sES, sCW, sCW, sCW, sCW, sCW}, |
806 | */ | 280 | /* i_a */{sCS, sCS, sCS, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
807 | {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | 281 | /* c_e */{sCE, sCE, sCE, sCE, sCE, sCE, sCE, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
808 | /* | 282 | /* c_a */{sES, sES, sES, sES, sES, sES, sES, sES, sES, sSS, sSR, sSA, sRJ, sCL}, |
809 | * SHUTDOWN sent from the server, move to SHUTDOWN_SER | 283 | /* s */{sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSR, sSA, sRJ, sCL}, |
810 | */ | 284 | /* s_a */{sSA, sSA, sSA, sSA, sSA, sCW, sCO, sCE, sES, sSA, sSA, sSA, sRJ, sCL}, |
811 | {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, | 285 | /* s_c */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
812 | /* | 286 | /* err */{sCL, sCL, sCL, sCL, sCL, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
813 | * client sent SHUDTDOWN_ACK, this should not happen let's close | 287 | /* ab */{sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
814 | * the connection. | 288 | }, |
815 | */ | 289 | { /* INPUT-ONLY */ |
816 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | 290 | /* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/ |
817 | /* | 291 | /* d */{sES, sI1, sIN, sCS, sCR, sES, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
818 | * Server resent SHUTDOWN ACK, stay in the same state | 292 | /* i */{sI1, sIN, sIN, sIN, sIN, sIN, sCO, sCE, sES, sSS, sSR, sSA, sIN, sIN}, |
819 | */ | 293 | /* i_a */{sCE, sCE, sCE, sCE, sCE, sCE, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
820 | {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | 294 | /* c_e */{sES, sES, sES, sES, sES, sES, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
821 | /* | 295 | /* c_a */{sES, sI1, sIN, sES, sES, sCW, sES, sES, sES, sSS, sSR, sSA, sRJ, sCL}, |
822 | * SHUTDOWN COM from client, this what we are expecting, let's close | 296 | /* s */{sSR, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sSR, sSS, sSR, sSA, sRJ, sCL}, |
823 | * the connection | 297 | /* s_a */{sCL, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sCL, sCL, sSR, sCL, sRJ, sCL}, |
824 | */ | 298 | /* s_c */{sCL, sCL, sCL, sCL, sCL, sCW, sCO, sCE, sES, sSS, sCL, sCL, sRJ, sCL}, |
825 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | 299 | /* err */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, |
826 | /* | 300 | /* ab */{sCL, sCL, sCL, sCL, sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
827 | * SHUTDOWN COMPLETE from server this should not happen. | 301 | }, |
828 | */ | ||
829 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
830 | }, | ||
831 | /* | ||
832 | * State : IP_VS_SCTP_S_CLOSED | ||
833 | */ | ||
834 | {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, | ||
835 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, | ||
836 | {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, | ||
837 | {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, | ||
838 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, | ||
839 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, | ||
840 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, | ||
841 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, | ||
842 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, | ||
843 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, | ||
844 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, | ||
845 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, | ||
846 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, | ||
847 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, | ||
848 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, | ||
849 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, | ||
850 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, | ||
851 | {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } | ||
852 | } | ||
853 | }; | 302 | }; |
854 | 303 | ||
855 | /* | 304 | #define IP_VS_SCTP_MAX_RTO ((60 + 1) * HZ) |
856 | * Timeout table[state] | 305 | |
857 | */ | 306 | /* Timeout table[state] */ |
858 | static const int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = { | 307 | static const int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = { |
859 | [IP_VS_SCTP_S_NONE] = 2 * HZ, | 308 | [IP_VS_SCTP_S_NONE] = 2 * HZ, |
860 | [IP_VS_SCTP_S_INIT_CLI] = 1 * 60 * HZ, | 309 | [IP_VS_SCTP_S_INIT1] = (0 + 3 + 1) * HZ, |
861 | [IP_VS_SCTP_S_INIT_SER] = 1 * 60 * HZ, | 310 | [IP_VS_SCTP_S_INIT] = IP_VS_SCTP_MAX_RTO, |
862 | [IP_VS_SCTP_S_INIT_ACK_CLI] = 1 * 60 * HZ, | 311 | [IP_VS_SCTP_S_COOKIE_SENT] = IP_VS_SCTP_MAX_RTO, |
863 | [IP_VS_SCTP_S_INIT_ACK_SER] = 1 * 60 * HZ, | 312 | [IP_VS_SCTP_S_COOKIE_REPLIED] = IP_VS_SCTP_MAX_RTO, |
864 | [IP_VS_SCTP_S_ECHO_CLI] = 1 * 60 * HZ, | 313 | [IP_VS_SCTP_S_COOKIE_WAIT] = IP_VS_SCTP_MAX_RTO, |
865 | [IP_VS_SCTP_S_ECHO_SER] = 1 * 60 * HZ, | 314 | [IP_VS_SCTP_S_COOKIE] = IP_VS_SCTP_MAX_RTO, |
866 | [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ, | 315 | [IP_VS_SCTP_S_COOKIE_ECHOED] = IP_VS_SCTP_MAX_RTO, |
867 | [IP_VS_SCTP_S_SHUT_CLI] = 1 * 60 * HZ, | 316 | [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ, |
868 | [IP_VS_SCTP_S_SHUT_SER] = 1 * 60 * HZ, | 317 | [IP_VS_SCTP_S_SHUTDOWN_SENT] = IP_VS_SCTP_MAX_RTO, |
869 | [IP_VS_SCTP_S_SHUT_ACK_CLI] = 1 * 60 * HZ, | 318 | [IP_VS_SCTP_S_SHUTDOWN_RECEIVED] = IP_VS_SCTP_MAX_RTO, |
870 | [IP_VS_SCTP_S_SHUT_ACK_SER] = 1 * 60 * HZ, | 319 | [IP_VS_SCTP_S_SHUTDOWN_ACK_SENT] = IP_VS_SCTP_MAX_RTO, |
871 | [IP_VS_SCTP_S_CLOSED] = 10 * HZ, | 320 | [IP_VS_SCTP_S_REJECTED] = (0 + 3 + 1) * HZ, |
872 | [IP_VS_SCTP_S_LAST] = 2 * HZ, | 321 | [IP_VS_SCTP_S_CLOSED] = IP_VS_SCTP_MAX_RTO, |
322 | [IP_VS_SCTP_S_LAST] = 2 * HZ, | ||
873 | }; | 323 | }; |
874 | 324 | ||
875 | static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = { | 325 | static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = { |
876 | [IP_VS_SCTP_S_NONE] = "NONE", | 326 | [IP_VS_SCTP_S_NONE] = "NONE", |
877 | [IP_VS_SCTP_S_INIT_CLI] = "INIT_CLI", | 327 | [IP_VS_SCTP_S_INIT1] = "INIT1", |
878 | [IP_VS_SCTP_S_INIT_SER] = "INIT_SER", | 328 | [IP_VS_SCTP_S_INIT] = "INIT", |
879 | [IP_VS_SCTP_S_INIT_ACK_CLI] = "INIT_ACK_CLI", | 329 | [IP_VS_SCTP_S_COOKIE_SENT] = "C-SENT", |
880 | [IP_VS_SCTP_S_INIT_ACK_SER] = "INIT_ACK_SER", | 330 | [IP_VS_SCTP_S_COOKIE_REPLIED] = "C-REPLIED", |
881 | [IP_VS_SCTP_S_ECHO_CLI] = "COOKIE_ECHO_CLI", | 331 | [IP_VS_SCTP_S_COOKIE_WAIT] = "C-WAIT", |
882 | [IP_VS_SCTP_S_ECHO_SER] = "COOKIE_ECHO_SER", | 332 | [IP_VS_SCTP_S_COOKIE] = "COOKIE", |
883 | [IP_VS_SCTP_S_ESTABLISHED] = "ESTABISHED", | 333 | [IP_VS_SCTP_S_COOKIE_ECHOED] = "C-ECHOED", |
884 | [IP_VS_SCTP_S_SHUT_CLI] = "SHUTDOWN_CLI", | 334 | [IP_VS_SCTP_S_ESTABLISHED] = "ESTABLISHED", |
885 | [IP_VS_SCTP_S_SHUT_SER] = "SHUTDOWN_SER", | 335 | [IP_VS_SCTP_S_SHUTDOWN_SENT] = "S-SENT", |
886 | [IP_VS_SCTP_S_SHUT_ACK_CLI] = "SHUTDOWN_ACK_CLI", | 336 | [IP_VS_SCTP_S_SHUTDOWN_RECEIVED] = "S-RECEIVED", |
887 | [IP_VS_SCTP_S_SHUT_ACK_SER] = "SHUTDOWN_ACK_SER", | 337 | [IP_VS_SCTP_S_SHUTDOWN_ACK_SENT] = "S-ACK-SENT", |
888 | [IP_VS_SCTP_S_CLOSED] = "CLOSED", | 338 | [IP_VS_SCTP_S_REJECTED] = "REJECTED", |
889 | [IP_VS_SCTP_S_LAST] = "BUG!" | 339 | [IP_VS_SCTP_S_CLOSED] = "CLOSED", |
340 | [IP_VS_SCTP_S_LAST] = "BUG!", | ||
890 | }; | 341 | }; |
891 | 342 | ||
892 | 343 | ||
@@ -943,17 +394,20 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, | |||
943 | } | 394 | } |
944 | } | 395 | } |
945 | 396 | ||
946 | event = sctp_events[chunk_type]; | 397 | event = (chunk_type < sizeof(sctp_events)) ? |
398 | sctp_events[chunk_type] : IP_VS_SCTP_DATA; | ||
947 | 399 | ||
948 | /* | 400 | /* Update direction to INPUT_ONLY if necessary |
949 | * If the direction is IP_VS_DIR_OUTPUT, this event is from server | 401 | * or delete NO_OUTPUT flag if output packet detected |
950 | */ | ||
951 | if (direction == IP_VS_DIR_OUTPUT) | ||
952 | event++; | ||
953 | /* | ||
954 | * get next state | ||
955 | */ | 402 | */ |
956 | next_state = sctp_states_table[cp->state][event].next_state; | 403 | if (cp->flags & IP_VS_CONN_F_NOOUTPUT) { |
404 | if (direction == IP_VS_DIR_OUTPUT) | ||
405 | cp->flags &= ~IP_VS_CONN_F_NOOUTPUT; | ||
406 | else | ||
407 | direction = IP_VS_DIR_INPUT_ONLY; | ||
408 | } | ||
409 | |||
410 | next_state = sctp_states[direction][event][cp->state]; | ||
957 | 411 | ||
958 | if (next_state != cp->state) { | 412 | if (next_state != cp->state) { |
959 | struct ip_vs_dest *dest = cp->dest; | 413 | struct ip_vs_dest *dest = cp->dest; |
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 50a15944c6c1..e3a697234a98 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c | |||
@@ -39,6 +39,7 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
39 | struct net *net; | 39 | struct net *net; |
40 | struct ip_vs_service *svc; | 40 | struct ip_vs_service *svc; |
41 | struct tcphdr _tcph, *th; | 41 | struct tcphdr _tcph, *th; |
42 | struct netns_ipvs *ipvs; | ||
42 | 43 | ||
43 | th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); | 44 | th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); |
44 | if (th == NULL) { | 45 | if (th == NULL) { |
@@ -46,14 +47,15 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, | |||
46 | return 0; | 47 | return 0; |
47 | } | 48 | } |
48 | net = skb_net(skb); | 49 | net = skb_net(skb); |
50 | ipvs = net_ipvs(net); | ||
49 | /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ | 51 | /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ |
50 | rcu_read_lock(); | 52 | rcu_read_lock(); |
51 | if (th->syn && | 53 | if ((th->syn || sysctl_sloppy_tcp(ipvs)) && !th->rst && |
52 | (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol, | 54 | (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol, |
53 | &iph->daddr, th->dest))) { | 55 | &iph->daddr, th->dest))) { |
54 | int ignored; | 56 | int ignored; |
55 | 57 | ||
56 | if (ip_vs_todrop(net_ipvs(net))) { | 58 | if (ip_vs_todrop(ipvs)) { |
57 | /* | 59 | /* |
58 | * It seems that we are very loaded. | 60 | * It seems that we are very loaded. |
59 | * We have to drop this packet :( | 61 | * We have to drop this packet :( |
@@ -401,7 +403,7 @@ static struct tcp_states_t tcp_states [] = { | |||
401 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ | 403 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ |
402 | /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }}, | 404 | /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }}, |
403 | /*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }}, | 405 | /*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }}, |
404 | /*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, | 406 | /*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, |
405 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }}, | 407 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }}, |
406 | 408 | ||
407 | /* OUTPUT */ | 409 | /* OUTPUT */ |
@@ -415,7 +417,7 @@ static struct tcp_states_t tcp_states [] = { | |||
415 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ | 417 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ |
416 | /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }}, | 418 | /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }}, |
417 | /*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }}, | 419 | /*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }}, |
418 | /*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, | 420 | /*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, |
419 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, | 421 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, |
420 | }; | 422 | }; |
421 | 423 | ||
@@ -424,7 +426,7 @@ static struct tcp_states_t tcp_states_dos [] = { | |||
424 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ | 426 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ |
425 | /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSA }}, | 427 | /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSA }}, |
426 | /*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sSA }}, | 428 | /*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sSA }}, |
427 | /*ack*/ {{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI, sSA }}, | 429 | /*ack*/ {{sES, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI, sSA }}, |
428 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, | 430 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, |
429 | 431 | ||
430 | /* OUTPUT */ | 432 | /* OUTPUT */ |
@@ -438,7 +440,7 @@ static struct tcp_states_t tcp_states_dos [] = { | |||
438 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ | 440 | /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ |
439 | /*syn*/ {{sSA, sES, sES, sSR, sSA, sSA, sSA, sSA, sSA, sSA, sSA }}, | 441 | /*syn*/ {{sSA, sES, sES, sSR, sSA, sSA, sSA, sSA, sSA, sSA, sSA }}, |
440 | /*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }}, | 442 | /*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }}, |
441 | /*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, | 443 | /*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, |
442 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, | 444 | /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, |
443 | }; | 445 | }; |
444 | 446 | ||
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c index c35986c793d9..176b87c35e34 100644 --- a/net/netfilter/ipvs/ip_vs_rr.c +++ b/net/netfilter/ipvs/ip_vs_rr.c | |||
@@ -55,7 +55,8 @@ static int ip_vs_rr_del_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest) | |||
55 | * Round-Robin Scheduling | 55 | * Round-Robin Scheduling |
56 | */ | 56 | */ |
57 | static struct ip_vs_dest * | 57 | static struct ip_vs_dest * |
58 | ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 58 | ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
59 | struct ip_vs_iphdr *iph) | ||
59 | { | 60 | { |
60 | struct list_head *p; | 61 | struct list_head *p; |
61 | struct ip_vs_dest *dest, *last; | 62 | struct ip_vs_dest *dest, *last; |
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c index f3205925359a..a5284cc3d882 100644 --- a/net/netfilter/ipvs/ip_vs_sed.c +++ b/net/netfilter/ipvs/ip_vs_sed.c | |||
@@ -59,7 +59,8 @@ ip_vs_sed_dest_overhead(struct ip_vs_dest *dest) | |||
59 | * Weighted Least Connection scheduling | 59 | * Weighted Least Connection scheduling |
60 | */ | 60 | */ |
61 | static struct ip_vs_dest * | 61 | static struct ip_vs_dest * |
62 | ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 62 | ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
63 | struct ip_vs_iphdr *iph) | ||
63 | { | 64 | { |
64 | struct ip_vs_dest *dest, *least; | 65 | struct ip_vs_dest *dest, *least; |
65 | unsigned int loh, doh; | 66 | unsigned int loh, doh; |
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index a65edfe4b16c..f16c027df15b 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c | |||
@@ -48,6 +48,10 @@ | |||
48 | 48 | ||
49 | #include <net/ip_vs.h> | 49 | #include <net/ip_vs.h> |
50 | 50 | ||
51 | #include <net/tcp.h> | ||
52 | #include <linux/udp.h> | ||
53 | #include <linux/sctp.h> | ||
54 | |||
51 | 55 | ||
52 | /* | 56 | /* |
53 | * IPVS SH bucket | 57 | * IPVS SH bucket |
@@ -71,10 +75,19 @@ struct ip_vs_sh_state { | |||
71 | struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE]; | 75 | struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE]; |
72 | }; | 76 | }; |
73 | 77 | ||
78 | /* Helper function to determine if server is unavailable */ | ||
79 | static inline bool is_unavailable(struct ip_vs_dest *dest) | ||
80 | { | ||
81 | return atomic_read(&dest->weight) <= 0 || | ||
82 | dest->flags & IP_VS_DEST_F_OVERLOAD; | ||
83 | } | ||
84 | |||
74 | /* | 85 | /* |
75 | * Returns hash value for IPVS SH entry | 86 | * Returns hash value for IPVS SH entry |
76 | */ | 87 | */ |
77 | static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr) | 88 | static inline unsigned int |
89 | ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr, | ||
90 | __be16 port, unsigned int offset) | ||
78 | { | 91 | { |
79 | __be32 addr_fold = addr->ip; | 92 | __be32 addr_fold = addr->ip; |
80 | 93 | ||
@@ -83,7 +96,8 @@ static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *ad | |||
83 | addr_fold = addr->ip6[0]^addr->ip6[1]^ | 96 | addr_fold = addr->ip6[0]^addr->ip6[1]^ |
84 | addr->ip6[2]^addr->ip6[3]; | 97 | addr->ip6[2]^addr->ip6[3]; |
85 | #endif | 98 | #endif |
86 | return (ntohl(addr_fold)*2654435761UL) & IP_VS_SH_TAB_MASK; | 99 | return (offset + (ntohs(port) + ntohl(addr_fold))*2654435761UL) & |
100 | IP_VS_SH_TAB_MASK; | ||
87 | } | 101 | } |
88 | 102 | ||
89 | 103 | ||
@@ -91,12 +105,42 @@ static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *ad | |||
91 | * Get ip_vs_dest associated with supplied parameters. | 105 | * Get ip_vs_dest associated with supplied parameters. |
92 | */ | 106 | */ |
93 | static inline struct ip_vs_dest * | 107 | static inline struct ip_vs_dest * |
94 | ip_vs_sh_get(int af, struct ip_vs_sh_state *s, const union nf_inet_addr *addr) | 108 | ip_vs_sh_get(struct ip_vs_service *svc, struct ip_vs_sh_state *s, |
109 | const union nf_inet_addr *addr, __be16 port) | ||
95 | { | 110 | { |
96 | return rcu_dereference(s->buckets[ip_vs_sh_hashkey(af, addr)].dest); | 111 | unsigned int hash = ip_vs_sh_hashkey(svc->af, addr, port, 0); |
112 | struct ip_vs_dest *dest = rcu_dereference(s->buckets[hash].dest); | ||
113 | |||
114 | return (!dest || is_unavailable(dest)) ? NULL : dest; | ||
97 | } | 115 | } |
98 | 116 | ||
99 | 117 | ||
118 | /* As ip_vs_sh_get, but with fallback if selected server is unavailable */ | ||
119 | static inline struct ip_vs_dest * | ||
120 | ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s, | ||
121 | const union nf_inet_addr *addr, __be16 port) | ||
122 | { | ||
123 | unsigned int offset; | ||
124 | unsigned int hash; | ||
125 | struct ip_vs_dest *dest; | ||
126 | |||
127 | for (offset = 0; offset < IP_VS_SH_TAB_SIZE; offset++) { | ||
128 | hash = ip_vs_sh_hashkey(svc->af, addr, port, offset); | ||
129 | dest = rcu_dereference(s->buckets[hash].dest); | ||
130 | if (!dest) | ||
131 | break; | ||
132 | if (is_unavailable(dest)) | ||
133 | IP_VS_DBG_BUF(6, "SH: selected unavailable server " | ||
134 | "%s:%d (offset %d)", | ||
135 | IP_VS_DBG_ADDR(svc->af, &dest->addr), | ||
136 | ntohs(dest->port), offset); | ||
137 | else | ||
138 | return dest; | ||
139 | } | ||
140 | |||
141 | return NULL; | ||
142 | } | ||
143 | |||
100 | /* | 144 | /* |
101 | * Assign all the hash buckets of the specified table with the service. | 145 | * Assign all the hash buckets of the specified table with the service. |
102 | */ | 146 | */ |
@@ -213,13 +257,33 @@ static int ip_vs_sh_dest_changed(struct ip_vs_service *svc, | |||
213 | } | 257 | } |
214 | 258 | ||
215 | 259 | ||
216 | /* | 260 | /* Helper function to get port number */ |
217 | * If the dest flags is set with IP_VS_DEST_F_OVERLOAD, | 261 | static inline __be16 |
218 | * consider that the server is overloaded here. | 262 | ip_vs_sh_get_port(const struct sk_buff *skb, struct ip_vs_iphdr *iph) |
219 | */ | ||
220 | static inline int is_overloaded(struct ip_vs_dest *dest) | ||
221 | { | 263 | { |
222 | return dest->flags & IP_VS_DEST_F_OVERLOAD; | 264 | __be16 port; |
265 | struct tcphdr _tcph, *th; | ||
266 | struct udphdr _udph, *uh; | ||
267 | sctp_sctphdr_t _sctph, *sh; | ||
268 | |||
269 | switch (iph->protocol) { | ||
270 | case IPPROTO_TCP: | ||
271 | th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); | ||
272 | port = th->source; | ||
273 | break; | ||
274 | case IPPROTO_UDP: | ||
275 | uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph); | ||
276 | port = uh->source; | ||
277 | break; | ||
278 | case IPPROTO_SCTP: | ||
279 | sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph); | ||
280 | port = sh->source; | ||
281 | break; | ||
282 | default: | ||
283 | port = 0; | ||
284 | } | ||
285 | |||
286 | return port; | ||
223 | } | 287 | } |
224 | 288 | ||
225 | 289 | ||
@@ -227,28 +291,32 @@ static inline int is_overloaded(struct ip_vs_dest *dest) | |||
227 | * Source Hashing scheduling | 291 | * Source Hashing scheduling |
228 | */ | 292 | */ |
229 | static struct ip_vs_dest * | 293 | static struct ip_vs_dest * |
230 | ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 294 | ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
295 | struct ip_vs_iphdr *iph) | ||
231 | { | 296 | { |
232 | struct ip_vs_dest *dest; | 297 | struct ip_vs_dest *dest; |
233 | struct ip_vs_sh_state *s; | 298 | struct ip_vs_sh_state *s; |
234 | struct ip_vs_iphdr iph; | 299 | __be16 port = 0; |
235 | |||
236 | ip_vs_fill_iph_addr_only(svc->af, skb, &iph); | ||
237 | 300 | ||
238 | IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n"); | 301 | IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n"); |
239 | 302 | ||
303 | if (svc->flags & IP_VS_SVC_F_SCHED_SH_PORT) | ||
304 | port = ip_vs_sh_get_port(skb, iph); | ||
305 | |||
240 | s = (struct ip_vs_sh_state *) svc->sched_data; | 306 | s = (struct ip_vs_sh_state *) svc->sched_data; |
241 | dest = ip_vs_sh_get(svc->af, s, &iph.saddr); | 307 | |
242 | if (!dest | 308 | if (svc->flags & IP_VS_SVC_F_SCHED_SH_FALLBACK) |
243 | || !(dest->flags & IP_VS_DEST_F_AVAILABLE) | 309 | dest = ip_vs_sh_get_fallback(svc, s, &iph->saddr, port); |
244 | || atomic_read(&dest->weight) <= 0 | 310 | else |
245 | || is_overloaded(dest)) { | 311 | dest = ip_vs_sh_get(svc, s, &iph->saddr, port); |
312 | |||
313 | if (!dest) { | ||
246 | ip_vs_scheduler_err(svc, "no destination available"); | 314 | ip_vs_scheduler_err(svc, "no destination available"); |
247 | return NULL; | 315 | return NULL; |
248 | } | 316 | } |
249 | 317 | ||
250 | IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n", | 318 | IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n", |
251 | IP_VS_DBG_ADDR(svc->af, &iph.saddr), | 319 | IP_VS_DBG_ADDR(svc->af, &iph->saddr), |
252 | IP_VS_DBG_ADDR(svc->af, &dest->addr), | 320 | IP_VS_DBG_ADDR(svc->af, &dest->addr), |
253 | ntohs(dest->port)); | 321 | ntohs(dest->port)); |
254 | 322 | ||
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index f6046d9af8d3..f4484719f3e6 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -425,6 +425,16 @@ ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs) | |||
425 | return sb; | 425 | return sb; |
426 | } | 426 | } |
427 | 427 | ||
428 | /* Check if connection is controlled by persistence */ | ||
429 | static inline bool in_persistence(struct ip_vs_conn *cp) | ||
430 | { | ||
431 | for (cp = cp->control; cp; cp = cp->control) { | ||
432 | if (cp->flags & IP_VS_CONN_F_TEMPLATE) | ||
433 | return true; | ||
434 | } | ||
435 | return false; | ||
436 | } | ||
437 | |||
428 | /* Check if conn should be synced. | 438 | /* Check if conn should be synced. |
429 | * pkts: conn packets, use sysctl_sync_threshold to avoid packet check | 439 | * pkts: conn packets, use sysctl_sync_threshold to avoid packet check |
430 | * - (1) sync_refresh_period: reduce sync rate. Additionally, retry | 440 | * - (1) sync_refresh_period: reduce sync rate. Additionally, retry |
@@ -447,6 +457,8 @@ static int ip_vs_sync_conn_needed(struct netns_ipvs *ipvs, | |||
447 | /* Check if we sync in current state */ | 457 | /* Check if we sync in current state */ |
448 | if (unlikely(cp->flags & IP_VS_CONN_F_TEMPLATE)) | 458 | if (unlikely(cp->flags & IP_VS_CONN_F_TEMPLATE)) |
449 | force = 0; | 459 | force = 0; |
460 | else if (unlikely(sysctl_sync_persist_mode(ipvs) && in_persistence(cp))) | ||
461 | return 0; | ||
450 | else if (likely(cp->protocol == IPPROTO_TCP)) { | 462 | else if (likely(cp->protocol == IPPROTO_TCP)) { |
451 | if (!((1 << cp->state) & | 463 | if (!((1 << cp->state) & |
452 | ((1 << IP_VS_TCP_S_ESTABLISHED) | | 464 | ((1 << IP_VS_TCP_S_ESTABLISHED) | |
@@ -461,9 +473,10 @@ static int ip_vs_sync_conn_needed(struct netns_ipvs *ipvs, | |||
461 | } else if (unlikely(cp->protocol == IPPROTO_SCTP)) { | 473 | } else if (unlikely(cp->protocol == IPPROTO_SCTP)) { |
462 | if (!((1 << cp->state) & | 474 | if (!((1 << cp->state) & |
463 | ((1 << IP_VS_SCTP_S_ESTABLISHED) | | 475 | ((1 << IP_VS_SCTP_S_ESTABLISHED) | |
464 | (1 << IP_VS_SCTP_S_CLOSED) | | 476 | (1 << IP_VS_SCTP_S_SHUTDOWN_SENT) | |
465 | (1 << IP_VS_SCTP_S_SHUT_ACK_CLI) | | 477 | (1 << IP_VS_SCTP_S_SHUTDOWN_RECEIVED) | |
466 | (1 << IP_VS_SCTP_S_SHUT_ACK_SER)))) | 478 | (1 << IP_VS_SCTP_S_SHUTDOWN_ACK_SENT) | |
479 | (1 << IP_VS_SCTP_S_CLOSED)))) | ||
467 | return 0; | 480 | return 0; |
468 | force = cp->state != cp->old_state; | 481 | force = cp->state != cp->old_state; |
469 | if (force && cp->state != IP_VS_SCTP_S_ESTABLISHED) | 482 | if (force && cp->state != IP_VS_SCTP_S_ESTABLISHED) |
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c index c60a81c4ce9a..6dc1fa128840 100644 --- a/net/netfilter/ipvs/ip_vs_wlc.c +++ b/net/netfilter/ipvs/ip_vs_wlc.c | |||
@@ -31,7 +31,8 @@ | |||
31 | * Weighted Least Connection scheduling | 31 | * Weighted Least Connection scheduling |
32 | */ | 32 | */ |
33 | static struct ip_vs_dest * | 33 | static struct ip_vs_dest * |
34 | ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 34 | ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
35 | struct ip_vs_iphdr *iph) | ||
35 | { | 36 | { |
36 | struct ip_vs_dest *dest, *least; | 37 | struct ip_vs_dest *dest, *least; |
37 | unsigned int loh, doh; | 38 | unsigned int loh, doh; |
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c index 0e68555bceb9..0546cd572d6b 100644 --- a/net/netfilter/ipvs/ip_vs_wrr.c +++ b/net/netfilter/ipvs/ip_vs_wrr.c | |||
@@ -162,7 +162,8 @@ static int ip_vs_wrr_dest_changed(struct ip_vs_service *svc, | |||
162 | * Weighted Round-Robin Scheduling | 162 | * Weighted Round-Robin Scheduling |
163 | */ | 163 | */ |
164 | static struct ip_vs_dest * | 164 | static struct ip_vs_dest * |
165 | ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 165 | ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, |
166 | struct ip_vs_iphdr *iph) | ||
166 | { | 167 | { |
167 | struct ip_vs_dest *dest, *last, *stop = NULL; | 168 | struct ip_vs_dest *dest, *last, *stop = NULL; |
168 | struct ip_vs_wrr_mark *mark = svc->sched_data; | 169 | struct ip_vs_wrr_mark *mark = svc->sched_data; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 6d0f8a17c5b7..f83a52298efe 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -828,7 +828,9 @@ ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) | |||
828 | struct nf_conntrack_l3proto *l3proto; | 828 | struct nf_conntrack_l3proto *l3proto; |
829 | int ret = 0; | 829 | int ret = 0; |
830 | 830 | ||
831 | nla_parse_nested(tb, CTA_IP_MAX, attr, NULL); | 831 | ret = nla_parse_nested(tb, CTA_IP_MAX, attr, NULL); |
832 | if (ret < 0) | ||
833 | return ret; | ||
832 | 834 | ||
833 | rcu_read_lock(); | 835 | rcu_read_lock(); |
834 | l3proto = __nf_ct_l3proto_find(tuple->src.l3num); | 836 | l3proto = __nf_ct_l3proto_find(tuple->src.l3num); |
@@ -895,7 +897,9 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[], | |||
895 | 897 | ||
896 | memset(tuple, 0, sizeof(*tuple)); | 898 | memset(tuple, 0, sizeof(*tuple)); |
897 | 899 | ||
898 | nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy); | 900 | err = nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy); |
901 | if (err < 0) | ||
902 | return err; | ||
899 | 903 | ||
900 | if (!tb[CTA_TUPLE_IP]) | 904 | if (!tb[CTA_TUPLE_IP]) |
901 | return -EINVAL; | 905 | return -EINVAL; |
@@ -946,9 +950,12 @@ static inline int | |||
946 | ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, | 950 | ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, |
947 | struct nlattr **helpinfo) | 951 | struct nlattr **helpinfo) |
948 | { | 952 | { |
953 | int err; | ||
949 | struct nlattr *tb[CTA_HELP_MAX+1]; | 954 | struct nlattr *tb[CTA_HELP_MAX+1]; |
950 | 955 | ||
951 | nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy); | 956 | err = nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy); |
957 | if (err < 0) | ||
958 | return err; | ||
952 | 959 | ||
953 | if (!tb[CTA_HELP_NAME]) | 960 | if (!tb[CTA_HELP_NAME]) |
954 | return -EINVAL; | 961 | return -EINVAL; |
@@ -1431,7 +1438,9 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[] | |||
1431 | struct nf_conntrack_l4proto *l4proto; | 1438 | struct nf_conntrack_l4proto *l4proto; |
1432 | int err = 0; | 1439 | int err = 0; |
1433 | 1440 | ||
1434 | nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy); | 1441 | err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy); |
1442 | if (err < 0) | ||
1443 | return err; | ||
1435 | 1444 | ||
1436 | rcu_read_lock(); | 1445 | rcu_read_lock(); |
1437 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); | 1446 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); |
@@ -1452,9 +1461,12 @@ static const struct nla_policy nat_seq_policy[CTA_NAT_SEQ_MAX+1] = { | |||
1452 | static inline int | 1461 | static inline int |
1453 | change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr) | 1462 | change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr) |
1454 | { | 1463 | { |
1464 | int err; | ||
1455 | struct nlattr *cda[CTA_NAT_SEQ_MAX+1]; | 1465 | struct nlattr *cda[CTA_NAT_SEQ_MAX+1]; |
1456 | 1466 | ||
1457 | nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy); | 1467 | err = nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy); |
1468 | if (err < 0) | ||
1469 | return err; | ||
1458 | 1470 | ||
1459 | if (!cda[CTA_NAT_SEQ_CORRECTION_POS]) | 1471 | if (!cda[CTA_NAT_SEQ_CORRECTION_POS]) |
1460 | return -EINVAL; | 1472 | return -EINVAL; |
@@ -2115,7 +2127,9 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) | |||
2115 | struct nlattr *cda[CTA_MAX+1]; | 2127 | struct nlattr *cda[CTA_MAX+1]; |
2116 | int ret; | 2128 | int ret; |
2117 | 2129 | ||
2118 | nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); | 2130 | ret = nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); |
2131 | if (ret < 0) | ||
2132 | return ret; | ||
2119 | 2133 | ||
2120 | spin_lock_bh(&nf_conntrack_lock); | 2134 | spin_lock_bh(&nf_conntrack_lock); |
2121 | ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); | 2135 | ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); |
@@ -2710,7 +2724,9 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr, | |||
2710 | struct nf_conntrack_tuple nat_tuple = {}; | 2724 | struct nf_conntrack_tuple nat_tuple = {}; |
2711 | int err; | 2725 | int err; |
2712 | 2726 | ||
2713 | nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy); | 2727 | err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy); |
2728 | if (err < 0) | ||
2729 | return err; | ||
2714 | 2730 | ||
2715 | if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE]) | 2731 | if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE]) |
2716 | return -EINVAL; | 2732 | return -EINVAL; |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 4d4d8f1d01fc..7dcc376eea5f 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -1043,6 +1043,12 @@ static int tcp_packet(struct nf_conn *ct, | |||
1043 | nf_ct_kill_acct(ct, ctinfo, skb); | 1043 | nf_ct_kill_acct(ct, ctinfo, skb); |
1044 | return NF_ACCEPT; | 1044 | return NF_ACCEPT; |
1045 | } | 1045 | } |
1046 | /* ESTABLISHED without SEEN_REPLY, i.e. mid-connection | ||
1047 | * pickup with loose=1. Avoid large ESTABLISHED timeout. | ||
1048 | */ | ||
1049 | if (new_state == TCP_CONNTRACK_ESTABLISHED && | ||
1050 | timeout > timeouts[TCP_CONNTRACK_UNACK]) | ||
1051 | timeout = timeouts[TCP_CONNTRACK_UNACK]; | ||
1046 | } else if (!test_bit(IPS_ASSURED_BIT, &ct->status) | 1052 | } else if (!test_bit(IPS_ASSURED_BIT, &ct->status) |
1047 | && (old_state == TCP_CONNTRACK_SYN_RECV | 1053 | && (old_state == TCP_CONNTRACK_SYN_RECV |
1048 | || old_state == TCP_CONNTRACK_ESTABLISHED) | 1054 | || old_state == TCP_CONNTRACK_ESTABLISHED) |
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index a191b6db657e..9e287cb56a04 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c | |||
@@ -67,9 +67,12 @@ static int | |||
67 | nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, | 67 | nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, |
68 | const struct nlattr *attr) | 68 | const struct nlattr *attr) |
69 | { | 69 | { |
70 | int err; | ||
70 | struct nlattr *tb[NFCTH_TUPLE_MAX+1]; | 71 | struct nlattr *tb[NFCTH_TUPLE_MAX+1]; |
71 | 72 | ||
72 | nla_parse_nested(tb, NFCTH_TUPLE_MAX, attr, nfnl_cthelper_tuple_pol); | 73 | err = nla_parse_nested(tb, NFCTH_TUPLE_MAX, attr, nfnl_cthelper_tuple_pol); |
74 | if (err < 0) | ||
75 | return err; | ||
73 | 76 | ||
74 | if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) | 77 | if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) |
75 | return -EINVAL; | 78 | return -EINVAL; |
@@ -121,9 +124,12 @@ static int | |||
121 | nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy, | 124 | nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy, |
122 | const struct nlattr *attr) | 125 | const struct nlattr *attr) |
123 | { | 126 | { |
127 | int err; | ||
124 | struct nlattr *tb[NFCTH_POLICY_MAX+1]; | 128 | struct nlattr *tb[NFCTH_POLICY_MAX+1]; |
125 | 129 | ||
126 | nla_parse_nested(tb, NFCTH_POLICY_MAX, attr, nfnl_cthelper_expect_pol); | 130 | err = nla_parse_nested(tb, NFCTH_POLICY_MAX, attr, nfnl_cthelper_expect_pol); |
131 | if (err < 0) | ||
132 | return err; | ||
127 | 133 | ||
128 | if (!tb[NFCTH_POLICY_NAME] || | 134 | if (!tb[NFCTH_POLICY_NAME] || |
129 | !tb[NFCTH_POLICY_EXPECT_MAX] || | 135 | !tb[NFCTH_POLICY_EXPECT_MAX] || |
@@ -153,8 +159,10 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, | |||
153 | struct nf_conntrack_expect_policy *expect_policy; | 159 | struct nf_conntrack_expect_policy *expect_policy; |
154 | struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; | 160 | struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; |
155 | 161 | ||
156 | nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, | 162 | ret = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, |
157 | nfnl_cthelper_expect_policy_set); | 163 | nfnl_cthelper_expect_policy_set); |
164 | if (ret < 0) | ||
165 | return ret; | ||
158 | 166 | ||
159 | if (!tb[NFCTH_POLICY_SET_NUM]) | 167 | if (!tb[NFCTH_POLICY_SET_NUM]) |
160 | return -EINVAL; | 168 | return -EINVAL; |
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 65074dfb9383..50580494148d 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c | |||
@@ -59,8 +59,10 @@ ctnl_timeout_parse_policy(struct ctnl_timeout *timeout, | |||
59 | if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { | 59 | if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { |
60 | struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1]; | 60 | struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1]; |
61 | 61 | ||
62 | nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, | 62 | ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, |
63 | attr, l4proto->ctnl_timeout.nla_policy); | 63 | attr, l4proto->ctnl_timeout.nla_policy); |
64 | if (ret < 0) | ||
65 | return ret; | ||
64 | 66 | ||
65 | ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, | 67 | ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, |
66 | &timeout->data); | 68 | &timeout->data); |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 299a48ae5dc9..971ea145ab3e 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -280,12 +280,17 @@ nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
280 | skb_shinfo(to)->nr_frags = j; | 280 | skb_shinfo(to)->nr_frags = j; |
281 | } | 281 | } |
282 | 282 | ||
283 | static int nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet) | 283 | static int |
284 | nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet, | ||
285 | bool csum_verify) | ||
284 | { | 286 | { |
285 | __u32 flags = 0; | 287 | __u32 flags = 0; |
286 | 288 | ||
287 | if (packet->ip_summed == CHECKSUM_PARTIAL) | 289 | if (packet->ip_summed == CHECKSUM_PARTIAL) |
288 | flags = NFQA_SKB_CSUMNOTREADY; | 290 | flags = NFQA_SKB_CSUMNOTREADY; |
291 | else if (csum_verify) | ||
292 | flags = NFQA_SKB_CSUM_NOTVERIFIED; | ||
293 | |||
289 | if (skb_is_gso(packet)) | 294 | if (skb_is_gso(packet)) |
290 | flags |= NFQA_SKB_GSO; | 295 | flags |= NFQA_SKB_GSO; |
291 | 296 | ||
@@ -310,6 +315,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
310 | struct net_device *outdev; | 315 | struct net_device *outdev; |
311 | struct nf_conn *ct = NULL; | 316 | struct nf_conn *ct = NULL; |
312 | enum ip_conntrack_info uninitialized_var(ctinfo); | 317 | enum ip_conntrack_info uninitialized_var(ctinfo); |
318 | bool csum_verify; | ||
313 | 319 | ||
314 | size = nlmsg_total_size(sizeof(struct nfgenmsg)) | 320 | size = nlmsg_total_size(sizeof(struct nfgenmsg)) |
315 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) | 321 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) |
@@ -327,6 +333,12 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
327 | if (entskb->tstamp.tv64) | 333 | if (entskb->tstamp.tv64) |
328 | size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); | 334 | size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); |
329 | 335 | ||
336 | if (entry->hook <= NF_INET_FORWARD || | ||
337 | (entry->hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) | ||
338 | csum_verify = !skb_csum_unnecessary(entskb); | ||
339 | else | ||
340 | csum_verify = false; | ||
341 | |||
330 | outdev = entry->outdev; | 342 | outdev = entry->outdev; |
331 | 343 | ||
332 | switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) { | 344 | switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) { |
@@ -476,7 +488,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
476 | nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) | 488 | nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) |
477 | goto nla_put_failure; | 489 | goto nla_put_failure; |
478 | 490 | ||
479 | if (nfqnl_put_packet_info(skb, entskb)) | 491 | if (nfqnl_put_packet_info(skb, entskb, csum_verify)) |
480 | goto nla_put_failure; | 492 | goto nla_put_failure; |
481 | 493 | ||
482 | if (data_len) { | 494 | if (data_len) { |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 02704245710e..f8b71911037a 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -163,8 +163,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, | |||
163 | bool wildcard; | 163 | bool wildcard; |
164 | bool transparent = true; | 164 | bool transparent = true; |
165 | 165 | ||
166 | /* Ignore sockets listening on INADDR_ANY */ | 166 | /* Ignore sockets listening on INADDR_ANY, |
167 | wildcard = (sk->sk_state != TCP_TIME_WAIT && | 167 | * unless XT_SOCKET_NOWILDCARD is set |
168 | */ | ||
169 | wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) && | ||
170 | sk->sk_state != TCP_TIME_WAIT && | ||
168 | inet_sk(sk)->inet_rcv_saddr == 0); | 171 | inet_sk(sk)->inet_rcv_saddr == 0); |
169 | 172 | ||
170 | /* Ignore non-transparent sockets, | 173 | /* Ignore non-transparent sockets, |
@@ -197,7 +200,7 @@ socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par) | |||
197 | } | 200 | } |
198 | 201 | ||
199 | static bool | 202 | static bool |
200 | socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par) | 203 | socket_mt4_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) |
201 | { | 204 | { |
202 | return socket_match(skb, par, par->matchinfo); | 205 | return socket_match(skb, par, par->matchinfo); |
203 | } | 206 | } |
@@ -259,7 +262,7 @@ extract_icmp6_fields(const struct sk_buff *skb, | |||
259 | } | 262 | } |
260 | 263 | ||
261 | static bool | 264 | static bool |
262 | socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | 265 | socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) |
263 | { | 266 | { |
264 | struct ipv6hdr *iph = ipv6_hdr(skb); | 267 | struct ipv6hdr *iph = ipv6_hdr(skb); |
265 | struct udphdr _hdr, *hp = NULL; | 268 | struct udphdr _hdr, *hp = NULL; |
@@ -302,8 +305,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
302 | bool wildcard; | 305 | bool wildcard; |
303 | bool transparent = true; | 306 | bool transparent = true; |
304 | 307 | ||
305 | /* Ignore sockets listening on INADDR_ANY */ | 308 | /* Ignore sockets listening on INADDR_ANY |
306 | wildcard = (sk->sk_state != TCP_TIME_WAIT && | 309 | * unless XT_SOCKET_NOWILDCARD is set |
310 | */ | ||
311 | wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) && | ||
312 | sk->sk_state != TCP_TIME_WAIT && | ||
307 | ipv6_addr_any(&inet6_sk(sk)->rcv_saddr)); | 313 | ipv6_addr_any(&inet6_sk(sk)->rcv_saddr)); |
308 | 314 | ||
309 | /* Ignore non-transparent sockets, | 315 | /* Ignore non-transparent sockets, |
@@ -331,6 +337,28 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
331 | } | 337 | } |
332 | #endif | 338 | #endif |
333 | 339 | ||
340 | static int socket_mt_v1_check(const struct xt_mtchk_param *par) | ||
341 | { | ||
342 | const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; | ||
343 | |||
344 | if (info->flags & ~XT_SOCKET_FLAGS_V1) { | ||
345 | pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static int socket_mt_v2_check(const struct xt_mtchk_param *par) | ||
352 | { | ||
353 | const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo; | ||
354 | |||
355 | if (info->flags & ~XT_SOCKET_FLAGS_V2) { | ||
356 | pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | return 0; | ||
360 | } | ||
361 | |||
334 | static struct xt_match socket_mt_reg[] __read_mostly = { | 362 | static struct xt_match socket_mt_reg[] __read_mostly = { |
335 | { | 363 | { |
336 | .name = "socket", | 364 | .name = "socket", |
@@ -345,7 +373,8 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
345 | .name = "socket", | 373 | .name = "socket", |
346 | .revision = 1, | 374 | .revision = 1, |
347 | .family = NFPROTO_IPV4, | 375 | .family = NFPROTO_IPV4, |
348 | .match = socket_mt4_v1, | 376 | .match = socket_mt4_v1_v2, |
377 | .checkentry = socket_mt_v1_check, | ||
349 | .matchsize = sizeof(struct xt_socket_mtinfo1), | 378 | .matchsize = sizeof(struct xt_socket_mtinfo1), |
350 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 379 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
351 | (1 << NF_INET_LOCAL_IN), | 380 | (1 << NF_INET_LOCAL_IN), |
@@ -356,7 +385,32 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
356 | .name = "socket", | 385 | .name = "socket", |
357 | .revision = 1, | 386 | .revision = 1, |
358 | .family = NFPROTO_IPV6, | 387 | .family = NFPROTO_IPV6, |
359 | .match = socket_mt6_v1, | 388 | .match = socket_mt6_v1_v2, |
389 | .checkentry = socket_mt_v1_check, | ||
390 | .matchsize = sizeof(struct xt_socket_mtinfo1), | ||
391 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
392 | (1 << NF_INET_LOCAL_IN), | ||
393 | .me = THIS_MODULE, | ||
394 | }, | ||
395 | #endif | ||
396 | { | ||
397 | .name = "socket", | ||
398 | .revision = 2, | ||
399 | .family = NFPROTO_IPV4, | ||
400 | .match = socket_mt4_v1_v2, | ||
401 | .checkentry = socket_mt_v2_check, | ||
402 | .matchsize = sizeof(struct xt_socket_mtinfo1), | ||
403 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
404 | (1 << NF_INET_LOCAL_IN), | ||
405 | .me = THIS_MODULE, | ||
406 | }, | ||
407 | #ifdef XT_SOCKET_HAVE_IPV6 | ||
408 | { | ||
409 | .name = "socket", | ||
410 | .revision = 2, | ||
411 | .family = NFPROTO_IPV6, | ||
412 | .match = socket_mt6_v1_v2, | ||
413 | .checkentry = socket_mt_v2_check, | ||
360 | .matchsize = sizeof(struct xt_socket_mtinfo1), | 414 | .matchsize = sizeof(struct xt_socket_mtinfo1), |
361 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 415 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
362 | (1 << NF_INET_LOCAL_IN), | 416 | (1 << NF_INET_LOCAL_IN), |