Browse code

Allow skipping multple remotes via management interface

The mamangement command "remote SKIP" is extended with an
optional parameter 'count' > 0. If count is greater than
number of connection entries (len), count % len is used.
On going past the index of the last connection entry,
counting is restarted from the first connection entry.

Without this, use of management-query-remote from a UI is
virtually impractical except when there are only a handful
of remote entries. Skipping the entries one by one takes
a long time when there are many entries to be skipped
(~ 1 second per entry). Use of "remote MOD" is not an
option as change of protocol is not supported.

Management clients can determine the availability of this
feature by checking that the management interface version
is > 3. Older versions will ignore the count parameter and
behave identically to using count = 1.

Signed-off-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <20210907223614.8574-1-selva.nair@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22817.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit ec5ffe35a394c44b1ea25b7c10dab7da7d792ef2)

Selva Nair authored on 2021/09/08 07:36:14
Showing 3 changed files
... ...
@@ -877,6 +877,13 @@ use this command:
877 877
 
878 878
   remote SKIP
879 879
 
880
+Starting OpenVPN version 2.6 (management version > 3), skip
881
+multiple remotes using:
882
+
883
+  remote SKIP n
884
+
885
+where n > 0 is the number of remotes to skip.
886
+
880 887
 COMMAND -- proxy  (OpenVPN 2.3 or higher)
881 888
 --------------------------------------------
882 889
 
... ...
@@ -389,6 +389,7 @@ management_callback_remote_cmd(void *arg, const char **p)
389 389
         {
390 390
             flags = CE_MAN_QUERY_REMOTE_SKIP;
391 391
             ret = true;
392
+            c->options.ce_advance_count = (p[2]) ? atoi(p[2]) : 1;
392 393
         }
393 394
         else if (!strcmp(p[1], "MOD") && p[2] && p[3])
394 395
         {
... ...
@@ -563,18 +564,28 @@ next_connection_entry(struct context *c)
563 563
                         c->c1.link_socket_addr.remote_list;
564 564
                 }
565 565
 
566
+                int advance_count = 1;
567
+
568
+                /* If previous connection entry was skipped by management client
569
+                 * with a count to advance by, apply it.
570
+                 */
571
+                if (c->options.ce_advance_count > 0)
572
+                {
573
+                    advance_count = c->options.ce_advance_count;
574
+                }
575
+
566 576
                 /*
567 577
                  * Increase the number of connection attempts
568 578
                  * If this is connect-retry-max * size(l)
569 579
                  * OpenVPN will quit
570 580
                  */
571 581
 
572
-                c->options.unsuccessful_attempts++;
582
+                c->options.unsuccessful_attempts += advance_count;
583
+                l->current += advance_count;
573 584
 
574
-                if (++l->current >= l->len)
585
+                if (l->current >= l->len)
575 586
                 {
576
-
577
-                    l->current = 0;
587
+                    l->current %= l->len;
578 588
                     if (++n_cycles >= 2)
579 589
                     {
580 590
                         msg(M_FATAL, "No usable connection profiles are present");
... ...
@@ -583,6 +594,7 @@ next_connection_entry(struct context *c)
583 583
             }
584 584
         }
585 585
 
586
+        c->options.ce_advance_count = 1;
586 587
         ce = l->array[l->current];
587 588
 
588 589
         if (ce->flags & CE_DISABLED)
... ...
@@ -285,6 +285,8 @@ struct options
285 285
     bool advance_next_remote;
286 286
     /* Counts the number of unsuccessful connection attempts */
287 287
     unsigned int unsuccessful_attempts;
288
+    /* count of connection entries to advance by when no_advance is not set */
289
+    int ce_advance_count;
288 290
     /* the server can suggest a backoff time to the client, it
289 291
      * will still be capped by the max timeout between connections
290 292
      * (300s by default) */