sctp: Sysctl configuration for IPv4 Address Scoping
authorBhaskar Dutta <bhaskie@gmail.com>
Thu, 3 Sep 2009 11:55:47 +0000 (17:25 +0530)
committerVlad Yasevich <vladislav.yasevich@hp.com>
Fri, 4 Sep 2009 22:21:01 +0000 (18:21 -0400)
This patch introduces a new sysctl option to make IPv4 Address Scoping
configurable <draft-stewart-tsvwg-sctp-ipv4-00.txt>.

In networking environments where DNAT rules in iptables prerouting
chains convert destination IP's to link-local/private IP addresses,
SCTP connections fail to establish as the INIT chunk is dropped by the
kernel due to address scope match failure.
For example to support overlapping IP addresses (same IP address with
different vlan id) a Layer-5 application listens on link local IP's,
and there is a DNAT rule that maps the destination IP to a link local
IP. Such applications never get the SCTP INIT if the address-scoping
draft is strictly followed.

This sysctl configuration allows SCTP to function in such
unconventional networking environments.

Sysctl options:
0 - Disable IPv4 address scoping draft altogether
1 - Enable IPv4 address scoping (default, current behavior)
2 - Enable address scoping but allow IPv4 private addresses in init/init-ack
3 - Enable address scoping but allow IPv4 link local address in init/init-ack

Signed-off-by: Bhaskar Dutta <bhaskar.dutta@globallogic.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Documentation/networking/ip-sysctl.txt
include/net/sctp/constants.h
include/net/sctp/structs.h
net/sctp/bind_addr.c
net/sctp/protocol.c
net/sctp/sysctl.c

index 4e9c6d7b4efc16e39d77c4a6f973cdc96f14c7bd..fbe427a6580cc5996a3352c4115327db371eaecc 100644 (file)
@@ -1297,6 +1297,16 @@ sctp_rmem - vector of 3 INTEGERs: min, default, max
 sctp_wmem  - vector of 3 INTEGERs: min, default, max
        See tcp_wmem for a description.
 
+addr_scope_policy - INTEGER
+       Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
+
+       0   - Disable IPv4 address scoping
+       1   - Enable IPv4 address scoping
+       2   - Follow draft but allow IPv4 private addresses
+       3   - Follow draft but allow IPv4 link local addresses
+
+       Default: 1
+
 
 /proc/sys/net/core/*
 dev_weight - INTEGER
index af8c1508109e0ab25a9d853773e5a94ad67f438e..58f714a3b670965a38888a3c594f5455f4de68df 100644 (file)
@@ -363,6 +363,13 @@ typedef enum {
        SCTP_SCOPE_UNUSABLE,            /* IPv4 unusable addresses */
 } sctp_scope_t;
 
+typedef enum {
+       SCTP_SCOPE_POLICY_DISABLE,      /* Disable IPv4 address scoping */
+       SCTP_SCOPE_POLICY_ENABLE,       /* Enable IPv4 address scoping */
+       SCTP_SCOPE_POLICY_PRIVATE,      /* Follow draft but allow IPv4 private addresses */
+       SCTP_SCOPE_POLICY_LINK,         /* Follow draft but allow IPv4 link local addresses */
+} sctp_scope_policy_t;
+
 /* Based on IPv4 scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>,
  * SCTP IPv4 unusable addresses: 0.0.0.0/8, 224.0.0.0/4, 198.18.0.0/24,
  * 192.88.99.0/24.
index 993cfff9218efde317c5011d69563281ae855ce2..a48d80e77cd79e2fabf40eda89bcd9b18c2e6f47 100644 (file)
@@ -219,6 +219,15 @@ extern struct sctp_globals {
        /* Flag to idicate if SCTP-AUTH is enabled */
        int auth_enable;
 
+       /*
+        * Policy to control SCTP IPv4 address scoping
+        * 0   - Disable IPv4 address scoping
+        * 1   - Enable IPv4 address scoping
+        * 2   - Selectively allow only IPv4 private addresses
+        * 3   - Selectively allow only IPv4 link local address
+        */
+       int ipv4_scope_policy;
+
        /* Flag to indicate whether computing and verifying checksum
         * is disabled. */
         int checksum_disable;
@@ -252,6 +261,7 @@ extern struct sctp_globals {
 #define sctp_port_hashtable            (sctp_globals.port_hashtable)
 #define sctp_local_addr_list           (sctp_globals.local_addr_list)
 #define sctp_local_addr_lock           (sctp_globals.addr_list_lock)
+#define sctp_scope_policy              (sctp_globals.ipv4_scope_policy)
 #define sctp_addip_enable              (sctp_globals.addip_enable)
 #define sctp_addip_noauth              (sctp_globals.addip_noauth_enable)
 #define sctp_prsctp_enable             (sctp_globals.prsctp_enable)
index 6d5944a745d4e3d709ef2660389638d65882a1bc..13a6fba410776bef83c73ce9a6eadc65ad9493ee 100644 (file)
@@ -510,9 +510,28 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
         * of requested destination address, sender and receiver
         * SHOULD include all of its addresses with level greater
         * than or equal to L.
+        *
+        * Address scoping can be selectively controlled via sysctl
+        * option
         */
-       if (addr_scope <= scope)
+       switch (sctp_scope_policy) {
+       case SCTP_SCOPE_POLICY_DISABLE:
                return 1;
+       case SCTP_SCOPE_POLICY_ENABLE:
+               if (addr_scope <= scope)
+                       return 1;
+               break;
+       case SCTP_SCOPE_POLICY_PRIVATE:
+               if (addr_scope <= scope || SCTP_SCOPE_PRIVATE == addr_scope)
+                       return 1;
+               break;
+       case SCTP_SCOPE_POLICY_LINK:
+               if (addr_scope <= scope || SCTP_SCOPE_LINK == addr_scope)
+                       return 1;
+               break;
+       default:
+               break;
+       }
 
        return 0;
 }
index a76da657244a8e38fdb692426857130034da5fd0..60093be8385d68fa27ba002e6c84e51db437a2dd 100644 (file)
@@ -431,16 +431,14 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
  * of requested destination address, sender and receiver
  * SHOULD include all of its addresses with level greater
  * than or equal to L.
+ *
+ * IPv4 scoping can be controlled through sysctl option
+ * net.sctp.addr_scope_policy
  */
 static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
 {
        sctp_scope_t retval;
 
-       /* Should IPv4 scoping be a sysctl configurable option
-        * so users can turn it off (default on) for certain
-        * unconventional networking environments?
-        */
-
        /* Check for unusable SCTP addresses. */
        if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) {
                retval =  SCTP_SCOPE_UNUSABLE;
@@ -1259,6 +1257,9 @@ SCTP_STATIC __init int sctp_init(void)
        /* Disable AUTH by default. */
        sctp_auth_enable = 0;
 
+       /* Set SCOPE policy to enabled */
+       sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
+
        sctp_sysctl_register();
 
        INIT_LIST_HEAD(&sctp_address_families);
index 63eabbc71298a30b76196aa8f341db78bdf30f31..ab7151da120fb08818666495a25803e90a658087 100644 (file)
@@ -51,6 +51,7 @@ static int timer_max = 86400000; /* ms in one day */
 static int int_max = INT_MAX;
 static int sack_timer_min = 1;
 static int sack_timer_max = 500;
+static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
 
 extern int sysctl_sctp_mem[3];
 extern int sysctl_sctp_rmem[3];
@@ -272,6 +273,17 @@ static ctl_table sctp_table[] = {
                .proc_handler   = proc_dointvec,
                .strategy       = sysctl_intvec
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "addr_scope_policy",
+               .data           = &sctp_scope_policy,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+               .extra2         = &addr_scope_max,
+       },
        { .ctl_name = 0 }
 };