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