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