Bug Summary

File:out/../deps/openssl/openssl/crypto/bio/bss_dgram.c
Warning:line 490, column 18
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -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 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D OPENSSL_NO_HW -D OPENSSL_API_COMPAT=0x10100001L -D STATIC_LEGACY -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -D MODULESDIR="/home/maurizio/node-v18.6.0/out/Release/obj.target/deps/openssl/lib/openssl-modules" -D OPENSSLDIR="/home/maurizio/node-v18.6.0/out/Release/obj.target/deps/openssl" -D OPENSSLDIR="/etc/ssl" -D ENGINESDIR="/dev/null" -D TERMIOS -I ../deps/openssl/openssl -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/openssl/crypto/modes -I ../deps/openssl/openssl/crypto/ec/curve448 -I ../deps/openssl/openssl/crypto/ec/curve448/arch_32 -I ../deps/openssl/openssl/providers/common/include -I ../deps/openssl/openssl/providers/implementations/include -I ../deps/openssl/config -I ../deps/openssl/config/archs/linux-x86_64/asm -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm/crypto -I ../deps/openssl/config/archs/linux-x86_64/asm/crypto/include/internal -I ../deps/openssl/config/archs/linux-x86_64/asm/providers/common/include -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-missing-field-initializers -Wno-old-style-declaration -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c ../deps/openssl/openssl/crypto/bio/bss_dgram.c
1/*
2 * Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#ifndef _GNU_SOURCE
11# define _GNU_SOURCE
12#endif
13
14#include <stdio.h>
15#include <errno(*__errno_location ()).h>
16
17#include "bio_local.h"
18#ifndef OPENSSL_NO_DGRAM
19
20# ifndef OPENSSL_NO_SCTP
21# include <netinet/sctp.h>
22# include <fcntl.h>
23# define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00
24# define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
25# endif
26
27# if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU14)
28# define IP_MTU14 14 /* linux is lame */
29# endif
30
31# if OPENSSL_USE_IPV61 && !defined(IPPROTO_IPV6IPPROTO_IPV6)
32# define IPPROTO_IPV6IPPROTO_IPV6 41 /* windows is lame */
33# endif
34
35# if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED)
36/* Standard definition causes type-punning problems. */
37# undef IN6_IS_ADDR_V4MAPPED
38# define s6_addr32__in6_u.__u6_addr32 __u6_addr.__u6_addr32
39# define IN6_IS_ADDR_V4MAPPED(a)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (a); __a->__in6_u.__u6_addr32[0] == 0 && __a->
__in6_u.__u6_addr32[1] == 0 && __a->__in6_u.__u6_addr32
[2] == __bswap_32 (0xffff); }))
\
40 (((a)->s6_addr32__in6_u.__u6_addr32[0] == 0) && \
41 ((a)->s6_addr32__in6_u.__u6_addr32[1] == 0) && \
42 ((a)->s6_addr32__in6_u.__u6_addr32[2] == htonl(0x0000ffff)__bswap_32 (0x0000ffff)))
43# endif
44
45static int dgram_write(BIO *h, const char *buf, int num);
46static int dgram_read(BIO *h, char *buf, int size);
47static int dgram_puts(BIO *h, const char *str);
48static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
49static int dgram_new(BIO *h);
50static int dgram_free(BIO *data);
51static int dgram_clear(BIO *bio);
52
53# ifndef OPENSSL_NO_SCTP
54static int dgram_sctp_write(BIO *h, const char *buf, int num);
55static int dgram_sctp_read(BIO *h, char *buf, int size);
56static int dgram_sctp_puts(BIO *h, const char *str);
57static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
58static int dgram_sctp_new(BIO *h);
59static int dgram_sctp_free(BIO *data);
60static int dgram_sctp_wait_for_dry(BIO *b);
61static int dgram_sctp_msg_waiting(BIO *b);
62# ifdef SCTP_AUTHENTICATION_EVENT
63static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification
64 *snp);
65# endif
66# endif
67
68static int BIO_dgram_should_retry(int s);
69
70static void get_current_time(struct timeval *t);
71
72static const BIO_METHOD methods_dgramp = {
73 BIO_TYPE_DGRAM(21|0x0400|0x0100),
74 "datagram socket",
75 bwrite_conv,
76 dgram_write,
77 bread_conv,
78 dgram_read,
79 dgram_puts,
80 NULL((void*)0), /* dgram_gets, */
81 dgram_ctrl,
82 dgram_new,
83 dgram_free,
84 NULL((void*)0), /* dgram_callback_ctrl */
85};
86
87# ifndef OPENSSL_NO_SCTP
88static const BIO_METHOD methods_dgramp_sctp = {
89 BIO_TYPE_DGRAM_SCTP,
90 "datagram sctp socket",
91 bwrite_conv,
92 dgram_sctp_write,
93 bread_conv,
94 dgram_sctp_read,
95 dgram_sctp_puts,
96 NULL((void*)0), /* dgram_gets, */
97 dgram_sctp_ctrl,
98 dgram_sctp_new,
99 dgram_sctp_free,
100 NULL((void*)0), /* dgram_callback_ctrl */
101};
102# endif
103
104typedef struct bio_dgram_data_st {
105 BIO_ADDR peer;
106 unsigned int connected;
107 unsigned int _errno;
108 unsigned int mtu;
109 struct timeval next_timeout;
110 struct timeval socket_timeout;
111 unsigned int peekmode;
112} bio_dgram_data;
113
114# ifndef OPENSSL_NO_SCTP
115typedef struct bio_dgram_sctp_save_message_st {
116 BIO *bio;
117 char *data;
118 int length;
119} bio_dgram_sctp_save_message;
120
121typedef struct bio_dgram_sctp_data_st {
122 BIO_ADDR peer;
123 unsigned int connected;
124 unsigned int _errno;
125 unsigned int mtu;
126 struct bio_dgram_sctp_sndinfo sndinfo;
127 struct bio_dgram_sctp_rcvinfo rcvinfo;
128 struct bio_dgram_sctp_prinfo prinfo;
129 BIO_dgram_sctp_notification_handler_fn handle_notifications;
130 void *notification_context;
131 int in_handshake;
132 int ccs_rcvd;
133 int ccs_sent;
134 int save_shutdown;
135 int peer_auth_tested;
136} bio_dgram_sctp_data;
137# endif
138
139const BIO_METHOD *BIO_s_datagram(void)
140{
141 return &methods_dgramp;
142}
143
144BIO *BIO_new_dgram(int fd, int close_flag)
145{
146 BIO *ret;
147
148 ret = BIO_new(BIO_s_datagram());
149 if (ret == NULL((void*)0))
150 return NULL((void*)0);
151 BIO_set_fd(ret, fd, close_flag)BIO_int_ctrl(ret,104,close_flag,fd);
152 return ret;
153}
154
155static int dgram_new(BIO *bi)
156{
157 bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data))CRYPTO_zalloc(sizeof(*data), "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 157)
;
158
159 if (data == NULL((void*)0))
160 return 0;
161 bi->ptr = data;
162 return 1;
163}
164
165static int dgram_free(BIO *a)
166{
167 bio_dgram_data *data;
168
169 if (a == NULL((void*)0))
170 return 0;
171 if (!dgram_clear(a))
172 return 0;
173
174 data = (bio_dgram_data *)a->ptr;
175 OPENSSL_free(data)CRYPTO_free(data, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 175)
;
176
177 return 1;
178}
179
180static int dgram_clear(BIO *a)
181{
182 if (a == NULL((void*)0))
183 return 0;
184 if (a->shutdown) {
185 if (a->init) {
186 BIO_closesocket(a->num);
187 }
188 a->init = 0;
189 a->flags = 0;
190 }
191 return 1;
192}
193
194static void dgram_adjust_rcv_timeout(BIO *b)
195{
196# if defined(SO_RCVTIMEO20)
197 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
198
199 /* Is a timer active? */
200 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
201 struct timeval timenow, timeleft;
202
203 /* Read current socket timeout */
204# ifdef OPENSSL_SYS_WINDOWS
205 int timeout;
206
207 int sz = sizeof(timeout);
208 if (getsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
209 (void *)&timeout, &sz) < 0) {
210 perror("getsockopt");
211 } else {
212 data->socket_timeout.tv_sec = timeout / 1000;
213 data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
214 }
215# else
216 socklen_t sz = sizeof(data->socket_timeout);
217 if (getsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
218 &(data->socket_timeout), &sz) < 0) {
219 perror("getsockopt");
220 } else
221 OPENSSL_assert(sz <= sizeof(data->socket_timeout))(void)((sz <= sizeof(data->socket_timeout)) ? 0 : (OPENSSL_die
("assertion failed: " "sz <= sizeof(data->socket_timeout)"
, "../deps/openssl/openssl/crypto/bio/bss_dgram.c", 221), 1))
;
222# endif
223
224 /* Get current time */
225 get_current_time(&timenow);
226
227 /* Calculate time left until timer expires */
228 memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
229 if (timeleft.tv_usec < timenow.tv_usec) {
230 timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec;
231 timeleft.tv_sec--;
232 } else {
233 timeleft.tv_usec -= timenow.tv_usec;
234 }
235 if (timeleft.tv_sec < timenow.tv_sec) {
236 timeleft.tv_sec = 0;
237 timeleft.tv_usec = 1;
238 } else {
239 timeleft.tv_sec -= timenow.tv_sec;
240 }
241
242 /*
243 * Adjust socket timeout if next handshake message timer will expire
244 * earlier.
245 */
246 if ((data->socket_timeout.tv_sec == 0
247 && data->socket_timeout.tv_usec == 0)
248 || (data->socket_timeout.tv_sec > timeleft.tv_sec)
249 || (data->socket_timeout.tv_sec == timeleft.tv_sec
250 && data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
251# ifdef OPENSSL_SYS_WINDOWS
252 timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
253 if (setsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
254 (void *)&timeout, sizeof(timeout)) < 0) {
255 perror("setsockopt");
256 }
257# else
258 if (setsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20, &timeleft,
259 sizeof(struct timeval)) < 0) {
260 perror("setsockopt");
261 }
262# endif
263 }
264 }
265# endif
266}
267
268static void dgram_reset_rcv_timeout(BIO *b)
269{
270# if defined(SO_RCVTIMEO20)
271 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
272
273 /* Is a timer active? */
274 if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
275# ifdef OPENSSL_SYS_WINDOWS
276 int timeout = data->socket_timeout.tv_sec * 1000 +
277 data->socket_timeout.tv_usec / 1000;
278 if (setsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
279 (void *)&timeout, sizeof(timeout)) < 0) {
280 perror("setsockopt");
281 }
282# else
283 if (setsockopt
284 (b->num, SOL_SOCKET1, SO_RCVTIMEO20, &(data->socket_timeout),
285 sizeof(struct timeval)) < 0) {
286 perror("setsockopt");
287 }
288# endif
289 }
290# endif
291}
292
293static int dgram_read(BIO *b, char *out, int outl)
294{
295 int ret = 0;
296 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
297 int flags = 0;
298
299 BIO_ADDR peer;
300 socklen_t len = sizeof(peer);
301
302 if (out != NULL((void*)0)) {
303 clear_socket_error()(*__errno_location ())=0;
304 memset(&peer, 0, sizeof(peer));
305 dgram_adjust_rcv_timeout(b);
306 if (data->peekmode)
307 flags = MSG_PEEKMSG_PEEK;
308 ret = recvfrom(b->num, out, outl, flags,
309 BIO_ADDR_sockaddr_noconst(&peer), &len);
310
311 if (!data->connected && ret >= 0)
312 BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER44, 0, &peer);
313
314 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
315 if (ret < 0) {
316 if (BIO_dgram_should_retry(ret)) {
317 BIO_set_retry_read(b)BIO_set_flags(b, (0x01|0x08));
318 data->_errno = get_last_socket_error()(*__errno_location ());
319 }
320 }
321
322 dgram_reset_rcv_timeout(b);
323 }
324 return ret;
325}
326
327static int dgram_write(BIO *b, const char *in, int inl)
328{
329 int ret;
330 bio_dgram_data *data = (bio_dgram_data *)b->ptr;
331 clear_socket_error()(*__errno_location ())=0;
332
333 if (data->connected)
334 ret = writesocket(b->num, in, inl)write((b->num),(in),(inl));
335 else {
336 int peerlen = BIO_ADDR_sockaddr_size(&data->peer);
337
338 ret = sendto(b->num, in, inl, 0,
339 BIO_ADDR_sockaddr(&data->peer), peerlen);
340 }
341
342 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
343 if (ret <= 0) {
344 if (BIO_dgram_should_retry(ret)) {
345 BIO_set_retry_write(b)BIO_set_flags(b, (0x02|0x08));
346 data->_errno = get_last_socket_error()(*__errno_location ());
347 }
348 }
349 return ret;
350}
351
352static long dgram_get_mtu_overhead(bio_dgram_data *data)
353{
354 long ret;
355
356 switch (BIO_ADDR_family(&data->peer)) {
357 case AF_INET2:
358 /*
359 * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP
360 */
361 ret = 28;
362 break;
363# if OPENSSL_USE_IPV61
364 case AF_INET610:
365 {
366# ifdef IN6_IS_ADDR_V4MAPPED
367 struct in6_addr tmp_addr;
368 if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL((void*)0))
369 && IN6_IS_ADDR_V4MAPPED(&tmp_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&tmp_addr); __a->__in6_u.__u6_addr32[0] == 0 &&
__a->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u
.__u6_addr32[2] == __bswap_32 (0xffff); }))
)
370 /*
371 * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP
372 */
373 ret = 28;
374 else
375# endif
376 /*
377 * Assume this is UDP - 40 bytes for IP, 8 bytes for UDP
378 */
379 ret = 48;
380 }
381 break;
382# endif
383 default:
384 /* We don't know. Go with the historical default */
385 ret = 28;
386 break;
387 }
388 return ret;
389}
390
391static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
392{
393 long ret = 1;
394 int *ip;
395 bio_dgram_data *data = NULL((void*)0);
396 int sockopt_val = 0;
397 int d_errno;
398# if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER10) || defined(IP_MTU14))
399 socklen_t sockopt_len; /* assume that system supporting IP_MTU is
400 * modern enough to define socklen_t */
401 socklen_t addr_len;
402 BIO_ADDR addr;
403# endif
404
405 data = (bio_dgram_data *)b->ptr;
406
407 switch (cmd) {
408 case BIO_CTRL_RESET1:
409 num = 0;
410 ret = 0;
411 break;
412 case BIO_CTRL_INFO3:
413 ret = 0;
414 break;
415 case BIO_C_SET_FD104:
416 dgram_clear(b);
417 b->num = *((int *)ptr);
418 b->shutdown = (int)num;
419 b->init = 1;
420 break;
421 case BIO_C_GET_FD105:
422 if (b->init) {
423 ip = (int *)ptr;
424 if (ip != NULL((void*)0))
425 *ip = b->num;
426 ret = b->num;
427 } else
428 ret = -1;
429 break;
430 case BIO_CTRL_GET_CLOSE8:
431 ret = b->shutdown;
432 break;
433 case BIO_CTRL_SET_CLOSE9:
434 b->shutdown = (int)num;
435 break;
436 case BIO_CTRL_PENDING10:
437 case BIO_CTRL_WPENDING13:
438 ret = 0;
439 break;
440 case BIO_CTRL_DUP12:
441 case BIO_CTRL_FLUSH11:
442 ret = 1;
443 break;
444 case BIO_CTRL_DGRAM_CONNECT31:
445 BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));
446 break;
447 /* (Linux)kernel sets DF bit on outgoing IP packets */
448 case BIO_CTRL_DGRAM_MTU_DISCOVER39:
449# if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER10) && defined(IP_PMTUDISC_DO2)
450 addr_len = (socklen_t) sizeof(addr);
451 memset(&addr, 0, sizeof(addr));
452 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
453 ret = 0;
454 break;
455 }
456 switch (addr.sa.sa_family) {
457 case AF_INET2:
458 sockopt_val = IP_PMTUDISC_DO2;
459 if ((ret = setsockopt(b->num, IPPROTO_IPIPPROTO_IP, IP_MTU_DISCOVER10,
460 &sockopt_val, sizeof(sockopt_val))) < 0)
461 perror("setsockopt");
462 break;
463# if OPENSSL_USE_IPV61 && defined(IPV6_MTU_DISCOVER23) && defined(IPV6_PMTUDISC_DO2)
464 case AF_INET610:
465 sockopt_val = IPV6_PMTUDISC_DO2;
466 if ((ret = setsockopt(b->num, IPPROTO_IPV6IPPROTO_IPV6, IPV6_MTU_DISCOVER23,
467 &sockopt_val, sizeof(sockopt_val))) < 0)
468 perror("setsockopt");
469 break;
470# endif
471 default:
472 ret = -1;
473 break;
474 }
475# else
476 ret = -1;
477# endif
478 break;
479 case BIO_CTRL_DGRAM_QUERY_MTU40:
480# if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU14)
481 addr_len = (socklen_t) sizeof(addr);
482 memset(&addr, 0, sizeof(addr));
483 if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
484 ret = 0;
485 break;
486 }
487 sockopt_len = sizeof(sockopt_val);
488 switch (addr.sa.sa_family) {
489 case AF_INET2:
490 if ((ret =
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'
491 getsockopt(b->num, IPPROTO_IPIPPROTO_IP, IP_MTU14, (void *)&sockopt_val,
492 &sockopt_len)) < 0 || sockopt_val < 0) {
493 ret = 0;
494 } else {
495 /*
496 * we assume that the transport protocol is UDP and no IP
497 * options are used.
498 */
499 data->mtu = sockopt_val - 8 - 20;
500 ret = data->mtu;
501 }
502 break;
503# if OPENSSL_USE_IPV61 && defined(IPV6_MTU24)
504 case AF_INET610:
505 if ((ret =
506 getsockopt(b->num, IPPROTO_IPV6IPPROTO_IPV6, IPV6_MTU24,
507 (void *)&sockopt_val, &sockopt_len)) < 0
508 || sockopt_val < 0) {
509 ret = 0;
510 } else {
511 /*
512 * we assume that the transport protocol is UDP and no IPV6
513 * options are used.
514 */
515 data->mtu = sockopt_val - 8 - 40;
516 ret = data->mtu;
517 }
518 break;
519# endif
520 default:
521 ret = 0;
522 break;
523 }
524# else
525 ret = 0;
526# endif
527 break;
528 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU47:
529 ret = -dgram_get_mtu_overhead(data);
530 switch (BIO_ADDR_family(&data->peer)) {
531 case AF_INET2:
532 ret += 576;
533 break;
534# if OPENSSL_USE_IPV61
535 case AF_INET610:
536 {
537# ifdef IN6_IS_ADDR_V4MAPPED
538 struct in6_addr tmp_addr;
539 if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL((void*)0))
540 && IN6_IS_ADDR_V4MAPPED(&tmp_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&tmp_addr); __a->__in6_u.__u6_addr32[0] == 0 &&
__a->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u
.__u6_addr32[2] == __bswap_32 (0xffff); }))
)
541 ret += 576;
542 else
543# endif
544 ret += 1280;
545 }
546 break;
547# endif
548 default:
549 ret += 576;
550 break;
551 }
552 break;
553 case BIO_CTRL_DGRAM_GET_MTU41:
554 return data->mtu;
555 case BIO_CTRL_DGRAM_SET_MTU42:
556 data->mtu = num;
557 ret = num;
558 break;
559 case BIO_CTRL_DGRAM_SET_CONNECTED32:
560 if (ptr != NULL((void*)0)) {
561 data->connected = 1;
562 BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));
563 } else {
564 data->connected = 0;
565 memset(&data->peer, 0, sizeof(data->peer));
566 }
567 break;
568 case BIO_CTRL_DGRAM_GET_PEER46:
569 ret = BIO_ADDR_sockaddr_size(&data->peer);
570 /* FIXME: if num < ret, we will only return part of an address.
571 That should bee an error, no? */
572 if (num == 0 || num > ret)
573 num = ret;
574 memcpy(ptr, &data->peer, (ret = num));
575 break;
576 case BIO_CTRL_DGRAM_SET_PEER44:
577 BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr));
578 break;
579 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT45:
580 memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
581 break;
582# if defined(SO_RCVTIMEO20)
583 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT33:
584# ifdef OPENSSL_SYS_WINDOWS
585 {
586 struct timeval *tv = (struct timeval *)ptr;
587 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
588 if (setsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
589 (void *)&timeout, sizeof(timeout)) < 0) {
590 perror("setsockopt");
591 ret = -1;
592 }
593 }
594# else
595 if (setsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20, ptr,
596 sizeof(struct timeval)) < 0) {
597 perror("setsockopt");
598 ret = -1;
599 }
600# endif
601 break;
602 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT34:
603 {
604# ifdef OPENSSL_SYS_WINDOWS
605 int sz = 0;
606 int timeout;
607 struct timeval *tv = (struct timeval *)ptr;
608
609 sz = sizeof(timeout);
610 if (getsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
611 (void *)&timeout, &sz) < 0) {
612 perror("getsockopt");
613 ret = -1;
614 } else {
615 tv->tv_sec = timeout / 1000;
616 tv->tv_usec = (timeout % 1000) * 1000;
617 ret = sizeof(*tv);
618 }
619# else
620 socklen_t sz = sizeof(struct timeval);
621 if (getsockopt(b->num, SOL_SOCKET1, SO_RCVTIMEO20,
622 ptr, &sz) < 0) {
623 perror("getsockopt");
624 ret = -1;
625 } else {
626 OPENSSL_assert(sz <= sizeof(struct timeval))(void)((sz <= sizeof(struct timeval)) ? 0 : (OPENSSL_die("assertion failed: "
"sz <= sizeof(struct timeval)", "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 626), 1))
;
627 ret = (int)sz;
628 }
629# endif
630 }
631 break;
632# endif
633# if defined(SO_SNDTIMEO21)
634 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT35:
635# ifdef OPENSSL_SYS_WINDOWS
636 {
637 struct timeval *tv = (struct timeval *)ptr;
638 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
639 if (setsockopt(b->num, SOL_SOCKET1, SO_SNDTIMEO21,
640 (void *)&timeout, sizeof(timeout)) < 0) {
641 perror("setsockopt");
642 ret = -1;
643 }
644 }
645# else
646 if (setsockopt(b->num, SOL_SOCKET1, SO_SNDTIMEO21, ptr,
647 sizeof(struct timeval)) < 0) {
648 perror("setsockopt");
649 ret = -1;
650 }
651# endif
652 break;
653 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT36:
654 {
655# ifdef OPENSSL_SYS_WINDOWS
656 int sz = 0;
657 int timeout;
658 struct timeval *tv = (struct timeval *)ptr;
659
660 sz = sizeof(timeout);
661 if (getsockopt(b->num, SOL_SOCKET1, SO_SNDTIMEO21,
662 (void *)&timeout, &sz) < 0) {
663 perror("getsockopt");
664 ret = -1;
665 } else {
666 tv->tv_sec = timeout / 1000;
667 tv->tv_usec = (timeout % 1000) * 1000;
668 ret = sizeof(*tv);
669 }
670# else
671 socklen_t sz = sizeof(struct timeval);
672 if (getsockopt(b->num, SOL_SOCKET1, SO_SNDTIMEO21,
673 ptr, &sz) < 0) {
674 perror("getsockopt");
675 ret = -1;
676 } else {
677 OPENSSL_assert(sz <= sizeof(struct timeval))(void)((sz <= sizeof(struct timeval)) ? 0 : (OPENSSL_die("assertion failed: "
"sz <= sizeof(struct timeval)", "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 677), 1))
;
678 ret = (int)sz;
679 }
680# endif
681 }
682 break;
683# endif
684 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP38:
685 /* fall-through */
686 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP37:
687# ifdef OPENSSL_SYS_WINDOWS
688 d_errno = (data->_errno == WSAETIMEDOUT);
689# else
690 d_errno = (data->_errno == EAGAIN11);
691# endif
692 if (d_errno) {
693 ret = 1;
694 data->_errno = 0;
695 } else
696 ret = 0;
697 break;
698# ifdef EMSGSIZE90
699 case BIO_CTRL_DGRAM_MTU_EXCEEDED43:
700 if (data->_errno == EMSGSIZE90) {
701 ret = 1;
702 data->_errno = 0;
703 } else
704 ret = 0;
705 break;
706# endif
707 case BIO_CTRL_DGRAM_SET_DONT_FRAG48:
708 sockopt_val = num ? 1 : 0;
709
710 switch (data->peer.sa.sa_family) {
711 case AF_INET2:
712# if defined(IP_DONTFRAG)
713 if ((ret = setsockopt(b->num, IPPROTO_IPIPPROTO_IP, IP_DONTFRAG,
714 &sockopt_val, sizeof(sockopt_val))) < 0) {
715 perror("setsockopt");
716 ret = -1;
717 }
718# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER10) && defined (IP_PMTUDISC_PROBE3)
719 if ((sockopt_val = num ? IP_PMTUDISC_PROBE3 : IP_PMTUDISC_DONT0),
720 (ret = setsockopt(b->num, IPPROTO_IPIPPROTO_IP, IP_MTU_DISCOVER10,
721 &sockopt_val, sizeof(sockopt_val))) < 0) {
722 perror("setsockopt");
723 ret = -1;
724 }
725# elif defined(OPENSSL_SYS_WINDOWS) && defined(IP_DONTFRAGMENT)
726 if ((ret = setsockopt(b->num, IPPROTO_IPIPPROTO_IP, IP_DONTFRAGMENT,
727 (const char *)&sockopt_val,
728 sizeof(sockopt_val))) < 0) {
729 perror("setsockopt");
730 ret = -1;
731 }
732# else
733 ret = -1;
734# endif
735 break;
736# if OPENSSL_USE_IPV61
737 case AF_INET610:
738# if defined(IPV6_DONTFRAG62)
739 if ((ret = setsockopt(b->num, IPPROTO_IPV6IPPROTO_IPV6, IPV6_DONTFRAG62,
740 (const void *)&sockopt_val,
741 sizeof(sockopt_val))) < 0) {
742 perror("setsockopt");
743 ret = -1;
744 }
745# elif defined(OPENSSL_SYS_LINUX) && defined(IPV6_MTUDISCOVER)
746 if ((sockopt_val = num ? IP_PMTUDISC_PROBE3 : IP_PMTUDISC_DONT0),
747 (ret = setsockopt(b->num, IPPROTO_IPV6IPPROTO_IPV6, IPV6_MTU_DISCOVER23,
748 &sockopt_val, sizeof(sockopt_val))) < 0) {
749 perror("setsockopt");
750 ret = -1;
751 }
752# else
753 ret = -1;
754# endif
755 break;
756# endif
757 default:
758 ret = -1;
759 break;
760 }
761 break;
762 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD49:
763 ret = dgram_get_mtu_overhead(data);
764 break;
765
766 /*
767 * BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE is used here for compatibility
768 * reasons. When BIO_CTRL_DGRAM_SET_PEEK_MODE was first defined its value
769 * was incorrectly clashing with BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE. The
770 * value has been updated to a non-clashing value. However to preserve
771 * binary compatibility we now respond to both the old value and the new one
772 */
773 case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE50:
774 case BIO_CTRL_DGRAM_SET_PEEK_MODE71:
775 data->peekmode = (unsigned int)num;
776 break;
777 default:
778 ret = 0;
779 break;
780 }
781 return ret;
782}
783
784static int dgram_puts(BIO *bp, const char *str)
785{
786 int n, ret;
787
788 n = strlen(str);
789 ret = dgram_write(bp, str, n);
790 return ret;
791}
792
793# ifndef OPENSSL_NO_SCTP
794const BIO_METHOD *BIO_s_datagram_sctp(void)
795{
796 return &methods_dgramp_sctp;
797}
798
799BIO *BIO_new_dgram_sctp(int fd, int close_flag)
800{
801 BIO *bio;
802 int ret, optval = 20000;
803 int auth_data = 0, auth_forward = 0;
804 unsigned char *p;
805 struct sctp_authchunk auth;
806 struct sctp_authchunks *authchunks;
807 socklen_t sockopt_len;
808# ifdef SCTP_AUTHENTICATION_EVENT
809# ifdef SCTP_EVENT
810 struct sctp_event event;
811# else
812 struct sctp_event_subscribe event;
813# endif
814# endif
815
816 bio = BIO_new(BIO_s_datagram_sctp());
817 if (bio == NULL((void*)0))
818 return NULL((void*)0);
819 BIO_set_fd(bio, fd, close_flag)BIO_int_ctrl(bio,104,close_flag,fd);
820
821 /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
822 auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
823 ret =
824 setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth,
825 sizeof(struct sctp_authchunk));
826 if (ret < 0) {
827 BIO_vfree(bio);
828 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/bio/bss_dgram.c"
,828,__func__), ERR_set_error)
(ERR_LIB_BIO32, ERR_R_SYS_LIB(2 | (0x2 << 18L)),
829 "Ensure SCTP AUTH chunks are enabled in kernel");
830 return NULL((void*)0);
831 }
832 auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
833 ret =
834 setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth,
835 sizeof(struct sctp_authchunk));
836 if (ret < 0) {
837 BIO_vfree(bio);
838 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/bio/bss_dgram.c"
,838,__func__), ERR_set_error)
(ERR_LIB_BIO32, ERR_R_SYS_LIB(2 | (0x2 << 18L)),
839 "Ensure SCTP AUTH chunks are enabled in kernel");
840 return NULL((void*)0);
841 }
842
843 /*
844 * Test if activation was successful. When using accept(), SCTP-AUTH has
845 * to be activated for the listening socket already, otherwise the
846 * connected socket won't use it. Similarly with connect(): the socket
847 * prior to connection must be activated for SCTP-AUTH
848 */
849 sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
850 authchunks = OPENSSL_zalloc(sockopt_len)CRYPTO_zalloc(sockopt_len, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 850)
;
851 if (authchunks == NULL((void*)0)) {
852 BIO_vfree(bio);
853 return NULL((void*)0);
854 }
855 ret = getsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks,
856 &sockopt_len);
857 if (ret < 0) {
858 OPENSSL_free(authchunks)CRYPTO_free(authchunks, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 858)
;
859 BIO_vfree(bio);
860 return NULL((void*)0);
861 }
862
863 for (p = (unsigned char *)authchunks->gauth_chunks;
864 p < (unsigned char *)authchunks + sockopt_len;
865 p += sizeof(uint8_t)) {
866 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
867 auth_data = 1;
868 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
869 auth_forward = 1;
870 }
871
872 OPENSSL_free(authchunks)CRYPTO_free(authchunks, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 872)
;
873
874 if (!auth_data || !auth_forward) {
875 BIO_vfree(bio);
876 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/bio/bss_dgram.c"
,876,__func__), ERR_set_error)
(ERR_LIB_BIO32, ERR_R_SYS_LIB(2 | (0x2 << 18L)),
877 "Ensure SCTP AUTH chunks are enabled on the "
878 "underlying socket");
879 return NULL((void*)0);
880 }
881
882# ifdef SCTP_AUTHENTICATION_EVENT
883# ifdef SCTP_EVENT
884 memset(&event, 0, sizeof(event));
885 event.se_assoc_id = 0;
886 event.se_type = SCTP_AUTHENTICATION_EVENT;
887 event.se_on = 1;
888 ret =
889 setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENT, &event,
890 sizeof(struct sctp_event));
891 if (ret < 0) {
892 BIO_vfree(bio);
893 return NULL((void*)0);
894 }
895# else
896 sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
897 ret = getsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
898 if (ret < 0) {
899 BIO_vfree(bio);
900 return NULL((void*)0);
901 }
902
903 event.sctp_authentication_event = 1;
904
905 ret =
906 setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event,
907 sizeof(struct sctp_event_subscribe));
908 if (ret < 0) {
909 BIO_vfree(bio);
910 return NULL((void*)0);
911 }
912# endif
913# endif
914
915 /*
916 * Disable partial delivery by setting the min size larger than the max
917 * record size of 2^14 + 2048 + 13
918 */
919 ret =
920 setsockopt(fd, IPPROTO_SCTPIPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval,
921 sizeof(optval));
922 if (ret < 0) {
923 BIO_vfree(bio);
924 return NULL((void*)0);
925 }
926
927 return bio;
928}
929
930int BIO_dgram_is_sctp(BIO *bio)
931{
932 return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
933}
934
935static int dgram_sctp_new(BIO *bi)
936{
937 bio_dgram_sctp_data *data = NULL((void*)0);
938
939 bi->init = 0;
940 bi->num = 0;
941 if ((data = OPENSSL_zalloc(sizeof(*data))CRYPTO_zalloc(sizeof(*data), "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 941)
) == NULL((void*)0)) {
942 ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/bio/bss_dgram.c"
,942,__func__), ERR_set_error)((32),((256|((0x1 << 18L)
|(0x2 << 18L)))),((void*)0))
;
943 return 0;
944 }
945# ifdef SCTP_PR_SCTP_NONE
946 data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
947# endif
948 bi->ptr = data;
949
950 bi->flags = 0;
951 return 1;
952}
953
954static int dgram_sctp_free(BIO *a)
955{
956 bio_dgram_sctp_data *data;
957
958 if (a == NULL((void*)0))
959 return 0;
960 if (!dgram_clear(a))
961 return 0;
962
963 data = (bio_dgram_sctp_data *) a->ptr;
964 if (data != NULL((void*)0))
965 OPENSSL_free(data)CRYPTO_free(data, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 965)
;
966
967 return 1;
968}
969
970# ifdef SCTP_AUTHENTICATION_EVENT
971void dgram_sctp_handle_auth_free_key_event(BIO *b,
972 union sctp_notification *snp)
973{
974 int ret;
975 struct sctp_authkey_event *authkeyevent = &snp->sn_auth_event;
976
977 if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) {
978 struct sctp_authkeyid authkeyid;
979
980 /* delete key */
981 authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
982 ret = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
983 &authkeyid, sizeof(struct sctp_authkeyid));
984 }
985}
986# endif
987
988static int dgram_sctp_read(BIO *b, char *out, int outl)
989{
990 int ret = 0, n = 0, i, optval;
991 socklen_t optlen;
992 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
993 struct msghdr msg;
994 struct iovec iov;
995 struct cmsghdr *cmsg;
996 char cmsgbuf[512];
997
998 if (out != NULL((void*)0)) {
999 clear_socket_error()(*__errno_location ())=0;
1000
1001 do {
1002 memset(&data->rcvinfo, 0, sizeof(data->rcvinfo));
1003 iov.iov_base = out;
1004 iov.iov_len = outl;
1005 msg.msg_name = NULL((void*)0);
1006 msg.msg_namelen = 0;
1007 msg.msg_iov = &iov;
1008 msg.msg_iovlen = 1;
1009 msg.msg_control = cmsgbuf;
1010 msg.msg_controllen = 512;
1011 msg.msg_flags = 0;
1012 n = recvmsg(b->num, &msg, 0);
1013
1014 if (n <= 0) {
1015 if (n < 0)
1016 ret = n;
1017 break;
1018 }
1019
1020 if (msg.msg_controllen > 0) {
1021 for (cmsg = CMSG_FIRSTHDR(&msg)((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr
) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr
*) 0)
; cmsg;
1022 cmsg = CMSG_NXTHDR(&msg, cmsg)__cmsg_nxthdr (&msg, cmsg)) {
1023 if (cmsg->cmsg_level != IPPROTO_SCTPIPPROTO_SCTP)
1024 continue;
1025# ifdef SCTP_RCVINFO
1026 if (cmsg->cmsg_type == SCTP_RCVINFO) {
1027 struct sctp_rcvinfo *rcvinfo;
1028
1029 rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg)((cmsg)->__cmsg_data);
1030 data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
1031 data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
1032 data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
1033 data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
1034 data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
1035 data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
1036 data->rcvinfo.rcv_context = rcvinfo->rcv_context;
1037 }
1038# endif
1039# ifdef SCTP_SNDRCV
1040 if (cmsg->cmsg_type == SCTP_SNDRCV) {
1041 struct sctp_sndrcvinfo *sndrcvinfo;
1042
1043 sndrcvinfo =
1044 (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg)((cmsg)->__cmsg_data);
1045 data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
1046 data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
1047 data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
1048 data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
1049 data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
1050 data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
1051 data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
1052 }
1053# endif
1054 }
1055 }
1056
1057 if (msg.msg_flags & MSG_NOTIFICATION) {
1058 union sctp_notification snp;
1059
1060 memcpy(&snp, out, sizeof(snp));
1061 if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
1062# ifdef SCTP_EVENT
1063 struct sctp_event event;
1064# else
1065 struct sctp_event_subscribe event;
1066 socklen_t eventsize;
1067# endif
1068
1069 /* disable sender dry event */
1070# ifdef SCTP_EVENT
1071 memset(&event, 0, sizeof(event));
1072 event.se_assoc_id = 0;
1073 event.se_type = SCTP_SENDER_DRY_EVENT;
1074 event.se_on = 0;
1075 i = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENT, &event,
1076 sizeof(struct sctp_event));
1077 if (i < 0) {
1078 ret = i;
1079 break;
1080 }
1081# else
1082 eventsize = sizeof(struct sctp_event_subscribe);
1083 i = getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event,
1084 &eventsize);
1085 if (i < 0) {
1086 ret = i;
1087 break;
1088 }
1089
1090 event.sctp_sender_dry_event = 0;
1091
1092 i = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event,
1093 sizeof(struct sctp_event_subscribe));
1094 if (i < 0) {
1095 ret = i;
1096 break;
1097 }
1098# endif
1099 }
1100# ifdef SCTP_AUTHENTICATION_EVENT
1101 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1102 dgram_sctp_handle_auth_free_key_event(b, &snp);
1103# endif
1104
1105 if (data->handle_notifications != NULL((void*)0))
1106 data->handle_notifications(b, data->notification_context,
1107 (void *)out);
1108
1109 memset(&snp, 0, sizeof(snp));
1110 memset(out, 0, outl);
1111 } else {
1112 ret += n;
1113 }
1114 }
1115 while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EORMSG_EOR)
1116 && (ret < outl));
1117
1118 if (ret > 0 && !(msg.msg_flags & MSG_EORMSG_EOR)) {
1119 /* Partial message read, this should never happen! */
1120
1121 /*
1122 * The buffer was too small, this means the peer sent a message
1123 * that was larger than allowed.
1124 */
1125 if (ret == outl)
1126 return -1;
1127
1128 /*
1129 * Test if socket buffer can handle max record size (2^14 + 2048
1130 * + 13)
1131 */
1132 optlen = (socklen_t) sizeof(int);
1133 ret = getsockopt(b->num, SOL_SOCKET1, SO_RCVBUF8, &optval, &optlen);
1134 if (ret >= 0)
1135 OPENSSL_assert(optval >= 18445)(void)((optval >= 18445) ? 0 : (OPENSSL_die("assertion failed: "
"optval >= 18445", "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 1135), 1))
;
1136
1137 /*
1138 * Test if SCTP doesn't partially deliver below max record size
1139 * (2^14 + 2048 + 13)
1140 */
1141 optlen = (socklen_t) sizeof(int);
1142 ret =
1143 getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
1144 &optval, &optlen);
1145 if (ret >= 0)
1146 OPENSSL_assert(optval >= 18445)(void)((optval >= 18445) ? 0 : (OPENSSL_die("assertion failed: "
"optval >= 18445", "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 1146), 1))
;
1147
1148 /*
1149 * Partially delivered notification??? Probably a bug....
1150 */
1151 OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION))(void)((!(msg.msg_flags & MSG_NOTIFICATION)) ? 0 : (OPENSSL_die
("assertion failed: " "!(msg.msg_flags & MSG_NOTIFICATION)"
, "../deps/openssl/openssl/crypto/bio/bss_dgram.c", 1151), 1)
)
;
1152
1153 /*
1154 * Everything seems ok till now, so it's most likely a message
1155 * dropped by PR-SCTP.
1156 */
1157 memset(out, 0, outl);
1158 BIO_set_retry_read(b)BIO_set_flags(b, (0x01|0x08));
1159 return -1;
1160 }
1161
1162 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
1163 if (ret < 0) {
1164 if (BIO_dgram_should_retry(ret)) {
1165 BIO_set_retry_read(b)BIO_set_flags(b, (0x01|0x08));
1166 data->_errno = get_last_socket_error()(*__errno_location ());
1167 }
1168 }
1169
1170 /* Test if peer uses SCTP-AUTH before continuing */
1171 if (!data->peer_auth_tested) {
1172 int ii, auth_data = 0, auth_forward = 0;
1173 unsigned char *p;
1174 struct sctp_authchunks *authchunks;
1175
1176 optlen =
1177 (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
1178 authchunks = OPENSSL_malloc(optlen)CRYPTO_malloc(optlen, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 1178)
;
1179 if (authchunks == NULL((void*)0)) {
1180 ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/bio/bss_dgram.c"
,1180,__func__), ERR_set_error)((32),((256|((0x1 << 18L
)|(0x2 << 18L)))),((void*)0))
;
1181 return -1;
1182 }
1183 memset(authchunks, 0, optlen);
1184 ii = getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS,
1185 authchunks, &optlen);
1186
1187 if (ii >= 0)
1188 for (p = (unsigned char *)authchunks->gauth_chunks;
1189 p < (unsigned char *)authchunks + optlen;
1190 p += sizeof(uint8_t)) {
1191 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
1192 auth_data = 1;
1193 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
1194 auth_forward = 1;
1195 }
1196
1197 OPENSSL_free(authchunks)CRYPTO_free(authchunks, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 1197)
;
1198
1199 if (!auth_data || !auth_forward) {
1200 ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/bio/bss_dgram.c"
,1200,__func__), ERR_set_error)((32),(103),((void*)0))
;
1201 return -1;
1202 }
1203
1204 data->peer_auth_tested = 1;
1205 }
1206 }
1207 return ret;
1208}
1209
1210/*
1211 * dgram_sctp_write - send message on SCTP socket
1212 * @b: BIO to write to
1213 * @in: data to send
1214 * @inl: amount of bytes in @in to send
1215 *
1216 * Returns -1 on error or the sent amount of bytes on success
1217 */
1218static int dgram_sctp_write(BIO *b, const char *in, int inl)
1219{
1220 int ret;
1221 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1222 struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
1223 struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
1224 struct bio_dgram_sctp_sndinfo handshake_sinfo;
1225 struct iovec iov[1];
1226 struct msghdr msg;
1227 struct cmsghdr *cmsg;
1228# if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1229 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))((((sizeof(struct sctp_sndinfo)) + sizeof (size_t) - 1) &
(size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr
)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1
)))
+
1230 CMSG_SPACE(sizeof(struct sctp_prinfo))((((sizeof(struct sctp_prinfo)) + sizeof (size_t) - 1) & (
size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr))
+ sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)
))
];
1231 struct sctp_sndinfo *sndinfo;
1232 struct sctp_prinfo *prinfo;
1233# else
1234 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))((((sizeof(struct sctp_sndrcvinfo)) + sizeof (size_t) - 1) &
(size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr
)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1
)))
];
1235 struct sctp_sndrcvinfo *sndrcvinfo;
1236# endif
1237
1238 clear_socket_error()(*__errno_location ())=0;
1239
1240 /*
1241 * If we're send anything else than application data, disable all user
1242 * parameters and flags.
1243 */
1244 if (in[0] != 23) {
1245 memset(&handshake_sinfo, 0, sizeof(handshake_sinfo));
1246# ifdef SCTP_SACK_IMMEDIATELY
1247 handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
1248# endif
1249 sinfo = &handshake_sinfo;
1250 }
1251
1252 /* We can only send a shutdown alert if the socket is dry */
1253 if (data->save_shutdown) {
1254 ret = BIO_dgram_sctp_wait_for_dry(b);
1255 if (ret < 0)
1256 return -1;
1257 if (ret == 0) {
1258 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
1259 BIO_set_retry_write(b)BIO_set_flags(b, (0x02|0x08));
1260 return -1;
1261 }
1262 }
1263
1264 iov[0].iov_base = (char *)in;
1265 iov[0].iov_len = inl;
1266 msg.msg_name = NULL((void*)0);
1267 msg.msg_namelen = 0;
1268 msg.msg_iov = iov;
1269 msg.msg_iovlen = 1;
1270 msg.msg_control = (caddr_t) cmsgbuf;
1271 msg.msg_controllen = 0;
1272 msg.msg_flags = 0;
1273# if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1274 cmsg = (struct cmsghdr *)cmsgbuf;
1275 cmsg->cmsg_level = IPPROTO_SCTPIPPROTO_SCTP;
1276 cmsg->cmsg_type = SCTP_SNDINFO;
1277 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (sizeof(struct sctp_sndinfo)))
;
1278 sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg)((cmsg)->__cmsg_data);
1279 memset(sndinfo, 0, sizeof(*sndinfo));
1280 sndinfo->snd_sid = sinfo->snd_sid;
1281 sndinfo->snd_flags = sinfo->snd_flags;
1282 sndinfo->snd_ppid = sinfo->snd_ppid;
1283 sndinfo->snd_context = sinfo->snd_context;
1284 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo))((((sizeof(struct sctp_sndinfo)) + sizeof (size_t) - 1) &
(size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr
)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1
)))
;
1285
1286 cmsg =
1287 (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))((((sizeof(struct sctp_sndinfo)) + sizeof (size_t) - 1) &
(size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr
)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1
)))
];
1288 cmsg->cmsg_level = IPPROTO_SCTPIPPROTO_SCTP;
1289 cmsg->cmsg_type = SCTP_PRINFO;
1290 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (sizeof(struct sctp_prinfo)))
;
1291 prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg)((cmsg)->__cmsg_data);
1292 memset(prinfo, 0, sizeof(*prinfo));
1293 prinfo->pr_policy = pinfo->pr_policy;
1294 prinfo->pr_value = pinfo->pr_value;
1295 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo))((((sizeof(struct sctp_prinfo)) + sizeof (size_t) - 1) & (
size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr))
+ sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)
))
;
1296# else
1297 cmsg = (struct cmsghdr *)cmsgbuf;
1298 cmsg->cmsg_level = IPPROTO_SCTPIPPROTO_SCTP;
1299 cmsg->cmsg_type = SCTP_SNDRCV;
1300 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (sizeof(struct sctp_sndrcvinfo)))
;
1301 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg)((cmsg)->__cmsg_data);
1302 memset(sndrcvinfo, 0, sizeof(*sndrcvinfo));
1303 sndrcvinfo->sinfo_stream = sinfo->snd_sid;
1304 sndrcvinfo->sinfo_flags = sinfo->snd_flags;
1305# ifdef __FreeBSD__
1306 sndrcvinfo->sinfo_flags |= pinfo->pr_policy;
1307# endif
1308 sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
1309 sndrcvinfo->sinfo_context = sinfo->snd_context;
1310 sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
1311 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))((((sizeof(struct sctp_sndrcvinfo)) + sizeof (size_t) - 1) &
(size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr
)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1
)))
;
1312# endif
1313
1314 ret = sendmsg(b->num, &msg, 0);
1315
1316 BIO_clear_retry_flags(b)BIO_clear_flags(b, ((0x01|0x02|0x04)|0x08));
1317 if (ret <= 0) {
1318 if (BIO_dgram_should_retry(ret)) {
1319 BIO_set_retry_write(b)BIO_set_flags(b, (0x02|0x08));
1320 data->_errno = get_last_socket_error()(*__errno_location ());
1321 }
1322 }
1323 return ret;
1324}
1325
1326static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
1327{
1328 long ret = 1;
1329 bio_dgram_sctp_data *data = NULL((void*)0);
1330 socklen_t sockopt_len = 0;
1331 struct sctp_authkeyid authkeyid;
1332 struct sctp_authkey *authkey = NULL((void*)0);
1333
1334 data = (bio_dgram_sctp_data *) b->ptr;
1335
1336 switch (cmd) {
1337 case BIO_CTRL_DGRAM_QUERY_MTU40:
1338 /*
1339 * Set to maximum (2^14) and ignore user input to enable transport
1340 * protocol fragmentation. Returns always 2^14.
1341 */
1342 data->mtu = 16384;
1343 ret = data->mtu;
1344 break;
1345 case BIO_CTRL_DGRAM_SET_MTU42:
1346 /*
1347 * Set to maximum (2^14) and ignore input to enable transport
1348 * protocol fragmentation. Returns always 2^14.
1349 */
1350 data->mtu = 16384;
1351 ret = data->mtu;
1352 break;
1353 case BIO_CTRL_DGRAM_SET_CONNECTED32:
1354 case BIO_CTRL_DGRAM_CONNECT31:
1355 /* Returns always -1. */
1356 ret = -1;
1357 break;
1358 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT45:
1359 /*
1360 * SCTP doesn't need the DTLS timer Returns always 1.
1361 */
1362 break;
1363 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD49:
1364 /*
1365 * We allow transport protocol fragmentation so this is irrelevant
1366 */
1367 ret = 0;
1368 break;
1369 case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE50:
1370 if (num > 0)
1371 data->in_handshake = 1;
1372 else
1373 data->in_handshake = 0;
1374
1375 ret =
1376 setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_NODELAY,
1377 &data->in_handshake, sizeof(int));
1378 break;
1379 case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
1380 /*
1381 * New shared key for SCTP AUTH. Returns 0 on success, -1 otherwise.
1382 */
1383
1384 /* Get active key */
1385 sockopt_len = sizeof(struct sctp_authkeyid);
1386 ret =
1387 getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid,
1388 &sockopt_len);
1389 if (ret < 0)
1390 break;
1391
1392 /* Add new key */
1393 sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
1394 authkey = OPENSSL_malloc(sockopt_len)CRYPTO_malloc(sockopt_len, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 1394)
;
1395 if (authkey == NULL((void*)0)) {
1396 ret = -1;
1397 break;
1398 }
1399 memset(authkey, 0, sockopt_len);
1400 authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
1401# ifndef __FreeBSD__
1402 /*
1403 * This field is missing in FreeBSD 8.2 and earlier, and FreeBSD 8.3
1404 * and higher work without it.
1405 */
1406 authkey->sca_keylength = 64;
1407# endif
1408 memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
1409
1410 ret =
1411 setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_KEY, authkey,
1412 sockopt_len);
1413 OPENSSL_free(authkey)CRYPTO_free(authkey, "../deps/openssl/openssl/crypto/bio/bss_dgram.c"
, 1413)
;
1414 authkey = NULL((void*)0);
1415 if (ret < 0)
1416 break;
1417
1418 /* Reset active key */
1419 ret = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1420 &authkeyid, sizeof(struct sctp_authkeyid));
1421 if (ret < 0)
1422 break;
1423
1424 break;
1425 case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
1426 /* Returns 0 on success, -1 otherwise. */
1427
1428 /* Get active key */
1429 sockopt_len = sizeof(struct sctp_authkeyid);
1430 ret =
1431 getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid,
1432 &sockopt_len);
1433 if (ret < 0)
1434 break;
1435
1436 /* Set active key */
1437 authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
1438 ret = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1439 &authkeyid, sizeof(struct sctp_authkeyid));
1440 if (ret < 0)
1441 break;
1442
1443 /*
1444 * CCS has been sent, so remember that and fall through to check if
1445 * we need to deactivate an old key
1446 */
1447 data->ccs_sent = 1;
1448 /* fall-through */
1449
1450 case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
1451 /* Returns 0 on success, -1 otherwise. */
1452
1453 /*
1454 * Has this command really been called or is this just a
1455 * fall-through?
1456 */
1457 if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
1458 data->ccs_rcvd = 1;
1459
1460 /*
1461 * CSS has been both, received and sent, so deactivate an old key
1462 */
1463 if (data->ccs_rcvd == 1 && data->ccs_sent == 1) {
1464 /* Get active key */
1465 sockopt_len = sizeof(struct sctp_authkeyid);
1466 ret =
1467 getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1468 &authkeyid, &sockopt_len);
1469 if (ret < 0)
1470 break;
1471
1472 /*
1473 * Deactivate key or delete second last key if
1474 * SCTP_AUTHENTICATION_EVENT is not available.
1475 */
1476 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1477# ifdef SCTP_AUTH_DEACTIVATE_KEY
1478 sockopt_len = sizeof(struct sctp_authkeyid);
1479 ret = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,
1480 &authkeyid, sockopt_len);
1481 if (ret < 0)
1482 break;
1483# endif
1484# ifndef SCTP_AUTHENTICATION_EVENT
1485 if (authkeyid.scact_keynumber > 0) {
1486 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1487 ret = setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
1488 &authkeyid, sizeof(struct sctp_authkeyid));
1489 if (ret < 0)
1490 break;
1491 }
1492# endif
1493
1494 data->ccs_rcvd = 0;
1495 data->ccs_sent = 0;
1496 }
1497 break;
1498 case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
1499 /* Returns the size of the copied struct. */
1500 if (num > (long)sizeof(struct bio_dgram_sctp_sndinfo))
1501 num = sizeof(struct bio_dgram_sctp_sndinfo);
1502
1503 memcpy(ptr, &(data->sndinfo), num);
1504 ret = num;
1505 break;
1506 case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
1507 /* Returns the size of the copied struct. */
1508 if (num > (long)sizeof(struct bio_dgram_sctp_sndinfo))
1509 num = sizeof(struct bio_dgram_sctp_sndinfo);
1510
1511 memcpy(&(data->sndinfo), ptr, num);
1512 break;
1513 case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
1514 /* Returns the size of the copied struct. */
1515 if (num > (long)sizeof(struct bio_dgram_sctp_rcvinfo))
1516 num = sizeof(struct bio_dgram_sctp_rcvinfo);
1517
1518 memcpy(ptr, &data->rcvinfo, num);
1519
1520 ret = num;
1521 break;
1522 case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
1523 /* Returns the size of the copied struct. */
1524 if (num > (long)sizeof(struct bio_dgram_sctp_rcvinfo))
1525 num = sizeof(struct bio_dgram_sctp_rcvinfo);
1526
1527 memcpy(&(data->rcvinfo), ptr, num);
1528 break;
1529 case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
1530 /* Returns the size of the copied struct. */
1531 if (num > (long)sizeof(struct bio_dgram_sctp_prinfo))
1532 num = sizeof(struct bio_dgram_sctp_prinfo);
1533
1534 memcpy(ptr, &(data->prinfo), num);
1535 ret = num;
1536 break;
1537 case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
1538 /* Returns the size of the copied struct. */
1539 if (num > (long)sizeof(struct bio_dgram_sctp_prinfo))
1540 num = sizeof(struct bio_dgram_sctp_prinfo);
1541
1542 memcpy(&(data->prinfo), ptr, num);
1543 break;
1544 case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
1545 /* Returns always 1. */
1546 if (num > 0)
1547 data->save_shutdown = 1;
1548 else
1549 data->save_shutdown = 0;
1550 break;
1551 case BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY77:
1552 return dgram_sctp_wait_for_dry(b);
1553 case BIO_CTRL_DGRAM_SCTP_MSG_WAITING78:
1554 return dgram_sctp_msg_waiting(b);
1555
1556 default:
1557 /*
1558 * Pass to default ctrl function to process SCTP unspecific commands
1559 */
1560 ret = dgram_ctrl(b, cmd, num, ptr);
1561 break;
1562 }
1563 return ret;
1564}
1565
1566int BIO_dgram_sctp_notification_cb(BIO *b,
1567 BIO_dgram_sctp_notification_handler_fn handle_notifications,
1568 void *context)
1569{
1570 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1571
1572 if (handle_notifications != NULL((void*)0)) {
1573 data->handle_notifications = handle_notifications;
1574 data->notification_context = context;
1575 } else
1576 return -1;
1577
1578 return 0;
1579}
1580
1581/*
1582 * BIO_dgram_sctp_wait_for_dry - Wait for SCTP SENDER_DRY event
1583 * @b: The BIO to check for the dry event
1584 *
1585 * Wait until the peer confirms all packets have been received, and so that
1586 * our kernel doesn't have anything to send anymore. This is only received by
1587 * the peer's kernel, not the application.
1588 *
1589 * Returns:
1590 * -1 on error
1591 * 0 when not dry yet
1592 * 1 when dry
1593 */
1594int BIO_dgram_sctp_wait_for_dry(BIO *b)
1595{
1596 return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY77, 0, NULL((void*)0));
1597}
1598
1599static int dgram_sctp_wait_for_dry(BIO *b)
1600{
1601 int is_dry = 0;
1602 int sockflags = 0;
1603 int n, ret;
1604 union sctp_notification snp;
1605 struct msghdr msg;
1606 struct iovec iov;
1607# ifdef SCTP_EVENT
1608 struct sctp_event event;
1609# else
1610 struct sctp_event_subscribe event;
1611 socklen_t eventsize;
1612# endif
1613 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1614
1615 /* set sender dry event */
1616# ifdef SCTP_EVENT
1617 memset(&event, 0, sizeof(event));
1618 event.se_assoc_id = 0;
1619 event.se_type = SCTP_SENDER_DRY_EVENT;
1620 event.se_on = 1;
1621 ret =
1622 setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENT, &event,
1623 sizeof(struct sctp_event));
1624# else
1625 eventsize = sizeof(struct sctp_event_subscribe);
1626 ret = getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1627 if (ret < 0)
1628 return -1;
1629
1630 event.sctp_sender_dry_event = 1;
1631
1632 ret =
1633 setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event,
1634 sizeof(struct sctp_event_subscribe));
1635# endif
1636 if (ret < 0)
1637 return -1;
1638
1639 /* peek for notification */
1640 memset(&snp, 0, sizeof(snp));
1641 iov.iov_base = (char *)&snp;
1642 iov.iov_len = sizeof(union sctp_notification);
1643 msg.msg_name = NULL((void*)0);
1644 msg.msg_namelen = 0;
1645 msg.msg_iov = &iov;
1646 msg.msg_iovlen = 1;
1647 msg.msg_control = NULL((void*)0);
1648 msg.msg_controllen = 0;
1649 msg.msg_flags = 0;
1650
1651 n = recvmsg(b->num, &msg, MSG_PEEKMSG_PEEK);
1652 if (n <= 0) {
1653 if ((n < 0) && (get_last_socket_error()(*__errno_location ()) != EAGAIN11)
1654 && (get_last_socket_error()(*__errno_location ()) != EWOULDBLOCK11))
1655 return -1;
1656 else
1657 return 0;
1658 }
1659
1660 /* if we find a notification, process it and try again if necessary */
1661 while (msg.msg_flags & MSG_NOTIFICATION) {
1662 memset(&snp, 0, sizeof(snp));
1663 iov.iov_base = (char *)&snp;
1664 iov.iov_len = sizeof(union sctp_notification);
1665 msg.msg_name = NULL((void*)0);
1666 msg.msg_namelen = 0;
1667 msg.msg_iov = &iov;
1668 msg.msg_iovlen = 1;
1669 msg.msg_control = NULL((void*)0);
1670 msg.msg_controllen = 0;
1671 msg.msg_flags = 0;
1672
1673 n = recvmsg(b->num, &msg, 0);
1674 if (n <= 0) {
1675 if ((n < 0) && (get_last_socket_error()(*__errno_location ()) != EAGAIN11)
1676 && (get_last_socket_error()(*__errno_location ()) != EWOULDBLOCK11))
1677 return -1;
1678 else
1679 return is_dry;
1680 }
1681
1682 if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
1683 is_dry = 1;
1684
1685 /* disable sender dry event */
1686# ifdef SCTP_EVENT
1687 memset(&event, 0, sizeof(event));
1688 event.se_assoc_id = 0;
1689 event.se_type = SCTP_SENDER_DRY_EVENT;
1690 event.se_on = 0;
1691 ret =
1692 setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENT, &event,
1693 sizeof(struct sctp_event));
1694# else
1695 eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
1696 ret =
1697 getsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event,
1698 &eventsize);
1699 if (ret < 0)
1700 return -1;
1701
1702 event.sctp_sender_dry_event = 0;
1703
1704 ret =
1705 setsockopt(b->num, IPPROTO_SCTPIPPROTO_SCTP, SCTP_EVENTS, &event,
1706 sizeof(struct sctp_event_subscribe));
1707# endif
1708 if (ret < 0)
1709 return -1;
1710 }
1711# ifdef SCTP_AUTHENTICATION_EVENT
1712 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1713 dgram_sctp_handle_auth_free_key_event(b, &snp);
1714# endif
1715
1716 if (data->handle_notifications != NULL((void*)0))
1717 data->handle_notifications(b, data->notification_context,
1718 (void *)&snp);
1719
1720 /* found notification, peek again */
1721 memset(&snp, 0, sizeof(snp));
1722 iov.iov_base = (char *)&snp;
1723 iov.iov_len = sizeof(union sctp_notification);
1724 msg.msg_name = NULL((void*)0);
1725 msg.msg_namelen = 0;
1726 msg.msg_iov = &iov;
1727 msg.msg_iovlen = 1;
1728 msg.msg_control = NULL((void*)0);
1729 msg.msg_controllen = 0;
1730 msg.msg_flags = 0;
1731
1732 /* if we have seen the dry already, don't wait */
1733 if (is_dry) {
1734 sockflags = fcntl(b->num, F_GETFL, 0);
1735 fcntl(b->num, F_SETFL, O_NONBLOCK);
1736 }
1737
1738 n = recvmsg(b->num, &msg, MSG_PEEKMSG_PEEK);
1739
1740 if (is_dry) {
1741 fcntl(b->num, F_SETFL, sockflags);
1742 }
1743
1744 if (n <= 0) {
1745 if ((n < 0) && (get_last_socket_error()(*__errno_location ()) != EAGAIN11)
1746 && (get_last_socket_error()(*__errno_location ()) != EWOULDBLOCK11))
1747 return -1;
1748 else
1749 return is_dry;
1750 }
1751 }
1752
1753 /* read anything else */
1754 return is_dry;
1755}
1756
1757int BIO_dgram_sctp_msg_waiting(BIO *b)
1758{
1759 return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_MSG_WAITING78, 0, NULL((void*)0));
1760}
1761
1762static int dgram_sctp_msg_waiting(BIO *b)
1763{
1764 int n, sockflags;
1765 union sctp_notification snp;
1766 struct msghdr msg;
1767 struct iovec iov;
1768 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1769
1770 /* Check if there are any messages waiting to be read */
1771 do {
1772 memset(&snp, 0, sizeof(snp));
1773 iov.iov_base = (char *)&snp;
1774 iov.iov_len = sizeof(union sctp_notification);
1775 msg.msg_name = NULL((void*)0);
1776 msg.msg_namelen = 0;
1777 msg.msg_iov = &iov;
1778 msg.msg_iovlen = 1;
1779 msg.msg_control = NULL((void*)0);
1780 msg.msg_controllen = 0;
1781 msg.msg_flags = 0;
1782
1783 sockflags = fcntl(b->num, F_GETFL, 0);
1784 fcntl(b->num, F_SETFL, O_NONBLOCK);
1785 n = recvmsg(b->num, &msg, MSG_PEEKMSG_PEEK);
1786 fcntl(b->num, F_SETFL, sockflags);
1787
1788 /* if notification, process and try again */
1789 if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) {
1790# ifdef SCTP_AUTHENTICATION_EVENT
1791 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1792 dgram_sctp_handle_auth_free_key_event(b, &snp);
1793# endif
1794
1795 memset(&snp, 0, sizeof(snp));
1796 iov.iov_base = (char *)&snp;
1797 iov.iov_len = sizeof(union sctp_notification);
1798 msg.msg_name = NULL((void*)0);
1799 msg.msg_namelen = 0;
1800 msg.msg_iov = &iov;
1801 msg.msg_iovlen = 1;
1802 msg.msg_control = NULL((void*)0);
1803 msg.msg_controllen = 0;
1804 msg.msg_flags = 0;
1805 n = recvmsg(b->num, &msg, 0);
1806
1807 if (data->handle_notifications != NULL((void*)0))
1808 data->handle_notifications(b, data->notification_context,
1809 (void *)&snp);
1810 }
1811
1812 } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
1813
1814 /* Return 1 if there is a message to be read, return 0 otherwise. */
1815 if (n > 0)
1816 return 1;
1817 else
1818 return 0;
1819}
1820
1821static int dgram_sctp_puts(BIO *bp, const char *str)
1822{
1823 int n, ret;
1824
1825 n = strlen(str);
1826 ret = dgram_sctp_write(bp, str, n);
1827 return ret;
1828}
1829# endif
1830
1831static int BIO_dgram_should_retry(int i)
1832{
1833 int err;
1834
1835 if ((i == 0) || (i == -1)) {
1836 err = get_last_socket_error()(*__errno_location ());
1837
1838# if defined(OPENSSL_SYS_WINDOWS)
1839 /*
1840 * If the socket return value (i) is -1 and err is unexpectedly 0 at
1841 * this point, the error code was overwritten by another system call
1842 * before this error handling is called.
1843 */
1844# endif
1845
1846 return BIO_dgram_non_fatal_error(err);
1847 }
1848 return 0;
1849}
1850
1851int BIO_dgram_non_fatal_error(int err)
1852{
1853 switch (err) {
1854# if defined(OPENSSL_SYS_WINDOWS)
1855# if defined(WSAEWOULDBLOCK)
1856 case WSAEWOULDBLOCK:
1857# endif
1858# endif
1859
1860# ifdef EWOULDBLOCK11
1861# ifdef WSAEWOULDBLOCK
1862# if WSAEWOULDBLOCK != EWOULDBLOCK11
1863 case EWOULDBLOCK11:
1864# endif
1865# else
1866 case EWOULDBLOCK11:
1867# endif
1868# endif
1869
1870# ifdef EINTR4
1871 case EINTR4:
1872# endif
1873
1874# ifdef EAGAIN11
1875# if EWOULDBLOCK11 != EAGAIN11
1876 case EAGAIN11:
1877# endif
1878# endif
1879
1880# ifdef EPROTO71
1881 case EPROTO71:
1882# endif
1883
1884# ifdef EINPROGRESS115
1885 case EINPROGRESS115:
1886# endif
1887
1888# ifdef EALREADY114
1889 case EALREADY114:
1890# endif
1891
1892 return 1;
1893 default:
1894 break;
1895 }
1896 return 0;
1897}
1898
1899static void get_current_time(struct timeval *t)
1900{
1901# if defined(_WIN32)
1902 SYSTEMTIME st;
1903 unsigned __int64 now_ul;
1904 FILETIME now_ft;
1905
1906 GetSystemTime(&st);
1907 SystemTimeToFileTime(&st, &now_ft);
1908 now_ul = ((unsigned __int64)now_ft.dwHighDateTime << 32) | now_ft.dwLowDateTime;
1909# ifdef __MINGW32__
1910 now_ul -= 116444736000000000ULL;
1911# else
1912 now_ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */
1913# endif
1914 t->tv_sec = (long)(now_ul / 10000000);
1915 t->tv_usec = ((int)(now_ul % 10000000)) / 10;
1916# else
1917 gettimeofday(t, NULL((void*)0));
1918# endif
1919}
1920
1921#endif