From: Andy Polyakov Date: Tue, 19 Jun 2012 12:28:47 +0000 (+0000) Subject: bss_dgram.c: add BIO_CTRL_DGRAM_SET_DONT_FRAG, fix bugs [from HEAD]. X-Git-Tag: OpenSSL_1_0_2-beta1~610 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=3e8b4b5055ec8214f566dcb6ea13bfc72248cb4b bss_dgram.c: add BIO_CTRL_DGRAM_SET_DONT_FRAG, fix bugs [from HEAD]. PR: 2830, 2833 --- diff --git a/crypto/bio/bio.h b/crypto/bio/bio.h index 05699ab212..d32bf7f7a2 100644 --- a/crypto/bio/bio.h +++ b/crypto/bio/bio.h @@ -174,6 +174,7 @@ extern "C" { #define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to * adjust socket timeouts */ +#define BIO_CTRL_DGRAM_SET_DONT_FRAG 48 #ifndef OPENSSL_NO_SCTP /* SCTP stuff */ diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 46cbe8a407..0d3c1cf342 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -77,11 +77,11 @@ #define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0 #endif -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU) #define IP_MTU 14 /* linux is lame */ #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED) /* Standard definition causes type-punning problems. */ #undef IN6_IS_ADDR_V4MAPPED #define s6_addr32 __u6_addr.__u6_addr32 @@ -265,7 +265,7 @@ static void dgram_adjust_rcv_timeout(BIO *b) { #if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; - int sz = sizeof(int); + union { size_t s; int i; } sz = {0}; /* Is a timer active? */ if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) @@ -275,6 +275,8 @@ static void dgram_adjust_rcv_timeout(BIO *b) /* Read current socket timeout */ #ifdef OPENSSL_SYS_WINDOWS int timeout; + + sz.i = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, &sz) < 0) { perror("getsockopt"); } @@ -284,9 +286,12 @@ static void dgram_adjust_rcv_timeout(BIO *b) data->socket_timeout.tv_usec = (timeout % 1000) * 1000; } #else + sz.i = sizeof(data->socket_timeout); if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), (void *)&sz) < 0) { perror("getsockopt"); } + else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) + OPENSSL_assert(sz.s<=sizeof(data->socket_timeout)); #endif /* Get current time */ @@ -455,11 +460,10 @@ 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(IP_MTU_DISCOVER) || defined(IP_MTU) - long sockopt_val = 0; - unsigned int sockopt_len = 0; -#endif -#ifdef OPENSSL_SYS_LINUX + 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; union { struct sockaddr sa; @@ -541,7 +545,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; /* (Linux)kernel sets DF bit on outgoing IP packets */ case BIO_CTRL_DGRAM_MTU_DISCOVER: -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) addr_len = (socklen_t)sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) @@ -549,7 +553,6 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; break; } - sockopt_len = sizeof(sockopt_val); switch (addr.sa.sa_family) { case AF_INET: @@ -558,7 +561,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 && defined(IPV6_MTU_DISCOVER) +#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) case AF_INET6: sockopt_val = IPV6_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, @@ -575,7 +578,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; #endif case BIO_CTRL_DGRAM_QUERY_MTU: -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU) addr_len = (socklen_t)sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) @@ -737,10 +740,13 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: -#ifdef OPENSSL_SYS_WINDOWS { - int timeout, sz = sizeof(timeout); + union { size_t s; int i; } sz = {0}; +#ifdef OPENSSL_SYS_WINDOWS + int timeout; struct timeval *tv = (struct timeval *)ptr; + + sz.i = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } @@ -750,12 +756,20 @@ 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_RCVTIMEO, - ptr, (void *)&ret) < 0) + ptr, (void *)&sz) < 0) { perror("getsockopt"); ret = -1; } + else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) + { + OPENSSL_assert(sz.s<=sizeof(struct timeval)); + ret = (int)sz.s; + } + else + ret = sz.i; #endif + } break; #endif #if defined(SO_SNDTIMEO) @@ -775,10 +789,13 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: -#ifdef OPENSSL_SYS_WINDOWS { - int timeout, sz = sizeof(timeout); + union { size_t s; int i; } sz = {0}; +#ifdef OPENSSL_SYS_WINDOWS + int timeout; struct timeval *tv = (struct timeval *)ptr; + + sz.i = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, (void*)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } @@ -790,10 +807,19 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) } } #else + sz.i = sizeof(struct timeval); if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - ptr, (void *)&ret) < 0) + ptr, (void *)&sz) < 0) { perror("getsockopt"); ret = -1; } + else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) + { + OPENSSL_assert(sz.s<=sizeof(struct timeval)); + ret = (int)sz.s; + } + else + ret = sz.i; #endif + } break; #endif case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: @@ -822,6 +848,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, + &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; @@ -965,7 +1035,6 @@ static int dgram_sctp_free(BIO *a) #ifdef SCTP_AUTHENTICATION_EVENT void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp) { - unsigned int sockopt_len = 0; int ret; struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event; @@ -975,9 +1044,8 @@ void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp) /* delete key */ authkeyid.scact_keynumber = authkeyevent->auth_keynumber; - sockopt_len = sizeof(struct sctp_authkeyid); ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, - &authkeyid, sockopt_len); + &authkeyid, sizeof(struct sctp_authkeyid)); } } #endif @@ -1308,7 +1376,7 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; bio_dgram_sctp_data *data = NULL; - unsigned int sockopt_len = 0; + socklen_t sockopt_len = 0; struct sctp_authkeyid authkeyid; struct sctp_authkey *authkey;