Bug Summary

File:src/lib/libcrypto/bio/bss_dgram.c
Warning:line 346, column 3
Value stored to 'num' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name bss_dgram.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libcrypto/obj -resource-dir /usr/local/lib/clang/13.0.0 -D LIBRESSL_INTERNAL -D LIBRESSL_CRYPTO_INTERNAL -D DSO_DLFCN -D HAVE_DLFCN_H -D HAVE_FUNOPEN -D OPENSSL_NO_HW_PADLOCK -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdh -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/x509 -I /usr/src/lib/libcrypto/obj -D AES_ASM -D BSAES_ASM -D VPAES_ASM -D OPENSSL_IA32_SSE2 -D RSA_ASM -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_BN_ASM_GF2m -D MD5_ASM -D GHASH_ASM -D RC4_MD5_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D WHIRLPOOL_ASM -D OPENSSL_CPUID_OBJ -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libcrypto/bio/bss_dgram.c
1/* $OpenBSD: bss_dgram.c,v 1.43 2022/01/07 09:02:17 tb Exp $ */
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#include <sys/socket.h>
61#include <sys/time.h>
62
63#include <netinet/in.h>
64
65#include <errno(*__errno()).h>
66#include <netdb.h>
67#include <stdio.h>
68#include <string.h>
69#include <unistd.h>
70
71#include <openssl/opensslconf.h>
72
73#include <openssl/bio.h>
74
75#include "bio_local.h"
76
77#ifndef OPENSSL_NO_DGRAM
78
79
80static int dgram_write(BIO *h, const char *buf, int num);
81static int dgram_read(BIO *h, char *buf, int size);
82static int dgram_puts(BIO *h, const char *str);
83static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
84static int dgram_new(BIO *h);
85static int dgram_free(BIO *data);
86static int dgram_clear(BIO *bio);
87
88
89static int BIO_dgram_should_retry(int s);
90
91static const BIO_METHOD methods_dgramp = {
92 .type = BIO_TYPE_DGRAM(21|0x0400|0x0100),
93 .name = "datagram socket",
94 .bwrite = dgram_write,
95 .bread = dgram_read,
96 .bputs = dgram_puts,
97 .ctrl = dgram_ctrl,
98 .create = dgram_new,
99 .destroy = dgram_free
100};
101
102
103typedef struct bio_dgram_data_st {
104 union {
105 struct sockaddr sa;
106 struct sockaddr_in sa_in;
107 struct sockaddr_in6 sa_in6;
108 } peer;
109 unsigned int connected;
110 unsigned int _errno;
111 unsigned int mtu;
112 struct timeval next_timeout;
113 struct timeval socket_timeout;
114} bio_dgram_data;
115
116
117const BIO_METHOD *
118BIO_s_datagram(void)
119{
120 return (&methods_dgramp);
121}
122
123BIO *
124BIO_new_dgram(int fd, int close_flag)
125{
126 BIO *ret;
127
128 ret = BIO_new(BIO_s_datagram());
129 if (ret == NULL((void *)0))
130 return (NULL((void *)0));
131 BIO_set_fd(ret, fd, close_flag)BIO_int_ctrl(ret,104,close_flag,fd);
132 return (ret);
133}
134
135static int
136dgram_new(BIO *bi)
137{
138 bio_dgram_data *data = NULL((void *)0);
139
140 bi->init = 0;
141 bi->num = 0;
142 data = calloc(1, sizeof(bio_dgram_data));
143 if (data == NULL((void *)0))
144 return 0;
145 bi->ptr = data;
146
147 bi->flags = 0;
148 return (1);
149}
150
151static int
152dgram_free(BIO *a)
153{
154 bio_dgram_data *data;
155
156 if (a == NULL((void *)0))
157 return (0);
158 if (!dgram_clear(a))
159 return 0;
160
161 data = (bio_dgram_data *)a->ptr;
162 free(data);
163
164 return (1);
165}
166
167static int
168dgram_clear(BIO *a)
169{
170 if (a == NULL((void *)0))
171 return (0);
172 if (a->shutdown) {
173 if (a->init) {
174 shutdown(a->num, SHUT_RDWR2);
175 close(a->num);
176 }
177 a->init = 0;
178 a->flags = 0;
179 }
180 return (1);
181}
182
183static void
184dgram_adjust_rcv_timeout(BIO *b)
185{
186#if defined(SO_RCVTIMEO0x1006)
187 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
188
189 /* Is a timer active? */
190 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
191 struct timeval timenow, timeleft;
192
193 /* Read current socket timeout */
194 socklen_t sz = sizeof(data->socket_timeout);
195 if (getsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
196 &(data->socket_timeout), &sz) < 0) {
197 perror("getsockopt");
198 }
199
200 /* Get current time */
201 gettimeofday(&timenow, NULL((void *)0));
202
203 /* Calculate time left until timer expires */
204 memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
205 timeleft.tv_sec -= timenow.tv_sec;
206 timeleft.tv_usec -= timenow.tv_usec;
207 if (timeleft.tv_usec < 0) {
208 timeleft.tv_sec--;
209 timeleft.tv_usec += 1000000;
210 }
211
212 if (timeleft.tv_sec < 0) {
213 timeleft.tv_sec = 0;
214 timeleft.tv_usec = 1;
215 }
216
217 /* Adjust socket timeout if next handhake message timer
218 * will expire earlier.
219 */
220 if ((data->socket_timeout.tv_sec == 0 &&
221 data->socket_timeout.tv_usec == 0) ||
222 (data->socket_timeout.tv_sec > timeleft.tv_sec) ||
223 (data->socket_timeout.tv_sec == timeleft.tv_sec &&
224 data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
225 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
226 &timeleft, sizeof(struct timeval)) < 0) {
227 perror("setsockopt");
228 }
229 }
230 }
231#endif
232}
233
234static void
235dgram_reset_rcv_timeout(BIO *b)
236{
237#if defined(SO_RCVTIMEO0x1006)
238 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
239
240 /* Is a timer active? */
241 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
242 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
243 &(data->socket_timeout), sizeof(struct timeval)) < 0) {
244 perror("setsockopt");
245 }
246 }
247#endif
248}
249
250static int
251dgram_read(BIO *b, char *out, int outl)
252{
253 int ret = 0;
254 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
255
256 struct {
257 socklen_t len;
258 union {
259 struct sockaddr sa;
260 struct sockaddr_in sa_in;
261 struct sockaddr_in6 sa_in6;
262 } peer;
263 } sa;
264
265 sa.len = sizeof(sa.peer);
266
267 if (out != NULL((void *)0)) {
268 errno(*__errno()) = 0;
269 memset(&sa.peer, 0, sizeof(sa.peer));
270 dgram_adjust_rcv_timeout(b);
271 ret = recvfrom(b->num, out, outl, 0, &sa.peer.sa, &sa.len);
272
273 if (! data->connected && ret >= 0)
274 BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER44, 0, &sa.peer);
275
276 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
277 if (ret < 0) {
278 if (BIO_dgram_should_retry(ret)) {
279 BIO_set_retry_read(b)BIO_set_flags(b, (0x01|0x08));
280 data->_errno = errno(*__errno());
281 }
282 }
283
284 dgram_reset_rcv_timeout(b);
285 }
286 return (ret);
287}
288
289static int
290dgram_write(BIO *b, const char *in, int inl)
291{
292 int ret;
293 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
294 errno(*__errno()) = 0;
295
296 if (data->connected)
297 ret = write(b->num, in, inl);
298 else {
299 int peerlen = sizeof(data->peer);
300
301 if (data->peer.sa.sa_family == AF_INET2)
302 peerlen = sizeof(data->peer.sa_in);
303 else if (data->peer.sa.sa_family == AF_INET624)
304 peerlen = sizeof(data->peer.sa_in6);
305 ret = sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
306 }
307
308 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
309 if (ret <= 0) {
310 if (BIO_dgram_should_retry(ret)) {
311 BIO_set_retry_write(b)BIO_set_flags(b, (0x02|0x08));
312
313 data->_errno = errno(*__errno());
314 /*
315 * higher layers are responsible for querying MTU,
316 * if necessary
317 */
318 }
319 }
320 return (ret);
321}
322
323static long
324dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
325{
326 long ret = 1;
327 int *ip;
328 struct sockaddr *to = NULL((void *)0);
329 bio_dgram_data *data = NULL((void *)0);
330#if (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
331 int sockopt_val = 0;
332 socklen_t sockopt_len; /* assume that system supporting IP_MTU is
333 * modern enough to define socklen_t */
334 socklen_t addr_len;
335 union {
336 struct sockaddr sa;
337 struct sockaddr_in s4;
338 struct sockaddr_in6 s6;
339 } addr;
340#endif
341
342 data = (bio_dgram_data *)b->ptr;
343
344 switch (cmd) {
345 case BIO_CTRL_RESET1:
346 num = 0;
Value stored to 'num' is never read
347 case BIO_C_FILE_SEEK128:
348 ret = 0;
349 break;
350 case BIO_C_FILE_TELL133:
351 case BIO_CTRL_INFO3:
352 ret = 0;
353 break;
354 case BIO_C_SET_FD104:
355 dgram_clear(b);
356 b->num= *((int *)ptr);
357 b->shutdown = (int)num;
358 b->init = 1;
359 break;
360 case BIO_C_GET_FD105:
361 if (b->init) {
362 ip = (int *)ptr;
363 if (ip != NULL((void *)0))
364 *ip = b->num;
365 ret = b->num;
366 } else
367 ret = -1;
368 break;
369 case BIO_CTRL_GET_CLOSE8:
370 ret = b->shutdown;
371 break;
372 case BIO_CTRL_SET_CLOSE9:
373 b->shutdown = (int)num;
374 break;
375 case BIO_CTRL_PENDING10:
376 case BIO_CTRL_WPENDING13:
377 ret = 0;
378 break;
379 case BIO_CTRL_DUP12:
380 case BIO_CTRL_FLUSH11:
381 ret = 1;
382 break;
383 case BIO_CTRL_DGRAM_CONNECT31:
384 to = (struct sockaddr *)ptr;
385 switch (to->sa_family) {
386 case AF_INET2:
387 memcpy(&data->peer, to, sizeof(data->peer.sa_in));
388 break;
389 case AF_INET624:
390 memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
391 break;
392 default:
393 memcpy(&data->peer, to, sizeof(data->peer.sa));
394 break;
395 }
396 break;
397 /* (Linux)kernel sets DF bit on outgoing IP packets */
398 case BIO_CTRL_DGRAM_MTU_DISCOVER39:
399#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
400 addr_len = (socklen_t)sizeof(addr);
401 memset((void *)&addr, 0, sizeof(addr));
402 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
403 ret = 0;
404 break;
405 }
406 switch (addr.sa.sa_family) {
407 case AF_INET2:
408 sockopt_val = IP_PMTUDISC_DO;
409 ret = setsockopt(b->num, IPPROTO_IP0, IP_MTU_DISCOVER,
410 &sockopt_val, sizeof(sockopt_val));
411 if (ret < 0)
412 perror("setsockopt");
413 break;
414#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
415 case AF_INET624:
416 sockopt_val = IPV6_PMTUDISC_DO;
417 ret = setsockopt(b->num, IPPROTO_IPV641,
418 IPV6_MTU_DISCOVER, &sockopt_val,
419 sizeof(sockopt_val));
420 if (ret < 0)
421 perror("setsockopt");
422 break;
423#endif
424 default:
425 ret = -1;
426 break;
427 }
428#else
429 ret = -1;
430#endif
431 break;
432 case BIO_CTRL_DGRAM_QUERY_MTU40:
433#if defined(IP_MTU)
434 addr_len = (socklen_t)sizeof(addr);
435 memset((void *)&addr, 0, sizeof(addr));
436 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
437 ret = 0;
438 break;
439 }
440 sockopt_len = sizeof(sockopt_val);
441 switch (addr.sa.sa_family) {
442 case AF_INET2:
443 ret = getsockopt(b->num, IPPROTO_IP0, IP_MTU,
444 &sockopt_val, &sockopt_len);
445 if (ret < 0 || sockopt_val < 0) {
446 ret = 0;
447 } else {
448 /* we assume that the transport protocol is UDP and no
449 * IP options are used.
450 */
451 data->mtu = sockopt_val - 8 - 20;
452 ret = data->mtu;
453 }
454 break;
455#if defined(IPV6_MTU)
456 case AF_INET624:
457 ret = getsockopt(b->num, IPPROTO_IPV641, IPV6_MTU,
458 &sockopt_val, &sockopt_len);
459 if (ret < 0 || sockopt_val < 0) {
460 ret = 0;
461 } else {
462 /* we assume that the transport protocol is UDP and no
463 * IPV6 options are used.
464 */
465 data->mtu = sockopt_val - 8 - 40;
466 ret = data->mtu;
467 }
468 break;
469#endif
470default:
471 ret = 0;
472 break;
473 }
474#else
475 ret = 0;
476#endif
477 break;
478 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU47:
479 switch (data->peer.sa.sa_family) {
480 case AF_INET2:
481 ret = 576 - 20 - 8;
482 break;
483 case AF_INET624:
484#ifdef IN6_IS_ADDR_V4MAPPED
485 if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr)((*(const u_int32_t *)(const void *)(&(&data->peer
.sa_in6.sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&data->peer
.sa_in6.sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&data->peer
.sa_in6.sin6_addr)->__u6_addr.__u6_addr8[8]) == (__uint32_t
)(__builtin_constant_p(0x0000ffff) ? (__uint32_t)(((__uint32_t
)(0x0000ffff) & 0xff) << 24 | ((__uint32_t)(0x0000ffff
) & 0xff00) << 8 | ((__uint32_t)(0x0000ffff) & 0xff0000
) >> 8 | ((__uint32_t)(0x0000ffff) & 0xff000000) >>
24) : __swap32md(0x0000ffff))))
)
486 ret = 576 - 20 - 8;
487 else
488#endif
489 ret = 1280 - 40 - 8;
490 break;
491 default:
492 ret = 576 - 20 - 8;
493 break;
494 }
495 break;
496 case BIO_CTRL_DGRAM_GET_MTU41:
497 return data->mtu;
498 break;
499 case BIO_CTRL_DGRAM_SET_MTU42:
500 data->mtu = num;
501 ret = num;
502 break;
503 case BIO_CTRL_DGRAM_SET_CONNECTED32:
504 to = (struct sockaddr *)ptr;
505
506 if (to != NULL((void *)0)) {
507 data->connected = 1;
508 switch (to->sa_family) {
509 case AF_INET2:
510 memcpy(&data->peer, to, sizeof(data->peer.sa_in));
511 break;
512 case AF_INET624:
513 memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
514 break;
515 default:
516 memcpy(&data->peer, to, sizeof(data->peer.sa));
517 break;
518 }
519 } else {
520 data->connected = 0;
521 memset(&(data->peer), 0, sizeof(data->peer));
522 }
523 break;
524 case BIO_CTRL_DGRAM_GET_PEER46:
525 switch (data->peer.sa.sa_family) {
526 case AF_INET2:
527 ret = sizeof(data->peer.sa_in);
528 break;
529 case AF_INET624:
530 ret = sizeof(data->peer.sa_in6);
531 break;
532 default:
533 ret = sizeof(data->peer.sa);
534 break;
535 }
536 if (num == 0 || num > ret)
537 num = ret;
538 memcpy(ptr, &data->peer, (ret = num));
539 break;
540 case BIO_CTRL_DGRAM_SET_PEER44:
541 to = (struct sockaddr *) ptr;
542 switch (to->sa_family) {
543 case AF_INET2:
544 memcpy(&data->peer, to, sizeof(data->peer.sa_in));
545 break;
546 case AF_INET624:
547 memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
548 break;
549 default:
550 memcpy(&data->peer, to, sizeof(data->peer.sa));
551 break;
552 }
553 break;
554 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT45:
555 memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
556 break;
557#if defined(SO_RCVTIMEO0x1006)
558 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT33:
559 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006, ptr,
560 sizeof(struct timeval)) < 0) {
561 perror("setsockopt");
562 ret = -1;
563 }
564 break;
565 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT34:
566 {
567 socklen_t sz = sizeof(struct timeval);
568 if (getsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
569 ptr, &sz) < 0) {
570 perror("getsockopt");
571 ret = -1;
572 } else
573 ret = sz;
574 }
575 break;
576#endif
577#if defined(SO_SNDTIMEO0x1005)
578 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT35:
579 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_SNDTIMEO0x1005, ptr,
580 sizeof(struct timeval)) < 0) {
581 perror("setsockopt");
582 ret = -1;
583 }
584 break;
585 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT36:
586 {
587 socklen_t sz = sizeof(struct timeval);
588 if (getsockopt(b->num, SOL_SOCKET0xffff, SO_SNDTIMEO0x1005,
589 ptr, &sz) < 0) {
590 perror("getsockopt");
591 ret = -1;
592 } else
593 ret = sz;
594 }
595 break;
596#endif
597 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP38:
598 /* fall-through */
599 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP37:
600 if (data->_errno == EAGAIN35) {
601 ret = 1;
602 data->_errno = 0;
603 } else
604 ret = 0;
605 break;
606#ifdef EMSGSIZE40
607 case BIO_CTRL_DGRAM_MTU_EXCEEDED43:
608 if (data->_errno == EMSGSIZE40) {
609 ret = 1;
610 data->_errno = 0;
611 } else
612 ret = 0;
613 break;
614#endif
615 default:
616 ret = 0;
617 break;
618 }
619 return (ret);
620}
621
622static int
623dgram_puts(BIO *bp, const char *str)
624{
625 int n, ret;
626
627 n = strlen(str);
628 ret = dgram_write(bp, str, n);
629 return (ret);
630}
631
632
633static int
634BIO_dgram_should_retry(int i)
635{
636 int err;
637
638 if ((i == 0) || (i == -1)) {
639 err = errno(*__errno());
640 return (BIO_dgram_non_fatal_error(err));
641 }
642 return (0);
643}
644
645int
646BIO_dgram_non_fatal_error(int err)
647{
648 switch (err) {
649 case EINTR4:
650 case EAGAIN35:
651 case EINPROGRESS36:
652 case EALREADY37:
653 return (1);
654 default:
655 break;
656 }
657 return (0);
658}
659
660#endif