tcp_input.c (268190) | tcp_input.c (269699) |
---|---|
1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 2007-2008,2010 5 * Swinburne University of Technology, Melbourne, Australia. 6 * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org> 7 * Copyright (c) 2010 The FreeBSD Foundation 8 * Copyright (c) 2010-2011 Juniper Networks, Inc. --- 34 unchanged lines hidden (view full) --- 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 * 47 * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 48 */ 49 50#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 2007-2008,2010 5 * Swinburne University of Technology, Melbourne, Australia. 6 * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org> 7 * Copyright (c) 2010 The FreeBSD Foundation 8 * Copyright (c) 2010-2011 Juniper Networks, Inc. --- 34 unchanged lines hidden (view full) --- 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 * 47 * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 48 */ 49 50#include <sys/cdefs.h> |
51__FBSDID("$FreeBSD: head/sys/netinet/tcp_input.c 268183 2014-07-02 22:04:14Z hiren $"); | 51__FBSDID("$FreeBSD: head/sys/netinet/tcp_input.c 269699 2014-08-08 01:57:15Z kevlo $"); |
52 53#include "opt_ipfw.h" /* for ipfw_fwd */ 54#include "opt_inet.h" 55#include "opt_inet6.h" 56#include "opt_ipsec.h" 57#include "opt_tcpdebug.h" 58 59#include <sys/param.h> --- 457 unchanged lines hidden (view full) --- 517 ia6 = ip6_getdstifaddr(m); 518 if (ia6 && (ia6->ia6_flags & IN6_IFF_ANYCAST)) { 519 struct ip6_hdr *ip6; 520 521 ifa_free(&ia6->ia_ifa); 522 ip6 = mtod(m, struct ip6_hdr *); 523 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 524 (caddr_t)&ip6->ip6_dst - (caddr_t)ip6); | 52 53#include "opt_ipfw.h" /* for ipfw_fwd */ 54#include "opt_inet.h" 55#include "opt_inet6.h" 56#include "opt_ipsec.h" 57#include "opt_tcpdebug.h" 58 59#include <sys/param.h> --- 457 unchanged lines hidden (view full) --- 517 ia6 = ip6_getdstifaddr(m); 518 if (ia6 && (ia6->ia6_flags & IN6_IFF_ANYCAST)) { 519 struct ip6_hdr *ip6; 520 521 ifa_free(&ia6->ia_ifa); 522 ip6 = mtod(m, struct ip6_hdr *); 523 icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 524 (caddr_t)&ip6->ip6_dst - (caddr_t)ip6); |
525 return IPPROTO_DONE; | 525 return (IPPROTO_DONE); |
526 } 527 if (ia6) 528 ifa_free(&ia6->ia_ifa); 529 | 526 } 527 if (ia6) 528 ifa_free(&ia6->ia_ifa); 529 |
530 tcp_input(m, *offp); 531 return IPPROTO_DONE; | 530 return (tcp_input(mp, offp, proto)); |
532} 533#endif /* INET6 */ 534 | 531} 532#endif /* INET6 */ 533 |
535void 536tcp_input(struct mbuf *m, int off0) | 534int 535tcp_input(struct mbuf **mp, int *offp, int proto) |
537{ | 536{ |
537 struct mbuf *m = *mp; |
|
538 struct tcphdr *th = NULL; 539 struct ip *ip = NULL; 540 struct inpcb *inp = NULL; 541 struct tcpcb *tp = NULL; 542 struct socket *so = NULL; 543 u_char *optp = NULL; | 538 struct tcphdr *th = NULL; 539 struct ip *ip = NULL; 540 struct inpcb *inp = NULL; 541 struct tcpcb *tp = NULL; 542 struct socket *so = NULL; 543 u_char *optp = NULL; |
544 int off0; |
|
544 int optlen = 0; 545#ifdef INET 546 int len; 547#endif 548 int tlen = 0, off; 549 int drop_hdrlen; 550 int thflags; 551 int rstreason = 0; /* For badport_bandlim accounting purposes */ --- 23 unchanged lines hidden (view full) --- 575 struct tcphdr tcp_savetcp; 576 short ostate = 0; 577#endif 578 579#ifdef INET6 580 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; 581#endif 582 | 545 int optlen = 0; 546#ifdef INET 547 int len; 548#endif 549 int tlen = 0, off; 550 int drop_hdrlen; 551 int thflags; 552 int rstreason = 0; /* For badport_bandlim accounting purposes */ --- 23 unchanged lines hidden (view full) --- 576 struct tcphdr tcp_savetcp; 577 short ostate = 0; 578#endif 579 580#ifdef INET6 581 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; 582#endif 583 |
584 off0 = *offp; 585 m = *mp; 586 *mp = NULL; |
|
583 to.to_flags = 0; 584 TCPSTAT_INC(tcps_rcvtotal); 585 586#ifdef INET6 587 if (isipv6) { 588 /* IP6_EXTHDR_CHECK() is already done at tcp6_input(). */ 589 590 if (m->m_len < (sizeof(*ip6) + sizeof(*th))) { 591 m = m_pullup(m, sizeof(*ip6) + sizeof(*th)); 592 if (m == NULL) { 593 TCPSTAT_INC(tcps_rcvshort); | 587 to.to_flags = 0; 588 TCPSTAT_INC(tcps_rcvtotal); 589 590#ifdef INET6 591 if (isipv6) { 592 /* IP6_EXTHDR_CHECK() is already done at tcp6_input(). */ 593 594 if (m->m_len < (sizeof(*ip6) + sizeof(*th))) { 595 m = m_pullup(m, sizeof(*ip6) + sizeof(*th)); 596 if (m == NULL) { 597 TCPSTAT_INC(tcps_rcvshort); |
594 return; | 598 return (IPPROTO_DONE); |
595 } 596 } 597 598 ip6 = mtod(m, struct ip6_hdr *); 599 th = (struct tcphdr *)((caddr_t)ip6 + off0); 600 tlen = sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0; 601 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) { 602 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) --- 35 unchanged lines hidden (view full) --- 638 if (off0 > sizeof (struct ip)) { 639 ip_stripoptions(m); 640 off0 = sizeof(struct ip); 641 } 642 if (m->m_len < sizeof (struct tcpiphdr)) { 643 if ((m = m_pullup(m, sizeof (struct tcpiphdr))) 644 == NULL) { 645 TCPSTAT_INC(tcps_rcvshort); | 599 } 600 } 601 602 ip6 = mtod(m, struct ip6_hdr *); 603 th = (struct tcphdr *)((caddr_t)ip6 + off0); 604 tlen = sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0; 605 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) { 606 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) --- 35 unchanged lines hidden (view full) --- 642 if (off0 > sizeof (struct ip)) { 643 ip_stripoptions(m); 644 off0 = sizeof(struct ip); 645 } 646 if (m->m_len < sizeof (struct tcpiphdr)) { 647 if ((m = m_pullup(m, sizeof (struct tcpiphdr))) 648 == NULL) { 649 TCPSTAT_INC(tcps_rcvshort); |
646 return; | 650 return (IPPROTO_DONE); |
647 } 648 } 649 ip = mtod(m, struct ip *); 650 th = (struct tcphdr *)((caddr_t)ip + off0); 651 tlen = ntohs(ip->ip_len) - off0; 652 653 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 654 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) --- 46 unchanged lines hidden (view full) --- 701 if (off < sizeof (struct tcphdr) || off > tlen) { 702 TCPSTAT_INC(tcps_rcvbadoff); 703 goto drop; 704 } 705 tlen -= off; /* tlen is used instead of ti->ti_len */ 706 if (off > sizeof (struct tcphdr)) { 707#ifdef INET6 708 if (isipv6) { | 651 } 652 } 653 ip = mtod(m, struct ip *); 654 th = (struct tcphdr *)((caddr_t)ip + off0); 655 tlen = ntohs(ip->ip_len) - off0; 656 657 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 658 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) --- 46 unchanged lines hidden (view full) --- 705 if (off < sizeof (struct tcphdr) || off > tlen) { 706 TCPSTAT_INC(tcps_rcvbadoff); 707 goto drop; 708 } 709 tlen -= off; /* tlen is used instead of ti->ti_len */ 710 if (off > sizeof (struct tcphdr)) { 711#ifdef INET6 712 if (isipv6) { |
709 IP6_EXTHDR_CHECK(m, off0, off, ); | 713 IP6_EXTHDR_CHECK(m, off0, off, IPPROTO_DONE); |
710 ip6 = mtod(m, struct ip6_hdr *); 711 th = (struct tcphdr *)((caddr_t)ip6 + off0); 712 } 713#endif 714#if defined(INET) && defined(INET6) 715 else 716#endif 717#ifdef INET 718 { 719 if (m->m_len < sizeof(struct ip) + off) { 720 if ((m = m_pullup(m, sizeof (struct ip) + off)) 721 == NULL) { 722 TCPSTAT_INC(tcps_rcvshort); | 714 ip6 = mtod(m, struct ip6_hdr *); 715 th = (struct tcphdr *)((caddr_t)ip6 + off0); 716 } 717#endif 718#if defined(INET) && defined(INET6) 719 else 720#endif 721#ifdef INET 722 { 723 if (m->m_len < sizeof(struct ip) + off) { 724 if ((m = m_pullup(m, sizeof (struct ip) + off)) 725 == NULL) { 726 TCPSTAT_INC(tcps_rcvshort); |
723 return; | 727 return (IPPROTO_DONE); |
724 } 725 ip = mtod(m, struct ip *); 726 th = (struct tcphdr *)((caddr_t)ip + off0); 727 } 728 } 729#endif 730 optlen = off - sizeof (struct tcphdr); 731 optp = (u_char *)(th + 1); --- 212 unchanged lines hidden (view full) --- 944 if (thflags & TH_SYN) 945 tcp_dooptions(&to, optp, optlen, TO_SYN); 946 /* 947 * NB: tcp_twcheck unlocks the INP and frees the mbuf. 948 */ 949 if (tcp_twcheck(inp, &to, th, m, tlen)) 950 goto findpcb; 951 INP_INFO_WUNLOCK(&V_tcbinfo); | 728 } 729 ip = mtod(m, struct ip *); 730 th = (struct tcphdr *)((caddr_t)ip + off0); 731 } 732 } 733#endif 734 optlen = off - sizeof (struct tcphdr); 735 optp = (u_char *)(th + 1); --- 212 unchanged lines hidden (view full) --- 948 if (thflags & TH_SYN) 949 tcp_dooptions(&to, optp, optlen, TO_SYN); 950 /* 951 * NB: tcp_twcheck unlocks the INP and frees the mbuf. 952 */ 953 if (tcp_twcheck(inp, &to, th, m, tlen)) 954 goto findpcb; 955 INP_INFO_WUNLOCK(&V_tcbinfo); |
952 return; | 956 return (IPPROTO_DONE); |
953 } 954 /* 955 * The TCPCB may no longer exist if the connection is winding 956 * down or it is in the CLOSED state. Either way we drop the 957 * segment and send an appropriate response. 958 */ 959 tp = intotcpcb(inp); 960 if (tp == NULL || tp->t_state == TCPS_CLOSED) { --- 172 unchanged lines hidden (view full) --- 1133 /* 1134 * Process the segment and the data it 1135 * contains. tcp_do_segment() consumes 1136 * the mbuf chain and unlocks the inpcb. 1137 */ 1138 tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, 1139 iptos, ti_locked); 1140 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | 957 } 958 /* 959 * The TCPCB may no longer exist if the connection is winding 960 * down or it is in the CLOSED state. Either way we drop the 961 * segment and send an appropriate response. 962 */ 963 tp = intotcpcb(inp); 964 if (tp == NULL || tp->t_state == TCPS_CLOSED) { --- 172 unchanged lines hidden (view full) --- 1137 /* 1138 * Process the segment and the data it 1139 * contains. tcp_do_segment() consumes 1140 * the mbuf chain and unlocks the inpcb. 1141 */ 1142 tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, 1143 iptos, ti_locked); 1144 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); |
1141 return; | 1145 return (IPPROTO_DONE); |
1142 } 1143 /* 1144 * Segment flag validation for new connection attempts: 1145 * 1146 * Our (SYN|ACK) response was rejected. 1147 * Check with syncache and remove entry to prevent 1148 * retransmits. 1149 * --- 183 unchanged lines hidden (view full) --- 1333#endif 1334 tcp_dooptions(&to, optp, optlen, TO_SYN); 1335 syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL); 1336 /* 1337 * Entry added to syncache and mbuf consumed. 1338 * Everything already unlocked by syncache_add(). 1339 */ 1340 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | 1146 } 1147 /* 1148 * Segment flag validation for new connection attempts: 1149 * 1150 * Our (SYN|ACK) response was rejected. 1151 * Check with syncache and remove entry to prevent 1152 * retransmits. 1153 * --- 183 unchanged lines hidden (view full) --- 1337#endif 1338 tcp_dooptions(&to, optp, optlen, TO_SYN); 1339 syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL); 1340 /* 1341 * Entry added to syncache and mbuf consumed. 1342 * Everything already unlocked by syncache_add(). 1343 */ 1344 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); |
1341 return; | 1345 return (IPPROTO_DONE); |
1342 } else if (tp->t_state == TCPS_LISTEN) { 1343 /* 1344 * When a listen socket is torn down the SO_ACCEPTCONN 1345 * flag is removed first while connections are drained 1346 * from the accept queue in a unlock/lock cycle of the 1347 * ACCEPT_LOCK, opening a race condition allowing a SYN 1348 * attempt go through unhandled. 1349 */ --- 23 unchanged lines hidden (view full) --- 1373 1374 /* 1375 * Segment belongs to a connection in SYN_SENT, ESTABLISHED or later 1376 * state. tcp_do_segment() always consumes the mbuf chain, unlocks 1377 * the inpcb, and unlocks pcbinfo. 1378 */ 1379 tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked); 1380 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); | 1346 } else if (tp->t_state == TCPS_LISTEN) { 1347 /* 1348 * When a listen socket is torn down the SO_ACCEPTCONN 1349 * flag is removed first while connections are drained 1350 * from the accept queue in a unlock/lock cycle of the 1351 * ACCEPT_LOCK, opening a race condition allowing a SYN 1352 * attempt go through unhandled. 1353 */ --- 23 unchanged lines hidden (view full) --- 1377 1378 /* 1379 * Segment belongs to a connection in SYN_SENT, ESTABLISHED or later 1380 * state. tcp_do_segment() always consumes the mbuf chain, unlocks 1381 * the inpcb, and unlocks pcbinfo. 1382 */ 1383 tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked); 1384 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); |
1381 return; | 1385 return (IPPROTO_DONE); |
1382 1383dropwithreset: 1384 TCP_PROBE5(receive, NULL, tp, mtod(m, const char *), tp, th); 1385 1386 if (ti_locked == TI_WLOCKED) { 1387 INP_INFO_WUNLOCK(&V_tcbinfo); 1388 ti_locked = TI_UNLOCKED; 1389 } --- 33 unchanged lines hidden (view full) --- 1423 INP_WUNLOCK(inp); 1424 1425drop: 1426 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); 1427 if (s != NULL) 1428 free(s, M_TCPLOG); 1429 if (m != NULL) 1430 m_freem(m); | 1386 1387dropwithreset: 1388 TCP_PROBE5(receive, NULL, tp, mtod(m, const char *), tp, th); 1389 1390 if (ti_locked == TI_WLOCKED) { 1391 INP_INFO_WUNLOCK(&V_tcbinfo); 1392 ti_locked = TI_UNLOCKED; 1393 } --- 33 unchanged lines hidden (view full) --- 1427 INP_WUNLOCK(inp); 1428 1429drop: 1430 INP_INFO_UNLOCK_ASSERT(&V_tcbinfo); 1431 if (s != NULL) 1432 free(s, M_TCPLOG); 1433 if (m != NULL) 1434 m_freem(m); |
1435 return (IPPROTO_DONE); |
|
1431} 1432 1433static void 1434tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, 1435 struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos, 1436 int ti_locked) 1437{ 1438 int thflags, acked, ourfinisacked, needoutput = 0; --- 2255 unchanged lines hidden --- | 1436} 1437 1438static void 1439tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, 1440 struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos, 1441 int ti_locked) 1442{ 1443 int thflags, acked, ourfinisacked, needoutput = 0; --- 2255 unchanged lines hidden --- |