Hi,

I'm not sure when it is broken, in old versions, it was assumed the
pipex queues are empty when pipex_iface_stop() is called.  The problem
mvs@ found is the assumption is not true any more.

pipex has a mechanism that delete a session when the queues are empty.

    819 Static void
    820 pipex_timer(void *ignored_arg)
    821 {
    (snip)
    854                 case PIPEX_STATE_CLOSED:
    855                         /*
    856                          * mbuf queued in pipexinq or pipexoutq may 
have a
    857                          * refererce to this session.
    858                          */
    859                         if (!mq_empty(&pipexinq) || 
!mq_empty(&pipexoutq))
    860                                 continue;
    861 
    862                         pipex_destroy_session(session);
    863                         break;

I think using this is better.

How about this?

diff --git a/sys/net/pipex.c b/sys/net/pipex.c
index 2ad7757fee9..6fe14c400bf 100644
--- a/sys/net/pipex.c
+++ b/sys/net/pipex.c
@@ -190,7 +190,7 @@ pipex_iface_stop(struct pipex_iface_context *pipex_iface)
        LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
            session_tmp) {
                if (session->pipex_iface == pipex_iface)
-                       pipex_destroy_session(session);
+                       pipex_unlink_session(session);
        }
 }
 
@@ -470,9 +470,16 @@ pipex_link_session(struct pipex_session *session,
 void
 pipex_unlink_session(struct pipex_session *session)
 {
+       struct radix_node *rn;
+
        session->ifindex = 0;
 
        NET_ASSERT_LOCKED();
+       if (!in_nullhost(session->ip_address.sin_addr)) {
+               rn = rn_delete(&session->ip_address, &session->ip_netmask,
+                   pipex_rd_head4, (struct radix_node *)session);
+               KASSERT(rn != NULL);
+       }
        LIST_REMOVE(session, id_chain);
 #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
        switch (session->protocol) {
@@ -486,10 +493,6 @@ pipex_unlink_session(struct pipex_session *session)
                LIST_REMOVE(session, state_list);
        LIST_REMOVE(session, session_list);
        session->state = PIPEX_STATE_CLOSED;
-
-       /* if final session is destroyed, stop timer */
-       if (LIST_EMPTY(&pipex_session_list))
-               pipex_timer_stop();
 }
 
 Static int
@@ -652,20 +655,16 @@ pipex_get_closed(struct pipex_session_list_req *req,
 Static int
 pipex_destroy_session(struct pipex_session *session)
 {
-       struct radix_node *rn;
-
        /* remove from radix tree and hash chain */
        NET_ASSERT_LOCKED();
 
-       if (!in_nullhost(session->ip_address.sin_addr)) {
-               rn = rn_delete(&session->ip_address, &session->ip_netmask,
-                   pipex_rd_head4, (struct radix_node *)session);
-               KASSERT(rn != NULL);
-       }
-
        pipex_unlink_session(session);
        pipex_rele_session(session);
 
+       /* if final session is destroyed, stop timer */
+       if (LIST_EMPTY(&pipex_session_list))
+               pipex_timer_stop();
+
        return (0);
 }
 
@@ -739,7 +738,8 @@ pipexintr(void)
        mq_delist(&pipexoutq, &ml);
        while ((m = ml_dequeue(&ml)) != NULL) {
                pkt_session = m->m_pkthdr.ph_cookie;
-               if (pkt_session == NULL) {
+               if (pkt_session == NULL ||
+                   pkt_session->state == PIPEX_STATE_CLOSED) {
                        m_freem(m);
                        continue;
                }
@@ -776,7 +776,8 @@ pipexintr(void)
        mq_delist(&pipexinq, &ml);
        while ((m = ml_dequeue(&ml)) != NULL) {
                pkt_session = m->m_pkthdr.ph_cookie;
-               if (pkt_session == NULL) {
+               if (pkt_session == NULL ||
+                   pkt_session->state == PIPEX_STATE_CLOSED) {
                        m_freem(m);
                        continue;
                }

Reply via email to