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