Start on DTLS setup
authorDavid Woodhouse <David.Woodhouse@intel.com>
Tue, 23 Sep 2008 00:00:08 +0000 (17:00 -0700)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Tue, 23 Sep 2008 00:01:43 +0000 (17:01 -0700)
anyconnect.h
dtls.c
ssl.c

index 056d10c..01f4d67 100644 (file)
@@ -55,6 +55,8 @@ struct anyconnect_info {
        z_stream deflate_strm;
        uint32_t deflate_adler32;
 
+       int dtls_keepalive;
+       unsigned char dtls_session_id[32];
        unsigned char dtls_secret[48];
        SSL_CTX *dtls_ctx;
        SSL *dtls_ssl;
@@ -72,6 +74,7 @@ struct anyconnect_info {
        struct pkt *incoming_queue;
        struct pkt *outgoing_queue;
 
+       socklen_t peer_addrlen;
        struct sockaddr *peer_addr;
 
        int deflate;
diff --git a/dtls.c b/dtls.c
index 20e9a82..2d1b888 100644 (file)
--- a/dtls.c
+++ b/dtls.c
  */
 
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
 
 #include "anyconnect.h"
 
  * easier to debug.
  */   
 
+static unsigned char nybble(unsigned char n)
+{
+       if      (n >= '0' && n <= '9') return n - '0';
+       else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
+       else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
+       return 0;
+}
+
+static unsigned char hex(const char *data)
+{
+       return (nybble(data[0]) << 4) | nybble(data[1]);
+}
 
 int setup_dtls(struct anyconnect_info *vpninfo)
 {
        struct vpn_option *dtls_opt = vpninfo->dtls_options;
+       int sessid_found = 0;
+       int dtls_port = 0;
+       int dtls_fd;
+       int i;
 
        while (dtls_opt) {
-               printf("DTLS option %s : %s\n", dtls_opt->option, dtls_opt->value);
+               if (verbose)
+                       printf("DTLS option %s : %s\n", dtls_opt->option, dtls_opt->value);
+
+               if (!strcmp(dtls_opt->option, "X-DTLS-Session-ID")) {
+                       if (strlen(dtls_opt->value) != 64) {
+                               fprintf(stderr, "X-DTLS-Session-ID not 64 characters\n");
+                               fprintf(stderr, "Is: %s\n", dtls_opt->value);
+                               return -EINVAL;
+                       }
+                       for (i = 0; i < 64; i += 2)
+                               vpninfo->dtls_session_id[i/2] = hex(dtls_opt->value + i);
+                       sessid_found = 1;
+               } else if (!strcmp(dtls_opt->option, "X-DTLS-Port")) {
+                       dtls_port = atol(dtls_opt->value);
+               } else if (!strcmp(dtls_opt->option, "X-DTLS-Keepalive")) {
+                       vpninfo->dtls_keepalive = atol(dtls_opt->value);
+               }
+                       
                dtls_opt = dtls_opt->next;
        }
+       if (!sessid_found || !dtls_port)
+               return -EINVAL;
+
+       if (vpninfo->peer_addr->sa_family == AF_INET) {
+               struct sockaddr_in *sin = (void *)vpninfo->peer_addr;
+               sin->sin_port = htons(dtls_port);
+       } else if (vpninfo->peer_addr->sa_family == AF_INET6) {
+               struct sockaddr_in6 *sin = (void *)vpninfo->peer_addr;
+               sin->sin6_port = htons(dtls_port);
+       } else {
+               fprintf(stderr, "Unknown protocol family %d. Cannot do DTLS\n",
+                       vpninfo->peer_addr->sa_family);
+               return -EINVAL;
+       }
+
+       dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+       if (dtls_fd < 0) {
+               perror("Open UDP socket for DTLS:");
+               return -EINVAL;
+       }
+       
+       if (connect(dtls_fd, vpninfo->peer_addr, vpninfo->peer_addrlen)) {
+               perror("UDP (DTLS) connect:\n");
+               close(dtls_fd);
+               return -EINVAL;
+       }
+
        /* No idea how to do this yet */
        return -EINVAL;
 }
diff --git a/ssl.c b/ssl.c
index 4dad4e1..6c94165 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -118,6 +118,7 @@ static int open_https(struct anyconnect_info *vpninfo)
                                close(ssl_sock);
                                return -ENOMEM;
                        }
+                       vpninfo->peer_addrlen = rp->ai_addrlen;
                        memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
                        break;
                }