2 * Copyright (c) 2015-2017 Patrick Kelsey
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * This is an implementation of TCP Fast Open (TFO) [RFC7413]. To include
29 * this code, add the following line to your kernel config:
34 * The generated TFO cookies are the 64-bit output of
35 * SipHash24(key=<16-byte-key>, msg=<client-ip>). Multiple concurrent valid
36 * keys are supported so that time-based rolling cookie invalidation
37 * policies can be implemented in the system. The default number of
38 * concurrent keys is 2. This can be adjusted in the kernel config as
41 * options TCP_RFC7413_MAX_KEYS=<num-keys>
44 * In addition to the facilities defined in RFC7413, this implementation
45 * supports a pre-shared key (PSK) mode of operation in which the TFO server
46 * requires the client to be in possession of a shared secret in order for
47 * the client to be able to successfully open TFO connections with the
48 * server. This is useful, for example, in environments where TFO servers
49 * are exposed to both internal and external clients and only wish to allow
50 * TFO connections from internal clients.
52 * In the PSK mode of operation, the server generates and sends TFO cookies
53 * to requesting clients as usual. However, when validating cookies
54 * received in TFO SYNs from clients, the server requires the
55 * client-supplied cookie to equal SipHash24(key=<16-byte-psk>,
56 * msg=<cookie-sent-to-client>).
58 * Multiple concurrent valid pre-shared keys are supported so that
59 * time-based rolling PSK invalidation policies can be implemented in the
60 * system. The default number of concurrent pre-shared keys is 2. This can
61 * be adjusted in the kernel config as follows:
63 * options TCP_RFC7413_MAX_PSKS=<num-psks>
66 * The following TFO-specific sysctls are defined:
68 * net.inet.tcp.fastopen.acceptany (RW, default 0)
69 * When non-zero, all client-supplied TFO cookies will be considered to
72 * net.inet.tcp.fastopen.autokey (RW, default 120)
73 * When this and net.inet.tcp.fastopen.server_enable are non-zero, a new
74 * key will be automatically generated after this many seconds.
76 * net.inet.tcp.fastopen.ccache_bucket_limit
77 * (RWTUN, default TCP_FASTOPEN_CCACHE_BUCKET_LIMIT_DEFAULT)
78 * The maximum number of entries in a client cookie cache bucket.
80 * net.inet.tcp.fastopen.ccache_buckets
81 * (RDTUN, default TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT)
82 * The number of client cookie cache buckets.
84 * net.inet.tcp.fastopen.ccache_list (RO)
85 * Print the client cookie cache.
87 * net.inet.tcp.fastopen.client_enable (RW, default 0)
88 * When zero, no new active (i.e., client) TFO connections can be
89 * created. On the transition from enabled to disabled, the client
90 * cookie cache is cleared and disabled. The transition from enabled to
91 * disabled does not affect any active TFO connections in progress; it
92 * only prevents new ones from being made.
94 * net.inet.tcp.fastopen.keylen (RD)
95 * The key length in bytes.
97 * net.inet.tcp.fastopen.maxkeys (RD)
98 * The maximum number of keys supported.
100 * net.inet.tcp.fastopen.maxpsks (RD)
101 * The maximum number of pre-shared keys supported.
103 * net.inet.tcp.fastopen.numkeys (RD)
104 * The current number of keys installed.
106 * net.inet.tcp.fastopen.numpsks (RD)
107 * The current number of pre-shared keys installed.
109 * net.inet.tcp.fastopen.path_disable_time
110 * (RW, default TCP_FASTOPEN_PATH_DISABLE_TIME_DEFAULT)
111 * When a failure occurs while trying to create a new active (i.e.,
112 * client) TFO connection, new active connections on the same path, as
113 * determined by the tuple {client_ip, server_ip, server_port}, will be
114 * forced to be non-TFO for this many seconds. Note that the path
115 * disable mechanism relies on state stored in client cookie cache
116 * entries, so it is possible for the disable time for a given path to
117 * be reduced if the corresponding client cookie cache entry is reused
118 * due to resource pressure before the disable period has elapsed.
120 * net.inet.tcp.fastopen.psk_enable (RW, default 0)
121 * When non-zero, pre-shared key (PSK) mode is enabled for all TFO
122 * servers. On the transition from enabled to disabled, all installed
123 * pre-shared keys are removed.
125 * net.inet.tcp.fastopen.server_enable (RW, default 0)
126 * When zero, no new passive (i.e., server) TFO connections can be
127 * created. On the transition from enabled to disabled, all installed
128 * keys and pre-shared keys are removed. On the transition from
129 * disabled to enabled, if net.inet.tcp.fastopen.autokey is non-zero and
130 * there are no keys installed, a new key will be generated immediately.
131 * The transition from enabled to disabled does not affect any passive
132 * TFO connections in progress; it only prevents new ones from being
135 * net.inet.tcp.fastopen.setkey (WR)
136 * Install a new key by writing net.inet.tcp.fastopen.keylen bytes to
139 * net.inet.tcp.fastopen.setpsk (WR)
140 * Install a new pre-shared key by writing net.inet.tcp.fastopen.keylen
141 * bytes to this sysctl.
143 * In order for TFO connections to be created via a listen socket, that
144 * socket must have the TCP_FASTOPEN socket option set on it. This option
145 * can be set on the socket either before or after the listen() is invoked.
146 * Clearing this option on a listen socket after it has been set has no
147 * effect on existing TFO connections or TFO connections in progress; it
148 * only prevents new TFO connections from being made.
150 * For passively-created sockets, the TCP_FASTOPEN socket option can be
151 * queried to determine whether the connection was established using TFO.
152 * Note that connections that are established via a TFO SYN, but that fall
153 * back to using a non-TFO SYN|ACK will have the TCP_FASTOPEN socket option
156 * Per the RFC, this implementation limits the number of TFO connections
157 * that can be in the SYN_RECEIVED state on a per listen-socket basis.
158 * Whenever this limit is exceeded, requests for new TFO connections are
159 * serviced as non-TFO requests. Without such a limit, given a valid TFO
160 * cookie, an attacker could keep the listen queue in an overflow condition
161 * using a TFO SYN flood. This implementation sets the limit at half the
162 * configured listen backlog.
166 #include <sys/cdefs.h>
167 #include "opt_inet.h"
169 #include <sys/param.h>
170 #include <sys/jail.h>
171 #include <sys/kernel.h>
172 #include <sys/hash.h>
173 #include <sys/limits.h>
174 #include <sys/lock.h>
175 #include <sys/proc.h>
176 #include <sys/rmlock.h>
177 #include <sys/sbuf.h>
178 #include <sys/socket.h>
179 #include <sys/socketvar.h>
180 #include <sys/sysctl.h>
181 #include <sys/systm.h>
183 #include <crypto/siphash/siphash.h>
185 #include <net/vnet.h>
187 #include <netinet/in.h>
188 #include <netinet/in_pcb.h>
189 #include <netinet/tcp_var.h>
190 #include <netinet/tcp_fastopen.h>
192 #define TCP_FASTOPEN_KEY_LEN SIPHASH_KEY_LENGTH
194 #if TCP_FASTOPEN_PSK_LEN != TCP_FASTOPEN_KEY_LEN
195 #error TCP_FASTOPEN_PSK_LEN must be equal to TCP_FASTOPEN_KEY_LEN
199 * Because a PSK-mode setsockopt() uses tcpcb.t_tfo_cookie.client to hold
200 * the PSK until the connect occurs.
202 #if TCP_FASTOPEN_MAX_COOKIE_LEN < TCP_FASTOPEN_PSK_LEN
203 #error TCP_FASTOPEN_MAX_COOKIE_LEN must be >= TCP_FASTOPEN_PSK_LEN
206 #define TCP_FASTOPEN_CCACHE_BUCKET_LIMIT_DEFAULT 16
207 #define TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT 2048 /* must be power of 2 */
209 #define TCP_FASTOPEN_PATH_DISABLE_TIME_DEFAULT 900 /* seconds */
211 #if !defined(TCP_RFC7413_MAX_KEYS) || (TCP_RFC7413_MAX_KEYS < 1)
212 #define TCP_FASTOPEN_MAX_KEYS 2
214 #define TCP_FASTOPEN_MAX_KEYS TCP_RFC7413_MAX_KEYS
217 #if TCP_FASTOPEN_MAX_KEYS > 10
218 #undef TCP_FASTOPEN_MAX_KEYS
219 #define TCP_FASTOPEN_MAX_KEYS 10
222 #if !defined(TCP_RFC7413_MAX_PSKS) || (TCP_RFC7413_MAX_PSKS < 1)
223 #define TCP_FASTOPEN_MAX_PSKS 2
225 #define TCP_FASTOPEN_MAX_PSKS TCP_RFC7413_MAX_PSKS
228 #if TCP_FASTOPEN_MAX_PSKS > 10
229 #undef TCP_FASTOPEN_MAX_PSKS
230 #define TCP_FASTOPEN_MAX_PSKS 10
233 struct tcp_fastopen_keylist
{
235 unsigned int newest_psk
;
236 uint8_t key
[TCP_FASTOPEN_MAX_KEYS
][TCP_FASTOPEN_KEY_LEN
];
237 uint8_t psk
[TCP_FASTOPEN_MAX_PSKS
][TCP_FASTOPEN_KEY_LEN
];
240 struct tcp_fastopen_callout
{
245 static struct tcp_fastopen_ccache_entry
*tcp_fastopen_ccache_lookup(
246 struct in_conninfo
*, struct tcp_fastopen_ccache_bucket
**);
247 static struct tcp_fastopen_ccache_entry
*tcp_fastopen_ccache_create(
248 struct tcp_fastopen_ccache_bucket
*, struct in_conninfo
*, uint16_t, uint8_t,
250 static void tcp_fastopen_ccache_bucket_trim(struct tcp_fastopen_ccache_bucket
*,
252 static void tcp_fastopen_ccache_entry_drop(struct tcp_fastopen_ccache_entry
*,
253 struct tcp_fastopen_ccache_bucket
*);
255 SYSCTL_NODE(_net_inet_tcp
, OID_AUTO
, fastopen
, CTLFLAG_RW
| CTLFLAG_MPSAFE
, 0,
258 VNET_DEFINE_STATIC(int, tcp_fastopen_acceptany
) = 0;
259 #define V_tcp_fastopen_acceptany VNET(tcp_fastopen_acceptany)
260 SYSCTL_INT(_net_inet_tcp_fastopen
, OID_AUTO
, acceptany
,
261 CTLFLAG_VNET
| CTLFLAG_RW
, &VNET_NAME(tcp_fastopen_acceptany
), 0,
262 "Accept any non-empty cookie");
264 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_autokey
) = 120;
265 #define V_tcp_fastopen_autokey VNET(tcp_fastopen_autokey)
266 static int sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS
);
267 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, autokey
,
268 CTLFLAG_VNET
| CTLTYPE_UINT
| CTLFLAG_RW
| CTLFLAG_MPSAFE
,
269 NULL
, 0, &sysctl_net_inet_tcp_fastopen_autokey
, "IU",
270 "Number of seconds between auto-generation of a new key; zero disables");
272 static int sysctl_net_inet_tcp_fastopen_ccache_bucket_limit(SYSCTL_HANDLER_ARGS
);
273 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, ccache_bucket_limit
,
274 CTLFLAG_VNET
| CTLTYPE_UINT
| CTLFLAG_RWTUN
| CTLFLAG_NOFETCH
| CTLFLAG_NEEDGIANT
,
275 NULL
, 0, &sysctl_net_inet_tcp_fastopen_ccache_bucket_limit
, "IU",
276 "Max entries per bucket in client cookie cache");
278 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_ccache_buckets
) =
279 TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT
;
280 #define V_tcp_fastopen_ccache_buckets VNET(tcp_fastopen_ccache_buckets)
281 SYSCTL_UINT(_net_inet_tcp_fastopen
, OID_AUTO
, ccache_buckets
,
282 CTLFLAG_VNET
| CTLFLAG_RDTUN
, &VNET_NAME(tcp_fastopen_ccache_buckets
), 0,
283 "Client cookie cache number of buckets (power of 2)");
285 VNET_DEFINE(unsigned int, tcp_fastopen_client_enable
) = 1;
286 static int sysctl_net_inet_tcp_fastopen_client_enable(SYSCTL_HANDLER_ARGS
);
287 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, client_enable
,
288 CTLFLAG_VNET
| CTLTYPE_UINT
| CTLFLAG_RW
| CTLFLAG_NEEDGIANT
,
289 NULL
, 0, &sysctl_net_inet_tcp_fastopen_client_enable
, "IU",
290 "Enable/disable TCP Fast Open client functionality");
292 SYSCTL_INT(_net_inet_tcp_fastopen
, OID_AUTO
, keylen
,
293 CTLFLAG_RD
, SYSCTL_NULL_INT_PTR
, TCP_FASTOPEN_KEY_LEN
,
294 "Key length in bytes");
296 SYSCTL_INT(_net_inet_tcp_fastopen
, OID_AUTO
, maxkeys
,
297 CTLFLAG_RD
, SYSCTL_NULL_INT_PTR
, TCP_FASTOPEN_MAX_KEYS
,
298 "Maximum number of keys supported");
300 SYSCTL_INT(_net_inet_tcp_fastopen
, OID_AUTO
, maxpsks
,
301 CTLFLAG_RD
, SYSCTL_NULL_INT_PTR
, TCP_FASTOPEN_MAX_PSKS
,
302 "Maximum number of pre-shared keys supported");
304 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_numkeys
) = 0;
305 #define V_tcp_fastopen_numkeys VNET(tcp_fastopen_numkeys)
306 SYSCTL_UINT(_net_inet_tcp_fastopen
, OID_AUTO
, numkeys
,
307 CTLFLAG_VNET
| CTLFLAG_RD
, &VNET_NAME(tcp_fastopen_numkeys
), 0,
308 "Number of keys installed");
310 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_numpsks
) = 0;
311 #define V_tcp_fastopen_numpsks VNET(tcp_fastopen_numpsks)
312 SYSCTL_UINT(_net_inet_tcp_fastopen
, OID_AUTO
, numpsks
,
313 CTLFLAG_VNET
| CTLFLAG_RD
, &VNET_NAME(tcp_fastopen_numpsks
), 0,
314 "Number of pre-shared keys installed");
316 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_path_disable_time
) =
317 TCP_FASTOPEN_PATH_DISABLE_TIME_DEFAULT
;
318 #define V_tcp_fastopen_path_disable_time VNET(tcp_fastopen_path_disable_time)
319 SYSCTL_UINT(_net_inet_tcp_fastopen
, OID_AUTO
, path_disable_time
,
320 CTLFLAG_VNET
| CTLFLAG_RW
, &VNET_NAME(tcp_fastopen_path_disable_time
), 0,
321 "Seconds a TFO failure disables a {client_ip, server_ip, server_port} path");
323 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_psk_enable
) = 0;
324 #define V_tcp_fastopen_psk_enable VNET(tcp_fastopen_psk_enable)
325 static int sysctl_net_inet_tcp_fastopen_psk_enable(SYSCTL_HANDLER_ARGS
);
326 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, psk_enable
,
327 CTLFLAG_VNET
| CTLTYPE_UINT
| CTLFLAG_RW
| CTLFLAG_MPSAFE
,
328 NULL
, 0, &sysctl_net_inet_tcp_fastopen_psk_enable
, "IU",
329 "Enable/disable TCP Fast Open server pre-shared key mode");
331 VNET_DEFINE(unsigned int, tcp_fastopen_server_enable
) = 0;
332 static int sysctl_net_inet_tcp_fastopen_server_enable(SYSCTL_HANDLER_ARGS
);
333 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, server_enable
,
334 CTLFLAG_VNET
| CTLTYPE_UINT
| CTLFLAG_RW
| CTLFLAG_MPSAFE
,
335 NULL
, 0, &sysctl_net_inet_tcp_fastopen_server_enable
, "IU",
336 "Enable/disable TCP Fast Open server functionality");
338 static int sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS
);
339 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, setkey
,
340 CTLFLAG_VNET
| CTLTYPE_OPAQUE
| CTLFLAG_WR
| CTLFLAG_MPSAFE
,
341 NULL
, 0, &sysctl_net_inet_tcp_fastopen_setkey
, "",
342 "Install a new key");
344 static int sysctl_net_inet_tcp_fastopen_setpsk(SYSCTL_HANDLER_ARGS
);
345 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, setpsk
,
346 CTLFLAG_VNET
| CTLTYPE_OPAQUE
| CTLFLAG_WR
| CTLFLAG_MPSAFE
,
347 NULL
, 0, &sysctl_net_inet_tcp_fastopen_setpsk
, "",
348 "Install a new pre-shared key");
350 static int sysctl_net_inet_tcp_fastopen_ccache_list(SYSCTL_HANDLER_ARGS
);
351 SYSCTL_PROC(_net_inet_tcp_fastopen
, OID_AUTO
, ccache_list
,
352 CTLFLAG_VNET
| CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_SKIP
| CTLFLAG_MPSAFE
,
353 NULL
, 0, sysctl_net_inet_tcp_fastopen_ccache_list
, "A",
354 "List of all client cookie cache entries");
356 VNET_DEFINE_STATIC(struct rmlock
, tcp_fastopen_keylock
);
357 #define V_tcp_fastopen_keylock VNET(tcp_fastopen_keylock)
359 #define TCP_FASTOPEN_KEYS_RLOCK(t) rm_rlock(&V_tcp_fastopen_keylock, (t))
360 #define TCP_FASTOPEN_KEYS_RUNLOCK(t) rm_runlock(&V_tcp_fastopen_keylock, (t))
361 #define TCP_FASTOPEN_KEYS_WLOCK() rm_wlock(&V_tcp_fastopen_keylock)
362 #define TCP_FASTOPEN_KEYS_WUNLOCK() rm_wunlock(&V_tcp_fastopen_keylock)
364 VNET_DEFINE_STATIC(struct tcp_fastopen_keylist
, tcp_fastopen_keys
);
365 #define V_tcp_fastopen_keys VNET(tcp_fastopen_keys)
367 VNET_DEFINE_STATIC(struct tcp_fastopen_callout
, tcp_fastopen_autokey_ctx
);
368 #define V_tcp_fastopen_autokey_ctx VNET(tcp_fastopen_autokey_ctx)
370 VNET_DEFINE_STATIC(uma_zone_t
, counter_zone
);
371 #define V_counter_zone VNET(counter_zone)
373 static MALLOC_DEFINE(M_TCP_FASTOPEN_CCACHE
, "tfo_ccache", "TFO client cookie cache buckets");
375 VNET_DEFINE_STATIC(struct tcp_fastopen_ccache
, tcp_fastopen_ccache
);
376 #define V_tcp_fastopen_ccache VNET(tcp_fastopen_ccache)
378 #define CCB_LOCK(ccb) mtx_lock(&(ccb)->ccb_mtx)
379 #define CCB_UNLOCK(ccb) mtx_unlock(&(ccb)->ccb_mtx)
380 #define CCB_LOCK_ASSERT(ccb) mtx_assert(&(ccb)->ccb_mtx, MA_OWNED)
383 tcp_fastopen_init(void)
387 V_counter_zone
= uma_zcreate("tfo", sizeof(unsigned int),
388 NULL
, NULL
, NULL
, NULL
, UMA_ALIGN_PTR
, 0);
389 rm_init(&V_tcp_fastopen_keylock
, "tfo_keylock");
390 callout_init_rm(&V_tcp_fastopen_autokey_ctx
.c
,
391 &V_tcp_fastopen_keylock
, 0);
392 V_tcp_fastopen_autokey_ctx
.v
= curvnet
;
393 V_tcp_fastopen_keys
.newest
= TCP_FASTOPEN_MAX_KEYS
- 1;
394 V_tcp_fastopen_keys
.newest_psk
= TCP_FASTOPEN_MAX_PSKS
- 1;
396 TUNABLE_INT_FETCH("net.inet.tcp.fastopen.ccache_bucket_limit",
397 &V_tcp_fastopen_ccache
.bucket_limit
);
398 if (V_tcp_fastopen_ccache
.bucket_limit
== 0)
399 V_tcp_fastopen_ccache
.bucket_limit
=
400 TCP_FASTOPEN_CCACHE_BUCKET_LIMIT_DEFAULT
;
402 /* May already be non-zero if kernel tunable was set */
403 if ((V_tcp_fastopen_ccache_buckets
== 0) ||
404 !powerof2(V_tcp_fastopen_ccache_buckets
))
405 V_tcp_fastopen_ccache
.buckets
=
406 TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT
;
408 V_tcp_fastopen_ccache
.buckets
= V_tcp_fastopen_ccache_buckets
;
410 V_tcp_fastopen_ccache
.mask
= V_tcp_fastopen_ccache
.buckets
- 1;
411 V_tcp_fastopen_ccache
.secret
= arc4random();
413 V_tcp_fastopen_ccache
.base
= malloc(V_tcp_fastopen_ccache
.buckets
*
414 sizeof(struct tcp_fastopen_ccache_bucket
), M_TCP_FASTOPEN_CCACHE
,
417 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
; i
++) {
418 TAILQ_INIT(&V_tcp_fastopen_ccache
.base
[i
].ccb_entries
);
419 mtx_init(&V_tcp_fastopen_ccache
.base
[i
].ccb_mtx
, "tfo_ccache_bucket",
421 if (V_tcp_fastopen_client_enable
) {
423 V_tcp_fastopen_ccache
.base
[i
].ccb_num_entries
= 0;
426 V_tcp_fastopen_ccache
.base
[i
].ccb_num_entries
= -1;
428 V_tcp_fastopen_ccache
.base
[i
].ccb_ccache
= &V_tcp_fastopen_ccache
;
432 * Note that while the total number of entries in the cookie cache
433 * is limited by the table management logic to
434 * V_tcp_fastopen_ccache.buckets *
435 * V_tcp_fastopen_ccache.bucket_limit, the total number of items in
436 * this zone can exceed that amount by the number of CPUs in the
437 * system times the maximum number of unallocated items that can be
438 * present in each UMA per-CPU cache for this zone.
440 V_tcp_fastopen_ccache
.zone
= uma_zcreate("tfo_ccache_entries",
441 sizeof(struct tcp_fastopen_ccache_entry
), NULL
, NULL
, NULL
, NULL
,
446 tcp_fastopen_destroy(void)
448 struct tcp_fastopen_ccache_bucket
*ccb
;
451 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
; i
++) {
452 ccb
= &V_tcp_fastopen_ccache
.base
[i
];
453 tcp_fastopen_ccache_bucket_trim(ccb
, 0);
454 mtx_destroy(&ccb
->ccb_mtx
);
457 KASSERT(uma_zone_get_cur(V_tcp_fastopen_ccache
.zone
) == 0,
458 ("%s: TFO ccache zone allocation count not 0", __func__
));
459 uma_zdestroy(V_tcp_fastopen_ccache
.zone
);
460 free(V_tcp_fastopen_ccache
.base
, M_TCP_FASTOPEN_CCACHE
);
462 callout_drain(&V_tcp_fastopen_autokey_ctx
.c
);
463 rm_destroy(&V_tcp_fastopen_keylock
);
464 uma_zdestroy(V_counter_zone
);
468 tcp_fastopen_alloc_counter(void)
470 unsigned int *counter
;
471 counter
= uma_zalloc(V_counter_zone
, M_NOWAIT
);
478 tcp_fastopen_decrement_counter(unsigned int *counter
)
481 uma_zfree(V_counter_zone
, counter
);
483 atomic_subtract_int(counter
, 1);
487 tcp_fastopen_addkey_locked(uint8_t *key
)
490 V_tcp_fastopen_keys
.newest
++;
491 if (V_tcp_fastopen_keys
.newest
== TCP_FASTOPEN_MAX_KEYS
)
492 V_tcp_fastopen_keys
.newest
= 0;
493 memcpy(V_tcp_fastopen_keys
.key
[V_tcp_fastopen_keys
.newest
], key
,
494 TCP_FASTOPEN_KEY_LEN
);
495 if (V_tcp_fastopen_numkeys
< TCP_FASTOPEN_MAX_KEYS
)
496 V_tcp_fastopen_numkeys
++;
500 tcp_fastopen_addpsk_locked(uint8_t *psk
)
503 V_tcp_fastopen_keys
.newest_psk
++;
504 if (V_tcp_fastopen_keys
.newest_psk
== TCP_FASTOPEN_MAX_PSKS
)
505 V_tcp_fastopen_keys
.newest_psk
= 0;
506 memcpy(V_tcp_fastopen_keys
.psk
[V_tcp_fastopen_keys
.newest_psk
], psk
,
507 TCP_FASTOPEN_KEY_LEN
);
508 if (V_tcp_fastopen_numpsks
< TCP_FASTOPEN_MAX_PSKS
)
509 V_tcp_fastopen_numpsks
++;
513 tcp_fastopen_autokey_locked(void)
515 uint8_t newkey
[TCP_FASTOPEN_KEY_LEN
];
517 arc4rand(newkey
, TCP_FASTOPEN_KEY_LEN
, 0);
518 tcp_fastopen_addkey_locked(newkey
);
522 tcp_fastopen_autokey_callout(void *arg
)
524 struct tcp_fastopen_callout
*ctx
= arg
;
527 tcp_fastopen_autokey_locked();
528 callout_reset(&ctx
->c
, V_tcp_fastopen_autokey
* hz
,
529 tcp_fastopen_autokey_callout
, ctx
);
534 tcp_fastopen_make_cookie(uint8_t key
[SIPHASH_KEY_LENGTH
], struct in_conninfo
*inc
)
539 SipHash24_Init(&ctx
);
540 SipHash_SetKey(&ctx
, key
);
541 switch (inc
->inc_flags
& INC_ISIPV6
) {
544 SipHash_Update(&ctx
, &inc
->inc_faddr
, sizeof(inc
->inc_faddr
));
549 SipHash_Update(&ctx
, &inc
->inc6_faddr
, sizeof(inc
->inc6_faddr
));
553 SipHash_Final((u_int8_t
*)&siphash
, &ctx
);
559 tcp_fastopen_make_psk_cookie(uint8_t *psk
, uint8_t *cookie
, uint8_t cookie_len
)
564 SipHash24_Init(&ctx
);
565 SipHash_SetKey(&ctx
, psk
);
566 SipHash_Update(&ctx
, cookie
, cookie_len
);
567 SipHash_Final((u_int8_t
*)&psk_cookie
, &ctx
);
573 tcp_fastopen_find_cookie_match_locked(uint8_t *wire_cookie
, uint64_t *cur_cookie
)
575 unsigned int i
, psk_index
;
578 if (V_tcp_fastopen_psk_enable
) {
579 psk_index
= V_tcp_fastopen_keys
.newest_psk
;
580 for (i
= 0; i
< V_tcp_fastopen_numpsks
; i
++) {
582 tcp_fastopen_make_psk_cookie(
583 V_tcp_fastopen_keys
.psk
[psk_index
],
584 (uint8_t *)cur_cookie
,
585 TCP_FASTOPEN_COOKIE_LEN
);
587 if (memcmp(wire_cookie
, &psk_cookie
,
588 TCP_FASTOPEN_COOKIE_LEN
) == 0)
592 psk_index
= TCP_FASTOPEN_MAX_PSKS
- 1;
596 } else if (memcmp(wire_cookie
, cur_cookie
, TCP_FASTOPEN_COOKIE_LEN
) == 0)
604 * -1 the cookie is invalid and no valid cookie is available
605 * 0 the cookie is invalid and the latest cookie has been returned
606 * 1 the cookie is valid and the latest cookie has been returned
609 tcp_fastopen_check_cookie(struct in_conninfo
*inc
, uint8_t *cookie
,
610 unsigned int len
, uint64_t *latest_cookie
)
612 struct rm_priotracker tracker
;
613 unsigned int i
, key_index
;
617 if (V_tcp_fastopen_acceptany
) {
622 TCP_FASTOPEN_KEYS_RLOCK(&tracker
);
623 if (len
!= TCP_FASTOPEN_COOKIE_LEN
) {
624 if (V_tcp_fastopen_numkeys
> 0) {
626 tcp_fastopen_make_cookie(
627 V_tcp_fastopen_keys
.key
[V_tcp_fastopen_keys
.newest
],
636 * Check against each available key, from newest to oldest.
638 key_index
= V_tcp_fastopen_keys
.newest
;
639 for (i
= 0; i
< V_tcp_fastopen_numkeys
; i
++) {
641 tcp_fastopen_make_cookie(V_tcp_fastopen_keys
.key
[key_index
],
644 *latest_cookie
= cur_cookie
;
645 rv
= tcp_fastopen_find_cookie_match_locked(cookie
, &cur_cookie
);
649 key_index
= TCP_FASTOPEN_MAX_KEYS
- 1;
656 TCP_FASTOPEN_KEYS_RUNLOCK(&tracker
);
661 sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS
)
666 new = V_tcp_fastopen_autokey
;
667 error
= sysctl_handle_int(oidp
, &new, 0, req
);
668 if (error
== 0 && req
->newptr
) {
669 if (new > (INT_MAX
/ hz
))
672 TCP_FASTOPEN_KEYS_WLOCK();
673 if (V_tcp_fastopen_server_enable
) {
674 if (V_tcp_fastopen_autokey
&& !new)
675 callout_stop(&V_tcp_fastopen_autokey_ctx
.c
);
677 callout_reset(&V_tcp_fastopen_autokey_ctx
.c
,
678 new * hz
, tcp_fastopen_autokey_callout
,
679 &V_tcp_fastopen_autokey_ctx
);
681 V_tcp_fastopen_autokey
= new;
682 TCP_FASTOPEN_KEYS_WUNLOCK();
689 sysctl_net_inet_tcp_fastopen_psk_enable(SYSCTL_HANDLER_ARGS
)
694 new = V_tcp_fastopen_psk_enable
;
695 error
= sysctl_handle_int(oidp
, &new, 0, req
);
696 if (error
== 0 && req
->newptr
) {
697 if (V_tcp_fastopen_psk_enable
&& !new) {
698 /* enabled -> disabled */
699 TCP_FASTOPEN_KEYS_WLOCK();
700 V_tcp_fastopen_numpsks
= 0;
701 V_tcp_fastopen_keys
.newest_psk
=
702 TCP_FASTOPEN_MAX_PSKS
- 1;
703 V_tcp_fastopen_psk_enable
= 0;
704 TCP_FASTOPEN_KEYS_WUNLOCK();
705 } else if (!V_tcp_fastopen_psk_enable
&& new) {
706 /* disabled -> enabled */
707 TCP_FASTOPEN_KEYS_WLOCK();
708 V_tcp_fastopen_psk_enable
= 1;
709 TCP_FASTOPEN_KEYS_WUNLOCK();
716 sysctl_net_inet_tcp_fastopen_server_enable(SYSCTL_HANDLER_ARGS
)
721 new = V_tcp_fastopen_server_enable
;
722 error
= sysctl_handle_int(oidp
, &new, 0, req
);
723 if (error
== 0 && req
->newptr
) {
724 if (V_tcp_fastopen_server_enable
&& !new) {
725 /* enabled -> disabled */
726 TCP_FASTOPEN_KEYS_WLOCK();
727 V_tcp_fastopen_numkeys
= 0;
728 V_tcp_fastopen_keys
.newest
= TCP_FASTOPEN_MAX_KEYS
- 1;
729 if (V_tcp_fastopen_autokey
)
730 callout_stop(&V_tcp_fastopen_autokey_ctx
.c
);
731 V_tcp_fastopen_numpsks
= 0;
732 V_tcp_fastopen_keys
.newest_psk
=
733 TCP_FASTOPEN_MAX_PSKS
- 1;
734 V_tcp_fastopen_server_enable
= 0;
735 TCP_FASTOPEN_KEYS_WUNLOCK();
736 } else if (!V_tcp_fastopen_server_enable
&& new) {
737 /* disabled -> enabled */
738 TCP_FASTOPEN_KEYS_WLOCK();
739 if (V_tcp_fastopen_autokey
&&
740 (V_tcp_fastopen_numkeys
== 0)) {
741 tcp_fastopen_autokey_locked();
742 callout_reset(&V_tcp_fastopen_autokey_ctx
.c
,
743 V_tcp_fastopen_autokey
* hz
,
744 tcp_fastopen_autokey_callout
,
745 &V_tcp_fastopen_autokey_ctx
);
747 V_tcp_fastopen_server_enable
= 1;
748 TCP_FASTOPEN_KEYS_WUNLOCK();
755 sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS
)
758 uint8_t newkey
[TCP_FASTOPEN_KEY_LEN
];
760 if (req
->oldptr
!= NULL
|| req
->oldlen
!= 0)
762 if (req
->newptr
== NULL
)
764 if (req
->newlen
!= sizeof(newkey
))
766 error
= SYSCTL_IN(req
, newkey
, sizeof(newkey
));
770 TCP_FASTOPEN_KEYS_WLOCK();
771 tcp_fastopen_addkey_locked(newkey
);
772 TCP_FASTOPEN_KEYS_WUNLOCK();
778 sysctl_net_inet_tcp_fastopen_setpsk(SYSCTL_HANDLER_ARGS
)
781 uint8_t newpsk
[TCP_FASTOPEN_KEY_LEN
];
783 if (req
->oldptr
!= NULL
|| req
->oldlen
!= 0)
785 if (req
->newptr
== NULL
)
787 if (req
->newlen
!= sizeof(newpsk
))
789 error
= SYSCTL_IN(req
, newpsk
, sizeof(newpsk
));
793 TCP_FASTOPEN_KEYS_WLOCK();
794 tcp_fastopen_addpsk_locked(newpsk
);
795 TCP_FASTOPEN_KEYS_WUNLOCK();
801 sysctl_net_inet_tcp_fastopen_ccache_bucket_limit(SYSCTL_HANDLER_ARGS
)
803 struct tcp_fastopen_ccache_bucket
*ccb
;
808 new = V_tcp_fastopen_ccache
.bucket_limit
;
809 error
= sysctl_handle_int(oidp
, &new, 0, req
);
810 if (error
== 0 && req
->newptr
) {
811 if ((new == 0) || (new > INT_MAX
))
814 if (new < V_tcp_fastopen_ccache
.bucket_limit
) {
815 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
;
817 ccb
= &V_tcp_fastopen_ccache
.base
[i
];
818 tcp_fastopen_ccache_bucket_trim(ccb
, new);
821 V_tcp_fastopen_ccache
.bucket_limit
= new;
828 sysctl_net_inet_tcp_fastopen_client_enable(SYSCTL_HANDLER_ARGS
)
830 struct tcp_fastopen_ccache_bucket
*ccb
;
834 new = V_tcp_fastopen_client_enable
;
835 error
= sysctl_handle_int(oidp
, &new, 0, req
);
836 if (error
== 0 && req
->newptr
) {
837 if (V_tcp_fastopen_client_enable
&& !new) {
838 /* enabled -> disabled */
839 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
; i
++) {
840 ccb
= &V_tcp_fastopen_ccache
.base
[i
];
841 KASSERT(ccb
->ccb_num_entries
> -1,
842 ("%s: ccb->ccb_num_entries %d is negative",
843 __func__
, ccb
->ccb_num_entries
));
844 tcp_fastopen_ccache_bucket_trim(ccb
, 0);
846 V_tcp_fastopen_client_enable
= 0;
847 } else if (!V_tcp_fastopen_client_enable
&& new) {
848 /* disabled -> enabled */
849 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
; i
++) {
850 ccb
= &V_tcp_fastopen_ccache
.base
[i
];
852 KASSERT(TAILQ_EMPTY(&ccb
->ccb_entries
),
853 ("%s: ccb->ccb_entries not empty", __func__
));
854 KASSERT(ccb
->ccb_num_entries
== -1,
855 ("%s: ccb->ccb_num_entries %d not -1", __func__
,
856 ccb
->ccb_num_entries
));
857 ccb
->ccb_num_entries
= 0; /* enable bucket */
860 V_tcp_fastopen_client_enable
= 1;
867 tcp_fastopen_connect(struct tcpcb
*tp
)
869 struct inpcb
*inp
= tptoinpcb(tp
);
870 struct tcp_fastopen_ccache_bucket
*ccb
;
871 struct tcp_fastopen_ccache_entry
*cce
;
877 cce
= tcp_fastopen_ccache_lookup(&inp
->inp_inc
, &ccb
);
879 if (cce
->disable_time
== 0) {
880 if ((cce
->cookie_len
> 0) &&
881 (tp
->t_tfo_client_cookie_len
==
882 TCP_FASTOPEN_PSK_LEN
)) {
884 tcp_fastopen_make_psk_cookie(
885 tp
->t_tfo_cookie
.client
,
886 cce
->cookie
, cce
->cookie_len
);
888 tp
->t_tfo_client_cookie_len
= cce
->cookie_len
;
889 memcpy(tp
->t_tfo_cookie
.client
, cce
->cookie
,
892 server_mss
= cce
->server_mss
;
894 if (tp
->t_tfo_client_cookie_len
==
895 TCP_FASTOPEN_PSK_LEN
&& psk_cookie
) {
896 tp
->t_tfo_client_cookie_len
=
897 TCP_FASTOPEN_COOKIE_LEN
;
898 memcpy(tp
->t_tfo_cookie
.client
, &psk_cookie
,
899 TCP_FASTOPEN_COOKIE_LEN
);
901 tcp_mss(tp
, server_mss
? server_mss
: -1);
902 tp
->snd_wnd
= tp
->t_maxseg
;
905 * The path is disabled. Check the time and
906 * possibly re-enable.
908 now
= getsbinuptime();
909 if (now
- cce
->disable_time
>
910 ((sbintime_t
)V_tcp_fastopen_path_disable_time
<< 32)) {
912 * Re-enable path. Force a TFO cookie
913 * request. Forget the old MSS as it may be
914 * bogus now, and we will rediscover it in
917 cce
->disable_time
= 0;
921 * tp->t_tfo... cookie details are already
922 * zero from the tcpcb init.
926 * Path is disabled, so disable TFO on this
929 tp
->t_flags
&= ~TF_FASTOPEN
;
934 * snd_wnd is irrelevant since we are either forcing
935 * a TFO cookie request or disabling TFO - either
936 * way, no data with the SYN.
941 * A new entry for this path will be created when a SYN|ACK
942 * comes back, or the attempt otherwise fails.
947 * snd_wnd is irrelevant since we are forcing a TFO cookie
954 tcp_fastopen_disable_path(struct tcpcb
*tp
)
956 struct in_conninfo
*inc
= &tptoinpcb(tp
)->inp_inc
;
957 struct tcp_fastopen_ccache_bucket
*ccb
;
958 struct tcp_fastopen_ccache_entry
*cce
;
960 cce
= tcp_fastopen_ccache_lookup(inc
, &ccb
);
965 * Preserve the existing disable time if it is already
968 if (cce
->disable_time
== 0)
969 cce
->disable_time
= getsbinuptime();
970 } else /* use invalid cookie len to create disabled entry */
971 tcp_fastopen_ccache_create(ccb
, inc
, 0,
972 TCP_FASTOPEN_MAX_COOKIE_LEN
+ 1, NULL
);
975 tp
->t_flags
&= ~TF_FASTOPEN
;
979 tcp_fastopen_update_cache(struct tcpcb
*tp
, uint16_t mss
,
980 uint8_t cookie_len
, uint8_t *cookie
)
982 struct in_conninfo
*inc
= &tptoinpcb(tp
)->inp_inc
;
983 struct tcp_fastopen_ccache_bucket
*ccb
;
984 struct tcp_fastopen_ccache_entry
*cce
;
986 cce
= tcp_fastopen_ccache_lookup(inc
, &ccb
);
988 if ((cookie_len
>= TCP_FASTOPEN_MIN_COOKIE_LEN
) &&
989 (cookie_len
<= TCP_FASTOPEN_MAX_COOKIE_LEN
) &&
990 ((cookie_len
& 0x1) == 0)) {
991 cce
->server_mss
= mss
;
992 cce
->cookie_len
= cookie_len
;
993 memcpy(cce
->cookie
, cookie
, cookie_len
);
994 cce
->disable_time
= 0;
996 /* invalid cookie length, disable entry */
1000 * Preserve the existing disable time if it is
1003 if (cce
->disable_time
== 0)
1004 cce
->disable_time
= getsbinuptime();
1007 tcp_fastopen_ccache_create(ccb
, inc
, mss
, cookie_len
, cookie
);
1012 static struct tcp_fastopen_ccache_entry
*
1013 tcp_fastopen_ccache_lookup(struct in_conninfo
*inc
,
1014 struct tcp_fastopen_ccache_bucket
**ccbp
)
1016 struct tcp_fastopen_ccache_bucket
*ccb
;
1017 struct tcp_fastopen_ccache_entry
*cce
;
1021 hash
= jenkins_hash32((uint32_t *)&inc
->inc_ie
.ie_dependladdr
, 4,
1022 V_tcp_fastopen_ccache
.secret
);
1023 hash
= jenkins_hash32((uint32_t *)&inc
->inc_ie
.ie_dependfaddr
, 4,
1025 last_word
= inc
->inc_fport
;
1026 hash
= jenkins_hash32(&last_word
, 1, hash
);
1027 ccb
= &V_tcp_fastopen_ccache
.base
[hash
& V_tcp_fastopen_ccache
.mask
];
1032 * Always returns with locked bucket.
1034 TAILQ_FOREACH(cce
, &ccb
->ccb_entries
, cce_link
)
1035 if ((!(cce
->af
== AF_INET6
) == !(inc
->inc_flags
& INC_ISIPV6
)) &&
1036 (cce
->server_port
== inc
->inc_ie
.ie_fport
) &&
1037 (((cce
->af
== AF_INET
) &&
1038 (cce
->cce_client_ip
.v4
.s_addr
== inc
->inc_laddr
.s_addr
) &&
1039 (cce
->cce_server_ip
.v4
.s_addr
== inc
->inc_faddr
.s_addr
)) ||
1040 ((cce
->af
== AF_INET6
) &&
1041 IN6_ARE_ADDR_EQUAL(&cce
->cce_client_ip
.v6
, &inc
->inc6_laddr
) &&
1042 IN6_ARE_ADDR_EQUAL(&cce
->cce_server_ip
.v6
, &inc
->inc6_faddr
))))
1048 static struct tcp_fastopen_ccache_entry
*
1049 tcp_fastopen_ccache_create(struct tcp_fastopen_ccache_bucket
*ccb
,
1050 struct in_conninfo
*inc
, uint16_t mss
, uint8_t cookie_len
, uint8_t *cookie
)
1052 struct tcp_fastopen_ccache_entry
*cce
;
1055 * 1. Create a new entry, or
1056 * 2. Reclaim an existing entry, or
1060 CCB_LOCK_ASSERT(ccb
);
1063 if (ccb
->ccb_num_entries
< V_tcp_fastopen_ccache
.bucket_limit
)
1064 cce
= uma_zalloc(V_tcp_fastopen_ccache
.zone
, M_NOWAIT
);
1068 * At bucket limit, or out of memory - reclaim last
1071 cce
= TAILQ_LAST(&ccb
->ccb_entries
, bucket_entries
);
1073 /* XXX count this event */
1077 TAILQ_REMOVE(&ccb
->ccb_entries
, cce
, cce_link
);
1079 ccb
->ccb_num_entries
++;
1081 TAILQ_INSERT_HEAD(&ccb
->ccb_entries
, cce
, cce_link
);
1082 cce
->af
= (inc
->inc_flags
& INC_ISIPV6
) ? AF_INET6
: AF_INET
;
1083 if (cce
->af
== AF_INET
) {
1084 cce
->cce_client_ip
.v4
= inc
->inc_laddr
;
1085 cce
->cce_server_ip
.v4
= inc
->inc_faddr
;
1087 cce
->cce_client_ip
.v6
= inc
->inc6_laddr
;
1088 cce
->cce_server_ip
.v6
= inc
->inc6_faddr
;
1090 cce
->server_port
= inc
->inc_fport
;
1091 if ((cookie_len
>= TCP_FASTOPEN_MIN_COOKIE_LEN
) &&
1092 (cookie_len
<= TCP_FASTOPEN_MAX_COOKIE_LEN
) &&
1093 ((cookie_len
& 0x1) == 0)) {
1094 cce
->server_mss
= mss
;
1095 cce
->cookie_len
= cookie_len
;
1096 memcpy(cce
->cookie
, cookie
, cookie_len
);
1097 cce
->disable_time
= 0;
1099 /* invalid cookie length, disable cce */
1100 cce
->server_mss
= 0;
1101 cce
->cookie_len
= 0;
1102 cce
->disable_time
= getsbinuptime();
1109 tcp_fastopen_ccache_bucket_trim(struct tcp_fastopen_ccache_bucket
*ccb
,
1112 struct tcp_fastopen_ccache_entry
*cce
, *cce_tmp
;
1113 unsigned int entries
;
1117 TAILQ_FOREACH_SAFE(cce
, &ccb
->ccb_entries
, cce_link
, cce_tmp
) {
1119 if (entries
> limit
)
1120 tcp_fastopen_ccache_entry_drop(cce
, ccb
);
1122 KASSERT(ccb
->ccb_num_entries
<= (int)limit
,
1123 ("%s: ccb->ccb_num_entries %d exceeds limit %d", __func__
,
1124 ccb
->ccb_num_entries
, limit
));
1126 KASSERT(TAILQ_EMPTY(&ccb
->ccb_entries
),
1127 ("%s: ccb->ccb_entries not empty", __func__
));
1128 ccb
->ccb_num_entries
= -1; /* disable bucket */
1134 tcp_fastopen_ccache_entry_drop(struct tcp_fastopen_ccache_entry
*cce
,
1135 struct tcp_fastopen_ccache_bucket
*ccb
)
1138 CCB_LOCK_ASSERT(ccb
);
1140 TAILQ_REMOVE(&ccb
->ccb_entries
, cce
, cce_link
);
1141 ccb
->ccb_num_entries
--;
1142 uma_zfree(V_tcp_fastopen_ccache
.zone
, cce
);
1146 sysctl_net_inet_tcp_fastopen_ccache_list(SYSCTL_HANDLER_ARGS
)
1149 struct tcp_fastopen_ccache_bucket
*ccb
;
1150 struct tcp_fastopen_ccache_entry
*cce
;
1151 sbintime_t now
, duration
, limit
;
1152 const int linesize
= 128;
1153 int i
, error
, num_entries
;
1156 char clt_buf
[INET6_ADDRSTRLEN
], srv_buf
[INET6_ADDRSTRLEN
];
1158 char clt_buf
[INET_ADDRSTRLEN
], srv_buf
[INET_ADDRSTRLEN
];
1161 if (jailed_without_vnet(curthread
->td_ucred
) != 0)
1164 /* Only allow root to read the client cookie cache */
1165 if (curthread
->td_ucred
->cr_uid
!= 0)
1169 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
; i
++) {
1170 ccb
= &V_tcp_fastopen_ccache
.base
[i
];
1172 if (ccb
->ccb_num_entries
> 0)
1173 num_entries
+= ccb
->ccb_num_entries
;
1176 sbuf_new(&sb
, NULL
, linesize
* (num_entries
+ 1), SBUF_INCLUDENUL
);
1179 "\nLocal IP address Remote IP address Port MSS"
1180 " Disabled Cookie\n");
1182 now
= getsbinuptime();
1183 limit
= (sbintime_t
)V_tcp_fastopen_path_disable_time
<< 32;
1184 for (i
= 0; i
< V_tcp_fastopen_ccache
.buckets
; i
++) {
1185 ccb
= &V_tcp_fastopen_ccache
.base
[i
];
1187 TAILQ_FOREACH(cce
, &ccb
->ccb_entries
, cce_link
) {
1188 if (cce
->disable_time
!= 0) {
1189 duration
= now
- cce
->disable_time
;
1190 if (limit
>= duration
)
1191 duration
= limit
- duration
;
1197 "%-20s %-20s %5u %5u ",
1198 inet_ntop(cce
->af
, &cce
->cce_client_ip
,
1199 clt_buf
, sizeof(clt_buf
)),
1200 inet_ntop(cce
->af
, &cce
->cce_server_ip
,
1201 srv_buf
, sizeof(srv_buf
)),
1202 ntohs(cce
->server_port
),
1205 sbuf_printf(&sb
, "%7ds ", sbintime_getsec(duration
));
1207 sbuf_printf(&sb
, "%8s ", "No");
1208 for (j
= 0; j
< cce
->cookie_len
; j
++)
1209 sbuf_printf(&sb
, "%02x", cce
->cookie
[j
]);
1210 sbuf_putc(&sb
, '\n');
1214 error
= sbuf_finish(&sb
);
1216 error
= SYSCTL_OUT(req
, sbuf_data(&sb
), sbuf_len(&sb
));