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