xref: /linux/net/netfilter/ipvs/ip_vs_proto_sctp.c (revision fab183d632628381b466a41479489541ac0e29a0)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/ip.h>
4 #include <linux/sctp.h>
5 #include <net/ip.h>
6 #include <net/ip6_checksum.h>
7 #include <linux/netfilter.h>
8 #include <linux/netfilter_ipv4.h>
9 #include <net/sctp/checksum.h>
10 #include <net/ip_vs.h>
11 
12 static int
13 sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
14 		struct ip_vs_iphdr *iph);
15 
16 static int
sctp_conn_schedule(struct netns_ipvs * ipvs,int af,struct sk_buff * skb,struct ip_vs_proto_data * pd,int * verdict,struct ip_vs_conn ** cpp,struct ip_vs_iphdr * iph)17 sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
18 		   struct ip_vs_proto_data *pd,
19 		   int *verdict, struct ip_vs_conn **cpp,
20 		   struct ip_vs_iphdr *iph)
21 {
22 	struct ip_vs_service *svc;
23 	struct sctp_chunkhdr _schunkh, *sch;
24 	struct sctphdr *sh, _sctph;
25 	__be16 _ports[2], *ports = NULL;
26 
27 	if (likely(!ip_vs_iph_icmp(iph))) {
28 		sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
29 		if (sh) {
30 			sch = skb_header_pointer(skb, iph->len + sizeof(_sctph),
31 						 sizeof(_schunkh), &_schunkh);
32 			if (sch) {
33 				if (sch->type == SCTP_CID_ABORT ||
34 				    !(sysctl_sloppy_sctp(ipvs) ||
35 				      sch->type == SCTP_CID_INIT))
36 					return 1;
37 				ports = &sh->source;
38 			}
39 		}
40 	} else {
41 		ports = skb_header_pointer(
42 			skb, iph->len, sizeof(_ports), &_ports);
43 	}
44 
45 	if (!ports) {
46 		*verdict = NF_DROP;
47 		return 0;
48 	}
49 
50 	if (likely(!ip_vs_iph_inverse(iph)))
51 		svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
52 					 &iph->daddr, ports[1]);
53 	else
54 		svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
55 					 &iph->saddr, ports[0]);
56 	if (svc) {
57 		int ignored;
58 
59 		if (ip_vs_todrop(ipvs)) {
60 			/*
61 			 * It seems that we are very loaded.
62 			 * We have to drop this packet :(
63 			 */
64 			*verdict = NF_DROP;
65 			return 0;
66 		}
67 		/*
68 		 * Let the virtual server select a real server for the
69 		 * incoming connection, and create a connection entry.
70 		 */
71 		*cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
72 		if (!*cpp && ignored <= 0) {
73 			if (!ignored)
74 				*verdict = ip_vs_leave(svc, skb, pd, iph);
75 			else
76 				*verdict = NF_DROP;
77 			return 0;
78 		}
79 	}
80 	/* NF_ACCEPT */
81 	return 1;
82 }
83 
sctp_nat_csum(struct sk_buff * skb,struct sctphdr * sctph,unsigned int sctphoff)84 static void sctp_nat_csum(struct sk_buff *skb, struct sctphdr *sctph,
85 			  unsigned int sctphoff)
86 {
87 	sctph->checksum = sctp_compute_cksum(skb, sctphoff);
88 	skb->ip_summed = CHECKSUM_UNNECESSARY;
89 }
90 
91 static int
sctp_snat_handler(struct sk_buff * skb,struct ip_vs_protocol * pp,struct ip_vs_conn * cp,struct ip_vs_iphdr * iph)92 sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
93 		  struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
94 {
95 	struct sctphdr *sctph;
96 	unsigned int sctphoff = iph->len;
97 	bool payload_csum = false;
98 
99 #ifdef CONFIG_IP_VS_IPV6
100 	if (cp->af == AF_INET6 && iph->fragoffs)
101 		return 1;
102 #endif
103 
104 	/* csum_check requires unshared skb */
105 	if (skb_ensure_writable(skb, sctphoff + sizeof(*sctph)))
106 		return 0;
107 
108 	if (unlikely(cp->app != NULL)) {
109 		int ret;
110 
111 		/* Some checks before mangling */
112 		if (!sctp_csum_check(cp->af, skb, pp, iph))
113 			return 0;
114 
115 		/* Call application helper if needed */
116 		ret = ip_vs_app_pkt_out(cp, skb, iph);
117 		if (ret == 0)
118 			return 0;
119 		/* ret=2: csum update is needed after payload mangling */
120 		if (ret == 2)
121 			payload_csum = true;
122 	}
123 
124 	sctph = (void *)skb->data + sctphoff;
125 
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 		if (!skb_is_gso(skb))
131 			sctp_nat_csum(skb, sctph, sctphoff);
132 	} else {
133 		skb->ip_summed = CHECKSUM_UNNECESSARY;
134 	}
135 
136 	return 1;
137 }
138 
139 static int
sctp_dnat_handler(struct sk_buff * skb,struct ip_vs_protocol * pp,struct ip_vs_conn * cp,struct ip_vs_iphdr * iph)140 sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
141 		  struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
142 {
143 	struct sctphdr *sctph;
144 	unsigned int sctphoff = iph->len;
145 	bool payload_csum = false;
146 
147 #ifdef CONFIG_IP_VS_IPV6
148 	if (cp->af == AF_INET6 && iph->fragoffs)
149 		return 1;
150 #endif
151 
152 	/* csum_check requires unshared skb */
153 	if (skb_ensure_writable(skb, sctphoff + sizeof(*sctph)))
154 		return 0;
155 
156 	if (unlikely(cp->app != NULL)) {
157 		int ret;
158 
159 		/* Some checks before mangling */
160 		if (!sctp_csum_check(cp->af, skb, pp, iph))
161 			return 0;
162 
163 		/* Call application helper if needed */
164 		ret = ip_vs_app_pkt_in(cp, skb, iph);
165 		if (ret == 0)
166 			return 0;
167 		/* ret=2: csum update is needed after payload mangling */
168 		if (ret == 2)
169 			payload_csum = true;
170 	}
171 
172 	sctph = (void *)skb->data + sctphoff;
173 
174 	/* Only update csum if we really have to */
175 	if (sctph->dest != cp->dport || payload_csum ||
176 	    (skb->ip_summed == CHECKSUM_PARTIAL &&
177 	     !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) {
178 		sctph->dest = cp->dport;
179 		if (!skb_is_gso(skb))
180 			sctp_nat_csum(skb, sctph, sctphoff);
181 	} else if (skb->ip_summed != CHECKSUM_PARTIAL) {
182 		skb->ip_summed = CHECKSUM_UNNECESSARY;
183 	}
184 
185 	return 1;
186 }
187 
188 static int
sctp_csum_check(int af,struct sk_buff * skb,struct ip_vs_protocol * pp,struct ip_vs_iphdr * iph)189 sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
190 		struct ip_vs_iphdr *iph)
191 {
192 	unsigned int sctphoff = iph->len;
193 	struct sctphdr *sh;
194 	__le32 cmp, val;
195 
196 	if (!ip_vs_checksum_needed(skb))
197 		return 1;
198 	sh = (struct sctphdr *)(skb->data + sctphoff);
199 	cmp = sh->checksum;
200 	val = sctp_compute_cksum(skb, sctphoff);
201 
202 	if (val != cmp) {
203 		/* CRC failure, dump it. */
204 		IP_VS_DBG_RL_PKT(0, af, pp, skb, iph->off,
205 				 "Failed checksum for");
206 		return 0;
207 	}
208 	return 1;
209 }
210 
211 enum ipvs_sctp_event_t {
212 	IP_VS_SCTP_DATA = 0,		/* DATA, SACK, HEARTBEATs */
213 	IP_VS_SCTP_INIT,
214 	IP_VS_SCTP_INIT_ACK,
215 	IP_VS_SCTP_COOKIE_ECHO,
216 	IP_VS_SCTP_COOKIE_ACK,
217 	IP_VS_SCTP_SHUTDOWN,
218 	IP_VS_SCTP_SHUTDOWN_ACK,
219 	IP_VS_SCTP_SHUTDOWN_COMPLETE,
220 	IP_VS_SCTP_ERROR,
221 	IP_VS_SCTP_ABORT,
222 	IP_VS_SCTP_EVENT_LAST
223 };
224 
225 /* RFC 2960, 3.2 Chunk Field Descriptions */
226 static __u8 sctp_events[] = {
227 	[SCTP_CID_DATA]			= IP_VS_SCTP_DATA,
228 	[SCTP_CID_INIT]			= IP_VS_SCTP_INIT,
229 	[SCTP_CID_INIT_ACK]		= IP_VS_SCTP_INIT_ACK,
230 	[SCTP_CID_SACK]			= IP_VS_SCTP_DATA,
231 	[SCTP_CID_HEARTBEAT]		= IP_VS_SCTP_DATA,
232 	[SCTP_CID_HEARTBEAT_ACK]	= IP_VS_SCTP_DATA,
233 	[SCTP_CID_ABORT]		= IP_VS_SCTP_ABORT,
234 	[SCTP_CID_SHUTDOWN]		= IP_VS_SCTP_SHUTDOWN,
235 	[SCTP_CID_SHUTDOWN_ACK]		= IP_VS_SCTP_SHUTDOWN_ACK,
236 	[SCTP_CID_ERROR]		= IP_VS_SCTP_ERROR,
237 	[SCTP_CID_COOKIE_ECHO]		= IP_VS_SCTP_COOKIE_ECHO,
238 	[SCTP_CID_COOKIE_ACK]		= IP_VS_SCTP_COOKIE_ACK,
239 	[SCTP_CID_ECN_ECNE]		= IP_VS_SCTP_DATA,
240 	[SCTP_CID_ECN_CWR]		= IP_VS_SCTP_DATA,
241 	[SCTP_CID_SHUTDOWN_COMPLETE]	= IP_VS_SCTP_SHUTDOWN_COMPLETE,
242 };
243 
244 /* SCTP States:
245  * See RFC 2960, 4. SCTP Association State Diagram
246  *
247  * New states (not in diagram):
248  * - INIT1 state: use shorter timeout for dropped INIT packets
249  * - REJECTED state: use shorter timeout if INIT is rejected with ABORT
250  * - INIT, COOKIE_SENT, COOKIE_REPLIED, COOKIE states: for better debugging
251  *
252  * The states are as seen in real server. In the diagram, INIT1, INIT,
253  * COOKIE_SENT and COOKIE_REPLIED processing happens in CLOSED state.
254  *
255  * States as per packets from client (C) and server (S):
256  *
257  * Setup of client connection:
258  * IP_VS_SCTP_S_INIT1: First C:INIT sent, wait for S:INIT-ACK
259  * IP_VS_SCTP_S_INIT: Next C:INIT sent, wait for S:INIT-ACK
260  * IP_VS_SCTP_S_COOKIE_SENT: S:INIT-ACK sent, wait for C:COOKIE-ECHO
261  * IP_VS_SCTP_S_COOKIE_REPLIED: C:COOKIE-ECHO sent, wait for S:COOKIE-ACK
262  *
263  * Setup of server connection:
264  * IP_VS_SCTP_S_COOKIE_WAIT: S:INIT sent, wait for C:INIT-ACK
265  * IP_VS_SCTP_S_COOKIE: C:INIT-ACK sent, wait for S:COOKIE-ECHO
266  * IP_VS_SCTP_S_COOKIE_ECHOED: S:COOKIE-ECHO sent, wait for C:COOKIE-ACK
267  */
268 
269 #define sNO IP_VS_SCTP_S_NONE
270 #define sI1 IP_VS_SCTP_S_INIT1
271 #define sIN IP_VS_SCTP_S_INIT
272 #define sCS IP_VS_SCTP_S_COOKIE_SENT
273 #define sCR IP_VS_SCTP_S_COOKIE_REPLIED
274 #define sCW IP_VS_SCTP_S_COOKIE_WAIT
275 #define sCO IP_VS_SCTP_S_COOKIE
276 #define sCE IP_VS_SCTP_S_COOKIE_ECHOED
277 #define sES IP_VS_SCTP_S_ESTABLISHED
278 #define sSS IP_VS_SCTP_S_SHUTDOWN_SENT
279 #define sSR IP_VS_SCTP_S_SHUTDOWN_RECEIVED
280 #define sSA IP_VS_SCTP_S_SHUTDOWN_ACK_SENT
281 #define sRJ IP_VS_SCTP_S_REJECTED
282 #define sCL IP_VS_SCTP_S_CLOSED
283 
284 static const __u8 sctp_states
285 	[IP_VS_DIR_LAST][IP_VS_SCTP_EVENT_LAST][IP_VS_SCTP_S_LAST] = {
286 	{ /* INPUT */
287 /*        sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/
288 /* d   */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
289 /* i   */{sI1, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sIN, sIN},
290 /* i_a */{sCW, sCW, sCW, sCS, sCR, sCO, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
291 /* c_e */{sCR, sIN, sIN, sCR, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
292 /* c_a */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sES, sES, sSS, sSR, sSA, sRJ, sCL},
293 /* s   */{sSR, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sSR, sSS, sSR, sSA, sRJ, sCL},
294 /* s_a */{sCL, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sES, sCL, sSR, sCL, sRJ, sCL},
295 /* s_c */{sCL, sCL, sCL, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sCL, sRJ, sCL},
296 /* err */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCL, sES, sSS, sSR, sSA, sRJ, sCL},
297 /* ab  */{sCL, sCL, sCL, sCL, sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
298 	},
299 	{ /* OUTPUT */
300 /*        sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/
301 /* d   */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
302 /* i   */{sCW, sCW, sCW, sCW, sCW, sCW, sCW, sCW, sES, sCW, sCW, sCW, sCW, sCW},
303 /* i_a */{sCS, sCS, sCS, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
304 /* c_e */{sCE, sCE, sCE, sCE, sCE, sCE, sCE, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
305 /* c_a */{sES, sES, sES, sES, sES, sES, sES, sES, sES, sSS, sSR, sSA, sRJ, sCL},
306 /* s   */{sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSR, sSA, sRJ, sCL},
307 /* s_a */{sSA, sSA, sSA, sSA, sSA, sCW, sCO, sCE, sES, sSA, sSA, sSA, sRJ, sCL},
308 /* s_c */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
309 /* err */{sCL, sCL, sCL, sCL, sCL, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
310 /* ab  */{sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
311 	},
312 	{ /* INPUT-ONLY */
313 /*        sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/
314 /* d   */{sES, sI1, sIN, sCS, sCR, sES, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
315 /* i   */{sI1, sIN, sIN, sIN, sIN, sIN, sCO, sCE, sES, sSS, sSR, sSA, sIN, sIN},
316 /* i_a */{sCE, sCE, sCE, sCE, sCE, sCE, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
317 /* c_e */{sES, sES, sES, sES, sES, sES, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
318 /* c_a */{sES, sI1, sIN, sES, sES, sCW, sES, sES, sES, sSS, sSR, sSA, sRJ, sCL},
319 /* s   */{sSR, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sSR, sSS, sSR, sSA, sRJ, sCL},
320 /* s_a */{sCL, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sCL, sCL, sSR, sCL, sRJ, sCL},
321 /* s_c */{sCL, sCL, sCL, sCL, sCL, sCW, sCO, sCE, sES, sSS, sCL, sCL, sRJ, sCL},
322 /* err */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL},
323 /* ab  */{sCL, sCL, sCL, sCL, sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
324 	},
325 };
326 
327 #define IP_VS_SCTP_MAX_RTO	((60 + 1) * HZ)
328 
329 /* Timeout table[state] */
330 static const int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = {
331 	[IP_VS_SCTP_S_NONE]			= 2 * HZ,
332 	[IP_VS_SCTP_S_INIT1]			= (0 + 3 + 1) * HZ,
333 	[IP_VS_SCTP_S_INIT]			= IP_VS_SCTP_MAX_RTO,
334 	[IP_VS_SCTP_S_COOKIE_SENT]		= IP_VS_SCTP_MAX_RTO,
335 	[IP_VS_SCTP_S_COOKIE_REPLIED]		= IP_VS_SCTP_MAX_RTO,
336 	[IP_VS_SCTP_S_COOKIE_WAIT]		= IP_VS_SCTP_MAX_RTO,
337 	[IP_VS_SCTP_S_COOKIE]			= IP_VS_SCTP_MAX_RTO,
338 	[IP_VS_SCTP_S_COOKIE_ECHOED]		= IP_VS_SCTP_MAX_RTO,
339 	[IP_VS_SCTP_S_ESTABLISHED]		= 15 * 60 * HZ,
340 	[IP_VS_SCTP_S_SHUTDOWN_SENT]		= IP_VS_SCTP_MAX_RTO,
341 	[IP_VS_SCTP_S_SHUTDOWN_RECEIVED]	= IP_VS_SCTP_MAX_RTO,
342 	[IP_VS_SCTP_S_SHUTDOWN_ACK_SENT]	= IP_VS_SCTP_MAX_RTO,
343 	[IP_VS_SCTP_S_REJECTED]			= (0 + 3 + 1) * HZ,
344 	[IP_VS_SCTP_S_CLOSED]			= IP_VS_SCTP_MAX_RTO,
345 	[IP_VS_SCTP_S_LAST]			= 2 * HZ,
346 };
347 
348 static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = {
349 	[IP_VS_SCTP_S_NONE]			= "NONE",
350 	[IP_VS_SCTP_S_INIT1]			= "INIT1",
351 	[IP_VS_SCTP_S_INIT]			= "INIT",
352 	[IP_VS_SCTP_S_COOKIE_SENT]		= "C-SENT",
353 	[IP_VS_SCTP_S_COOKIE_REPLIED]		= "C-REPLIED",
354 	[IP_VS_SCTP_S_COOKIE_WAIT]		= "C-WAIT",
355 	[IP_VS_SCTP_S_COOKIE]			= "COOKIE",
356 	[IP_VS_SCTP_S_COOKIE_ECHOED]		= "C-ECHOED",
357 	[IP_VS_SCTP_S_ESTABLISHED]		= "ESTABLISHED",
358 	[IP_VS_SCTP_S_SHUTDOWN_SENT]		= "S-SENT",
359 	[IP_VS_SCTP_S_SHUTDOWN_RECEIVED]	= "S-RECEIVED",
360 	[IP_VS_SCTP_S_SHUTDOWN_ACK_SENT]	= "S-ACK-SENT",
361 	[IP_VS_SCTP_S_REJECTED]			= "REJECTED",
362 	[IP_VS_SCTP_S_CLOSED]			= "CLOSED",
363 	[IP_VS_SCTP_S_LAST]			= "BUG!",
364 };
365 
366 
sctp_state_name(int state)367 static const char *sctp_state_name(int state)
368 {
369 	if (state >= IP_VS_SCTP_S_LAST)
370 		return "ERR!";
371 	if (sctp_state_name_table[state])
372 		return sctp_state_name_table[state];
373 	return "?";
374 }
375 
376 static inline void
set_sctp_state(struct ip_vs_proto_data * pd,struct ip_vs_conn * cp,int direction,const struct sk_buff * skb,unsigned int iph_len)377 set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
378 		int direction, const struct sk_buff *skb,
379 		unsigned int iph_len)
380 {
381 	struct sctp_chunkhdr _sctpch, *sch;
382 	unsigned char chunk_type;
383 	int event, next_state;
384 	int cofs;
385 
386 	cofs = iph_len + sizeof(struct sctphdr);
387 	sch = skb_header_pointer(skb, cofs, sizeof(_sctpch), &_sctpch);
388 	if (sch == NULL)
389 		return;
390 
391 	chunk_type = sch->type;
392 	/*
393 	 * Section 3: Multiple chunks can be bundled into one SCTP packet
394 	 * up to the MTU size, except for the INIT, INIT ACK, and
395 	 * SHUTDOWN COMPLETE chunks. These chunks MUST NOT be bundled with
396 	 * any other chunk in a packet.
397 	 *
398 	 * Section 3.3.7: DATA chunks MUST NOT be bundled with ABORT. Control
399 	 * chunks (except for INIT, INIT ACK, and SHUTDOWN COMPLETE) MAY be
400 	 * bundled with an ABORT, but they MUST be placed before the ABORT
401 	 * in the SCTP packet or they will be ignored by the receiver.
402 	 */
403 	if ((sch->type == SCTP_CID_COOKIE_ECHO) ||
404 	    (sch->type == SCTP_CID_COOKIE_ACK)) {
405 		int clen = ntohs(sch->length);
406 
407 		if (clen >= sizeof(_sctpch)) {
408 			sch = skb_header_pointer(skb, cofs + ALIGN(clen, 4),
409 						 sizeof(_sctpch), &_sctpch);
410 			if (sch && sch->type == SCTP_CID_ABORT)
411 				chunk_type = sch->type;
412 		}
413 	}
414 
415 	event = (chunk_type < sizeof(sctp_events)) ?
416 		sctp_events[chunk_type] : IP_VS_SCTP_DATA;
417 
418 	/* Update direction to INPUT_ONLY if necessary
419 	 * or delete NO_OUTPUT flag if output packet detected
420 	 */
421 	if (cp->flags & IP_VS_CONN_F_NOOUTPUT) {
422 		if (direction == IP_VS_DIR_OUTPUT)
423 			cp->flags &= ~IP_VS_CONN_F_NOOUTPUT;
424 		else
425 			direction = IP_VS_DIR_INPUT_ONLY;
426 	}
427 
428 	next_state = sctp_states[direction][event][cp->state];
429 
430 	if (next_state != cp->state) {
431 		struct ip_vs_dest *dest = cp->dest;
432 
433 		IP_VS_DBG_BUF(8, "%s %s  %s:%d->"
434 				"%s:%d state: %s->%s conn->refcnt:%d\n",
435 				pd->pp->name,
436 				((direction == IP_VS_DIR_OUTPUT) ?
437 				 "output " : "input "),
438 				IP_VS_DBG_ADDR(cp->daf, &cp->daddr),
439 				ntohs(cp->dport),
440 				IP_VS_DBG_ADDR(cp->af, &cp->caddr),
441 				ntohs(cp->cport),
442 				sctp_state_name(cp->state),
443 				sctp_state_name(next_state),
444 				refcount_read(&cp->refcnt));
445 		if (dest) {
446 			if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
447 				(next_state != IP_VS_SCTP_S_ESTABLISHED)) {
448 				atomic_dec(&dest->activeconns);
449 				cp->flags |= IP_VS_CONN_F_INACTIVE;
450 			} else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
451 				   (next_state == IP_VS_SCTP_S_ESTABLISHED)) {
452 				atomic_inc(&dest->activeconns);
453 				cp->flags &= ~IP_VS_CONN_F_INACTIVE;
454 			}
455 		}
456 		if (next_state == IP_VS_SCTP_S_ESTABLISHED)
457 			ip_vs_control_assure_ct(cp);
458 	}
459 	if (likely(pd))
460 		cp->timeout = pd->timeout_table[cp->state = next_state];
461 	else	/* What to do ? */
462 		cp->timeout = sctp_timeouts[cp->state = next_state];
463 }
464 
465 static void
sctp_state_transition(struct ip_vs_conn * cp,int direction,const struct sk_buff * skb,struct ip_vs_proto_data * pd,unsigned int iph_len)466 sctp_state_transition(struct ip_vs_conn *cp, int direction,
467 		const struct sk_buff *skb, struct ip_vs_proto_data *pd,
468 		unsigned int iph_len)
469 {
470 	spin_lock_bh(&cp->lock);
471 	set_sctp_state(pd, cp, direction, skb, iph_len);
472 	spin_unlock_bh(&cp->lock);
473 }
474 
sctp_app_hashkey(__be16 port)475 static inline __u16 sctp_app_hashkey(__be16 port)
476 {
477 	return (((__force u16)port >> SCTP_APP_TAB_BITS) ^ (__force u16)port)
478 		& SCTP_APP_TAB_MASK;
479 }
480 
sctp_register_app(struct netns_ipvs * ipvs,struct ip_vs_app * inc)481 static int sctp_register_app(struct netns_ipvs *ipvs, struct ip_vs_app *inc)
482 {
483 	struct ip_vs_app *i;
484 	__u16 hash;
485 	__be16 port = inc->port;
486 	int ret = 0;
487 	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(ipvs, IPPROTO_SCTP);
488 
489 	hash = sctp_app_hashkey(port);
490 
491 	list_for_each_entry(i, &ipvs->sctp_apps[hash], p_list) {
492 		if (i->port == port) {
493 			ret = -EEXIST;
494 			goto out;
495 		}
496 	}
497 	list_add_rcu(&inc->p_list, &ipvs->sctp_apps[hash]);
498 	atomic_inc(&pd->appcnt);
499 out:
500 
501 	return ret;
502 }
503 
sctp_unregister_app(struct netns_ipvs * ipvs,struct ip_vs_app * inc)504 static void sctp_unregister_app(struct netns_ipvs *ipvs, struct ip_vs_app *inc)
505 {
506 	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(ipvs, IPPROTO_SCTP);
507 
508 	atomic_dec(&pd->appcnt);
509 	list_del_rcu(&inc->p_list);
510 }
511 
sctp_app_conn_bind(struct ip_vs_conn * cp)512 static int sctp_app_conn_bind(struct ip_vs_conn *cp)
513 {
514 	struct netns_ipvs *ipvs = cp->ipvs;
515 	int hash;
516 	struct ip_vs_app *inc;
517 	int result = 0;
518 
519 	/* Default binding: bind app only for NAT */
520 	if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
521 		return 0;
522 	/* Lookup application incarnations and bind the right one */
523 	hash = sctp_app_hashkey(cp->vport);
524 
525 	list_for_each_entry_rcu(inc, &ipvs->sctp_apps[hash], p_list) {
526 		if (inc->port == cp->vport) {
527 			if (unlikely(!ip_vs_app_inc_get(inc)))
528 				break;
529 
530 			IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->"
531 					"%s:%u to app %s on port %u\n",
532 					__func__,
533 					IP_VS_DBG_ADDR(cp->af, &cp->caddr),
534 					ntohs(cp->cport),
535 					IP_VS_DBG_ADDR(cp->af, &cp->vaddr),
536 					ntohs(cp->vport),
537 					inc->name, ntohs(inc->port));
538 			cp->app = inc;
539 			if (inc->init_conn)
540 				result = inc->init_conn(inc, cp);
541 			break;
542 		}
543 	}
544 
545 	return result;
546 }
547 
548 /* ---------------------------------------------
549  *   timeouts is netns related now.
550  * ---------------------------------------------
551  */
__ip_vs_sctp_init(struct netns_ipvs * ipvs,struct ip_vs_proto_data * pd)552 static int __ip_vs_sctp_init(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
553 {
554 	ip_vs_init_hash_table(ipvs->sctp_apps, SCTP_APP_TAB_SIZE);
555 	pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts,
556 							sizeof(sctp_timeouts));
557 	if (!pd->timeout_table)
558 		return -ENOMEM;
559 	return 0;
560 }
561 
__ip_vs_sctp_exit(struct netns_ipvs * ipvs,struct ip_vs_proto_data * pd)562 static void __ip_vs_sctp_exit(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
563 {
564 	kfree(pd->timeout_table);
565 }
566 
567 struct ip_vs_protocol ip_vs_protocol_sctp = {
568 	.name		= "SCTP",
569 	.protocol	= IPPROTO_SCTP,
570 	.num_states	= IP_VS_SCTP_S_LAST,
571 	.dont_defrag	= 0,
572 	.init		= NULL,
573 	.exit		= NULL,
574 	.init_netns	= __ip_vs_sctp_init,
575 	.exit_netns	= __ip_vs_sctp_exit,
576 	.register_app	= sctp_register_app,
577 	.unregister_app = sctp_unregister_app,
578 	.conn_schedule	= sctp_conn_schedule,
579 	.conn_in_get	= ip_vs_conn_in_get_proto,
580 	.conn_out_get	= ip_vs_conn_out_get_proto,
581 	.snat_handler	= sctp_snat_handler,
582 	.dnat_handler	= sctp_dnat_handler,
583 	.state_name	= sctp_state_name,
584 	.state_transition = sctp_state_transition,
585 	.app_conn_bind	= sctp_app_conn_bind,
586 	.debug_packet	= ip_vs_tcpudp_debug_packet,
587 	.timeout_change	= NULL,
588 };
589