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