Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet When listening socket goes away, remove assockat...



details:   https://anonhg.NetBSD.org/src/rev/2bfa7bfdd98f
branches:  trunk
changeset: 475783:2bfa7bfdd98f
user:      itojun <itojun%NetBSD.org@localhost>
date:      Wed Aug 25 15:23:12 1999 +0000

description:
When listening socket goes away, remove assockated syn cache entires.
Stale syn cache entries are useless because none of them will be used
if there is no listening socket, as tcp_input looks up listening socket by
in_pcblookup*() before looking into syn cache.

This fixes race condition due to dangling socket pointer from syn cache
entries to listening socket (this was introduced when ipsec is merged in).

This should preserve currently implemented behavior (but not 4.4BSD
behavior prior to syn cache).

Tested in KAME repository before commit, but we'd better run some
regression tests.

diffstat:

 sys/netinet/tcp_input.c |  62 ++++++++++++++++++++++++++++++++++++++++++++----
 sys/netinet/tcp_subr.c  |   4 ++-
 sys/netinet/tcp_var.h   |  12 +++++++--
 3 files changed, 68 insertions(+), 10 deletions(-)

diffs (184 lines):

diff -r 1aabb1ccc231 -r 2bfa7bfdd98f sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c   Wed Aug 25 14:42:35 1999 +0000
+++ b/sys/netinet/tcp_input.c   Wed Aug 25 15:23:12 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_input.c,v 1.92 1999/08/23 14:14:30 christos Exp $  */
+/*     $NetBSD: tcp_input.c,v 1.93 1999/08/25 15:23:12 itojun Exp $    */
 
 /*
 %%% portions-copyright-nrl-95
@@ -2377,6 +2377,8 @@
 #define        SYN_CACHE_RM(sc)                                                \
 do {                                                                   \
        LIST_REMOVE((sc), sc_bucketq);                                  \
+       (sc)->sc_tp = NULL;                                             \
+       LIST_REMOVE((sc), sc_tpq);                                      \
        tcp_syn_cache[(sc)->sc_bucketidx].sch_length--;                 \
        TAILQ_REMOVE(&tcp_syn_cache_timeq[(sc)->sc_rxtshift], (sc), sc_timeq); \
        syn_cache_count--;                                              \
@@ -2427,8 +2429,9 @@
 }
 
 void
-syn_cache_insert(sc)
+syn_cache_insert(sc, tp)
        struct syn_cache *sc;
+       struct tcpcb *tp;
 {
        struct syn_cache_head *scp;
        struct syn_cache *sc2;
@@ -2519,6 +2522,9 @@
        SYN_CACHE_TIMER_ARM(sc);
        TAILQ_INSERT_TAIL(&tcp_syn_cache_timeq[sc->sc_rxtshift], sc, sc_timeq);
 
+       /* Link it from tcpcb entry */
+       LIST_INSERT_HEAD(&tp->t_sc, sc, sc_tpq);
+
        /* Put it into the bucket. */
        LIST_INSERT_HEAD(&scp->sch_bucket, sc, sc_bucketq);
        scp->sch_length++;
@@ -2592,6 +2598,36 @@
 }
 
 /*
+ * Remove syn cache created by the specified tcb entry,
+ * because this does not make sense to keep them
+ * (if there's no tcb entry, syn cache entry will never be used)
+ */
+void
+syn_cache_cleanup(tp)
+       struct tcpcb *tp;
+{
+       struct syn_cache *sc, *nsc;
+       int s;
+
+       s = splsoftnet();
+
+       for (sc = LIST_FIRST(&tp->t_sc); sc != NULL; sc = nsc) {
+               nsc = LIST_NEXT(sc, sc_tpq);
+
+#ifdef DIAGNOSTIC
+               if (sc->sc_tp != tp)
+                       panic("invalid sc_tp in syn_cache_cleanup");
+#endif
+               SYN_CACHE_RM(sc);
+               SYN_CACHE_PUT(sc);
+       }
+       /* just for safety */
+       LIST_INIT(&tp->t_sc);
+
+       splx(s);
+}
+
+/*
  * Find an entry in the syn cache.
  */
 struct syn_cache *
@@ -3166,9 +3202,9 @@
                sc->sc_requested_s_scale = 15;
                sc->sc_request_r_scale = 15;
        }
-       sc->sc_so = so;
+       sc->sc_tp = tp;
        if (syn_cache_respond(sc, m) == 0) {
-               syn_cache_insert(sc);
+               syn_cache_insert(sc, tp);
                tcpstat.tcps_sndacks++;
                tcpstat.tcps_sndtotal++;
        } else {
@@ -3234,8 +3270,22 @@
        m->m_data += max_linkhdr;
        m->m_len = m->m_pkthdr.len = tlen;
 #ifdef IPSEC
-       /* use IPsec policy on listening socket, on SYN ACK */
-       m->m_pkthdr.rcvif = (struct ifnet *)sc->sc_so;
+       if (sc->sc_tp) {
+               struct tcpcb *tp;
+               struct socket *so;
+
+               tp = sc->sc_tp;
+               if (tp->t_inpcb)
+                       so = tp->t_inpcb->inp_socket;
+#ifdef INET6
+               else if (tp->t_in6pcb)
+                       so = tp->t_in6pcb->in6p_socket;
+#endif
+               else
+                       so = NULL;
+               /* use IPsec policy on listening socket, on SYN ACK */
+               m->m_pkthdr.rcvif = (struct ifnet *)so;
+       }
 #else
        m->m_pkthdr.rcvif = NULL;
 #endif
diff -r 1aabb1ccc231 -r 2bfa7bfdd98f sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c    Wed Aug 25 14:42:35 1999 +0000
+++ b/sys/netinet/tcp_subr.c    Wed Aug 25 15:23:12 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_subr.c,v 1.77 1999/08/25 12:38:14 itojun Exp $     */
+/*     $NetBSD: tcp_subr.c,v 1.78 1999/08/25 15:23:13 itojun Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -703,6 +703,7 @@
        tp->t_peermss = tcp_mssdflt;
        tp->t_ourmss = tcp_mssdflt;
        tp->t_segsz = tcp_mssdflt;
+       LIST_INIT(&tp->t_sc);
 
        tp->t_flags = 0;
        if (tcp_do_rfc1323 && tcp_do_win_scale)
@@ -895,6 +896,7 @@
        TCP_REASS_UNLOCK(tp);
 
        TCP_CLEAR_DELACK(tp);
+       syn_cache_cleanup(tp);
 
        if (tp->t_template) {
                m_free(tp->t_template);
diff -r 1aabb1ccc231 -r 2bfa7bfdd98f sys/netinet/tcp_var.h
--- a/sys/netinet/tcp_var.h     Wed Aug 25 14:42:35 1999 +0000
+++ b/sys/netinet/tcp_var.h     Wed Aug 25 15:23:12 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_var.h,v 1.66 1999/08/12 16:04:52 itojun Exp $      */
+/*     $NetBSD: tcp_var.h,v 1.67 1999/08/25 15:23:13 itojun Exp $      */
 
 /*
 %%% portions-copyright-nrl-98
@@ -224,6 +224,9 @@
 
 /* SACK stuff */
        struct ipqehead timeq;          /* time sequenced queue (for SACK) */
+
+/* pointer for syn cache entries*/
+       LIST_HEAD(, syn_cache) t_sc;    /* list of entries by this tcb */
 };
 
 #ifdef _KERNEL
@@ -367,7 +370,9 @@
        u_int16_t sc_ourmaxseg;
        u_int8_t sc_request_r_scale     : 4,
                 sc_requested_s_scale   : 4;
-       struct socket *sc_so;                   /* listening socket */
+
+       struct tcpcb *sc_tp;                    /* tcb for listening socket */
+       LIST_ENTRY(syn_cache) sc_tpq;           /* list of entries by same tp */
 };
 
 struct syn_cache_head {
@@ -683,13 +688,14 @@
                struct tcphdr *, unsigned int, unsigned int,
                struct socket *so, struct mbuf *));
 void    syn_cache_init __P((void));
-void    syn_cache_insert __P((struct syn_cache *));
+void    syn_cache_insert __P((struct syn_cache *, struct tcpcb *));
 struct syn_cache *syn_cache_lookup __P((struct sockaddr *, struct sockaddr *,
                struct syn_cache_head **));
 void    syn_cache_reset __P((struct sockaddr *, struct sockaddr *,
                struct tcphdr *));
 int     syn_cache_respond __P((struct syn_cache *, struct mbuf *));
 void    syn_cache_timer __P((void));
+void    syn_cache_cleanup __P((struct tcpcb *));
 
 int    tcp_newreno __P((struct tcpcb *, struct tcphdr *));
 #endif



Home | Main Index | Thread Index | Old Index