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