| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: tcp_input.c,v 1.357.4.3 2018/03/30 11:17:19 martin Exp $ */ | | 1 | /* $NetBSD: tcp_input.c,v 1.357.4.4 2020/07/07 11:56:57 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -138,27 +138,27 @@ | | | @@ -138,27 +138,27 @@ |
138 | */ | | 138 | */ |
139 | | | 139 | |
140 | /* | | 140 | /* |
141 | * TODO list for SYN cache stuff: | | 141 | * TODO list for SYN cache stuff: |
142 | * | | 142 | * |
143 | * Find room for a "state" field, which is needed to keep a | | 143 | * Find room for a "state" field, which is needed to keep a |
144 | * compressed state for TIME_WAIT TCBs. It's been noted already | | 144 | * compressed state for TIME_WAIT TCBs. It's been noted already |
145 | * that this is fairly important for very high-volume web and | | 145 | * that this is fairly important for very high-volume web and |
146 | * mail servers, which use a large number of short-lived | | 146 | * mail servers, which use a large number of short-lived |
147 | * connections. | | 147 | * connections. |
148 | */ | | 148 | */ |
149 | | | 149 | |
150 | #include <sys/cdefs.h> | | 150 | #include <sys/cdefs.h> |
151 | __KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.357.4.3 2018/03/30 11:17:19 martin Exp $"); | | 151 | __KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.357.4.4 2020/07/07 11:56:57 martin Exp $"); |
152 | | | 152 | |
153 | #ifdef _KERNEL_OPT | | 153 | #ifdef _KERNEL_OPT |
154 | #include "opt_inet.h" | | 154 | #include "opt_inet.h" |
155 | #include "opt_ipsec.h" | | 155 | #include "opt_ipsec.h" |
156 | #include "opt_inet_csum.h" | | 156 | #include "opt_inet_csum.h" |
157 | #include "opt_tcp_debug.h" | | 157 | #include "opt_tcp_debug.h" |
158 | #endif | | 158 | #endif |
159 | | | 159 | |
160 | #include <sys/param.h> | | 160 | #include <sys/param.h> |
161 | #include <sys/systm.h> | | 161 | #include <sys/systm.h> |
162 | #include <sys/malloc.h> | | 162 | #include <sys/malloc.h> |
163 | #include <sys/mbuf.h> | | 163 | #include <sys/mbuf.h> |
164 | #include <sys/protosw.h> | | 164 | #include <sys/protosw.h> |
| @@ -1263,56 +1263,70 @@ tcp_input(struct mbuf *m, ...) | | | @@ -1263,56 +1263,70 @@ tcp_input(struct mbuf *m, ...) |
1263 | */ | | 1263 | */ |
1264 | if (m->m_flags & (M_BCAST|M_MCAST)) { | | 1264 | if (m->m_flags & (M_BCAST|M_MCAST)) { |
1265 | /* XXX stat */ | | 1265 | /* XXX stat */ |
1266 | goto drop; | | 1266 | goto drop; |
1267 | } | | 1267 | } |
1268 | #ifdef INET6 | | 1268 | #ifdef INET6 |
1269 | if (m->m_flags & M_ANYCAST6) { | | 1269 | if (m->m_flags & M_ANYCAST6) { |
1270 | /* XXX stat */ | | 1270 | /* XXX stat */ |
1271 | goto drop; | | 1271 | goto drop; |
1272 | } | | 1272 | } |
1273 | #endif | | 1273 | #endif |
1274 | | | 1274 | |
1275 | /* | | 1275 | /* |
| | | 1276 | * Enforce alignment requirements that are violated in |
| | | 1277 | * some cases, see kern/50766 for details. |
| | | 1278 | */ |
| | | 1279 | if (TCP_HDR_ALIGNED_P(th) == 0) { |
| | | 1280 | m = m_copyup(m, toff + sizeof(struct tcphdr), 0); |
| | | 1281 | if (m == NULL) { |
| | | 1282 | TCP_STATINC(TCP_STAT_RCVSHORT); |
| | | 1283 | return; |
| | | 1284 | } |
| | | 1285 | th = (struct tcphdr *)(mtod(m, char *) + toff); |
| | | 1286 | } |
| | | 1287 | KASSERT(TCP_HDR_ALIGNED_P(th)); |
| | | 1288 | |
| | | 1289 | /* |
1276 | * Get IP and TCP header. | | 1290 | * Get IP and TCP header. |
1277 | * Note: IP leaves IP header in first mbuf. | | 1291 | * Note: IP leaves IP header in first mbuf. |
1278 | */ | | 1292 | */ |
| | | 1293 | #ifdef INET6 |
| | | 1294 | ip6 = mtod(m, struct ip6_hdr *); |
| | | 1295 | #endif |
| | | 1296 | #ifdef INET |
1279 | ip = mtod(m, struct ip *); | | 1297 | ip = mtod(m, struct ip *); |
| | | 1298 | #endif |
1280 | switch (ip->ip_v) { | | 1299 | switch (ip->ip_v) { |
1281 | #ifdef INET | | 1300 | #ifdef INET |
1282 | case 4: | | 1301 | case 4: |
1283 | #ifdef INET6 | | | |
1284 | ip6 = NULL; | | | |
1285 | #endif | | | |
1286 | af = AF_INET; | | 1302 | af = AF_INET; |
1287 | iphlen = sizeof(struct ip); | | 1303 | iphlen = sizeof(struct ip); |
1288 | IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, | | 1304 | IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, |
1289 | sizeof(struct tcphdr)); | | 1305 | sizeof(struct tcphdr)); |
1290 | if (th == NULL) { | | 1306 | if (th == NULL) { |
1291 | TCP_STATINC(TCP_STAT_RCVSHORT); | | 1307 | TCP_STATINC(TCP_STAT_RCVSHORT); |
1292 | return; | | 1308 | return; |
1293 | } | | 1309 | } |
1294 | /* We do the checksum after PCB lookup... */ | | 1310 | /* We do the checksum after PCB lookup... */ |
1295 | len = ntohs(ip->ip_len); | | 1311 | len = ntohs(ip->ip_len); |
1296 | tlen = len - toff; | | 1312 | tlen = len - toff; |
1297 | iptos = ip->ip_tos; | | 1313 | iptos = ip->ip_tos; |
1298 | break; | | 1314 | break; |
1299 | #endif | | 1315 | #endif |
1300 | #ifdef INET6 | | 1316 | #ifdef INET6 |
1301 | case 6: | | 1317 | case 6: |
1302 | ip = NULL; | | | |
1303 | iphlen = sizeof(struct ip6_hdr); | | 1318 | iphlen = sizeof(struct ip6_hdr); |
1304 | af = AF_INET6; | | 1319 | af = AF_INET6; |
1305 | ip6 = mtod(m, struct ip6_hdr *); | | | |
1306 | IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, | | 1320 | IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, |
1307 | sizeof(struct tcphdr)); | | 1321 | sizeof(struct tcphdr)); |
1308 | if (th == NULL) { | | 1322 | if (th == NULL) { |
1309 | TCP_STATINC(TCP_STAT_RCVSHORT); | | 1323 | TCP_STATINC(TCP_STAT_RCVSHORT); |
1310 | return; | | 1324 | return; |
1311 | } | | 1325 | } |
1312 | | | 1326 | |
1313 | /* Be proactive about malicious use of IPv4 mapped address */ | | 1327 | /* Be proactive about malicious use of IPv4 mapped address */ |
1314 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | | 1328 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || |
1315 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | | 1329 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { |
1316 | /* XXX stat */ | | 1330 | /* XXX stat */ |
1317 | goto drop; | | 1331 | goto drop; |
1318 | } | | 1332 | } |
| @@ -1339,43 +1353,26 @@ tcp_input(struct mbuf *m, ...) | | | @@ -1339,43 +1353,26 @@ tcp_input(struct mbuf *m, ...) |
1339 | goto drop; | | 1353 | goto drop; |
1340 | } | | 1354 | } |
1341 | | | 1355 | |
1342 | /* We do the checksum after PCB lookup... */ | | 1356 | /* We do the checksum after PCB lookup... */ |
1343 | len = m->m_pkthdr.len; | | 1357 | len = m->m_pkthdr.len; |
1344 | tlen = len - toff; | | 1358 | tlen = len - toff; |
1345 | iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; | | 1359 | iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; |
1346 | break; | | 1360 | break; |
1347 | #endif | | 1361 | #endif |
1348 | default: | | 1362 | default: |
1349 | m_freem(m); | | 1363 | m_freem(m); |
1350 | return; | | 1364 | return; |
1351 | } | | 1365 | } |
1352 | /* | | | |
1353 | * Enforce alignment requirements that are violated in | | | |
1354 | * some cases, see kern/50766 for details. | | | |
1355 | */ | | | |
1356 | if (TCP_HDR_ALIGNED_P(th) == 0) { | | | |
1357 | m = m_copyup(m, toff + sizeof(struct tcphdr), 0); | | | |
1358 | if (m == NULL) { | | | |
1359 | TCP_STATINC(TCP_STAT_RCVSHORT); | | | |
1360 | return; | | | |
1361 | } | | | |
1362 | ip = mtod(m, struct ip *); | | | |
1363 | #ifdef INET6 | | | |
1364 | ip6 = mtod(m, struct ip6_hdr *); | | | |
1365 | #endif | | | |
1366 | th = (struct tcphdr *)(mtod(m, char *) + toff); | | | |
1367 | } | | | |
1368 | KASSERT(TCP_HDR_ALIGNED_P(th)); | | | |
1369 | | | 1366 | |
1370 | /* | | 1367 | /* |
1371 | * Check that TCP offset makes sense, | | 1368 | * Check that TCP offset makes sense, |
1372 | * pull out TCP options and adjust length. XXX | | 1369 | * pull out TCP options and adjust length. XXX |
1373 | */ | | 1370 | */ |
1374 | off = th->th_off << 2; | | 1371 | off = th->th_off << 2; |
1375 | if (off < sizeof (struct tcphdr) || off > tlen) { | | 1372 | if (off < sizeof (struct tcphdr) || off > tlen) { |
1376 | TCP_STATINC(TCP_STAT_RCVBADOFF); | | 1373 | TCP_STATINC(TCP_STAT_RCVBADOFF); |
1377 | goto drop; | | 1374 | goto drop; |
1378 | } | | 1375 | } |
1379 | tlen -= off; | | 1376 | tlen -= off; |
1380 | | | 1377 | |
1381 | /* | | 1378 | /* |
| @@ -1591,27 +1588,26 @@ findpcb: | | | @@ -1591,27 +1588,26 @@ findpcb: |
1591 | /* Unscale the window into a 32-bit value. */ | | 1588 | /* Unscale the window into a 32-bit value. */ |
1592 | if ((tiflags & TH_SYN) == 0) | | 1589 | if ((tiflags & TH_SYN) == 0) |
1593 | tiwin = th->th_win << tp->snd_scale; | | 1590 | tiwin = th->th_win << tp->snd_scale; |
1594 | else | | 1591 | else |
1595 | tiwin = th->th_win; | | 1592 | tiwin = th->th_win; |
1596 | | | 1593 | |
1597 | #ifdef INET6 | | 1594 | #ifdef INET6 |
1598 | /* save packet options if user wanted */ | | 1595 | /* save packet options if user wanted */ |
1599 | if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS)) { | | 1596 | if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS)) { |
1600 | if (in6p->in6p_options) { | | 1597 | if (in6p->in6p_options) { |
1601 | m_freem(in6p->in6p_options); | | 1598 | m_freem(in6p->in6p_options); |
1602 | in6p->in6p_options = 0; | | 1599 | in6p->in6p_options = 0; |
1603 | } | | 1600 | } |
1604 | KASSERT(ip6 != NULL); | | | |
1605 | ip6_savecontrol(in6p, &in6p->in6p_options, ip6, m); | | 1601 | ip6_savecontrol(in6p, &in6p->in6p_options, ip6, m); |
1606 | } | | 1602 | } |
1607 | #endif | | 1603 | #endif |
1608 | | | 1604 | |
1609 | if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { | | 1605 | if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { |
1610 | union syn_cache_sa src; | | 1606 | union syn_cache_sa src; |
1611 | union syn_cache_sa dst; | | 1607 | union syn_cache_sa dst; |
1612 | | | 1608 | |
1613 | memset(&src, 0, sizeof(src)); | | 1609 | memset(&src, 0, sizeof(src)); |
1614 | memset(&dst, 0, sizeof(dst)); | | 1610 | memset(&dst, 0, sizeof(dst)); |
1615 | switch (af) { | | 1611 | switch (af) { |
1616 | #ifdef INET | | 1612 | #ifdef INET |
1617 | case AF_INET: | | 1613 | case AF_INET: |