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