Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipvs: SCTP Trasport Loadbalancing Support

Enhance IPVS to load balance SCTP transport protocol packets. This is done
based on the SCTP rfc 4960. All possible control chunks have been taken
care. The state machine used in this code looks some what lengthy. I tried
to make the state machine easy to understand.

Signed-off-by: Venkata Mohan Reddy Koppula <mohanreddykv@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Venkata Mohan Reddy and committed by
Patrick McHardy
2906f66a 477c6086

+1285 -12
+21 -1
include/net/ip_vs.h
··· 225 225 }; 226 226 227 227 /* 228 + * SCTP State Values 229 + */ 230 + enum ip_vs_sctp_states { 231 + IP_VS_SCTP_S_NONE, 232 + IP_VS_SCTP_S_INIT_CLI, 233 + IP_VS_SCTP_S_INIT_SER, 234 + IP_VS_SCTP_S_INIT_ACK_CLI, 235 + IP_VS_SCTP_S_INIT_ACK_SER, 236 + IP_VS_SCTP_S_ECHO_CLI, 237 + IP_VS_SCTP_S_ECHO_SER, 238 + IP_VS_SCTP_S_ESTABLISHED, 239 + IP_VS_SCTP_S_SHUT_CLI, 240 + IP_VS_SCTP_S_SHUT_SER, 241 + IP_VS_SCTP_S_SHUT_ACK_CLI, 242 + IP_VS_SCTP_S_SHUT_ACK_SER, 243 + IP_VS_SCTP_S_CLOSED, 244 + IP_VS_SCTP_S_LAST 245 + }; 246 + 247 + /* 228 248 * Delta sequence info structure 229 249 * Each ip_vs_conn has 2 (output AND input seq. changes). 230 250 * Only used in the VS/NAT. ··· 761 741 extern struct ip_vs_protocol ip_vs_protocol_icmp; 762 742 extern struct ip_vs_protocol ip_vs_protocol_esp; 763 743 extern struct ip_vs_protocol ip_vs_protocol_ah; 764 - 744 + extern struct ip_vs_protocol ip_vs_protocol_sctp; 765 745 766 746 /* 767 747 * Registering/unregistering scheduler functions
+7
net/netfilter/ipvs/Kconfig
··· 104 104 This option enables support for load balancing AH (Authentication 105 105 Header) transport protocol. Say Y if unsure. 106 106 107 + config IP_VS_PROTO_SCTP 108 + bool "SCTP load balancing support" 109 + select LIBCRC32C 110 + ---help--- 111 + This option enables support for load balancing SCTP transport 112 + protocol. Say Y if unsure. 113 + 107 114 comment "IPVS scheduler" 108 115 109 116 config IP_VS_RR
+1
net/netfilter/ipvs/Makefile
··· 7 7 ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o 8 8 ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o 9 9 ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o 10 + ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_SCTP) += ip_vs_proto_sctp.o 10 11 11 12 ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \ 12 13 ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \
+53 -9
net/netfilter/ipvs/ip_vs_core.c
··· 31 31 #include <linux/kernel.h> 32 32 #include <linux/ip.h> 33 33 #include <linux/tcp.h> 34 + #include <linux/sctp.h> 34 35 #include <linux/icmp.h> 35 36 36 37 #include <net/ip.h> ··· 82 81 return "UDP"; 83 82 case IPPROTO_TCP: 84 83 return "TCP"; 84 + case IPPROTO_SCTP: 85 + return "SCTP"; 85 86 case IPPROTO_ICMP: 86 87 return "ICMP"; 87 88 #ifdef CONFIG_IP_VS_IPV6 ··· 592 589 ip_send_check(ciph); 593 590 } 594 591 595 - /* the TCP/UDP port */ 596 - if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol) { 592 + /* the TCP/UDP/SCTP port */ 593 + if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol || 594 + IPPROTO_SCTP == ciph->protocol) { 597 595 __be16 *ports = (void *)ciph + ciph->ihl*4; 598 596 599 597 if (inout) ··· 634 630 ciph->saddr = cp->daddr.in6; 635 631 } 636 632 637 - /* the TCP/UDP port */ 638 - if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr) { 633 + /* the TCP/UDP/SCTP port */ 634 + if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr || 635 + IPPROTO_SCTP == ciph->nexthdr) { 639 636 __be16 *ports = (void *)ciph + sizeof(struct ipv6hdr); 640 637 641 638 if (inout) ··· 684 679 goto out; 685 680 } 686 681 687 - if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol) 682 + if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || 683 + IPPROTO_SCTP == protocol) 688 684 offset += 2 * sizeof(__u16); 689 685 if (!skb_make_writable(skb, offset)) 690 686 goto out; ··· 863 857 } 864 858 #endif 865 859 860 + /* 861 + * Check if sctp chunc is ABORT chunk 862 + */ 863 + static inline int is_sctp_abort(const struct sk_buff *skb, int nh_len) 864 + { 865 + sctp_chunkhdr_t *sch, schunk; 866 + sch = skb_header_pointer(skb, nh_len + sizeof(sctp_sctphdr_t), 867 + sizeof(schunk), &schunk); 868 + if (sch == NULL) 869 + return 0; 870 + if (sch->type == SCTP_CID_ABORT) 871 + return 1; 872 + return 0; 873 + } 874 + 866 875 static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) 867 876 { 868 877 struct tcphdr _tcph, *th; ··· 1020 999 if (unlikely(!cp)) { 1021 1000 if (sysctl_ip_vs_nat_icmp_send && 1022 1001 (pp->protocol == IPPROTO_TCP || 1023 - pp->protocol == IPPROTO_UDP)) { 1002 + pp->protocol == IPPROTO_UDP || 1003 + pp->protocol == IPPROTO_SCTP)) { 1024 1004 __be16 _ports[2], *pptr; 1025 1005 1026 1006 pptr = skb_header_pointer(skb, iph.len, ··· 1036 1014 * existing entry if it is not RST 1037 1015 * packet or not TCP packet. 1038 1016 */ 1039 - if (iph.protocol != IPPROTO_TCP 1040 - || !is_tcp_reset(skb, iph.len)) { 1017 + if ((iph.protocol != IPPROTO_TCP && 1018 + iph.protocol != IPPROTO_SCTP) 1019 + || ((iph.protocol == IPPROTO_TCP 1020 + && !is_tcp_reset(skb, iph.len)) 1021 + || (iph.protocol == IPPROTO_SCTP 1022 + && !is_sctp_abort(skb, 1023 + iph.len)))) { 1041 1024 #ifdef CONFIG_IP_VS_IPV6 1042 1025 if (af == AF_INET6) 1043 1026 icmpv6_send(skb, ··· 1262 1235 1263 1236 /* do the statistics and put it back */ 1264 1237 ip_vs_in_stats(cp, skb); 1265 - if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr) 1238 + if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || 1239 + IPPROTO_SCTP == cih->nexthdr) 1266 1240 offset += 2 * sizeof(__u16); 1267 1241 verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); 1268 1242 /* do not touch skb anymore */ ··· 1386 1358 * encorage the standby servers to update the connections timeout 1387 1359 */ 1388 1360 pkts = atomic_add_return(1, &cp->in_pkts); 1361 + if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) && 1362 + cp->protocol == IPPROTO_SCTP) { 1363 + if ((cp->state == IP_VS_SCTP_S_ESTABLISHED && 1364 + (atomic_read(&cp->in_pkts) % 1365 + sysctl_ip_vs_sync_threshold[1] 1366 + == sysctl_ip_vs_sync_threshold[0])) || 1367 + (cp->old_state != cp->state && 1368 + ((cp->state == IP_VS_SCTP_S_CLOSED) || 1369 + (cp->state == IP_VS_SCTP_S_SHUT_ACK_CLI) || 1370 + (cp->state == IP_VS_SCTP_S_SHUT_ACK_SER)))) { 1371 + ip_vs_sync_conn(cp); 1372 + goto out; 1373 + } 1374 + } 1375 + 1389 1376 if (af == AF_INET && 1390 1377 (ip_vs_sync_state & IP_VS_STATE_MASTER) && 1391 1378 (((cp->protocol != IPPROTO_TCP || ··· 1413 1370 (cp->state == IP_VS_TCP_S_CLOSE_WAIT) || 1414 1371 (cp->state == IP_VS_TCP_S_TIME_WAIT))))) 1415 1372 ip_vs_sync_conn(cp); 1373 + out: 1416 1374 cp->old_state = cp->state; 1417 1375 1418 1376 ip_vs_conn_put(cp);
+3 -2
net/netfilter/ipvs/ip_vs_ctl.c
··· 2132 2132 } 2133 2133 } 2134 2134 2135 - /* Check for valid protocol: TCP or UDP, even for fwmark!=0 */ 2136 - if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP) { 2135 + /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */ 2136 + if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP && 2137 + usvc.protocol != IPPROTO_SCTP) { 2137 2138 pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n", 2138 2139 usvc.protocol, &usvc.addr.ip, 2139 2140 ntohs(usvc.port), usvc.sched_name);
+3
net/netfilter/ipvs/ip_vs_proto.c
··· 257 257 #ifdef CONFIG_IP_VS_PROTO_UDP 258 258 REGISTER_PROTOCOL(&ip_vs_protocol_udp); 259 259 #endif 260 + #ifdef CONFIG_IP_VS_PROTO_SCTP 261 + REGISTER_PROTOCOL(&ip_vs_protocol_sctp); 262 + #endif 260 263 #ifdef CONFIG_IP_VS_PROTO_AH 261 264 REGISTER_PROTOCOL(&ip_vs_protocol_ah); 262 265 #endif
+1183
net/netfilter/ipvs/ip_vs_proto_sctp.c
··· 1 + #include <linux/kernel.h> 2 + #include <linux/ip.h> 3 + #include <linux/sctp.h> 4 + #include <net/ip.h> 5 + #include <net/ip6_checksum.h> 6 + #include <linux/netfilter.h> 7 + #include <linux/netfilter_ipv4.h> 8 + #include <net/sctp/checksum.h> 9 + #include <net/ip_vs.h> 10 + 11 + 12 + static struct ip_vs_conn * 13 + sctp_conn_in_get(int af, 14 + const struct sk_buff *skb, 15 + struct ip_vs_protocol *pp, 16 + const struct ip_vs_iphdr *iph, 17 + unsigned int proto_off, 18 + int inverse) 19 + { 20 + __be16 _ports[2], *pptr; 21 + 22 + pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); 23 + if (pptr == NULL) 24 + return NULL; 25 + 26 + if (likely(!inverse)) 27 + return ip_vs_conn_in_get(af, iph->protocol, 28 + &iph->saddr, pptr[0], 29 + &iph->daddr, pptr[1]); 30 + else 31 + return ip_vs_conn_in_get(af, iph->protocol, 32 + &iph->daddr, pptr[1], 33 + &iph->saddr, pptr[0]); 34 + } 35 + 36 + static struct ip_vs_conn * 37 + sctp_conn_out_get(int af, 38 + const struct sk_buff *skb, 39 + struct ip_vs_protocol *pp, 40 + const struct ip_vs_iphdr *iph, 41 + unsigned int proto_off, 42 + int inverse) 43 + { 44 + __be16 _ports[2], *pptr; 45 + 46 + pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); 47 + if (pptr == NULL) 48 + return NULL; 49 + 50 + if (likely(!inverse)) 51 + return ip_vs_conn_out_get(af, iph->protocol, 52 + &iph->saddr, pptr[0], 53 + &iph->daddr, pptr[1]); 54 + else 55 + return ip_vs_conn_out_get(af, iph->protocol, 56 + &iph->daddr, pptr[1], 57 + &iph->saddr, pptr[0]); 58 + } 59 + 60 + static int 61 + sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, 62 + int *verdict, struct ip_vs_conn **cpp) 63 + { 64 + struct ip_vs_service *svc; 65 + sctp_chunkhdr_t _schunkh, *sch; 66 + sctp_sctphdr_t *sh, _sctph; 67 + struct ip_vs_iphdr iph; 68 + 69 + ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); 70 + 71 + sh = skb_header_pointer(skb, iph.len, sizeof(_sctph), &_sctph); 72 + if (sh == NULL) 73 + return 0; 74 + 75 + sch = skb_header_pointer(skb, iph.len + sizeof(sctp_sctphdr_t), 76 + sizeof(_schunkh), &_schunkh); 77 + if (sch == NULL) 78 + return 0; 79 + 80 + if ((sch->type == SCTP_CID_INIT) && 81 + (svc = ip_vs_service_get(af, skb->mark, iph.protocol, 82 + &iph.daddr, sh->dest))) { 83 + if (ip_vs_todrop()) { 84 + /* 85 + * It seems that we are very loaded. 86 + * We have to drop this packet :( 87 + */ 88 + ip_vs_service_put(svc); 89 + *verdict = NF_DROP; 90 + return 0; 91 + } 92 + /* 93 + * Let the virtual server select a real server for the 94 + * incoming connection, and create a connection entry. 95 + */ 96 + *cpp = ip_vs_schedule(svc, skb); 97 + if (!*cpp) { 98 + *verdict = ip_vs_leave(svc, skb, pp); 99 + return 0; 100 + } 101 + ip_vs_service_put(svc); 102 + } 103 + 104 + return 1; 105 + } 106 + 107 + static int 108 + sctp_snat_handler(struct sk_buff *skb, 109 + struct ip_vs_protocol *pp, struct ip_vs_conn *cp) 110 + { 111 + sctp_sctphdr_t *sctph; 112 + unsigned int sctphoff; 113 + __be32 crc32; 114 + 115 + #ifdef CONFIG_IP_VS_IPV6 116 + if (cp->af == AF_INET6) 117 + sctphoff = sizeof(struct ipv6hdr); 118 + else 119 + #endif 120 + sctphoff = ip_hdrlen(skb); 121 + 122 + /* csum_check requires unshared skb */ 123 + if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) 124 + return 0; 125 + 126 + if (unlikely(cp->app != NULL)) { 127 + /* Some checks before mangling */ 128 + if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) 129 + return 0; 130 + 131 + /* Call application helper if needed */ 132 + if (!ip_vs_app_pkt_out(cp, skb)) 133 + return 0; 134 + } 135 + 136 + sctph = (void *) skb_network_header(skb) + sctphoff; 137 + sctph->source = cp->vport; 138 + 139 + /* Calculate the checksum */ 140 + crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff); 141 + for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) 142 + crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb), 143 + crc32); 144 + crc32 = sctp_end_cksum(crc32); 145 + sctph->checksum = crc32; 146 + 147 + return 1; 148 + } 149 + 150 + static int 151 + sctp_dnat_handler(struct sk_buff *skb, 152 + struct ip_vs_protocol *pp, struct ip_vs_conn *cp) 153 + { 154 + 155 + sctp_sctphdr_t *sctph; 156 + unsigned int sctphoff; 157 + __be32 crc32; 158 + 159 + #ifdef CONFIG_IP_VS_IPV6 160 + if (cp->af == AF_INET6) 161 + sctphoff = sizeof(struct ipv6hdr); 162 + else 163 + #endif 164 + sctphoff = ip_hdrlen(skb); 165 + 166 + /* csum_check requires unshared skb */ 167 + if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) 168 + return 0; 169 + 170 + if (unlikely(cp->app != NULL)) { 171 + /* Some checks before mangling */ 172 + if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) 173 + return 0; 174 + 175 + /* Call application helper if needed */ 176 + if (!ip_vs_app_pkt_out(cp, skb)) 177 + return 0; 178 + } 179 + 180 + sctph = (void *) skb_network_header(skb) + sctphoff; 181 + sctph->dest = cp->dport; 182 + 183 + /* Calculate the checksum */ 184 + crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff); 185 + for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) 186 + crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb), 187 + crc32); 188 + crc32 = sctp_end_cksum(crc32); 189 + sctph->checksum = crc32; 190 + 191 + return 1; 192 + } 193 + 194 + static int 195 + sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) 196 + { 197 + struct sk_buff *list = skb_shinfo(skb)->frag_list; 198 + unsigned int sctphoff; 199 + struct sctphdr *sh, _sctph; 200 + __le32 cmp; 201 + __le32 val; 202 + __u32 tmp; 203 + 204 + #ifdef CONFIG_IP_VS_IPV6 205 + if (af == AF_INET6) 206 + sctphoff = sizeof(struct ipv6hdr); 207 + else 208 + #endif 209 + sctphoff = ip_hdrlen(skb); 210 + 211 + sh = skb_header_pointer(skb, sctphoff, sizeof(_sctph), &_sctph); 212 + if (sh == NULL) 213 + return 0; 214 + 215 + cmp = sh->checksum; 216 + 217 + tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb)); 218 + for (; list; list = list->next) 219 + tmp = sctp_update_cksum((__u8 *) list->data, 220 + skb_headlen(list), tmp); 221 + 222 + val = sctp_end_cksum(tmp); 223 + 224 + if (val != cmp) { 225 + /* CRC failure, dump it. */ 226 + IP_VS_DBG_RL_PKT(0, pp, skb, 0, 227 + "Failed checksum for"); 228 + return 0; 229 + } 230 + return 1; 231 + } 232 + 233 + struct ipvs_sctp_nextstate { 234 + int next_state; 235 + }; 236 + enum ipvs_sctp_event_t { 237 + IP_VS_SCTP_EVE_DATA_CLI, 238 + IP_VS_SCTP_EVE_DATA_SER, 239 + IP_VS_SCTP_EVE_INIT_CLI, 240 + IP_VS_SCTP_EVE_INIT_SER, 241 + IP_VS_SCTP_EVE_INIT_ACK_CLI, 242 + IP_VS_SCTP_EVE_INIT_ACK_SER, 243 + IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, 244 + IP_VS_SCTP_EVE_COOKIE_ECHO_SER, 245 + IP_VS_SCTP_EVE_COOKIE_ACK_CLI, 246 + IP_VS_SCTP_EVE_COOKIE_ACK_SER, 247 + IP_VS_SCTP_EVE_ABORT_CLI, 248 + IP_VS_SCTP_EVE__ABORT_SER, 249 + IP_VS_SCTP_EVE_SHUT_CLI, 250 + IP_VS_SCTP_EVE_SHUT_SER, 251 + IP_VS_SCTP_EVE_SHUT_ACK_CLI, 252 + IP_VS_SCTP_EVE_SHUT_ACK_SER, 253 + IP_VS_SCTP_EVE_SHUT_COM_CLI, 254 + IP_VS_SCTP_EVE_SHUT_COM_SER, 255 + IP_VS_SCTP_EVE_LAST 256 + }; 257 + 258 + static enum ipvs_sctp_event_t sctp_events[255] = { 259 + IP_VS_SCTP_EVE_DATA_CLI, 260 + IP_VS_SCTP_EVE_INIT_CLI, 261 + IP_VS_SCTP_EVE_INIT_ACK_CLI, 262 + IP_VS_SCTP_EVE_DATA_CLI, 263 + IP_VS_SCTP_EVE_DATA_CLI, 264 + IP_VS_SCTP_EVE_DATA_CLI, 265 + IP_VS_SCTP_EVE_ABORT_CLI, 266 + IP_VS_SCTP_EVE_SHUT_CLI, 267 + IP_VS_SCTP_EVE_SHUT_ACK_CLI, 268 + IP_VS_SCTP_EVE_DATA_CLI, 269 + IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, 270 + IP_VS_SCTP_EVE_COOKIE_ACK_CLI, 271 + IP_VS_SCTP_EVE_DATA_CLI, 272 + IP_VS_SCTP_EVE_DATA_CLI, 273 + IP_VS_SCTP_EVE_SHUT_COM_CLI, 274 + }; 275 + 276 + static struct ipvs_sctp_nextstate 277 + sctp_states_table[IP_VS_SCTP_S_LAST][IP_VS_SCTP_EVE_LAST] = { 278 + /* 279 + * STATE : IP_VS_SCTP_S_NONE 280 + */ 281 + /*next state *//*event */ 282 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 283 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 284 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 285 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 286 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 287 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 288 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 289 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 290 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 291 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 292 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 293 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 294 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 295 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 296 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 297 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 298 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 299 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ }, 300 + }, 301 + /* 302 + * STATE : IP_VS_SCTP_S_INIT_CLI 303 + * Cient sent INIT and is waiting for reply from server(In ECHO_WAIT) 304 + */ 305 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 306 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 307 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 308 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 309 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 310 + {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 311 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ECHO_CLI */ }, 312 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_ECHO_SER */ }, 313 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 314 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 315 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 316 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 317 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 318 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 319 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 320 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 321 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 322 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 323 + }, 324 + /* 325 + * State : IP_VS_SCTP_S_INIT_SER 326 + * Server sent INIT and waiting for INIT ACK from the client 327 + */ 328 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 329 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 330 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 331 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 332 + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 333 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 334 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 335 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 336 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 337 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 338 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 339 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 340 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 341 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 342 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 343 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 344 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 345 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 346 + }, 347 + /* 348 + * State : IP_VS_SCTP_S_INIT_ACK_CLI 349 + * Client sent INIT ACK and waiting for ECHO from the server 350 + */ 351 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 352 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 353 + /* 354 + * We have got an INIT from client. From the spec.“Upon receipt of 355 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 356 + * an INIT ACK using the same parameters it sent in its original 357 + * INIT chunk (including its Initiate Tag, unchanged”). 358 + */ 359 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 360 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 361 + /* 362 + * INIT_ACK has been resent by the client, let us stay is in 363 + * the same state 364 + */ 365 + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 366 + /* 367 + * INIT_ACK sent by the server, close the connection 368 + */ 369 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 370 + /* 371 + * ECHO by client, it should not happen, close the connection 372 + */ 373 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 374 + /* 375 + * ECHO by server, this is what we are expecting, move to ECHO_SER 376 + */ 377 + {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 378 + /* 379 + * COOKIE ACK from client, it should not happen, close the connection 380 + */ 381 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 382 + /* 383 + * Unexpected COOKIE ACK from server, staty in the same state 384 + */ 385 + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 386 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 387 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 388 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 389 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 390 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 391 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 392 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 393 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 394 + }, 395 + /* 396 + * State : IP_VS_SCTP_S_INIT_ACK_SER 397 + * Server sent INIT ACK and waiting for ECHO from the client 398 + */ 399 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 400 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 401 + /* 402 + * We have got an INIT from client. From the spec.“Upon receipt of 403 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 404 + * an INIT ACK using the same parameters it sent in its original 405 + * INIT chunk (including its Initiate Tag, unchanged”). 406 + */ 407 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 408 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 409 + /* 410 + * Unexpected INIT_ACK by the client, let us close the connection 411 + */ 412 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 413 + /* 414 + * INIT_ACK resent by the server, let us move to same state 415 + */ 416 + {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 417 + /* 418 + * Client send the ECHO, this is what we are expecting, 419 + * move to ECHO_CLI 420 + */ 421 + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 422 + /* 423 + * ECHO received from the server, Not sure what to do, 424 + * let us close it 425 + */ 426 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 427 + /* 428 + * COOKIE ACK from client, let us stay in the same state 429 + */ 430 + {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 431 + /* 432 + * COOKIE ACK from server, hmm... this should not happen, lets close 433 + * the connection. 434 + */ 435 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 436 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 437 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 438 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 439 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 440 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 441 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 442 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 443 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 444 + }, 445 + /* 446 + * State : IP_VS_SCTP_S_ECHO_CLI 447 + * Cient sent ECHO and waiting COOKEI ACK from the Server 448 + */ 449 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 450 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 451 + /* 452 + * We have got an INIT from client. From the spec.“Upon receipt of 453 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 454 + * an INIT ACK using the same parameters it sent in its original 455 + * INIT chunk (including its Initiate Tag, unchanged”). 456 + */ 457 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 458 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 459 + /* 460 + * INIT_ACK has been by the client, let us close the connection 461 + */ 462 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 463 + /* 464 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 465 + * “If an INIT ACK is received by an endpoint in any state other 466 + * than the COOKIE-WAIT state, the endpoint should discard the 467 + * INIT ACK chunk”. Stay in the same state 468 + */ 469 + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 470 + /* 471 + * Client resent the ECHO, let us stay in the same state 472 + */ 473 + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 474 + /* 475 + * ECHO received from the server, Not sure what to do, 476 + * let us close it 477 + */ 478 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 479 + /* 480 + * COOKIE ACK from client, this shoud not happen, let's close the 481 + * connection 482 + */ 483 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 484 + /* 485 + * COOKIE ACK from server, this is what we are awaiting,lets move to 486 + * ESTABLISHED. 487 + */ 488 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 489 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 490 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 491 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 492 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 493 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 494 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 495 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 496 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 497 + }, 498 + /* 499 + * State : IP_VS_SCTP_S_ECHO_SER 500 + * Server sent ECHO and waiting COOKEI ACK from the client 501 + */ 502 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 503 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 504 + /* 505 + * We have got an INIT from client. From the spec.“Upon receipt of 506 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 507 + * an INIT ACK using the same parameters it sent in its original 508 + * INIT chunk (including its Initiate Tag, unchanged”). 509 + */ 510 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 511 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 512 + /* 513 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 514 + * “If an INIT ACK is received by an endpoint in any state other 515 + * than the COOKIE-WAIT state, the endpoint should discard the 516 + * INIT ACK chunk”. Stay in the same state 517 + */ 518 + {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 519 + /* 520 + * INIT_ACK has been by the server, let us close the connection 521 + */ 522 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 523 + /* 524 + * Client sent the ECHO, not sure what to do, let's close the 525 + * connection. 526 + */ 527 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 528 + /* 529 + * ECHO resent by the server, stay in the same state 530 + */ 531 + {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 532 + /* 533 + * COOKIE ACK from client, this is what we are expecting, let's move 534 + * to ESTABLISHED. 535 + */ 536 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 537 + /* 538 + * COOKIE ACK from server, this should not happen, lets close the 539 + * connection. 540 + */ 541 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 542 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 543 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 544 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 545 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 546 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 547 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 548 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 549 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 550 + }, 551 + /* 552 + * State : IP_VS_SCTP_S_ESTABLISHED 553 + * Association established 554 + */ 555 + {{IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 556 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_SER */ }, 557 + /* 558 + * We have got an INIT from client. From the spec.“Upon receipt of 559 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 560 + * an INIT ACK using the same parameters it sent in its original 561 + * INIT chunk (including its Initiate Tag, unchanged”). 562 + */ 563 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 564 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 565 + /* 566 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 567 + * “If an INIT ACK is received by an endpoint in any state other 568 + * than the COOKIE-WAIT state, the endpoint should discard the 569 + * INIT ACK chunk”. Stay in the same state 570 + */ 571 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 572 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 573 + /* 574 + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the 575 + * peer and peer shall move to the ESTABISHED. if it doesn't handle 576 + * it will send ERROR chunk. So, stay in the same state 577 + */ 578 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 579 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 580 + /* 581 + * COOKIE ACK from client, not sure what to do stay in the same state 582 + */ 583 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 584 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 585 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 586 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 587 + /* 588 + * SHUTDOWN from the client, move to SHUDDOWN_CLI 589 + */ 590 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 591 + /* 592 + * SHUTDOWN from the server, move to SHUTDOWN_SER 593 + */ 594 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, 595 + /* 596 + * client sent SHUDTDOWN_ACK, this should not happen, let's close 597 + * the connection 598 + */ 599 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 600 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 601 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 602 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 603 + }, 604 + /* 605 + * State : IP_VS_SCTP_S_SHUT_CLI 606 + * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server 607 + */ 608 + /* 609 + * We recieved the data chuck, keep the state unchanged. I assume 610 + * that still data chuncks can be received by both the peers in 611 + * SHUDOWN state 612 + */ 613 + 614 + {{IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, 615 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, 616 + /* 617 + * We have got an INIT from client. From the spec.“Upon receipt of 618 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 619 + * an INIT ACK using the same parameters it sent in its original 620 + * INIT chunk (including its Initiate Tag, unchanged”). 621 + */ 622 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 623 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 624 + /* 625 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 626 + * “If an INIT ACK is received by an endpoint in any state other 627 + * than the COOKIE-WAIT state, the endpoint should discard the 628 + * INIT ACK chunk”. Stay in the same state 629 + */ 630 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 631 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 632 + /* 633 + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the 634 + * peer and peer shall move to the ESTABISHED. if it doesn't handle 635 + * it will send ERROR chunk. So, stay in the same state 636 + */ 637 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 638 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 639 + /* 640 + * COOKIE ACK from client, not sure what to do stay in the same state 641 + */ 642 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 643 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 644 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 645 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 646 + /* 647 + * SHUTDOWN resent from the client, move to SHUDDOWN_CLI 648 + */ 649 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 650 + /* 651 + * SHUTDOWN from the server, move to SHUTDOWN_SER 652 + */ 653 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, 654 + /* 655 + * client sent SHUDTDOWN_ACK, this should not happen, let's close 656 + * the connection 657 + */ 658 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 659 + /* 660 + * Server sent SHUTDOWN ACK, this is what we are expecting, let's move 661 + * to SHUDOWN_ACK_SER 662 + */ 663 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 664 + /* 665 + * SHUTDOWN COM from client, this should not happen, let's close the 666 + * connection 667 + */ 668 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 669 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 670 + }, 671 + /* 672 + * State : IP_VS_SCTP_S_SHUT_SER 673 + * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client 674 + */ 675 + /* 676 + * We recieved the data chuck, keep the state unchanged. I assume 677 + * that still data chuncks can be received by both the peers in 678 + * SHUDOWN state 679 + */ 680 + 681 + {{IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, 682 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, 683 + /* 684 + * We have got an INIT from client. From the spec.“Upon receipt of 685 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 686 + * an INIT ACK using the same parameters it sent in its original 687 + * INIT chunk (including its Initiate Tag, unchanged”). 688 + */ 689 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 690 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 691 + /* 692 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 693 + * “If an INIT ACK is received by an endpoint in any state other 694 + * than the COOKIE-WAIT state, the endpoint should discard the 695 + * INIT ACK chunk”. Stay in the same state 696 + */ 697 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 698 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 699 + /* 700 + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the 701 + * peer and peer shall move to the ESTABISHED. if it doesn't handle 702 + * it will send ERROR chunk. So, stay in the same state 703 + */ 704 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 705 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 706 + /* 707 + * COOKIE ACK from client, not sure what to do stay in the same state 708 + */ 709 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 710 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 711 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 712 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 713 + /* 714 + * SHUTDOWN resent from the client, move to SHUDDOWN_CLI 715 + */ 716 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 717 + /* 718 + * SHUTDOWN resent from the server, move to SHUTDOWN_SER 719 + */ 720 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, 721 + /* 722 + * client sent SHUDTDOWN_ACK, this is what we are expecting, let's 723 + * move to SHUT_ACK_CLI 724 + */ 725 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 726 + /* 727 + * Server sent SHUTDOWN ACK, this should not happen, let's close the 728 + * connection 729 + */ 730 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 731 + /* 732 + * SHUTDOWN COM from client, this should not happen, let's close the 733 + * connection 734 + */ 735 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 736 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 737 + }, 738 + 739 + /* 740 + * State : IP_VS_SCTP_S_SHUT_ACK_CLI 741 + * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server 742 + */ 743 + /* 744 + * We recieved the data chuck, keep the state unchanged. I assume 745 + * that still data chuncks can be received by both the peers in 746 + * SHUDOWN state 747 + */ 748 + 749 + {{IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, 750 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, 751 + /* 752 + * We have got an INIT from client. From the spec.“Upon receipt of 753 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 754 + * an INIT ACK using the same parameters it sent in its original 755 + * INIT chunk (including its Initiate Tag, unchanged”). 756 + */ 757 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 758 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 759 + /* 760 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 761 + * “If an INIT ACK is received by an endpoint in any state other 762 + * than the COOKIE-WAIT state, the endpoint should discard the 763 + * INIT ACK chunk”. Stay in the same state 764 + */ 765 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 766 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 767 + /* 768 + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the 769 + * peer and peer shall move to the ESTABISHED. if it doesn't handle 770 + * it will send ERROR chunk. So, stay in the same state 771 + */ 772 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 773 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 774 + /* 775 + * COOKIE ACK from client, not sure what to do stay in the same state 776 + */ 777 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 778 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 779 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 780 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 781 + /* 782 + * SHUTDOWN sent from the client, move to SHUDDOWN_CLI 783 + */ 784 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 785 + /* 786 + * SHUTDOWN sent from the server, move to SHUTDOWN_SER 787 + */ 788 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, 789 + /* 790 + * client resent SHUDTDOWN_ACK, let's stay in the same state 791 + */ 792 + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 793 + /* 794 + * Server sent SHUTDOWN ACK, this should not happen, let's close the 795 + * connection 796 + */ 797 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 798 + /* 799 + * SHUTDOWN COM from client, this should not happen, let's close the 800 + * connection 801 + */ 802 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 803 + /* 804 + * SHUTDOWN COMPLETE from server this is what we are expecting. 805 + */ 806 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 807 + }, 808 + 809 + /* 810 + * State : IP_VS_SCTP_S_SHUT_ACK_SER 811 + * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client 812 + */ 813 + /* 814 + * We recieved the data chuck, keep the state unchanged. I assume 815 + * that still data chuncks can be received by both the peers in 816 + * SHUDOWN state 817 + */ 818 + 819 + {{IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, 820 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, 821 + /* 822 + * We have got an INIT from client. From the spec.“Upon receipt of 823 + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with 824 + * an INIT ACK using the same parameters it sent in its original 825 + * INIT chunk (including its Initiate Tag, unchanged”). 826 + */ 827 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 828 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 829 + /* 830 + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, 831 + * “If an INIT ACK is received by an endpoint in any state other 832 + * than the COOKIE-WAIT state, the endpoint should discard the 833 + * INIT ACK chunk”. Stay in the same state 834 + */ 835 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 836 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 837 + /* 838 + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the 839 + * peer and peer shall move to the ESTABISHED. if it doesn't handle 840 + * it will send ERROR chunk. So, stay in the same state 841 + */ 842 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 843 + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 844 + /* 845 + * COOKIE ACK from client, not sure what to do stay in the same state 846 + */ 847 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 848 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 849 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 850 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 851 + /* 852 + * SHUTDOWN sent from the client, move to SHUDDOWN_CLI 853 + */ 854 + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 855 + /* 856 + * SHUTDOWN sent from the server, move to SHUTDOWN_SER 857 + */ 858 + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, 859 + /* 860 + * client sent SHUDTDOWN_ACK, this should not happen let's close 861 + * the connection. 862 + */ 863 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 864 + /* 865 + * Server resent SHUTDOWN ACK, stay in the same state 866 + */ 867 + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 868 + /* 869 + * SHUTDOWN COM from client, this what we are expecting, let's close 870 + * the connection 871 + */ 872 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 873 + /* 874 + * SHUTDOWN COMPLETE from server this should not happen. 875 + */ 876 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 877 + }, 878 + /* 879 + * State : IP_VS_SCTP_S_CLOSED 880 + */ 881 + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, 882 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, 883 + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, 884 + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, 885 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, 886 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, 887 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, 888 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, 889 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, 890 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, 891 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, 892 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, 893 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, 894 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, 895 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, 896 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, 897 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, 898 + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } 899 + } 900 + }; 901 + 902 + /* 903 + * Timeout table[state] 904 + */ 905 + static int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = { 906 + [IP_VS_SCTP_S_NONE] = 2 * HZ, 907 + [IP_VS_SCTP_S_INIT_CLI] = 1 * 60 * HZ, 908 + [IP_VS_SCTP_S_INIT_SER] = 1 * 60 * HZ, 909 + [IP_VS_SCTP_S_INIT_ACK_CLI] = 1 * 60 * HZ, 910 + [IP_VS_SCTP_S_INIT_ACK_SER] = 1 * 60 * HZ, 911 + [IP_VS_SCTP_S_ECHO_CLI] = 1 * 60 * HZ, 912 + [IP_VS_SCTP_S_ECHO_SER] = 1 * 60 * HZ, 913 + [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ, 914 + [IP_VS_SCTP_S_SHUT_CLI] = 1 * 60 * HZ, 915 + [IP_VS_SCTP_S_SHUT_SER] = 1 * 60 * HZ, 916 + [IP_VS_SCTP_S_SHUT_ACK_CLI] = 1 * 60 * HZ, 917 + [IP_VS_SCTP_S_SHUT_ACK_SER] = 1 * 60 * HZ, 918 + [IP_VS_SCTP_S_CLOSED] = 10 * HZ, 919 + [IP_VS_SCTP_S_LAST] = 2 * HZ, 920 + }; 921 + 922 + static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = { 923 + [IP_VS_SCTP_S_NONE] = "NONE", 924 + [IP_VS_SCTP_S_INIT_CLI] = "INIT_CLI", 925 + [IP_VS_SCTP_S_INIT_SER] = "INIT_SER", 926 + [IP_VS_SCTP_S_INIT_ACK_CLI] = "INIT_ACK_CLI", 927 + [IP_VS_SCTP_S_INIT_ACK_SER] = "INIT_ACK_SER", 928 + [IP_VS_SCTP_S_ECHO_CLI] = "COOKIE_ECHO_CLI", 929 + [IP_VS_SCTP_S_ECHO_SER] = "COOKIE_ECHO_SER", 930 + [IP_VS_SCTP_S_ESTABLISHED] = "ESTABISHED", 931 + [IP_VS_SCTP_S_SHUT_CLI] = "SHUTDOWN_CLI", 932 + [IP_VS_SCTP_S_SHUT_SER] = "SHUTDOWN_SER", 933 + [IP_VS_SCTP_S_SHUT_ACK_CLI] = "SHUTDOWN_ACK_CLI", 934 + [IP_VS_SCTP_S_SHUT_ACK_SER] = "SHUTDOWN_ACK_SER", 935 + [IP_VS_SCTP_S_CLOSED] = "CLOSED", 936 + [IP_VS_SCTP_S_LAST] = "BUG!" 937 + }; 938 + 939 + 940 + static const char *sctp_state_name(int state) 941 + { 942 + if (state >= IP_VS_SCTP_S_LAST) 943 + return "ERR!"; 944 + if (sctp_state_name_table[state]) 945 + return sctp_state_name_table[state]; 946 + return "?"; 947 + } 948 + 949 + static void sctp_timeout_change(struct ip_vs_protocol *pp, int flags) 950 + { 951 + } 952 + 953 + static int 954 + sctp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to) 955 + { 956 + 957 + return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_SCTP_S_LAST, 958 + sctp_state_name_table, sname, to); 959 + } 960 + 961 + static inline int 962 + set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, 963 + int direction, const struct sk_buff *skb) 964 + { 965 + sctp_chunkhdr_t _sctpch, *sch; 966 + unsigned char chunk_type; 967 + int event, next_state; 968 + int ihl; 969 + 970 + #ifdef CONFIG_IP_VS_IPV6 971 + ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr); 972 + #else 973 + ihl = ip_hdrlen(skb); 974 + #endif 975 + 976 + sch = skb_header_pointer(skb, ihl + sizeof(sctp_sctphdr_t), 977 + sizeof(_sctpch), &_sctpch); 978 + if (sch == NULL) 979 + return 0; 980 + 981 + chunk_type = sch->type; 982 + /* 983 + * Section 3: Multiple chunks can be bundled into one SCTP packet 984 + * up to the MTU size, except for the INIT, INIT ACK, and 985 + * SHUTDOWN COMPLETE chunks. These chunks MUST NOT be bundled with 986 + * any other chunk in a packet. 987 + * 988 + * Section 3.3.7: DATA chunks MUST NOT be bundled with ABORT. Control 989 + * chunks (except for INIT, INIT ACK, and SHUTDOWN COMPLETE) MAY be 990 + * bundled with an ABORT, but they MUST be placed before the ABORT 991 + * in the SCTP packet or they will be ignored by the receiver. 992 + */ 993 + if ((sch->type == SCTP_CID_COOKIE_ECHO) || 994 + (sch->type == SCTP_CID_COOKIE_ACK)) { 995 + sch = skb_header_pointer(skb, (ihl + sizeof(sctp_sctphdr_t) + 996 + sch->length), sizeof(_sctpch), &_sctpch); 997 + if (sch) { 998 + if (sch->type == SCTP_CID_ABORT) 999 + chunk_type = sch->type; 1000 + } 1001 + } 1002 + 1003 + event = sctp_events[chunk_type]; 1004 + 1005 + /* 1006 + * If the direction is IP_VS_DIR_OUTPUT, this event is from server 1007 + */ 1008 + if (direction == IP_VS_DIR_OUTPUT) 1009 + event++; 1010 + /* 1011 + * get next state 1012 + */ 1013 + next_state = sctp_states_table[cp->state][event].next_state; 1014 + 1015 + if (next_state != cp->state) { 1016 + struct ip_vs_dest *dest = cp->dest; 1017 + 1018 + IP_VS_DBG_BUF(8, "%s %s %s:%d->" 1019 + "%s:%d state: %s->%s conn->refcnt:%d\n", 1020 + pp->name, 1021 + ((direction == IP_VS_DIR_OUTPUT) ? 1022 + "output " : "input "), 1023 + IP_VS_DBG_ADDR(cp->af, &cp->daddr), 1024 + ntohs(cp->dport), 1025 + IP_VS_DBG_ADDR(cp->af, &cp->caddr), 1026 + ntohs(cp->cport), 1027 + sctp_state_name(cp->state), 1028 + sctp_state_name(next_state), 1029 + atomic_read(&cp->refcnt)); 1030 + if (dest) { 1031 + if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && 1032 + (next_state != IP_VS_SCTP_S_ESTABLISHED)) { 1033 + atomic_dec(&dest->activeconns); 1034 + atomic_inc(&dest->inactconns); 1035 + cp->flags |= IP_VS_CONN_F_INACTIVE; 1036 + } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) && 1037 + (next_state == IP_VS_SCTP_S_ESTABLISHED)) { 1038 + atomic_inc(&dest->activeconns); 1039 + atomic_dec(&dest->inactconns); 1040 + cp->flags &= ~IP_VS_CONN_F_INACTIVE; 1041 + } 1042 + } 1043 + } 1044 + 1045 + cp->timeout = pp->timeout_table[cp->state = next_state]; 1046 + 1047 + return 1; 1048 + } 1049 + 1050 + static int 1051 + sctp_state_transition(struct ip_vs_conn *cp, int direction, 1052 + const struct sk_buff *skb, struct ip_vs_protocol *pp) 1053 + { 1054 + int ret = 0; 1055 + 1056 + spin_lock(&cp->lock); 1057 + ret = set_sctp_state(pp, cp, direction, skb); 1058 + spin_unlock(&cp->lock); 1059 + 1060 + return ret; 1061 + } 1062 + 1063 + /* 1064 + * Hash table for SCTP application incarnations 1065 + */ 1066 + #define SCTP_APP_TAB_BITS 4 1067 + #define SCTP_APP_TAB_SIZE (1 << SCTP_APP_TAB_BITS) 1068 + #define SCTP_APP_TAB_MASK (SCTP_APP_TAB_SIZE - 1) 1069 + 1070 + static struct list_head sctp_apps[SCTP_APP_TAB_SIZE]; 1071 + static DEFINE_SPINLOCK(sctp_app_lock); 1072 + 1073 + static inline __u16 sctp_app_hashkey(__be16 port) 1074 + { 1075 + return (((__force u16)port >> SCTP_APP_TAB_BITS) ^ (__force u16)port) 1076 + & SCTP_APP_TAB_MASK; 1077 + } 1078 + 1079 + static int sctp_register_app(struct ip_vs_app *inc) 1080 + { 1081 + struct ip_vs_app *i; 1082 + __u16 hash; 1083 + __be16 port = inc->port; 1084 + int ret = 0; 1085 + 1086 + hash = sctp_app_hashkey(port); 1087 + 1088 + spin_lock_bh(&sctp_app_lock); 1089 + list_for_each_entry(i, &sctp_apps[hash], p_list) { 1090 + if (i->port == port) { 1091 + ret = -EEXIST; 1092 + goto out; 1093 + } 1094 + } 1095 + list_add(&inc->p_list, &sctp_apps[hash]); 1096 + atomic_inc(&ip_vs_protocol_sctp.appcnt); 1097 + out: 1098 + spin_unlock_bh(&sctp_app_lock); 1099 + 1100 + return ret; 1101 + } 1102 + 1103 + static void sctp_unregister_app(struct ip_vs_app *inc) 1104 + { 1105 + spin_lock_bh(&sctp_app_lock); 1106 + atomic_dec(&ip_vs_protocol_sctp.appcnt); 1107 + list_del(&inc->p_list); 1108 + spin_unlock_bh(&sctp_app_lock); 1109 + } 1110 + 1111 + static int sctp_app_conn_bind(struct ip_vs_conn *cp) 1112 + { 1113 + int hash; 1114 + struct ip_vs_app *inc; 1115 + int result = 0; 1116 + 1117 + /* Default binding: bind app only for NAT */ 1118 + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) 1119 + return 0; 1120 + /* Lookup application incarnations and bind the right one */ 1121 + hash = sctp_app_hashkey(cp->vport); 1122 + 1123 + spin_lock(&sctp_app_lock); 1124 + list_for_each_entry(inc, &sctp_apps[hash], p_list) { 1125 + if (inc->port == cp->vport) { 1126 + if (unlikely(!ip_vs_app_inc_get(inc))) 1127 + break; 1128 + spin_unlock(&sctp_app_lock); 1129 + 1130 + IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->" 1131 + "%s:%u to app %s on port %u\n", 1132 + __func__, 1133 + IP_VS_DBG_ADDR(cp->af, &cp->caddr), 1134 + ntohs(cp->cport), 1135 + IP_VS_DBG_ADDR(cp->af, &cp->vaddr), 1136 + ntohs(cp->vport), 1137 + inc->name, ntohs(inc->port)); 1138 + cp->app = inc; 1139 + if (inc->init_conn) 1140 + result = inc->init_conn(inc, cp); 1141 + goto out; 1142 + } 1143 + } 1144 + spin_unlock(&sctp_app_lock); 1145 + out: 1146 + return result; 1147 + } 1148 + 1149 + static void ip_vs_sctp_init(struct ip_vs_protocol *pp) 1150 + { 1151 + IP_VS_INIT_HASH_TABLE(sctp_apps); 1152 + pp->timeout_table = sctp_timeouts; 1153 + } 1154 + 1155 + 1156 + static void ip_vs_sctp_exit(struct ip_vs_protocol *pp) 1157 + { 1158 + 1159 + } 1160 + 1161 + struct ip_vs_protocol ip_vs_protocol_sctp = { 1162 + .name = "SCTP", 1163 + .protocol = IPPROTO_SCTP, 1164 + .num_states = IP_VS_SCTP_S_LAST, 1165 + .dont_defrag = 0, 1166 + .appcnt = ATOMIC_INIT(0), 1167 + .init = ip_vs_sctp_init, 1168 + .exit = ip_vs_sctp_exit, 1169 + .register_app = sctp_register_app, 1170 + .unregister_app = sctp_unregister_app, 1171 + .conn_schedule = sctp_conn_schedule, 1172 + .conn_in_get = sctp_conn_in_get, 1173 + .conn_out_get = sctp_conn_out_get, 1174 + .snat_handler = sctp_snat_handler, 1175 + .dnat_handler = sctp_dnat_handler, 1176 + .csum_check = sctp_csum_check, 1177 + .state_name = sctp_state_name, 1178 + .state_transition = sctp_state_transition, 1179 + .app_conn_bind = sctp_app_conn_bind, 1180 + .debug_packet = ip_vs_tcpudp_debug_packet, 1181 + .timeout_change = sctp_timeout_change, 1182 + .set_state_timeout = sctp_set_state_timeout, 1183 + };
+14
net/netfilter/ipvs/ip_vs_sync.c
··· 400 400 flags |= IP_VS_CONN_F_INACTIVE; 401 401 else 402 402 flags &= ~IP_VS_CONN_F_INACTIVE; 403 + } else if (s->protocol == IPPROTO_SCTP) { 404 + if (state != IP_VS_SCTP_S_ESTABLISHED) 405 + flags |= IP_VS_CONN_F_INACTIVE; 406 + else 407 + flags &= ~IP_VS_CONN_F_INACTIVE; 403 408 } 404 409 cp = ip_vs_conn_new(AF_INET, s->protocol, 405 410 (union nf_inet_addr *)&s->caddr, ··· 438 433 atomic_inc(&dest->activeconns); 439 434 atomic_dec(&dest->inactconns); 440 435 cp->flags &= ~IP_VS_CONN_F_INACTIVE; 436 + } 437 + } else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) && 438 + (cp->state != state)) { 439 + dest = cp->dest; 440 + if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && 441 + (state != IP_VS_SCTP_S_ESTABLISHED)) { 442 + atomic_dec(&dest->activeconns); 443 + atomic_inc(&dest->inactconns); 444 + cp->flags &= ~IP_VS_CONN_F_INACTIVE; 441 445 } 442 446 } 443 447