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