linux/net/ipv4/tcp_fastopen.c
<<
>>
Prefs
   1#include <linux/err.h>
   2#include <linux/init.h>
   3#include <linux/kernel.h>
   4#include <linux/list.h>
   5#include <linux/tcp.h>
   6#include <linux/rcupdate.h>
   7#include <linux/rculist.h>
   8#include <net/inetpeer.h>
   9#include <net/tcp.h>
  10
  11int sysctl_tcp_fastopen __read_mostly;
  12
  13struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
  14
  15static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock);
  16
  17static void tcp_fastopen_ctx_free(struct rcu_head *head)
  18{
  19        struct tcp_fastopen_context *ctx =
  20            container_of(head, struct tcp_fastopen_context, rcu);
  21        crypto_free_cipher(ctx->tfm);
  22        kfree(ctx);
  23}
  24
  25int tcp_fastopen_reset_cipher(void *key, unsigned int len)
  26{
  27        int err;
  28        struct tcp_fastopen_context *ctx, *octx;
  29
  30        ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
  31        if (!ctx)
  32                return -ENOMEM;
  33        ctx->tfm = crypto_alloc_cipher("aes", 0, 0);
  34
  35        if (IS_ERR(ctx->tfm)) {
  36                err = PTR_ERR(ctx->tfm);
  37error:          kfree(ctx);
  38                pr_err("TCP: TFO aes cipher alloc error: %d\n", err);
  39                return err;
  40        }
  41        err = crypto_cipher_setkey(ctx->tfm, key, len);
  42        if (err) {
  43                pr_err("TCP: TFO cipher key error: %d\n", err);
  44                crypto_free_cipher(ctx->tfm);
  45                goto error;
  46        }
  47        memcpy(ctx->key, key, len);
  48
  49        spin_lock(&tcp_fastopen_ctx_lock);
  50
  51        octx = rcu_dereference_protected(tcp_fastopen_ctx,
  52                                lockdep_is_held(&tcp_fastopen_ctx_lock));
  53        rcu_assign_pointer(tcp_fastopen_ctx, ctx);
  54        spin_unlock(&tcp_fastopen_ctx_lock);
  55
  56        if (octx)
  57                call_rcu(&octx->rcu, tcp_fastopen_ctx_free);
  58        return err;
  59}
  60
  61/* Computes the fastopen cookie for the peer.
  62 * The peer address is a 128 bits long (pad with zeros for IPv4).
  63 *
  64 * The caller must check foc->len to determine if a valid cookie
  65 * has been generated successfully.
  66*/
  67void tcp_fastopen_cookie_gen(__be32 addr, struct tcp_fastopen_cookie *foc)
  68{
  69        __be32 peer_addr[4] = { addr, 0, 0, 0 };
  70        struct tcp_fastopen_context *ctx;
  71
  72        rcu_read_lock();
  73        ctx = rcu_dereference(tcp_fastopen_ctx);
  74        if (ctx) {
  75                crypto_cipher_encrypt_one(ctx->tfm,
  76                                          foc->val,
  77                                          (__u8 *)peer_addr);
  78                foc->len = TCP_FASTOPEN_COOKIE_SIZE;
  79        }
  80        rcu_read_unlock();
  81}
  82
  83static int __init tcp_fastopen_init(void)
  84{
  85        __u8 key[TCP_FASTOPEN_KEY_LENGTH];
  86
  87        get_random_bytes(key, sizeof(key));
  88        tcp_fastopen_reset_cipher(key, sizeof(key));
  89        return 0;
  90}
  91
  92late_initcall(tcp_fastopen_init);
  93
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.