blob: d254345bfda7066504c305832340dc4105f827fb [file] [log] [blame]
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +01001#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
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +010011static int
12sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
13 int *verdict, struct ip_vs_conn **cpp)
14{
15 struct ip_vs_service *svc;
16 sctp_chunkhdr_t _schunkh, *sch;
17 sctp_sctphdr_t *sh, _sctph;
18 struct ip_vs_iphdr iph;
19
20 ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
21
22 sh = skb_header_pointer(skb, iph.len, sizeof(_sctph), &_sctph);
23 if (sh == NULL)
24 return 0;
25
26 sch = skb_header_pointer(skb, iph.len + sizeof(sctp_sctphdr_t),
27 sizeof(_schunkh), &_schunkh);
28 if (sch == NULL)
29 return 0;
30
31 if ((sch->type == SCTP_CID_INIT) &&
32 (svc = ip_vs_service_get(af, skb->mark, iph.protocol,
33 &iph.daddr, sh->dest))) {
Julian Anastasov190ecd22010-10-17 16:24:37 +030034 int ignored;
35
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +010036 if (ip_vs_todrop()) {
37 /*
38 * It seems that we are very loaded.
39 * We have to drop this packet :(
40 */
41 ip_vs_service_put(svc);
42 *verdict = NF_DROP;
43 return 0;
44 }
45 /*
46 * Let the virtual server select a real server for the
47 * incoming connection, and create a connection entry.
48 */
Julian Anastasov190ecd22010-10-17 16:24:37 +030049 *cpp = ip_vs_schedule(svc, skb, pp, &ignored);
50 if (!*cpp && !ignored) {
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +010051 *verdict = ip_vs_leave(svc, skb, pp);
52 return 0;
53 }
54 ip_vs_service_put(svc);
55 }
56
57 return 1;
58}
59
60static int
61sctp_snat_handler(struct sk_buff *skb,
62 struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
63{
64 sctp_sctphdr_t *sctph;
65 unsigned int sctphoff;
66 __be32 crc32;
67
68#ifdef CONFIG_IP_VS_IPV6
69 if (cp->af == AF_INET6)
70 sctphoff = sizeof(struct ipv6hdr);
71 else
72#endif
73 sctphoff = ip_hdrlen(skb);
74
75 /* csum_check requires unshared skb */
76 if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
77 return 0;
78
79 if (unlikely(cp->app != NULL)) {
80 /* Some checks before mangling */
81 if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
82 return 0;
83
84 /* Call application helper if needed */
85 if (!ip_vs_app_pkt_out(cp, skb))
86 return 0;
87 }
88
89 sctph = (void *) skb_network_header(skb) + sctphoff;
90 sctph->source = cp->vport;
91
92 /* Calculate the checksum */
93 crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
94 for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
95 crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb),
96 crc32);
97 crc32 = sctp_end_cksum(crc32);
98 sctph->checksum = crc32;
99
100 return 1;
101}
102
103static int
104sctp_dnat_handler(struct sk_buff *skb,
105 struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
106{
107
108 sctp_sctphdr_t *sctph;
109 unsigned int sctphoff;
110 __be32 crc32;
111
112#ifdef CONFIG_IP_VS_IPV6
113 if (cp->af == AF_INET6)
114 sctphoff = sizeof(struct ipv6hdr);
115 else
116#endif
117 sctphoff = ip_hdrlen(skb);
118
119 /* csum_check requires unshared skb */
120 if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
121 return 0;
122
123 if (unlikely(cp->app != NULL)) {
124 /* Some checks before mangling */
125 if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
126 return 0;
127
128 /* Call application helper if needed */
Xiaoyu Du8a0acaa2010-07-09 17:27:47 +0200129 if (!ip_vs_app_pkt_in(cp, skb))
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +0100130 return 0;
131 }
132
133 sctph = (void *) skb_network_header(skb) + sctphoff;
134 sctph->dest = cp->dport;
135
136 /* Calculate the checksum */
137 crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
138 for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
139 crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb),
140 crc32);
141 crc32 = sctp_end_cksum(crc32);
142 sctph->checksum = crc32;
143
144 return 1;
145}
146
147static int
148sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
149{
150 struct sk_buff *list = skb_shinfo(skb)->frag_list;
151 unsigned int sctphoff;
152 struct sctphdr *sh, _sctph;
153 __le32 cmp;
154 __le32 val;
155 __u32 tmp;
156
157#ifdef CONFIG_IP_VS_IPV6
158 if (af == AF_INET6)
159 sctphoff = sizeof(struct ipv6hdr);
160 else
161#endif
162 sctphoff = ip_hdrlen(skb);
163
164 sh = skb_header_pointer(skb, sctphoff, sizeof(_sctph), &_sctph);
165 if (sh == NULL)
166 return 0;
167
168 cmp = sh->checksum;
169
170 tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb));
171 for (; list; list = list->next)
172 tmp = sctp_update_cksum((__u8 *) list->data,
173 skb_headlen(list), tmp);
174
175 val = sctp_end_cksum(tmp);
176
177 if (val != cmp) {
178 /* CRC failure, dump it. */
Julian Anastasov0d796412010-10-17 16:46:17 +0300179 IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +0100180 "Failed checksum for");
181 return 0;
182 }
183 return 1;
184}
185
186struct ipvs_sctp_nextstate {
187 int next_state;
188};
189enum ipvs_sctp_event_t {
190 IP_VS_SCTP_EVE_DATA_CLI,
191 IP_VS_SCTP_EVE_DATA_SER,
192 IP_VS_SCTP_EVE_INIT_CLI,
193 IP_VS_SCTP_EVE_INIT_SER,
194 IP_VS_SCTP_EVE_INIT_ACK_CLI,
195 IP_VS_SCTP_EVE_INIT_ACK_SER,
196 IP_VS_SCTP_EVE_COOKIE_ECHO_CLI,
197 IP_VS_SCTP_EVE_COOKIE_ECHO_SER,
198 IP_VS_SCTP_EVE_COOKIE_ACK_CLI,
199 IP_VS_SCTP_EVE_COOKIE_ACK_SER,
200 IP_VS_SCTP_EVE_ABORT_CLI,
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};
210
211static enum ipvs_sctp_event_t sctp_events[255] = {
212 IP_VS_SCTP_EVE_DATA_CLI,
213 IP_VS_SCTP_EVE_INIT_CLI,
214 IP_VS_SCTP_EVE_INIT_ACK_CLI,
215 IP_VS_SCTP_EVE_DATA_CLI,
216 IP_VS_SCTP_EVE_DATA_CLI,
217 IP_VS_SCTP_EVE_DATA_CLI,
218 IP_VS_SCTP_EVE_ABORT_CLI,
219 IP_VS_SCTP_EVE_SHUT_CLI,
220 IP_VS_SCTP_EVE_SHUT_ACK_CLI,
221 IP_VS_SCTP_EVE_DATA_CLI,
222 IP_VS_SCTP_EVE_COOKIE_ECHO_CLI,
223 IP_VS_SCTP_EVE_COOKIE_ACK_CLI,
224 IP_VS_SCTP_EVE_DATA_CLI,
225 IP_VS_SCTP_EVE_DATA_CLI,
226 IP_VS_SCTP_EVE_SHUT_COM_CLI,
227};
228
229static struct ipvs_sctp_nextstate
230 sctp_states_table[IP_VS_SCTP_S_LAST][IP_VS_SCTP_EVE_LAST] = {
231 /*
232 * STATE : IP_VS_SCTP_S_NONE
233 */
234 /*next state *//*event */
235 {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ },
236 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ },
237 {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ },
238 {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ },
239 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ },
240 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ },
241 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ },
242 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ },
243 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ },
244 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ },
245 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ },
246 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ },
247 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ },
248 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ },
249 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ },
250 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ },
251 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ },
252 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ },
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 recieved 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 recieved 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 recieved 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 recieved 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
772 {{IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_CLI */ },
773 {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_SER */ },
774 /*
775 * We have got an INIT from client. From the spec.“Upon receipt of
776 * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with
777 * an INIT ACK using the same parameters it sent in its original
778 * INIT chunk (including its Initiate Tag, unchanged”).
779 */
780 {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ },
781 {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ },
782 /*
783 * INIT_ACK sent by the server, Unexpected INIT ACK, spec says,
784 * “If an INIT ACK is received by an endpoint in any state other
785 * than the COOKIE-WAIT state, the endpoint should discard the
786 * INIT ACK chunk”. Stay in the same state
787 */
788 {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ },
789 {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ },
790 /*
791 * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the
792 * peer and peer shall move to the ESTABISHED. if it doesn't handle
793 * it will send ERROR chunk. So, stay in the same state
794 */
795 {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ },
796 {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ },
797 /*
798 * COOKIE ACK from client, not sure what to do stay in the same state
799 */
800 {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ },
801 {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ },
802 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ },
803 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ },
804 /*
805 * SHUTDOWN sent from the client, move to SHUDDOWN_CLI
806 */
807 {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ },
808 /*
809 * SHUTDOWN sent from the server, move to SHUTDOWN_SER
810 */
811 {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ },
812 /*
813 * client sent SHUDTDOWN_ACK, this should not happen let's close
814 * the connection.
815 */
816 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ },
817 /*
818 * Server resent SHUTDOWN ACK, stay in the same state
819 */
820 {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ },
821 /*
822 * SHUTDOWN COM from client, this what we are expecting, let's close
823 * the connection
824 */
825 {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ },
826 /*
827 * SHUTDOWN COMPLETE from server this should not happen.
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};
854
855/*
856 * Timeout table[state]
857 */
858static int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = {
859 [IP_VS_SCTP_S_NONE] = 2 * HZ,
860 [IP_VS_SCTP_S_INIT_CLI] = 1 * 60 * HZ,
861 [IP_VS_SCTP_S_INIT_SER] = 1 * 60 * HZ,
862 [IP_VS_SCTP_S_INIT_ACK_CLI] = 1 * 60 * HZ,
863 [IP_VS_SCTP_S_INIT_ACK_SER] = 1 * 60 * HZ,
864 [IP_VS_SCTP_S_ECHO_CLI] = 1 * 60 * HZ,
865 [IP_VS_SCTP_S_ECHO_SER] = 1 * 60 * HZ,
866 [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ,
867 [IP_VS_SCTP_S_SHUT_CLI] = 1 * 60 * HZ,
868 [IP_VS_SCTP_S_SHUT_SER] = 1 * 60 * HZ,
869 [IP_VS_SCTP_S_SHUT_ACK_CLI] = 1 * 60 * HZ,
870 [IP_VS_SCTP_S_SHUT_ACK_SER] = 1 * 60 * HZ,
871 [IP_VS_SCTP_S_CLOSED] = 10 * HZ,
872 [IP_VS_SCTP_S_LAST] = 2 * HZ,
873};
874
875static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = {
876 [IP_VS_SCTP_S_NONE] = "NONE",
877 [IP_VS_SCTP_S_INIT_CLI] = "INIT_CLI",
878 [IP_VS_SCTP_S_INIT_SER] = "INIT_SER",
879 [IP_VS_SCTP_S_INIT_ACK_CLI] = "INIT_ACK_CLI",
880 [IP_VS_SCTP_S_INIT_ACK_SER] = "INIT_ACK_SER",
881 [IP_VS_SCTP_S_ECHO_CLI] = "COOKIE_ECHO_CLI",
882 [IP_VS_SCTP_S_ECHO_SER] = "COOKIE_ECHO_SER",
883 [IP_VS_SCTP_S_ESTABLISHED] = "ESTABISHED",
884 [IP_VS_SCTP_S_SHUT_CLI] = "SHUTDOWN_CLI",
885 [IP_VS_SCTP_S_SHUT_SER] = "SHUTDOWN_SER",
886 [IP_VS_SCTP_S_SHUT_ACK_CLI] = "SHUTDOWN_ACK_CLI",
887 [IP_VS_SCTP_S_SHUT_ACK_SER] = "SHUTDOWN_ACK_SER",
888 [IP_VS_SCTP_S_CLOSED] = "CLOSED",
889 [IP_VS_SCTP_S_LAST] = "BUG!"
890};
891
892
893static const char *sctp_state_name(int state)
894{
895 if (state >= IP_VS_SCTP_S_LAST)
896 return "ERR!";
897 if (sctp_state_name_table[state])
898 return sctp_state_name_table[state];
899 return "?";
900}
901
902static void sctp_timeout_change(struct ip_vs_protocol *pp, int flags)
903{
904}
905
906static int
907sctp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
908{
909
910return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_SCTP_S_LAST,
911 sctp_state_name_table, sname, to);
912}
913
914static inline int
915set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
916 int direction, const struct sk_buff *skb)
917{
918 sctp_chunkhdr_t _sctpch, *sch;
919 unsigned char chunk_type;
920 int event, next_state;
921 int ihl;
922
923#ifdef CONFIG_IP_VS_IPV6
924 ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr);
925#else
926 ihl = ip_hdrlen(skb);
927#endif
928
929 sch = skb_header_pointer(skb, ihl + sizeof(sctp_sctphdr_t),
930 sizeof(_sctpch), &_sctpch);
931 if (sch == NULL)
932 return 0;
933
934 chunk_type = sch->type;
935 /*
936 * Section 3: Multiple chunks can be bundled into one SCTP packet
937 * up to the MTU size, except for the INIT, INIT ACK, and
938 * SHUTDOWN COMPLETE chunks. These chunks MUST NOT be bundled with
939 * any other chunk in a packet.
940 *
941 * Section 3.3.7: DATA chunks MUST NOT be bundled with ABORT. Control
942 * chunks (except for INIT, INIT ACK, and SHUTDOWN COMPLETE) MAY be
943 * bundled with an ABORT, but they MUST be placed before the ABORT
944 * in the SCTP packet or they will be ignored by the receiver.
945 */
946 if ((sch->type == SCTP_CID_COOKIE_ECHO) ||
947 (sch->type == SCTP_CID_COOKIE_ACK)) {
948 sch = skb_header_pointer(skb, (ihl + sizeof(sctp_sctphdr_t) +
949 sch->length), sizeof(_sctpch), &_sctpch);
950 if (sch) {
951 if (sch->type == SCTP_CID_ABORT)
952 chunk_type = sch->type;
953 }
954 }
955
956 event = sctp_events[chunk_type];
957
958 /*
959 * If the direction is IP_VS_DIR_OUTPUT, this event is from server
960 */
961 if (direction == IP_VS_DIR_OUTPUT)
962 event++;
963 /*
964 * get next state
965 */
966 next_state = sctp_states_table[cp->state][event].next_state;
967
968 if (next_state != cp->state) {
969 struct ip_vs_dest *dest = cp->dest;
970
971 IP_VS_DBG_BUF(8, "%s %s %s:%d->"
972 "%s:%d state: %s->%s conn->refcnt:%d\n",
973 pp->name,
974 ((direction == IP_VS_DIR_OUTPUT) ?
975 "output " : "input "),
976 IP_VS_DBG_ADDR(cp->af, &cp->daddr),
977 ntohs(cp->dport),
978 IP_VS_DBG_ADDR(cp->af, &cp->caddr),
979 ntohs(cp->cport),
980 sctp_state_name(cp->state),
981 sctp_state_name(next_state),
982 atomic_read(&cp->refcnt));
983 if (dest) {
984 if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
985 (next_state != IP_VS_SCTP_S_ESTABLISHED)) {
986 atomic_dec(&dest->activeconns);
987 atomic_inc(&dest->inactconns);
988 cp->flags |= IP_VS_CONN_F_INACTIVE;
989 } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
990 (next_state == IP_VS_SCTP_S_ESTABLISHED)) {
991 atomic_inc(&dest->activeconns);
992 atomic_dec(&dest->inactconns);
993 cp->flags &= ~IP_VS_CONN_F_INACTIVE;
994 }
995 }
996 }
997
998 cp->timeout = pp->timeout_table[cp->state = next_state];
999
1000 return 1;
1001}
1002
1003static int
1004sctp_state_transition(struct ip_vs_conn *cp, int direction,
1005 const struct sk_buff *skb, struct ip_vs_protocol *pp)
1006{
1007 int ret = 0;
1008
1009 spin_lock(&cp->lock);
1010 ret = set_sctp_state(pp, cp, direction, skb);
1011 spin_unlock(&cp->lock);
1012
1013 return ret;
1014}
1015
1016/*
1017 * Hash table for SCTP application incarnations
1018 */
1019#define SCTP_APP_TAB_BITS 4
1020#define SCTP_APP_TAB_SIZE (1 << SCTP_APP_TAB_BITS)
1021#define SCTP_APP_TAB_MASK (SCTP_APP_TAB_SIZE - 1)
1022
1023static struct list_head sctp_apps[SCTP_APP_TAB_SIZE];
1024static DEFINE_SPINLOCK(sctp_app_lock);
1025
1026static inline __u16 sctp_app_hashkey(__be16 port)
1027{
1028 return (((__force u16)port >> SCTP_APP_TAB_BITS) ^ (__force u16)port)
1029 & SCTP_APP_TAB_MASK;
1030}
1031
1032static int sctp_register_app(struct ip_vs_app *inc)
1033{
1034 struct ip_vs_app *i;
1035 __u16 hash;
1036 __be16 port = inc->port;
1037 int ret = 0;
1038
1039 hash = sctp_app_hashkey(port);
1040
1041 spin_lock_bh(&sctp_app_lock);
1042 list_for_each_entry(i, &sctp_apps[hash], p_list) {
1043 if (i->port == port) {
1044 ret = -EEXIST;
1045 goto out;
1046 }
1047 }
1048 list_add(&inc->p_list, &sctp_apps[hash]);
1049 atomic_inc(&ip_vs_protocol_sctp.appcnt);
1050out:
1051 spin_unlock_bh(&sctp_app_lock);
1052
1053 return ret;
1054}
1055
1056static void sctp_unregister_app(struct ip_vs_app *inc)
1057{
1058 spin_lock_bh(&sctp_app_lock);
1059 atomic_dec(&ip_vs_protocol_sctp.appcnt);
1060 list_del(&inc->p_list);
1061 spin_unlock_bh(&sctp_app_lock);
1062}
1063
1064static int sctp_app_conn_bind(struct ip_vs_conn *cp)
1065{
1066 int hash;
1067 struct ip_vs_app *inc;
1068 int result = 0;
1069
1070 /* Default binding: bind app only for NAT */
1071 if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
1072 return 0;
1073 /* Lookup application incarnations and bind the right one */
1074 hash = sctp_app_hashkey(cp->vport);
1075
1076 spin_lock(&sctp_app_lock);
1077 list_for_each_entry(inc, &sctp_apps[hash], p_list) {
1078 if (inc->port == cp->vport) {
1079 if (unlikely(!ip_vs_app_inc_get(inc)))
1080 break;
1081 spin_unlock(&sctp_app_lock);
1082
1083 IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->"
1084 "%s:%u to app %s on port %u\n",
1085 __func__,
1086 IP_VS_DBG_ADDR(cp->af, &cp->caddr),
1087 ntohs(cp->cport),
1088 IP_VS_DBG_ADDR(cp->af, &cp->vaddr),
1089 ntohs(cp->vport),
1090 inc->name, ntohs(inc->port));
1091 cp->app = inc;
1092 if (inc->init_conn)
1093 result = inc->init_conn(inc, cp);
1094 goto out;
1095 }
1096 }
1097 spin_unlock(&sctp_app_lock);
1098out:
1099 return result;
1100}
1101
1102static void ip_vs_sctp_init(struct ip_vs_protocol *pp)
1103{
1104 IP_VS_INIT_HASH_TABLE(sctp_apps);
1105 pp->timeout_table = sctp_timeouts;
1106}
1107
1108
1109static void ip_vs_sctp_exit(struct ip_vs_protocol *pp)
1110{
1111
1112}
1113
1114struct ip_vs_protocol ip_vs_protocol_sctp = {
1115 .name = "SCTP",
1116 .protocol = IPPROTO_SCTP,
1117 .num_states = IP_VS_SCTP_S_LAST,
1118 .dont_defrag = 0,
1119 .appcnt = ATOMIC_INIT(0),
1120 .init = ip_vs_sctp_init,
1121 .exit = ip_vs_sctp_exit,
1122 .register_app = sctp_register_app,
1123 .unregister_app = sctp_unregister_app,
1124 .conn_schedule = sctp_conn_schedule,
Simon Horman5c0d2372010-08-02 17:12:44 +02001125 .conn_in_get = ip_vs_conn_in_get_proto,
1126 .conn_out_get = ip_vs_conn_out_get_proto,
Venkata Mohan Reddy2906f662010-02-18 12:31:05 +01001127 .snat_handler = sctp_snat_handler,
1128 .dnat_handler = sctp_dnat_handler,
1129 .csum_check = sctp_csum_check,
1130 .state_name = sctp_state_name,
1131 .state_transition = sctp_state_transition,
1132 .app_conn_bind = sctp_app_conn_bind,
1133 .debug_packet = ip_vs_tcpudp_debug_packet,
1134 .timeout_change = sctp_timeout_change,
1135 .set_state_timeout = sctp_set_state_timeout,
1136};