|
102 | 102 |
|
103 | 103 | #include <security/mac/mac_framework.h> |
104 | 104 |
|
105 | | -VNET_DEFINE_STATIC(int, tcp_syncookies) = 1; |
| 105 | +VNET_DEFINE_STATIC(bool, tcp_syncookies) = true; |
106 | 106 | #define V_tcp_syncookies VNET(tcp_syncookies) |
107 | | -SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_VNET | CTLFLAG_RW, |
| 107 | +SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_VNET | CTLFLAG_RW, |
108 | 108 | &VNET_NAME(tcp_syncookies), 0, |
109 | 109 | "Use TCP SYN cookies if the syncache overflows"); |
110 | 110 |
|
111 | | -VNET_DEFINE_STATIC(int, tcp_syncookiesonly) = 0; |
| 111 | +VNET_DEFINE_STATIC(bool, tcp_syncookiesonly) = false; |
112 | 112 | #define V_tcp_syncookiesonly VNET(tcp_syncookiesonly) |
113 | | -SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW, |
| 113 | +SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW, |
114 | 114 | &VNET_NAME(tcp_syncookiesonly), 0, |
115 | 115 | "Use only TCP SYN cookies"); |
116 | 116 |
|
@@ -553,9 +553,8 @@ syncache_timer(void *xsch) |
553 | 553 | static inline bool |
554 | 554 | syncache_cookiesonly(void) |
555 | 555 | { |
556 | | - |
557 | | - return (V_tcp_syncookies && (V_tcp_syncache.paused || |
558 | | - V_tcp_syncookiesonly)); |
| 556 | + return ((V_tcp_syncookies && V_tcp_syncache.paused) || |
| 557 | + V_tcp_syncookiesonly); |
559 | 558 | } |
560 | 559 |
|
561 | 560 | /* |
@@ -1083,40 +1082,48 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, |
1083 | 1082 | #endif |
1084 | 1083 |
|
1085 | 1084 | if (sc == NULL) { |
1086 | | - /* |
1087 | | - * There is no syncache entry, so see if this ACK is |
1088 | | - * a returning syncookie. To do this, first: |
1089 | | - * A. Check if syncookies are used in case of syncache |
1090 | | - * overflows |
1091 | | - * B. See if this socket has had a syncache entry dropped in |
1092 | | - * the recent past. We don't want to accept a bogus |
1093 | | - * syncookie if we've never received a SYN or accept it |
1094 | | - * twice. |
1095 | | - * C. check that the syncookie is valid. If it is, then |
1096 | | - * cobble up a fake syncache entry, and return. |
1097 | | - */ |
1098 | | - if (locked && !V_tcp_syncookies) { |
1099 | | - SCH_UNLOCK(sch); |
1100 | | - TCPSTAT_INC(tcps_sc_spurcookie); |
1101 | | - if ((s = tcp_log_addrs(inc, th, NULL, NULL))) |
1102 | | - log(LOG_DEBUG, "%s; %s: Spurious ACK, " |
1103 | | - "segment rejected (syncookies disabled)\n", |
1104 | | - s, __func__); |
1105 | | - goto failed; |
1106 | | - } |
1107 | | - if (locked && !V_tcp_syncookiesonly && |
1108 | | - sch->sch_last_overflow < time_uptime - SYNCOOKIE_LIFETIME) { |
| 1085 | + if (locked) { |
| 1086 | + /* |
| 1087 | + * The syncache is currently in use (neither disabled, |
| 1088 | + * nor paused), but no entry was found. |
| 1089 | + */ |
| 1090 | + if (!V_tcp_syncookies) { |
| 1091 | + /* |
| 1092 | + * Since no syncookies are used in case of |
| 1093 | + * a bucket overflow, don't even check for |
| 1094 | + * a valid syncookie. |
| 1095 | + */ |
| 1096 | + SCH_UNLOCK(sch); |
| 1097 | + TCPSTAT_INC(tcps_sc_spurcookie); |
| 1098 | + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) |
| 1099 | + log(LOG_DEBUG, "%s; %s: Spurious ACK, " |
| 1100 | + "segment rejected " |
| 1101 | + "(syncookies disabled)\n", |
| 1102 | + s, __func__); |
| 1103 | + goto failed; |
| 1104 | + } |
| 1105 | + if (sch->sch_last_overflow < |
| 1106 | + time_uptime - SYNCOOKIE_LIFETIME) { |
| 1107 | + /* |
| 1108 | + * Since the bucket did not overflow recently, |
| 1109 | + * don't even check for a valid syncookie. |
| 1110 | + */ |
| 1111 | + SCH_UNLOCK(sch); |
| 1112 | + TCPSTAT_INC(tcps_sc_spurcookie); |
| 1113 | + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) |
| 1114 | + log(LOG_DEBUG, "%s; %s: Spurious ACK, " |
| 1115 | + "segment rejected " |
| 1116 | + "(no syncache entry)\n", |
| 1117 | + s, __func__); |
| 1118 | + goto failed; |
| 1119 | + } |
1109 | 1120 | SCH_UNLOCK(sch); |
1110 | | - TCPSTAT_INC(tcps_sc_spurcookie); |
1111 | | - if ((s = tcp_log_addrs(inc, th, NULL, NULL))) |
1112 | | - log(LOG_DEBUG, "%s; %s: Spurious ACK, " |
1113 | | - "segment rejected (no syncache entry)\n", |
1114 | | - s, __func__); |
1115 | | - goto failed; |
1116 | 1121 | } |
1117 | | - if (locked) |
1118 | | - SCH_UNLOCK(sch); |
1119 | 1122 | bzero(&scs, sizeof(scs)); |
| 1123 | + /* |
| 1124 | + * Now check, if the syncookie is valid. If it is, create an on |
| 1125 | + * stack syncache entry. |
| 1126 | + */ |
1120 | 1127 | if (syncookie_expand(inc, sch, &scs, th, to, *lsop, port)) { |
1121 | 1128 | sc = &scs; |
1122 | 1129 | TCPSTAT_INC(tcps_sc_recvcookie); |
@@ -1291,7 +1298,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, |
1291 | 1298 | if (__predict_false(*lsop == NULL)) { |
1292 | 1299 | TCPSTAT_INC(tcps_sc_aborted); |
1293 | 1300 | TCPSTATES_DEC(TCPS_SYN_RECEIVED); |
1294 | | - } else |
| 1301 | + } else if (sc != &scs) |
1295 | 1302 | TCPSTAT_INC(tcps_sc_completed); |
1296 | 1303 |
|
1297 | 1304 | if (sc != &scs) |
@@ -1718,13 +1725,13 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, |
1718 | 1725 | if (V_tcp_do_ecn && (tp->t_flags2 & TF2_CANNOT_DO_ECN) == 0) |
1719 | 1726 | sc->sc_flags |= tcp_ecn_syncache_add(tcp_get_flags(th), iptos); |
1720 | 1727 |
|
1721 | | - if (V_tcp_syncookies) |
| 1728 | + if (V_tcp_syncookies || V_tcp_syncookiesonly) |
1722 | 1729 | sc->sc_iss = syncookie_generate(sch, sc); |
1723 | 1730 | else |
1724 | 1731 | sc->sc_iss = arc4random(); |
1725 | 1732 | #ifdef INET6 |
1726 | 1733 | if (autoflowlabel) { |
1727 | | - if (V_tcp_syncookies) |
| 1734 | + if (V_tcp_syncookies || V_tcp_syncookiesonly) |
1728 | 1735 | sc->sc_flowlabel = sc->sc_iss; |
1729 | 1736 | else |
1730 | 1737 | sc->sc_flowlabel = ip6_randomflowlabel(); |
|
0 commit comments