The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/tcp_fastopen.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2015-2017 Patrick Kelsey
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    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.
   13  *
   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
   24  * SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * This is an implementation of TCP Fast Open (TFO) [RFC7413]. To include
   29  * this code, add the following line to your kernel config:
   30  *
   31  * options TCP_RFC7413
   32  *
   33  *
   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
   39  * follows:
   40  *
   41  * options TCP_RFC7413_MAX_KEYS=<num-keys>
   42  *
   43  *
   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 posession 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.
   51  *
   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>).
   57  *
   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:
   62  *
   63  * options TCP_RFC7413_MAX_PSKS=<num-psks>
   64  *
   65  *
   66  * The following TFO-specific sysctls are defined:
   67  *
   68  * net.inet.tcp.fastopen.acceptany (RW, default 0)
   69  *     When non-zero, all client-supplied TFO cookies will be considered to
   70  *     be valid.
   71  *
   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.
   75  *
   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.
   79  *
   80  * net.inet.tcp.fastopen.ccache_buckets
   81  *                          (RDTUN, default TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT)
   82  *     The number of client cookie cache buckets.
   83  *
   84  * net.inet.tcp.fastopen.ccache_list (RO)
   85  *     Print the client cookie cache.
   86  *
   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.
   93  *
   94  * net.inet.tcp.fastopen.keylen (RD)
   95  *     The key length in bytes.
   96  *
   97  * net.inet.tcp.fastopen.maxkeys (RD)
   98  *     The maximum number of keys supported.
   99  *
  100  * net.inet.tcp.fastopen.maxpsks (RD)
  101  *     The maximum number of pre-shared keys supported.
  102  *
  103  * net.inet.tcp.fastopen.numkeys (RD)
  104  *     The current number of keys installed.
  105  *
  106  * net.inet.tcp.fastopen.numpsks (RD)
  107  *     The current number of pre-shared keys installed.
  108  *
  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.
  119  *
  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.
  124  *
  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
  133  *     made.
  134  *
  135  * net.inet.tcp.fastopen.setkey (WR)
  136  *     Install a new key by writing net.inet.tcp.fastopen.keylen bytes to
  137  *     this sysctl.
  138  *
  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.
  142  *
  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.
  149  *
  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
  154  * set.
  155  *
  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.
  163  *
  164  */
  165 
  166 #include <sys/cdefs.h>
  167 __FBSDID("$FreeBSD$");
  168 
  169 #include "opt_inet.h"
  170 
  171 #include <sys/param.h>
  172 #include <sys/jail.h>
  173 #include <sys/kernel.h>
  174 #include <sys/hash.h>
  175 #include <sys/limits.h>
  176 #include <sys/lock.h>
  177 #include <sys/proc.h>
  178 #include <sys/rmlock.h>
  179 #include <sys/sbuf.h>
  180 #include <sys/socket.h>
  181 #include <sys/socketvar.h>
  182 #include <sys/sysctl.h>
  183 #include <sys/systm.h>
  184 
  185 #include <crypto/siphash/siphash.h>
  186 
  187 #include <net/vnet.h>
  188 
  189 #include <netinet/in.h>
  190 #include <netinet/in_pcb.h>
  191 #include <netinet/tcp_var.h>
  192 #include <netinet/tcp_fastopen.h>
  193 
  194 
  195 #define TCP_FASTOPEN_KEY_LEN    SIPHASH_KEY_LENGTH
  196 
  197 #if TCP_FASTOPEN_PSK_LEN != TCP_FASTOPEN_KEY_LEN
  198 #error TCP_FASTOPEN_PSK_LEN must be equal to TCP_FASTOPEN_KEY_LEN
  199 #endif
  200 
  201 /*
  202  * Because a PSK-mode setsockopt() uses tcpcb.t_tfo_cookie.client to hold
  203  * the PSK until the connect occurs.
  204  */
  205 #if TCP_FASTOPEN_MAX_COOKIE_LEN < TCP_FASTOPEN_PSK_LEN
  206 #error TCP_FASTOPEN_MAX_COOKIE_LEN must be >= TCP_FASTOPEN_PSK_LEN
  207 #endif
  208 
  209 #define TCP_FASTOPEN_CCACHE_BUCKET_LIMIT_DEFAULT        16
  210 #define TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT             2048 /* must be power of 2 */
  211 
  212 #define TCP_FASTOPEN_PATH_DISABLE_TIME_DEFAULT          900 /* seconds */
  213 
  214 #if !defined(TCP_RFC7413_MAX_KEYS) || (TCP_RFC7413_MAX_KEYS < 1)
  215 #define TCP_FASTOPEN_MAX_KEYS   2
  216 #else
  217 #define TCP_FASTOPEN_MAX_KEYS   TCP_RFC7413_MAX_KEYS
  218 #endif
  219 
  220 #if TCP_FASTOPEN_MAX_KEYS > 10
  221 #undef TCP_FASTOPEN_MAX_KEYS
  222 #define TCP_FASTOPEN_MAX_KEYS   10
  223 #endif
  224 
  225 #if !defined(TCP_RFC7413_MAX_PSKS) || (TCP_RFC7413_MAX_PSKS < 1)
  226 #define TCP_FASTOPEN_MAX_PSKS   2
  227 #else
  228 #define TCP_FASTOPEN_MAX_PSKS   TCP_RFC7413_MAX_PSKS
  229 #endif
  230 
  231 #if TCP_FASTOPEN_MAX_PSKS > 10
  232 #undef TCP_FASTOPEN_MAX_PSKS
  233 #define TCP_FASTOPEN_MAX_PSKS   10
  234 #endif
  235 
  236 struct tcp_fastopen_keylist {
  237         unsigned int newest;
  238         unsigned int newest_psk;
  239         uint8_t key[TCP_FASTOPEN_MAX_KEYS][TCP_FASTOPEN_KEY_LEN];
  240         uint8_t psk[TCP_FASTOPEN_MAX_PSKS][TCP_FASTOPEN_KEY_LEN];
  241 };
  242 
  243 struct tcp_fastopen_callout {
  244         struct callout c;
  245         struct vnet *v;
  246 };
  247 
  248 static struct tcp_fastopen_ccache_entry *tcp_fastopen_ccache_lookup(
  249     struct in_conninfo *, struct tcp_fastopen_ccache_bucket **);
  250 static struct tcp_fastopen_ccache_entry *tcp_fastopen_ccache_create(
  251     struct tcp_fastopen_ccache_bucket *, struct in_conninfo *, uint16_t, uint8_t,
  252     uint8_t *);
  253 static void tcp_fastopen_ccache_bucket_trim(struct tcp_fastopen_ccache_bucket *,
  254     unsigned int);
  255 static void tcp_fastopen_ccache_entry_drop(struct tcp_fastopen_ccache_entry *,
  256     struct tcp_fastopen_ccache_bucket *);
  257 
  258 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, fastopen, CTLFLAG_RW, 0, "TCP Fast Open");
  259 
  260 VNET_DEFINE_STATIC(int, tcp_fastopen_acceptany) = 0;
  261 #define V_tcp_fastopen_acceptany        VNET(tcp_fastopen_acceptany)
  262 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, acceptany,
  263     CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_fastopen_acceptany), 0,
  264     "Accept any non-empty cookie");
  265 
  266 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_autokey) = 120;
  267 #define V_tcp_fastopen_autokey  VNET(tcp_fastopen_autokey)
  268 static int sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS);
  269 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, autokey,
  270     CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
  271     &sysctl_net_inet_tcp_fastopen_autokey, "IU",
  272     "Number of seconds between auto-generation of a new key; zero disables");
  273 
  274 static int sysctl_net_inet_tcp_fastopen_ccache_bucket_limit(SYSCTL_HANDLER_ARGS);
  275 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, ccache_bucket_limit,
  276     CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RWTUN, NULL, 0,
  277     &sysctl_net_inet_tcp_fastopen_ccache_bucket_limit, "IU",
  278     "Max entries per bucket in client cookie cache");
  279 
  280 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_ccache_buckets) =
  281     TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT;
  282 #define V_tcp_fastopen_ccache_buckets VNET(tcp_fastopen_ccache_buckets)
  283 SYSCTL_UINT(_net_inet_tcp_fastopen, OID_AUTO, ccache_buckets,
  284     CTLFLAG_VNET | CTLFLAG_RDTUN, &VNET_NAME(tcp_fastopen_ccache_buckets), 0,
  285     "Client cookie cache number of buckets (power of 2)");
  286 
  287 VNET_DEFINE(unsigned int, tcp_fastopen_client_enable) = 1;
  288 static int sysctl_net_inet_tcp_fastopen_client_enable(SYSCTL_HANDLER_ARGS);
  289 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, client_enable,
  290     CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
  291     &sysctl_net_inet_tcp_fastopen_client_enable, "IU",
  292     "Enable/disable TCP Fast Open client functionality");
  293 
  294 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, keylen,
  295     CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_KEY_LEN,
  296     "Key length in bytes");
  297 
  298 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, maxkeys,
  299     CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_MAX_KEYS,
  300     "Maximum number of keys supported");
  301 
  302 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, maxpsks,
  303     CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_MAX_PSKS,
  304     "Maximum number of pre-shared keys supported");
  305 
  306 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_numkeys) = 0;
  307 #define V_tcp_fastopen_numkeys  VNET(tcp_fastopen_numkeys)
  308 SYSCTL_UINT(_net_inet_tcp_fastopen, OID_AUTO, numkeys,
  309     CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(tcp_fastopen_numkeys), 0,
  310     "Number of keys installed");
  311 
  312 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_numpsks) = 0;
  313 #define V_tcp_fastopen_numpsks  VNET(tcp_fastopen_numpsks)
  314 SYSCTL_UINT(_net_inet_tcp_fastopen, OID_AUTO, numpsks,
  315     CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(tcp_fastopen_numpsks), 0,
  316     "Number of pre-shared keys installed");
  317 
  318 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_path_disable_time) =
  319     TCP_FASTOPEN_PATH_DISABLE_TIME_DEFAULT;
  320 #define V_tcp_fastopen_path_disable_time VNET(tcp_fastopen_path_disable_time)
  321 SYSCTL_UINT(_net_inet_tcp_fastopen, OID_AUTO, path_disable_time,
  322     CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_fastopen_path_disable_time), 0,
  323     "Seconds a TFO failure disables a {client_ip, server_ip, server_port} path");
  324 
  325 VNET_DEFINE_STATIC(unsigned int, tcp_fastopen_psk_enable) = 0;
  326 #define V_tcp_fastopen_psk_enable       VNET(tcp_fastopen_psk_enable)
  327 static int sysctl_net_inet_tcp_fastopen_psk_enable(SYSCTL_HANDLER_ARGS);
  328 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, psk_enable,
  329     CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
  330     &sysctl_net_inet_tcp_fastopen_psk_enable, "IU",
  331     "Enable/disable TCP Fast Open server pre-shared key mode");
  332 
  333 VNET_DEFINE(unsigned int, tcp_fastopen_server_enable) = 0;
  334 static int sysctl_net_inet_tcp_fastopen_server_enable(SYSCTL_HANDLER_ARGS);
  335 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, server_enable,
  336     CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
  337     &sysctl_net_inet_tcp_fastopen_server_enable, "IU",
  338     "Enable/disable TCP Fast Open server functionality");
  339 
  340 static int sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS);
  341 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, setkey,
  342     CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_WR, NULL, 0,
  343     &sysctl_net_inet_tcp_fastopen_setkey, "",
  344     "Install a new key");
  345 
  346 static int sysctl_net_inet_tcp_fastopen_setpsk(SYSCTL_HANDLER_ARGS);
  347 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, setpsk,
  348     CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_WR, NULL, 0,
  349     &sysctl_net_inet_tcp_fastopen_setpsk, "",
  350     "Install a new pre-shared key");
  351 
  352 static int sysctl_net_inet_tcp_fastopen_ccache_list(SYSCTL_HANDLER_ARGS);
  353 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, ccache_list,
  354     CTLFLAG_VNET | CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP, NULL, 0,
  355     sysctl_net_inet_tcp_fastopen_ccache_list, "A",
  356     "List of all client cookie cache entries");
  357 
  358 VNET_DEFINE_STATIC(struct rmlock, tcp_fastopen_keylock);
  359 #define V_tcp_fastopen_keylock  VNET(tcp_fastopen_keylock)
  360 
  361 #define TCP_FASTOPEN_KEYS_RLOCK(t)      rm_rlock(&V_tcp_fastopen_keylock, (t))
  362 #define TCP_FASTOPEN_KEYS_RUNLOCK(t)    rm_runlock(&V_tcp_fastopen_keylock, (t))
  363 #define TCP_FASTOPEN_KEYS_WLOCK()       rm_wlock(&V_tcp_fastopen_keylock)
  364 #define TCP_FASTOPEN_KEYS_WUNLOCK()     rm_wunlock(&V_tcp_fastopen_keylock)
  365 
  366 VNET_DEFINE_STATIC(struct tcp_fastopen_keylist, tcp_fastopen_keys);
  367 #define V_tcp_fastopen_keys     VNET(tcp_fastopen_keys)
  368 
  369 VNET_DEFINE_STATIC(struct tcp_fastopen_callout, tcp_fastopen_autokey_ctx);
  370 #define V_tcp_fastopen_autokey_ctx      VNET(tcp_fastopen_autokey_ctx)
  371 
  372 VNET_DEFINE_STATIC(uma_zone_t, counter_zone);
  373 #define V_counter_zone                  VNET(counter_zone)
  374 
  375 static MALLOC_DEFINE(M_TCP_FASTOPEN_CCACHE, "tfo_ccache", "TFO client cookie cache buckets");
  376 
  377 VNET_DEFINE_STATIC(struct tcp_fastopen_ccache, tcp_fastopen_ccache);
  378 #define V_tcp_fastopen_ccache   VNET(tcp_fastopen_ccache)
  379 
  380 #define CCB_LOCK(ccb)           mtx_lock(&(ccb)->ccb_mtx)
  381 #define CCB_UNLOCK(ccb)         mtx_unlock(&(ccb)->ccb_mtx)
  382 #define CCB_LOCK_ASSERT(ccb)    mtx_assert(&(ccb)->ccb_mtx, MA_OWNED)
  383 
  384 
  385 void
  386 tcp_fastopen_init(void)
  387 {
  388         unsigned int i;
  389         
  390         V_counter_zone = uma_zcreate("tfo", sizeof(unsigned int),
  391             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  392         rm_init(&V_tcp_fastopen_keylock, "tfo_keylock");
  393         callout_init_rm(&V_tcp_fastopen_autokey_ctx.c,
  394             &V_tcp_fastopen_keylock, 0);
  395         V_tcp_fastopen_autokey_ctx.v = curvnet;
  396         V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
  397         V_tcp_fastopen_keys.newest_psk = TCP_FASTOPEN_MAX_PSKS - 1;
  398 
  399         /* May already be non-zero if kernel tunable was set */
  400         if (V_tcp_fastopen_ccache.bucket_limit == 0)
  401                 V_tcp_fastopen_ccache.bucket_limit =
  402                     TCP_FASTOPEN_CCACHE_BUCKET_LIMIT_DEFAULT;
  403 
  404         /* May already be non-zero if kernel tunable was set */
  405         if ((V_tcp_fastopen_ccache_buckets == 0) ||
  406             !powerof2(V_tcp_fastopen_ccache_buckets))
  407                 V_tcp_fastopen_ccache.buckets =
  408                         TCP_FASTOPEN_CCACHE_BUCKETS_DEFAULT;
  409         else
  410                 V_tcp_fastopen_ccache.buckets = V_tcp_fastopen_ccache_buckets;
  411 
  412         V_tcp_fastopen_ccache.mask = V_tcp_fastopen_ccache.buckets - 1;
  413         V_tcp_fastopen_ccache.secret = arc4random();
  414 
  415         V_tcp_fastopen_ccache.base = malloc(V_tcp_fastopen_ccache.buckets *
  416             sizeof(struct tcp_fastopen_ccache_bucket), M_TCP_FASTOPEN_CCACHE,
  417             M_WAITOK | M_ZERO);
  418 
  419         for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) {
  420                 TAILQ_INIT(&V_tcp_fastopen_ccache.base[i].ccb_entries);
  421                 mtx_init(&V_tcp_fastopen_ccache.base[i].ccb_mtx, "tfo_ccache_bucket",
  422                          NULL, MTX_DEF);
  423                 if (V_tcp_fastopen_client_enable) {
  424                         /* enable bucket */
  425                         V_tcp_fastopen_ccache.base[i].ccb_num_entries = 0;
  426                 } else {
  427                         /* disable bucket */
  428                         V_tcp_fastopen_ccache.base[i].ccb_num_entries = -1;
  429                 }
  430                 V_tcp_fastopen_ccache.base[i].ccb_ccache = &V_tcp_fastopen_ccache;
  431         }
  432 
  433         /*
  434          * Note that while the total number of entries in the cookie cache
  435          * is limited by the table management logic to
  436          * V_tcp_fastopen_ccache.buckets *
  437          * V_tcp_fastopen_ccache.bucket_limit, the total number of items in
  438          * this zone can exceed that amount by the number of CPUs in the
  439          * system times the maximum number of unallocated items that can be
  440          * present in each UMA per-CPU cache for this zone.
  441          */
  442         V_tcp_fastopen_ccache.zone = uma_zcreate("tfo_ccache_entries",
  443             sizeof(struct tcp_fastopen_ccache_entry), NULL, NULL, NULL, NULL,
  444             UMA_ALIGN_CACHE, 0);
  445 }
  446 
  447 void
  448 tcp_fastopen_destroy(void)
  449 {
  450         struct tcp_fastopen_ccache_bucket *ccb;
  451         unsigned int i;
  452 
  453         for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) {           
  454                 ccb = &V_tcp_fastopen_ccache.base[i];
  455                 tcp_fastopen_ccache_bucket_trim(ccb, 0);
  456                 mtx_destroy(&ccb->ccb_mtx);
  457         }
  458 
  459         KASSERT(uma_zone_get_cur(V_tcp_fastopen_ccache.zone) == 0,
  460             ("%s: TFO ccache zone allocation count not 0", __func__));
  461         uma_zdestroy(V_tcp_fastopen_ccache.zone);
  462         free(V_tcp_fastopen_ccache.base, M_TCP_FASTOPEN_CCACHE);
  463 
  464         callout_drain(&V_tcp_fastopen_autokey_ctx.c);
  465         rm_destroy(&V_tcp_fastopen_keylock);
  466         uma_zdestroy(V_counter_zone);
  467 }
  468 
  469 unsigned int *
  470 tcp_fastopen_alloc_counter(void)
  471 {
  472         unsigned int *counter;
  473         counter = uma_zalloc(V_counter_zone, M_NOWAIT);
  474         if (counter)
  475                 *counter = 1;
  476         return (counter);
  477 }
  478 
  479 void
  480 tcp_fastopen_decrement_counter(unsigned int *counter)
  481 {
  482         if (*counter == 1)
  483                 uma_zfree(V_counter_zone, counter);
  484         else
  485                 atomic_subtract_int(counter, 1);
  486 }
  487 
  488 static void
  489 tcp_fastopen_addkey_locked(uint8_t *key)
  490 {
  491 
  492         V_tcp_fastopen_keys.newest++;
  493         if (V_tcp_fastopen_keys.newest == TCP_FASTOPEN_MAX_KEYS)
  494                 V_tcp_fastopen_keys.newest = 0;
  495         memcpy(V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest], key,
  496             TCP_FASTOPEN_KEY_LEN);
  497         if (V_tcp_fastopen_numkeys < TCP_FASTOPEN_MAX_KEYS)
  498                 V_tcp_fastopen_numkeys++;
  499 }
  500 
  501 static void
  502 tcp_fastopen_addpsk_locked(uint8_t *psk)
  503 {
  504 
  505         V_tcp_fastopen_keys.newest_psk++;
  506         if (V_tcp_fastopen_keys.newest_psk == TCP_FASTOPEN_MAX_PSKS)
  507                 V_tcp_fastopen_keys.newest_psk = 0;
  508         memcpy(V_tcp_fastopen_keys.psk[V_tcp_fastopen_keys.newest_psk], psk,
  509             TCP_FASTOPEN_KEY_LEN);
  510         if (V_tcp_fastopen_numpsks < TCP_FASTOPEN_MAX_PSKS)
  511                 V_tcp_fastopen_numpsks++;
  512 }
  513 
  514 static void
  515 tcp_fastopen_autokey_locked(void)
  516 {
  517         uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
  518 
  519         arc4rand(newkey, TCP_FASTOPEN_KEY_LEN, 0);
  520         tcp_fastopen_addkey_locked(newkey);
  521 }
  522 
  523 static void
  524 tcp_fastopen_autokey_callout(void *arg)
  525 {
  526         struct tcp_fastopen_callout *ctx = arg;
  527 
  528         CURVNET_SET(ctx->v);
  529         tcp_fastopen_autokey_locked();
  530         callout_reset(&ctx->c, V_tcp_fastopen_autokey * hz,
  531                       tcp_fastopen_autokey_callout, ctx);
  532         CURVNET_RESTORE();
  533 }
  534 
  535 
  536 static uint64_t
  537 tcp_fastopen_make_cookie(uint8_t key[SIPHASH_KEY_LENGTH], struct in_conninfo *inc)
  538 {
  539         SIPHASH_CTX ctx;
  540         uint64_t siphash;
  541 
  542         SipHash24_Init(&ctx);
  543         SipHash_SetKey(&ctx, key);
  544         switch (inc->inc_flags & INC_ISIPV6) {
  545 #ifdef INET
  546         case 0:
  547                 SipHash_Update(&ctx, &inc->inc_faddr, sizeof(inc->inc_faddr));
  548                 break;
  549 #endif
  550 #ifdef INET6
  551         case INC_ISIPV6:
  552                 SipHash_Update(&ctx, &inc->inc6_faddr, sizeof(inc->inc6_faddr));
  553                 break;
  554 #endif
  555         }
  556         SipHash_Final((u_int8_t *)&siphash, &ctx);
  557 
  558         return (siphash);
  559 }
  560 
  561 static uint64_t
  562 tcp_fastopen_make_psk_cookie(uint8_t *psk, uint8_t *cookie, uint8_t cookie_len)
  563 {
  564         SIPHASH_CTX ctx;
  565         uint64_t psk_cookie;
  566 
  567         SipHash24_Init(&ctx);
  568         SipHash_SetKey(&ctx, psk);
  569         SipHash_Update(&ctx, cookie, cookie_len);
  570         SipHash_Final((u_int8_t *)&psk_cookie, &ctx);
  571 
  572         return (psk_cookie);
  573 }
  574 
  575 static int
  576 tcp_fastopen_find_cookie_match_locked(uint8_t *wire_cookie, uint64_t *cur_cookie)
  577 {
  578         unsigned int i, psk_index;
  579         uint64_t psk_cookie;
  580 
  581         if (V_tcp_fastopen_psk_enable) {
  582                 psk_index = V_tcp_fastopen_keys.newest_psk;
  583                 for (i = 0; i < V_tcp_fastopen_numpsks; i++) {
  584                         psk_cookie =
  585                             tcp_fastopen_make_psk_cookie(
  586                                  V_tcp_fastopen_keys.psk[psk_index],
  587                                  (uint8_t *)cur_cookie,
  588                                  TCP_FASTOPEN_COOKIE_LEN);
  589 
  590                         if (memcmp(wire_cookie, &psk_cookie,
  591                                    TCP_FASTOPEN_COOKIE_LEN) == 0)
  592                                 return (1);
  593 
  594                         if (psk_index == 0)
  595                                 psk_index = TCP_FASTOPEN_MAX_PSKS - 1;
  596                         else
  597                                 psk_index--;
  598                 }
  599         } else if (memcmp(wire_cookie, cur_cookie, TCP_FASTOPEN_COOKIE_LEN) == 0)
  600                 return (1);
  601 
  602         return (0);
  603 }
  604 
  605 /*
  606  * Return values:
  607  *      -1      the cookie is invalid and no valid cookie is available
  608  *       0      the cookie is invalid and the latest cookie has been returned
  609  *       1      the cookie is valid and the latest cookie has been returned
  610  */
  611 int
  612 tcp_fastopen_check_cookie(struct in_conninfo *inc, uint8_t *cookie,
  613     unsigned int len, uint64_t *latest_cookie)
  614 {
  615         struct rm_priotracker tracker;
  616         unsigned int i, key_index;
  617         int rv;
  618         uint64_t cur_cookie;
  619 
  620         if (V_tcp_fastopen_acceptany) {
  621                 *latest_cookie = 0;
  622                 return (1);
  623         }
  624 
  625         TCP_FASTOPEN_KEYS_RLOCK(&tracker);
  626         if (len != TCP_FASTOPEN_COOKIE_LEN) {
  627                 if (V_tcp_fastopen_numkeys > 0) {
  628                         *latest_cookie =
  629                             tcp_fastopen_make_cookie(
  630                                 V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest],
  631                                 inc);
  632                         rv = 0;
  633                 } else
  634                         rv = -1;
  635                 goto out;
  636         }
  637 
  638         /*
  639          * Check against each available key, from newest to oldest.
  640          */
  641         key_index = V_tcp_fastopen_keys.newest;
  642         for (i = 0; i < V_tcp_fastopen_numkeys; i++) {
  643                 cur_cookie =
  644                     tcp_fastopen_make_cookie(V_tcp_fastopen_keys.key[key_index],
  645                         inc);
  646                 if (i == 0)
  647                         *latest_cookie = cur_cookie;
  648                 rv = tcp_fastopen_find_cookie_match_locked(cookie, &cur_cookie);
  649                 if (rv)
  650                         goto out;
  651                 if (key_index == 0)
  652                         key_index = TCP_FASTOPEN_MAX_KEYS - 1;
  653                 else
  654                         key_index--;
  655         }
  656         rv = 0;
  657 
  658  out:
  659         TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
  660         return (rv);
  661 }
  662 
  663 static int
  664 sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS)
  665 {
  666         int error;
  667         unsigned int new;
  668 
  669         new = V_tcp_fastopen_autokey;
  670         error = sysctl_handle_int(oidp, &new, 0, req);
  671         if (error == 0 && req->newptr) {
  672                 if (new > (INT_MAX / hz))
  673                         return (EINVAL);
  674 
  675                 TCP_FASTOPEN_KEYS_WLOCK();
  676                 if (V_tcp_fastopen_server_enable) {
  677                         if (V_tcp_fastopen_autokey && !new)
  678                                 callout_stop(&V_tcp_fastopen_autokey_ctx.c);
  679                         else if (new)
  680                                 callout_reset(&V_tcp_fastopen_autokey_ctx.c,
  681                                     new * hz, tcp_fastopen_autokey_callout,
  682                                     &V_tcp_fastopen_autokey_ctx);
  683                 }
  684                 V_tcp_fastopen_autokey = new;
  685                 TCP_FASTOPEN_KEYS_WUNLOCK();
  686         }
  687 
  688         return (error);
  689 }
  690 
  691 static int
  692 sysctl_net_inet_tcp_fastopen_psk_enable(SYSCTL_HANDLER_ARGS)
  693 {
  694         int error;
  695         unsigned int new;
  696 
  697         new = V_tcp_fastopen_psk_enable;
  698         error = sysctl_handle_int(oidp, &new, 0, req);
  699         if (error == 0 && req->newptr) {
  700                 if (V_tcp_fastopen_psk_enable && !new) {
  701                         /* enabled -> disabled */
  702                         TCP_FASTOPEN_KEYS_WLOCK();
  703                         V_tcp_fastopen_numpsks = 0;
  704                         V_tcp_fastopen_keys.newest_psk =
  705                             TCP_FASTOPEN_MAX_PSKS - 1;
  706                         V_tcp_fastopen_psk_enable = 0;
  707                         TCP_FASTOPEN_KEYS_WUNLOCK();
  708                 } else if (!V_tcp_fastopen_psk_enable && new) {
  709                         /* disabled -> enabled */
  710                         TCP_FASTOPEN_KEYS_WLOCK();
  711                         V_tcp_fastopen_psk_enable = 1;
  712                         TCP_FASTOPEN_KEYS_WUNLOCK();
  713                 }
  714         }
  715         return (error);
  716 }
  717 
  718 static int
  719 sysctl_net_inet_tcp_fastopen_server_enable(SYSCTL_HANDLER_ARGS)
  720 {
  721         int error;
  722         unsigned int new;
  723 
  724         new = V_tcp_fastopen_server_enable;
  725         error = sysctl_handle_int(oidp, &new, 0, req);
  726         if (error == 0 && req->newptr) {
  727                 if (V_tcp_fastopen_server_enable && !new) {
  728                         /* enabled -> disabled */
  729                         TCP_FASTOPEN_KEYS_WLOCK();
  730                         V_tcp_fastopen_numkeys = 0;
  731                         V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
  732                         if (V_tcp_fastopen_autokey)
  733                                 callout_stop(&V_tcp_fastopen_autokey_ctx.c);
  734                         V_tcp_fastopen_numpsks = 0;
  735                         V_tcp_fastopen_keys.newest_psk =
  736                             TCP_FASTOPEN_MAX_PSKS - 1;
  737                         V_tcp_fastopen_server_enable = 0;
  738                         TCP_FASTOPEN_KEYS_WUNLOCK();
  739                 } else if (!V_tcp_fastopen_server_enable && new) {
  740                         /* disabled -> enabled */
  741                         TCP_FASTOPEN_KEYS_WLOCK();
  742                         if (V_tcp_fastopen_autokey &&
  743                             (V_tcp_fastopen_numkeys == 0)) {
  744                                 tcp_fastopen_autokey_locked();
  745                                 callout_reset(&V_tcp_fastopen_autokey_ctx.c,
  746                                     V_tcp_fastopen_autokey * hz,
  747                                     tcp_fastopen_autokey_callout,
  748                                     &V_tcp_fastopen_autokey_ctx);
  749                         }
  750                         V_tcp_fastopen_server_enable = 1;
  751                         TCP_FASTOPEN_KEYS_WUNLOCK();
  752                 }
  753         }
  754         return (error);
  755 }
  756 
  757 static int
  758 sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS)
  759 {
  760         int error;
  761         uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
  762 
  763         if (req->oldptr != NULL || req->oldlen != 0)
  764                 return (EINVAL);
  765         if (req->newptr == NULL)
  766                 return (EPERM);
  767         if (req->newlen != sizeof(newkey))
  768                 return (EINVAL);
  769         error = SYSCTL_IN(req, newkey, sizeof(newkey));
  770         if (error)
  771                 return (error);
  772 
  773         TCP_FASTOPEN_KEYS_WLOCK();
  774         tcp_fastopen_addkey_locked(newkey);
  775         TCP_FASTOPEN_KEYS_WUNLOCK();
  776 
  777         return (0);
  778 }
  779 
  780 static int
  781 sysctl_net_inet_tcp_fastopen_setpsk(SYSCTL_HANDLER_ARGS)
  782 {
  783         int error;
  784         uint8_t newpsk[TCP_FASTOPEN_KEY_LEN];
  785 
  786         if (req->oldptr != NULL || req->oldlen != 0)
  787                 return (EINVAL);
  788         if (req->newptr == NULL)
  789                 return (EPERM);
  790         if (req->newlen != sizeof(newpsk))
  791                 return (EINVAL);
  792         error = SYSCTL_IN(req, newpsk, sizeof(newpsk));
  793         if (error)
  794                 return (error);
  795 
  796         TCP_FASTOPEN_KEYS_WLOCK();
  797         tcp_fastopen_addpsk_locked(newpsk);
  798         TCP_FASTOPEN_KEYS_WUNLOCK();
  799 
  800         return (0);
  801 }
  802 
  803 static int
  804 sysctl_net_inet_tcp_fastopen_ccache_bucket_limit(SYSCTL_HANDLER_ARGS)
  805 {
  806         struct tcp_fastopen_ccache_bucket *ccb;
  807         int error;
  808         unsigned int new;
  809         unsigned int i;
  810         
  811         new = V_tcp_fastopen_ccache.bucket_limit;
  812         error = sysctl_handle_int(oidp, &new, 0, req);
  813         if (error == 0 && req->newptr) {
  814                 if ((new == 0) || (new > INT_MAX))
  815                         error = EINVAL;
  816                 else {
  817                         if (new < V_tcp_fastopen_ccache.bucket_limit) {
  818                                 for (i = 0; i < V_tcp_fastopen_ccache.buckets;
  819                                      i++) {
  820                                         ccb = &V_tcp_fastopen_ccache.base[i];
  821                                         tcp_fastopen_ccache_bucket_trim(ccb, new);
  822                                 }
  823                         }
  824                         V_tcp_fastopen_ccache.bucket_limit = new;
  825                 }
  826                         
  827         }
  828         return (error);
  829 }
  830 
  831 static int
  832 sysctl_net_inet_tcp_fastopen_client_enable(SYSCTL_HANDLER_ARGS)
  833 {
  834         struct tcp_fastopen_ccache_bucket *ccb;
  835         int error;
  836         unsigned int new, i;
  837 
  838         new = V_tcp_fastopen_client_enable;
  839         error = sysctl_handle_int(oidp, &new, 0, req);
  840         if (error == 0 && req->newptr) {
  841                 if (V_tcp_fastopen_client_enable && !new) {
  842                         /* enabled -> disabled */
  843                         for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) {
  844                                 ccb = &V_tcp_fastopen_ccache.base[i];
  845                                 KASSERT(ccb->ccb_num_entries > -1,
  846                                     ("%s: ccb->ccb_num_entries %d is negative",
  847                                         __func__, ccb->ccb_num_entries));
  848                                 tcp_fastopen_ccache_bucket_trim(ccb, 0);
  849                         }
  850                         V_tcp_fastopen_client_enable = 0;
  851                 } else if (!V_tcp_fastopen_client_enable && new) {
  852                         /* disabled -> enabled */
  853                         for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) {
  854                                 ccb = &V_tcp_fastopen_ccache.base[i];
  855                                 CCB_LOCK(ccb);
  856                                 KASSERT(TAILQ_EMPTY(&ccb->ccb_entries),
  857                                     ("%s: ccb->ccb_entries not empty", __func__));
  858                                 KASSERT(ccb->ccb_num_entries == -1,
  859                                     ("%s: ccb->ccb_num_entries %d not -1", __func__,
  860                                         ccb->ccb_num_entries));
  861                                 ccb->ccb_num_entries = 0; /* enable bucket */
  862                                 CCB_UNLOCK(ccb);
  863                         }                       
  864                         V_tcp_fastopen_client_enable = 1;
  865                 }
  866         }
  867         return (error);
  868 }
  869 
  870 void
  871 tcp_fastopen_connect(struct tcpcb *tp)
  872 {
  873         struct inpcb *inp;
  874         struct tcp_fastopen_ccache_bucket *ccb;
  875         struct tcp_fastopen_ccache_entry *cce;
  876         sbintime_t now;
  877         uint16_t server_mss;
  878         uint64_t psk_cookie;
  879         
  880         psk_cookie = 0;
  881         inp = tp->t_inpcb;
  882         cce = tcp_fastopen_ccache_lookup(&inp->inp_inc, &ccb);
  883         if (cce) {
  884                 if (cce->disable_time == 0) {
  885                         if ((cce->cookie_len > 0) &&
  886                             (tp->t_tfo_client_cookie_len ==
  887                              TCP_FASTOPEN_PSK_LEN)) {
  888                                 psk_cookie =
  889                                     tcp_fastopen_make_psk_cookie(
  890                                         tp->t_tfo_cookie.client,
  891                                         cce->cookie, cce->cookie_len);
  892                         } else {
  893                                 tp->t_tfo_client_cookie_len = cce->cookie_len;
  894                                 memcpy(tp->t_tfo_cookie.client, cce->cookie,
  895                                     cce->cookie_len);
  896                         }
  897                         server_mss = cce->server_mss;
  898                         CCB_UNLOCK(ccb);
  899                         if (tp->t_tfo_client_cookie_len ==
  900                             TCP_FASTOPEN_PSK_LEN && psk_cookie) {
  901                                 tp->t_tfo_client_cookie_len =
  902                                     TCP_FASTOPEN_COOKIE_LEN;
  903                                 memcpy(tp->t_tfo_cookie.client, &psk_cookie,
  904                                     TCP_FASTOPEN_COOKIE_LEN);
  905                         }
  906                         tcp_mss(tp, server_mss ? server_mss : -1);
  907                         tp->snd_wnd = tp->t_maxseg;
  908                 } else {
  909                         /*
  910                          * The path is disabled.  Check the time and
  911                          * possibly re-enable.
  912                          */
  913                         now = getsbinuptime();
  914                         if (now - cce->disable_time >
  915                             ((sbintime_t)V_tcp_fastopen_path_disable_time << 32)) {
  916                                 /*
  917                                  * Re-enable path.  Force a TFO cookie
  918                                  * request.  Forget the old MSS as it may be
  919                                  * bogus now, and we will rediscover it in
  920                                  * the SYN|ACK.
  921                                  */
  922                                 cce->disable_time = 0;
  923                                 cce->server_mss = 0;
  924                                 cce->cookie_len = 0;
  925                                 /*
  926                                  * tp->t_tfo... cookie details are already
  927                                  * zero from the tcpcb init.
  928                                  */
  929                         } else {
  930                                 /*
  931                                  * Path is disabled, so disable TFO on this
  932                                  * connection.
  933                                  */
  934                                 tp->t_flags &= ~TF_FASTOPEN;
  935                         }
  936                         CCB_UNLOCK(ccb);
  937                         tcp_mss(tp, -1);
  938                         /*
  939                          * snd_wnd is irrelevant since we are either forcing
  940                          * a TFO cookie request or disabling TFO - either
  941                          * way, no data with the SYN.
  942                          */
  943                 }
  944         } else {
  945                 /*
  946                  * A new entry for this path will be created when a SYN|ACK
  947                  * comes back, or the attempt otherwise fails.
  948                  */
  949                 CCB_UNLOCK(ccb);
  950                 tcp_mss(tp, -1);
  951                 /*
  952                  * snd_wnd is irrelevant since we are forcing a TFO cookie
  953                  * request.
  954                  */
  955         }
  956 }
  957 
  958 void
  959 tcp_fastopen_disable_path(struct tcpcb *tp)
  960 {
  961         struct in_conninfo *inc = &tp->t_inpcb->inp_inc;
  962         struct tcp_fastopen_ccache_bucket *ccb;
  963         struct tcp_fastopen_ccache_entry *cce;
  964 
  965         cce = tcp_fastopen_ccache_lookup(inc, &ccb);
  966         if (cce) {
  967                 cce->server_mss = 0;
  968                 cce->cookie_len = 0;
  969                 /*
  970                  * Preserve the existing disable time if it is already
  971                  * disabled.
  972                  */
  973                 if (cce->disable_time == 0)
  974                         cce->disable_time = getsbinuptime();
  975         } else /* use invalid cookie len to create disabled entry */
  976                 tcp_fastopen_ccache_create(ccb, inc, 0,
  977                     TCP_FASTOPEN_MAX_COOKIE_LEN + 1, NULL);
  978 
  979         CCB_UNLOCK(ccb);
  980         tp->t_flags &= ~TF_FASTOPEN;
  981 }
  982 
  983 void
  984 tcp_fastopen_update_cache(struct tcpcb *tp, uint16_t mss,
  985     uint8_t cookie_len, uint8_t *cookie)
  986 {
  987         struct in_conninfo *inc = &tp->t_inpcb->inp_inc;
  988         struct tcp_fastopen_ccache_bucket *ccb;
  989         struct tcp_fastopen_ccache_entry *cce;
  990 
  991         cce = tcp_fastopen_ccache_lookup(inc, &ccb);
  992         if (cce) {
  993                 if ((cookie_len >= TCP_FASTOPEN_MIN_COOKIE_LEN) &&
  994                     (cookie_len <= TCP_FASTOPEN_MAX_COOKIE_LEN) &&
  995                     ((cookie_len & 0x1) == 0)) {
  996                         cce->server_mss = mss;
  997                         cce->cookie_len = cookie_len;
  998                         memcpy(cce->cookie, cookie, cookie_len);
  999                         cce->disable_time = 0;
 1000                 } else {
 1001                         /* invalid cookie length, disable entry */
 1002                         cce->server_mss = 0;
 1003                         cce->cookie_len = 0;
 1004                         /*
 1005                          * Preserve the existing disable time if it is
 1006                          * already disabled.
 1007                          */
 1008                         if (cce->disable_time == 0)
 1009                                 cce->disable_time = getsbinuptime();
 1010                 }
 1011         } else
 1012                 tcp_fastopen_ccache_create(ccb, inc, mss, cookie_len, cookie);
 1013 
 1014         CCB_UNLOCK(ccb);
 1015 }
 1016 
 1017 static struct tcp_fastopen_ccache_entry *
 1018 tcp_fastopen_ccache_lookup(struct in_conninfo *inc,
 1019     struct tcp_fastopen_ccache_bucket **ccbp)
 1020 {
 1021         struct tcp_fastopen_ccache_bucket *ccb;
 1022         struct tcp_fastopen_ccache_entry *cce;
 1023         uint32_t last_word;
 1024         uint32_t hash;
 1025 
 1026         hash = jenkins_hash32((uint32_t *)&inc->inc_ie.ie_dependladdr, 4,
 1027             V_tcp_fastopen_ccache.secret);
 1028         hash = jenkins_hash32((uint32_t *)&inc->inc_ie.ie_dependfaddr, 4,
 1029             hash);
 1030         last_word = inc->inc_fport;
 1031         hash = jenkins_hash32(&last_word, 1, hash);
 1032         ccb = &V_tcp_fastopen_ccache.base[hash & V_tcp_fastopen_ccache.mask];
 1033         *ccbp = ccb;
 1034         CCB_LOCK(ccb);
 1035         
 1036         /*
 1037          * Always returns with locked bucket.
 1038          */
 1039         TAILQ_FOREACH(cce, &ccb->ccb_entries, cce_link)
 1040                 if ((!(cce->af == AF_INET6) == !(inc->inc_flags & INC_ISIPV6)) &&
 1041                     (cce->server_port == inc->inc_ie.ie_fport) &&
 1042                     (((cce->af == AF_INET) &&
 1043                       (cce->cce_client_ip.v4.s_addr == inc->inc_laddr.s_addr) &&
 1044                       (cce->cce_server_ip.v4.s_addr == inc->inc_faddr.s_addr)) ||
 1045                      ((cce->af == AF_INET6) &&
 1046                       IN6_ARE_ADDR_EQUAL(&cce->cce_client_ip.v6, &inc->inc6_laddr) &&
 1047                       IN6_ARE_ADDR_EQUAL(&cce->cce_server_ip.v6, &inc->inc6_faddr))))
 1048                         break;
 1049 
 1050         return (cce);
 1051 }
 1052 
 1053 static struct tcp_fastopen_ccache_entry *
 1054 tcp_fastopen_ccache_create(struct tcp_fastopen_ccache_bucket *ccb,
 1055     struct in_conninfo *inc, uint16_t mss, uint8_t cookie_len, uint8_t *cookie)
 1056 {
 1057         struct tcp_fastopen_ccache_entry *cce;
 1058         
 1059         /*
 1060          * 1. Create a new entry, or
 1061          * 2. Reclaim an existing entry, or
 1062          * 3. Fail
 1063          */
 1064 
 1065         CCB_LOCK_ASSERT(ccb);
 1066         
 1067         cce = NULL;
 1068         if (ccb->ccb_num_entries < V_tcp_fastopen_ccache.bucket_limit)
 1069                 cce = uma_zalloc(V_tcp_fastopen_ccache.zone, M_NOWAIT);
 1070 
 1071         if (cce == NULL) {
 1072                 /*
 1073                  * At bucket limit, or out of memory - reclaim last
 1074                  * entry in bucket.
 1075                  */
 1076                 cce = TAILQ_LAST(&ccb->ccb_entries, bucket_entries);
 1077                 if (cce == NULL) {
 1078                         /* XXX count this event */
 1079                         return (NULL);
 1080                 }
 1081 
 1082                 TAILQ_REMOVE(&ccb->ccb_entries, cce, cce_link);
 1083         } else
 1084                 ccb->ccb_num_entries++;
 1085 
 1086         TAILQ_INSERT_HEAD(&ccb->ccb_entries, cce, cce_link);
 1087         cce->af = (inc->inc_flags & INC_ISIPV6) ? AF_INET6 : AF_INET;
 1088         if (cce->af == AF_INET) {
 1089                 cce->cce_client_ip.v4 = inc->inc_laddr;
 1090                 cce->cce_server_ip.v4 = inc->inc_faddr;
 1091         } else {
 1092                 cce->cce_client_ip.v6 = inc->inc6_laddr;
 1093                 cce->cce_server_ip.v6 = inc->inc6_faddr;
 1094         }
 1095         cce->server_port = inc->inc_fport;
 1096         if ((cookie_len >= TCP_FASTOPEN_MIN_COOKIE_LEN) &&
 1097             (cookie_len <= TCP_FASTOPEN_MAX_COOKIE_LEN) &&
 1098             ((cookie_len & 0x1) == 0)) {
 1099                 cce->server_mss = mss;
 1100                 cce->cookie_len = cookie_len;
 1101                 memcpy(cce->cookie, cookie, cookie_len);
 1102                 cce->disable_time = 0;
 1103         } else {
 1104                 /* invalid cookie length, disable cce */
 1105                 cce->server_mss = 0;
 1106                 cce->cookie_len = 0;
 1107                 cce->disable_time = getsbinuptime();
 1108         }
 1109         
 1110         return (cce);
 1111 }
 1112 
 1113 static void
 1114 tcp_fastopen_ccache_bucket_trim(struct tcp_fastopen_ccache_bucket *ccb,
 1115     unsigned int limit)
 1116 {
 1117         struct tcp_fastopen_ccache_entry *cce, *cce_tmp;
 1118         unsigned int entries;
 1119         
 1120         CCB_LOCK(ccb);
 1121         entries = 0;
 1122         TAILQ_FOREACH_SAFE(cce, &ccb->ccb_entries, cce_link, cce_tmp) {
 1123                 entries++;
 1124                 if (entries > limit)
 1125                         tcp_fastopen_ccache_entry_drop(cce, ccb);
 1126         }
 1127         KASSERT(ccb->ccb_num_entries <= (int)limit,
 1128             ("%s: ccb->ccb_num_entries %d exceeds limit %d", __func__,
 1129                 ccb->ccb_num_entries, limit));
 1130         if (limit == 0) {
 1131                 KASSERT(TAILQ_EMPTY(&ccb->ccb_entries),
 1132                     ("%s: ccb->ccb_entries not empty", __func__));
 1133                 ccb->ccb_num_entries = -1; /* disable bucket */
 1134         }
 1135         CCB_UNLOCK(ccb);
 1136 }
 1137 
 1138 static void
 1139 tcp_fastopen_ccache_entry_drop(struct tcp_fastopen_ccache_entry *cce,
 1140     struct tcp_fastopen_ccache_bucket *ccb)
 1141 {
 1142 
 1143         CCB_LOCK_ASSERT(ccb);
 1144 
 1145         TAILQ_REMOVE(&ccb->ccb_entries, cce, cce_link);
 1146         ccb->ccb_num_entries--;
 1147         uma_zfree(V_tcp_fastopen_ccache.zone, cce);
 1148 }
 1149 
 1150 static int
 1151 sysctl_net_inet_tcp_fastopen_ccache_list(SYSCTL_HANDLER_ARGS)
 1152 {
 1153         struct sbuf sb;
 1154         struct tcp_fastopen_ccache_bucket *ccb;
 1155         struct tcp_fastopen_ccache_entry *cce;
 1156         sbintime_t now, duration, limit;
 1157         const int linesize = 128;
 1158         int i, error, num_entries;
 1159         unsigned int j;
 1160 #ifdef INET6
 1161         char clt_buf[INET6_ADDRSTRLEN], srv_buf[INET6_ADDRSTRLEN];
 1162 #else
 1163         char clt_buf[INET_ADDRSTRLEN], srv_buf[INET_ADDRSTRLEN];
 1164 #endif
 1165 
 1166         if (jailed_without_vnet(curthread->td_ucred) != 0)
 1167                 return (EPERM);
 1168 
 1169         /* Only allow root to read the client cookie cache */
 1170         if (curthread->td_ucred->cr_uid != 0)
 1171                 return (EPERM);
 1172 
 1173         num_entries = 0;
 1174         for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) {
 1175                 ccb = &V_tcp_fastopen_ccache.base[i];
 1176                 CCB_LOCK(ccb);
 1177                 if (ccb->ccb_num_entries > 0)
 1178                         num_entries += ccb->ccb_num_entries;
 1179                 CCB_UNLOCK(ccb);
 1180         }
 1181         sbuf_new(&sb, NULL, linesize * (num_entries + 1), SBUF_INCLUDENUL);
 1182 
 1183         sbuf_printf(&sb,
 1184                     "\nLocal IP address     Remote IP address     Port   MSS"
 1185                     " Disabled Cookie\n");
 1186 
 1187         now = getsbinuptime();
 1188         limit = (sbintime_t)V_tcp_fastopen_path_disable_time << 32;
 1189         for (i = 0; i < V_tcp_fastopen_ccache.buckets; i++) {
 1190                 ccb = &V_tcp_fastopen_ccache.base[i];
 1191                 CCB_LOCK(ccb);
 1192                 TAILQ_FOREACH(cce, &ccb->ccb_entries, cce_link) {
 1193                         if (cce->disable_time != 0) {
 1194                                 duration = now - cce->disable_time;
 1195                                 if (limit >= duration)
 1196                                         duration = limit - duration;
 1197                                 else
 1198                                         duration = 0;
 1199                         } else
 1200                                 duration = 0;
 1201                         sbuf_printf(&sb,
 1202                                     "%-20s %-20s %5u %5u ",
 1203                                     inet_ntop(cce->af, &cce->cce_client_ip,
 1204                                         clt_buf, sizeof(clt_buf)),
 1205                                     inet_ntop(cce->af, &cce->cce_server_ip,
 1206                                         srv_buf, sizeof(srv_buf)),
 1207                                     ntohs(cce->server_port),
 1208                                     cce->server_mss);
 1209                         if (duration > 0)
 1210                                 sbuf_printf(&sb, "%7ds ", sbintime_getsec(duration));
 1211                         else
 1212                                 sbuf_printf(&sb, "%8s ", "No");
 1213                         for (j = 0; j < cce->cookie_len; j++)
 1214                                 sbuf_printf(&sb, "%02x", cce->cookie[j]);
 1215                         sbuf_putc(&sb, '\n');
 1216                 }
 1217                 CCB_UNLOCK(ccb);
 1218         }
 1219         error = sbuf_finish(&sb);
 1220         if (error == 0)
 1221                 error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
 1222         sbuf_delete(&sb);
 1223         return (error);
 1224 }
 1225 

Cache object: c9599367862403973e02ba262863fdf5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.