1 #include <linux/kernel.h>
3 #include <linux/sctp.h>
5 #include <net/ip6_checksum.h>
6 #include <linux/netfilter.h>
7 #include <linux/netfilter_ipv4.h>
8 #include <net/sctp/checksum.h>
12 sctp_conn_schedule(int af
, struct sk_buff
*skb
, struct ip_vs_proto_data
*pd
,
13 int *verdict
, struct ip_vs_conn
**cpp
,
14 struct ip_vs_iphdr
*iph
)
17 struct ip_vs_service
*svc
;
18 struct netns_ipvs
*ipvs
;
19 sctp_chunkhdr_t _schunkh
, *sch
;
20 sctp_sctphdr_t
*sh
, _sctph
;
21 __be16 _ports
[2], *ports
= NULL
;
26 if (likely(!ip_vs_iph_icmp(iph
))) {
27 sh
= skb_header_pointer(skb
, iph
->len
, sizeof(_sctph
), &_sctph
);
29 sch
= skb_header_pointer(
30 skb
, iph
->len
+ sizeof(sctp_sctphdr_t
),
31 sizeof(_schunkh
), &_schunkh
);
32 if (sch
&& (sch
->type
== SCTP_CID_INIT
||
33 sysctl_sloppy_sctp(ipvs
)))
37 ports
= skb_header_pointer(
38 skb
, iph
->len
, sizeof(_ports
), &_ports
);
47 if (likely(!ip_vs_iph_inverse(iph
)))
48 svc
= ip_vs_service_find(ipvs
, af
, skb
->mark
, iph
->protocol
,
49 &iph
->daddr
, ports
[1]);
51 svc
= ip_vs_service_find(ipvs
, af
, skb
->mark
, iph
->protocol
,
52 &iph
->saddr
, ports
[0]);
56 if (ip_vs_todrop(ipvs
)) {
58 * It seems that we are very loaded.
59 * We have to drop this packet :(
66 * Let the virtual server select a real server for the
67 * incoming connection, and create a connection entry.
69 *cpp
= ip_vs_schedule(svc
, skb
, pd
, &ignored
, iph
);
70 if (!*cpp
&& ignored
<= 0) {
72 *verdict
= ip_vs_leave(svc
, skb
, pd
, iph
);
84 static void sctp_nat_csum(struct sk_buff
*skb
, sctp_sctphdr_t
*sctph
,
85 unsigned int sctphoff
)
87 sctph
->checksum
= sctp_compute_cksum(skb
, sctphoff
);
88 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
92 sctp_snat_handler(struct sk_buff
*skb
, struct ip_vs_protocol
*pp
,
93 struct ip_vs_conn
*cp
, struct ip_vs_iphdr
*iph
)
95 sctp_sctphdr_t
*sctph
;
96 unsigned int sctphoff
= iph
->len
;
97 bool payload_csum
= false;
99 #ifdef CONFIG_IP_VS_IPV6
100 if (cp
->af
== AF_INET6
&& iph
->fragoffs
)
104 /* csum_check requires unshared skb */
105 if (!skb_make_writable(skb
, sctphoff
+ sizeof(*sctph
)))
108 if (unlikely(cp
->app
!= NULL
)) {
111 /* Some checks before mangling */
112 if (pp
->csum_check
&& !pp
->csum_check(cp
->af
, skb
, pp
))
115 /* Call application helper if needed */
116 ret
= ip_vs_app_pkt_out(cp
, skb
);
119 /* ret=2: csum update is needed after payload mangling */
124 sctph
= (void *) skb_network_header(skb
) + sctphoff
;
126 /* Only update csum if we really have to */
127 if (sctph
->source
!= cp
->vport
|| payload_csum
||
128 skb
->ip_summed
== CHECKSUM_PARTIAL
) {
129 sctph
->source
= cp
->vport
;
130 sctp_nat_csum(skb
, sctph
, sctphoff
);
132 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
139 sctp_dnat_handler(struct sk_buff
*skb
, struct ip_vs_protocol
*pp
,
140 struct ip_vs_conn
*cp
, struct ip_vs_iphdr
*iph
)
142 sctp_sctphdr_t
*sctph
;
143 unsigned int sctphoff
= iph
->len
;
144 bool payload_csum
= false;
146 #ifdef CONFIG_IP_VS_IPV6
147 if (cp
->af
== AF_INET6
&& iph
->fragoffs
)
151 /* csum_check requires unshared skb */
152 if (!skb_make_writable(skb
, sctphoff
+ sizeof(*sctph
)))
155 if (unlikely(cp
->app
!= NULL
)) {
158 /* Some checks before mangling */
159 if (pp
->csum_check
&& !pp
->csum_check(cp
->af
, skb
, pp
))
162 /* Call application helper if needed */
163 ret
= ip_vs_app_pkt_in(cp
, skb
);
166 /* ret=2: csum update is needed after payload mangling */
171 sctph
= (void *) skb_network_header(skb
) + sctphoff
;
173 /* Only update csum if we really have to */
174 if (sctph
->dest
!= cp
->dport
|| payload_csum
||
175 (skb
->ip_summed
== CHECKSUM_PARTIAL
&&
176 !(skb_dst(skb
)->dev
->features
& NETIF_F_SCTP_CSUM
))) {
177 sctph
->dest
= cp
->dport
;
178 sctp_nat_csum(skb
, sctph
, sctphoff
);
179 } else if (skb
->ip_summed
!= CHECKSUM_PARTIAL
) {
180 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
187 sctp_csum_check(int af
, struct sk_buff
*skb
, struct ip_vs_protocol
*pp
)
189 unsigned int sctphoff
;
190 struct sctphdr
*sh
, _sctph
;
193 #ifdef CONFIG_IP_VS_IPV6
195 sctphoff
= sizeof(struct ipv6hdr
);
198 sctphoff
= ip_hdrlen(skb
);
200 sh
= skb_header_pointer(skb
, sctphoff
, sizeof(_sctph
), &_sctph
);
205 val
= sctp_compute_cksum(skb
, sctphoff
);
208 /* CRC failure, dump it. */
209 IP_VS_DBG_RL_PKT(0, af
, pp
, skb
, 0,
210 "Failed checksum for");
216 enum ipvs_sctp_event_t
{
217 IP_VS_SCTP_DATA
= 0, /* DATA, SACK, HEARTBEATs */
220 IP_VS_SCTP_COOKIE_ECHO
,
221 IP_VS_SCTP_COOKIE_ACK
,
223 IP_VS_SCTP_SHUTDOWN_ACK
,
224 IP_VS_SCTP_SHUTDOWN_COMPLETE
,
227 IP_VS_SCTP_EVENT_LAST
230 /* RFC 2960, 3.2 Chunk Field Descriptions */
231 static __u8 sctp_events
[] = {
232 [SCTP_CID_DATA
] = IP_VS_SCTP_DATA
,
233 [SCTP_CID_INIT
] = IP_VS_SCTP_INIT
,
234 [SCTP_CID_INIT_ACK
] = IP_VS_SCTP_INIT_ACK
,
235 [SCTP_CID_SACK
] = IP_VS_SCTP_DATA
,
236 [SCTP_CID_HEARTBEAT
] = IP_VS_SCTP_DATA
,
237 [SCTP_CID_HEARTBEAT_ACK
] = IP_VS_SCTP_DATA
,
238 [SCTP_CID_ABORT
] = IP_VS_SCTP_ABORT
,
239 [SCTP_CID_SHUTDOWN
] = IP_VS_SCTP_SHUTDOWN
,
240 [SCTP_CID_SHUTDOWN_ACK
] = IP_VS_SCTP_SHUTDOWN_ACK
,
241 [SCTP_CID_ERROR
] = IP_VS_SCTP_ERROR
,
242 [SCTP_CID_COOKIE_ECHO
] = IP_VS_SCTP_COOKIE_ECHO
,
243 [SCTP_CID_COOKIE_ACK
] = IP_VS_SCTP_COOKIE_ACK
,
244 [SCTP_CID_ECN_ECNE
] = IP_VS_SCTP_DATA
,
245 [SCTP_CID_ECN_CWR
] = IP_VS_SCTP_DATA
,
246 [SCTP_CID_SHUTDOWN_COMPLETE
] = IP_VS_SCTP_SHUTDOWN_COMPLETE
,
250 * See RFC 2960, 4. SCTP Association State Diagram
252 * New states (not in diagram):
253 * - INIT1 state: use shorter timeout for dropped INIT packets
254 * - REJECTED state: use shorter timeout if INIT is rejected with ABORT
255 * - INIT, COOKIE_SENT, COOKIE_REPLIED, COOKIE states: for better debugging
257 * The states are as seen in real server. In the diagram, INIT1, INIT,
258 * COOKIE_SENT and COOKIE_REPLIED processing happens in CLOSED state.
260 * States as per packets from client (C) and server (S):
262 * Setup of client connection:
263 * IP_VS_SCTP_S_INIT1: First C:INIT sent, wait for S:INIT-ACK
264 * IP_VS_SCTP_S_INIT: Next C:INIT sent, wait for S:INIT-ACK
265 * IP_VS_SCTP_S_COOKIE_SENT: S:INIT-ACK sent, wait for C:COOKIE-ECHO
266 * IP_VS_SCTP_S_COOKIE_REPLIED: C:COOKIE-ECHO sent, wait for S:COOKIE-ACK
268 * Setup of server connection:
269 * IP_VS_SCTP_S_COOKIE_WAIT: S:INIT sent, wait for C:INIT-ACK
270 * IP_VS_SCTP_S_COOKIE: C:INIT-ACK sent, wait for S:COOKIE-ECHO
271 * IP_VS_SCTP_S_COOKIE_ECHOED: S:COOKIE-ECHO sent, wait for C:COOKIE-ACK
274 #define sNO IP_VS_SCTP_S_NONE
275 #define sI1 IP_VS_SCTP_S_INIT1
276 #define sIN IP_VS_SCTP_S_INIT
277 #define sCS IP_VS_SCTP_S_COOKIE_SENT
278 #define sCR IP_VS_SCTP_S_COOKIE_REPLIED
279 #define sCW IP_VS_SCTP_S_COOKIE_WAIT
280 #define sCO IP_VS_SCTP_S_COOKIE
281 #define sCE IP_VS_SCTP_S_COOKIE_ECHOED
282 #define sES IP_VS_SCTP_S_ESTABLISHED
283 #define sSS IP_VS_SCTP_S_SHUTDOWN_SENT
284 #define sSR IP_VS_SCTP_S_SHUTDOWN_RECEIVED
285 #define sSA IP_VS_SCTP_S_SHUTDOWN_ACK_SENT
286 #define sRJ IP_VS_SCTP_S_REJECTED
287 #define sCL IP_VS_SCTP_S_CLOSED
289 static const __u8 sctp_states
290 [IP_VS_DIR_LAST
][IP_VS_SCTP_EVENT_LAST
][IP_VS_SCTP_S_LAST
] = {
292 /* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/
293 /* d */{sES
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
294 /* i */{sI1
, sIN
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sIN
, sIN
},
295 /* i_a */{sCW
, sCW
, sCW
, sCS
, sCR
, sCO
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
296 /* c_e */{sCR
, sIN
, sIN
, sCR
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
297 /* c_a */{sES
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sES
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
298 /* s */{sSR
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sSR
, sSS
, sSR
, sSA
, sRJ
, sCL
},
299 /* s_a */{sCL
, sIN
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sCL
, sSR
, sCL
, sRJ
, sCL
},
300 /* s_c */{sCL
, sCL
, sCL
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sCL
, sRJ
, sCL
},
301 /* err */{sCL
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCL
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
302 /* ab */{sCL
, sCL
, sCL
, sCL
, sCL
, sRJ
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
},
305 /* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/
306 /* d */{sES
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
307 /* i */{sCW
, sCW
, sCW
, sCW
, sCW
, sCW
, sCW
, sCW
, sES
, sCW
, sCW
, sCW
, sCW
, sCW
},
308 /* i_a */{sCS
, sCS
, sCS
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
309 /* c_e */{sCE
, sCE
, sCE
, sCE
, sCE
, sCE
, sCE
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
310 /* c_a */{sES
, sES
, sES
, sES
, sES
, sES
, sES
, sES
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
311 /* s */{sSS
, sSS
, sSS
, sSS
, sSS
, sSS
, sSS
, sSS
, sSS
, sSS
, sSR
, sSA
, sRJ
, sCL
},
312 /* s_a */{sSA
, sSA
, sSA
, sSA
, sSA
, sCW
, sCO
, sCE
, sES
, sSA
, sSA
, sSA
, sRJ
, sCL
},
313 /* s_c */{sCL
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
314 /* err */{sCL
, sCL
, sCL
, sCL
, sCL
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
315 /* ab */{sCL
, sRJ
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
},
318 /* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/
319 /* d */{sES
, sI1
, sIN
, sCS
, sCR
, sES
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
320 /* i */{sI1
, sIN
, sIN
, sIN
, sIN
, sIN
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sIN
, sIN
},
321 /* i_a */{sCE
, sCE
, sCE
, sCE
, sCE
, sCE
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
322 /* c_e */{sES
, sES
, sES
, sES
, sES
, sES
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
323 /* c_a */{sES
, sI1
, sIN
, sES
, sES
, sCW
, sES
, sES
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
324 /* s */{sSR
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sSR
, sSS
, sSR
, sSA
, sRJ
, sCL
},
325 /* s_a */{sCL
, sIN
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sCL
, sCL
, sSR
, sCL
, sRJ
, sCL
},
326 /* s_c */{sCL
, sCL
, sCL
, sCL
, sCL
, sCW
, sCO
, sCE
, sES
, sSS
, sCL
, sCL
, sRJ
, sCL
},
327 /* err */{sCL
, sI1
, sIN
, sCS
, sCR
, sCW
, sCO
, sCE
, sES
, sSS
, sSR
, sSA
, sRJ
, sCL
},
328 /* ab */{sCL
, sCL
, sCL
, sCL
, sCL
, sRJ
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
, sCL
},
332 #define IP_VS_SCTP_MAX_RTO ((60 + 1) * HZ)
334 /* Timeout table[state] */
335 static const int sctp_timeouts
[IP_VS_SCTP_S_LAST
+ 1] = {
336 [IP_VS_SCTP_S_NONE
] = 2 * HZ
,
337 [IP_VS_SCTP_S_INIT1
] = (0 + 3 + 1) * HZ
,
338 [IP_VS_SCTP_S_INIT
] = IP_VS_SCTP_MAX_RTO
,
339 [IP_VS_SCTP_S_COOKIE_SENT
] = IP_VS_SCTP_MAX_RTO
,
340 [IP_VS_SCTP_S_COOKIE_REPLIED
] = IP_VS_SCTP_MAX_RTO
,
341 [IP_VS_SCTP_S_COOKIE_WAIT
] = IP_VS_SCTP_MAX_RTO
,
342 [IP_VS_SCTP_S_COOKIE
] = IP_VS_SCTP_MAX_RTO
,
343 [IP_VS_SCTP_S_COOKIE_ECHOED
] = IP_VS_SCTP_MAX_RTO
,
344 [IP_VS_SCTP_S_ESTABLISHED
] = 15 * 60 * HZ
,
345 [IP_VS_SCTP_S_SHUTDOWN_SENT
] = IP_VS_SCTP_MAX_RTO
,
346 [IP_VS_SCTP_S_SHUTDOWN_RECEIVED
] = IP_VS_SCTP_MAX_RTO
,
347 [IP_VS_SCTP_S_SHUTDOWN_ACK_SENT
] = IP_VS_SCTP_MAX_RTO
,
348 [IP_VS_SCTP_S_REJECTED
] = (0 + 3 + 1) * HZ
,
349 [IP_VS_SCTP_S_CLOSED
] = IP_VS_SCTP_MAX_RTO
,
350 [IP_VS_SCTP_S_LAST
] = 2 * HZ
,
353 static const char *sctp_state_name_table
[IP_VS_SCTP_S_LAST
+ 1] = {
354 [IP_VS_SCTP_S_NONE
] = "NONE",
355 [IP_VS_SCTP_S_INIT1
] = "INIT1",
356 [IP_VS_SCTP_S_INIT
] = "INIT",
357 [IP_VS_SCTP_S_COOKIE_SENT
] = "C-SENT",
358 [IP_VS_SCTP_S_COOKIE_REPLIED
] = "C-REPLIED",
359 [IP_VS_SCTP_S_COOKIE_WAIT
] = "C-WAIT",
360 [IP_VS_SCTP_S_COOKIE
] = "COOKIE",
361 [IP_VS_SCTP_S_COOKIE_ECHOED
] = "C-ECHOED",
362 [IP_VS_SCTP_S_ESTABLISHED
] = "ESTABLISHED",
363 [IP_VS_SCTP_S_SHUTDOWN_SENT
] = "S-SENT",
364 [IP_VS_SCTP_S_SHUTDOWN_RECEIVED
] = "S-RECEIVED",
365 [IP_VS_SCTP_S_SHUTDOWN_ACK_SENT
] = "S-ACK-SENT",
366 [IP_VS_SCTP_S_REJECTED
] = "REJECTED",
367 [IP_VS_SCTP_S_CLOSED
] = "CLOSED",
368 [IP_VS_SCTP_S_LAST
] = "BUG!",
372 static const char *sctp_state_name(int state
)
374 if (state
>= IP_VS_SCTP_S_LAST
)
376 if (sctp_state_name_table
[state
])
377 return sctp_state_name_table
[state
];
382 set_sctp_state(struct ip_vs_proto_data
*pd
, struct ip_vs_conn
*cp
,
383 int direction
, const struct sk_buff
*skb
)
385 sctp_chunkhdr_t _sctpch
, *sch
;
386 unsigned char chunk_type
;
387 int event
, next_state
;
390 #ifdef CONFIG_IP_VS_IPV6
391 ihl
= cp
->af
== AF_INET
? ip_hdrlen(skb
) : sizeof(struct ipv6hdr
);
393 ihl
= ip_hdrlen(skb
);
396 cofs
= ihl
+ sizeof(sctp_sctphdr_t
);
397 sch
= skb_header_pointer(skb
, cofs
, sizeof(_sctpch
), &_sctpch
);
401 chunk_type
= sch
->type
;
403 * Section 3: Multiple chunks can be bundled into one SCTP packet
404 * up to the MTU size, except for the INIT, INIT ACK, and
405 * SHUTDOWN COMPLETE chunks. These chunks MUST NOT be bundled with
406 * any other chunk in a packet.
408 * Section 3.3.7: DATA chunks MUST NOT be bundled with ABORT. Control
409 * chunks (except for INIT, INIT ACK, and SHUTDOWN COMPLETE) MAY be
410 * bundled with an ABORT, but they MUST be placed before the ABORT
411 * in the SCTP packet or they will be ignored by the receiver.
413 if ((sch
->type
== SCTP_CID_COOKIE_ECHO
) ||
414 (sch
->type
== SCTP_CID_COOKIE_ACK
)) {
415 int clen
= ntohs(sch
->length
);
417 if (clen
>= sizeof(sctp_chunkhdr_t
)) {
418 sch
= skb_header_pointer(skb
, cofs
+ ALIGN(clen
, 4),
419 sizeof(_sctpch
), &_sctpch
);
420 if (sch
&& sch
->type
== SCTP_CID_ABORT
)
421 chunk_type
= sch
->type
;
425 event
= (chunk_type
< sizeof(sctp_events
)) ?
426 sctp_events
[chunk_type
] : IP_VS_SCTP_DATA
;
428 /* Update direction to INPUT_ONLY if necessary
429 * or delete NO_OUTPUT flag if output packet detected
431 if (cp
->flags
& IP_VS_CONN_F_NOOUTPUT
) {
432 if (direction
== IP_VS_DIR_OUTPUT
)
433 cp
->flags
&= ~IP_VS_CONN_F_NOOUTPUT
;
435 direction
= IP_VS_DIR_INPUT_ONLY
;
438 next_state
= sctp_states
[direction
][event
][cp
->state
];
440 if (next_state
!= cp
->state
) {
441 struct ip_vs_dest
*dest
= cp
->dest
;
443 IP_VS_DBG_BUF(8, "%s %s %s:%d->"
444 "%s:%d state: %s->%s conn->refcnt:%d\n",
446 ((direction
== IP_VS_DIR_OUTPUT
) ?
447 "output " : "input "),
448 IP_VS_DBG_ADDR(cp
->daf
, &cp
->daddr
),
450 IP_VS_DBG_ADDR(cp
->af
, &cp
->caddr
),
452 sctp_state_name(cp
->state
),
453 sctp_state_name(next_state
),
454 atomic_read(&cp
->refcnt
));
456 if (!(cp
->flags
& IP_VS_CONN_F_INACTIVE
) &&
457 (next_state
!= IP_VS_SCTP_S_ESTABLISHED
)) {
458 atomic_dec(&dest
->activeconns
);
459 atomic_inc(&dest
->inactconns
);
460 cp
->flags
|= IP_VS_CONN_F_INACTIVE
;
461 } else if ((cp
->flags
& IP_VS_CONN_F_INACTIVE
) &&
462 (next_state
== IP_VS_SCTP_S_ESTABLISHED
)) {
463 atomic_inc(&dest
->activeconns
);
464 atomic_dec(&dest
->inactconns
);
465 cp
->flags
&= ~IP_VS_CONN_F_INACTIVE
;
470 cp
->timeout
= pd
->timeout_table
[cp
->state
= next_state
];
471 else /* What to do ? */
472 cp
->timeout
= sctp_timeouts
[cp
->state
= next_state
];
476 sctp_state_transition(struct ip_vs_conn
*cp
, int direction
,
477 const struct sk_buff
*skb
, struct ip_vs_proto_data
*pd
)
479 spin_lock_bh(&cp
->lock
);
480 set_sctp_state(pd
, cp
, direction
, skb
);
481 spin_unlock_bh(&cp
->lock
);
484 static inline __u16
sctp_app_hashkey(__be16 port
)
486 return (((__force u16
)port
>> SCTP_APP_TAB_BITS
) ^ (__force u16
)port
)
490 static int sctp_register_app(struct net
*net
, struct ip_vs_app
*inc
)
494 __be16 port
= inc
->port
;
496 struct netns_ipvs
*ipvs
= net_ipvs(net
);
497 struct ip_vs_proto_data
*pd
= ip_vs_proto_data_get(ipvs
, IPPROTO_SCTP
);
499 hash
= sctp_app_hashkey(port
);
501 list_for_each_entry(i
, &ipvs
->sctp_apps
[hash
], p_list
) {
502 if (i
->port
== port
) {
507 list_add_rcu(&inc
->p_list
, &ipvs
->sctp_apps
[hash
]);
508 atomic_inc(&pd
->appcnt
);
514 static void sctp_unregister_app(struct net
*net
, struct ip_vs_app
*inc
)
516 struct ip_vs_proto_data
*pd
= ip_vs_proto_data_get(net_ipvs(net
), IPPROTO_SCTP
);
518 atomic_dec(&pd
->appcnt
);
519 list_del_rcu(&inc
->p_list
);
522 static int sctp_app_conn_bind(struct ip_vs_conn
*cp
)
524 struct netns_ipvs
*ipvs
= cp
->ipvs
;
526 struct ip_vs_app
*inc
;
529 /* Default binding: bind app only for NAT */
530 if (IP_VS_FWD_METHOD(cp
) != IP_VS_CONN_F_MASQ
)
532 /* Lookup application incarnations and bind the right one */
533 hash
= sctp_app_hashkey(cp
->vport
);
536 list_for_each_entry_rcu(inc
, &ipvs
->sctp_apps
[hash
], p_list
) {
537 if (inc
->port
== cp
->vport
) {
538 if (unlikely(!ip_vs_app_inc_get(inc
)))
542 IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->"
543 "%s:%u to app %s on port %u\n",
545 IP_VS_DBG_ADDR(cp
->af
, &cp
->caddr
),
547 IP_VS_DBG_ADDR(cp
->af
, &cp
->vaddr
),
549 inc
->name
, ntohs(inc
->port
));
552 result
= inc
->init_conn(inc
, cp
);
561 /* ---------------------------------------------
562 * timeouts is netns related now.
563 * ---------------------------------------------
565 static int __ip_vs_sctp_init(struct net
*net
, struct ip_vs_proto_data
*pd
)
567 struct netns_ipvs
*ipvs
= net_ipvs(net
);
569 ip_vs_init_hash_table(ipvs
->sctp_apps
, SCTP_APP_TAB_SIZE
);
570 pd
->timeout_table
= ip_vs_create_timeout_table((int *)sctp_timeouts
,
571 sizeof(sctp_timeouts
));
572 if (!pd
->timeout_table
)
577 static void __ip_vs_sctp_exit(struct net
*net
, struct ip_vs_proto_data
*pd
)
579 kfree(pd
->timeout_table
);
582 struct ip_vs_protocol ip_vs_protocol_sctp
= {
584 .protocol
= IPPROTO_SCTP
,
585 .num_states
= IP_VS_SCTP_S_LAST
,
589 .init_netns
= __ip_vs_sctp_init
,
590 .exit_netns
= __ip_vs_sctp_exit
,
591 .register_app
= sctp_register_app
,
592 .unregister_app
= sctp_unregister_app
,
593 .conn_schedule
= sctp_conn_schedule
,
594 .conn_in_get
= ip_vs_conn_in_get_proto
,
595 .conn_out_get
= ip_vs_conn_out_get_proto
,
596 .snat_handler
= sctp_snat_handler
,
597 .dnat_handler
= sctp_dnat_handler
,
598 .csum_check
= sctp_csum_check
,
599 .state_name
= sctp_state_name
,
600 .state_transition
= sctp_state_transition
,
601 .app_conn_bind
= sctp_app_conn_bind
,
602 .debug_packet
= ip_vs_tcpudp_debug_packet
,
603 .timeout_change
= NULL
,