sendto is reportedly picky about destination socket address length.
[openssl.git] / crypto / bio / bss_dgram.c
index fa886af55785a782f1d7e06730828f54e1aee510..eb7e365467723ec83b2df2aa6197f87fbb831d44 100644 (file)
@@ -335,11 +335,21 @@ static int dgram_write(BIO *b, const char *in, int inl)
        if ( data->connected )
                ret=writesocket(b->num,in,inl);
        else
+               {
+               int peerlen = sizeof(data->peer);
+
+               if (data->peer.sa.sa_family == AF_INET)
+                       peerlen = sizeof(data->peer.sa_in);
+#if OPENSSL_USE_IVP6
+               else if (data->peer.sa.sa_family == AF_INET6)
+                       peerlen = sizeof(data->peer.sa_in6);
+#endif
 #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
-               ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, sizeof(data->peer));
+               ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen);
 #else
-               ret=sendto(b->num, in, inl, 0, &data->peer.sa, sizeof(data->peer));
+               ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
 #endif
+               }
 
        BIO_clear_retry_flags(b);
        if (ret <= 0)
@@ -371,7 +381,13 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 #endif
 #ifdef OPENSSL_SYS_LINUX
        socklen_t addr_len;
-       struct sockaddr_storage addr;
+       union   {
+               struct sockaddr sa;
+               struct sockaddr_in s4;
+#if OPENSSL_USE_IPV6
+               struct sockaddr_in6 s6;
+#endif
+               } addr;
 #endif
 
        data = (bio_dgram_data *)b->ptr;
@@ -446,15 +462,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                /* (Linux)kernel sets DF bit on outgoing IP packets */
        case BIO_CTRL_DGRAM_MTU_DISCOVER:
 #ifdef OPENSSL_SYS_LINUX
-               addr_len = (socklen_t)sizeof(struct sockaddr_storage);
-               memset((void *)&addr, 0, sizeof(struct sockaddr_storage));
-               if (getsockname(b->num, (void *)&addr, &addr_len) < 0)
+               addr_len = (socklen_t)sizeof(addr);
+               memset((void *)&addr, 0, sizeof(addr));
+               if (getsockname(b->num, &addr.sa, &addr_len) < 0)
                        {
                        ret = 0;
                        break;
                        }
                sockopt_len = sizeof(sockopt_val);
-               switch (addr.ss_family)
+               switch (addr.sa.sa_family)
                        {
                case AF_INET:
                        sockopt_val = IP_PMTUDISC_DO;
@@ -462,7 +478,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                                &sockopt_val, sizeof(sockopt_val))) < 0)
                                perror("setsockopt");
                        break;
-#if OPENSSL_USE_IPV6
+#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER)
                case AF_INET6:
                        sockopt_val = IPV6_PMTUDISC_DO;
                        if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
@@ -480,15 +496,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 #endif
        case BIO_CTRL_DGRAM_QUERY_MTU:
 #ifdef OPENSSL_SYS_LINUX
-               addr_len = (socklen_t)sizeof(struct sockaddr_storage);
-               memset((void *)&addr, 0, sizeof(struct sockaddr_storage));
-               if (getsockname(b->num, (void *)&addr, &addr_len) < 0)
+               addr_len = (socklen_t)sizeof(addr);
+               memset((void *)&addr, 0, sizeof(addr));
+               if (getsockname(b->num, &addr.sa, &addr_len) < 0)
                        {
                        ret = 0;
                        break;
                        }
                sockopt_len = sizeof(sockopt_val);
-               switch (addr.ss_family)
+               switch (addr.sa.sa_family)
                        {
                case AF_INET:
                        if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
@@ -505,7 +521,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
                                ret = data->mtu;
                                }
                        break;
-#if OPENSSL_USE_IPV6
+#if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
                case AF_INET6:
                        if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
                                &sockopt_len)) < 0 || sockopt_val < 0)