Don't use msg on error.
[openssl.git] / crypto / bio / bss_dgram.c
index a5a5cc125598af55d5e82640bb982a630e6de2e6..8a1eb6de8b2357a372b954830692aa026ff5f7d8 100644 (file)
@@ -66,7 +66,7 @@
 #include <openssl/bio.h>
 #ifndef OPENSSL_NO_DGRAM
 
-#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
+#if defined(OPENSSL_SYS_VMS)
 #include <sys/timeb.h>
 #endif
 
 #define IP_MTU      14 /* linux is lame */
 #endif
 
+#if OPENSSL_USE_IPV6 && !defined(IPPROTO_IPV6)
+#define IPPROTO_IPV6 41 /* windows is lame */
+#endif
+
 #if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED)
 /* Standard definition causes type-punning problems. */
 #undef IN6_IS_ADDR_V4MAPPED
@@ -278,7 +282,7 @@ static void dgram_adjust_rcv_timeout(BIO *b)
 
                sz.i = sizeof(timeout);
                if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
-                                          (void*)&timeout, &sz) < 0)
+                                          (void*)&timeout, &sz.i) < 0)
                        { perror("getsockopt"); }
                else
                        {
@@ -460,8 +464,8 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
        int *ip;
        struct sockaddr *to = NULL;
        bio_dgram_data *data = NULL;
-#if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
        int sockopt_val = 0;
+#if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
        socklen_t sockopt_len;  /* assume that system supporting IP_MTU is
                                 * modern enough to define socklen_t */
        socklen_t addr_len;
@@ -573,10 +577,10 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                        ret = -1;
                        break;
                        }
-               ret = -1;
 #else
-               break;
+               ret = -1;
 #endif
+               break;
        case BIO_CTRL_DGRAM_QUERY_MTU:
 #if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU)
                addr_len = (socklen_t)sizeof(addr);
@@ -748,7 +752,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 
                sz.i = sizeof(timeout);
                if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
-                       (void*)&timeout, &sz) < 0)
+                       (void*)&timeout, &sz.i) < 0)
                        { perror("getsockopt"); ret = -1; }
                else
                        {
@@ -797,7 +801,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 
                sz.i = sizeof(timeout);
                if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
-                       (void*)&timeout, &sz) < 0)
+                       (void*)&timeout, &sz.i) < 0)
                        { perror("getsockopt"); ret = -1; }
                else
                        {
@@ -805,7 +809,6 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                        tv->tv_usec = (timeout % 1000) * 1000;
                        ret = sizeof(*tv);
                        }
-               }
 #else
                sz.i = sizeof(struct timeval);
                if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 
@@ -848,6 +851,50 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                        ret = 0;
                break;
 #endif
+       case BIO_CTRL_DGRAM_SET_DONT_FRAG:
+               sockopt_val = num ? 1 : 0;
+
+               switch (data->peer.sa.sa_family)
+                       {
+                       case AF_INET:
+#if defined(IP_DONTFRAG)
+                               if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAG,
+                                       &sockopt_val, sizeof(sockopt_val))) < 0)
+                                       { perror("setsockopt"); ret = -1; }
+#elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTUDISCOVER)
+                               if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),
+                                   (ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
+                                       &sockopt_val, sizeof(sockopt_val))) < 0)
+                                       { perror("setsockopt"); ret = -1; }
+#elif defined(OPENSSL_SYS_WINDOWS) && defined(IP_DONTFRAGMENT)
+                               if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAGMENT,
+                                       (const char *)&sockopt_val, sizeof(sockopt_val))) < 0)
+                                       { perror("setsockopt"); ret = -1; }
+#else
+                               ret = -1;
+#endif
+                               break;
+#if OPENSSL_USE_IPV6 
+                       case AF_INET6:
+#if defined(IPV6_DONTFRAG)
+                               if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_DONTFRAG,
+                                       (const void *)&sockopt_val, sizeof(sockopt_val))) < 0)
+                                       { perror("setsockopt"); ret = -1; }
+#elif defined(OPENSSL_SYS_LINUX) && defined(IPV6_MTUDISCOVER)
+                               if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),
+                                   (ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
+                                       &sockopt_val, sizeof(sockopt_val))) < 0)
+                                       { perror("setsockopt"); ret = -1; }
+#else
+                               ret = -1;
+#endif
+                               break;
+#endif
+                       default:
+                               ret = -1;
+                               break;
+                       }
+               break;
        default:
                ret=0;
                break;
@@ -904,11 +951,11 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag)
         * already, otherwise the connected socket won't use it. */
        sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
        authchunks = OPENSSL_malloc(sockopt_len);
-       memset(authchunks, 0, sizeof(sockopt_len));
+       memset(authchunks, 0, sockopt_len);
        ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
        OPENSSL_assert(ret >= 0);
-       
-       for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
+
+       for (p = (unsigned char*) authchunks->gauth_chunks;
             p < (unsigned char*) authchunks + sockopt_len;
             p += sizeof(uint8_t))
                {
@@ -1035,6 +1082,13 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
                        msg.msg_flags = 0;
                        n = recvmsg(b->num, &msg, 0);
 
+                       if (n <= 0)
+                               {
+                               if (n < 0)
+                                       ret = n;
+                               break;
+                               }
+
                        if (msg.msg_controllen > 0)
                                {
                                for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
@@ -1074,13 +1128,6 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
                                        }
                                }
 
-                       if (n <= 0)
-                               {
-                               if (n < 0)
-                                       ret = n;
-                               break;
-                               }
-
                        if (msg.msg_flags & MSG_NOTIFICATION)
                                {
                                snp = (union sctp_notification*) out;
@@ -1194,11 +1241,11 @@ static int dgram_sctp_read(BIO *b, char *out, int outl)
 
                        optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
                        authchunks = OPENSSL_malloc(optlen);
-                       memset(authchunks, 0, sizeof(optlen));
+                       memset(authchunks, 0, optlen);
                        ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
                        OPENSSL_assert(ii >= 0);
 
-                       for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
+                       for (p = (unsigned char*) authchunks->gauth_chunks;
                                 p < (unsigned char*) authchunks + optlen;
                                 p += sizeof(uint8_t))
                                {
@@ -1334,7 +1381,7 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
        bio_dgram_sctp_data *data = NULL;
        socklen_t sockopt_len = 0;
        struct sctp_authkeyid authkeyid;
-       struct sctp_authkey *authkey;
+       struct sctp_authkey *authkey = NULL;
 
        data = (bio_dgram_sctp_data *)b->ptr;
 
@@ -1389,6 +1436,11 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
                /* Add new key */
                sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
                authkey = OPENSSL_malloc(sockopt_len);
+               if (authkey == NULL)
+                       {
+                       ret = -1;
+                       break;
+                       }
                memset(authkey, 0x00, sockopt_len);
                authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
 #ifndef __FreeBSD__
@@ -1400,6 +1452,8 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
                memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
 
                ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
+               OPENSSL_free(authkey);
+               authkey = NULL;
                if (ret < 0) break;
 
                /* Reset active key */
@@ -1848,11 +1902,19 @@ int BIO_dgram_non_fatal_error(int err)
 
 static void get_current_time(struct timeval *t)
        {
-#ifdef OPENSSL_SYS_WIN32
-       struct _timeb tb;
-       _ftime(&tb);
-       t->tv_sec = (long)tb.time;
-       t->tv_usec = (long)tb.millitm * 1000;
+#if defined(_WIN32)
+       SYSTEMTIME st;
+       union { unsigned __int64 ul; FILETIME ft; } now;
+
+       GetSystemTime(&st);
+       SystemTimeToFileTime(&st,&now.ft);
+#ifdef __MINGW32__
+       now.ul -= 116444736000000000ULL;
+#else
+       now.ul -= 116444736000000000UI64;       /* re-bias to 1/1/1970 */
+#endif
+       t->tv_sec  = (long)(now.ul/10000000);
+       t->tv_usec = ((int)(now.ul%10000000))/10;
 #elif defined(OPENSSL_SYS_VMS)
        struct timeb tb;
        ftime(&tb);