1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2016 Joyent, Inc. 24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 25 * Copyright (c) 2012, 2017 by Delphix. All rights reserved. 26 * Copyright 2022 Garrett D'Amore 27 */ 28 /* Copyright (c) 1990 Mentat Inc. */ 29 30 #include <inet/ip.h> 31 #include <inet/tcp_impl.h> 32 #include <inet/cc.h> 33 #include <sys/sunddi.h> 34 35 /* Max size IP datagram is 64k - 1 */ 36 #define TCP_MSS_MAX_IPV4 (IP_MAXPACKET - (sizeof (ipha_t) + sizeof (tcpha_t))) 37 #define TCP_MSS_MAX_IPV6 (IP_MAXPACKET - (sizeof (ip6_t) + sizeof (tcpha_t))) 38 39 /* Max of the above */ 40 #define TCP_MSS_MAX TCP_MSS_MAX_IPV4 41 42 typedef struct { 43 char *ccn_buf; 44 uint_t ccn_bufsize; 45 uint_t ccn_bytes; 46 } tcp_copy_ccname_t; 47 48 /* 49 * Set the RFC 1948 pass phrase 50 */ 51 /* ARGSUSED */ 52 static int 53 tcp_set_1948phrase(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 54 const char *ifname, const void* pr_val, uint_t flags) 55 { 56 if (flags & MOD_PROP_DEFAULT) 57 return (ENOTSUP); 58 59 /* 60 * Basically, value contains a new pass phrase. Pass it along! 61 */ 62 tcp_iss_key_init((uint8_t *)pr_val, strlen(pr_val), 63 stack->netstack_tcp); 64 return (0); 65 } 66 67 /* 68 * returns the current list of listener limit configuration. 69 */ 70 /* ARGSUSED */ 71 static int 72 tcp_listener_conf_get(netstack_t *stack, mod_prop_info_t *pinfo, 73 const char *ifname, void *val, uint_t psize, uint_t flags) 74 { 75 tcp_stack_t *tcps = stack->netstack_tcp; 76 tcp_listener_t *tl; 77 char *pval = val; 78 size_t nbytes = 0, tbytes = 0; 79 uint_t size; 80 int err = 0; 81 82 bzero(pval, psize); 83 size = psize; 84 85 if (flags & (MOD_PROP_DEFAULT|MOD_PROP_PERM|MOD_PROP_POSSIBLE)) 86 return (0); 87 88 mutex_enter(&tcps->tcps_listener_conf_lock); 89 for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL; 90 tl = list_next(&tcps->tcps_listener_conf, tl)) { 91 if (psize == size) 92 nbytes = snprintf(pval, size, "%d:%d", tl->tl_port, 93 tl->tl_ratio); 94 else 95 nbytes = snprintf(pval, size, ",%d:%d", tl->tl_port, 96 tl->tl_ratio); 97 size -= nbytes; 98 pval += nbytes; 99 tbytes += nbytes; 100 if (tbytes >= psize) { 101 /* Buffer overflow, stop copying information */ 102 err = ENOBUFS; 103 break; 104 } 105 } 106 107 mutex_exit(&tcps->tcps_listener_conf_lock); 108 return (err); 109 } 110 111 /* 112 * add a new listener limit configuration. 113 */ 114 /* ARGSUSED */ 115 static int 116 tcp_listener_conf_add(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 117 const char *ifname, const void* pval, uint_t flags) 118 { 119 tcp_listener_t *new_tl; 120 tcp_listener_t *tl; 121 long lport; 122 long ratio; 123 char *colon; 124 tcp_stack_t *tcps = stack->netstack_tcp; 125 126 if (flags & MOD_PROP_DEFAULT) 127 return (ENOTSUP); 128 129 if (ddi_strtol(pval, &colon, 10, &lport) != 0 || lport <= 0 || 130 lport > USHRT_MAX || *colon != ':') { 131 return (EINVAL); 132 } 133 if (ddi_strtol(colon + 1, NULL, 10, &ratio) != 0 || ratio <= 0) 134 return (EINVAL); 135 136 mutex_enter(&tcps->tcps_listener_conf_lock); 137 for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL; 138 tl = list_next(&tcps->tcps_listener_conf, tl)) { 139 /* There is an existing entry, so update its ratio value. */ 140 if (tl->tl_port == lport) { 141 tl->tl_ratio = ratio; 142 mutex_exit(&tcps->tcps_listener_conf_lock); 143 return (0); 144 } 145 } 146 147 if ((new_tl = kmem_alloc(sizeof (tcp_listener_t), KM_NOSLEEP)) == 148 NULL) { 149 mutex_exit(&tcps->tcps_listener_conf_lock); 150 return (ENOMEM); 151 } 152 153 new_tl->tl_port = lport; 154 new_tl->tl_ratio = ratio; 155 list_insert_tail(&tcps->tcps_listener_conf, new_tl); 156 mutex_exit(&tcps->tcps_listener_conf_lock); 157 return (0); 158 } 159 160 /* 161 * remove a listener limit configuration. 162 */ 163 /* ARGSUSED */ 164 static int 165 tcp_listener_conf_del(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 166 const char *ifname, const void* pval, uint_t flags) 167 { 168 tcp_listener_t *tl; 169 long lport; 170 tcp_stack_t *tcps = stack->netstack_tcp; 171 172 if (flags & MOD_PROP_DEFAULT) 173 return (ENOTSUP); 174 175 if (ddi_strtol(pval, NULL, 10, &lport) != 0 || lport <= 0 || 176 lport > USHRT_MAX) { 177 return (EINVAL); 178 } 179 mutex_enter(&tcps->tcps_listener_conf_lock); 180 for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL; 181 tl = list_next(&tcps->tcps_listener_conf, tl)) { 182 if (tl->tl_port == lport) { 183 list_remove(&tcps->tcps_listener_conf, tl); 184 mutex_exit(&tcps->tcps_listener_conf_lock); 185 kmem_free(tl, sizeof (tcp_listener_t)); 186 return (0); 187 } 188 } 189 mutex_exit(&tcps->tcps_listener_conf_lock); 190 return (ESRCH); 191 } 192 193 static int 194 tcp_set_buf_prop(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 195 const char *ifname, const void *pval, uint_t flags) 196 { 197 return (mod_set_buf_prop(stack->netstack_tcp->tcps_propinfo_tbl, stack, 198 cr, pinfo, ifname, pval, flags)); 199 } 200 201 static int 202 tcp_get_buf_prop(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname, 203 void *val, uint_t psize, uint_t flags) 204 { 205 return (mod_get_buf_prop(stack->netstack_tcp->tcps_propinfo_tbl, stack, 206 pinfo, ifname, val, psize, flags)); 207 } 208 209 /* 210 * Special checkers for smallest/largest anonymous port so they don't 211 * ever happen to be (largest < smallest). 212 */ 213 /* ARGSUSED */ 214 static int 215 tcp_smallest_anon_set(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 216 const char *ifname, const void *pval, uint_t flags) 217 { 218 unsigned long new_value; 219 tcp_stack_t *tcps = stack->netstack_tcp; 220 int err; 221 222 if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0) 223 return (err); 224 /* mod_uint32_value() + pinfo guarantees we're in TCP port range. */ 225 if ((uint32_t)new_value > tcps->tcps_largest_anon_port) 226 return (ERANGE); 227 pinfo->prop_cur_uval = (uint32_t)new_value; 228 return (0); 229 } 230 231 /* ARGSUSED */ 232 static int 233 tcp_largest_anon_set(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 234 const char *ifname, const void *pval, uint_t flags) 235 { 236 unsigned long new_value; 237 tcp_stack_t *tcps = stack->netstack_tcp; 238 int err; 239 240 if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0) 241 return (err); 242 /* mod_uint32_value() + pinfo guarantees we're in TCP port range. */ 243 if ((uint32_t)new_value < tcps->tcps_smallest_anon_port) 244 return (ERANGE); 245 pinfo->prop_cur_uval = (uint32_t)new_value; 246 return (0); 247 } 248 249 /* ARGSUSED */ 250 static int 251 tcp_set_cc_algorithm(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, 252 const char *ifname, const void *pval, uint_t flags) 253 { 254 tcp_stack_t *tcps = stack->netstack_tcp; 255 char *name = (flags & MOD_PROP_DEFAULT) ? 256 CC_DEFAULT_ALGO_NAME : (char *)pval; 257 struct cc_algo *algo = cc_load_algo(name); 258 259 if (algo == NULL) { 260 return (EINVAL); 261 } 262 263 tcps->tcps_default_cc_algo = algo; 264 265 return (0); 266 } 267 268 static int 269 tcp_copy_ccname(void *data, struct cc_algo *algo) 270 { 271 tcp_copy_ccname_t *cd = data; 272 char *sep = cd->ccn_bytes > 0 ? "," : ""; 273 size_t avail = 0; 274 275 if (cd->ccn_bytes < cd->ccn_bufsize) { 276 avail = cd->ccn_bufsize - cd->ccn_bytes; 277 } 278 279 cd->ccn_bytes += snprintf(cd->ccn_buf + cd->ccn_bytes, avail, 280 "%s%s", sep, algo->name); 281 282 return (cd->ccn_bytes >= cd->ccn_bufsize ? ENOBUFS : 0); 283 } 284 285 /* ARGSUSED */ 286 static int 287 tcp_get_cc_algorithm(netstack_t *stack, mod_prop_info_t *pinfo, 288 const char *ifname, void *pval, uint_t psize, uint_t flags) 289 { 290 size_t nbytes; 291 292 if (flags & MOD_PROP_POSSIBLE) { 293 tcp_copy_ccname_t cd = { pval, psize, 0 }; 294 return (cc_walk_algos(tcp_copy_ccname, &cd)); 295 } else if (flags & MOD_PROP_PERM) { 296 nbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW); 297 } else if (flags & MOD_PROP_DEFAULT) { 298 nbytes = snprintf(pval, psize, "%s", CC_DEFAULT_ALGO_NAME); 299 } else { 300 nbytes = snprintf(pval, psize, "%s", 301 stack->netstack_tcp->tcps_default_cc_algo->name); 302 } 303 if (nbytes >= psize) 304 return (ENOBUFS); 305 return (0); 306 } 307 308 /* 309 * All of these are alterable, within the min/max values given, at run time. 310 * 311 * Note: All those tunables which do not start with "_" are Committed and 312 * therefore are public. See PSARC 2010/080. 313 */ 314 mod_prop_info_t tcp_propinfo_tbl[] = { 315 /* tunable - 0 */ 316 { "_time_wait_interval", MOD_PROTO_TCP, 317 mod_set_uint32, mod_get_uint32, 318 {1*SECONDS, TCP_TIME_WAIT_MAX, 1*MINUTES}, {1*MINUTES} }, 319 320 { "_conn_req_max_q", MOD_PROTO_TCP, 321 mod_set_uint32, mod_get_uint32, 322 {1, UINT32_MAX, 128}, {128} }, 323 324 { "_conn_req_max_q0", MOD_PROTO_TCP, 325 mod_set_uint32, mod_get_uint32, 326 {0, UINT32_MAX, 1024}, {1024} }, 327 328 { "_conn_req_min", MOD_PROTO_TCP, 329 mod_set_uint32, mod_get_uint32, 330 {1, 1024, 1}, {1} }, 331 332 { "_conn_grace_period", MOD_PROTO_TCP, 333 mod_set_uint32, mod_get_uint32, 334 {0*MS, 20*SECONDS, 0*MS}, {0*MS} }, 335 336 { "_cwnd_max", MOD_PROTO_TCP, 337 mod_set_uint32, mod_get_uint32, 338 {128, ULP_MAX_BUF, 1024*1024}, {1024*1024} }, 339 340 { "_debug", MOD_PROTO_TCP, 341 mod_set_uint32, mod_get_uint32, 342 {0, 10, 0}, {0} }, 343 344 { "smallest_nonpriv_port", MOD_PROTO_TCP, 345 mod_set_uint32, mod_get_uint32, 346 {1024, (32*1024), 1024}, {1024} }, 347 348 { "_ip_abort_cinterval", MOD_PROTO_TCP, 349 mod_set_uint32, mod_get_uint32, 350 {1*SECONDS, UINT32_MAX, 3*MINUTES}, {3*MINUTES} }, 351 352 { "_ip_abort_linterval", MOD_PROTO_TCP, 353 mod_set_uint32, mod_get_uint32, 354 {1*SECONDS, UINT32_MAX, 3*MINUTES}, {3*MINUTES} }, 355 356 /* tunable - 10 */ 357 { "_ip_abort_interval", MOD_PROTO_TCP, 358 mod_set_uint32, mod_get_uint32, 359 {500*MS, UINT32_MAX, 5*MINUTES}, {5*MINUTES} }, 360 361 { "_ip_notify_cinterval", MOD_PROTO_TCP, 362 mod_set_uint32, mod_get_uint32, 363 {1*SECONDS, UINT32_MAX, 10*SECONDS}, 364 {10*SECONDS} }, 365 366 { "_ip_notify_interval", MOD_PROTO_TCP, 367 mod_set_uint32, mod_get_uint32, 368 {500*MS, UINT32_MAX, 10*SECONDS}, {10*SECONDS} }, 369 370 { "_ipv4_ttl", MOD_PROTO_TCP, 371 mod_set_uint32, mod_get_uint32, 372 {1, 255, 64}, {64} }, 373 374 { "_keepalive_interval", MOD_PROTO_TCP, 375 mod_set_uint32, mod_get_uint32, 376 {1*SECONDS, 10*DAYS, 2*HOURS}, {2*HOURS} }, 377 378 { "_maxpsz_multiplier", MOD_PROTO_TCP, 379 mod_set_uint32, mod_get_uint32, 380 {0, 100, 10}, {10} }, 381 382 { "_mss_def_ipv4", MOD_PROTO_TCP, 383 mod_set_uint32, mod_get_uint32, 384 {1, TCP_MSS_MAX_IPV4, 536}, {536} }, 385 386 { "_mss_max_ipv4", MOD_PROTO_TCP, 387 mod_set_uint32, mod_get_uint32, 388 {1, TCP_MSS_MAX_IPV4, TCP_MSS_MAX_IPV4}, 389 {TCP_MSS_MAX_IPV4} }, 390 391 { "_mss_min", MOD_PROTO_TCP, 392 mod_set_uint32, mod_get_uint32, 393 {1, TCP_MSS_MAX, 108}, {108} }, 394 395 { "_naglim_def", MOD_PROTO_TCP, 396 mod_set_uint32, mod_get_uint32, 397 {1, (64*1024)-1, (4*1024)-1}, {(4*1024)-1} }, 398 399 /* tunable - 20 */ 400 { "_rexmit_interval_initial", MOD_PROTO_TCP, 401 mod_set_uint32, mod_get_uint32, 402 {1*MS, 20*SECONDS, 1*SECONDS}, {1*SECONDS} }, 403 404 { "_rexmit_interval_max", MOD_PROTO_TCP, 405 mod_set_uint32, mod_get_uint32, 406 {1*MS, 2*HOURS, 60*SECONDS}, {60*SECONDS} }, 407 408 { "_rexmit_interval_min", MOD_PROTO_TCP, 409 mod_set_uint32, mod_get_uint32, 410 {1*MS, 2*HOURS, 400*MS}, {400*MS} }, 411 412 { "_deferred_ack_interval", MOD_PROTO_TCP, 413 mod_set_uint32, mod_get_uint32, 414 {1*MS, 1*MINUTES, 100*MS}, {100*MS} }, 415 416 { "_snd_lowat_fraction", MOD_PROTO_TCP, 417 mod_set_uint32, mod_get_uint32, 418 {0, 16, 10}, {10} }, 419 420 { "_dupack_fast_retransmit", MOD_PROTO_TCP, 421 mod_set_uint32, mod_get_uint32, 422 {1, 10000, 3}, {3} }, 423 424 { "_ignore_path_mtu", MOD_PROTO_TCP, 425 mod_set_boolean, mod_get_boolean, 426 {B_FALSE}, {B_FALSE} }, 427 428 { "smallest_anon_port", MOD_PROTO_TCP, 429 tcp_smallest_anon_set, mod_get_uint32, 430 {1024, ULP_MAX_PORT, 32*1024}, {32*1024} }, 431 432 { "largest_anon_port", MOD_PROTO_TCP, 433 tcp_largest_anon_set, mod_get_uint32, 434 {1024, ULP_MAX_PORT, ULP_MAX_PORT}, 435 {ULP_MAX_PORT} }, 436 437 { "send_buf", MOD_PROTO_TCP, 438 tcp_set_buf_prop, tcp_get_buf_prop, 439 {TCP_XMIT_LOWATER, ULP_MAX_BUF, TCP_XMIT_HIWATER}, 440 {TCP_XMIT_HIWATER} }, 441 442 /* tunable - 30 */ 443 { "_xmit_lowat", MOD_PROTO_TCP, 444 mod_set_uint32, mod_get_uint32, 445 {TCP_XMIT_LOWATER, ULP_MAX_BUF, TCP_XMIT_LOWATER}, 446 {TCP_XMIT_LOWATER} }, 447 448 { "recv_buf", MOD_PROTO_TCP, 449 tcp_set_buf_prop, tcp_get_buf_prop, 450 {TCP_RECV_LOWATER, ULP_MAX_BUF, TCP_RECV_HIWATER}, 451 {TCP_RECV_HIWATER} }, 452 453 { "_recv_hiwat_minmss", MOD_PROTO_TCP, 454 mod_set_uint32, mod_get_uint32, 455 {1, 65536, 4}, {4} }, 456 457 { "_fin_wait_2_flush_interval", MOD_PROTO_TCP, 458 mod_set_uint32, mod_get_uint32, 459 {1*SECONDS, 2*HOURS, 60*SECONDS}, 460 {60*SECONDS} }, 461 462 { "max_buf", MOD_PROTO_TCP, 463 mod_set_uint32, mod_get_uint32, 464 {8192, ULP_MAX_BUF, 1024*1024}, {1024*1024} }, 465 466 { "_strong_iss", MOD_PROTO_TCP, 467 mod_set_uint32, mod_get_uint32, 468 {0, 2, 2}, {2} }, 469 470 { "_rtt_updates", MOD_PROTO_TCP, 471 mod_set_uint32, mod_get_uint32, 472 {0, 65536, 20}, {20} }, 473 474 { "_wscale_always", MOD_PROTO_TCP, 475 mod_set_boolean, mod_get_boolean, 476 {B_TRUE}, {B_TRUE} }, 477 478 { "_tstamp_always", MOD_PROTO_TCP, 479 mod_set_boolean, mod_get_boolean, 480 {B_FALSE}, {B_FALSE} }, 481 482 { "_tstamp_if_wscale", MOD_PROTO_TCP, 483 mod_set_boolean, mod_get_boolean, 484 {B_TRUE}, {B_TRUE} }, 485 486 /* tunable - 40 */ 487 { "_rexmit_interval_extra", MOD_PROTO_TCP, 488 mod_set_uint32, mod_get_uint32, 489 {0*MS, 2*HOURS, 0*MS}, {0*MS} }, 490 491 { "_deferred_acks_max", MOD_PROTO_TCP, 492 mod_set_uint32, mod_get_uint32, 493 {0, 16, 2}, {2} }, 494 495 { "_slow_start_after_idle", MOD_PROTO_TCP, 496 mod_set_uint32, mod_get_uint32, 497 {0, 16384, 0}, {0} }, 498 499 { "_slow_start_initial", MOD_PROTO_TCP, 500 mod_set_uint32, mod_get_uint32, 501 {0, 16, 0}, {0} }, 502 503 { "sack", MOD_PROTO_TCP, 504 mod_set_uint32, mod_get_uint32, 505 {0, 2, 2}, {2} }, 506 507 { "_ipv6_hoplimit", MOD_PROTO_TCP, 508 mod_set_uint32, mod_get_uint32, 509 {0, IPV6_MAX_HOPS, IPV6_DEFAULT_HOPS}, 510 {IPV6_DEFAULT_HOPS} }, 511 512 { "_mss_def_ipv6", MOD_PROTO_TCP, 513 mod_set_uint32, mod_get_uint32, 514 {1, TCP_MSS_MAX_IPV6, 1220}, {1220} }, 515 516 { "_mss_max_ipv6", MOD_PROTO_TCP, 517 mod_set_uint32, mod_get_uint32, 518 {1, TCP_MSS_MAX_IPV6, TCP_MSS_MAX_IPV6}, 519 {TCP_MSS_MAX_IPV6} }, 520 521 { "_rev_src_routes", MOD_PROTO_TCP, 522 mod_set_boolean, mod_get_boolean, 523 {B_FALSE}, {B_FALSE} }, 524 525 { "_local_dack_interval", MOD_PROTO_TCP, 526 mod_set_uint32, mod_get_uint32, 527 {10*MS, 500*MS, 50*MS}, {50*MS} }, 528 529 /* tunable - 50 */ 530 { "_local_dacks_max", MOD_PROTO_TCP, 531 mod_set_uint32, mod_get_uint32, 532 {0, 16, 8}, {8} }, 533 534 { "ecn", MOD_PROTO_TCP, 535 mod_set_uint32, mod_get_uint32, 536 {0, 2, 1}, {1} }, 537 538 { "_rst_sent_rate_enabled", MOD_PROTO_TCP, 539 mod_set_boolean, mod_get_boolean, 540 {B_TRUE}, {B_TRUE} }, 541 542 { "_rst_sent_rate", MOD_PROTO_TCP, 543 mod_set_uint32, mod_get_uint32, 544 {0, UINT32_MAX, 40}, {40} }, 545 546 { "_push_timer_interval", MOD_PROTO_TCP, 547 mod_set_uint32, mod_get_uint32, 548 {0, 100*MS, 50*MS}, {50*MS} }, 549 550 { "_use_smss_as_mss_opt", MOD_PROTO_TCP, 551 mod_set_boolean, mod_get_boolean, 552 {B_FALSE}, {B_FALSE} }, 553 554 { "_keepalive_abort_interval", MOD_PROTO_TCP, 555 mod_set_uint32, mod_get_uint32, 556 {0, UINT32_MAX, 8*MINUTES}, {8*MINUTES} }, 557 558 /* 559 * tcp_wroff_xtra is the extra space in front of TCP/IP header for link 560 * layer header. It has to be a multiple of 8. 561 */ 562 { "_wroff_xtra", MOD_PROTO_TCP, 563 mod_set_aligned, mod_get_uint32, 564 {0, 256, 32}, {32} }, 565 566 { "_dev_flow_ctl", MOD_PROTO_TCP, 567 mod_set_boolean, mod_get_boolean, 568 {B_FALSE}, {B_FALSE} }, 569 570 { "_reass_timeout", MOD_PROTO_TCP, 571 mod_set_uint32, mod_get_uint32, 572 {0, UINT32_MAX, 100*SECONDS}, {100*SECONDS} }, 573 574 /* tunable - 60 */ 575 { "extra_priv_ports", MOD_PROTO_TCP, 576 mod_set_extra_privports, mod_get_extra_privports, 577 {1, ULP_MAX_PORT, 0}, {0} }, 578 579 { "_1948_phrase", MOD_PROTO_TCP, 580 tcp_set_1948phrase, NULL, {0}, {0} }, 581 582 { "_listener_limit_conf", MOD_PROTO_TCP, 583 NULL, tcp_listener_conf_get, {0}, {0} }, 584 585 { "_listener_limit_conf_add", MOD_PROTO_TCP, 586 tcp_listener_conf_add, NULL, {0}, {0} }, 587 588 { "_listener_limit_conf_del", MOD_PROTO_TCP, 589 tcp_listener_conf_del, NULL, {0}, {0} }, 590 591 { "_iss_incr", MOD_PROTO_TCP, 592 mod_set_uint32, mod_get_uint32, 593 {1, ISS_INCR, ISS_INCR}, 594 {ISS_INCR} }, 595 596 { "congestion_control", MOD_PROTO_TCP, 597 tcp_set_cc_algorithm, tcp_get_cc_algorithm, {0}, {0} }, 598 599 /* RFC 3465 - TCP Congestion Control with Appropriate Byte Counting */ 600 { "_abc", MOD_PROTO_TCP, 601 mod_set_boolean, mod_get_boolean, {B_TRUE}, {B_TRUE} }, 602 603 /* "L" value from RFC 3465 */ 604 { "_abc_l_var", MOD_PROTO_TCP, 605 mod_set_uint32, mod_get_uint32, {1, UINT32_MAX, 2}, {2} }, 606 607 { "?", MOD_PROTO_TCP, NULL, mod_get_allprop, {0}, {0} }, 608 609 { NULL, 0, NULL, NULL, {0}, {0} } 610 }; 611 612 int tcp_propinfo_count = A_CNT(tcp_propinfo_tbl); 613