Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bss_dgram.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -D HAVE_FUNOPEN -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/arch/amd64 -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bn/arch/amd64 -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/curve25519 -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hidden -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/kdf -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/pkcs12 -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/sha -I /usr/src/lib/libcrypto/ts -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 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/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libcrypto/bio/bss_dgram.c
1/* $OpenBSD: bss_dgram.c,v 1.45 2023/07/05 21:23:37 beck 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}
122LCRYPTO_ALIAS(BIO_s_datagram)asm("");
123
124BIO *
125BIO_new_dgram(int fd, int close_flag)
126{
127 BIO *ret;
128
129 ret = BIO_new(BIO_s_datagram());
130 if (ret == NULL((void *)0))
131 return (NULL((void *)0));
132 BIO_set_fd(ret, fd, close_flag)BIO_int_ctrl(ret,104,close_flag,fd);
133 return (ret);
134}
135LCRYPTO_ALIAS(BIO_new_dgram)asm("");
136
137static int
138dgram_new(BIO *bi)
139{
140 bio_dgram_data *data = NULL((void *)0);
141
142 bi->init = 0;
143 bi->num = 0;
144 data = calloc(1, sizeof(bio_dgram_data));
145 if (data == NULL((void *)0))
146 return 0;
147 bi->ptr = data;
148
149 bi->flags = 0;
150 return (1);
151}
152
153static int
154dgram_free(BIO *a)
155{
156 bio_dgram_data *data;
157
158 if (a == NULL((void *)0))
159 return (0);
160 if (!dgram_clear(a))
161 return 0;
162
163 data = (bio_dgram_data *)a->ptr;
164 free(data);
165
166 return (1);
167}
168
169static int
170dgram_clear(BIO *a)
171{
172 if (a == NULL((void *)0))
173 return (0);
174 if (a->shutdown) {
175 if (a->init) {
176 shutdown(a->num, SHUT_RDWR2);
177 close(a->num);
178 }
179 a->init = 0;
180 a->flags = 0;
181 }
182 return (1);
183}
184
185static void
186dgram_adjust_rcv_timeout(BIO *b)
187{
188#if defined(SO_RCVTIMEO0x1006)
189 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
190
191 /* Is a timer active? */
192 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
193 struct timeval timenow, timeleft;
194
195 /* Read current socket timeout */
196 socklen_t sz = sizeof(data->socket_timeout);
197 if (getsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
198 &(data->socket_timeout), &sz) < 0) {
199 perror("getsockopt");
200 }
201
202 /* Get current time */
203 gettimeofday(&timenow, NULL((void *)0));
204
205 /* Calculate time left until timer expires */
206 memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
207 timeleft.tv_sec -= timenow.tv_sec;
208 timeleft.tv_usec -= timenow.tv_usec;
209 if (timeleft.tv_usec < 0) {
210 timeleft.tv_sec--;
211 timeleft.tv_usec += 1000000;
212 }
213
214 if (timeleft.tv_sec < 0) {
215 timeleft.tv_sec = 0;
216 timeleft.tv_usec = 1;
217 }
218
219 /* Adjust socket timeout if next handshake message timer
220 * will expire earlier.
221 */
222 if ((data->socket_timeout.tv_sec == 0 &&
223 data->socket_timeout.tv_usec == 0) ||
224 (data->socket_timeout.tv_sec > timeleft.tv_sec) ||
225 (data->socket_timeout.tv_sec == timeleft.tv_sec &&
226 data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
227 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
228 &timeleft, sizeof(struct timeval)) < 0) {
229 perror("setsockopt");
230 }
231 }
232 }
233#endif
234}
235
236static void
237dgram_reset_rcv_timeout(BIO *b)
238{
239#if defined(SO_RCVTIMEO0x1006)
240 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
241
242 /* Is a timer active? */
243 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
244 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
245 &(data->socket_timeout), sizeof(struct timeval)) < 0) {
246 perror("setsockopt");
247 }
248 }
249#endif
250}
251
252static int
253dgram_read(BIO *b, char *out, int outl)
254{
255 int ret = 0;
256 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
257
258 struct {
259 socklen_t len;
260 union {
261 struct sockaddr sa;
262 struct sockaddr_in sa_in;
263 struct sockaddr_in6 sa_in6;
264 } peer;
265 } sa;
266
267 sa.len = sizeof(sa.peer);
268
269 if (out != NULL((void *)0)) {
270 errno(*__errno()) = 0;
271 memset(&sa.peer, 0, sizeof(sa.peer));
272 dgram_adjust_rcv_timeout(b);
273 ret = recvfrom(b->num, out, outl, 0, &sa.peer.sa, &sa.len);
274
275 if (! data->connected && ret >= 0)
276 BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER44, 0, &sa.peer);
277
278 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
279 if (ret < 0) {
280 if (BIO_dgram_should_retry(ret)) {
281 BIO_set_retry_read(b)BIO_set_flags(b, (0x01|0x08));
282 data->_errno = errno(*__errno());
283 }
284 }
285
286 dgram_reset_rcv_timeout(b);
287 }
288 return (ret);
289}
290
291static int
292dgram_write(BIO *b, const char *in, int inl)
293{
294 int ret;
295 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
296 errno(*__errno()) = 0;
297
298 if (data->connected)
299 ret = write(b->num, in, inl);
300 else {
301 int peerlen = sizeof(data->peer);
302
303 if (data->peer.sa.sa_family == AF_INET2)
304 peerlen = sizeof(data->peer.sa_in);
305 else if (data->peer.sa.sa_family == AF_INET624)
306 peerlen = sizeof(data->peer.sa_in6);
307 ret = sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
308 }
309
310 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
311 if (ret <= 0) {
312 if (BIO_dgram_should_retry(ret)) {
313 BIO_set_retry_write(b)BIO_set_flags(b, (0x02|0x08));
314
315 data->_errno = errno(*__errno());
316 /*
317 * higher layers are responsible for querying MTU,
318 * if necessary
319 */
320 }
321 }
322 return (ret);
323}
324
325static long
326dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
327{
328 long ret = 1;
329 int *ip;
330 struct sockaddr *to = NULL((void *)0);
331 bio_dgram_data *data = NULL((void *)0);
332#if (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
333 int sockopt_val = 0;
334 socklen_t sockopt_len; /* assume that system supporting IP_MTU is
335 * modern enough to define socklen_t */
336 socklen_t addr_len;
337 union {
338 struct sockaddr sa;
339 struct sockaddr_in s4;
340 struct sockaddr_in6 s6;
341 } addr;
342#endif
343
344 data = (bio_dgram_data *)b->ptr;
345
346 switch (cmd) {
347 case BIO_CTRL_RESET1:
348 num = 0;
Value stored to 'num' is never read
349 case BIO_C_FILE_SEEK128:
350 ret = 0;
351 break;
352 case BIO_C_FILE_TELL133:
353 case BIO_CTRL_INFO3:
354 ret = 0;
355 break;
356 case BIO_C_SET_FD104:
357 dgram_clear(b);
358 b->num= *((int *)ptr);
359 b->shutdown = (int)num;
360 b->init = 1;
361 break;
362 case BIO_C_GET_FD105:
363 if (b->init) {
364 ip = (int *)ptr;
365 if (ip != NULL((void *)0))
366 *ip = b->num;
367 ret = b->num;
368 } else
369 ret = -1;
370 break;
371 case BIO_CTRL_GET_CLOSE8:
372 ret = b->shutdown;
373 break;
374 case BIO_CTRL_SET_CLOSE9:
375 b->shutdown = (int)num;
376 break;
377 case BIO_CTRL_PENDING10:
378 case BIO_CTRL_WPENDING13:
379 ret = 0;
380 break;
381 case BIO_CTRL_DUP12:
382 case BIO_CTRL_FLUSH11:
383 ret = 1;
384 break;
385 case BIO_CTRL_DGRAM_CONNECT31:
386 to = (struct sockaddr *)ptr;
387 switch (to->sa_family) {
388 case AF_INET2:
389 memcpy(&data->peer, to, sizeof(data->peer.sa_in));
390 break;
391 case AF_INET624:
392 memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
393 break;
394 default:
395 memcpy(&data->peer, to, sizeof(data->peer.sa));
396 break;
397 }
398 break;
399 /* (Linux)kernel sets DF bit on outgoing IP packets */
400 case BIO_CTRL_DGRAM_MTU_DISCOVER39:
401#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
402 addr_len = (socklen_t)sizeof(addr);
403 memset((void *)&addr, 0, sizeof(addr));
404 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
405 ret = 0;
406 break;
407 }
408 switch (addr.sa.sa_family) {
409 case AF_INET2:
410 sockopt_val = IP_PMTUDISC_DO;
411 ret = setsockopt(b->num, IPPROTO_IP0, IP_MTU_DISCOVER,
412 &sockopt_val, sizeof(sockopt_val));
413 if (ret < 0)
414 perror("setsockopt");
415 break;
416#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
417 case AF_INET624:
418 sockopt_val = IPV6_PMTUDISC_DO;
419 ret = setsockopt(b->num, IPPROTO_IPV641,
420 IPV6_MTU_DISCOVER, &sockopt_val,
421 sizeof(sockopt_val));
422 if (ret < 0)
423 perror("setsockopt");
424 break;
425#endif
426 default:
427 ret = -1;
428 break;
429 }
430#else
431 ret = -1;
432#endif
433 break;
434 case BIO_CTRL_DGRAM_QUERY_MTU40:
435#if defined(IP_MTU)
436 addr_len = (socklen_t)sizeof(addr);
437 memset((void *)&addr, 0, sizeof(addr));
438 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
439 ret = 0;
440 break;
441 }
442 sockopt_len = sizeof(sockopt_val);
443 switch (addr.sa.sa_family) {
444 case AF_INET2:
445 ret = getsockopt(b->num, IPPROTO_IP0, IP_MTU,
446 &sockopt_val, &sockopt_len);
447 if (ret < 0 || sockopt_val < 0) {
448 ret = 0;
449 } else {
450 /* we assume that the transport protocol is UDP and no
451 * IP options are used.
452 */
453 data->mtu = sockopt_val - 8 - 20;
454 ret = data->mtu;
455 }
456 break;
457#if defined(IPV6_MTU)
458 case AF_INET624:
459 ret = getsockopt(b->num, IPPROTO_IPV641, IPV6_MTU,
460 &sockopt_val, &sockopt_len);
461 if (ret < 0 || sockopt_val < 0) {
462 ret = 0;
463 } else {
464 /* we assume that the transport protocol is UDP and no
465 * IPV6 options are used.
466 */
467 data->mtu = sockopt_val - 8 - 40;
468 ret = data->mtu;
469 }
470 break;
471#endif
472default:
473 ret = 0;
474 break;
475 }
476#else
477 ret = 0;
478#endif
479 break;
480 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU47:
481 switch (data->peer.sa.sa_family) {
482 case AF_INET2:
483 ret = 576 - 20 - 8;
484 break;
485 case AF_INET624:
486#ifdef IN6_IS_ADDR_V4MAPPED
487 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))))
)
488 ret = 576 - 20 - 8;
489 else
490#endif
491 ret = 1280 - 40 - 8;
492 break;
493 default:
494 ret = 576 - 20 - 8;
495 break;
496 }
497 break;
498 case BIO_CTRL_DGRAM_GET_MTU41:
499 return data->mtu;
500 break;
501 case BIO_CTRL_DGRAM_SET_MTU42:
502 data->mtu = num;
503 ret = num;
504 break;
505 case BIO_CTRL_DGRAM_SET_CONNECTED32:
506 to = (struct sockaddr *)ptr;
507
508 if (to != NULL((void *)0)) {
509 data->connected = 1;
510 switch (to->sa_family) {
511 case AF_INET2:
512 memcpy(&data->peer, to, sizeof(data->peer.sa_in));
513 break;
514 case AF_INET624:
515 memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
516 break;
517 default:
518 memcpy(&data->peer, to, sizeof(data->peer.sa));
519 break;
520 }
521 } else {
522 data->connected = 0;
523 memset(&(data->peer), 0, sizeof(data->peer));
524 }
525 break;
526 case BIO_CTRL_DGRAM_GET_PEER46:
527 switch (data->peer.sa.sa_family) {
528 case AF_INET2:
529 ret = sizeof(data->peer.sa_in);
530 break;
531 case AF_INET624:
532 ret = sizeof(data->peer.sa_in6);
533 break;
534 default:
535 ret = sizeof(data->peer.sa);
536 break;
537 }
538 if (num == 0 || num > ret)
539 num = ret;
540 memcpy(ptr, &data->peer, (ret = num));
541 break;
542 case BIO_CTRL_DGRAM_SET_PEER44:
543 to = (struct sockaddr *) ptr;
544 switch (to->sa_family) {
545 case AF_INET2:
546 memcpy(&data->peer, to, sizeof(data->peer.sa_in));
547 break;
548 case AF_INET624:
549 memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
550 break;
551 default:
552 memcpy(&data->peer, to, sizeof(data->peer.sa));
553 break;
554 }
555 break;
556 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT45:
557 memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
558 break;
559#if defined(SO_RCVTIMEO0x1006)
560 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT33:
561 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006, ptr,
562 sizeof(struct timeval)) < 0) {
563 perror("setsockopt");
564 ret = -1;
565 }
566 break;
567 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT34:
568 {
569 socklen_t sz = sizeof(struct timeval);
570 if (getsockopt(b->num, SOL_SOCKET0xffff, SO_RCVTIMEO0x1006,
571 ptr, &sz) < 0) {
572 perror("getsockopt");
573 ret = -1;
574 } else
575 ret = sz;
576 }
577 break;
578#endif
579#if defined(SO_SNDTIMEO0x1005)
580 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT35:
581 if (setsockopt(b->num, SOL_SOCKET0xffff, SO_SNDTIMEO0x1005, ptr,
582 sizeof(struct timeval)) < 0) {
583 perror("setsockopt");
584 ret = -1;
585 }
586 break;
587 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT36:
588 {
589 socklen_t sz = sizeof(struct timeval);
590 if (getsockopt(b->num, SOL_SOCKET0xffff, SO_SNDTIMEO0x1005,
591 ptr, &sz) < 0) {
592 perror("getsockopt");
593 ret = -1;
594 } else
595 ret = sz;
596 }
597 break;
598#endif
599 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP38:
600 /* fall-through */
601 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP37:
602 if (data->_errno == EAGAIN35) {
603 ret = 1;
604 data->_errno = 0;
605 } else
606 ret = 0;
607 break;
608#ifdef EMSGSIZE40
609 case BIO_CTRL_DGRAM_MTU_EXCEEDED43:
610 if (data->_errno == EMSGSIZE40) {
611 ret = 1;
612 data->_errno = 0;
613 } else
614 ret = 0;
615 break;
616#endif
617 default:
618 ret = 0;
619 break;
620 }
621 return (ret);
622}
623
624static int
625dgram_puts(BIO *bp, const char *str)
626{
627 int n, ret;
628
629 n = strlen(str);
630 ret = dgram_write(bp, str, n);
631 return (ret);
632}
633
634
635static int
636BIO_dgram_should_retry(int i)
637{
638 int err;
639
640 if ((i == 0) || (i == -1)) {
641 err = errno(*__errno());
642 return (BIO_dgram_non_fatal_error(err));
643 }
644 return (0);
645}
646
647int
648BIO_dgram_non_fatal_error(int err)
649{
650 switch (err) {
651 case EINTR4:
652 case EAGAIN35:
653 case EINPROGRESS36:
654 case EALREADY37:
655 return (1);
656 default:
657 break;
658 }
659 return (0);
660}
661LCRYPTO_ALIAS(BIO_dgram_non_fatal_error)asm("");
662
663#endif