Deleted Added
full compact
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 ---