In the tcp_input() path:
- Filter out multicast destinations explicitly for every incoming packet, not just SYNs. Previously, non-SYN multicast destination would be filtered out as a side effect of PCB lookup. Remove now redundant similar checks in the dropwithreset case and in syn_cache_add(). - Defer the TCP checksum until we know that we want to process the packet (i.e. have a non-CLOSED connection or a listen socket).
This commit is contained in:
parent
b939c73fb4
commit
312cb38ccb
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: tcp_input.c,v 1.102 2000/01/31 14:18:56 itojun Exp $ */
|
/* $NetBSD: tcp_input.c,v 1.103 2000/02/12 17:19:34 thorpej Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
%%% portions-copyright-nrl-95
|
%%% portions-copyright-nrl-95
|
||||||
|
@ -226,6 +226,17 @@ do { \
|
||||||
TCP_SET_DELACK(tp); \
|
TCP_SET_DELACK(tp); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert TCP protocol fields to host order for easier processing.
|
||||||
|
*/
|
||||||
|
#define TCP_FIELDS_TO_HOST(th) \
|
||||||
|
do { \
|
||||||
|
NTOHL((th)->th_seq); \
|
||||||
|
NTOHL((th)->th_ack); \
|
||||||
|
NTOHS((th)->th_win); \
|
||||||
|
NTOHS((th)->th_urp); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
int
|
int
|
||||||
tcp_reass(tp, th, m, tlen)
|
tcp_reass(tp, th, m, tlen)
|
||||||
register struct tcpcb *tp;
|
register struct tcpcb *tp;
|
||||||
|
@ -584,6 +595,26 @@ tcp_input(m, va_alist)
|
||||||
opti.ts_present = 0;
|
opti.ts_present = 0;
|
||||||
opti.maxseg = 0;
|
opti.maxseg = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN.
|
||||||
|
*
|
||||||
|
* TCP is, by definition, unicast, so we reject all
|
||||||
|
* multicast outright.
|
||||||
|
*
|
||||||
|
* Note, there are additional src/dst address checks in
|
||||||
|
* the AF-specific code below.
|
||||||
|
*/
|
||||||
|
if (m->m_flags & (M_BCAST|M_MCAST)) {
|
||||||
|
/* XXX stat */
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
#ifdef INET6
|
||||||
|
if (m->m_flags & M_ANYCAST6) {
|
||||||
|
/* XXX stat */
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get IP and TCP header together in first mbuf.
|
* Get IP and TCP header together in first mbuf.
|
||||||
* Note: IP leaves IP header in first mbuf.
|
* Note: IP leaves IP header in first mbuf.
|
||||||
|
@ -621,27 +652,17 @@ tcp_input(m, va_alist)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checksum extended TCP header and data.
|
* Make sure destination address is not multicast.
|
||||||
|
* Source address checked in ip_input().
|
||||||
*/
|
*/
|
||||||
|
if (IN_MULTICAST(ip->ip_dst.s_addr)) {
|
||||||
|
/* XXX stat */
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We do the checksum after PCB lookup... */
|
||||||
len = ip->ip_len;
|
len = ip->ip_len;
|
||||||
tlen = len - toff;
|
tlen = len - toff;
|
||||||
#ifndef PULLDOWN_TEST
|
|
||||||
{
|
|
||||||
struct ipovly *ipov;
|
|
||||||
ipov = (struct ipovly *)ip;
|
|
||||||
bzero(ipov->ih_x1, sizeof ipov->ih_x1);
|
|
||||||
ipov->ih_len = htons(tlen);
|
|
||||||
}
|
|
||||||
if (in_cksum(m, len) != 0) {
|
|
||||||
tcpstat.tcps_rcvbadsum++;
|
|
||||||
goto drop;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (in4_cksum(m, IPPROTO_TCP, toff, tlen) != 0) {
|
|
||||||
tcpstat.tcps_rcvbadsum++;
|
|
||||||
goto drop;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
case 6:
|
case 6:
|
||||||
|
@ -676,14 +697,17 @@ tcp_input(m, va_alist)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checksum extended TCP header and data.
|
* Make sure destination address is not multicast.
|
||||||
|
* Source address checked in ip6_input().
|
||||||
*/
|
*/
|
||||||
len = m->m_pkthdr.len;
|
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||||
tlen = len - toff;
|
/* XXX stat */
|
||||||
if (in6_cksum(m, IPPROTO_TCP, toff, tlen)) {
|
|
||||||
tcpstat.tcps_rcvbadsum++;
|
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We do the checksum after PCB lookup... */
|
||||||
|
len = m->m_pkthdr.len;
|
||||||
|
tlen = len - toff;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -761,14 +785,6 @@ tcp_input(m, va_alist)
|
||||||
}
|
}
|
||||||
tiflags = th->th_flags;
|
tiflags = th->th_flags;
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert TCP protocol specific fields to host format.
|
|
||||||
*/
|
|
||||||
NTOHL(th->th_seq);
|
|
||||||
NTOHL(th->th_ack);
|
|
||||||
NTOHS(th->th_win);
|
|
||||||
NTOHS(th->th_urp);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate pcb for segment.
|
* Locate pcb for segment.
|
||||||
*/
|
*/
|
||||||
|
@ -839,6 +855,7 @@ findpcb:
|
||||||
dst, ntohs(th->th_dport),
|
dst, ntohs(th->th_dport),
|
||||||
src, ntohs(th->th_sport));
|
src, ntohs(th->th_sport));
|
||||||
}
|
}
|
||||||
|
TCP_FIELDS_TO_HOST(th);
|
||||||
goto dropwithreset;
|
goto dropwithreset;
|
||||||
}
|
}
|
||||||
#ifdef IPSEC
|
#ifdef IPSEC
|
||||||
|
@ -877,6 +894,7 @@ findpcb:
|
||||||
}
|
}
|
||||||
if (in6p == NULL) {
|
if (in6p == NULL) {
|
||||||
++tcpstat.tcps_noport;
|
++tcpstat.tcps_noport;
|
||||||
|
TCP_FIELDS_TO_HOST(th);
|
||||||
goto dropwithreset;
|
goto dropwithreset;
|
||||||
}
|
}
|
||||||
#ifdef IPSEC
|
#ifdef IPSEC
|
||||||
|
@ -909,11 +927,49 @@ findpcb:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (tp == 0) {
|
if (tp == 0) {
|
||||||
|
TCP_FIELDS_TO_HOST(th);
|
||||||
goto dropwithreset;
|
goto dropwithreset;
|
||||||
}
|
}
|
||||||
if (tp->t_state == TCPS_CLOSED)
|
if (tp->t_state == TCPS_CLOSED)
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checksum extended TCP header and data.
|
||||||
|
*/
|
||||||
|
switch (af) {
|
||||||
|
case AF_INET:
|
||||||
|
#ifndef PULLDOWN_TEST
|
||||||
|
{
|
||||||
|
struct ipovly *ipov;
|
||||||
|
ipov = (struct ipovly *)ip;
|
||||||
|
bzero(ipov->ih_x1, sizeof ipov->ih_x1);
|
||||||
|
ipov->ih_len = htons(tlen + off);
|
||||||
|
|
||||||
|
if (in_cksum(m, len) != 0) {
|
||||||
|
tcpstat.tcps_rcvbadsum++;
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (in4_cksum(m, IPPROTO_TCP, toff, tlen + off) != 0) {
|
||||||
|
tcpstat.tcps_rcvbadsum++;
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef INET6
|
||||||
|
case AF_INET6:
|
||||||
|
if (in6_cksum(m, IPPROTO_TCP, toff, tlen + off) != 0) {
|
||||||
|
tcpstat.tcps_rcvbadsum++;
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TCP_FIELDS_TO_HOST(th);
|
||||||
|
|
||||||
/* Unscale the window into a 32-bit value. */
|
/* Unscale the window into a 32-bit value. */
|
||||||
if ((tiflags & TH_SYN) == 0)
|
if ((tiflags & TH_SYN) == 0)
|
||||||
tiwin = th->th_win << tp->snd_scale;
|
tiwin = th->th_win << tp->snd_scale;
|
||||||
|
@ -2063,16 +2119,8 @@ dropwithreset:
|
||||||
* Make ACK acceptable to originator of segment.
|
* Make ACK acceptable to originator of segment.
|
||||||
* Don't bother to respond if destination was broadcast/multicast.
|
* Don't bother to respond if destination was broadcast/multicast.
|
||||||
*/
|
*/
|
||||||
if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST))
|
if (tiflags & TH_RST)
|
||||||
goto drop;
|
goto drop;
|
||||||
if (ip && IN_MULTICAST(ip->ip_dst.s_addr))
|
|
||||||
goto drop;
|
|
||||||
#ifdef INET6
|
|
||||||
if (m->m_flags & M_ANYCAST6)
|
|
||||||
goto drop;
|
|
||||||
else if (ip6 && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
|
|
||||||
goto drop;
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* need to recover version # field, which was overwritten on
|
* need to recover version # field, which was overwritten on
|
||||||
|
@ -3144,32 +3192,9 @@ syn_cache_add(src, dst, th, hlen, so, m, optp, optlen, oi)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
|
* RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
|
||||||
* in_broadcast() should never return true on a received
|
*
|
||||||
* packet with M_BCAST not set.
|
* Note this check is performed in tcp_input() very early on.
|
||||||
*/
|
*/
|
||||||
if (m->m_flags & (M_BCAST|M_MCAST))
|
|
||||||
return 0;
|
|
||||||
#ifdef INET6
|
|
||||||
if (m->m_flags & M_ANYCAST6)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (src->sa_family) {
|
|
||||||
case AF_INET:
|
|
||||||
if (IN_MULTICAST(((struct sockaddr_in *)src)->sin_addr.s_addr)
|
|
||||||
|| IN_MULTICAST(((struct sockaddr_in *)dst)->sin_addr.s_addr))
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
#ifdef INET6
|
|
||||||
case AF_INET6:
|
|
||||||
if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)src)->sin6_addr)
|
|
||||||
|| IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)dst)->sin6_addr))
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize some local state.
|
* Initialize some local state.
|
||||||
|
|
Loading…
Reference in New Issue