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