]>
Commit | Line | Data |
---|---|---|
36d16f8e BL |
1 | /* crypto/bio/bio_dgram.c */ |
2 | /* | |
3 | * DTLS implementation written by Nagendra Modadugu | |
4 | * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. | |
5 | */ | |
6 | /* ==================================================================== | |
7 | * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. | |
8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * | |
13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in | |
18 | * the documentation and/or other materials provided with the | |
19 | * distribution. | |
20 | * | |
21 | * 3. All advertising materials mentioning features or use of this | |
22 | * software must display the following acknowledgment: | |
23 | * "This product includes software developed by the OpenSSL Project | |
24 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
25 | * | |
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
27 | * endorse or promote products derived from this software without | |
28 | * prior written permission. For written permission, please contact | |
29 | * openssl-core@OpenSSL.org. | |
30 | * | |
31 | * 5. Products derived from this software may not be called "OpenSSL" | |
32 | * nor may "OpenSSL" appear in their names without prior written | |
33 | * permission of the OpenSSL Project. | |
34 | * | |
35 | * 6. Redistributions of any form whatsoever must retain the following | |
36 | * acknowledgment: | |
37 | * "This product includes software developed by the OpenSSL Project | |
38 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
39 | * | |
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
52 | * ==================================================================== | |
53 | * | |
54 | * This product includes cryptographic software written by Eric Young | |
55 | * (eay@cryptsoft.com). This product includes software written by Tim | |
56 | * Hudson (tjh@cryptsoft.com). | |
57 | * | |
58 | */ | |
59 | ||
60 | #ifndef OPENSSL_NO_DGRAM | |
61 | ||
62 | #include <stdio.h> | |
63 | #include <errno.h> | |
64 | #define USE_SOCKETS | |
65 | #include "cryptlib.h" | |
66 | ||
36d16f8e BL |
67 | #include <openssl/bio.h> |
68 | ||
3c3f98dc | 69 | #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) |
e5fa864f DSH |
70 | #include <sys/timeb.h> |
71 | #endif | |
72 | ||
36d16f8e BL |
73 | #define IP_MTU 14 /* linux is lame */ |
74 | ||
75 | #ifdef WATT32 | |
76 | #define sock_write SockWrite /* Watt-32 uses same names */ | |
77 | #define sock_read SockRead | |
78 | #define sock_puts SockPuts | |
79 | #endif | |
80 | ||
81 | static int dgram_write(BIO *h, const char *buf, int num); | |
82 | static int dgram_read(BIO *h, char *buf, int size); | |
83 | static int dgram_puts(BIO *h, const char *str); | |
84 | static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2); | |
85 | static int dgram_new(BIO *h); | |
86 | static int dgram_free(BIO *data); | |
87 | static int dgram_clear(BIO *bio); | |
88 | ||
b3e72fc3 | 89 | static int BIO_dgram_should_retry(int s); |
36d16f8e | 90 | |
5d6a0179 RL |
91 | static void get_current_time(struct timeval *t); |
92 | ||
36d16f8e BL |
93 | static BIO_METHOD methods_dgramp= |
94 | { | |
95 | BIO_TYPE_DGRAM, | |
96 | "datagram socket", | |
97 | dgram_write, | |
98 | dgram_read, | |
99 | dgram_puts, | |
100 | NULL, /* dgram_gets, */ | |
101 | dgram_ctrl, | |
102 | dgram_new, | |
103 | dgram_free, | |
104 | NULL, | |
105 | }; | |
106 | ||
107 | typedef struct bio_dgram_data_st | |
108 | { | |
109 | struct sockaddr peer; | |
110 | unsigned int connected; | |
111 | unsigned int _errno; | |
112 | unsigned int mtu; | |
e5fa864f DSH |
113 | struct timeval hstimeoutdiff; |
114 | struct timeval hstimeout; | |
36d16f8e BL |
115 | } bio_dgram_data; |
116 | ||
117 | BIO_METHOD *BIO_s_datagram(void) | |
118 | { | |
119 | return(&methods_dgramp); | |
120 | } | |
121 | ||
122 | BIO *BIO_new_dgram(int fd, int close_flag) | |
123 | { | |
124 | BIO *ret; | |
125 | ||
126 | ret=BIO_new(BIO_s_datagram()); | |
127 | if (ret == NULL) return(NULL); | |
128 | BIO_set_fd(ret,fd,close_flag); | |
129 | return(ret); | |
130 | } | |
131 | ||
132 | static int dgram_new(BIO *bi) | |
133 | { | |
134 | bio_dgram_data *data = NULL; | |
135 | ||
136 | bi->init=0; | |
137 | bi->num=0; | |
138 | data = OPENSSL_malloc(sizeof(bio_dgram_data)); | |
139 | if (data == NULL) | |
140 | return 0; | |
141 | memset(data, 0x00, sizeof(bio_dgram_data)); | |
142 | bi->ptr = data; | |
143 | ||
144 | bi->flags=0; | |
145 | return(1); | |
146 | } | |
147 | ||
148 | static int dgram_free(BIO *a) | |
149 | { | |
150 | bio_dgram_data *data; | |
151 | ||
152 | if (a == NULL) return(0); | |
153 | if ( ! dgram_clear(a)) | |
154 | return 0; | |
155 | ||
156 | data = (bio_dgram_data *)a->ptr; | |
157 | if(data != NULL) OPENSSL_free(data); | |
158 | ||
159 | return(1); | |
160 | } | |
161 | ||
162 | static int dgram_clear(BIO *a) | |
163 | { | |
164 | if (a == NULL) return(0); | |
165 | if (a->shutdown) | |
166 | { | |
167 | if (a->init) | |
168 | { | |
169 | SHUTDOWN2(a->num); | |
170 | } | |
171 | a->init=0; | |
172 | a->flags=0; | |
173 | } | |
174 | return(1); | |
175 | } | |
176 | ||
177 | static int dgram_read(BIO *b, char *out, int outl) | |
178 | { | |
179 | int ret=0; | |
180 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; | |
181 | ||
182 | struct sockaddr peer; | |
6c61726b | 183 | int peerlen = sizeof(peer); |
36d16f8e BL |
184 | |
185 | if (out != NULL) | |
186 | { | |
187 | clear_socket_error(); | |
188 | memset(&peer, 0x00, peerlen); | |
6c61726b DSH |
189 | /* Last arg in recvfrom is signed on some platforms and |
190 | * unsigned on others. It is of type socklen_t on some | |
191 | * but this is not universal. Cast to (void *) to avoid | |
192 | * compiler warnings. | |
193 | */ | |
194 | ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen); | |
36d16f8e BL |
195 | |
196 | if ( ! data->connected && ret > 0) | |
197 | BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer); | |
198 | ||
199 | BIO_clear_retry_flags(b); | |
200 | if (ret <= 0) | |
201 | { | |
202 | if (BIO_dgram_should_retry(ret)) | |
203 | { | |
204 | BIO_set_retry_read(b); | |
205 | data->_errno = get_last_socket_error(); | |
206 | } | |
e5fa864f DSH |
207 | memset(&(data->hstimeout), 0, sizeof(struct timeval)); |
208 | } | |
209 | else | |
210 | { | |
211 | if (data->hstimeout.tv_sec > 0 || data->hstimeout.tv_usec > 0) | |
212 | { | |
213 | struct timeval curtime; | |
5d6a0179 | 214 | get_current_time(&curtime); |
e5fa864f DSH |
215 | |
216 | if (curtime.tv_sec >= data->hstimeout.tv_sec && | |
217 | curtime.tv_usec >= data->hstimeout.tv_usec) | |
218 | { | |
219 | data->_errno = EAGAIN; | |
220 | ret = -1; | |
221 | memset(&(data->hstimeout), 0, sizeof(struct timeval)); | |
222 | } | |
223 | } | |
36d16f8e BL |
224 | } |
225 | } | |
226 | return(ret); | |
227 | } | |
228 | ||
229 | static int dgram_write(BIO *b, const char *in, int inl) | |
230 | { | |
231 | int ret; | |
232 | bio_dgram_data *data = (bio_dgram_data *)b->ptr; | |
233 | clear_socket_error(); | |
234 | ||
235 | if ( data->connected ) | |
eef0c1f3 | 236 | ret=writesocket(b->num,in,inl); |
36d16f8e | 237 | else |
eef0c1f3 DSH |
238 | #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) |
239 | ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer)); | |
240 | #else | |
36d16f8e | 241 | ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer)); |
eef0c1f3 | 242 | #endif |
36d16f8e BL |
243 | |
244 | BIO_clear_retry_flags(b); | |
245 | if (ret <= 0) | |
246 | { | |
247 | if (BIO_sock_should_retry(ret)) | |
248 | { | |
249 | BIO_set_retry_write(b); | |
250 | data->_errno = get_last_socket_error(); | |
251 | ||
252 | #if 0 /* higher layers are responsible for querying MTU, if necessary */ | |
253 | if ( data->_errno == EMSGSIZE) | |
254 | /* retrieve the new MTU */ | |
255 | BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); | |
256 | #endif | |
257 | } | |
258 | } | |
259 | return(ret); | |
260 | } | |
261 | ||
262 | static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) | |
263 | { | |
264 | long ret=1; | |
265 | int *ip; | |
266 | struct sockaddr *to = NULL; | |
267 | bio_dgram_data *data = NULL; | |
268 | long sockopt_val = 0; | |
269 | unsigned int sockopt_len = 0; | |
270 | ||
271 | data = (bio_dgram_data *)b->ptr; | |
272 | ||
273 | switch (cmd) | |
274 | { | |
275 | case BIO_CTRL_RESET: | |
276 | num=0; | |
277 | case BIO_C_FILE_SEEK: | |
278 | ret=0; | |
279 | break; | |
280 | case BIO_C_FILE_TELL: | |
281 | case BIO_CTRL_INFO: | |
282 | ret=0; | |
283 | break; | |
284 | case BIO_C_SET_FD: | |
285 | dgram_clear(b); | |
286 | b->num= *((int *)ptr); | |
287 | b->shutdown=(int)num; | |
288 | b->init=1; | |
289 | break; | |
290 | case BIO_C_GET_FD: | |
291 | if (b->init) | |
292 | { | |
293 | ip=(int *)ptr; | |
294 | if (ip != NULL) *ip=b->num; | |
295 | ret=b->num; | |
296 | } | |
297 | else | |
298 | ret= -1; | |
299 | break; | |
300 | case BIO_CTRL_GET_CLOSE: | |
301 | ret=b->shutdown; | |
302 | break; | |
303 | case BIO_CTRL_SET_CLOSE: | |
304 | b->shutdown=(int)num; | |
305 | break; | |
306 | case BIO_CTRL_PENDING: | |
307 | case BIO_CTRL_WPENDING: | |
308 | ret=0; | |
309 | break; | |
310 | case BIO_CTRL_DUP: | |
311 | case BIO_CTRL_FLUSH: | |
312 | ret=1; | |
313 | break; | |
314 | case BIO_CTRL_DGRAM_CONNECT: | |
315 | to = (struct sockaddr *)ptr; | |
316 | #if 0 | |
317 | if (connect(b->num, to, sizeof(struct sockaddr)) < 0) | |
318 | { perror("connect"); ret = 0; } | |
319 | else | |
320 | { | |
321 | #endif | |
322 | memcpy(&(data->peer),to, sizeof(struct sockaddr)); | |
323 | #if 0 | |
324 | } | |
325 | #endif | |
326 | break; | |
327 | /* (Linux)kernel sets DF bit on outgoing IP packets */ | |
328 | #ifdef IP_MTU_DISCOVER | |
329 | case BIO_CTRL_DGRAM_MTU_DISCOVER: | |
330 | sockopt_val = IP_PMTUDISC_DO; | |
331 | if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, | |
332 | &sockopt_val, sizeof(sockopt_val))) < 0) | |
333 | perror("setsockopt"); | |
334 | break; | |
335 | #endif | |
336 | case BIO_CTRL_DGRAM_QUERY_MTU: | |
337 | sockopt_len = sizeof(sockopt_val); | |
6c61726b | 338 | if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, |
36d16f8e BL |
339 | &sockopt_len)) < 0 || sockopt_val < 0) |
340 | { ret = 0; } | |
341 | else | |
342 | { | |
343 | data->mtu = sockopt_val; | |
344 | ret = data->mtu; | |
345 | } | |
346 | break; | |
347 | case BIO_CTRL_DGRAM_GET_MTU: | |
348 | return data->mtu; | |
349 | break; | |
350 | case BIO_CTRL_DGRAM_SET_MTU: | |
351 | data->mtu = num; | |
352 | ret = num; | |
353 | break; | |
354 | case BIO_CTRL_DGRAM_SET_CONNECTED: | |
355 | to = (struct sockaddr *)ptr; | |
356 | ||
357 | if ( to != NULL) | |
358 | { | |
359 | data->connected = 1; | |
360 | memcpy(&(data->peer),to, sizeof(struct sockaddr)); | |
361 | } | |
362 | else | |
363 | { | |
364 | data->connected = 0; | |
365 | memset(&(data->peer), 0x00, sizeof(struct sockaddr)); | |
366 | } | |
367 | break; | |
368 | case BIO_CTRL_DGRAM_SET_PEER: | |
369 | to = (struct sockaddr *) ptr; | |
370 | ||
371 | memcpy(&(data->peer), to, sizeof(struct sockaddr)); | |
372 | break; | |
e5fa864f DSH |
373 | case BIO_CTRL_DGRAM_SET_TIMEOUT: |
374 | if (num > 0) | |
375 | { | |
5d6a0179 | 376 | get_current_time(&data->hstimeout); |
e5fa864f DSH |
377 | data->hstimeout.tv_sec += data->hstimeoutdiff.tv_sec; |
378 | data->hstimeout.tv_usec += data->hstimeoutdiff.tv_usec; | |
379 | if (data->hstimeout.tv_usec >= 1000000) | |
380 | { | |
381 | data->hstimeout.tv_sec++; | |
382 | data->hstimeout.tv_usec -= 1000000; | |
383 | } | |
384 | } | |
385 | else | |
386 | { | |
387 | memset(&(data->hstimeout), 0, sizeof(struct timeval)); | |
388 | } | |
389 | break; | |
4700aea9 | 390 | #if defined(SO_RCVTIMEO) |
36d16f8e | 391 | case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: |
b9790c1c AP |
392 | #ifdef OPENSSL_SYS_WINDOWS |
393 | { | |
394 | struct timeval *tv = (struct timeval *)ptr; | |
395 | int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; | |
d7235a9d | 396 | if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, |
b9790c1c AP |
397 | (void*)&timeout, sizeof(timeout)) < 0) |
398 | { perror("setsockopt"); ret = -1; } | |
399 | } | |
400 | #else | |
36d16f8e BL |
401 | if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, |
402 | sizeof(struct timeval)) < 0) | |
403 | { perror("setsockopt"); ret = -1; } | |
b9790c1c | 404 | #endif |
e5fa864f | 405 | memcpy(&(data->hstimeoutdiff), ptr, sizeof(struct timeval)); |
36d16f8e BL |
406 | break; |
407 | case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: | |
b9790c1c AP |
408 | #ifdef OPENSSL_SYS_WINDOWS |
409 | { | |
410 | int timeout, sz = sizeof(timeout); | |
411 | struct timeval *tv = (struct timeval *)ptr; | |
d7235a9d AP |
412 | if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, |
413 | (void*)&timeout, &sz) < 0) | |
b9790c1c AP |
414 | { perror("getsockopt"); ret = -1; } |
415 | else | |
416 | { | |
417 | tv->tv_sec = timeout / 1000; | |
418 | tv->tv_usec = (timeout % 1000) * 1000; | |
419 | ret = sizeof(*tv); | |
420 | } | |
421 | } | |
422 | #else | |
36d16f8e | 423 | if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, |
6c61726b | 424 | ptr, (void *)&ret) < 0) |
36d16f8e | 425 | { perror("getsockopt"); ret = -1; } |
b9790c1c | 426 | #endif |
36d16f8e | 427 | break; |
4700aea9 UM |
428 | #endif |
429 | #if defined(SO_SNDTIMEO) | |
36d16f8e | 430 | case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: |
b9790c1c AP |
431 | #ifdef OPENSSL_SYS_WINDOWS |
432 | { | |
433 | struct timeval *tv = (struct timeval *)ptr; | |
434 | int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; | |
d7235a9d | 435 | if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, |
b9790c1c AP |
436 | (void*)&timeout, sizeof(timeout)) < 0) |
437 | { perror("setsockopt"); ret = -1; } | |
438 | } | |
439 | #else | |
36d16f8e BL |
440 | if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, |
441 | sizeof(struct timeval)) < 0) | |
442 | { perror("setsockopt"); ret = -1; } | |
b9790c1c | 443 | #endif |
36d16f8e BL |
444 | break; |
445 | case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: | |
b9790c1c AP |
446 | #ifdef OPENSSL_SYS_WINDOWS |
447 | { | |
448 | int timeout, sz = sizeof(timeout); | |
449 | struct timeval *tv = (struct timeval *)ptr; | |
d7235a9d AP |
450 | if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, |
451 | (void*)&timeout, &sz) < 0) | |
b9790c1c AP |
452 | { perror("getsockopt"); ret = -1; } |
453 | else | |
454 | { | |
455 | tv->tv_sec = timeout / 1000; | |
456 | tv->tv_usec = (timeout % 1000) * 1000; | |
457 | ret = sizeof(*tv); | |
458 | } | |
459 | } | |
460 | #else | |
36d16f8e | 461 | if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, |
6c61726b | 462 | ptr, (void *)&ret) < 0) |
36d16f8e | 463 | { perror("getsockopt"); ret = -1; } |
b9790c1c | 464 | #endif |
36d16f8e | 465 | break; |
4700aea9 | 466 | #endif |
36d16f8e BL |
467 | case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: |
468 | /* fall-through */ | |
469 | case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: | |
b9790c1c | 470 | #ifdef OPENSSL_SYS_WINDOWS |
d7235a9d | 471 | if ( data->_errno == WSAETIMEDOUT) |
b9790c1c | 472 | #else |
36d16f8e | 473 | if ( data->_errno == EAGAIN) |
b9790c1c | 474 | #endif |
36d16f8e BL |
475 | { |
476 | ret = 1; | |
477 | data->_errno = 0; | |
478 | } | |
479 | else | |
480 | ret = 0; | |
481 | break; | |
6c61726b | 482 | #ifdef EMSGSIZE |
36d16f8e BL |
483 | case BIO_CTRL_DGRAM_MTU_EXCEEDED: |
484 | if ( data->_errno == EMSGSIZE) | |
485 | { | |
486 | ret = 1; | |
487 | data->_errno = 0; | |
488 | } | |
489 | else | |
490 | ret = 0; | |
491 | break; | |
6c61726b | 492 | #endif |
36d16f8e BL |
493 | default: |
494 | ret=0; | |
495 | break; | |
496 | } | |
497 | return(ret); | |
498 | } | |
499 | ||
500 | static int dgram_puts(BIO *bp, const char *str) | |
501 | { | |
502 | int n,ret; | |
503 | ||
504 | n=strlen(str); | |
505 | ret=dgram_write(bp,str,n); | |
506 | return(ret); | |
507 | } | |
508 | ||
b3e72fc3 | 509 | static int BIO_dgram_should_retry(int i) |
36d16f8e BL |
510 | { |
511 | int err; | |
512 | ||
513 | if ((i == 0) || (i == -1)) | |
514 | { | |
515 | err=get_last_socket_error(); | |
516 | ||
517 | #if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ | |
518 | if ((i == -1) && (err == 0)) | |
519 | return(1); | |
520 | #endif | |
521 | ||
522 | return(BIO_dgram_non_fatal_error(err)); | |
523 | } | |
524 | return(0); | |
525 | } | |
526 | ||
527 | int BIO_dgram_non_fatal_error(int err) | |
528 | { | |
529 | switch (err) | |
530 | { | |
531 | #if defined(OPENSSL_SYS_WINDOWS) | |
532 | # if defined(WSAEWOULDBLOCK) | |
533 | case WSAEWOULDBLOCK: | |
534 | # endif | |
535 | ||
536 | # if 0 /* This appears to always be an error */ | |
537 | # if defined(WSAENOTCONN) | |
538 | case WSAENOTCONN: | |
539 | # endif | |
540 | # endif | |
541 | #endif | |
542 | ||
543 | #ifdef EWOULDBLOCK | |
544 | # ifdef WSAEWOULDBLOCK | |
545 | # if WSAEWOULDBLOCK != EWOULDBLOCK | |
546 | case EWOULDBLOCK: | |
547 | # endif | |
548 | # else | |
549 | case EWOULDBLOCK: | |
550 | # endif | |
551 | #endif | |
552 | ||
553 | #if defined(ENOTCONN) | |
554 | case ENOTCONN: | |
555 | #endif | |
556 | ||
557 | #ifdef EINTR | |
558 | case EINTR: | |
559 | #endif | |
560 | ||
561 | #ifdef EAGAIN | |
562 | #if EWOULDBLOCK != EAGAIN | |
563 | case EAGAIN: | |
564 | # endif | |
565 | #endif | |
566 | ||
567 | #ifdef EPROTO | |
568 | case EPROTO: | |
569 | #endif | |
570 | ||
571 | #ifdef EINPROGRESS | |
572 | case EINPROGRESS: | |
573 | #endif | |
574 | ||
575 | #ifdef EALREADY | |
576 | case EALREADY: | |
577 | #endif | |
578 | ||
579 | /* DF bit set, and packet larger than MTU */ | |
580 | #ifdef EMSGSIZE | |
581 | case EMSGSIZE: | |
582 | #endif | |
583 | ||
584 | return(1); | |
585 | /* break; */ | |
586 | default: | |
587 | break; | |
588 | } | |
589 | return(0); | |
590 | } | |
591 | #endif | |
5d6a0179 RL |
592 | |
593 | static void get_current_time(struct timeval *t) | |
594 | { | |
595 | #ifdef OPENSSL_SYS_WIN32 | |
596 | struct _timeb tb; | |
597 | _ftime(&tb); | |
598 | t->tv_sec = (long)tb.time; | |
599 | t->tv_usec = (long)tb.millitm * 1000; | |
600 | #elif defined(OPENSSL_SYS_VMS) | |
601 | struct timeb tb; | |
602 | ftime(&tb); | |
603 | t->tv_sec = (long)tb.time; | |
604 | t->tv_usec = (long)tb.millitm * 1000; | |
605 | #else | |
606 | gettimeofday(t, NULL); | |
607 | #endif | |
608 | } |