1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* crypto/bio/bio_dgram.c */
2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * DTLS implementation written by Nagendra Modadugu
4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* ====================================================================
7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Redistribution and use in source and binary forms, with or without
10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * modification, are permitted provided that the following conditions
11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * are met:
12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 1. Redistributions of source code must retain the above copyright
14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    notice, this list of conditions and the following disclaimer.
15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    notice, this list of conditions and the following disclaimer in
18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    the documentation and/or other materials provided with the
19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    distribution.
20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 3. All advertising materials mentioning features or use of this
22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    software must display the following acknowledgment:
23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    "This product includes software developed by the OpenSSL Project
24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    endorse or promote products derived from this software without
28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    prior written permission. For written permission, please contact
29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    openssl-core@OpenSSL.org.
30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 5. Products derived from this software may not be called "OpenSSL"
32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    nor may "OpenSSL" appear in their names without prior written
33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    permission of the OpenSSL Project.
34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 6. Redistributions of any form whatsoever must retain the following
36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    acknowledgment:
37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    "This product includes software developed by the OpenSSL Project
38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * OF THE POSSIBILITY OF SUCH DAMAGE.
52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ====================================================================
53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * This product includes cryptographic software written by Eric Young
55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * (eay@cryptsoft.com).  This product includes software written by Tim
56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Hudson (tjh@cryptsoft.com).
57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <stdio.h>
62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <errno.h>
63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define USE_SOCKETS
64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "cryptlib.h"
65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/bio.h>
67ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom#ifndef OPENSSL_NO_DGRAM
68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
6998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
7098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#include <sys/timeb.h>
7198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
7298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
73392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
74392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <netinet/sctp.h>
75392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <fcntl.h>
76392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define OPENSSL_SCTP_DATA_CHUNK_TYPE            0x00
77392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
78392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
79392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
8004ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU)
81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define IP_MTU      14 /* linux is lame */
8298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
8404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED)
8504ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom/* Standard definition causes type-punning problems. */
8604ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#undef IN6_IS_ADDR_V4MAPPED
8704ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#define s6_addr32 __u6_addr.__u6_addr32
8804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#define IN6_IS_ADDR_V4MAPPED(a)               \
8904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom        (((a)->s6_addr32[0] == 0) &&          \
9004ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom         ((a)->s6_addr32[1] == 0) &&          \
9104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom         ((a)->s6_addr32[2] == htonl(0x0000ffff)))
9204ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#endif
9304ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom
94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef WATT32
95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define sock_write SockWrite  /* Watt-32 uses same names */
96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define sock_read  SockRead
97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define sock_puts  SockPuts
98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_write(BIO *h, const char *buf, int num);
101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_read(BIO *h, char *buf, int size);
102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_puts(BIO *h, const char *str);
103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_new(BIO *h);
105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_free(BIO *data);
106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_clear(BIO *bio);
107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_write(BIO *h, const char *buf, int num);
110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_read(BIO *h, char *buf, int size);
111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_puts(BIO *h, const char *str);
112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_new(BIO *h);
114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_free(BIO *data);
115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp);
117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
120e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic int BIO_dgram_should_retry(int s);
121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
12298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void get_current_time(struct timeval *t);
12398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic BIO_METHOD methods_dgramp=
125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_TYPE_DGRAM,
127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	"datagram socket",
128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_write,
129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_read,
130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_puts,
131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	NULL, /* dgram_gets, */
132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_ctrl,
133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_new,
134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_free,
135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	NULL,
136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	};
137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic BIO_METHOD methods_dgramp_sctp=
140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO_TYPE_DGRAM_SCTP,
142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	"datagram sctp socket",
143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_write,
144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_read,
145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_puts,
146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	NULL, /* dgram_gets, */
147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_ctrl,
148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_new,
149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_free,
150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	NULL,
151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	};
152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projecttypedef struct bio_dgram_data_st
155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union {
157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr sa;
158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in sa_in;
159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
160221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in6 sa_in6;
161221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} peer;
163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int connected;
164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int _errno;
165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int mtu;
16698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct timeval next_timeout;
16798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct timeval socket_timeout;
168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	} bio_dgram_data;
169656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromtypedef struct bio_dgram_sctp_save_message_st
172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom        BIO *bio;
174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom        char *data;
175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom        int length;
176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} bio_dgram_sctp_save_message;
177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromtypedef struct bio_dgram_sctp_data_st
179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union {
181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sockaddr sa;
182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sockaddr_in sa_in;
183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if OPENSSL_USE_IPV6
184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sockaddr_in6 sa_in6;
185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} peer;
187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int connected;
188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int _errno;
189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int mtu;
190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_sndinfo sndinfo;
191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_rcvinfo rcvinfo;
192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_prinfo prinfo;
193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*handle_notifications)(BIO *bio, void *context, void *buf);
194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void* notification_context;
195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int in_handshake;
196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ccs_rcvd;
197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ccs_sent;
198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int save_shutdown;
199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int peer_auth_tested;
200392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_save_message saved_message;
201392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} bio_dgram_sctp_data;
202392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
203392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectBIO_METHOD *BIO_s_datagram(void)
205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(&methods_dgramp);
207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectBIO *BIO_new_dgram(int fd, int close_flag)
210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO *ret;
212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret=BIO_new(BIO_s_datagram());
214656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ret == NULL) return(NULL);
215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_set_fd(ret,fd,close_flag);
216656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
218656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
219656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_new(BIO *bi)
220656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
221656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = NULL;
222656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
223656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bi->init=0;
224656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bi->num=0;
225656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	data = OPENSSL_malloc(sizeof(bio_dgram_data));
226656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (data == NULL)
227656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
228656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	memset(data, 0x00, sizeof(bio_dgram_data));
229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    bi->ptr = data;
230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bi->flags=0;
232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(1);
233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_free(BIO *a)
236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
237656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data;
238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a == NULL) return(0);
240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if ( ! dgram_clear(a))
241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
243656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	data = (bio_dgram_data *)a->ptr;
244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if(data != NULL) OPENSSL_free(data);
245656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(1);
247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_clear(BIO *a)
250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
251656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a == NULL) return(0);
252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->shutdown)
253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
254656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (a->init)
255656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
256656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			SHUTDOWN2(a->num);
257656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
258656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		a->init=0;
259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		a->flags=0;
260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
261656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(1);
262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
26398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
26498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void dgram_adjust_rcv_timeout(BIO *b)
26598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	{
26698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#if defined(SO_RCVTIMEO)
26798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
26804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom	union { size_t s; int i; } sz = {0};
26998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
27098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	/* Is a timer active? */
27198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
27298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		{
27398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		struct timeval timenow, timeleft;
27498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
27598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Read current socket timeout */
27698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
27798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		int timeout;
27804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom
27904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		sz.i = sizeof(timeout);
28098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
28104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom					   (void*)&timeout, &sz.i) < 0)
28298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("getsockopt"); }
28398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		else
28498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
28598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			data->socket_timeout.tv_sec = timeout / 1000;
28698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
28798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
28898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
28904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		sz.i = sizeof(data->socket_timeout);
29098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
29198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom						&(data->socket_timeout), (void *)&sz) < 0)
29298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("getsockopt"); }
29304ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
29404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			OPENSSL_assert(sz.s<=sizeof(data->socket_timeout));
29598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
29698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
29798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Get current time */
29898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		get_current_time(&timenow);
29998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
30098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Calculate time left until timer expires */
30198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
30298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		timeleft.tv_sec -= timenow.tv_sec;
30398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		timeleft.tv_usec -= timenow.tv_usec;
30498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (timeleft.tv_usec < 0)
30598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
30698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_sec--;
30798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_usec += 1000000;
30898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
30998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
31098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (timeleft.tv_sec < 0)
31198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
31298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_sec = 0;
31398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_usec = 1;
31498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
31598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
31698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Adjust socket timeout if next handhake message timer
31798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		 * will expire earlier.
31898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		 */
31998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) ||
32098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			(data->socket_timeout.tv_sec > timeleft.tv_sec) ||
32198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			(data->socket_timeout.tv_sec == timeleft.tv_sec &&
32298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			 data->socket_timeout.tv_usec >= timeleft.tv_usec))
32398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
32498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
32598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
32698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
32798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom						   (void*)&timeout, sizeof(timeout)) < 0)
32898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{ perror("setsockopt"); }
32998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
33098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
33198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom							sizeof(struct timeval)) < 0)
33298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{ perror("setsockopt"); }
33398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
33498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
33598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		}
33698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
33798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	}
33898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
33998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void dgram_reset_rcv_timeout(BIO *b)
34098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	{
34198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#if defined(SO_RCVTIMEO)
34298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
34398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
34498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	/* Is a timer active? */
34598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
34698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		{
34798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
34898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		int timeout = data->socket_timeout.tv_sec * 1000 +
34998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom					  data->socket_timeout.tv_usec / 1000;
35098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
35198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom					   (void*)&timeout, sizeof(timeout)) < 0)
35298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("setsockopt"); }
35398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
35498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout),
35598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom						sizeof(struct timeval)) < 0)
35698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("setsockopt"); }
35798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
35898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		}
35998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
36098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	}
36198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
362656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_read(BIO *b, char *out, int outl)
363656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
364656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret=0;
365656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
366656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
367221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	struct	{
368221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/*
369221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	 * See commentary in b_sock.c. <appro>
370221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	 */
371221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union	{ size_t s; int i; } len;
372221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union	{
373221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr sa;
374221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in sa_in;
375221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
376221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in6 sa_in6;
377221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
378221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		} peer;
379221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} sa;
380221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
381221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	sa.len.s=0;
382221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	sa.len.i=sizeof(sa.peer);
383656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
384656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (out != NULL)
385656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
386656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		clear_socket_error();
387221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memset(&sa.peer, 0x00, sizeof(sa.peer));
38898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		dgram_adjust_rcv_timeout(b);
389221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len);
390221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0)
391221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
392221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			OPENSSL_assert(sa.len.s<=sizeof(sa.peer));
393221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			sa.len.i = (int)sa.len.s;
394221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
395656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
39698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ( ! data->connected  && ret >= 0)
397221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
398656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
399656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BIO_clear_retry_flags(b);
40098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (ret < 0)
401656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
402656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (BIO_dgram_should_retry(ret))
403656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
404656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				BIO_set_retry_read(b);
405656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				data->_errno = get_last_socket_error();
406656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
407656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
408ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom
409ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom		dgram_reset_rcv_timeout(b);
410656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
411656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
412656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
413656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
414656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_write(BIO *b, const char *in, int inl)
415656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
416656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret;
417656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
418656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	clear_socket_error();
419656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
420221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if ( data->connected )
421221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=writesocket(b->num,in,inl);
422221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
423221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
424221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		int peerlen = sizeof(data->peer);
425221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
426221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (data->peer.sa.sa_family == AF_INET)
427221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			peerlen = sizeof(data->peer.sa_in);
42881c4de7869b646592127e952cda763abf8305069Brian Carlstrom#if OPENSSL_USE_IPV6
429221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else if (data->peer.sa.sa_family == AF_INET6)
430221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			peerlen = sizeof(data->peer.sa_in6);
431221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
432656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
433221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen);
434656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#else
435221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
436656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
437221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
438656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
439656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_clear_retry_flags(b);
440656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ret <= 0)
441656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
44298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (BIO_dgram_should_retry(ret))
443656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
444656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			BIO_set_retry_write(b);
445656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->_errno = get_last_socket_error();
446656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
447656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if 0 /* higher layers are responsible for querying MTU, if necessary */
448656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if ( data->_errno == EMSGSIZE)
449656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				/* retrieve the new MTU */
450656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
451656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
452656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
453656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
454656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
455656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
456656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
457656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
458656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
459656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	long ret=1;
460656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int *ip;
461656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	struct sockaddr *to = NULL;
462656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = NULL;
46304ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
46404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom	int sockopt_val = 0;
46504ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom	socklen_t sockopt_len;	/* assume that system supporting IP_MTU is
46604ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom				 * modern enough to define socklen_t */
46798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	socklen_t addr_len;
468221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union	{
469221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr	sa;
470221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in s4;
471221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
472221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in6 s6;
473221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
474221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		} addr;
47598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
476656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
477656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	data = (bio_dgram_data *)b->ptr;
478656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
479656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	switch (cmd)
480656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
481656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_RESET:
482656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		num=0;
483656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_FILE_SEEK:
484656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
485656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
486656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_FILE_TELL:
487656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_INFO:
488656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
489656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
490656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_SET_FD:
491656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		dgram_clear(b);
492656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->num= *((int *)ptr);
493656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->shutdown=(int)num;
494656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->init=1;
495656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
496656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_GET_FD:
497656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (b->init)
498656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
499656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ip=(int *)ptr;
500656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (ip != NULL) *ip=b->num;
501656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret=b->num;
502656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
503656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
504656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret= -1;
505656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
506656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_GET_CLOSE:
507656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=b->shutdown;
508656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
509656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_SET_CLOSE:
510656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->shutdown=(int)num;
511656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
512656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_PENDING:
513656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_WPENDING:
514656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
515656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
516656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DUP:
517656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_FLUSH:
518656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=1;
519656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
520656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_CONNECT:
521656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		to = (struct sockaddr *)ptr;
522656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if 0
523656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
524656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("connect"); ret = 0; }
525656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
526656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
527656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
528221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			switch (to->sa_family)
529221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				{
530221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET:
531221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
532221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
533221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
534221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET6:
535221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
536221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
537221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
538221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				default:
539221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa));
540221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
541221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
542656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if 0
543656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
544656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
545656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
546656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* (Linux)kernel sets DF bit on outgoing IP packets */
547656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_MTU_DISCOVER:
54804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
549221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		addr_len = (socklen_t)sizeof(addr);
550221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memset((void *)&addr, 0, sizeof(addr));
551221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
55298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
55398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = 0;
55498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
55598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
556221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (addr.sa.sa_family)
55798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
55898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET:
55998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			sockopt_val = IP_PMTUDISC_DO;
56098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
56198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_val, sizeof(sockopt_val))) < 0)
56298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				perror("setsockopt");
56398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
56404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
56598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET6:
56698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			sockopt_val = IPV6_PMTUDISC_DO;
56798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
56898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_val, sizeof(sockopt_val))) < 0)
56998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				perror("setsockopt");
57098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
571221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
57298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		default:
57398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = -1;
57498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
57598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
57698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		ret = -1;
57798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
578656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
579656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
580656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_QUERY_MTU:
58104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU)
582221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		addr_len = (socklen_t)sizeof(addr);
583221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memset((void *)&addr, 0, sizeof(addr));
584221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
585656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
58698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = 0;
58798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
588656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
58998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		sockopt_len = sizeof(sockopt_val);
590221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (addr.sa.sa_family)
59198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
59298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET:
59398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
59498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_len)) < 0 || sockopt_val < 0)
59598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
59698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = 0;
59798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
59898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			else
59998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
60098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				/* we assume that the transport protocol is UDP and no
60198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 * IP options are used.
60298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 */
60398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				data->mtu = sockopt_val - 8 - 20;
60498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = data->mtu;
60598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
60698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
607221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
60898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET6:
60998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
61098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_len)) < 0 || sockopt_val < 0)
61198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
61298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = 0;
61398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
61498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			else
61598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
61698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				/* we assume that the transport protocol is UDP and no
61798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 * IPV6 options are used.
61898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 */
61998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				data->mtu = sockopt_val - 8 - 40;
62098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = data->mtu;
62198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
62298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
623221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
62498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		default:
62598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = 0;
62698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
62798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
62898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
62998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		ret = 0;
63098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
631656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
63221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
63321c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom		switch (data->peer.sa.sa_family)
63421c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			{
63521c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			case AF_INET:
63621c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				ret = 576 - 20 - 8;
63721c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				break;
63821c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#if OPENSSL_USE_IPV6
63921c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			case AF_INET6:
64021c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#ifdef IN6_IS_ADDR_V4MAPPED
64121c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
64221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom					ret = 576 - 20 - 8;
64321c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				else
64421c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#endif
64521c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom					ret = 1280 - 40 - 8;
64621c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				break;
64721c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#endif
64821c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			default:
64921c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				ret = 576 - 20 - 8;
65021c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				break;
65121c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			}
65221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom		break;
653656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_MTU:
654656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return data->mtu;
655656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
656656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_MTU:
657656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		data->mtu = num;
658656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret = num;
659656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
660656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_CONNECTED:
661656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		to = (struct sockaddr *)ptr;
662656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
663656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( to != NULL)
664656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
665656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->connected = 1;
666221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			switch (to->sa_family)
667221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				{
668221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET:
669221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
670221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
671221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
672221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET6:
673221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
674221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
675221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
676221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				default:
677221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa));
678221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
679221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
680656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
681656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
682656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
683656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->connected = 0;
684221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			memset(&(data->peer), 0x00, sizeof(data->peer));
685221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
686221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
687221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	case BIO_CTRL_DGRAM_GET_PEER:
688221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (data->peer.sa.sa_family)
689221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
690221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET:
691221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ret=sizeof(data->peer.sa_in);
692221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
693221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
694221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET6:
695221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ret=sizeof(data->peer.sa_in6);
696221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
697221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
698221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			default:
699221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ret=sizeof(data->peer.sa);
700221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
701221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
702221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (num==0 || num>ret)
703221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			num=ret;
704221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memcpy(ptr,&data->peer,(ret=num));
705221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
706221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	case BIO_CTRL_DGRAM_SET_PEER:
707221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		to = (struct sockaddr *) ptr;
708221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (to->sa_family)
709221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
710221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET:
711221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				memcpy(&data->peer,to,sizeof(data->peer.sa_in));
712221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
713221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
714221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET6:
715221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
716221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
717221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
718221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			default:
719221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				memcpy(&data->peer,to,sizeof(data->peer.sa));
720221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
721656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
722656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
72398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
724221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
72598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		break;
726e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#if defined(SO_RCVTIMEO)
727656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
728e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
729e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
730e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
731e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
732e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
733e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			(void*)&timeout, sizeof(timeout)) < 0)
734e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("setsockopt"); ret = -1; }
735e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		}
736e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
737656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
738656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			sizeof(struct timeval)) < 0)
739656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("setsockopt");	ret = -1; }
740e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
741656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
742656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
743e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
74404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		union { size_t s; int i; } sz = {0};
74504ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
74604ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		int timeout;
747e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
74804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom
74904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		sz.i = sizeof(timeout);
750e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
75104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			(void*)&timeout, &sz.i) < 0)
752e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("getsockopt"); ret = -1; }
753e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		else
754e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{
755e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_sec = timeout / 1000;
756e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_usec = (timeout % 1000) * 1000;
757e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			ret = sizeof(*tv);
758e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			}
759e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
76004ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		sz.i = sizeof(struct timeval);
761656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
76204ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			ptr, (void *)&sz) < 0)
763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("getsockopt"); ret = -1; }
76404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
76504ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			{
76604ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			OPENSSL_assert(sz.s<=sizeof(struct timeval));
76704ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			ret = (int)sz.s;
76804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			}
76904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		else
77004ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			ret = sz.i;
771e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
77204ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		}
773656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
774e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
775e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#if defined(SO_SNDTIMEO)
776656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
777e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
778e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
779e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
780e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
781e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
782e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			(void*)&timeout, sizeof(timeout)) < 0)
783e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("setsockopt"); ret = -1; }
784e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		}
785e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
786656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
787656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			sizeof(struct timeval)) < 0)
788656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("setsockopt");	ret = -1; }
789e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
790656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
791656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
792e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
79304ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		union { size_t s; int i; } sz = {0};
79404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
79504ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		int timeout;
796e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
79704ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom
79804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		sz.i = sizeof(timeout);
799e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
80004ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			(void*)&timeout, &sz.i) < 0)
801e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("getsockopt"); ret = -1; }
802e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		else
803e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{
804e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_sec = timeout / 1000;
805e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_usec = (timeout % 1000) * 1000;
806e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			ret = sizeof(*tv);
807e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			}
808e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
80904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		sz.i = sizeof(struct timeval);
810656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
81104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			ptr, (void *)&sz) < 0)
812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("getsockopt"); ret = -1; }
81304ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
81404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			{
81504ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			OPENSSL_assert(sz.s<=sizeof(struct timeval));
81604ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			ret = (int)sz.s;
81704ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			}
81804ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		else
81904ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom			ret = sz.i;
820e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
82104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		}
822656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
823e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
824656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
825656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* fall-through */
826656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
827e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
828e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if ( data->_errno == WSAETIMEDOUT)
829e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
830656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( data->_errno == EAGAIN)
831e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
832656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
833656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 1;
834656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->_errno = 0;
835656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
836656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
837656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 0;
838656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
839656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EMSGSIZE
840656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
841656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( data->_errno == EMSGSIZE)
842656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
843656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 1;
844656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->_errno = 0;
845656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
846656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
847656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 0;
848656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
849656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
850656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	default:
851656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
852656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
853656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
854656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
855656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
856656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
857656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_puts(BIO *bp, const char *str)
858656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
859656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int n,ret;
860656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
861656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n=strlen(str);
862656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret=dgram_write(bp,str,n);
863656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
864656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
865656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
866392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
867392aa7cc7d2b122614c5393c3e357da07fd07af3Brian CarlstromBIO_METHOD *BIO_s_datagram_sctp(void)
868392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
869392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(&methods_dgramp_sctp);
870392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
871392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
872392aa7cc7d2b122614c5393c3e357da07fd07af3Brian CarlstromBIO *BIO_new_dgram_sctp(int fd, int close_flag)
873392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
874392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO *bio;
875392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret, optval = 20000;
876392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int auth_data = 0, auth_forward = 0;
877392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned char *p;
878392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authchunk auth;
879392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authchunks *authchunks;
880392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	socklen_t sockopt_len;
881392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
882392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
883392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event event;
884392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
885392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event_subscribe event;
886392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
887392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
888392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
889392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio=BIO_new(BIO_s_datagram_sctp());
890392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (bio == NULL) return(NULL);
891392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO_set_fd(bio,fd,close_flag);
892392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
893392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
894392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
895392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
896392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
897392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
898392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
899392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
900392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
901392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Test if activation was successful. When using accept(),
902392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * SCTP-AUTH has to be activated for the listening socket
903392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * already, otherwise the connected socket won't use it. */
904392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
905392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	authchunks = OPENSSL_malloc(sockopt_len);
906392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(authchunks, 0, sizeof(sockopt_len));
907392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
908392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
909ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
910ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	for (p = (unsigned char*) authchunks->gauth_chunks;
911392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	     p < (unsigned char*) authchunks + sockopt_len;
912392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	     p += sizeof(uint8_t))
913392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
914392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
915392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
916392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
917392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
918392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_free(authchunks);
919392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
920392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(auth_data);
921392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(auth_forward);
922392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
923392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
924392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
925392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(&event, 0, sizeof(struct sctp_event));
926392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_assoc_id = 0;
927392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_type = SCTP_AUTHENTICATION_EVENT;
928392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_on = 1;
929392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
930392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
931392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
932392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
933392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
934392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
935392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
936392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.sctp_authentication_event = 1;
937392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
938392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
939392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
940392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
941392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
942392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
943392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Disable partial delivery by setting the min size
944392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * larger than the max record size of 2^14 + 2048 + 13
945392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
946392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
947392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
948392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
949392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(bio);
950392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
951392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
952392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_is_sctp(BIO *bio)
953392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
954392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
955392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
956392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
957392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_new(BIO *bi)
958392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
959392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = NULL;
960392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
961392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bi->init=0;
962392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bi->num=0;
963392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data));
964392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (data == NULL)
965392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
966392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(data, 0x00, sizeof(bio_dgram_sctp_data));
967392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_PR_SCTP_NONE
968392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
969392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
970392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    bi->ptr = data;
971392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
972392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bi->flags=0;
973392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(1);
974392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
975392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
976392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_free(BIO *a)
977392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
978392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data;
979392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
980392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (a == NULL) return(0);
981392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ( ! dgram_clear(a))
982392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
983392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
984392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data = (bio_dgram_sctp_data *)a->ptr;
985392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if(data != NULL) OPENSSL_free(data);
986392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
987392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(1);
988392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
989392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
990392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
991392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
992392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
993392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret;
994392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
995392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
996392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY)
997392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
998392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sctp_authkeyid authkeyid;
999392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1000392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* delete key */
1001392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
1002392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
100304ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom		      &authkeyid, sizeof(struct sctp_authkeyid));
1004392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1005392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1006392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1007392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1008392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_read(BIO *b, char *out, int outl)
1009392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1010392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret = 0, n = 0, i, optval;
1011392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	socklen_t optlen;
1012392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1013392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union sctp_notification *snp;
1014392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1015392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov;
1016392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct cmsghdr *cmsg;
1017392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	char cmsgbuf[512];
1018392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1019392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (out != NULL)
1020392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1021392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		clear_socket_error();
1022392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1023392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		do
1024392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1025392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
1026392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_base = out;
1027392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_len = outl;
1028392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_name = NULL;
1029392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_namelen = 0;
1030392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iov = &iov;
1031392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iovlen = 1;
1032392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_control = cmsgbuf;
1033392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_controllen = 512;
1034392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_flags = 0;
1035392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = recvmsg(b->num, &msg, 0);
1036392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1037392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (msg.msg_controllen > 0)
1038392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1039392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
1040392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					{
1041392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (cmsg->cmsg_level != IPPROTO_SCTP)
1042392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						continue;
1043392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_RCVINFO
1044392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (cmsg->cmsg_type == SCTP_RCVINFO)
1045392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						{
1046392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						struct sctp_rcvinfo *rcvinfo;
1047392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1048392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
1049392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
1050392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
1051392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
1052392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
1053392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
1054392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
1055392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_context = rcvinfo->rcv_context;
1056392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						}
1057392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1058392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_SNDRCV
1059392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (cmsg->cmsg_type == SCTP_SNDRCV)
1060392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						{
1061392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						struct sctp_sndrcvinfo *sndrcvinfo;
1062392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1063392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1064392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
1065392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
1066392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
1067392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
1068392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
1069392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
1070392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
1071392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						}
1072392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1073392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					}
1074392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1075392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1076392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (n <= 0)
1077392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1078392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (n < 0)
1079392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					ret = n;
1080392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				break;
1081392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1082392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1083392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (msg.msg_flags & MSG_NOTIFICATION)
1084392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1085392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				snp = (union sctp_notification*) out;
1086392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
1087392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					{
1088392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1089392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					struct sctp_event event;
1090392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1091392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					struct sctp_event_subscribe event;
1092392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					socklen_t eventsize;
1093392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1094392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					/* If a message has been delayed until the socket
1095392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					 * is dry, it can be sent now.
1096392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					 */
1097392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (data->saved_message.length > 0)
1098392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						{
1099392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
1100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						                 data->saved_message.length);
1101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						OPENSSL_free(data->saved_message.data);
1102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->saved_message.length = 0;
1103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						}
1104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					/* disable sender dry event */
1106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					memset(&event, 0, sizeof(struct sctp_event));
1108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.se_assoc_id = 0;
1109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.se_type = SCTP_SENDER_DRY_EVENT;
1110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.se_on = 0;
1111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					OPENSSL_assert(i >= 0);
1113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					eventsize = sizeof(struct sctp_event_subscribe);
1115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					OPENSSL_assert(i >= 0);
1117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.sctp_sender_dry_event = 0;
1119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1120392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1121392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					OPENSSL_assert(i >= 0);
1122392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					}
1124392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
1126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					dgram_sctp_handle_auth_free_key_event(b, snp);
1128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (data->handle_notifications != NULL)
1131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					data->handle_notifications(b, data->notification_context, (void*) out);
1132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				memset(out, 0, outl);
1134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ret += n;
1137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
1139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret > 0 && !(msg.msg_flags & MSG_EOR))
1141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Partial message read, this should never happen! */
1143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* The buffer was too small, this means the peer sent
1145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * a message that was larger than allowed. */
1146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret == outl)
1147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Test if socket buffer can handle max record
1150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * size (2^14 + 2048 + 13)
1151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			optlen = (socklen_t) sizeof(int);
1153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
1154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(ret >= 0);
1155392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(optval >= 18445);
1156392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1157392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Test if SCTP doesn't partially deliver below
1158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * max record size (2^14 + 2048 + 13)
1159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			optlen = (socklen_t) sizeof(int);
1161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
1162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			                 &optval, &optlen);
1163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(ret >= 0);
1164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(optval >= 18445);
1165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Partially delivered notification??? Probably a bug.... */
1167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
1168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Everything seems ok till now, so it's most likely
1170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * a message dropped by PR-SCTP.
1171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(out, 0, outl);
1173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			BIO_set_retry_read(b);
1174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return -1;
1175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BIO_clear_retry_flags(b);
1178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0)
1179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (BIO_dgram_should_retry(ret))
1181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				BIO_set_retry_read(b);
1183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				data->_errno = get_last_socket_error();
1184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Test if peer uses SCTP-AUTH before continuing */
1188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!data->peer_auth_tested)
1189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			int ii, auth_data = 0, auth_forward = 0;
1191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			unsigned char *p;
1192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			struct sctp_authchunks *authchunks;
1193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
1195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			authchunks = OPENSSL_malloc(optlen);
1196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(authchunks, 0, sizeof(optlen));
1197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
1198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(ii >= 0);
1199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1200ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (p = (unsigned char*) authchunks->gauth_chunks;
1201392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				 p < (unsigned char*) authchunks + optlen;
1202392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				 p += sizeof(uint8_t))
1203392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1204392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
1205392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
1206392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1207392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1208392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_free(authchunks);
1209392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1210392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (!auth_data || !auth_forward)
1211392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1212392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				BIOerr(BIO_F_DGRAM_SCTP_READ,BIO_R_CONNECT_ERROR);
1213392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1214392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1215392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1216392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->peer_auth_tested = 1;
1217392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1218392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1219392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1220392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1221392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1222392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_write(BIO *b, const char *in, int inl)
1223392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1224392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret;
1225392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1226392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
1227392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
1228392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_sndinfo handshake_sinfo;
1229392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov[1];
1230392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1231392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct cmsghdr *cmsg;
1232392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1233392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
1234392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_sndinfo *sndinfo;
1235392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_prinfo *prinfo;
1236392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1237392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1238392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_sndrcvinfo *sndrcvinfo;
1239392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1240392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1241392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	clear_socket_error();
1242392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1243392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* If we're send anything else than application data,
1244392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * disable all user parameters and flags.
1245392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
1246392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (in[0] != 23) {
1247392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo));
1248392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_SACK_IMMEDIATELY
1249392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
1250392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1251392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sinfo = &handshake_sinfo;
1252392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1253392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1254392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* If we have to send a shutdown alert message and the
1255392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * socket is not dry yet, we have to save it and send it
1256392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * as soon as the socket gets dry.
1257392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
1258392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b))
1259392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1260392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->saved_message.bio = b;
1261392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->saved_message.length = inl;
1262392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->saved_message.data = OPENSSL_malloc(inl);
1263392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(data->saved_message.data, in, inl);
1264392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return inl;
1265392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1266392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1267392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov[0].iov_base = (char *)in;
1268392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov[0].iov_len = inl;
1269392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_name = NULL;
1270392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_namelen = 0;
1271392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iov = iov;
1272392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iovlen = 1;
1273392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_control = (caddr_t)cmsgbuf;
1274392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen = 0;
1275392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_flags = 0;
1276392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1277392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg = (struct cmsghdr *)cmsgbuf;
1278392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_level = IPPROTO_SCTP;
1279392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_type = SCTP_SNDINFO;
1280392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
1281392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
1282392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
1283392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_sid = sinfo->snd_sid;
1284392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_flags = sinfo->snd_flags;
1285392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_ppid = sinfo->snd_ppid;
1286392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_context = sinfo->snd_context;
1287392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
1288392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1289392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
1290392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_level = IPPROTO_SCTP;
1291392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_type = SCTP_PRINFO;
1292392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
1293392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
1294392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(prinfo, 0, sizeof(struct sctp_prinfo));
1295392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	prinfo->pr_policy = pinfo->pr_policy;
1296392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	prinfo->pr_value = pinfo->pr_value;
1297392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
1298392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1299392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg = (struct cmsghdr *)cmsgbuf;
1300392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_level = IPPROTO_SCTP;
1301392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_type = SCTP_SNDRCV;
1302392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
1303392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1304392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
1305392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_stream = sinfo->snd_sid;
1306392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_flags = sinfo->snd_flags;
1307392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef __FreeBSD__
1308392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_flags |= pinfo->pr_policy;
1309392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1310392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
1311392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_context = sinfo->snd_context;
1312392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
1313392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
1314392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1315392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1316392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = sendmsg(b->num, &msg, 0);
1317392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1318392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO_clear_retry_flags(b);
1319392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ret <= 0)
1320392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1321392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (BIO_dgram_should_retry(ret))
1322392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1323392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			BIO_set_retry_write(b);
1324392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->_errno = get_last_socket_error();
1325392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1326392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1327392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1328392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1329392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1330392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
1331392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1332392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	long ret=1;
1333392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = NULL;
133404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom	socklen_t sockopt_len = 0;
1335392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authkeyid authkeyid;
133677c6be7176c48d2ce4d5979a84876d34204eedafKenny Root	struct sctp_authkey *authkey = NULL;
1337392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1338392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data = (bio_dgram_sctp_data *)b->ptr;
1339392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1340392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	switch (cmd)
1341392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1342392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_QUERY_MTU:
1343392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Set to maximum (2^14)
1344392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * and ignore user input to enable transport
1345392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * protocol fragmentation.
1346392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns always 2^14.
1347392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1348392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->mtu = 16384;
1349392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = data->mtu;
1350392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1351392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SET_MTU:
1352392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Set to maximum (2^14)
1353392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * and ignore input to enable transport
1354392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * protocol fragmentation.
1355392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns always 2^14.
1356392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1357392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->mtu = 16384;
1358392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = data->mtu;
1359392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1360392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SET_CONNECTED:
1361392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_CONNECT:
1362392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns always -1. */
1363392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = -1;
1364392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1365392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
1366392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* SCTP doesn't need the DTLS timer
1367392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns always 1.
1368392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1369392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1370392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
1371392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > 0)
1372392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->in_handshake = 1;
1373392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1374392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->in_handshake = 0;
1375392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1376392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
1377392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1378392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
1379392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* New shared key for SCTP AUTH.
1380392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns 0 on success, -1 otherwise.
1381392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1382392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1383392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Get active key */
1384392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkeyid);
1385392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1386392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1387392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1388392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Add new key */
1389392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
1390392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkey = OPENSSL_malloc(sockopt_len);
139177c6be7176c48d2ce4d5979a84876d34204eedafKenny Root		if (authkey == NULL)
139277c6be7176c48d2ce4d5979a84876d34204eedafKenny Root			{
139377c6be7176c48d2ce4d5979a84876d34204eedafKenny Root			ret = -1;
139477c6be7176c48d2ce4d5979a84876d34204eedafKenny Root			break;
139577c6be7176c48d2ce4d5979a84876d34204eedafKenny Root			}
1396392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(authkey, 0x00, sockopt_len);
1397392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
1398392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef __FreeBSD__
1399392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* This field is missing in FreeBSD 8.2 and earlier,
1400392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * and FreeBSD 8.3 and higher work without it.
1401392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1402392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkey->sca_keylength = 64;
1403392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1404392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
1405392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1406392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
140777c6be7176c48d2ce4d5979a84876d34204eedafKenny Root		OPENSSL_free(authkey);
140877c6be7176c48d2ce4d5979a84876d34204eedafKenny Root		authkey = NULL;
1409392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1410392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1411392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Reset active key */
1412392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1413392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		      &authkeyid, sizeof(struct sctp_authkeyid));
1414392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1415392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1416392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1417392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
1418392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns 0 on success, -1 otherwise. */
1419392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1420392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Get active key */
1421392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkeyid);
1422392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1423392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1424392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1425392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Set active key */
1426392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
1427392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1428392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		      &authkeyid, sizeof(struct sctp_authkeyid));
1429392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1430392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1431392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* CCS has been sent, so remember that and fall through
1432392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * to check if we need to deactivate an old key
1433392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1434392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->ccs_sent = 1;
1435392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1436392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
1437392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns 0 on success, -1 otherwise. */
1438392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1439392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Has this command really been called or is this just a fall-through? */
1440392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
1441392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->ccs_rcvd = 1;
1442392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1443392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* CSS has been both, received and sent, so deactivate an old key */
1444392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (data->ccs_rcvd == 1 && data->ccs_sent == 1)
1445392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1446392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Get active key */
1447392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			sockopt_len = sizeof(struct sctp_authkeyid);
1448392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1449392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0) break;
1450392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1451392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Deactivate key or delete second last key if
1452392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * SCTP_AUTHENTICATION_EVENT is not available.
1453392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1454392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1455392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTH_DEACTIVATE_KEY
1456392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			sockopt_len = sizeof(struct sctp_authkeyid);
1457392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,
1458392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			      &authkeyid, sockopt_len);
1459392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0) break;
1460392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1461392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef SCTP_AUTHENTICATION_EVENT
1462392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (authkeyid.scact_keynumber > 0)
1463392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1464392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1465392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
1466392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					  &authkeyid, sizeof(struct sctp_authkeyid));
1467392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (ret < 0) break;
1468392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1469392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1470392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1471392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->ccs_rcvd = 0;
1472392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->ccs_sent = 0;
1473392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1474392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1475392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
1476392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1477392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1478392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_sndinfo);
1479392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1480392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ptr, &(data->sndinfo), num);
1481392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = num;
1482392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1483392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
1484392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1485392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1486392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_sndinfo);
1487392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1488392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&(data->sndinfo), ptr, num);
1489392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1490392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
1491392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1492392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1493392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_rcvinfo);
1494392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1495392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ptr, &data->rcvinfo, num);
1496392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1497392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = num;
1498392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1499392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
1500392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1501392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1502392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_rcvinfo);
1503392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1504392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&(data->rcvinfo), ptr, num);
1505392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1506392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
1507392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1508392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1509392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_prinfo);
1510392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1511392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ptr, &(data->prinfo), num);
1512392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = num;
1513392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1514392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
1515392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1516392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1517392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_prinfo);
1518392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1519392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&(data->prinfo), ptr, num);
1520392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1521392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
1522392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns always 1. */
1523392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > 0)
1524392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->save_shutdown = 1;
1525392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1526392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->save_shutdown = 0;
1527392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1528392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1529392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	default:
1530392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Pass to default ctrl function to
1531392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * process SCTP unspecific commands
1532392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1533392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret=dgram_ctrl(b, cmd, num, ptr);
1534392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1535392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1536392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1537392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1538392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1539392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_sctp_notification_cb(BIO *b,
1540392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom                                   void (*handle_notifications)(BIO *bio, void *context, void *buf),
1541392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom                                   void *context)
1542392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1543392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1544392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1545392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (handle_notifications != NULL)
1546392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1547392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->handle_notifications = handle_notifications;
1548392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->notification_context = context;
1549392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1550392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1551392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1552392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1553392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1554392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1555392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1556392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_sctp_wait_for_dry(BIO *b)
1557392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1558392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int is_dry = 0;
1559392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int n, sockflags, ret;
1560392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union sctp_notification snp;
1561392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1562392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov;
1563392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1564392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event event;
1565392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1566392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event_subscribe event;
1567392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	socklen_t eventsize;
1568392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1569392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1570392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1571392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* set sender dry event */
1572392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1573392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(&event, 0, sizeof(struct sctp_event));
1574392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_assoc_id = 0;
1575392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_type = SCTP_SENDER_DRY_EVENT;
1576392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_on = 1;
1577392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1578392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1579392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	eventsize = sizeof(struct sctp_event_subscribe);
1580392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1581392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ret < 0)
1582392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1583392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1584392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.sctp_sender_dry_event = 1;
1585392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1586392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1587392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1588392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ret < 0)
1589392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1590392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1591392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* peek for notification */
1592392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(&snp, 0x00, sizeof(union sctp_notification));
1593392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov.iov_base = (char *)&snp;
1594392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov.iov_len = sizeof(union sctp_notification);
1595392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_name = NULL;
1596392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_namelen = 0;
1597392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iov = &iov;
1598392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iovlen = 1;
1599392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_control = NULL;
1600392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen = 0;
1601392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_flags = 0;
1602392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1603392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = recvmsg(b->num, &msg, MSG_PEEK);
1604392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n <= 0)
1605392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1606392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
1607392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return -1;
1608392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1609392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
1610392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1611392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1612392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* if we find a notification, process it and try again if necessary */
1613392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (msg.msg_flags & MSG_NOTIFICATION)
1614392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1615392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&snp, 0x00, sizeof(union sctp_notification));
1616392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_base = (char *)&snp;
1617392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_len = sizeof(union sctp_notification);
1618392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_name = NULL;
1619392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_namelen = 0;
1620392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iov = &iov;
1621392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iovlen = 1;
1622392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_control = NULL;
1623392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_controllen = 0;
1624392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_flags = 0;
1625392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1626392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = recvmsg(b->num, &msg, 0);
1627392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n <= 0)
1628392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1629392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
1630392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1631392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1632392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return is_dry;
1633392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1634392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1635392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
1636392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1637392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			is_dry = 1;
1638392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1639392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* disable sender dry event */
1640392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1641392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(&event, 0, sizeof(struct sctp_event));
1642392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.se_assoc_id = 0;
1643392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.se_type = SCTP_SENDER_DRY_EVENT;
1644392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.se_on = 0;
1645392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1646392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1647392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
1648392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1649392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0)
1650392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1651392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1652392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.sctp_sender_dry_event = 0;
1653392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1654392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1655392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1656392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0)
1657392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1658392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1659392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1660392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
1661392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1662392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			dgram_sctp_handle_auth_free_key_event(b, &snp);
1663392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1664392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1665392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (data->handle_notifications != NULL)
1666392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->handle_notifications(b, data->notification_context, (void*) &snp);
1667392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1668392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* found notification, peek again */
1669392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&snp, 0x00, sizeof(union sctp_notification));
1670392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_base = (char *)&snp;
1671392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_len = sizeof(union sctp_notification);
1672392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_name = NULL;
1673392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_namelen = 0;
1674392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iov = &iov;
1675392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iovlen = 1;
1676392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_control = NULL;
1677392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_controllen = 0;
1678392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_flags = 0;
1679392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1680392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* if we have seen the dry already, don't wait */
1681392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_dry)
1682392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1683392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			sockflags = fcntl(b->num, F_GETFL, 0);
1684392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			fcntl(b->num, F_SETFL, O_NONBLOCK);
1685392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1686392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1687392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = recvmsg(b->num, &msg, MSG_PEEK);
1688392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1689392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_dry)
1690392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1691392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			fcntl(b->num, F_SETFL, sockflags);
1692392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1693392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1694392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n <= 0)
1695392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1696392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
1697392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1698392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1699392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return is_dry;
1700392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1701392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1702392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1703392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* read anything else */
1704392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return is_dry;
1705392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1706392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1707392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_sctp_msg_waiting(BIO *b)
1708392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1709392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int n, sockflags;
1710392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union sctp_notification snp;
1711392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1712392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov;
1713392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1714392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1715392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Check if there are any messages waiting to be read */
1716392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	do
1717392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1718392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&snp, 0x00, sizeof(union sctp_notification));
1719392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_base = (char *)&snp;
1720392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_len = sizeof(union sctp_notification);
1721392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_name = NULL;
1722392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_namelen = 0;
1723392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iov = &iov;
1724392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iovlen = 1;
1725392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_control = NULL;
1726392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_controllen = 0;
1727392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_flags = 0;
1728392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1729392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockflags = fcntl(b->num, F_GETFL, 0);
1730392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		fcntl(b->num, F_SETFL, O_NONBLOCK);
1731392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = recvmsg(b->num, &msg, MSG_PEEK);
1732392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		fcntl(b->num, F_SETFL, sockflags);
1733392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1734392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* if notification, process and try again */
1735392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION))
1736392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1737392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
1738392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1739392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				dgram_sctp_handle_auth_free_key_event(b, &snp);
1740392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1741392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1742392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(&snp, 0x00, sizeof(union sctp_notification));
1743392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_base = (char *)&snp;
1744392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_len = sizeof(union sctp_notification);
1745392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_name = NULL;
1746392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_namelen = 0;
1747392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iov = &iov;
1748392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iovlen = 1;
1749392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_control = NULL;
1750392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_controllen = 0;
1751392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_flags = 0;
1752392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = recvmsg(b->num, &msg, 0);
1753392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1754392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (data->handle_notifications != NULL)
1755392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				data->handle_notifications(b, data->notification_context, (void*) &snp);
1756392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1757392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1758392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		} while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
1759392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1760392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Return 1 if there is a message to be read, return 0 otherwise. */
1761392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n > 0)
1762392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 1;
1763392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1764392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
1765392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1766392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1767392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_puts(BIO *bp, const char *str)
1768392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1769392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int n,ret;
1770392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1771392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n=strlen(str);
1772392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret=dgram_sctp_write(bp,str,n);
1773392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1774392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1775392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1776392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1777e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic int BIO_dgram_should_retry(int i)
1778656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1779656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int err;
1780656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1781656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if ((i == 0) || (i == -1))
1782656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1783656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		err=get_last_socket_error();
1784656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1785ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom#if defined(OPENSSL_SYS_WINDOWS)
1786ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	/* If the socket return value (i) is -1
1787ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * and err is unexpectedly 0 at this point,
1788ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * the error code was overwritten by
1789ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * another system call before this error
1790ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * handling is called.
1791ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 */
1792656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1793656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1794656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return(BIO_dgram_non_fatal_error(err));
1795656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1796656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(0);
1797656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1798656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1799656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint BIO_dgram_non_fatal_error(int err)
1800656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1801656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	switch (err)
1802656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1803656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if defined(OPENSSL_SYS_WINDOWS)
1804656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# if defined(WSAEWOULDBLOCK)
1805656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case WSAEWOULDBLOCK:
1806656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1807656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1808656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# if 0 /* This appears to always be an error */
1809656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  if defined(WSAENOTCONN)
1810656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case WSAENOTCONN:
1811656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  endif
1812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1813656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1814656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1815656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EWOULDBLOCK
1816656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# ifdef WSAEWOULDBLOCK
1817656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  if WSAEWOULDBLOCK != EWOULDBLOCK
1818656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EWOULDBLOCK:
1819656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  endif
1820656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# else
1821656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EWOULDBLOCK:
1822656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1823656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1824656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1825656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EINTR
1826656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EINTR:
1827656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1828656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1829656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EAGAIN
1830656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if EWOULDBLOCK != EAGAIN
1831656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EAGAIN:
1832656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1833656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1834656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1835656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EPROTO
1836656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EPROTO:
1837656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1838656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1839656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EINPROGRESS
1840656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EINPROGRESS:
1841656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1842656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1843656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EALREADY
1844656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EALREADY:
1845656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1846656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1847656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return(1);
1848656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* break; */
1849656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	default:
1850656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
1851656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1852656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(0);
1853656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
185498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
185598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void get_current_time(struct timeval *t)
185698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	{
185798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WIN32
185898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct _timeb tb;
185998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	_ftime(&tb);
186098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_sec = (long)tb.time;
186198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_usec = (long)tb.millitm * 1000;
186298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#elif defined(OPENSSL_SYS_VMS)
186398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct timeb tb;
186498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	ftime(&tb);
186598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_sec = (long)tb.time;
186698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_usec = (long)tb.millitm * 1000;
186798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
186898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	gettimeofday(t, NULL);
186998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
187098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	}
1871ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom
1872ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom#endif
1873