root/net/netfilter/ipvs/ip_vs_proto_sctp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sctp_conn_schedule
  2. sctp_nat_csum
  3. sctp_snat_handler
  4. sctp_dnat_handler
  5. sctp_csum_check
  6. sctp_state_name
  7. set_sctp_state
  8. sctp_state_transition
  9. sctp_app_hashkey
  10. sctp_register_app
  11. sctp_unregister_app
  12. sctp_app_conn_bind
  13. __ip_vs_sctp_init
  14. __ip_vs_sctp_exit

   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_ensure_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_ensure_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 };

/* [<][>][^][v][top][bottom][index][help] */