On Tue, Jun 09, 2020 at 10:42:13AM +0200, Martin Pieuchot wrote:
> >
> > [skip]
> >
> > +   pxi->pxi_ifcontext.ifnet_this = ifp;
> > +   pxi->pxi_ifcontext.pipexmode = PIPEX_ENABLED;
> > +
> > +   error = pipex_init_session(session, req, &pxi->pxi_ifcontext);
> 
> Can you make pipex_init_session() not require an `iface' argument?  This
> way you don't need to do a pool_get/put(9) in case of error.

`iface' is not required now. But session requires to be allocated
before it's initialization. Now pipex_init_session() will allocate
session but after all checks. I placed MPPE related checks before
session allocation so there is no pool_get(9)/pool_put(9) dances. Also
session is not linked to any list after successfull pipex_init_session()
call.

> >
> > [skip]
> >
> > -           return (EEXIST);
> > +   LIST_FOREACH(session_tmp, &pipex_session_list, session_list) {
> > +           if (session_tmp->protocol == req->pr_protocol &&
> > +               session_tmp->session_id == req->pr_session_id)
> > +                   return (EEXIST);
> > +   }
> 
> Why can't we keep pipex_lookup_by_session_id() here?

pipex_lookup_by_session_id() does search in hash not in `session_list'.
But since pipex_init_session() doesn't link session to this list too
it's not actual.

> >
> > [skip] 
> >
> > -   NET_ASSERT_LOCKED();
> > +   LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
> > +
> > +   /* if first session is added, start timer */
> > +   if (LIST_NEXT(session, session_list) == NULL)
> > +           pipex_timer_start();
> 
> Adding `session' to the list and starting the timer should be in
> link_session(), no?  Their counterpart operation are done in
> unlink_session().

I decided to split pipex_unlink_session() to pipex_unlink_session()
which only disconnects session from pipex(4) and pipex_rele_session()
which releases session. Only link/unlink routines operates timer now.

Updated diff below.

1. pipex_init_session() does checks, allocates session and initializes
it. This session is not linked to pipex(4).
2. pipex_rele_session() just releases allocated session and it's
internal allocations.
3. pipex_link_session() does checks and links session to pipex(4).
4. pipex_unlink_session() unlinks session to pipex(4).


Index: sys/net/if_pppx.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.87
diff -u -p -r1.87 if_pppx.c
--- sys/net/if_pppx.c   29 May 2020 06:51:52 -0000      1.87
+++ sys/net/if_pppx.c   9 Jun 2020 12:09:35 -0000
@@ -155,7 +155,7 @@ struct pppx_if {
        int                     pxi_unit;
        struct ifnet            pxi_if;
        struct pppx_dev         *pxi_dev;
-       struct pipex_session    pxi_session;
+       struct pipex_session    *pxi_session;
        struct pipex_iface_context      pxi_ifcontext;
 };
 
@@ -659,14 +659,10 @@ pppx_add_session(struct pppx_dev *pxd, s
 {
        struct pppx_if *pxi;
        struct pipex_session *session;
-       struct pipex_hash_head *chain;
        struct ifnet *ifp;
        int unit, error = 0;
        struct in_ifaddr *ia;
        struct sockaddr_in ifaddr;
-#ifdef PIPEX_PPPOE
-       struct ifnet *over_ifp = NULL;
-#endif
 
        /*
         * XXX: As long as `session' is allocated as part of a `pxi'
@@ -676,156 +672,21 @@ pppx_add_session(struct pppx_dev *pxd, s
        if (req->pr_timeout_sec != 0)
                return (EINVAL);
 
-       switch (req->pr_protocol) {
-#ifdef PIPEX_PPPOE
-       case PIPEX_PROTO_PPPOE:
-               over_ifp = ifunit(req->pr_proto.pppoe.over_ifname);
-               if (over_ifp == NULL)
-                       return (EINVAL);
-               if (req->pr_peer_address.ss_family != AF_UNSPEC)
-                       return (EINVAL);
-               break;
-#endif
-#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
-       case PIPEX_PROTO_PPTP:
-       case PIPEX_PROTO_L2TP:
-               switch (req->pr_peer_address.ss_family) {
-               case AF_INET:
-                       if (req->pr_peer_address.ss_len != sizeof(struct 
sockaddr_in))
-                               return (EINVAL);
-                       break;
-#ifdef INET6
-               case AF_INET6:
-                       if (req->pr_peer_address.ss_len != sizeof(struct 
sockaddr_in6))
-                               return (EINVAL);
-                       break;
-#endif
-               default:
-                       return (EPROTONOSUPPORT);
-               }
-               if (req->pr_peer_address.ss_family !=
-                   req->pr_local_address.ss_family ||
-                   req->pr_peer_address.ss_len !=
-                   req->pr_local_address.ss_len)
-                       return (EINVAL);
-               break;
-#endif /* defined(PIPEX_PPTP) || defined(PIPEX_L2TP) */
-       default:
-               return (EPROTONOSUPPORT);
-       }
-
-       session = pipex_lookup_by_session_id(req->pr_protocol,
-           req->pr_session_id);
-       if (session)
-               return (EEXIST);
+       error = pipex_init_session(&session, req);
+       if (error)
+               return (error);
 
        pxi = pool_get(pppx_if_pl, PR_WAITOK | PR_ZERO);
-
-       session = &pxi->pxi_session;
        ifp = &pxi->pxi_if;
 
+       pxi->pxi_session = session;
        /* fake a pipex interface context */
-       session->pipex_iface = &pxi->pxi_ifcontext;
-       session->pipex_iface->ifnet_this = ifp;
-       session->pipex_iface->pipexmode = PIPEX_ENABLED;
-
-       /* setup session */
-       session->state = PIPEX_STATE_OPENED;
-       session->protocol = req->pr_protocol;
-       session->session_id = req->pr_session_id;
-       session->peer_session_id = req->pr_peer_session_id;
-       session->peer_mru = req->pr_peer_mru;
-       session->timeout_sec = req->pr_timeout_sec;
-       session->ppp_flags = req->pr_ppp_flags;
-       session->ppp_id = req->pr_ppp_id;
-
-       session->ip_forward = 1;
-
-       session->ip_address.sin_family = AF_INET;
-       session->ip_address.sin_len = sizeof(struct sockaddr_in);
-       session->ip_address.sin_addr = req->pr_ip_address;
-
-       session->ip_netmask.sin_family = AF_INET;
-       session->ip_netmask.sin_len = sizeof(struct sockaddr_in);
-       session->ip_netmask.sin_addr = req->pr_ip_netmask;
-
-       if (session->ip_netmask.sin_addr.s_addr == 0L)
-               session->ip_netmask.sin_addr.s_addr = 0xffffffffL;
-       session->ip_address.sin_addr.s_addr &=
-           session->ip_netmask.sin_addr.s_addr;
-
-       if (req->pr_peer_address.ss_len > 0)
-               memcpy(&session->peer, &req->pr_peer_address,
-                   MIN(req->pr_peer_address.ss_len, sizeof(session->peer)));
-       if (req->pr_local_address.ss_len > 0)
-               memcpy(&session->local, &req->pr_local_address,
-                   MIN(req->pr_local_address.ss_len, sizeof(session->local)));
-#ifdef PIPEX_PPPOE
-       if (req->pr_protocol == PIPEX_PROTO_PPPOE)
-               session->proto.pppoe.over_ifidx = over_ifp->if_index;
-#endif
-#ifdef PIPEX_PPTP
-       if (req->pr_protocol == PIPEX_PROTO_PPTP) {
-               struct pipex_pptp_session *sess_pptp = &session->proto.pptp;
-
-               sess_pptp->snd_gap = 0;
-               sess_pptp->rcv_gap = 0;
-               sess_pptp->snd_una = req->pr_proto.pptp.snd_una;
-               sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt;
-               sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt;
-               sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked;
-
-               sess_pptp->winsz = req->pr_proto.pptp.winsz;
-               sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz;
-               sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz;
-               /* last ack number */
-               sess_pptp->ul_snd_una = sess_pptp->snd_una - 1;
-       }
-#endif
-#ifdef PIPEX_L2TP
-       if (req->pr_protocol == PIPEX_PROTO_L2TP) {
-               struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp;
-
-               /* session keys */
-               sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id;
-               sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id;
-
-               /* protocol options */
-               sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags;
-
-               /* initial state of dynamic context */
-               sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0;
-               sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt;
-               sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt;
-               sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una;
-               sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked;
-               /* last ack number */
-               sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1;
-       }
-#endif
-#ifdef PIPEX_MPPE
-       if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0)
-               pipex_session_init_mppe_recv(session,
-                   req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits,
-                   req->pr_mppe_recv.master_key);
-       if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0)
-               pipex_session_init_mppe_send(session,
-                   req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits,
-                   req->pr_mppe_send.master_key);
-
-       if (pipex_session_is_mppe_required(session)) {
-               if (!pipex_session_is_mppe_enabled(session) ||
-                   !pipex_session_is_mppe_accepted(session)) {
-                       pool_put(pppx_if_pl, pxi);
-                       return (EINVAL);
-               }
-       }
-#endif
+       pxi->pxi_ifcontext.ifnet_this = ifp;
+       pxi->pxi_ifcontext.pipexmode = PIPEX_ENABLED;
 
        /* try to set the interface up */
        unit = pppx_if_next_unit();
        if (unit < 0) {
-               pool_put(pppx_if_pl, pxi);
                error = ENOMEM;
                goto out;
        }
@@ -837,7 +698,6 @@ pppx_add_session(struct pppx_dev *pxd, s
 
        /* this is safe without splnet since we're not modifying it */
        if (RBT_FIND(pppx_ifs, &pppx_ifs, pxi) != NULL) {
-               pool_put(pppx_if_pl, pxi);
                error = EADDRINUSE;
                goto out;
        }
@@ -858,24 +718,9 @@ pppx_add_session(struct pppx_dev *pxd, s
        ifp->if_softc = pxi;
        /* ifp->if_rdomain = req->pr_rdomain; */
 
-       /* hook up pipex context */
-       chain = PIPEX_ID_HASHTABLE(session->session_id);
-       LIST_INSERT_HEAD(chain, session, id_chain);
-       LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
-#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
-       switch (req->pr_protocol) {
-       case PIPEX_PROTO_PPTP:
-       case PIPEX_PROTO_L2TP:
-               chain = PIPEX_PEER_ADDR_HASHTABLE(
-                   pipex_sockaddr_hash_key(&session->peer.sa));
-               LIST_INSERT_HEAD(chain, session, peer_addr_chain);
-               break;
-       }
-#endif
-
-       /* if first session is added, start timer */
-       if (LIST_NEXT(session, session_list) == NULL)
-               pipex_timer_start();
+       error = pipex_link_session(session, &pxi->pxi_ifcontext);
+       if (error)
+               goto remove;
 
        /* XXXSMP breaks atomicity */
        NET_UNLOCK();
@@ -928,7 +773,16 @@ pppx_add_session(struct pppx_dev *pxd, s
        }
        pxi->pxi_ready = 1;
 
+       return (error);
+
+remove:
+       if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL)
+               panic("%s: pppx_ifs modified while lock was held", __func__);
+       LIST_REMOVE(pxi, pxi_list);
 out:
+       pool_put(pppx_if_pl, pxi);
+       pipex_rele_session(session);
+
        return (error);
 }
 
@@ -941,7 +795,7 @@ pppx_del_session(struct pppx_dev *pxd, s
        if (pxi == NULL)
                return (EINVAL);
 
-       req->pcr_stat = pxi->pxi_session.stat;
+       req->pcr_stat = pxi->pxi_session->stat;
 
        pppx_if_destroy(pxd, pxi);
        return (0);
@@ -1005,29 +859,17 @@ pppx_if_destroy(struct pppx_dev *pxd, st
 
        NET_ASSERT_LOCKED();
        pxi->pxi_ready = 0;
-       session = &pxi->pxi_session;
+       session = pxi->pxi_session;
        ifp = &pxi->pxi_if;
 
-       LIST_REMOVE(session, id_chain);
-       LIST_REMOVE(session, session_list);
-#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
-       switch (session->protocol) {
-       case PIPEX_PROTO_PPTP:
-       case PIPEX_PROTO_L2TP:
-               LIST_REMOVE(session, peer_addr_chain);
-               break;
-       }
-#endif
-
-       /* if final session is destroyed, stop timer */
-       if (LIST_EMPTY(&pipex_session_list))
-               pipex_timer_stop();
+       pipex_unlink_session(session);
 
        /* XXXSMP breaks atomicity */
        NET_UNLOCK();
        if_detach(ifp);
        NET_LOCK();
 
+       pipex_rele_session(session);
        if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL)
                panic("%s: pppx_ifs modified while lock was held", __func__);
        LIST_REMOVE(pxi, pxi_list);
@@ -1057,7 +899,7 @@ pppx_if_start(struct ifnet *ifp)
                ifp->if_obytes += m->m_pkthdr.len;
                ifp->if_opackets++;
 
-               pipex_ppp_output(m, &pxi->pxi_session, proto);
+               pipex_ppp_output(m, pxi->pxi_session, proto);
        }
 }
 
@@ -1117,7 +959,7 @@ pppx_if_output(struct ifnet *ifp, struct
                }
                th = mtod(m, struct pppx_hdr *);
                th->pppx_proto = 0;     /* not used */
-               th->pppx_id = pxi->pxi_session.ppp_id;
+               th->pppx_id = pxi->pxi_session->ppp_id;
                rw_enter_read(&pppx_devs_lk);
                error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m);
                if (error == 0) {
@@ -1156,7 +998,7 @@ pppx_if_ioctl(struct ifnet *ifp, u_long 
 
        case SIOCSIFMTU:
                if (ifr->ifr_mtu < 512 ||
-                   ifr->ifr_mtu > pxi->pxi_session.peer_mru)
+                   ifr->ifr_mtu > pxi->pxi_session->peer_mru)
                        error = EINVAL;
                else
                        ifp->if_mtu = ifr->ifr_mtu;
Index: sys/net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.114
diff -u -p -r1.114 pipex.c
--- sys/net/pipex.c     31 May 2020 03:14:59 -0000      1.114
+++ sys/net/pipex.c     9 Jun 2020 12:09:35 -0000
@@ -258,20 +258,16 @@ pipex_ioctl(struct pipex_iface_context *
 /************************************************************************
  * Session management functions
  ************************************************************************/
-Static int
-pipex_add_session(struct pipex_session_req *req,
-    struct pipex_iface_context *iface)
+int
+pipex_init_session(struct pipex_session **rsession,
+    struct pipex_session_req *req)
 {
        struct pipex_session *session;
-       struct pipex_hash_head *chain;
-       struct radix_node *rn;
 #ifdef PIPEX_PPPOE
        struct ifnet *over_ifp = NULL;
 #endif
 
        /* Checks requeted parameters.  */
-       if (!iface->pipexmode)
-               return (ENXIO);
        switch (req->pr_protocol) {
 #ifdef PIPEX_PPPOE
        case PIPEX_PROTO_PPPOE:
@@ -311,21 +307,31 @@ pipex_add_session(struct pipex_session_r
        default:
                return (EPROTONOSUPPORT);
        }
-
-       session = pipex_lookup_by_session_id(req->pr_protocol,
-           req->pr_session_id);
-       if (session)
-               return (EEXIST);
+#ifdef PIPEX_MPPE
+       if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
+               if (req->pr_mppe_recv.keylenbits <= 0)
+                       return (EINVAL);
+       }
+       if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
+               if (req->pr_mppe_send.keylenbits <= 0)
+                       return (EINVAL);
+       }
+       if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_REQUIRED) != 0) {
+               if ((req->pr_ppp_flags &
+                   (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED)) !=
+                   (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED))
+                       return (EINVAL);
+       }
+#endif
 
        /* prepare a new session */
        session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
-       session->state = PIPEX_STATE_OPENED;
+       session->state = PIPEX_STATE_INITIAL;
        session->protocol = req->pr_protocol;
        session->session_id = req->pr_session_id;
        session->peer_session_id = req->pr_peer_session_id;
        session->peer_mru = req->pr_peer_mru;
        session->timeout_sec = req->pr_timeout_sec;
-       session->pipex_iface = iface;
        session->ppp_flags = req->pr_ppp_flags;
        session->ppp_id = req->pr_ppp_id;
 
@@ -396,78 +402,131 @@ pipex_add_session(struct pipex_session_r
 #endif
 #ifdef PIPEX_MPPE
        if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
-               if (req->pr_mppe_recv.keylenbits <= 0) {
-                       pool_put(&pipex_session_pool, session);
-                       return (EINVAL);
-               }
                pipex_session_init_mppe_recv(session,
                    req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits,
                    req->pr_mppe_recv.master_key);
        }
        if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
-               if (req->pr_mppe_send.keylenbits <= 0) {
-                       pool_put(&pipex_session_pool, session);
-                       return (EINVAL);
-               }
                pipex_session_init_mppe_send(session,
                    req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits,
                    req->pr_mppe_send.master_key);
        }
+#endif
 
-       if (pipex_session_is_mppe_required(session)) {
-               if (!pipex_session_is_mppe_enabled(session) ||
-                   !pipex_session_is_mppe_accepted(session)) {
-                       pool_put(&pipex_session_pool, session);
-                       return (EINVAL);
-               }
+       *rsession = session;
+
+       return 0;
+}
+
+void
+pipex_rele_session(struct pipex_session *session)
+{
+       if (session->mppe_recv.old_session_keys)
+               pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
+       pool_put(&pipex_session_pool, session);
+}
+
+int
+pipex_link_session(struct pipex_session *session,
+       struct pipex_iface_context *iface)
+{
+       struct pipex_hash_head *chain;
+
+       if (!iface->pipexmode)
+               return (ENXIO);
+       if (pipex_lookup_by_session_id(session->protocol,
+           session->session_id))
+               return (EEXIST);
+
+       session->pipex_iface = iface;
+
+       LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
+       chain = PIPEX_ID_HASHTABLE(session->session_id);
+       LIST_INSERT_HEAD(chain, session, id_chain);
+#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
+       switch (session->protocol) {
+       case PIPEX_PROTO_PPTP:
+       case PIPEX_PROTO_L2TP:
+               chain = PIPEX_PEER_ADDR_HASHTABLE(
+                   pipex_sockaddr_hash_key(&session->peer.sa));
+               LIST_INSERT_HEAD(chain, session, peer_addr_chain);
        }
 #endif
 
-       NET_ASSERT_LOCKED();
+       /* if first session is added, start timer */
+       if (LIST_NEXT(session, session_list) == NULL)
+               pipex_timer_start();
+       session->state = PIPEX_STATE_OPENED;
+
+       return (0);
+}
+
+void
+pipex_unlink_session(struct pipex_session *session)
+{
+       LIST_REMOVE(session, id_chain);
+#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
+       switch (session->protocol) {
+       case PIPEX_PROTO_PPTP:
+       case PIPEX_PROTO_L2TP:
+               LIST_REMOVE(session, peer_addr_chain);
+               break;
+       }
+#endif
+
+       LIST_REMOVE(session, session_list);
+
+       /* if final session is destroyed, stop timer */
+       if (LIST_EMPTY(&pipex_session_list))
+               pipex_timer_stop();
+}
+
+Static int
+pipex_add_session(struct pipex_session_req *req,
+    struct pipex_iface_context *iface)
+{
+       struct pipex_session *session;
+       struct radix_node *rn;
+       int error;
+
+       if ((error = pipex_init_session(&session, req)) != 0)
+               goto out;
+
        /* commit the session */
        if (!in_nullhost(session->ip_address.sin_addr)) {
                if (pipex_lookup_by_ip_address(session->ip_address.sin_addr)
                    != NULL) {
-                       pool_put(&pipex_session_pool, session);
-                       return (EADDRINUSE);
+                       error = EADDRINUSE;
+                       goto free;
                }
 
                rn = rn_addroute(&session->ip_address, &session->ip_netmask,
                    pipex_rd_head4, session->ps4_rn, RTP_STATIC);
                if (rn == NULL) {
-                       pool_put(&pipex_session_pool, session);
-                       return (ENOMEM);
+                       error = ENOMEM;
+                       goto free;
                }
        }
        if (0) { /* NOT YET */
                rn = rn_addroute(&session->ip6_address, &session->ip6_prefixlen,
                    pipex_rd_head6, session->ps6_rn, RTP_STATIC);
                if (rn == NULL) {
-                       pool_put(&pipex_session_pool, session);
-                       return (ENOMEM);
+                       error = ENOMEM;
+                       goto free;
                }
        }
 
-       chain = PIPEX_ID_HASHTABLE(session->session_id);
-       LIST_INSERT_HEAD(chain, session, id_chain);
-       LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
-#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
-       switch (req->pr_protocol) {
-       case PIPEX_PROTO_PPTP:
-       case PIPEX_PROTO_L2TP:
-               chain = PIPEX_PEER_ADDR_HASHTABLE(
-                   pipex_sockaddr_hash_key(&session->peer.sa));
-               LIST_INSERT_HEAD(chain, session, peer_addr_chain);
-       }
-#endif
-
-       /* if first session is added, start timer */
-       if (LIST_NEXT(session, session_list) == NULL)
-               pipex_timer_start();
+       if ((error = pipex_link_session(session, iface)) != 0)
+               goto free;
 
        pipex_session_log(session, LOG_INFO, "PIPEX is ready.");
 
-       return (0);
+       return 0;
+
+free:
+       pipex_rele_session(session);
+out:
+       return error;
 }
 
 int
@@ -593,23 +652,7 @@ pipex_destroy_session(struct pipex_sessi
                KASSERT(rn != NULL);
        }
 
-       LIST_REMOVE(session, id_chain);
-       LIST_REMOVE(session, session_list);
-#if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
-       switch (session->protocol) {
-       case PIPEX_PROTO_PPTP:
-       case PIPEX_PROTO_L2TP:
-               LIST_REMOVE(session, peer_addr_chain);
-               break;
-       }
-#endif
-
-       /* if final session is destroyed, stop timer */
-       if (LIST_EMPTY(&pipex_session_list))
-               pipex_timer_stop();
-
-       if (session->mppe_recv.old_session_keys)
-               pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
+       pipex_unlink_session(session);
        pool_put(&pipex_session_pool, session);
 
        return (0);
Index: sys/net/pipex_local.h
===================================================================
RCS file: /cvs/src/sys/net/pipex_local.h,v
retrieving revision 1.34
diff -u -p -r1.34 pipex_local.h
--- sys/net/pipex_local.h       26 May 2020 07:06:37 -0000      1.34
+++ sys/net/pipex_local.h       9 Jun 2020 12:09:35 -0000
@@ -376,6 +376,12 @@ extern struct pipex_hash_head      pipex_id_h
 
 void                  pipex_iface_start (struct pipex_iface_context *);
 void                  pipex_iface_stop (struct pipex_iface_context *);
+int                   pipex_init_session(struct pipex_session **,
+                                             struct pipex_session_req *);
+void                  pipex_rele_session(struct pipex_session *);
+int                   pipex_link_session(struct pipex_session *,
+                                             struct pipex_iface_context *);
+void                  pipex_unlink_session(struct pipex_session *);
 int                   pipex_add_session (struct pipex_session_req *, struct 
pipex_iface_context *);
 int                   pipex_close_session (struct pipex_session_close_req *,
                           struct pipex_iface_context *);

Reply via email to