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