1c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* crypto/bio/bio_dgram.c */
2c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/*
3c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * DTLS implementation written by Nagendra Modadugu
4c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
6c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* ====================================================================
7c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
9c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Redistribution and use in source and binary forms, with or without
10c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * modification, are permitted provided that the following conditions
11c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * are met:
12c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
13c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 1. Redistributions of source code must retain the above copyright
14c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer.
15c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
16c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
17c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer in
18c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    the documentation and/or other materials provided with the
19c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    distribution.
20c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
21c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 3. All advertising materials mentioning features or use of this
22c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    software must display the following acknowledgment:
23c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software developed by the OpenSSL Project
24c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
26c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    endorse or promote products derived from this software without
28c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    prior written permission. For written permission, please contact
29c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    openssl-core@OpenSSL.org.
30c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
31c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 5. Products derived from this software may not be called "OpenSSL"
32c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    nor may "OpenSSL" appear in their names without prior written
33c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    permission of the OpenSSL Project.
34c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
35c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 6. Redistributions of any form whatsoever must retain the following
36c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    acknowledgment:
37c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software developed by the OpenSSL Project
38c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
40c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
52c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ====================================================================
53c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
54c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This product includes cryptographic software written by Eric Young
55c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * (eay@cryptsoft.com).  This product includes software written by Tim
56c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Hudson (tjh@cryptsoft.com).
57c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
58c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
59c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
60c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
61c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <stdio.h>
62c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <errno.h>
63c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define USE_SOCKETS
64c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include "cryptlib.h"
65c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
66c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/bio.h>
67480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#ifndef OPENSSL_NO_DGRAM
68c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
69c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
70c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <sys/timeb.h>
71c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
72c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef OPENSSL_NO_SCTP
742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <netinet/sctp.h>
752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <fcntl.h>
762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define OPENSSL_SCTP_DATA_CHUNK_TYPE            0x00
772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
807453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU)
81c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define IP_MTU      14 /* linux is lame */
82c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
83c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
847453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED)
857453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org/* Standard definition causes type-punning problems. */
867453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#undef IN6_IS_ADDR_V4MAPPED
877453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#define s6_addr32 __u6_addr.__u6_addr32
887453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#define IN6_IS_ADDR_V4MAPPED(a)               \
897453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org        (((a)->s6_addr32[0] == 0) &&          \
907453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org         ((a)->s6_addr32[1] == 0) &&          \
917453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org         ((a)->s6_addr32[2] == htonl(0x0000ffff)))
927453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#endif
937453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org
94c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef WATT32
95c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define sock_write SockWrite  /* Watt-32 uses same names */
96c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define sock_read  SockRead
97c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define sock_puts  SockPuts
98c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
99c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
100c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_write(BIO *h, const char *buf, int num);
101c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_read(BIO *h, char *buf, int size);
102c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_puts(BIO *h, const char *str);
103c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
104c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_new(BIO *h);
105c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_free(BIO *data);
106c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_clear(BIO *bio);
107c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef OPENSSL_NO_SCTP
1092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_write(BIO *h, const char *buf, int num);
1102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_read(BIO *h, char *buf, int size);
1112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_puts(BIO *h, const char *str);
1122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
1132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_new(BIO *h);
1142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_free(BIO *data);
1152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
1162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp);
1172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
1182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
1192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
120c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int BIO_dgram_should_retry(int s);
121c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
122c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void get_current_time(struct timeval *t);
123c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
124c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic BIO_METHOD methods_dgramp=
125c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
126c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_TYPE_DGRAM,
127c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	"datagram socket",
128c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	dgram_write,
129c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	dgram_read,
130c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	dgram_puts,
131c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	NULL, /* dgram_gets, */
132c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	dgram_ctrl,
133c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	dgram_new,
134c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	dgram_free,
135c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	NULL,
136c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	};
137c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef OPENSSL_NO_SCTP
1392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic BIO_METHOD methods_dgramp_sctp=
1402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
1412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	BIO_TYPE_DGRAM_SCTP,
1422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	"datagram sctp socket",
1432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	dgram_sctp_write,
1442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	dgram_sctp_read,
1452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	dgram_sctp_puts,
1462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	NULL, /* dgram_gets, */
1472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	dgram_sctp_ctrl,
1482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	dgram_sctp_new,
1492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	dgram_sctp_free,
1502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	NULL,
1512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	};
1522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
1532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
154c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgtypedef struct bio_dgram_data_st
155c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
156480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	union {
157480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr sa;
158480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr_in sa_in;
159480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
160480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr_in6 sa_in6;
161480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
162480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	} peer;
163c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	unsigned int connected;
164c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	unsigned int _errno;
165c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	unsigned int mtu;
166c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	struct timeval next_timeout;
167c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	struct timeval socket_timeout;
168c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	} bio_dgram_data;
169c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef OPENSSL_NO_SCTP
1712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgtypedef struct bio_dgram_sctp_save_message_st
1722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
1732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org        BIO *bio;
1742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org        char *data;
1752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org        int length;
1762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	} bio_dgram_sctp_save_message;
1772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
1782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgtypedef struct bio_dgram_sctp_data_st
1792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
1802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	union {
1812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		struct sockaddr sa;
1822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		struct sockaddr_in sa_in;
1832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if OPENSSL_USE_IPV6
1842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		struct sockaddr_in6 sa_in6;
1852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
1862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	} peer;
1872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	unsigned int connected;
1882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	unsigned int _errno;
1892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	unsigned int mtu;
1902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct bio_dgram_sctp_sndinfo sndinfo;
1912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct bio_dgram_sctp_rcvinfo rcvinfo;
1922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct bio_dgram_sctp_prinfo prinfo;
1932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	void (*handle_notifications)(BIO *bio, void *context, void *buf);
1942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	void* notification_context;
1952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int in_handshake;
1962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ccs_rcvd;
1972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ccs_sent;
1982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int save_shutdown;
1992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int peer_auth_tested;
2002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_save_message saved_message;
2012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	} bio_dgram_sctp_data;
2022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
2032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
204c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO_METHOD *BIO_s_datagram(void)
205c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
206c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(&methods_dgramp);
207c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
208c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
209c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO *BIO_new_dgram(int fd, int close_flag)
210c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
211c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *ret;
212c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
213c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret=BIO_new(BIO_s_datagram());
214c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret == NULL) return(NULL);
215c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_set_fd(ret,fd,close_flag);
216c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
217c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
218c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
219c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_new(BIO *bi)
220c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
221c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data = NULL;
222c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
223c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bi->init=0;
224c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bi->num=0;
225c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data = OPENSSL_malloc(sizeof(bio_dgram_data));
226c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (data == NULL)
227c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
228c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	memset(data, 0x00, sizeof(bio_dgram_data));
229c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org    bi->ptr = data;
230c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
231c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bi->flags=0;
232c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
233c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
234c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
235c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_free(BIO *a)
236c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
237c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data;
238c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
239c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a == NULL) return(0);
240c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ( ! dgram_clear(a))
241c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
242c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
243c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data = (bio_dgram_data *)a->ptr;
244c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if(data != NULL) OPENSSL_free(data);
245c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
246c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
247c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
248c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
249c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_clear(BIO *a)
250c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
251c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a == NULL) return(0);
252c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a->shutdown)
253c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
254c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (a->init)
255c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
256c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			SHUTDOWN2(a->num);
257c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
258c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		a->init=0;
259c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		a->flags=0;
260c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
261c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
262c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
263c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
264c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void dgram_adjust_rcv_timeout(BIO *b)
265c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
266c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(SO_RCVTIMEO)
267c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
2687453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org	union { size_t s; int i; } sz = {0};
269c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
270c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Is a timer active? */
271c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
272c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
273c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		struct timeval timenow, timeleft;
274c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
275c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Read current socket timeout */
276c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WINDOWS
277c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int timeout;
2787453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org
2797453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		sz.i = sizeof(timeout);
280c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
2817453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org					   (void*)&timeout, &sz.i) < 0)
282c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("getsockopt"); }
283c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
284c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
285c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->socket_timeout.tv_sec = timeout / 1000;
286c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
287c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
288c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
2897453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		sz.i = sizeof(data->socket_timeout);
290c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
291c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						&(data->socket_timeout), (void *)&sz) < 0)
292c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("getsockopt"); }
2937453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
2947453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			OPENSSL_assert(sz.s<=sizeof(data->socket_timeout));
295c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
296c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
297c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Get current time */
298c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		get_current_time(&timenow);
299c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
300c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Calculate time left until timer expires */
301c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
302c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		timeleft.tv_sec -= timenow.tv_sec;
303c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		timeleft.tv_usec -= timenow.tv_usec;
304c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (timeleft.tv_usec < 0)
305c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
306c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			timeleft.tv_sec--;
307c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			timeleft.tv_usec += 1000000;
308c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
309c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
310c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (timeleft.tv_sec < 0)
311c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
312c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			timeleft.tv_sec = 0;
313c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			timeleft.tv_usec = 1;
314c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
315c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
316c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Adjust socket timeout if next handhake message timer
317c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 * will expire earlier.
318c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		 */
319c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) ||
320c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			(data->socket_timeout.tv_sec > timeleft.tv_sec) ||
321c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			(data->socket_timeout.tv_sec == timeleft.tv_sec &&
322c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			 data->socket_timeout.tv_usec >= timeleft.tv_usec))
323c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
324c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WINDOWS
325c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
326c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
327c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						   (void*)&timeout, sizeof(timeout)) < 0)
328c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{ perror("setsockopt"); }
329c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
330c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
331c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							sizeof(struct timeval)) < 0)
332c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{ perror("setsockopt"); }
333c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
334c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
335c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
336c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
337c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
338c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
339c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void dgram_reset_rcv_timeout(BIO *b)
340c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
341c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(SO_RCVTIMEO)
342c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
343c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
344c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Is a timer active? */
345c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
346c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
347c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WINDOWS
348c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int timeout = data->socket_timeout.tv_sec * 1000 +
349c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					  data->socket_timeout.tv_usec / 1000;
350c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
351c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					   (void*)&timeout, sizeof(timeout)) < 0)
352c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("setsockopt"); }
353c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
354c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout),
355c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						sizeof(struct timeval)) < 0)
356c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("setsockopt"); }
357c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
358c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
359c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
360c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
361c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
362c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_read(BIO *b, char *out, int outl)
363c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
364c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret=0;
365c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
366c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
367480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	struct	{
368480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/*
369480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 * See commentary in b_sock.c. <appro>
370480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 */
371480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	union	{ size_t s; int i; } len;
372480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	union	{
373480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr sa;
374480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr_in sa_in;
375480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
376480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr_in6 sa_in6;
377480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
378480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		} peer;
379480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	} sa;
380480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
381480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	sa.len.s=0;
382480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	sa.len.i=sizeof(sa.peer);
383c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
384c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (out != NULL)
385c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
386c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		clear_socket_error();
387480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		memset(&sa.peer, 0x00, sizeof(sa.peer));
388c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		dgram_adjust_rcv_timeout(b);
389480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len);
390480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0)
391480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
392480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			OPENSSL_assert(sa.len.s<=sizeof(sa.peer));
393480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			sa.len.i = (int)sa.len.s;
394480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
395c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
396c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( ! data->connected  && ret >= 0)
397480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
398c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
399c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_clear_retry_flags(b);
400c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ret < 0)
401c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
402c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (BIO_dgram_should_retry(ret))
403c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
404c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_set_retry_read(b);
405c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->_errno = get_last_socket_error();
406c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
407c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
408480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
409480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		dgram_reset_rcv_timeout(b);
410c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
411c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
412c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
413c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
414c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_write(BIO *b, const char *in, int inl)
415c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
416c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret;
417c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
418c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	clear_socket_error();
419c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
420480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if ( data->connected )
421480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret=writesocket(b->num,in,inl);
422480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	else
423480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
424480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		int peerlen = sizeof(data->peer);
425480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
426480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (data->peer.sa.sa_family == AF_INET)
427480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			peerlen = sizeof(data->peer.sa_in);
428480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
429480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		else if (data->peer.sa.sa_family == AF_INET6)
430480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			peerlen = sizeof(data->peer.sa_in6);
431480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
432c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
433480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen);
434c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
435480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
436c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
437480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
438c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
439c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_clear_retry_flags(b);
440c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret <= 0)
441c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
442c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (BIO_dgram_should_retry(ret))
443c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
444c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_retry_write(b);
445c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->_errno = get_last_socket_error();
446c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
447c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0 /* higher layers are responsible for querying MTU, if necessary */
448c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ( data->_errno == EMSGSIZE)
449c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				/* retrieve the new MTU */
450c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
451c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
452c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
453c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
454c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
455c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
456c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
457c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
458c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
459c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	long ret=1;
460c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int *ip;
461c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	struct sockaddr *to = NULL;
462c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bio_dgram_data *data = NULL;
4637453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
4647453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org	int sockopt_val = 0;
4657453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org	socklen_t sockopt_len;	/* assume that system supporting IP_MTU is
4667453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org				 * modern enough to define socklen_t */
467c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	socklen_t addr_len;
468480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	union	{
469480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr	sa;
470480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr_in s4;
471480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
472480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		struct sockaddr_in6 s6;
473480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
474480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		} addr;
475c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
476c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
477c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data = (bio_dgram_data *)b->ptr;
478c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
479c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (cmd)
480c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
481c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_RESET:
482c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		num=0;
483c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_FILE_SEEK:
484c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
485c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
486c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_FILE_TELL:
487c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_INFO:
488c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
489c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
490c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_SET_FD:
491c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		dgram_clear(b);
492c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		b->num= *((int *)ptr);
493c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		b->shutdown=(int)num;
494c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		b->init=1;
495c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
496c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_GET_FD:
497c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (b->init)
498c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
499c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ip=(int *)ptr;
500c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (ip != NULL) *ip=b->num;
501c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=b->num;
502c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
503c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
504c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret= -1;
505c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
506c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_GET_CLOSE:
507c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=b->shutdown;
508c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
509c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_SET_CLOSE:
510c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		b->shutdown=(int)num;
511c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
512c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_PENDING:
513c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_WPENDING:
514c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
515c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
516c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DUP:
517c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_FLUSH:
518c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=1;
519c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
520c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_CONNECT:
521c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		to = (struct sockaddr *)ptr;
522c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0
523c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
524c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("connect"); ret = 0; }
525c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
526c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
527c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
528480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			switch (to->sa_family)
529480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
530480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				case AF_INET:
531480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
532480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					break;
533480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
534480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				case AF_INET6:
535480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
536480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					break;
537480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
538480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				default:
539480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					memcpy(&data->peer,to,sizeof(data->peer.sa));
540480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					break;
541480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
542c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0
543c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
544c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
545c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
546c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* (Linux)kernel sets DF bit on outgoing IP packets */
547c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_MTU_DISCOVER:
5487453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
549480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		addr_len = (socklen_t)sizeof(addr);
550480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		memset((void *)&addr, 0, sizeof(addr));
551480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
552c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
553c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 0;
554c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
555c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
556480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		switch (addr.sa.sa_family)
557c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
558c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case AF_INET:
559c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sockopt_val = IP_PMTUDISC_DO;
560c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
561c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&sockopt_val, sizeof(sockopt_val))) < 0)
562c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				perror("setsockopt");
563c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
5647453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
565c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case AF_INET6:
566c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sockopt_val = IPV6_PMTUDISC_DO;
567c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
568c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&sockopt_val, sizeof(sockopt_val))) < 0)
569c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				perror("setsockopt");
570c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
571480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
572c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		default:
573c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = -1;
574c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
575c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
576c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret = -1;
577c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
578c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
579c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
580c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_QUERY_MTU:
5817453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU)
582480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		addr_len = (socklen_t)sizeof(addr);
583480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		memset((void *)&addr, 0, sizeof(addr));
584480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
585c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
586c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 0;
587c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
588c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
589c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		sockopt_len = sizeof(sockopt_val);
590480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		switch (addr.sa.sa_family)
591c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
592c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case AF_INET:
593c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
594c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&sockopt_len)) < 0 || sockopt_val < 0)
595c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
596c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ret = 0;
597c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
598c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else
599c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
600c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				/* we assume that the transport protocol is UDP and no
601c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				 * IP options are used.
602c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				 */
603c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->mtu = sockopt_val - 8 - 20;
604c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ret = data->mtu;
605c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
606c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
607480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
608c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case AF_INET6:
609c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
610c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				&sockopt_len)) < 0 || sockopt_val < 0)
611c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
612c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ret = 0;
613c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
614c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else
615c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
616c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				/* we assume that the transport protocol is UDP and no
617c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				 * IPV6 options are used.
618c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				 */
619c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->mtu = sockopt_val - 8 - 40;
620c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ret = data->mtu;
621c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
622c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
623480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
624c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		default:
625c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 0;
626c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
627c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
628c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
629c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret = 0;
630c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
631c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
6322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
6332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		switch (data->peer.sa.sa_family)
6342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
6352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			case AF_INET:
6362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				ret = 576 - 20 - 8;
6372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				break;
6382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if OPENSSL_USE_IPV6
6392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			case AF_INET6:
6402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef IN6_IS_ADDR_V4MAPPED
6412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
6422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					ret = 576 - 20 - 8;
6432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				else
6442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
6452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					ret = 1280 - 40 - 8;
6462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				break;
6472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
6482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			default:
6492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				ret = 576 - 20 - 8;
6502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				break;
6512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
6522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
653c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_GET_MTU:
654c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return data->mtu;
655c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
656c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_SET_MTU:
657c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data->mtu = num;
658c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret = num;
659c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
660c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_SET_CONNECTED:
661c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		to = (struct sockaddr *)ptr;
662c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
663c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( to != NULL)
664c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
665c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->connected = 1;
666480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			switch (to->sa_family)
667480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
668480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				case AF_INET:
669480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
670480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					break;
671480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
672480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				case AF_INET6:
673480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
674480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					break;
675480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
676480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				default:
677480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					memcpy(&data->peer,to,sizeof(data->peer.sa));
678480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org					break;
679480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
680c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
681c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
682c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
683c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->connected = 0;
684480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			memset(&(data->peer), 0x00, sizeof(data->peer));
685480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
686480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
687480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	case BIO_CTRL_DGRAM_GET_PEER:
688480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		switch (data->peer.sa.sa_family)
689480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
690480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			case AF_INET:
691480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ret=sizeof(data->peer.sa_in);
692480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				break;
693480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
694480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			case AF_INET6:
695480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ret=sizeof(data->peer.sa_in6);
696480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				break;
697480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
698480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			default:
699480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				ret=sizeof(data->peer.sa);
700480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				break;
701480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
702480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (num==0 || num>ret)
703480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			num=ret;
704480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		memcpy(ptr,&data->peer,(ret=num));
705480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		break;
706480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	case BIO_CTRL_DGRAM_SET_PEER:
707480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		to = (struct sockaddr *) ptr;
708480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		switch (to->sa_family)
709480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
710480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			case AF_INET:
711480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				memcpy(&data->peer,to,sizeof(data->peer.sa_in));
712480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				break;
713480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if OPENSSL_USE_IPV6
714480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			case AF_INET6:
715480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
716480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				break;
717480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
718480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			default:
719480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				memcpy(&data->peer,to,sizeof(data->peer.sa));
720480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				break;
721c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
722c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
723c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
724480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
725c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
726c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(SO_RCVTIMEO)
727c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
728c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WINDOWS
729c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
730c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		struct timeval *tv = (struct timeval *)ptr;
731c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
732c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
733c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			(void*)&timeout, sizeof(timeout)) < 0)
734c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("setsockopt"); ret = -1; }
735c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
736c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
737c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
738c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sizeof(struct timeval)) < 0)
739c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("setsockopt");	ret = -1; }
740c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
741c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
742c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
743c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
7447453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		union { size_t s; int i; } sz = {0};
7457453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#ifdef OPENSSL_SYS_WINDOWS
7467453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		int timeout;
747c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		struct timeval *tv = (struct timeval *)ptr;
7487453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org
7497453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		sz.i = sizeof(timeout);
750c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
7517453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			(void*)&timeout, &sz.i) < 0)
752c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("getsockopt"); ret = -1; }
753c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
754c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
755c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			tv->tv_sec = timeout / 1000;
756c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			tv->tv_usec = (timeout % 1000) * 1000;
757c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = sizeof(*tv);
758c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
759c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
7607453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		sz.i = sizeof(struct timeval);
761c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
7627453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			ptr, (void *)&sz) < 0)
763c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("getsockopt"); ret = -1; }
7647453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
7657453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			{
7667453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			OPENSSL_assert(sz.s<=sizeof(struct timeval));
7677453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			ret = (int)sz.s;
7687453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			}
7697453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		else
7707453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			ret = sz.i;
771c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
7727453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		}
773c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
774c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
775c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(SO_SNDTIMEO)
776c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
777c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WINDOWS
778c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
779c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		struct timeval *tv = (struct timeval *)ptr;
780c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
781c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
782c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			(void*)&timeout, sizeof(timeout)) < 0)
783c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("setsockopt"); ret = -1; }
784c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
785c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
786c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
787c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sizeof(struct timeval)) < 0)
788c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("setsockopt");	ret = -1; }
789c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
790c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
791c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
792c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
7937453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		union { size_t s; int i; } sz = {0};
7947453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org#ifdef OPENSSL_SYS_WINDOWS
7957453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		int timeout;
796c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		struct timeval *tv = (struct timeval *)ptr;
7977453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org
7987453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		sz.i = sizeof(timeout);
799c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
8007453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			(void*)&timeout, &sz.i) < 0)
801c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("getsockopt"); ret = -1; }
802c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
803c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
804c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			tv->tv_sec = timeout / 1000;
805c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			tv->tv_usec = (timeout % 1000) * 1000;
806c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = sizeof(*tv);
807c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
808c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
8097453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		sz.i = sizeof(struct timeval);
810c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
8117453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			ptr, (void *)&sz) < 0)
812c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{ perror("getsockopt"); ret = -1; }
8137453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
8147453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			{
8157453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			OPENSSL_assert(sz.s<=sizeof(struct timeval));
8167453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			ret = (int)sz.s;
8177453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			}
8187453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		else
8197453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org			ret = sz.i;
820c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
8217453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		}
822c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
823c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
824c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
825c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* fall-through */
826c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
827c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WINDOWS
828c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( data->_errno == WSAETIMEDOUT)
829c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
830c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( data->_errno == EAGAIN)
831c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
832c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
833c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 1;
834c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->_errno = 0;
835c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
836c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
837c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 0;
838c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
839c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EMSGSIZE
840c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
841c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if ( data->_errno == EMSGSIZE)
842c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
843c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 1;
844c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			data->_errno = 0;
845c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
846c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
847c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret = 0;
848c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
849c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
850c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
851c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
852c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
853c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
854c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
855c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
856c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
857c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int dgram_puts(BIO *bp, const char *str)
858c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
859c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int n,ret;
860c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
861c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	n=strlen(str);
862c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret=dgram_write(bp,str,n);
863c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
864c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
865c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
8662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef OPENSSL_NO_SCTP
8672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgBIO_METHOD *BIO_s_datagram_sctp(void)
8682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
8692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(&methods_dgramp_sctp);
8702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
8712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
8722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgBIO *BIO_new_dgram_sctp(int fd, int close_flag)
8732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
8742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	BIO *bio;
8752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ret, optval = 20000;
8762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int auth_data = 0, auth_forward = 0;
8772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	unsigned char *p;
8782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_authchunk auth;
8792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_authchunks *authchunks;
8802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	socklen_t sockopt_len;
8812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
8822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
8832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_event event;
8842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
8852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_event_subscribe event;
8862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
8872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
8882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
8892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio=BIO_new(BIO_s_datagram_sctp());
8902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (bio == NULL) return(NULL);
8912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	BIO_set_fd(bio,fd,close_flag);
8922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
8932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
8942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
8952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
8962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
8972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
8982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
8992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
9002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* Test if activation was successful. When using accept(),
9022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 * SCTP-AUTH has to be activated for the listening socket
9032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 * already, otherwise the connected socket won't use it. */
9042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
9052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	authchunks = OPENSSL_malloc(sockopt_len);
9062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(authchunks, 0, sizeof(sockopt_len));
9072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
9082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
9092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
9112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	     p < (unsigned char*) authchunks + sockopt_len;
9122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	     p += sizeof(uint8_t))
9132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
9142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
9152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
9162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
9172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_free(authchunks);
9192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(auth_data);
9212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(auth_forward);
9222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
9242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
9252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(&event, 0, sizeof(struct sctp_event));
9262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.se_assoc_id = 0;
9272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.se_type = SCTP_AUTHENTICATION_EVENT;
9282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.se_on = 1;
9292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
9302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
9312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
9322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
9332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
9342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
9352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.sctp_authentication_event = 1;
9372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
9392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
9402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
9412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
9422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* Disable partial delivery by setting the min size
9442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 * larger than the max record size of 2^14 + 2048 + 13
9452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 */
9462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
9472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	OPENSSL_assert(ret >= 0);
9482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(bio);
9502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
9512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint BIO_dgram_is_sctp(BIO *bio)
9532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
9542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
9552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
9562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_new(BIO *bi)
9582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
9592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = NULL;
9602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bi->init=0;
9622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bi->num=0;
9632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data));
9642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (data == NULL)
9652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 0;
9662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(data, 0x00, sizeof(bio_dgram_sctp_data));
9672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_PR_SCTP_NONE
9682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
9692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
9702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org    bi->ptr = data;
9712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bi->flags=0;
9732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(1);
9742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
9752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_free(BIO *a)
9772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
9782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data;
9792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (a == NULL) return(0);
9812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if ( ! dgram_clear(a))
9822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 0;
9832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	data = (bio_dgram_sctp_data *)a->ptr;
9852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if(data != NULL) OPENSSL_free(data);
9862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(1);
9882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
9892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
9912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgvoid dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
9922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
9932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ret;
9942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
9952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
9962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY)
9972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
9982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		struct sctp_authkeyid authkeyid;
9992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* delete key */
10012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
10022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
10037453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org		      &authkeyid, sizeof(struct sctp_authkeyid));
10042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
10052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
10062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
10072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_read(BIO *b, char *out, int outl)
10092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
10102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ret = 0, n = 0, i, optval;
10112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	socklen_t optlen;
10122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
10132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	union sctp_notification *snp;
10142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct msghdr msg;
10152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct iovec iov;
10162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct cmsghdr *cmsg;
10172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	char cmsgbuf[512];
10182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (out != NULL)
10202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
10212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		clear_socket_error();
10222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		do
10242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
10252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
10262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			iov.iov_base = out;
10272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			iov.iov_len = outl;
10282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_name = NULL;
10292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_namelen = 0;
10302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_iov = &iov;
10312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_iovlen = 1;
10322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_control = cmsgbuf;
10332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_controllen = 512;
10342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_flags = 0;
10352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			n = recvmsg(b->num, &msg, 0);
10362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (msg.msg_controllen > 0)
10382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
10392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					{
10412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					if (cmsg->cmsg_level != IPPROTO_SCTP)
10422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						continue;
10432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_RCVINFO
10442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					if (cmsg->cmsg_type == SCTP_RCVINFO)
10452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						{
10462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						struct sctp_rcvinfo *rcvinfo;
10472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
10492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
10502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
10512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
10522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
10532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
10542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
10552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_context = rcvinfo->rcv_context;
10562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						}
10572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
10582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_SNDRCV
10592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					if (cmsg->cmsg_type == SCTP_SNDRCV)
10602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						{
10612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						struct sctp_sndrcvinfo *sndrcvinfo;
10622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
10642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
10652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
10662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
10672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
10682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
10692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
10702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
10712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						}
10722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
10732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					}
10742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
10752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (n <= 0)
10772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
10782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (n < 0)
10792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					ret = n;
10802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				break;
10812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
10822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
10832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (msg.msg_flags & MSG_NOTIFICATION)
10842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
10852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				snp = (union sctp_notification*) out;
10862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
10872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					{
10882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
10892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					struct sctp_event event;
10902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
10912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					struct sctp_event_subscribe event;
10922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					socklen_t eventsize;
10932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
10942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					/* If a message has been delayed until the socket
10952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					 * is dry, it can be sent now.
10962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					 */
10972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					if (data->saved_message.length > 0)
10982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						{
10992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
11002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						                 data->saved_message.length);
11012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						OPENSSL_free(data->saved_message.data);
11022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						data->saved_message.length = 0;
11032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org						}
11042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					/* disable sender dry event */
11062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
11072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					memset(&event, 0, sizeof(struct sctp_event));
11082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					event.se_assoc_id = 0;
11092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					event.se_type = SCTP_SENDER_DRY_EVENT;
11102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					event.se_on = 0;
11112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
11122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					OPENSSL_assert(i >= 0);
11132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
11142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					eventsize = sizeof(struct sctp_event_subscribe);
11152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
11162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					OPENSSL_assert(i >= 0);
11172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					event.sctp_sender_dry_event = 0;
11192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
11212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					OPENSSL_assert(i >= 0);
11222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
11232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					}
11242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
11262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
11272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					dgram_sctp_handle_auth_free_key_event(b, snp);
11282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
11292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (data->handle_notifications != NULL)
11312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					data->handle_notifications(b, data->notification_context, (void*) out);
11322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				memset(out, 0, outl);
11342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
11352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			else
11362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				ret += n;
11372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
11382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
11392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret > 0 && !(msg.msg_flags & MSG_EOR))
11412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
11422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Partial message read, this should never happen! */
11432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* The buffer was too small, this means the peer sent
11452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * a message that was larger than allowed. */
11462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret == outl)
11472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
11482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Test if socket buffer can handle max record
11502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * size (2^14 + 2048 + 13)
11512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 */
11522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			optlen = (socklen_t) sizeof(int);
11532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
11542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_assert(ret >= 0);
11552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_assert(optval >= 18445);
11562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Test if SCTP doesn't partially deliver below
11582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * max record size (2^14 + 2048 + 13)
11592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 */
11602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			optlen = (socklen_t) sizeof(int);
11612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
11622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			                 &optval, &optlen);
11632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_assert(ret >= 0);
11642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_assert(optval >= 18445);
11652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Partially delivered notification??? Probably a bug.... */
11672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
11682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Everything seems ok till now, so it's most likely
11702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * a message dropped by PR-SCTP.
11712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 */
11722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			memset(out, 0, outl);
11732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			BIO_set_retry_read(b);
11742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			return -1;
11752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
11762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		BIO_clear_retry_flags(b);
11782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret < 0)
11792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
11802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (BIO_dgram_should_retry(ret))
11812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
11822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				BIO_set_retry_read(b);
11832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				data->_errno = get_last_socket_error();
11842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
11852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
11862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Test if peer uses SCTP-AUTH before continuing */
11882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (!data->peer_auth_tested)
11892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
11902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			int ii, auth_data = 0, auth_forward = 0;
11912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			unsigned char *p;
11922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			struct sctp_authchunks *authchunks;
11932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
11942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
11952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			authchunks = OPENSSL_malloc(optlen);
11962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			memset(authchunks, 0, sizeof(optlen));
11972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
11982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_assert(ii >= 0);
11992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
12012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				 p < (unsigned char*) authchunks + optlen;
12022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				 p += sizeof(uint8_t))
12032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
12042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
12052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
12062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
12072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			OPENSSL_free(authchunks);
12092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (!auth_data || !auth_forward)
12112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
12122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				BIOerr(BIO_F_DGRAM_SCTP_READ,BIO_R_CONNECT_ERROR);
12132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
12142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
12152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->peer_auth_tested = 1;
12172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
12182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
12192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(ret);
12202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
12212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_write(BIO *b, const char *in, int inl)
12232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
12242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int ret;
12252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
12262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
12272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
12282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct bio_dgram_sctp_sndinfo handshake_sinfo;
12292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct iovec iov[1];
12302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct msghdr msg;
12312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct cmsghdr *cmsg;
12322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
12332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
12342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_sndinfo *sndinfo;
12352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_prinfo *prinfo;
12362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
12372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
12382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_sndrcvinfo *sndrcvinfo;
12392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
12402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	clear_socket_error();
12422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* If we're send anything else than application data,
12442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 * disable all user parameters and flags.
12452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 */
12462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (in[0] != 23) {
12472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo));
12482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_SACK_IMMEDIATELY
12492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
12502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
12512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		sinfo = &handshake_sinfo;
12522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
12532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* If we have to send a shutdown alert message and the
12552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 * socket is not dry yet, we have to save it and send it
12562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 * as soon as the socket gets dry.
12572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	 */
12582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b))
12592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
12602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->saved_message.bio = b;
12612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->saved_message.length = inl;
12622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->saved_message.data = OPENSSL_malloc(inl);
12632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(data->saved_message.data, in, inl);
12642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return inl;
12652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
12662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	iov[0].iov_base = (char *)in;
12682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	iov[0].iov_len = inl;
12692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_name = NULL;
12702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_namelen = 0;
12712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_iov = iov;
12722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_iovlen = 1;
12732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_control = (caddr_t)cmsgbuf;
12742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_controllen = 0;
12752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_flags = 0;
12762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
12772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg = (struct cmsghdr *)cmsgbuf;
12782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_level = IPPROTO_SCTP;
12792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_type = SCTP_SNDINFO;
12802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
12812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
12822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
12832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndinfo->snd_sid = sinfo->snd_sid;
12842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndinfo->snd_flags = sinfo->snd_flags;
12852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndinfo->snd_ppid = sinfo->snd_ppid;
12862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndinfo->snd_context = sinfo->snd_context;
12872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
12882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
12892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
12902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_level = IPPROTO_SCTP;
12912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_type = SCTP_PRINFO;
12922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
12932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
12942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(prinfo, 0, sizeof(struct sctp_prinfo));
12952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	prinfo->pr_policy = pinfo->pr_policy;
12962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	prinfo->pr_value = pinfo->pr_value;
12972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
12982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
12992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg = (struct cmsghdr *)cmsgbuf;
13002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_level = IPPROTO_SCTP;
13012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_type = SCTP_SNDRCV;
13022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
13032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
13042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
13052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo->sinfo_stream = sinfo->snd_sid;
13062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo->sinfo_flags = sinfo->snd_flags;
13072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef __FreeBSD__
13082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo->sinfo_flags |= pinfo->pr_policy;
13092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
13102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
13112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo->sinfo_context = sinfo->snd_context;
13122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
13132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
13142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
13152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = sendmsg(b->num, &msg, 0);
13172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	BIO_clear_retry_flags(b);
13192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (ret <= 0)
13202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
13212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (BIO_dgram_should_retry(ret))
13222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
13232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			BIO_set_retry_write(b);
13242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->_errno = get_last_socket_error();
13252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
13262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
13272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(ret);
13282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
13292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
13312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
13322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	long ret=1;
13332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = NULL;
13347453c6c0666947e06d87565404f4397a4b387f91digit@chromium.org	socklen_t sockopt_len = 0;
13352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_authkeyid authkeyid;
13362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_authkey *authkey;
13372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	data = (bio_dgram_sctp_data *)b->ptr;
13392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	switch (cmd)
13412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
13422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_QUERY_MTU:
13432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Set to maximum (2^14)
13442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * and ignore user input to enable transport
13452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * protocol fragmentation.
13462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * Returns always 2^14.
13472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
13482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->mtu = 16384;
13492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = data->mtu;
13502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
13512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SET_MTU:
13522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Set to maximum (2^14)
13532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * and ignore input to enable transport
13542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * protocol fragmentation.
13552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * Returns always 2^14.
13562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
13572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->mtu = 16384;
13582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = data->mtu;
13592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
13602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SET_CONNECTED:
13612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_CONNECT:
13622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns always -1. */
13632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = -1;
13642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
13652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
13662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* SCTP doesn't need the DTLS timer
13672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * Returns always 1.
13682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
13692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
13702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
13712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > 0)
13722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->in_handshake = 1;
13732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		else
13742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->in_handshake = 0;
13752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
13772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
13782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
13792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* New shared key for SCTP AUTH.
13802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * Returns 0 on success, -1 otherwise.
13812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
13822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Get active key */
13842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		sockopt_len = sizeof(struct sctp_authkeyid);
13852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
13862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret < 0) break;
13872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
13882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Add new key */
13892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
13902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		authkey = OPENSSL_malloc(sockopt_len);
13912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memset(authkey, 0x00, sockopt_len);
13922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
13932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef __FreeBSD__
13942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* This field is missing in FreeBSD 8.2 and earlier,
13952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * and FreeBSD 8.3 and higher work without it.
13962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
13972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		authkey->sca_keylength = 64;
13982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
13992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
14002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
14022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret < 0) break;
14032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Reset active key */
14052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
14062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		      &authkeyid, sizeof(struct sctp_authkeyid));
14072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret < 0) break;
14082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
14102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
14112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns 0 on success, -1 otherwise. */
14122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Get active key */
14142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		sockopt_len = sizeof(struct sctp_authkeyid);
14152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
14162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret < 0) break;
14172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Set active key */
14192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
14202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
14212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		      &authkeyid, sizeof(struct sctp_authkeyid));
14222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (ret < 0) break;
14232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* CCS has been sent, so remember that and fall through
14252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * to check if we need to deactivate an old key
14262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
14272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->ccs_sent = 1;
14282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
14302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns 0 on success, -1 otherwise. */
14312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Has this command really been called or is this just a fall-through? */
14332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
14342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->ccs_rcvd = 1;
14352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* CSS has been both, received and sent, so deactivate an old key */
14372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (data->ccs_rcvd == 1 && data->ccs_sent == 1)
14382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
14392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Get active key */
14402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			sockopt_len = sizeof(struct sctp_authkeyid);
14412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
14422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret < 0) break;
14432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* Deactivate key or delete second last key if
14452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 * SCTP_AUTHENTICATION_EVENT is not available.
14462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			 */
14472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
14482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTH_DEACTIVATE_KEY
14492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			sockopt_len = sizeof(struct sctp_authkeyid);
14502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,
14512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			      &authkeyid, sockopt_len);
14522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret < 0) break;
14532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
14542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef SCTP_AUTHENTICATION_EVENT
14552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (authkeyid.scact_keynumber > 0)
14562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				{
14572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
14582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
14592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org					  &authkeyid, sizeof(struct sctp_authkeyid));
14602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				if (ret < 0) break;
14612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				}
14622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
14632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->ccs_rcvd = 0;
14652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->ccs_sent = 0;
14662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
14672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
14682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
14692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns the size of the copied struct. */
14702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
14712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			num = sizeof(struct bio_dgram_sctp_sndinfo);
14722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(ptr, &(data->sndinfo), num);
14742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = num;
14752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
14762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
14772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns the size of the copied struct. */
14782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
14792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			num = sizeof(struct bio_dgram_sctp_sndinfo);
14802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(&(data->sndinfo), ptr, num);
14822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
14832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
14842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns the size of the copied struct. */
14852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
14862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			num = sizeof(struct bio_dgram_sctp_rcvinfo);
14872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(ptr, &data->rcvinfo, num);
14892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = num;
14912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
14922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
14932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns the size of the copied struct. */
14942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
14952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			num = sizeof(struct bio_dgram_sctp_rcvinfo);
14962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
14972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(&(data->rcvinfo), ptr, num);
14982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
14992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
15002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns the size of the copied struct. */
15012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
15022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			num = sizeof(struct bio_dgram_sctp_prinfo);
15032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(ptr, &(data->prinfo), num);
15052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret = num;
15062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
15072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
15082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns the size of the copied struct. */
15092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
15102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			num = sizeof(struct bio_dgram_sctp_prinfo);
15112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memcpy(&(data->prinfo), ptr, num);
15132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
15142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
15152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Returns always 1. */
15162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (num > 0)
15172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->save_shutdown = 1;
15182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		else
15192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->save_shutdown = 0;
15202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
15212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	default:
15232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* Pass to default ctrl function to
15242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 * process SCTP unspecific commands
15252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		 */
15262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		ret=dgram_ctrl(b, cmd, num, ptr);
15272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		break;
15282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
15292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(ret);
15302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
15312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint BIO_dgram_sctp_notification_cb(BIO *b,
15332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                                   void (*handle_notifications)(BIO *bio, void *context, void *buf),
15342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org                                   void *context)
15352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
15362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
15372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (handle_notifications != NULL)
15392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
15402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->handle_notifications = handle_notifications;
15412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		data->notification_context = context;
15422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
15432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	else
15442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
15452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return 0;
15472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
15482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint BIO_dgram_sctp_wait_for_dry(BIO *b)
15502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{
15512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int is_dry = 0;
15522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int n, sockflags, ret;
15532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	union sctp_notification snp;
15542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct msghdr msg;
15552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct iovec iov;
15562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
15572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_event event;
15582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
15592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct sctp_event_subscribe event;
15602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	socklen_t eventsize;
15612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
15622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
15632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* set sender dry event */
15652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
15662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(&event, 0, sizeof(struct sctp_event));
15672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.se_assoc_id = 0;
15682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.se_type = SCTP_SENDER_DRY_EVENT;
15692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.se_on = 1;
15702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
15712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
15722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	eventsize = sizeof(struct sctp_event_subscribe);
15732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
15742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (ret < 0)
15752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
15762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	event.sctp_sender_dry_event = 1;
15782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
15802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
15812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (ret < 0)
15822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return -1;
15832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* peek for notification */
15852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	memset(&snp, 0x00, sizeof(union sctp_notification));
15862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	iov.iov_base = (char *)&snp;
15872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	iov.iov_len = sizeof(union sctp_notification);
15882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_name = NULL;
15892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_namelen = 0;
15902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_iov = &iov;
15912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_iovlen = 1;
15922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_control = NULL;
15932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_controllen = 0;
15942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	msg.msg_flags = 0;
15952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
15962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	n = recvmsg(b->num, &msg, MSG_PEEK);
15972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (n <= 0)
15982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
15992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
16002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			return -1;
16012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		else
16022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			return 0;
16032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
16042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* if we find a notification, process it and try again if necessary */
16062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	while (msg.msg_flags & MSG_NOTIFICATION)
16072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
16082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memset(&snp, 0x00, sizeof(union sctp_notification));
16092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		iov.iov_base = (char *)&snp;
16102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		iov.iov_len = sizeof(union sctp_notification);
16112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_name = NULL;
16122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_namelen = 0;
16132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_iov = &iov;
16142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_iovlen = 1;
16152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_control = NULL;
16162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_controllen = 0;
16172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_flags = 0;
16182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		n = recvmsg(b->num, &msg, 0);
16202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (n <= 0)
16212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
16222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
16232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
16242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			else
16252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return is_dry;
16262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
16272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
16292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
16302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			is_dry = 1;
16312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			/* disable sender dry event */
16332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_EVENT
16342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			memset(&event, 0, sizeof(struct sctp_event));
16352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			event.se_assoc_id = 0;
16362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			event.se_type = SCTP_SENDER_DRY_EVENT;
16372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			event.se_on = 0;
16382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
16392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else
16402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
16412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
16422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret < 0)
16432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
16442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			event.sctp_sender_dry_event = 0;
16462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
16482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
16492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (ret < 0)
16502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
16512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
16522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
16542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
16552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			dgram_sctp_handle_auth_free_key_event(b, &snp);
16562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
16572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (data->handle_notifications != NULL)
16592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			data->handle_notifications(b, data->notification_context, (void*) &snp);
16602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* found notification, peek again */
16622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memset(&snp, 0x00, sizeof(union sctp_notification));
16632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		iov.iov_base = (char *)&snp;
16642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		iov.iov_len = sizeof(union sctp_notification);
16652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_name = NULL;
16662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_namelen = 0;
16672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_iov = &iov;
16682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_iovlen = 1;
16692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_control = NULL;
16702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_controllen = 0;
16712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_flags = 0;
16722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* if we have seen the dry already, don't wait */
16742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (is_dry)
16752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
16762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			sockflags = fcntl(b->num, F_GETFL, 0);
16772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			fcntl(b->num, F_SETFL, O_NONBLOCK);
16782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
16792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		n = recvmsg(b->num, &msg, MSG_PEEK);
16812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (is_dry)
16832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
16842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			fcntl(b->num, F_SETFL, sockflags);
16852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
16862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (n <= 0)
16882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
16892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
16902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return -1;
16912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			else
16922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				return is_dry;
16932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
16942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		}
16952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
16962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* read anything else */
16972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return is_dry;
16982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org}
16992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint BIO_dgram_sctp_msg_waiting(BIO *b)
17012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
17022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int n, sockflags;
17032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	union sctp_notification snp;
17042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct msghdr msg;
17052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	struct iovec iov;
17062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
17072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* Check if there are any messages waiting to be read */
17092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	do
17102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		{
17112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		memset(&snp, 0x00, sizeof(union sctp_notification));
17122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		iov.iov_base = (char *)&snp;
17132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		iov.iov_len = sizeof(union sctp_notification);
17142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_name = NULL;
17152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_namelen = 0;
17162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_iov = &iov;
17172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_iovlen = 1;
17182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_control = NULL;
17192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_controllen = 0;
17202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		msg.msg_flags = 0;
17212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		sockflags = fcntl(b->num, F_GETFL, 0);
17232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		fcntl(b->num, F_SETFL, O_NONBLOCK);
17242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		n = recvmsg(b->num, &msg, MSG_PEEK);
17252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		fcntl(b->num, F_SETFL, sockflags);
17262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		/* if notification, process and try again */
17282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION))
17292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			{
17302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifdef SCTP_AUTHENTICATION_EVENT
17312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
17322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				dgram_sctp_handle_auth_free_key_event(b, &snp);
17332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
17342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			memset(&snp, 0x00, sizeof(union sctp_notification));
17362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			iov.iov_base = (char *)&snp;
17372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			iov.iov_len = sizeof(union sctp_notification);
17382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_name = NULL;
17392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_namelen = 0;
17402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_iov = &iov;
17412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_iovlen = 1;
17422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_control = NULL;
17432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_controllen = 0;
17442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			msg.msg_flags = 0;
17452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			n = recvmsg(b->num, &msg, 0);
17462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			if (data->handle_notifications != NULL)
17482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org				data->handle_notifications(b, data->notification_context, (void*) &snp);
17492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org			}
17502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		} while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
17522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	/* Return 1 if there is a message to be read, return 0 otherwise. */
17542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	if (n > 0)
17552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 1;
17562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	else
17572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		return 0;
17582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
17592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic int dgram_sctp_puts(BIO *bp, const char *str)
17612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	{
17622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	int n,ret;
17632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
17642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	n=strlen(str);
17652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	ret=dgram_sctp_write(bp,str,n);
17662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	return(ret);
17672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org	}
17682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif
17692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org
1770c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int BIO_dgram_should_retry(int i)
1771c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1772c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int err;
1773c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1774c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ((i == 0) || (i == -1))
1775c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1776c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		err=get_last_socket_error();
1777c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1778480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#if defined(OPENSSL_SYS_WINDOWS)
1779480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* If the socket return value (i) is -1
1780480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 * and err is unexpectedly 0 at this point,
1781480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 * the error code was overwritten by
1782480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 * another system call before this error
1783480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 * handling is called.
1784480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	 */
1785c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1786c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1787c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(BIO_dgram_non_fatal_error(err));
1788c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1789c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(0);
1790c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1791c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1792c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint BIO_dgram_non_fatal_error(int err)
1793c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1794c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (err)
1795c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
1796c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(OPENSSL_SYS_WINDOWS)
1797c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# if defined(WSAEWOULDBLOCK)
1798c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case WSAEWOULDBLOCK:
1799c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# endif
1800c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1801c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# if 0 /* This appears to always be an error */
1802c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#  if defined(WSAENOTCONN)
1803c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case WSAENOTCONN:
1804c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#  endif
1805c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# endif
1806c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1807c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1808c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EWOULDBLOCK
1809c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# ifdef WSAEWOULDBLOCK
1810c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#  if WSAEWOULDBLOCK != EWOULDBLOCK
1811c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EWOULDBLOCK:
1812c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#  endif
1813c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# else
1814c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EWOULDBLOCK:
1815c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# endif
1816c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1817c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1818c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EINTR
1819c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EINTR:
1820c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1821c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1822c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EAGAIN
1823c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if EWOULDBLOCK != EAGAIN
1824c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EAGAIN:
1825c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org# endif
1826c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1827c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1828c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EPROTO
1829c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EPROTO:
1830c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1831c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1832c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EINPROGRESS
1833c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EINPROGRESS:
1834c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1835c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1836c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef EALREADY
1837c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case EALREADY:
1838c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1839c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1840c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(1);
1841c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* break; */
1842c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
1843c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
1844c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
1845c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(0);
1846c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1847c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
1848c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void get_current_time(struct timeval *t)
1849c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
1850c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WIN32
1851c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	struct _timeb tb;
1852c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	_ftime(&tb);
1853c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	t->tv_sec = (long)tb.time;
1854c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	t->tv_usec = (long)tb.millitm * 1000;
1855c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#elif defined(OPENSSL_SYS_VMS)
1856c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	struct timeb tb;
1857c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ftime(&tb);
1858c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	t->tv_sec = (long)tb.time;
1859c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	t->tv_usec = (long)tb.millitm * 1000;
1860c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
1861c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	gettimeofday(t, NULL);
1862c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
1863c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
1864480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
1865480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org#endif
1866