tcp_syncache.c (181337) | tcp_syncache.c (181803) |
---|---|
1/*- 2 * Copyright (c) 2001 McAfee, Inc. 3 * Copyright (c) 2006 Andre Oppermann, Internet Business Solutions AG 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by Jonathan Lemon 7 * and McAfee Research, the Security Research Division of McAfee, Inc. under 8 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the --- 17 unchanged lines hidden (view full) --- 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001 McAfee, Inc. 3 * Copyright (c) 2006 Andre Oppermann, Internet Business Solutions AG 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by Jonathan Lemon 7 * and McAfee Research, the Security Research Division of McAfee, Inc. under 8 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the --- 17 unchanged lines hidden (view full) --- 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/netinet/tcp_syncache.c 181337 2008-08-05 21:59:20Z jhb $"); | 34__FBSDID("$FreeBSD: head/sys/netinet/tcp_syncache.c 181803 2008-08-17 23:27:27Z bz $"); |
35 36#include "opt_inet.h" 37#include "opt_inet6.h" 38#include "opt_ipsec.h" 39#include "opt_mac.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> --- 5 unchanged lines hidden (view full) --- 48#include <sys/malloc.h> 49#include <sys/mbuf.h> 50#include <sys/md5.h> 51#include <sys/proc.h> /* for proc0 declaration */ 52#include <sys/random.h> 53#include <sys/socket.h> 54#include <sys/socketvar.h> 55#include <sys/syslog.h> | 35 36#include "opt_inet.h" 37#include "opt_inet6.h" 38#include "opt_ipsec.h" 39#include "opt_mac.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> --- 5 unchanged lines hidden (view full) --- 48#include <sys/malloc.h> 49#include <sys/mbuf.h> 50#include <sys/md5.h> 51#include <sys/proc.h> /* for proc0 declaration */ 52#include <sys/random.h> 53#include <sys/socket.h> 54#include <sys/socketvar.h> 55#include <sys/syslog.h> |
56#include <sys/vimage.h> |
|
56 57#include <vm/uma.h> 58 59#include <net/if.h> 60#include <net/route.h> 61 62#include <netinet/in.h> 63#include <netinet/in_systm.h> --- 162 unchanged lines hidden (view full) --- 226 227int tcp_sc_rst_sock_fail = 1; 228SYSCTL_INT(_net_inet_tcp_syncache, OID_AUTO, rst_on_sock_fail, CTLFLAG_RW, 229 &tcp_sc_rst_sock_fail, 0, "Send reset on socket allocation failure"); 230 231static MALLOC_DEFINE(M_SYNCACHE, "syncache", "TCP syncache"); 232 233#define SYNCACHE_HASH(inc, mask) \ | 57 58#include <vm/uma.h> 59 60#include <net/if.h> 61#include <net/route.h> 62 63#include <netinet/in.h> 64#include <netinet/in_systm.h> --- 162 unchanged lines hidden (view full) --- 227 228int tcp_sc_rst_sock_fail = 1; 229SYSCTL_INT(_net_inet_tcp_syncache, OID_AUTO, rst_on_sock_fail, CTLFLAG_RW, 230 &tcp_sc_rst_sock_fail, 0, "Send reset on socket allocation failure"); 231 232static MALLOC_DEFINE(M_SYNCACHE, "syncache", "TCP syncache"); 233 234#define SYNCACHE_HASH(inc, mask) \ |
234 ((tcp_syncache.hash_secret ^ \ | 235 ((V_tcp_syncache.hash_secret ^ \ |
235 (inc)->inc_faddr.s_addr ^ \ 236 ((inc)->inc_faddr.s_addr >> 16) ^ \ 237 (inc)->inc_fport ^ (inc)->inc_lport) & mask) 238 239#define SYNCACHE_HASH6(inc, mask) \ | 236 (inc)->inc_faddr.s_addr ^ \ 237 ((inc)->inc_faddr.s_addr >> 16) ^ \ 238 (inc)->inc_fport ^ (inc)->inc_lport) & mask) 239 240#define SYNCACHE_HASH6(inc, mask) \ |
240 ((tcp_syncache.hash_secret ^ \ | 241 ((V_tcp_syncache.hash_secret ^ \ |
241 (inc)->inc6_faddr.s6_addr32[0] ^ \ 242 (inc)->inc6_faddr.s6_addr32[3] ^ \ 243 (inc)->inc_fport ^ (inc)->inc_lport) & mask) 244 245#define ENDPTS_EQ(a, b) ( \ 246 (a)->ie_fport == (b)->ie_fport && \ 247 (a)->ie_lport == (b)->ie_lport && \ 248 (a)->ie_faddr.s_addr == (b)->ie_faddr.s_addr && \ --- 13 unchanged lines hidden (view full) --- 262syncache_free(struct syncache *sc) 263{ 264 if (sc->sc_ipopts) 265 (void) m_free(sc->sc_ipopts); 266#ifdef MAC 267 mac_syncache_destroy(&sc->sc_label); 268#endif 269 | 242 (inc)->inc6_faddr.s6_addr32[0] ^ \ 243 (inc)->inc6_faddr.s6_addr32[3] ^ \ 244 (inc)->inc_fport ^ (inc)->inc_lport) & mask) 245 246#define ENDPTS_EQ(a, b) ( \ 247 (a)->ie_fport == (b)->ie_fport && \ 248 (a)->ie_lport == (b)->ie_lport && \ 249 (a)->ie_faddr.s_addr == (b)->ie_faddr.s_addr && \ --- 13 unchanged lines hidden (view full) --- 263syncache_free(struct syncache *sc) 264{ 265 if (sc->sc_ipopts) 266 (void) m_free(sc->sc_ipopts); 267#ifdef MAC 268 mac_syncache_destroy(&sc->sc_label); 269#endif 270 |
270 uma_zfree(tcp_syncache.zone, sc); | 271 uma_zfree(V_tcp_syncache.zone, sc); |
271} 272 273void 274syncache_init(void) 275{ 276 int i; 277 | 272} 273 274void 275syncache_init(void) 276{ 277 int i; 278 |
278 tcp_syncache.cache_count = 0; 279 tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; 280 tcp_syncache.bucket_limit = TCP_SYNCACHE_BUCKETLIMIT; 281 tcp_syncache.rexmt_limit = SYNCACHE_MAXREXMTS; 282 tcp_syncache.hash_secret = arc4random(); | 279 V_tcp_syncache.cache_count = 0; 280 V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; 281 V_tcp_syncache.bucket_limit = TCP_SYNCACHE_BUCKETLIMIT; 282 V_tcp_syncache.rexmt_limit = SYNCACHE_MAXREXMTS; 283 V_tcp_syncache.hash_secret = arc4random(); |
283 284 TUNABLE_INT_FETCH("net.inet.tcp.syncache.hashsize", | 284 285 TUNABLE_INT_FETCH("net.inet.tcp.syncache.hashsize", |
285 &tcp_syncache.hashsize); | 286 &V_tcp_syncache.hashsize); |
286 TUNABLE_INT_FETCH("net.inet.tcp.syncache.bucketlimit", | 287 TUNABLE_INT_FETCH("net.inet.tcp.syncache.bucketlimit", |
287 &tcp_syncache.bucket_limit); 288 if (!powerof2(tcp_syncache.hashsize) || tcp_syncache.hashsize == 0) { | 288 &V_tcp_syncache.bucket_limit); 289 if (!powerof2(V_tcp_syncache.hashsize) || V_tcp_syncache.hashsize == 0) { |
289 printf("WARNING: syncache hash size is not a power of 2.\n"); | 290 printf("WARNING: syncache hash size is not a power of 2.\n"); |
290 tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; | 291 V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; |
291 } | 292 } |
292 tcp_syncache.hashmask = tcp_syncache.hashsize - 1; | 293 V_tcp_syncache.hashmask = V_tcp_syncache.hashsize - 1; |
293 294 /* Set limits. */ | 294 295 /* Set limits. */ |
295 tcp_syncache.cache_limit = 296 tcp_syncache.hashsize * tcp_syncache.bucket_limit; | 296 V_tcp_syncache.cache_limit = 297 V_tcp_syncache.hashsize * V_tcp_syncache.bucket_limit; |
297 TUNABLE_INT_FETCH("net.inet.tcp.syncache.cachelimit", | 298 TUNABLE_INT_FETCH("net.inet.tcp.syncache.cachelimit", |
298 &tcp_syncache.cache_limit); | 299 &V_tcp_syncache.cache_limit); |
299 300 /* Allocate the hash table. */ | 300 301 /* Allocate the hash table. */ |
301 MALLOC(tcp_syncache.hashbase, struct syncache_head *, 302 tcp_syncache.hashsize * sizeof(struct syncache_head), | 302 MALLOC(V_tcp_syncache.hashbase, struct syncache_head *, 303 V_tcp_syncache.hashsize * sizeof(struct syncache_head), |
303 M_SYNCACHE, M_WAITOK | M_ZERO); 304 305 /* Initialize the hash buckets. */ | 304 M_SYNCACHE, M_WAITOK | M_ZERO); 305 306 /* Initialize the hash buckets. */ |
306 for (i = 0; i < tcp_syncache.hashsize; i++) { 307 TAILQ_INIT(&tcp_syncache.hashbase[i].sch_bucket); 308 mtx_init(&tcp_syncache.hashbase[i].sch_mtx, "tcp_sc_head", | 307 for (i = 0; i < V_tcp_syncache.hashsize; i++) { 308 TAILQ_INIT(&V_tcp_syncache.hashbase[i].sch_bucket); 309 mtx_init(&V_tcp_syncache.hashbase[i].sch_mtx, "tcp_sc_head", |
309 NULL, MTX_DEF); | 310 NULL, MTX_DEF); |
310 callout_init_mtx(&tcp_syncache.hashbase[i].sch_timer, 311 &tcp_syncache.hashbase[i].sch_mtx, 0); 312 tcp_syncache.hashbase[i].sch_length = 0; | 311 callout_init_mtx(&V_tcp_syncache.hashbase[i].sch_timer, 312 &V_tcp_syncache.hashbase[i].sch_mtx, 0); 313 V_tcp_syncache.hashbase[i].sch_length = 0; |
313 } 314 315 /* Create the syncache entry zone. */ | 314 } 315 316 /* Create the syncache entry zone. */ |
316 tcp_syncache.zone = uma_zcreate("syncache", sizeof(struct syncache), | 317 V_tcp_syncache.zone = uma_zcreate("syncache", sizeof(struct syncache), |
317 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); | 318 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); |
318 uma_zone_set_max(tcp_syncache.zone, tcp_syncache.cache_limit); | 319 uma_zone_set_max(V_tcp_syncache.zone, V_tcp_syncache.cache_limit); |
319} 320 321/* 322 * Inserts a syncache entry into the specified bucket row. 323 * Locks and unlocks the syncache_head autonomously. 324 */ 325static void 326syncache_insert(struct syncache *sc, struct syncache_head *sch) 327{ 328 struct syncache *sc2; 329 330 SCH_LOCK(sch); 331 332 /* 333 * Make sure that we don't overflow the per-bucket limit. 334 * If the bucket is full, toss the oldest element. 335 */ | 320} 321 322/* 323 * Inserts a syncache entry into the specified bucket row. 324 * Locks and unlocks the syncache_head autonomously. 325 */ 326static void 327syncache_insert(struct syncache *sc, struct syncache_head *sch) 328{ 329 struct syncache *sc2; 330 331 SCH_LOCK(sch); 332 333 /* 334 * Make sure that we don't overflow the per-bucket limit. 335 * If the bucket is full, toss the oldest element. 336 */ |
336 if (sch->sch_length >= tcp_syncache.bucket_limit) { | 337 if (sch->sch_length >= V_tcp_syncache.bucket_limit) { |
337 KASSERT(!TAILQ_EMPTY(&sch->sch_bucket), 338 ("sch->sch_length incorrect")); 339 sc2 = TAILQ_LAST(&sch->sch_bucket, sch_head); 340 syncache_drop(sc2, sch); | 338 KASSERT(!TAILQ_EMPTY(&sch->sch_bucket), 339 ("sch->sch_length incorrect")); 340 sc2 = TAILQ_LAST(&sch->sch_bucket, sch_head); 341 syncache_drop(sc2, sch); |
341 tcpstat.tcps_sc_bucketoverflow++; | 342 V_tcpstat.tcps_sc_bucketoverflow++; |
342 } 343 344 /* Put it into the bucket. */ 345 TAILQ_INSERT_HEAD(&sch->sch_bucket, sc, sc_hash); 346 sch->sch_length++; 347 348 /* Reinitialize the bucket row's timer. */ 349 if (sch->sch_length == 1) 350 sch->sch_nextc = ticks + INT_MAX; 351 syncache_timeout(sc, sch, 1); 352 353 SCH_UNLOCK(sch); 354 | 343 } 344 345 /* Put it into the bucket. */ 346 TAILQ_INSERT_HEAD(&sch->sch_bucket, sc, sc_hash); 347 sch->sch_length++; 348 349 /* Reinitialize the bucket row's timer. */ 350 if (sch->sch_length == 1) 351 sch->sch_nextc = ticks + INT_MAX; 352 syncache_timeout(sc, sch, 1); 353 354 SCH_UNLOCK(sch); 355 |
355 tcp_syncache.cache_count++; 356 tcpstat.tcps_sc_added++; | 356 V_tcp_syncache.cache_count++; 357 V_tcpstat.tcps_sc_added++; |
357} 358 359/* 360 * Remove and free entry from syncache bucket row. 361 * Expects locked syncache head. 362 */ 363static void 364syncache_drop(struct syncache *sc, struct syncache_head *sch) --- 4 unchanged lines hidden (view full) --- 369 TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash); 370 sch->sch_length--; 371 372#ifndef TCP_OFFLOAD_DISABLE 373 if (sc->sc_tu) 374 sc->sc_tu->tu_syncache_event(TOE_SC_DROP, sc->sc_toepcb); 375#endif 376 syncache_free(sc); | 358} 359 360/* 361 * Remove and free entry from syncache bucket row. 362 * Expects locked syncache head. 363 */ 364static void 365syncache_drop(struct syncache *sc, struct syncache_head *sch) --- 4 unchanged lines hidden (view full) --- 370 TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash); 371 sch->sch_length--; 372 373#ifndef TCP_OFFLOAD_DISABLE 374 if (sc->sc_tu) 375 sc->sc_tu->tu_syncache_event(TOE_SC_DROP, sc->sc_toepcb); 376#endif 377 syncache_free(sc); |
377 tcp_syncache.cache_count--; | 378 V_tcp_syncache.cache_count--; |
378} 379 380/* 381 * Engage/reengage time on bucket row. 382 */ 383static void 384syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout) 385{ --- 39 unchanged lines hidden (view full) --- 425 * then the RST will be sent by the time the remote 426 * host does the SYN/ACK->ACK. 427 */ 428 if (TSTMP_GT(sc->sc_rxttime, tick)) { 429 if (TSTMP_LT(sc->sc_rxttime, sch->sch_nextc)) 430 sch->sch_nextc = sc->sc_rxttime; 431 continue; 432 } | 379} 380 381/* 382 * Engage/reengage time on bucket row. 383 */ 384static void 385syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout) 386{ --- 39 unchanged lines hidden (view full) --- 426 * then the RST will be sent by the time the remote 427 * host does the SYN/ACK->ACK. 428 */ 429 if (TSTMP_GT(sc->sc_rxttime, tick)) { 430 if (TSTMP_LT(sc->sc_rxttime, sch->sch_nextc)) 431 sch->sch_nextc = sc->sc_rxttime; 432 continue; 433 } |
433 if (sc->sc_rxmits > tcp_syncache.rexmt_limit) { | 434 if (sc->sc_rxmits > V_tcp_syncache.rexmt_limit) { |
434 if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { 435 log(LOG_DEBUG, "%s; %s: Retransmits exhausted, " 436 "giving up and removing syncache entry\n", 437 s, __func__); 438 free(s, M_TCPLOG); 439 } 440 syncache_drop(sc, sch); | 435 if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { 436 log(LOG_DEBUG, "%s; %s: Retransmits exhausted, " 437 "giving up and removing syncache entry\n", 438 s, __func__); 439 free(s, M_TCPLOG); 440 } 441 syncache_drop(sc, sch); |
441 tcpstat.tcps_sc_stale++; | 442 V_tcpstat.tcps_sc_stale++; |
442 continue; 443 } 444 if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { 445 log(LOG_DEBUG, "%s; %s: Response timeout, " 446 "retransmitting (%u) SYN|ACK\n", 447 s, __func__, sc->sc_rxmits); 448 free(s, M_TCPLOG); 449 } 450 451 (void) syncache_respond(sc); | 443 continue; 444 } 445 if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { 446 log(LOG_DEBUG, "%s; %s: Response timeout, " 447 "retransmitting (%u) SYN|ACK\n", 448 s, __func__, sc->sc_rxmits); 449 free(s, M_TCPLOG); 450 } 451 452 (void) syncache_respond(sc); |
452 tcpstat.tcps_sc_retransmitted++; | 453 V_tcpstat.tcps_sc_retransmitted++; |
453 syncache_timeout(sc, sch, 0); 454 } 455 if (!TAILQ_EMPTY(&(sch)->sch_bucket)) 456 callout_reset(&(sch)->sch_timer, (sch)->sch_nextc - tick, 457 syncache_timer, (void *)(sch)); 458} 459 460/* 461 * Find an entry in the syncache. 462 * Returns always with locked syncache_head plus a matching entry or NULL. 463 */ 464struct syncache * 465syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp) 466{ 467 struct syncache *sc; 468 struct syncache_head *sch; 469 470#ifdef INET6 471 if (inc->inc_isipv6) { | 454 syncache_timeout(sc, sch, 0); 455 } 456 if (!TAILQ_EMPTY(&(sch)->sch_bucket)) 457 callout_reset(&(sch)->sch_timer, (sch)->sch_nextc - tick, 458 syncache_timer, (void *)(sch)); 459} 460 461/* 462 * Find an entry in the syncache. 463 * Returns always with locked syncache_head plus a matching entry or NULL. 464 */ 465struct syncache * 466syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp) 467{ 468 struct syncache *sc; 469 struct syncache_head *sch; 470 471#ifdef INET6 472 if (inc->inc_isipv6) { |
472 sch = &tcp_syncache.hashbase[ 473 SYNCACHE_HASH6(inc, tcp_syncache.hashmask)]; | 473 sch = &V_tcp_syncache.hashbase[ 474 SYNCACHE_HASH6(inc, V_tcp_syncache.hashmask)]; |
474 *schp = sch; 475 476 SCH_LOCK(sch); 477 478 /* Circle through bucket row to find matching entry. */ 479 TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { 480 if (ENDPTS6_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie)) 481 return (sc); 482 } 483 } else 484#endif 485 { | 475 *schp = sch; 476 477 SCH_LOCK(sch); 478 479 /* Circle through bucket row to find matching entry. */ 480 TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { 481 if (ENDPTS6_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie)) 482 return (sc); 483 } 484 } else 485#endif 486 { |
486 sch = &tcp_syncache.hashbase[ 487 SYNCACHE_HASH(inc, tcp_syncache.hashmask)]; | 487 sch = &V_tcp_syncache.hashbase[ 488 SYNCACHE_HASH(inc, V_tcp_syncache.hashmask)]; |
488 *schp = sch; 489 490 SCH_LOCK(sch); 491 492 /* Circle through bucket row to find matching entry. */ 493 TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { 494#ifdef INET6 495 if (sc->sc_inc.inc_isipv6) --- 25 unchanged lines hidden (view full) --- 521 /* 522 * Any RST to our SYN|ACK must not carry ACK, SYN or FIN flags. 523 * See RFC 793 page 65, section SEGMENT ARRIVES. 524 */ 525 if (th->th_flags & (TH_ACK|TH_SYN|TH_FIN)) { 526 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 527 log(LOG_DEBUG, "%s; %s: Spurious RST with ACK, SYN or " 528 "FIN flag set, segment ignored\n", s, __func__); | 489 *schp = sch; 490 491 SCH_LOCK(sch); 492 493 /* Circle through bucket row to find matching entry. */ 494 TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { 495#ifdef INET6 496 if (sc->sc_inc.inc_isipv6) --- 25 unchanged lines hidden (view full) --- 522 /* 523 * Any RST to our SYN|ACK must not carry ACK, SYN or FIN flags. 524 * See RFC 793 page 65, section SEGMENT ARRIVES. 525 */ 526 if (th->th_flags & (TH_ACK|TH_SYN|TH_FIN)) { 527 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 528 log(LOG_DEBUG, "%s; %s: Spurious RST with ACK, SYN or " 529 "FIN flag set, segment ignored\n", s, __func__); |
529 tcpstat.tcps_badrst++; | 530 V_tcpstat.tcps_badrst++; |
530 goto done; 531 } 532 533 /* 534 * No corresponding connection was found in syncache. 535 * If syncookies are enabled and possibly exclusively 536 * used, or we are under memory pressure, a valid RST 537 * may not find a syncache entry. In that case we're 538 * done and no SYN|ACK retransmissions will happen. 539 * Otherwise the the RST was misdirected or spoofed. 540 */ 541 if (sc == NULL) { 542 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 543 log(LOG_DEBUG, "%s; %s: Spurious RST without matching " 544 "syncache entry (possibly syncookie only), " 545 "segment ignored\n", s, __func__); | 531 goto done; 532 } 533 534 /* 535 * No corresponding connection was found in syncache. 536 * If syncookies are enabled and possibly exclusively 537 * used, or we are under memory pressure, a valid RST 538 * may not find a syncache entry. In that case we're 539 * done and no SYN|ACK retransmissions will happen. 540 * Otherwise the the RST was misdirected or spoofed. 541 */ 542 if (sc == NULL) { 543 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 544 log(LOG_DEBUG, "%s; %s: Spurious RST without matching " 545 "syncache entry (possibly syncookie only), " 546 "segment ignored\n", s, __func__); |
546 tcpstat.tcps_badrst++; | 547 V_tcpstat.tcps_badrst++; |
547 goto done; 548 } 549 550 /* 551 * If the RST bit is set, check the sequence number to see 552 * if this is a valid reset segment. 553 * RFC 793 page 37: 554 * In all states except SYN-SENT, all reset (RST) segments --- 7 unchanged lines hidden (view full) --- 562 */ 563 if (SEQ_GEQ(th->th_seq, sc->sc_irs) && 564 SEQ_LEQ(th->th_seq, sc->sc_irs + sc->sc_wnd)) { 565 syncache_drop(sc, sch); 566 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 567 log(LOG_DEBUG, "%s; %s: Our SYN|ACK was rejected, " 568 "connection attempt aborted by remote endpoint\n", 569 s, __func__); | 548 goto done; 549 } 550 551 /* 552 * If the RST bit is set, check the sequence number to see 553 * if this is a valid reset segment. 554 * RFC 793 page 37: 555 * In all states except SYN-SENT, all reset (RST) segments --- 7 unchanged lines hidden (view full) --- 563 */ 564 if (SEQ_GEQ(th->th_seq, sc->sc_irs) && 565 SEQ_LEQ(th->th_seq, sc->sc_irs + sc->sc_wnd)) { 566 syncache_drop(sc, sch); 567 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 568 log(LOG_DEBUG, "%s; %s: Our SYN|ACK was rejected, " 569 "connection attempt aborted by remote endpoint\n", 570 s, __func__); |
570 tcpstat.tcps_sc_reset++; | 571 V_tcpstat.tcps_sc_reset++; |
571 } else { 572 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 573 log(LOG_DEBUG, "%s; %s: RST with invalid SEQ %u != " 574 "IRS %u (+WND %u), segment ignored\n", 575 s, __func__, th->th_seq, sc->sc_irs, sc->sc_wnd); | 572 } else { 573 if ((s = tcp_log_addrs(inc, th, NULL, NULL))) 574 log(LOG_DEBUG, "%s; %s: RST with invalid SEQ %u != " 575 "IRS %u (+WND %u), segment ignored\n", 576 s, __func__, th->th_seq, sc->sc_irs, sc->sc_wnd); |
576 tcpstat.tcps_badrst++; | 577 V_tcpstat.tcps_badrst++; |
577 } 578 579done: 580 if (s != NULL) 581 free(s, M_TCPLOG); 582 SCH_UNLOCK(sch); 583} 584 585void 586syncache_badack(struct in_conninfo *inc) 587{ 588 struct syncache *sc; 589 struct syncache_head *sch; 590 591 sc = syncache_lookup(inc, &sch); /* returns locked sch */ 592 SCH_LOCK_ASSERT(sch); 593 if (sc != NULL) { 594 syncache_drop(sc, sch); | 578 } 579 580done: 581 if (s != NULL) 582 free(s, M_TCPLOG); 583 SCH_UNLOCK(sch); 584} 585 586void 587syncache_badack(struct in_conninfo *inc) 588{ 589 struct syncache *sc; 590 struct syncache_head *sch; 591 592 sc = syncache_lookup(inc, &sch); /* returns locked sch */ 593 SCH_LOCK_ASSERT(sch); 594 if (sc != NULL) { 595 syncache_drop(sc, sch); |
595 tcpstat.tcps_sc_badack++; | 596 V_tcpstat.tcps_sc_badack++; |
596 } 597 SCH_UNLOCK(sch); 598} 599 600void 601syncache_unreach(struct in_conninfo *inc, struct tcphdr *th) 602{ 603 struct syncache *sc; --- 16 unchanged lines hidden (view full) --- 620 * 621 * See tcp_notify(). 622 */ 623 if ((sc->sc_flags & SCF_UNREACH) == 0 || sc->sc_rxmits < 3 + 1) { 624 sc->sc_flags |= SCF_UNREACH; 625 goto done; 626 } 627 syncache_drop(sc, sch); | 597 } 598 SCH_UNLOCK(sch); 599} 600 601void 602syncache_unreach(struct in_conninfo *inc, struct tcphdr *th) 603{ 604 struct syncache *sc; --- 16 unchanged lines hidden (view full) --- 621 * 622 * See tcp_notify(). 623 */ 624 if ((sc->sc_flags & SCF_UNREACH) == 0 || sc->sc_rxmits < 3 + 1) { 625 sc->sc_flags |= SCF_UNREACH; 626 goto done; 627 } 628 syncache_drop(sc, sch); |
628 tcpstat.tcps_sc_unreach++; | 629 V_tcpstat.tcps_sc_unreach++; |
629done: 630 SCH_UNLOCK(sch); 631} 632 633/* 634 * Build a new TCP socket structure from a syncache entry. 635 */ 636static struct socket * 637syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) 638{ 639 struct inpcb *inp = NULL; 640 struct socket *so; 641 struct tcpcb *tp; 642 char *s; 643 | 630done: 631 SCH_UNLOCK(sch); 632} 633 634/* 635 * Build a new TCP socket structure from a syncache entry. 636 */ 637static struct socket * 638syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) 639{ 640 struct inpcb *inp = NULL; 641 struct socket *so; 642 struct tcpcb *tp; 643 char *s; 644 |
644 INP_INFO_WLOCK_ASSERT(&tcbinfo); | 645 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); |
645 646 /* 647 * Ok, create the full blown connection, and set things up 648 * as they would have been set up if we had created the 649 * connection when the SYN arrived. If we can't create 650 * the connection, abort it. 651 */ 652 so = sonewconn(lso, SS_ISCONNECTED); 653 if (so == NULL) { 654 /* 655 * Drop the connection; we will either send a RST or 656 * have the peer retransmit its SYN again after its 657 * RTO and try again. 658 */ | 646 647 /* 648 * Ok, create the full blown connection, and set things up 649 * as they would have been set up if we had created the 650 * connection when the SYN arrived. If we can't create 651 * the connection, abort it. 652 */ 653 so = sonewconn(lso, SS_ISCONNECTED); 654 if (so == NULL) { 655 /* 656 * Drop the connection; we will either send a RST or 657 * have the peer retransmit its SYN again after its 658 * RTO and try again. 659 */ |
659 tcpstat.tcps_listendrop++; | 660 V_tcpstat.tcps_listendrop++; |
660 if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { 661 log(LOG_DEBUG, "%s; %s: Socket create failed " 662 "due to limits or memory shortage\n", 663 s, __func__); 664 free(s, M_TCPLOG); 665 } 666 goto abort2; 667 } --- 153 unchanged lines hidden (view full) --- 821 * If the SYN,ACK was retransmitted, reset cwnd to 1 segment. 822 */ 823 if (sc->sc_rxmits) 824 tp->snd_cwnd = tp->t_maxseg; 825 tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); 826 827 INP_WUNLOCK(inp); 828 | 661 if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) { 662 log(LOG_DEBUG, "%s; %s: Socket create failed " 663 "due to limits or memory shortage\n", 664 s, __func__); 665 free(s, M_TCPLOG); 666 } 667 goto abort2; 668 } --- 153 unchanged lines hidden (view full) --- 822 * If the SYN,ACK was retransmitted, reset cwnd to 1 segment. 823 */ 824 if (sc->sc_rxmits) 825 tp->snd_cwnd = tp->t_maxseg; 826 tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); 827 828 INP_WUNLOCK(inp); 829 |
829 tcpstat.tcps_accepts++; | 830 V_tcpstat.tcps_accepts++; |
830 return (so); 831 832abort: 833 INP_WUNLOCK(inp); 834abort2: 835 if (so != NULL) 836 soabort(so); 837 return (NULL); --- 14 unchanged lines hidden (view full) --- 852 struct syncache_head *sch; 853 struct syncache scs; 854 char *s; 855 856 /* 857 * Global TCP locks are held because we manipulate the PCB lists 858 * and create a new socket. 859 */ | 831 return (so); 832 833abort: 834 INP_WUNLOCK(inp); 835abort2: 836 if (so != NULL) 837 soabort(so); 838 return (NULL); --- 14 unchanged lines hidden (view full) --- 853 struct syncache_head *sch; 854 struct syncache scs; 855 char *s; 856 857 /* 858 * Global TCP locks are held because we manipulate the PCB lists 859 * and create a new socket. 860 */ |
860 INP_INFO_WLOCK_ASSERT(&tcbinfo); | 861 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); |
861 KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_ACK, 862 ("%s: can handle only ACK", __func__)); 863 864 sc = syncache_lookup(inc, &sch); /* returns locked sch */ 865 SCH_LOCK_ASSERT(sch); 866 if (sc == NULL) { 867 /* 868 * There is no syncache entry, so see if this ACK is --- 21 unchanged lines hidden (view full) --- 890 "SYNCOOKIE authentication, segment rejected " 891 "(probably spoofed)\n", s, __func__); 892 goto failed; 893 } 894 } else { 895 /* Pull out the entry to unlock the bucket row. */ 896 TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash); 897 sch->sch_length--; | 862 KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_ACK, 863 ("%s: can handle only ACK", __func__)); 864 865 sc = syncache_lookup(inc, &sch); /* returns locked sch */ 866 SCH_LOCK_ASSERT(sch); 867 if (sc == NULL) { 868 /* 869 * There is no syncache entry, so see if this ACK is --- 21 unchanged lines hidden (view full) --- 891 "SYNCOOKIE authentication, segment rejected " 892 "(probably spoofed)\n", s, __func__); 893 goto failed; 894 } 895 } else { 896 /* Pull out the entry to unlock the bucket row. */ 897 TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash); 898 sch->sch_length--; |
898 tcp_syncache.cache_count--; | 899 V_tcp_syncache.cache_count--; |
899 SCH_UNLOCK(sch); 900 } 901 902 /* 903 * Segment validation: 904 * ACK must match our initial sequence number + 1 (the SYN|ACK). 905 */ 906 if (th->th_ack != sc->sc_iss + 1 && !TOEPCB_ISSET(sc)) { --- 33 unchanged lines hidden (view full) --- 940 "segment rejected\n", 941 s, __func__, to->to_tsecr, sc->sc_ts); 942 goto failed; 943 } 944 945 *lsop = syncache_socket(sc, *lsop, m); 946 947 if (*lsop == NULL) | 900 SCH_UNLOCK(sch); 901 } 902 903 /* 904 * Segment validation: 905 * ACK must match our initial sequence number + 1 (the SYN|ACK). 906 */ 907 if (th->th_ack != sc->sc_iss + 1 && !TOEPCB_ISSET(sc)) { --- 33 unchanged lines hidden (view full) --- 941 "segment rejected\n", 942 s, __func__, to->to_tsecr, sc->sc_ts); 943 goto failed; 944 } 945 946 *lsop = syncache_socket(sc, *lsop, m); 947 948 if (*lsop == NULL) |
948 tcpstat.tcps_sc_aborted++; | 949 V_tcpstat.tcps_sc_aborted++; |
949 else | 950 else |
950 tcpstat.tcps_sc_completed++; | 951 V_tcpstat.tcps_sc_completed++; |
951 952/* how do we find the inp for the new socket? */ 953 if (sc != &scs) 954 syncache_free(sc); 955 return (1); 956failed: 957 if (sc != NULL && sc != &scs) 958 syncache_free(sc); --- 4 unchanged lines hidden (view full) --- 963} 964 965int 966tcp_offload_syncache_expand(struct in_conninfo *inc, struct tcpopt *to, 967 struct tcphdr *th, struct socket **lsop, struct mbuf *m) 968{ 969 int rc; 970 | 952 953/* how do we find the inp for the new socket? */ 954 if (sc != &scs) 955 syncache_free(sc); 956 return (1); 957failed: 958 if (sc != NULL && sc != &scs) 959 syncache_free(sc); --- 4 unchanged lines hidden (view full) --- 964} 965 966int 967tcp_offload_syncache_expand(struct in_conninfo *inc, struct tcpopt *to, 968 struct tcphdr *th, struct socket **lsop, struct mbuf *m) 969{ 970 int rc; 971 |
971 INP_INFO_WLOCK(&tcbinfo); | 972 INP_INFO_WLOCK(&V_tcbinfo); |
972 rc = syncache_expand(inc, to, th, lsop, m); | 973 rc = syncache_expand(inc, to, th, lsop, m); |
973 INP_INFO_WUNLOCK(&tcbinfo); | 974 INP_INFO_WUNLOCK(&V_tcbinfo); |
974 975 return (rc); 976} 977 978/* 979 * Given a LISTEN socket and an inbound SYN request, add 980 * this to the syn cache, and send back a segment: 981 * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> --- 22 unchanged lines hidden (view full) --- 1004#ifdef INET6 1005 int autoflowlabel = 0; 1006#endif 1007#ifdef MAC 1008 struct label *maclabel; 1009#endif 1010 struct syncache scs; 1011 | 975 976 return (rc); 977} 978 979/* 980 * Given a LISTEN socket and an inbound SYN request, add 981 * this to the syn cache, and send back a segment: 982 * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> --- 22 unchanged lines hidden (view full) --- 1005#ifdef INET6 1006 int autoflowlabel = 0; 1007#endif 1008#ifdef MAC 1009 struct label *maclabel; 1010#endif 1011 struct syncache scs; 1012 |
1012 INP_INFO_WLOCK_ASSERT(&tcbinfo); | 1013 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); |
1013 INP_WLOCK_ASSERT(inp); /* listen socket */ 1014 KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_SYN, 1015 ("%s: unexpected tcp flags", __func__)); 1016 1017 /* 1018 * Combine all so/tp operations very early to drop the INP lock as 1019 * soon as possible. 1020 */ --- 12 unchanged lines hidden (view full) --- 1033 noopt = (tp->t_flags & TF_NOOPT); 1034 1035 so = NULL; 1036 tp = NULL; 1037 1038#ifdef MAC 1039 if (mac_syncache_init(&maclabel) != 0) { 1040 INP_WUNLOCK(inp); | 1014 INP_WLOCK_ASSERT(inp); /* listen socket */ 1015 KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_SYN, 1016 ("%s: unexpected tcp flags", __func__)); 1017 1018 /* 1019 * Combine all so/tp operations very early to drop the INP lock as 1020 * soon as possible. 1021 */ --- 12 unchanged lines hidden (view full) --- 1034 noopt = (tp->t_flags & TF_NOOPT); 1035 1036 so = NULL; 1037 tp = NULL; 1038 1039#ifdef MAC 1040 if (mac_syncache_init(&maclabel) != 0) { 1041 INP_WUNLOCK(inp); |
1041 INP_INFO_WUNLOCK(&tcbinfo); | 1042 INP_INFO_WUNLOCK(&V_tcbinfo); |
1042 goto done; 1043 } else 1044 mac_syncache_create(maclabel, inp); 1045#endif 1046 INP_WUNLOCK(inp); | 1043 goto done; 1044 } else 1045 mac_syncache_create(maclabel, inp); 1046#endif 1047 INP_WUNLOCK(inp); |
1047 INP_INFO_WUNLOCK(&tcbinfo); | 1048 INP_INFO_WUNLOCK(&V_tcbinfo); |
1048 1049 /* 1050 * Remember the IP options, if any. 1051 */ 1052#ifdef INET6 1053 if (!inc->inc_isipv6) 1054#endif 1055 ipopts = (m) ? ip_srcroute(m) : NULL; --- 13 unchanged lines hidden (view full) --- 1069 sc = syncache_lookup(inc, &sch); /* returns locked entry */ 1070 SCH_LOCK_ASSERT(sch); 1071 if (sc != NULL) { 1072#ifndef TCP_OFFLOAD_DISABLE 1073 if (sc->sc_tu) 1074 sc->sc_tu->tu_syncache_event(TOE_SC_ENTRY_PRESENT, 1075 sc->sc_toepcb); 1076#endif | 1049 1050 /* 1051 * Remember the IP options, if any. 1052 */ 1053#ifdef INET6 1054 if (!inc->inc_isipv6) 1055#endif 1056 ipopts = (m) ? ip_srcroute(m) : NULL; --- 13 unchanged lines hidden (view full) --- 1070 sc = syncache_lookup(inc, &sch); /* returns locked entry */ 1071 SCH_LOCK_ASSERT(sch); 1072 if (sc != NULL) { 1073#ifndef TCP_OFFLOAD_DISABLE 1074 if (sc->sc_tu) 1075 sc->sc_tu->tu_syncache_event(TOE_SC_ENTRY_PRESENT, 1076 sc->sc_toepcb); 1077#endif |
1077 tcpstat.tcps_sc_dupsyn++; | 1078 V_tcpstat.tcps_sc_dupsyn++; |
1078 if (ipopts) { 1079 /* 1080 * If we were remembering a previous source route, 1081 * forget it and use the new one we've been given. 1082 */ 1083 if (sc->sc_ipopts) 1084 (void) m_free(sc->sc_ipopts); 1085 sc->sc_ipopts = ipopts; --- 20 unchanged lines hidden (view full) --- 1106 log(LOG_DEBUG, "%s; %s: Received duplicate SYN, " 1107 "resetting timer and retransmitting SYN|ACK\n", 1108 s, __func__); 1109 free(s, M_TCPLOG); 1110 } 1111 if (!TOEPCB_ISSET(sc) && syncache_respond(sc) == 0) { 1112 sc->sc_rxmits = 0; 1113 syncache_timeout(sc, sch, 1); | 1079 if (ipopts) { 1080 /* 1081 * If we were remembering a previous source route, 1082 * forget it and use the new one we've been given. 1083 */ 1084 if (sc->sc_ipopts) 1085 (void) m_free(sc->sc_ipopts); 1086 sc->sc_ipopts = ipopts; --- 20 unchanged lines hidden (view full) --- 1107 log(LOG_DEBUG, "%s; %s: Received duplicate SYN, " 1108 "resetting timer and retransmitting SYN|ACK\n", 1109 s, __func__); 1110 free(s, M_TCPLOG); 1111 } 1112 if (!TOEPCB_ISSET(sc) && syncache_respond(sc) == 0) { 1113 sc->sc_rxmits = 0; 1114 syncache_timeout(sc, sch, 1); |
1114 tcpstat.tcps_sndacks++; 1115 tcpstat.tcps_sndtotal++; | 1115 V_tcpstat.tcps_sndacks++; 1116 V_tcpstat.tcps_sndtotal++; |
1116 } 1117 SCH_UNLOCK(sch); 1118 goto done; 1119 } 1120 | 1117 } 1118 SCH_UNLOCK(sch); 1119 goto done; 1120 } 1121 |
1121 sc = uma_zalloc(tcp_syncache.zone, M_NOWAIT | M_ZERO); | 1122 sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO); |
1122 if (sc == NULL) { 1123 /* 1124 * The zone allocator couldn't provide more entries. 1125 * Treat this as if the cache was full; drop the oldest 1126 * entry and insert the new one. 1127 */ | 1123 if (sc == NULL) { 1124 /* 1125 * The zone allocator couldn't provide more entries. 1126 * Treat this as if the cache was full; drop the oldest 1127 * entry and insert the new one. 1128 */ |
1128 tcpstat.tcps_sc_zonefail++; | 1129 V_tcpstat.tcps_sc_zonefail++; |
1129 if ((sc = TAILQ_LAST(&sch->sch_bucket, sch_head)) != NULL) 1130 syncache_drop(sc, sch); | 1130 if ((sc = TAILQ_LAST(&sch->sch_bucket, sch_head)) != NULL) 1131 syncache_drop(sc, sch); |
1131 sc = uma_zalloc(tcp_syncache.zone, M_NOWAIT | M_ZERO); | 1132 sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO); |
1132 if (sc == NULL) { 1133 if (tcp_syncookies) { 1134 bzero(&scs, sizeof(scs)); 1135 sc = &scs; 1136 } else { 1137 SCH_UNLOCK(sch); 1138 if (ipopts) 1139 (void) m_free(ipopts); --- 30 unchanged lines hidden (view full) --- 1170 /* 1171 * Initial receive window: clip sbspace to [0 .. TCP_MAXWIN]. 1172 * win was derived from socket earlier in the function. 1173 */ 1174 win = imax(win, 0); 1175 win = imin(win, TCP_MAXWIN); 1176 sc->sc_wnd = win; 1177 | 1133 if (sc == NULL) { 1134 if (tcp_syncookies) { 1135 bzero(&scs, sizeof(scs)); 1136 sc = &scs; 1137 } else { 1138 SCH_UNLOCK(sch); 1139 if (ipopts) 1140 (void) m_free(ipopts); --- 30 unchanged lines hidden (view full) --- 1171 /* 1172 * Initial receive window: clip sbspace to [0 .. TCP_MAXWIN]. 1173 * win was derived from socket earlier in the function. 1174 */ 1175 win = imax(win, 0); 1176 win = imin(win, TCP_MAXWIN); 1177 sc->sc_wnd = win; 1178 |
1178 if (tcp_do_rfc1323) { | 1179 if (V_tcp_do_rfc1323) { |
1179 /* 1180 * A timestamp received in a SYN makes 1181 * it ok to send timestamp requests and replies. 1182 */ 1183 if (to->to_flags & TOF_TS) { 1184 sc->sc_tsreflect = to->to_tsval; 1185 sc->sc_ts = ticks; 1186 sc->sc_flags |= SCF_TIMESTAMP; --- 42 unchanged lines hidden (view full) --- 1229 sc->sc_flags |= SCF_SIGNATURE; 1230#endif 1231 if (to->to_flags & TOF_SACKPERM) 1232 sc->sc_flags |= SCF_SACK; 1233 if (to->to_flags & TOF_MSS) 1234 sc->sc_peer_mss = to->to_mss; /* peer mss may be zero */ 1235 if (noopt) 1236 sc->sc_flags |= SCF_NOOPT; | 1180 /* 1181 * A timestamp received in a SYN makes 1182 * it ok to send timestamp requests and replies. 1183 */ 1184 if (to->to_flags & TOF_TS) { 1185 sc->sc_tsreflect = to->to_tsval; 1186 sc->sc_ts = ticks; 1187 sc->sc_flags |= SCF_TIMESTAMP; --- 42 unchanged lines hidden (view full) --- 1230 sc->sc_flags |= SCF_SIGNATURE; 1231#endif 1232 if (to->to_flags & TOF_SACKPERM) 1233 sc->sc_flags |= SCF_SACK; 1234 if (to->to_flags & TOF_MSS) 1235 sc->sc_peer_mss = to->to_mss; /* peer mss may be zero */ 1236 if (noopt) 1237 sc->sc_flags |= SCF_NOOPT; |
1237 if ((th->th_flags & (TH_ECE|TH_CWR)) && tcp_do_ecn) | 1238 if ((th->th_flags & (TH_ECE|TH_CWR)) && V_tcp_do_ecn) |
1238 sc->sc_flags |= SCF_ECN; 1239 1240 if (tcp_syncookies) { 1241 syncookie_generate(sch, sc, &flowtmp); 1242#ifdef INET6 1243 if (autoflowlabel) 1244 sc->sc_flowlabel = flowtmp; 1245#endif --- 9 unchanged lines hidden (view full) --- 1255 /* 1256 * Do a standard 3-way handshake. 1257 */ 1258 if (TOEPCB_ISSET(sc) || syncache_respond(sc) == 0) { 1259 if (tcp_syncookies && tcp_syncookiesonly && sc != &scs) 1260 syncache_free(sc); 1261 else if (sc != &scs) 1262 syncache_insert(sc, sch); /* locks and unlocks sch */ | 1239 sc->sc_flags |= SCF_ECN; 1240 1241 if (tcp_syncookies) { 1242 syncookie_generate(sch, sc, &flowtmp); 1243#ifdef INET6 1244 if (autoflowlabel) 1245 sc->sc_flowlabel = flowtmp; 1246#endif --- 9 unchanged lines hidden (view full) --- 1256 /* 1257 * Do a standard 3-way handshake. 1258 */ 1259 if (TOEPCB_ISSET(sc) || syncache_respond(sc) == 0) { 1260 if (tcp_syncookies && tcp_syncookiesonly && sc != &scs) 1261 syncache_free(sc); 1262 else if (sc != &scs) 1263 syncache_insert(sc, sch); /* locks and unlocks sch */ |
1263 tcpstat.tcps_sndacks++; 1264 tcpstat.tcps_sndtotal++; | 1264 V_tcpstat.tcps_sndacks++; 1265 V_tcpstat.tcps_sndtotal++; |
1265 } else { 1266 if (sc != &scs) 1267 syncache_free(sc); | 1266 } else { 1267 if (sc != &scs) 1268 syncache_free(sc); |
1268 tcpstat.tcps_sc_dropped++; | 1269 V_tcpstat.tcps_sc_dropped++; |
1269 } 1270 1271done: 1272#ifdef MAC 1273 if (sc == &scs) 1274 mac_syncache_destroy(&maclabel); 1275#endif 1276 if (m) { --- 22 unchanged lines hidden (view full) --- 1299 (sc->sc_inc.inc_isipv6) ? sizeof(struct ip6_hdr) : 1300#endif 1301 sizeof(struct ip); 1302 tlen = hlen + sizeof(struct tcphdr); 1303 1304 /* Determine MSS we advertize to other end of connection. */ 1305 mssopt = tcp_mssopt(&sc->sc_inc); 1306 if (sc->sc_peer_mss) | 1270 } 1271 1272done: 1273#ifdef MAC 1274 if (sc == &scs) 1275 mac_syncache_destroy(&maclabel); 1276#endif 1277 if (m) { --- 22 unchanged lines hidden (view full) --- 1300 (sc->sc_inc.inc_isipv6) ? sizeof(struct ip6_hdr) : 1301#endif 1302 sizeof(struct ip); 1303 tlen = hlen + sizeof(struct tcphdr); 1304 1305 /* Determine MSS we advertize to other end of connection. */ 1306 mssopt = tcp_mssopt(&sc->sc_inc); 1307 if (sc->sc_peer_mss) |
1307 mssopt = max( min(sc->sc_peer_mss, mssopt), tcp_minmss); | 1308 mssopt = max( min(sc->sc_peer_mss, mssopt), V_tcp_minmss); |
1308 1309 /* XXX: Assume that the entire packet will fit in a header mbuf. */ 1310 KASSERT(max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN, 1311 ("syncache: mbuf too small")); 1312 1313 /* Create the IP+TCP header from scratch. */ 1314 m = m_gethdr(M_DONTWAIT, MT_DATA); 1315 if (m == NULL) --- 37 unchanged lines hidden (view full) --- 1353 1354 /* 1355 * See if we should do MTU discovery. Route lookups are 1356 * expensive, so we will only unset the DF bit if: 1357 * 1358 * 1) path_mtu_discovery is disabled 1359 * 2) the SCF_UNREACH flag has been set 1360 */ | 1309 1310 /* XXX: Assume that the entire packet will fit in a header mbuf. */ 1311 KASSERT(max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN, 1312 ("syncache: mbuf too small")); 1313 1314 /* Create the IP+TCP header from scratch. */ 1315 m = m_gethdr(M_DONTWAIT, MT_DATA); 1316 if (m == NULL) --- 37 unchanged lines hidden (view full) --- 1354 1355 /* 1356 * See if we should do MTU discovery. Route lookups are 1357 * expensive, so we will only unset the DF bit if: 1358 * 1359 * 1) path_mtu_discovery is disabled 1360 * 2) the SCF_UNREACH flag has been set 1361 */ |
1361 if (path_mtu_discovery && ((sc->sc_flags & SCF_UNREACH) == 0)) | 1362 if (V_path_mtu_discovery && ((sc->sc_flags & SCF_UNREACH) == 0)) |
1362 ip->ip_off |= IP_DF; 1363 1364 th = (struct tcphdr *)(ip + 1); 1365 } 1366 th->th_sport = sc->sc_inc.inc_lport; 1367 th->th_dport = sc->sc_inc.inc_fport; 1368 1369 th->th_seq = htonl(sc->sc_iss); 1370 th->th_ack = htonl(sc->sc_irs + 1); 1371 th->th_off = sizeof(struct tcphdr) >> 2; 1372 th->th_x2 = 0; 1373 th->th_flags = TH_SYN|TH_ACK; 1374 th->th_win = htons(sc->sc_wnd); 1375 th->th_urp = 0; 1376 1377 if (sc->sc_flags & SCF_ECN) { 1378 th->th_flags |= TH_ECE; | 1363 ip->ip_off |= IP_DF; 1364 1365 th = (struct tcphdr *)(ip + 1); 1366 } 1367 th->th_sport = sc->sc_inc.inc_lport; 1368 th->th_dport = sc->sc_inc.inc_fport; 1369 1370 th->th_seq = htonl(sc->sc_iss); 1371 th->th_ack = htonl(sc->sc_irs + 1); 1372 th->th_off = sizeof(struct tcphdr) >> 2; 1373 th->th_x2 = 0; 1374 th->th_flags = TH_SYN|TH_ACK; 1375 th->th_win = htons(sc->sc_wnd); 1376 th->th_urp = 0; 1377 1378 if (sc->sc_flags & SCF_ECN) { 1379 th->th_flags |= TH_ECE; |
1379 tcpstat.tcps_ecn_shs++; | 1380 V_tcpstat.tcps_ecn_shs++; |
1380 } 1381 1382 /* Tack on the TCP options. */ 1383 if ((sc->sc_flags & SCF_NOOPT) == 0) { 1384 to.to_flags = 0; 1385 1386 to.to_mss = mssopt; 1387 to.to_flags = TOF_MSS; --- 61 unchanged lines hidden (view full) --- 1449} 1450 1451void 1452tcp_offload_syncache_add(struct in_conninfo *inc, struct tcpopt *to, 1453 struct tcphdr *th, struct inpcb *inp, struct socket **lsop, 1454 struct toe_usrreqs *tu, void *toepcb) 1455{ 1456 | 1381 } 1382 1383 /* Tack on the TCP options. */ 1384 if ((sc->sc_flags & SCF_NOOPT) == 0) { 1385 to.to_flags = 0; 1386 1387 to.to_mss = mssopt; 1388 to.to_flags = TOF_MSS; --- 61 unchanged lines hidden (view full) --- 1450} 1451 1452void 1453tcp_offload_syncache_add(struct in_conninfo *inc, struct tcpopt *to, 1454 struct tcphdr *th, struct inpcb *inp, struct socket **lsop, 1455 struct toe_usrreqs *tu, void *toepcb) 1456{ 1457 |
1457 INP_INFO_WLOCK(&tcbinfo); | 1458 INP_INFO_WLOCK(&V_tcbinfo); |
1458 INP_WLOCK(inp); 1459 _syncache_add(inc, to, th, inp, lsop, NULL, tu, toepcb); 1460} 1461 1462/* 1463 * The purpose of SYN cookies is to avoid keeping track of all SYN's we 1464 * receive and to be able to handle SYN floods from bogus source addresses 1465 * (where we will never receive any reply). SYN floods try to exhaust all --- 97 unchanged lines hidden (view full) --- 1563 secbits[i] = arc4random(); 1564 sch->sch_reseed = time_uptime + SYNCOOKIE_LIFETIME; 1565 } 1566 1567 /* Secret rotation offset. */ 1568 off = sc->sc_iss & 0x7; /* iss was randomized before */ 1569 1570 /* Maximum segment size calculation. */ | 1459 INP_WLOCK(inp); 1460 _syncache_add(inc, to, th, inp, lsop, NULL, tu, toepcb); 1461} 1462 1463/* 1464 * The purpose of SYN cookies is to avoid keeping track of all SYN's we 1465 * receive and to be able to handle SYN floods from bogus source addresses 1466 * (where we will never receive any reply). SYN floods try to exhaust all --- 97 unchanged lines hidden (view full) --- 1564 secbits[i] = arc4random(); 1565 sch->sch_reseed = time_uptime + SYNCOOKIE_LIFETIME; 1566 } 1567 1568 /* Secret rotation offset. */ 1569 off = sc->sc_iss & 0x7; /* iss was randomized before */ 1570 1571 /* Maximum segment size calculation. */ |
1571 pmss = max( min(sc->sc_peer_mss, tcp_mssopt(&sc->sc_inc)), tcp_minmss); | 1572 pmss = max( min(sc->sc_peer_mss, tcp_mssopt(&sc->sc_inc)), V_tcp_minmss); |
1572 for (mss = sizeof(tcp_sc_msstab) / sizeof(int) - 1; mss > 0; mss--) 1573 if (tcp_sc_msstab[mss] <= pmss) 1574 break; 1575 1576 /* Fold parameters and MD5 digest into the ISN we will send. */ 1577 data = sch->sch_oddeven;/* odd or even secret, 1 bit */ 1578 data |= off << 1; /* secret offset, derived from iss, 3 bits */ 1579 data |= mss << 4; /* mss, 3 bits */ --- 21 unchanged lines hidden (view full) --- 1601 data |= sc->sc_requested_s_scale << 2; /* SWIN scale, 4 bits */ 1602 data |= sc->sc_requested_r_scale << 6; /* RWIN scale, 4 bits */ 1603 data |= md5_buffer[2] << 10; /* more digest bits */ 1604 data ^= md5_buffer[3]; 1605 sc->sc_ts = data; 1606 sc->sc_tsoff = data - ticks; /* after XOR */ 1607 } 1608 | 1573 for (mss = sizeof(tcp_sc_msstab) / sizeof(int) - 1; mss > 0; mss--) 1574 if (tcp_sc_msstab[mss] <= pmss) 1575 break; 1576 1577 /* Fold parameters and MD5 digest into the ISN we will send. */ 1578 data = sch->sch_oddeven;/* odd or even secret, 1 bit */ 1579 data |= off << 1; /* secret offset, derived from iss, 3 bits */ 1580 data |= mss << 4; /* mss, 3 bits */ --- 21 unchanged lines hidden (view full) --- 1602 data |= sc->sc_requested_s_scale << 2; /* SWIN scale, 4 bits */ 1603 data |= sc->sc_requested_r_scale << 6; /* RWIN scale, 4 bits */ 1604 data |= md5_buffer[2] << 10; /* more digest bits */ 1605 data ^= md5_buffer[3]; 1606 sc->sc_ts = data; 1607 sc->sc_tsoff = data - ticks; /* after XOR */ 1608 } 1609 |
1609 tcpstat.tcps_sc_sendcookie++; | 1610 V_tcpstat.tcps_sc_sendcookie++; |
1610 return; 1611} 1612 1613static struct syncache * 1614syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch, 1615 struct syncache *sc, struct tcpopt *to, struct tcphdr *th, 1616 struct socket *so) 1617{ --- 86 unchanged lines hidden (view full) --- 1704 wnd = sbspace(&so->so_rcv); 1705 wnd = imax(wnd, 0); 1706 wnd = imin(wnd, TCP_MAXWIN); 1707 sc->sc_wnd = wnd; 1708 1709 sc->sc_rxmits = 0; 1710 sc->sc_peer_mss = tcp_sc_msstab[mss]; 1711 | 1611 return; 1612} 1613 1614static struct syncache * 1615syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch, 1616 struct syncache *sc, struct tcpopt *to, struct tcphdr *th, 1617 struct socket *so) 1618{ --- 86 unchanged lines hidden (view full) --- 1705 wnd = sbspace(&so->so_rcv); 1706 wnd = imax(wnd, 0); 1707 wnd = imin(wnd, TCP_MAXWIN); 1708 sc->sc_wnd = wnd; 1709 1710 sc->sc_rxmits = 0; 1711 sc->sc_peer_mss = tcp_sc_msstab[mss]; 1712 |
1712 tcpstat.tcps_sc_recvcookie++; | 1713 V_tcpstat.tcps_sc_recvcookie++; |
1713 return (sc); 1714} 1715 1716/* 1717 * Returns the current number of syncache entries. This number 1718 * will probably change before you get around to calling 1719 * syncache_pcblist. 1720 */ 1721 1722int 1723syncache_pcbcount(void) 1724{ 1725 struct syncache_head *sch; 1726 int count, i; 1727 | 1714 return (sc); 1715} 1716 1717/* 1718 * Returns the current number of syncache entries. This number 1719 * will probably change before you get around to calling 1720 * syncache_pcblist. 1721 */ 1722 1723int 1724syncache_pcbcount(void) 1725{ 1726 struct syncache_head *sch; 1727 int count, i; 1728 |
1728 for (count = 0, i = 0; i < tcp_syncache.hashsize; i++) { | 1729 for (count = 0, i = 0; i < V_tcp_syncache.hashsize; i++) { |
1729 /* No need to lock for a read. */ | 1730 /* No need to lock for a read. */ |
1730 sch = &tcp_syncache.hashbase[i]; | 1731 sch = &V_tcp_syncache.hashbase[i]; |
1731 count += sch->sch_length; 1732 } 1733 return count; 1734} 1735 1736/* 1737 * Exports the syncache entries to userland so that netstat can display 1738 * them alongside the other sockets. This function is intended to be --- 6 unchanged lines hidden (view full) --- 1745int 1746syncache_pcblist(struct sysctl_req *req, int max_pcbs, int *pcbs_exported) 1747{ 1748 struct xtcpcb xt; 1749 struct syncache *sc; 1750 struct syncache_head *sch; 1751 int count, error, i; 1752 | 1732 count += sch->sch_length; 1733 } 1734 return count; 1735} 1736 1737/* 1738 * Exports the syncache entries to userland so that netstat can display 1739 * them alongside the other sockets. This function is intended to be --- 6 unchanged lines hidden (view full) --- 1746int 1747syncache_pcblist(struct sysctl_req *req, int max_pcbs, int *pcbs_exported) 1748{ 1749 struct xtcpcb xt; 1750 struct syncache *sc; 1751 struct syncache_head *sch; 1752 int count, error, i; 1753 |
1753 for (count = 0, error = 0, i = 0; i < tcp_syncache.hashsize; i++) { 1754 sch = &tcp_syncache.hashbase[i]; | 1754 for (count = 0, error = 0, i = 0; i < V_tcp_syncache.hashsize; i++) { 1755 sch = &V_tcp_syncache.hashbase[i]; |
1755 SCH_LOCK(sch); 1756 TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { 1757 if (count >= max_pcbs) { 1758 SCH_UNLOCK(sch); 1759 goto exit; 1760 } 1761 bzero(&xt, sizeof(xt)); 1762 xt.xt_len = sizeof(xt); --- 24 unchanged lines hidden --- | 1756 SCH_LOCK(sch); 1757 TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { 1758 if (count >= max_pcbs) { 1759 SCH_UNLOCK(sch); 1760 goto exit; 1761 } 1762 bzero(&xt, sizeof(xt)); 1763 xt.xt_len = sizeof(xt); --- 24 unchanged lines hidden --- |