linux/net/netfilter/ipvs/ip_vs_proto_sctp.c
<<
>>
Prefs
   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
  12static int
  13sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
  14
  15static int
  16sctp_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
  83static 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
  90static int
  91sctp_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
 137static int
 138sctp_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
 185static int
 186sctp_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
 212enum 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 */
 227static __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
 285static 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] */
 331static 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
 349static 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
 368static 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
 377static inline void
 378set_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
 473static void
 474sctp_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
 482static 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
 488static 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);
 506out:
 507
 508        return ret;
 509}
 510
 511static 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
 519static 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 */
 559static 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
 569static void __ip_vs_sctp_exit(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
 570{
 571        kfree(pd->timeout_table);
 572}
 573
 574struct 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