use generic KA stuff for dtls
authorDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 2 Oct 2008 10:20:19 +0000 (11:20 +0100)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 2 Oct 2008 10:20:19 +0000 (11:20 +0100)
anyconnect.h
dtls.c
mainloop.c

index e2752ed..696101e 100644 (file)
@@ -159,6 +159,7 @@ int vpn_add_pollfd(struct anyconnect_info *vpninfo, int fd, short events);
 int vpn_mainloop(struct anyconnect_info *vpninfo);
 int queue_new_packet(struct pkt **q, int type, void *buf, int len);
 void queue_packet(struct pkt **q, struct pkt *new);
+int keepalive_action(struct keepalive_info *ka, int *timeout);
 
 /* xml.c */
 int config_lookup_host(struct anyconnect_info *vpninfo, const char *host);
diff --git a/dtls.c b/dtls.c
index 2d9a689..b800831 100644 (file)
--- a/dtls.c
+++ b/dtls.c
@@ -253,6 +253,7 @@ int dtls_mainloop(struct anyconnect_info *vpninfo, int *timeout)
        unsigned char buf[2000];
        int len;
        int work_done = 0;
+       char magic_pkt;
 
        while ( (len = SSL_read(vpninfo->dtls_ssl, buf, sizeof(buf))) > 0 ) {
                if (verbose)
@@ -278,42 +279,13 @@ int dtls_mainloop(struct anyconnect_info *vpninfo, int *timeout)
                        return 1;
                }
        }
-       while (vpninfo->outgoing_queue) {
-               struct pkt *this = vpninfo->outgoing_queue;
-               int ret;
-
-               vpninfo->outgoing_queue = this->next;
-
-               /* One byte of header */
-               this->hdr[7] = AC_PKT_DATA;
-               
-               ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
-               /* There's not a lot we can do if the write fails. If the link is
-                  really dead, DPD will kick in and we should fall back to SSL,
-                  if that's still working */
-               vpninfo->dtls_times.last_tx = time(NULL);
-               if (verbose) {
-                       printf("Sent DTLS packet of %d bytes; SSL_write() returned %d\n",
-                              this->len, ret);
-               }
-       }
 
-       /* DPD is bidirectional -- PKT 3 out, PKT 4 back */
-       if (vpninfo->dtls_times.dpd) {
-               time_t now = time(NULL);
-               time_t due = vpninfo->dtls_times.last_rx + vpninfo->dtls_times.dpd;
-               time_t overdue = vpninfo->dtls_times.last_rx + (2 * vpninfo->dtls_times.dpd);
-
-               /* If we already have DPD outstanding, don't flood */
-               if (vpninfo->dtls_times.last_dpd > vpninfo->dtls_times.last_rx) {
-                       if (verbose) {
-                               printf("DTLS DPD outstanding. Will kill in %ld seconds\n",
-                                      overdue - now);
-                       }
-                       due = vpninfo->dtls_times.last_dpd + vpninfo->dtls_times.dpd;
-               }
-               if (now > overdue) {
-                       fprintf(stderr, "DTLS Dead Peer Detection detected dead peer!\n");
+       switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
+       case KA_REKEY:
+               if (verbose)
+                       printf("DTLS rekey due\n");
+               if (dtls_rekey(vpninfo)) {
+                       fprintf(stderr, "DTLS rekey failed\n");
                        /* Fall back to SSL */
                        SSL_free(vpninfo->dtls_ssl);
                        close(vpninfo->dtls_fd);
@@ -322,73 +294,66 @@ int dtls_mainloop(struct anyconnect_info *vpninfo, int *timeout)
                        vpninfo->dtls_fd = -1;
                        return 1;
                }
-               if (now >= due) {
-                       static unsigned char dtls_dpd_pkt[1] = { 3 };
-                       /* Haven't heard anything from the other end for a while.
-                          Check if it's still there */
-                       /* FIXME: If isn't, we should act on that */
-                       SSL_write(vpninfo->dtls_ssl, dtls_dpd_pkt, 1);
-                       vpninfo->dtls_times.last_dpd = vpninfo->dtls_times.last_tx = now;
-
-                       due = now + vpninfo->dtls_times.dpd;
-                       if (verbose)
-                               printf("Sent DTLS DPD\n");
-               }
-
-               if (verbose && due < overdue)
-                       printf("Next DTLS DPD due in %ld seconds\n", (due - now));
-               if (*timeout > (due - now) * 1000)
-                       *timeout = (due - now) * 1000;
-       }
+               time(&vpninfo->dtls_times.last_rekey);
+               work_done = 1;
+               break;
+
+
+       case KA_DPD_DEAD:
+               fprintf(stderr, "DTLS Dead Peer Detection detected dead peer!\n");
+               /* Fall back to SSL */
+               SSL_free(vpninfo->dtls_ssl);
+               close(vpninfo->dtls_fd);
+               vpninfo->pfds[vpninfo->dtls_pfd].fd = -1;
+               vpninfo->dtls_ssl = NULL;
+               vpninfo->dtls_fd = -1;
+               return 1;
+
+       case KA_DPD:
+               if (verbose)
+                       printf("Send DTLS DPD\n");
 
-       /* Keepalive is just client -> server */
-       if (vpninfo->dtls_times.keepalive) {
-               time_t now = time(NULL);
-               time_t due = vpninfo->dtls_times.last_tx + vpninfo->dtls_times.keepalive;
+               magic_pkt = AC_PKT_DPD_OUT;
+               SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
+               /* last_dpd will just have been set */
+               vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
+               work_done = 1;
+               break;
 
-               if (now >= due) {
-                       static unsigned char dtls_keepalive_pkt[1] = { 7 };
+       case KA_KEEPALIVE:
+               if (verbose)
+                       printf("Send DTLS Keepalive\n");
 
-                       /* Send something (which is discarded), to keep
-                          the connection alive. */
-                       SSL_write(vpninfo->dtls_ssl, dtls_keepalive_pkt, 1);
-                       vpninfo->dtls_times.last_tx = now;
+               /* No need to send an explicit keepalive
+                  if we have real data to send */
+               if (vpninfo->outgoing_queue)
+                       break;
 
-                       due = now + vpninfo->dtls_times.keepalive;
-                       if (verbose)
-                               printf("Sent DTLS Keepalive\n");
-               }
+               magic_pkt = AC_PKT_KEEPALIVE;
+               SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
+               time(&vpninfo->dtls_times.last_tx);
+               work_done = 1;
+               break;
 
-               if (verbose)
-                       printf("Next DTLS Keepalive due in %ld seconds\n", (due - now));
-               if (*timeout > (due - now) * 1000)
-                       *timeout = (due - now) * 1000;
+       case KA_NONE:
+               ;
        }
 
-       if (vpninfo->dtls_times.rekey) {
-               time_t now = time(NULL);
-               time_t due = vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey;
+       while (vpninfo->outgoing_queue) {
+               struct pkt *this = vpninfo->outgoing_queue;
+               int ret;
 
-               if (now >= due) {
-                       if (verbose)
-                               printf("DTLS rekey due\n");
-                       if (dtls_rekey(vpninfo)) {
-                               fprintf(stderr, "DTLS rekey failed\n");
-                               /* Fall back to SSL */
-                               SSL_free(vpninfo->dtls_ssl);
-                               close(vpninfo->dtls_fd);
-                               vpninfo->pfds[vpninfo->dtls_pfd].fd = -1;
-                               vpninfo->dtls_ssl = NULL;
-                               vpninfo->dtls_fd = -1;
-                               return 1;
-                       }
-                       vpninfo->dtls_times.last_rekey = time(NULL);
-                       due = vpninfo->dtls_times.last_rekey + vpninfo->dtls_times.rekey;
+               vpninfo->outgoing_queue = this->next;
+
+               /* One byte of header */
+               this->hdr[7] = AC_PKT_DATA;
+               
+               ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
+               time(&vpninfo->dtls_times.last_tx);
+               if (verbose) {
+                       printf("Sent DTLS packet of %d bytes; SSL_write() returned %d\n",
+                              this->len, ret);
                }
-               if (verbose)
-                       printf("Next DTLS rekey due in %ld seconds\n", (due - now));
-               if (*timeout > (due - now) * 1000)
-                       *timeout = (due - now) * 1000;
        }
 
        return work_done;
index c1cac2e..c01fba9 100644 (file)
@@ -134,7 +134,7 @@ int vpn_mainloop(struct anyconnect_info *vpninfo)
        return 0;
 }
 
-int keepalive_action(struct keepalive_info *ka, time_t *timeout)
+int keepalive_action(struct keepalive_info *ka, int *timeout)
 {
        time_t now = time(NULL);
 
@@ -144,6 +144,8 @@ int keepalive_action(struct keepalive_info *ka, time_t *timeout)
                if (now >= due)
                        return KA_REKEY;
 
+               if (verbose)
+                       printf("Rekey in %d seconds\n", (int)(due - now));
                if (*timeout > (due - now) * 1000)
                        *timeout = (due - now) * 1000;
        }
@@ -169,6 +171,8 @@ int keepalive_action(struct keepalive_info *ka, time_t *timeout)
                        return KA_DPD;
                }
 
+               if (verbose)
+                       printf("DPD in %d seconds\n", (int)(due - now));
                if (*timeout > (due - now) * 1000)
                        *timeout = (due - now) * 1000;
        }
@@ -182,6 +186,8 @@ int keepalive_action(struct keepalive_info *ka, time_t *timeout)
                if (now >= due)
                        return KA_KEEPALIVE;
 
+               if (verbose)
+                       printf("KA in %d seconds\n", (int)(due - now));
                if (*timeout > (due - now) * 1000)
                        *timeout = (due - now) * 1000;
        }