]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/ipv4/sysctl_net_ipv4.c
Merge tag 'trace-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
[linux.git] / net / ipv4 / sysctl_net_ipv4.c
index b6f14af926faf80f1686549bee7154c584dc63e6..7d66306b5f39719ac432178948ceac256018d52a 100644 (file)
@@ -279,55 +279,96 @@ static int proc_allowed_congestion_control(struct ctl_table *ctl,
        return ret;
 }
 
+static int sscanf_key(char *buf, __le32 *key)
+{
+       u32 user_key[4];
+       int i, ret = 0;
+
+       if (sscanf(buf, "%x-%x-%x-%x", user_key, user_key + 1,
+                  user_key + 2, user_key + 3) != 4) {
+               ret = -EINVAL;
+       } else {
+               for (i = 0; i < ARRAY_SIZE(user_key); i++)
+                       key[i] = cpu_to_le32(user_key[i]);
+       }
+       pr_debug("proc TFO key set 0x%x-%x-%x-%x <- 0x%s: %u\n",
+                user_key[0], user_key[1], user_key[2], user_key[3], buf, ret);
+
+       return ret;
+}
+
 static int proc_tcp_fastopen_key(struct ctl_table *table, int write,
                                 void __user *buffer, size_t *lenp,
                                 loff_t *ppos)
 {
        struct net *net = container_of(table->data, struct net,
            ipv4.sysctl_tcp_fastopen);
-       struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
-       struct tcp_fastopen_context *ctxt;
-       u32  user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */
-       __le32 key[4];
-       int ret, i;
+       /* maxlen to print the list of keys in hex (*2), with dashes
+        * separating doublewords and a comma in between keys.
+        */
+       struct ctl_table tbl = { .maxlen = ((TCP_FASTOPEN_KEY_LENGTH *
+                                           2 * TCP_FASTOPEN_KEY_MAX) +
+                                           (TCP_FASTOPEN_KEY_MAX * 5)) };
+       struct tcp_fastopen_context *ctx;
+       u32 user_key[TCP_FASTOPEN_KEY_MAX * 4];
+       __le32 key[TCP_FASTOPEN_KEY_MAX * 4];
+       char *backup_data;
+       int ret, i = 0, off = 0, n_keys = 0;
 
        tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL);
        if (!tbl.data)
                return -ENOMEM;
 
        rcu_read_lock();
-       ctxt = rcu_dereference(net->ipv4.tcp_fastopen_ctx);
-       if (ctxt)
-               memcpy(key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
-       else
-               memset(key, 0, sizeof(key));
+       ctx = rcu_dereference(net->ipv4.tcp_fastopen_ctx);
+       if (ctx) {
+               n_keys = tcp_fastopen_context_len(ctx);
+               memcpy(&key[0], &ctx->key[0], TCP_FASTOPEN_KEY_LENGTH * n_keys);
+       }
        rcu_read_unlock();
 
-       for (i = 0; i < ARRAY_SIZE(key); i++)
+       if (!n_keys) {
+               memset(&key[0], 0, TCP_FASTOPEN_KEY_LENGTH);
+               n_keys = 1;
+       }
+
+       for (i = 0; i < n_keys * 4; i++)
                user_key[i] = le32_to_cpu(key[i]);
 
-       snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x",
-               user_key[0], user_key[1], user_key[2], user_key[3]);
+       for (i = 0; i < n_keys; i++) {
+               off += snprintf(tbl.data + off, tbl.maxlen - off,
+                               "%08x-%08x-%08x-%08x",
+                               user_key[i * 4],
+                               user_key[i * 4 + 1],
+                               user_key[i * 4 + 2],
+                               user_key[i * 4 + 3]);
+               if (i + 1 < n_keys)
+                       off += snprintf(tbl.data + off, tbl.maxlen - off, ",");
+       }
+
        ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
 
        if (write && ret == 0) {
-               if (sscanf(tbl.data, "%x-%x-%x-%x", user_key, user_key + 1,
-                          user_key + 2, user_key + 3) != 4) {
+               backup_data = strchr(tbl.data, ',');
+               if (backup_data) {
+                       *backup_data = '\0';
+                       backup_data++;
+               }
+               if (sscanf_key(tbl.data, key)) {
                        ret = -EINVAL;
                        goto bad_key;
                }
-
-               for (i = 0; i < ARRAY_SIZE(user_key); i++)
-                       key[i] = cpu_to_le32(user_key[i]);
-
+               if (backup_data) {
+                       if (sscanf_key(backup_data, key + 4)) {
+                               ret = -EINVAL;
+                               goto bad_key;
+                       }
+               }
                tcp_fastopen_reset_cipher(net, NULL, key,
-                                         TCP_FASTOPEN_KEY_LENGTH);
+                                         backup_data ? key + 4 : NULL);
        }
 
 bad_key:
-       pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n",
-               user_key[0], user_key[1], user_key[2], user_key[3],
-              (char *)tbl.data, ret);
        kfree(tbl.data);
        return ret;
 }
@@ -956,7 +997,12 @@ static struct ctl_table ipv4_net_table[] = {
                .procname       = "tcp_fastopen_key",
                .mode           = 0600,
                .data           = &init_net.ipv4.sysctl_tcp_fastopen,
-               .maxlen         = ((TCP_FASTOPEN_KEY_LENGTH * 2) + 10),
+               /* maxlen to print the list of keys in hex (*2), with dashes
+                * separating doublewords and a comma in between keys.
+                */
+               .maxlen         = ((TCP_FASTOPEN_KEY_LENGTH *
+                                  2 * TCP_FASTOPEN_KEY_MAX) +
+                                  (TCP_FASTOPEN_KEY_MAX * 5)),
                .proc_handler   = proc_tcp_fastopen_key,
        },
        {
@@ -984,7 +1030,7 @@ static struct ctl_table ipv4_net_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_fib_multipath_hash_policy,
                .extra1         = &zero,
-               .extra2         = &one,
+               .extra2         = &two,
        },
 #endif
        {