diff options
Diffstat (limited to 'src/lib/libcrypto/bio/bss_dgram.c')
-rw-r--r-- | src/lib/libcrypto/bio/bss_dgram.c | 380 |
1 files changed, 331 insertions, 49 deletions
diff --git a/src/lib/libcrypto/bio/bss_dgram.c b/src/lib/libcrypto/bio/bss_dgram.c index c3da6dc82f..eb7e365467 100644 --- a/src/lib/libcrypto/bio/bss_dgram.c +++ b/src/lib/libcrypto/bio/bss_dgram.c | |||
@@ -66,7 +66,13 @@ | |||
66 | 66 | ||
67 | #include <openssl/bio.h> | 67 | #include <openssl/bio.h> |
68 | 68 | ||
69 | #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) | ||
70 | #include <sys/timeb.h> | ||
71 | #endif | ||
72 | |||
73 | #ifdef OPENSSL_SYS_LINUX | ||
69 | #define IP_MTU 14 /* linux is lame */ | 74 | #define IP_MTU 14 /* linux is lame */ |
75 | #endif | ||
70 | 76 | ||
71 | #ifdef WATT32 | 77 | #ifdef WATT32 |
72 | #define sock_write SockWrite /* Watt-32 uses same names */ | 78 | #define sock_write SockWrite /* Watt-32 uses same names */ |
@@ -84,6 +90,8 @@ static int dgram_clear(BIO *bio); | |||
84 | 90 | ||
85 | static int BIO_dgram_should_retry(int s); | 91 | static int BIO_dgram_should_retry(int s); |
86 | 92 | ||
93 | static void get_current_time(struct timeval *t); | ||
94 | |||
87 | static BIO_METHOD methods_dgramp= | 95 | static BIO_METHOD methods_dgramp= |
88 | { | 96 | { |
89 | BIO_TYPE_DGRAM, | 97 | BIO_TYPE_DGRAM, |
@@ -100,10 +108,18 @@ static BIO_METHOD methods_dgramp= | |||
100 | 108 | ||
101 | typedef struct bio_dgram_data_st | 109 | typedef struct bio_dgram_data_st |
102 | { | 110 | { |
103 | struct sockaddr peer; | 111 | union { |
112 | struct sockaddr sa; | ||
113 | struct sockaddr_in sa_in; | ||
114 | #if OPENSSL_USE_IPV6 | ||
115 | struct sockaddr_in6 sa_in6; | ||
116 | #endif | ||
117 | } peer; | ||
104 | unsigned int connected; | 118 | unsigned int connected; |
105 | unsigned int _errno; | 119 | unsigned int _errno; |
106 | unsigned int mtu; | 120 | unsigned int mtu; |
121 | struct timeval next_timeout; | ||
122 | struct timeval socket_timeout; | ||
107 | } bio_dgram_data; | 123 | } bio_dgram_data; |
108 | 124 | ||
109 | BIO_METHOD *BIO_s_datagram(void) | 125 | BIO_METHOD *BIO_s_datagram(void) |
@@ -165,31 +181,140 @@ static int dgram_clear(BIO *a) | |||
165 | } | 181 | } |
166 | return(1); | 182 | return(1); |
167 | } | 183 | } |
168 | 184 | ||
185 | static void dgram_adjust_rcv_timeout(BIO *b) | ||
186 | { | ||
187 | #if defined(SO_RCVTIMEO) | ||
188 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; | ||
189 | int sz = sizeof(int); | ||
190 | |||
191 | /* Is a timer active? */ | ||
192 | if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) | ||
193 | { | ||
194 | struct timeval timenow, timeleft; | ||
195 | |||
196 | /* Read current socket timeout */ | ||
197 | #ifdef OPENSSL_SYS_WINDOWS | ||
198 | int timeout; | ||
199 | if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, | ||
200 | (void*)&timeout, &sz) < 0) | ||
201 | { perror("getsockopt"); } | ||
202 | else | ||
203 | { | ||
204 | data->socket_timeout.tv_sec = timeout / 1000; | ||
205 | data->socket_timeout.tv_usec = (timeout % 1000) * 1000; | ||
206 | } | ||
207 | #else | ||
208 | if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, | ||
209 | &(data->socket_timeout), (void *)&sz) < 0) | ||
210 | { perror("getsockopt"); } | ||
211 | #endif | ||
212 | |||
213 | /* Get current time */ | ||
214 | get_current_time(&timenow); | ||
215 | |||
216 | /* Calculate time left until timer expires */ | ||
217 | memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); | ||
218 | timeleft.tv_sec -= timenow.tv_sec; | ||
219 | timeleft.tv_usec -= timenow.tv_usec; | ||
220 | if (timeleft.tv_usec < 0) | ||
221 | { | ||
222 | timeleft.tv_sec--; | ||
223 | timeleft.tv_usec += 1000000; | ||
224 | } | ||
225 | |||
226 | if (timeleft.tv_sec < 0) | ||
227 | { | ||
228 | timeleft.tv_sec = 0; | ||
229 | timeleft.tv_usec = 1; | ||
230 | } | ||
231 | |||
232 | /* Adjust socket timeout if next handhake message timer | ||
233 | * will expire earlier. | ||
234 | */ | ||
235 | if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) || | ||
236 | (data->socket_timeout.tv_sec > timeleft.tv_sec) || | ||
237 | (data->socket_timeout.tv_sec == timeleft.tv_sec && | ||
238 | data->socket_timeout.tv_usec >= timeleft.tv_usec)) | ||
239 | { | ||
240 | #ifdef OPENSSL_SYS_WINDOWS | ||
241 | timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; | ||
242 | if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, | ||
243 | (void*)&timeout, sizeof(timeout)) < 0) | ||
244 | { perror("setsockopt"); } | ||
245 | #else | ||
246 | if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft, | ||
247 | sizeof(struct timeval)) < 0) | ||
248 | { perror("setsockopt"); } | ||
249 | #endif | ||
250 | } | ||
251 | } | ||
252 | #endif | ||
253 | } | ||
254 | |||
255 | static void dgram_reset_rcv_timeout(BIO *b) | ||
256 | { | ||
257 | #if defined(SO_RCVTIMEO) | ||
258 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; | ||
259 | |||
260 | /* Is a timer active? */ | ||
261 | if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) | ||
262 | { | ||
263 | #ifdef OPENSSL_SYS_WINDOWS | ||
264 | int timeout = data->socket_timeout.tv_sec * 1000 + | ||
265 | data->socket_timeout.tv_usec / 1000; | ||
266 | if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, | ||
267 | (void*)&timeout, sizeof(timeout)) < 0) | ||
268 | { perror("setsockopt"); } | ||
269 | #else | ||
270 | if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), | ||
271 | sizeof(struct timeval)) < 0) | ||
272 | { perror("setsockopt"); } | ||
273 | #endif | ||
274 | } | ||
275 | #endif | ||
276 | } | ||
277 | |||
169 | static int dgram_read(BIO *b, char *out, int outl) | 278 | static int dgram_read(BIO *b, char *out, int outl) |
170 | { | 279 | { |
171 | int ret=0; | 280 | int ret=0; |
172 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; | 281 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; |
173 | 282 | ||
174 | struct sockaddr peer; | 283 | struct { |
175 | int peerlen = sizeof(peer); | 284 | /* |
285 | * See commentary in b_sock.c. <appro> | ||
286 | */ | ||
287 | union { size_t s; int i; } len; | ||
288 | union { | ||
289 | struct sockaddr sa; | ||
290 | struct sockaddr_in sa_in; | ||
291 | #if OPENSSL_USE_IPV6 | ||
292 | struct sockaddr_in6 sa_in6; | ||
293 | #endif | ||
294 | } peer; | ||
295 | } sa; | ||
296 | |||
297 | sa.len.s=0; | ||
298 | sa.len.i=sizeof(sa.peer); | ||
176 | 299 | ||
177 | if (out != NULL) | 300 | if (out != NULL) |
178 | { | 301 | { |
179 | clear_socket_error(); | 302 | clear_socket_error(); |
180 | memset(&peer, 0x00, peerlen); | 303 | memset(&sa.peer, 0x00, sizeof(sa.peer)); |
181 | /* Last arg in recvfrom is signed on some platforms and | 304 | dgram_adjust_rcv_timeout(b); |
182 | * unsigned on others. It is of type socklen_t on some | 305 | ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len); |
183 | * but this is not universal. Cast to (void *) to avoid | 306 | if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) |
184 | * compiler warnings. | 307 | { |
185 | */ | 308 | OPENSSL_assert(sa.len.s<=sizeof(sa.peer)); |
186 | ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen); | 309 | sa.len.i = (int)sa.len.s; |
310 | } | ||
311 | dgram_reset_rcv_timeout(b); | ||
187 | 312 | ||
188 | if ( ! data->connected && ret > 0) | 313 | if ( ! data->connected && ret >= 0) |
189 | BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer); | 314 | BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer); |
190 | 315 | ||
191 | BIO_clear_retry_flags(b); | 316 | BIO_clear_retry_flags(b); |
192 | if (ret <= 0) | 317 | if (ret < 0) |
193 | { | 318 | { |
194 | if (BIO_dgram_should_retry(ret)) | 319 | if (BIO_dgram_should_retry(ret)) |
195 | { | 320 | { |
@@ -207,19 +332,29 @@ static int dgram_write(BIO *b, const char *in, int inl) | |||
207 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; | 332 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; |
208 | clear_socket_error(); | 333 | clear_socket_error(); |
209 | 334 | ||
210 | if ( data->connected ) | 335 | if ( data->connected ) |
211 | ret=writesocket(b->num,in,inl); | 336 | ret=writesocket(b->num,in,inl); |
212 | else | 337 | else |
338 | { | ||
339 | int peerlen = sizeof(data->peer); | ||
340 | |||
341 | if (data->peer.sa.sa_family == AF_INET) | ||
342 | peerlen = sizeof(data->peer.sa_in); | ||
343 | #if OPENSSL_USE_IVP6 | ||
344 | else if (data->peer.sa.sa_family == AF_INET6) | ||
345 | peerlen = sizeof(data->peer.sa_in6); | ||
346 | #endif | ||
213 | #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) | 347 | #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) |
214 | ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer)); | 348 | ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen); |
215 | #else | 349 | #else |
216 | ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer)); | 350 | ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen); |
217 | #endif | 351 | #endif |
352 | } | ||
218 | 353 | ||
219 | BIO_clear_retry_flags(b); | 354 | BIO_clear_retry_flags(b); |
220 | if (ret <= 0) | 355 | if (ret <= 0) |
221 | { | 356 | { |
222 | if (BIO_sock_should_retry(ret)) | 357 | if (BIO_dgram_should_retry(ret)) |
223 | { | 358 | { |
224 | BIO_set_retry_write(b); | 359 | BIO_set_retry_write(b); |
225 | data->_errno = get_last_socket_error(); | 360 | data->_errno = get_last_socket_error(); |
@@ -240,8 +375,20 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
240 | int *ip; | 375 | int *ip; |
241 | struct sockaddr *to = NULL; | 376 | struct sockaddr *to = NULL; |
242 | bio_dgram_data *data = NULL; | 377 | bio_dgram_data *data = NULL; |
378 | #if defined(IP_MTU_DISCOVER) || defined(IP_MTU) | ||
243 | long sockopt_val = 0; | 379 | long sockopt_val = 0; |
244 | unsigned int sockopt_len = 0; | 380 | unsigned int sockopt_len = 0; |
381 | #endif | ||
382 | #ifdef OPENSSL_SYS_LINUX | ||
383 | socklen_t addr_len; | ||
384 | union { | ||
385 | struct sockaddr sa; | ||
386 | struct sockaddr_in s4; | ||
387 | #if OPENSSL_USE_IPV6 | ||
388 | struct sockaddr_in6 s6; | ||
389 | #endif | ||
390 | } addr; | ||
391 | #endif | ||
245 | 392 | ||
246 | data = (bio_dgram_data *)b->ptr; | 393 | data = (bio_dgram_data *)b->ptr; |
247 | 394 | ||
@@ -294,30 +441,110 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
294 | else | 441 | else |
295 | { | 442 | { |
296 | #endif | 443 | #endif |
297 | memcpy(&(data->peer),to, sizeof(struct sockaddr)); | 444 | switch (to->sa_family) |
445 | { | ||
446 | case AF_INET: | ||
447 | memcpy(&data->peer,to,sizeof(data->peer.sa_in)); | ||
448 | break; | ||
449 | #if OPENSSL_USE_IPV6 | ||
450 | case AF_INET6: | ||
451 | memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); | ||
452 | break; | ||
453 | #endif | ||
454 | default: | ||
455 | memcpy(&data->peer,to,sizeof(data->peer.sa)); | ||
456 | break; | ||
457 | } | ||
298 | #if 0 | 458 | #if 0 |
299 | } | 459 | } |
300 | #endif | 460 | #endif |
301 | break; | 461 | break; |
302 | /* (Linux)kernel sets DF bit on outgoing IP packets */ | 462 | /* (Linux)kernel sets DF bit on outgoing IP packets */ |
303 | #ifdef IP_MTU_DISCOVER | ||
304 | case BIO_CTRL_DGRAM_MTU_DISCOVER: | 463 | case BIO_CTRL_DGRAM_MTU_DISCOVER: |
305 | sockopt_val = IP_PMTUDISC_DO; | 464 | #ifdef OPENSSL_SYS_LINUX |
306 | if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, | 465 | addr_len = (socklen_t)sizeof(addr); |
307 | &sockopt_val, sizeof(sockopt_val))) < 0) | 466 | memset((void *)&addr, 0, sizeof(addr)); |
308 | perror("setsockopt"); | 467 | if (getsockname(b->num, &addr.sa, &addr_len) < 0) |
468 | { | ||
469 | ret = 0; | ||
470 | break; | ||
471 | } | ||
472 | sockopt_len = sizeof(sockopt_val); | ||
473 | switch (addr.sa.sa_family) | ||
474 | { | ||
475 | case AF_INET: | ||
476 | sockopt_val = IP_PMTUDISC_DO; | ||
477 | if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, | ||
478 | &sockopt_val, sizeof(sockopt_val))) < 0) | ||
479 | perror("setsockopt"); | ||
480 | break; | ||
481 | #if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) | ||
482 | case AF_INET6: | ||
483 | sockopt_val = IPV6_PMTUDISC_DO; | ||
484 | if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, | ||
485 | &sockopt_val, sizeof(sockopt_val))) < 0) | ||
486 | perror("setsockopt"); | ||
487 | break; | ||
488 | #endif | ||
489 | default: | ||
490 | ret = -1; | ||
491 | break; | ||
492 | } | ||
493 | ret = -1; | ||
494 | #else | ||
309 | break; | 495 | break; |
310 | #endif | 496 | #endif |
311 | case BIO_CTRL_DGRAM_QUERY_MTU: | 497 | case BIO_CTRL_DGRAM_QUERY_MTU: |
312 | sockopt_len = sizeof(sockopt_val); | 498 | #ifdef OPENSSL_SYS_LINUX |
313 | if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, | 499 | addr_len = (socklen_t)sizeof(addr); |
314 | &sockopt_len)) < 0 || sockopt_val < 0) | 500 | memset((void *)&addr, 0, sizeof(addr)); |
315 | { ret = 0; } | 501 | if (getsockname(b->num, &addr.sa, &addr_len) < 0) |
316 | else | 502 | { |
503 | ret = 0; | ||
504 | break; | ||
505 | } | ||
506 | sockopt_len = sizeof(sockopt_val); | ||
507 | switch (addr.sa.sa_family) | ||
317 | { | 508 | { |
318 | data->mtu = sockopt_val; | 509 | case AF_INET: |
319 | ret = data->mtu; | 510 | if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, |
511 | &sockopt_len)) < 0 || sockopt_val < 0) | ||
512 | { | ||
513 | ret = 0; | ||
514 | } | ||
515 | else | ||
516 | { | ||
517 | /* we assume that the transport protocol is UDP and no | ||
518 | * IP options are used. | ||
519 | */ | ||
520 | data->mtu = sockopt_val - 8 - 20; | ||
521 | ret = data->mtu; | ||
522 | } | ||
523 | break; | ||
524 | #if OPENSSL_USE_IPV6 && defined(IPV6_MTU) | ||
525 | case AF_INET6: | ||
526 | if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val, | ||
527 | &sockopt_len)) < 0 || sockopt_val < 0) | ||
528 | { | ||
529 | ret = 0; | ||
530 | } | ||
531 | else | ||
532 | { | ||
533 | /* we assume that the transport protocol is UDP and no | ||
534 | * IPV6 options are used. | ||
535 | */ | ||
536 | data->mtu = sockopt_val - 8 - 40; | ||
537 | ret = data->mtu; | ||
538 | } | ||
539 | break; | ||
540 | #endif | ||
541 | default: | ||
542 | ret = 0; | ||
543 | break; | ||
320 | } | 544 | } |
545 | #else | ||
546 | ret = 0; | ||
547 | #endif | ||
321 | break; | 548 | break; |
322 | case BIO_CTRL_DGRAM_GET_MTU: | 549 | case BIO_CTRL_DGRAM_GET_MTU: |
323 | return data->mtu; | 550 | return data->mtu; |
@@ -332,19 +559,66 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
332 | if ( to != NULL) | 559 | if ( to != NULL) |
333 | { | 560 | { |
334 | data->connected = 1; | 561 | data->connected = 1; |
335 | memcpy(&(data->peer),to, sizeof(struct sockaddr)); | 562 | switch (to->sa_family) |
563 | { | ||
564 | case AF_INET: | ||
565 | memcpy(&data->peer,to,sizeof(data->peer.sa_in)); | ||
566 | break; | ||
567 | #if OPENSSL_USE_IPV6 | ||
568 | case AF_INET6: | ||
569 | memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); | ||
570 | break; | ||
571 | #endif | ||
572 | default: | ||
573 | memcpy(&data->peer,to,sizeof(data->peer.sa)); | ||
574 | break; | ||
575 | } | ||
336 | } | 576 | } |
337 | else | 577 | else |
338 | { | 578 | { |
339 | data->connected = 0; | 579 | data->connected = 0; |
340 | memset(&(data->peer), 0x00, sizeof(struct sockaddr)); | 580 | memset(&(data->peer), 0x00, sizeof(data->peer)); |
341 | } | 581 | } |
342 | break; | 582 | break; |
343 | case BIO_CTRL_DGRAM_SET_PEER: | 583 | case BIO_CTRL_DGRAM_GET_PEER: |
344 | to = (struct sockaddr *) ptr; | 584 | switch (data->peer.sa.sa_family) |
345 | 585 | { | |
346 | memcpy(&(data->peer), to, sizeof(struct sockaddr)); | 586 | case AF_INET: |
347 | break; | 587 | ret=sizeof(data->peer.sa_in); |
588 | break; | ||
589 | #if OPENSSL_USE_IPV6 | ||
590 | case AF_INET6: | ||
591 | ret=sizeof(data->peer.sa_in6); | ||
592 | break; | ||
593 | #endif | ||
594 | default: | ||
595 | ret=sizeof(data->peer.sa); | ||
596 | break; | ||
597 | } | ||
598 | if (num==0 || num>ret) | ||
599 | num=ret; | ||
600 | memcpy(ptr,&data->peer,(ret=num)); | ||
601 | break; | ||
602 | case BIO_CTRL_DGRAM_SET_PEER: | ||
603 | to = (struct sockaddr *) ptr; | ||
604 | switch (to->sa_family) | ||
605 | { | ||
606 | case AF_INET: | ||
607 | memcpy(&data->peer,to,sizeof(data->peer.sa_in)); | ||
608 | break; | ||
609 | #if OPENSSL_USE_IPV6 | ||
610 | case AF_INET6: | ||
611 | memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); | ||
612 | break; | ||
613 | #endif | ||
614 | default: | ||
615 | memcpy(&data->peer,to,sizeof(data->peer.sa)); | ||
616 | break; | ||
617 | } | ||
618 | break; | ||
619 | case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: | ||
620 | memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); | ||
621 | break; | ||
348 | #if defined(SO_RCVTIMEO) | 622 | #if defined(SO_RCVTIMEO) |
349 | case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: | 623 | case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: |
350 | #ifdef OPENSSL_SYS_WINDOWS | 624 | #ifdef OPENSSL_SYS_WINDOWS |
@@ -507,10 +781,6 @@ int BIO_dgram_non_fatal_error(int err) | |||
507 | # endif | 781 | # endif |
508 | #endif | 782 | #endif |
509 | 783 | ||
510 | #if defined(ENOTCONN) | ||
511 | case ENOTCONN: | ||
512 | #endif | ||
513 | |||
514 | #ifdef EINTR | 784 | #ifdef EINTR |
515 | case EINTR: | 785 | case EINTR: |
516 | #endif | 786 | #endif |
@@ -533,11 +803,6 @@ int BIO_dgram_non_fatal_error(int err) | |||
533 | case EALREADY: | 803 | case EALREADY: |
534 | #endif | 804 | #endif |
535 | 805 | ||
536 | /* DF bit set, and packet larger than MTU */ | ||
537 | #ifdef EMSGSIZE | ||
538 | case EMSGSIZE: | ||
539 | #endif | ||
540 | |||
541 | return(1); | 806 | return(1); |
542 | /* break; */ | 807 | /* break; */ |
543 | default: | 808 | default: |
@@ -546,3 +811,20 @@ int BIO_dgram_non_fatal_error(int err) | |||
546 | return(0); | 811 | return(0); |
547 | } | 812 | } |
548 | #endif | 813 | #endif |
814 | |||
815 | static void get_current_time(struct timeval *t) | ||
816 | { | ||
817 | #ifdef OPENSSL_SYS_WIN32 | ||
818 | struct _timeb tb; | ||
819 | _ftime(&tb); | ||
820 | t->tv_sec = (long)tb.time; | ||
821 | t->tv_usec = (long)tb.millitm * 1000; | ||
822 | #elif defined(OPENSSL_SYS_VMS) | ||
823 | struct timeb tb; | ||
824 | ftime(&tb); | ||
825 | t->tv_sec = (long)tb.time; | ||
826 | t->tv_usec = (long)tb.millitm * 1000; | ||
827 | #else | ||
828 | gettimeofday(t, NULL); | ||
829 | #endif | ||
830 | } | ||