* We have overflowed a bucket. Let's pause dealing with the syncache. * This function will increment the bucketoverflow statistics appropriately * (once per pause when pausing is enabled; otherwise, once per overflow). */
| 2450 | * (once per pause when pausing is enabled; otherwise, once per overflow). |
| 2451 | */ |
| 2452 | static void |
| 2453 | syncache_pause(struct in_conninfo *inc) |
| 2454 | { |
| 2455 | time_t delta; |
| 2456 | const char *s; |
| 2457 | |
| 2458 | /* XXX: |
| 2459 | * 2. Add sysctl read here so we don't get the benefit of this |
| 2460 | * change without the new sysctl. |
| 2461 | */ |
| 2462 | |
| 2463 | /* |
| 2464 | * Try an unlocked read. If we already know that another thread |
| 2465 | * has activated the feature, there is no need to proceed. |
| 2466 | */ |
| 2467 | if (V_tcp_syncache.paused) |
| 2468 | return; |
| 2469 | |
| 2470 | /* Are cookied enabled? If not, we can't pause. */ |
| 2471 | if (!V_tcp_syncookies) { |
| 2472 | TCPSTAT_INC(tcps_sc_bucketoverflow); |
| 2473 | return; |
| 2474 | } |
| 2475 | |
| 2476 | /* |
| 2477 | * We may be the first thread to find an overflow. Get the lock |
| 2478 | * and evaluate if we need to take action. |
| 2479 | */ |
| 2480 | mtx_lock(&V_tcp_syncache.pause_mtx); |
| 2481 | if (V_tcp_syncache.paused) { |
| 2482 | mtx_unlock(&V_tcp_syncache.pause_mtx); |
| 2483 | return; |
| 2484 | } |
| 2485 | |
| 2486 | /* Activate protection. */ |
| 2487 | V_tcp_syncache.paused = true; |
| 2488 | TCPSTAT_INC(tcps_sc_bucketoverflow); |
| 2489 | |
| 2490 | /* |
| 2491 | * Determine the last backoff time. If we are seeing a re-newed |
| 2492 | * attack within that same time after last reactivating the syncache, |
| 2493 | * consider it an extension of the same attack. |
| 2494 | */ |
| 2495 | delta = TCP_SYNCACHE_PAUSE_TIME << V_tcp_syncache.pause_backoff; |
| 2496 | if (V_tcp_syncache.pause_until + delta - time_uptime > 0) { |
| 2497 | if (V_tcp_syncache.pause_backoff < TCP_SYNCACHE_MAX_BACKOFF) { |
| 2498 | delta <<= 1; |
| 2499 | V_tcp_syncache.pause_backoff++; |
| 2500 | } |
| 2501 | } else { |
| 2502 | delta = TCP_SYNCACHE_PAUSE_TIME; |
| 2503 | V_tcp_syncache.pause_backoff = 0; |
| 2504 | } |
| 2505 | |
| 2506 | /* Log a warning, including IP addresses, if able. */ |
| 2507 | if (inc != NULL) |
| 2508 | s = tcp_log_addrs(inc, NULL, NULL, NULL); |
| 2509 | else |
no test coverage detected