Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tcp_fastopen.c
Go to the documentation of this file.
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 
12 
14 
15 static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock);
16 
17 static 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 
25 int 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);
37 error: 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 */
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);
79  }
80  rcu_read_unlock();
81 }
82 
83 static int __init tcp_fastopen_init(void)
84 {
86 
87  get_random_bytes(key, sizeof(key));
88  tcp_fastopen_reset_cipher(key, sizeof(key));
89  return 0;
90 }
91 
92 late_initcall(tcp_fastopen_init);