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