When a connection is being dropped due to a listen queue overflow,

delete the cloned route that is associated with the connection.
This does not exhaust the routing table memory when the system
is under a SYN flood attack. The route entry is not deleted if there
is any prior information cached in it.

Reviewed by: Peter Wemm,asmodai
This commit is contained in:
jayanth 2000-07-21 23:26:37 +00:00
parent 9ed7fa2a25
commit 8c2fae5374
7 changed files with 65 additions and 3 deletions

View File

@ -139,7 +139,7 @@ struct ortentry {
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
#define RTF_DONE 0x40 /* message confirmed */
/* 0x80 unused */
#define RTF_DELCLONE 0x80 /* delete cloned route */
#define RTF_CLONING 0x100 /* generate new routes on use */
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */

View File

@ -531,6 +531,7 @@ in_pcbdetach(inp)
{
struct socket *so = inp->inp_socket;
struct inpcbinfo *ipi = inp->inp_pcbinfo;
struct rtentry *rt = inp->inp_route.ro_rt;
#ifdef IPSEC
ipsec4_delete_pcbpolicy(inp);
@ -541,8 +542,28 @@ in_pcbdetach(inp)
sofree(so);
if (inp->inp_options)
(void)m_free(inp->inp_options);
if (inp->inp_route.ro_rt)
rtfree(inp->inp_route.ro_rt);
if (rt) {
/*
* route deletion requires reference count to be <= zero
*/
if ((rt->rt_flags & RTF_DELCLONE) &&
(rt->rt_flags & RTF_WASCLONED)) {
if (--rt->rt_refcnt <= 0) {
rt->rt_flags &= ~RTF_UP;
rtrequest(RTM_DELETE, rt_key(rt),
rt->rt_gateway, rt_mask(rt),
rt->rt_flags, (struct rtentry **)0);
}
else
/*
* more than one reference, bump it up
* again.
*/
rt->rt_refcnt++;
}
else
rtfree(rt);
}
ip_freemoptions(inp->inp_moptions);
inp->inp_vflag = 0;
zfreei(ipi->ipi_zone, inp);

View File

@ -121,6 +121,11 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, delayed_ack, CTLFLAG_RW,
&tcp_delack_enabled, 0,
"Delay ACK to try and piggyback it onto a data packet");
int tcp_lq_overflow = 1;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_lq_overflow, CTLFLAG_RW,
&tcp_lq_overflow, 0,
"Listen Queue Overflow");
#ifdef TCP_DROP_SYNFIN
static int drop_synfin = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_RW,
@ -710,6 +715,9 @@ tcp_input(m, off0, proto)
tcpstat.tcps_listendrop++;
so2 = sodropablereq(so);
if (so2) {
if (tcp_lq_overflow)
sototcpcb(so2)->t_flags |=
TF_LQ_OVERFLOW;
tcp_drop(sototcpcb(so2), ETIMEDOUT);
so2 = sonewconn(so, 0);
}

View File

@ -121,6 +121,11 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, delayed_ack, CTLFLAG_RW,
&tcp_delack_enabled, 0,
"Delay ACK to try and piggyback it onto a data packet");
int tcp_lq_overflow = 1;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_lq_overflow, CTLFLAG_RW,
&tcp_lq_overflow, 0,
"Listen Queue Overflow");
#ifdef TCP_DROP_SYNFIN
static int drop_synfin = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_RW,
@ -710,6 +715,9 @@ tcp_input(m, off0, proto)
tcpstat.tcps_listendrop++;
so2 = sodropablereq(so);
if (so2) {
if (tcp_lq_overflow)
sototcpcb(so2)->t_flags |=
TF_LQ_OVERFLOW;
tcp_drop(sototcpcb(so2), ETIMEDOUT);
so2 = sonewconn(so, 0);
}

View File

@ -680,6 +680,18 @@ tcp_close(tp)
tcpstat.tcps_cachedssthresh++;
}
}
rt = inp->inp_route.ro_rt;
if (rt) {
/*
* mark route for deletion if no information is
* cached.
*/
if ((tp->t_flags & TF_LQ_OVERFLOW) &&
((rt->rt_rmx.rmx_locks & RTV_RTT) == 0)){
if (rt->rt_rmx.rmx_rtt == 0)
rt->rt_flags |= RTF_DELCLONE;
}
}
no_valid_rt:
/* free the reassembly queue, if any */
while((q = LIST_FIRST(&tp->t_segq)) != NULL) {

View File

@ -680,6 +680,18 @@ tcp_close(tp)
tcpstat.tcps_cachedssthresh++;
}
}
rt = inp->inp_route.ro_rt;
if (rt) {
/*
* mark route for deletion if no information is
* cached.
*/
if ((tp->t_flags & TF_LQ_OVERFLOW) &&
((rt->rt_rmx.rmx_locks & RTV_RTT) == 0)){
if (rt->rt_rmx.rmx_rtt == 0)
rt->rt_flags |= RTF_DELCLONE;
}
}
no_valid_rt:
/* free the reassembly queue, if any */
while((q = LIST_FIRST(&tp->t_segq)) != NULL) {

View File

@ -94,6 +94,7 @@ struct tcpcb {
#define TF_RCVD_CC 0x04000 /* a CC was received in SYN */
#define TF_SENDCCNEW 0x08000 /* send CCnew instead of CC in SYN */
#define TF_MORETOCOME 0x10000 /* More data to be appended to sock */
#define TF_LQ_OVERFLOW 0x20000 /* listen queue overflow */
int t_force; /* 1 if forcing out a byte */
tcp_seq snd_una; /* send unacknowledged */