Fix npppd to terminate all PPP sessions properly even in case the
authoryasuoka <yasuoka@openbsd.org>
Wed, 24 Jun 2015 05:20:16 +0000 (05:20 +0000)
committeryasuoka <yasuoka@openbsd.org>
Wed, 24 Jun 2015 05:20:16 +0000 (05:20 +0000)
sending window for L2TP control is full when the control is terminating
(by a L2TP keepalive failure or other reasons).  In that case, if the
L2TP peer didn't respond at all, npppd had kept some PPP sessions
forever.

usr.sbin/npppd/l2tp/l2tp.h
usr.sbin/npppd/l2tp/l2tp_call.c
usr.sbin/npppd/l2tp/l2tp_ctrl.c

index 86698f4..c7ecc94 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: l2tp.h,v 1.10 2014/03/22 04:32:39 yasuoka Exp $       */
+/*     $OpenBSD: l2tp.h,v 1.11 2015/06/24 05:20:16 yasuoka Exp $       */
 
 /*-
  * Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -30,7 +30,7 @@
 /*@file
  * header file for the L2TP module
  */
-/* $Id: l2tp.h,v 1.10 2014/03/22 04:32:39 yasuoka Exp $ */
+/* $Id: l2tp.h,v 1.11 2015/06/24 05:20:16 yasuoka Exp $ */
 
 /************************************************************************
  * Protocol Constants
@@ -444,6 +444,7 @@ l2tp_call        *l2tp_call_create (void);
 int              l2tp_call_init (l2tp_call *, l2tp_ctrl *);
 void             l2tp_call_destroy (l2tp_call *, int);
 void             l2tp_call_admin_disconnect(l2tp_call *);
+void             l2tp_call_drop (l2tp_call *);
 int              l2tp_call_recv_packet (l2tp_ctrl *, l2tp_call *, int, u_char *, int);
 void             l2tp_call_ppp_input (l2tp_call *, u_char *, int, int);
 
index 4d18d22..d1c2358 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: l2tp_call.c,v 1.16 2015/01/19 01:48:59 deraadt Exp $  */
+/*     $OpenBSD: l2tp_call.c,v 1.17 2015/06/24 05:20:16 yasuoka Exp $  */
 
 /*-
  * Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-/* $Id: l2tp_call.c,v 1.16 2015/01/19 01:48:59 deraadt Exp $ */
+/* $Id: l2tp_call.c,v 1.17 2015/06/24 05:20:16 yasuoka Exp $ */
 /**@file L2TP LNS call */
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -125,6 +125,12 @@ l2tp_call_admin_disconnect(l2tp_call *_this)
            NULL, NULL, 0);
 }
 
+void
+l2tp_call_drop(l2tp_call *_this)
+{
+       l2tp_call_disconnect(_this, 0, 0, NULL, NULL, 0);
+}
+
 /*
  * disconnect l2tp connection
  * @param result_code  disconect without CDN, specify zero
index 5b652ea..aa32afc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: l2tp_ctrl.c,v 1.19 2015/01/19 01:48:59 deraadt Exp $  */
+/*     $OpenBSD: l2tp_ctrl.c,v 1.20 2015/06/24 05:20:16 yasuoka Exp $  */
 
 /*-
  * Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  */
 /**@file Control connection processing functions for L2TP LNS */
-/* $Id: l2tp_ctrl.c,v 1.19 2015/01/19 01:48:59 deraadt Exp $ */
+/* $Id: l2tp_ctrl.c,v 1.20 2015/06/24 05:20:16 yasuoka Exp $ */
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/socket.h>
@@ -76,7 +76,7 @@ static void               l2tp_ctrl_purge_ipsec_sa (l2tp_ctrl *);
 static void               l2tp_ctrl_timeout (int, short, void *);
 static int                l2tp_ctrl_resend_una_packets (l2tp_ctrl *);
 static void               l2tp_ctrl_destroy_all_calls (l2tp_ctrl *);
-static int                l2tp_ctrl_disconnect_all_calls (l2tp_ctrl *);
+static int                l2tp_ctrl_disconnect_all_calls (l2tp_ctrl *, int);
 static void               l2tp_ctrl_reset_timeout (l2tp_ctrl *);
 static inline int         l2tp_ctrl_txwin_size (l2tp_ctrl *);
 static inline int         l2tp_ctrl_txwin_is_full (l2tp_ctrl *);
@@ -258,14 +258,14 @@ l2tp_ctrl_send_disconnect_notify(l2tp_ctrl *_this)
        /* Send CDN all Calls */
        ncalls = 0;
        if (slist_length(&_this->call_list) != 0) {
-               ncalls = l2tp_ctrl_disconnect_all_calls(_this);
+               ncalls = l2tp_ctrl_disconnect_all_calls(_this, 0);
                if (ncalls > 0) {
                        /*
                         * Call the function again to check whether the
                         * sending window is fulled.  In case ncalls == 0,
                         * it means we've sent CDN for all calls.
                         */
-                       ncalls = l2tp_ctrl_disconnect_all_calls(_this);
+                       ncalls = l2tp_ctrl_disconnect_all_calls(_this, 0);
                }
        }
        if (ncalls > 0)
@@ -320,7 +320,7 @@ l2tp_ctrl_stop(l2tp_ctrl *_this, int result)
        case L2TP_CTRL_STATE_CLEANUP_WAIT:
 cleanup:
                if (slist_length(&_this->call_list) != 0) {
-                       if (l2tp_ctrl_disconnect_all_calls(_this) > 0)
+                       if (l2tp_ctrl_disconnect_all_calls(_this, 1) > 0)
                                break;
                }
 #if 0
@@ -650,7 +650,7 @@ l2tp_ctrl_destroy_all_calls(l2tp_ctrl *_this)
  * @return return # of calls that is not waiting cleanup.
  */
 static int
-l2tp_ctrl_disconnect_all_calls(l2tp_ctrl *_this)
+l2tp_ctrl_disconnect_all_calls(l2tp_ctrl *_this, int drop)
 {
        int i, len, ncalls;
        l2tp_call *call;
@@ -663,12 +663,12 @@ l2tp_ctrl_disconnect_all_calls(l2tp_ctrl *_this)
                call = slist_get(&_this->call_list, i);
                if (call->state != L2TP_CALL_STATE_CLEANUP_WAIT) {
                        ncalls++;
-
                        if (l2tp_ctrl_txwin_is_full(_this)) {
                                L2TP_CTRL_DBG((_this, LOG_INFO,
                                    "Too many calls.  Sending window is not "
                                    "enough to send CDN to all clients."));
-                               /* nothing to do */
+                               if (drop)
+                                       l2tp_call_drop(call);
                        } else
                                l2tp_call_admin_disconnect(call);
                }