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
8098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_LINUX
81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define IP_MTU      14 /* linux is lame */
8298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef WATT32
85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define sock_write SockWrite  /* Watt-32 uses same names */
86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define sock_read  SockRead
87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define sock_puts  SockPuts
88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_write(BIO *h, const char *buf, int num);
91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_read(BIO *h, char *buf, int size);
92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_puts(BIO *h, const char *str);
93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_new(BIO *h);
95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_free(BIO *data);
96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_clear(BIO *bio);
97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
98392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
99392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_write(BIO *h, const char *buf, int num);
100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_read(BIO *h, char *buf, int size);
101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_puts(BIO *h, const char *str);
102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_new(BIO *h);
104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_free(BIO *data);
105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp);
107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
110e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic int BIO_dgram_should_retry(int s);
111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
11298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void get_current_time(struct timeval *t);
11398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic BIO_METHOD methods_dgramp=
115656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
116656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_TYPE_DGRAM,
117656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	"datagram socket",
118656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_write,
119656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_read,
120656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_puts,
121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	NULL, /* dgram_gets, */
122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_ctrl,
123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_new,
124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dgram_free,
125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	NULL,
126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	};
127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic BIO_METHOD methods_dgramp_sctp=
130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO_TYPE_DGRAM_SCTP,
132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	"datagram sctp socket",
133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_write,
134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_read,
135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_puts,
136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	NULL, /* dgram_gets, */
137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_ctrl,
138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_new,
139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	dgram_sctp_free,
140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	NULL,
141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	};
142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projecttypedef struct bio_dgram_data_st
145656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
146221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union {
147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr sa;
148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in sa_in;
149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in6 sa_in6;
151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} peer;
153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int connected;
154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int _errno;
155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int mtu;
15698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct timeval next_timeout;
15798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct timeval socket_timeout;
158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	} bio_dgram_data;
159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromtypedef struct bio_dgram_sctp_save_message_st
162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom        BIO *bio;
164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom        char *data;
165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom        int length;
166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} bio_dgram_sctp_save_message;
167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromtypedef struct bio_dgram_sctp_data_st
169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union {
171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sockaddr sa;
172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sockaddr_in sa_in;
173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if OPENSSL_USE_IPV6
174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sockaddr_in6 sa_in6;
175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} peer;
177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int connected;
178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int _errno;
179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int mtu;
180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_sndinfo sndinfo;
181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_rcvinfo rcvinfo;
182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_prinfo prinfo;
183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*handle_notifications)(BIO *bio, void *context, void *buf);
184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void* notification_context;
185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int in_handshake;
186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ccs_rcvd;
187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ccs_sent;
188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int save_shutdown;
189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int peer_auth_tested;
190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_save_message saved_message;
191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} bio_dgram_sctp_data;
192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectBIO_METHOD *BIO_s_datagram(void)
195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(&methods_dgramp);
197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
199656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectBIO *BIO_new_dgram(int fd, int close_flag)
200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO *ret;
202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret=BIO_new(BIO_s_datagram());
204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ret == NULL) return(NULL);
205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_set_fd(ret,fd,close_flag);
206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_new(BIO *bi)
210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = NULL;
212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bi->init=0;
214656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bi->num=0;
215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	data = OPENSSL_malloc(sizeof(bio_dgram_data));
216656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (data == NULL)
217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
218656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	memset(data, 0x00, sizeof(bio_dgram_data));
219656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    bi->ptr = data;
220656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
221656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bi->flags=0;
222656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(1);
223656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
224656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
225656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_free(BIO *a)
226656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
227656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data;
228656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a == NULL) return(0);
230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if ( ! dgram_clear(a))
231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	data = (bio_dgram_data *)a->ptr;
234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if(data != NULL) OPENSSL_free(data);
235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(1);
237656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_clear(BIO *a)
240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a == NULL) return(0);
242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->shutdown)
243656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (a->init)
245656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			SHUTDOWN2(a->num);
247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		a->init=0;
249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		a->flags=0;
250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
251656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(1);
252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
25398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
25498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void dgram_adjust_rcv_timeout(BIO *b)
25598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	{
25698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#if defined(SO_RCVTIMEO)
25798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
25898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	int sz = sizeof(int);
25998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
26098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	/* Is a timer active? */
26198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
26298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		{
26398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		struct timeval timenow, timeleft;
26498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
26598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Read current socket timeout */
26698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
26798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		int timeout;
26898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
26998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom					   (void*)&timeout, &sz) < 0)
27098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("getsockopt"); }
27198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		else
27298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
27398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			data->socket_timeout.tv_sec = timeout / 1000;
27498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
27598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
27698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
27798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
27898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom						&(data->socket_timeout), (void *)&sz) < 0)
27998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("getsockopt"); }
28098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
28198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
28298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Get current time */
28398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		get_current_time(&timenow);
28498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
28598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Calculate time left until timer expires */
28698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
28798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		timeleft.tv_sec -= timenow.tv_sec;
28898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		timeleft.tv_usec -= timenow.tv_usec;
28998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (timeleft.tv_usec < 0)
29098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
29198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_sec--;
29298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_usec += 1000000;
29398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
29498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
29598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (timeleft.tv_sec < 0)
29698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
29798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_sec = 0;
29898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeleft.tv_usec = 1;
29998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
30098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
30198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		/* Adjust socket timeout if next handhake message timer
30298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		 * will expire earlier.
30398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		 */
30498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) ||
30598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			(data->socket_timeout.tv_sec > timeleft.tv_sec) ||
30698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			(data->socket_timeout.tv_sec == timeleft.tv_sec &&
30798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			 data->socket_timeout.tv_usec >= timeleft.tv_usec))
30898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
30998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
31098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
31198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
31298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom						   (void*)&timeout, sizeof(timeout)) < 0)
31398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{ perror("setsockopt"); }
31498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
31598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
31698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom							sizeof(struct timeval)) < 0)
31798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{ perror("setsockopt"); }
31898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
31998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
32098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		}
32198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
32298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	}
32398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
32498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void dgram_reset_rcv_timeout(BIO *b)
32598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	{
32698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#if defined(SO_RCVTIMEO)
32798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
32898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
32998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	/* Is a timer active? */
33098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
33198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		{
33298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WINDOWS
33398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		int timeout = data->socket_timeout.tv_sec * 1000 +
33498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom					  data->socket_timeout.tv_usec / 1000;
33598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
33698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom					   (void*)&timeout, sizeof(timeout)) < 0)
33798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("setsockopt"); }
33898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
33998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout),
34098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom						sizeof(struct timeval)) < 0)
34198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{ perror("setsockopt"); }
34298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
34398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		}
34498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
34598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	}
34698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
347656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_read(BIO *b, char *out, int outl)
348656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
349656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret=0;
350656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
351656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
352221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	struct	{
353221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/*
354221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	 * See commentary in b_sock.c. <appro>
355221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	 */
356221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union	{ size_t s; int i; } len;
357221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union	{
358221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr sa;
359221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in sa_in;
360221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
361221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in6 sa_in6;
362221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
363221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		} peer;
364221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} sa;
365221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
366221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	sa.len.s=0;
367221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	sa.len.i=sizeof(sa.peer);
368656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
369656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (out != NULL)
370656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
371656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		clear_socket_error();
372221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memset(&sa.peer, 0x00, sizeof(sa.peer));
37398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		dgram_adjust_rcv_timeout(b);
374221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len);
375221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0)
376221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
377221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			OPENSSL_assert(sa.len.s<=sizeof(sa.peer));
378221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			sa.len.i = (int)sa.len.s;
379221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
380656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
38198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if ( ! data->connected  && ret >= 0)
382221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
383656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
384656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BIO_clear_retry_flags(b);
38598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (ret < 0)
386656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
387656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (BIO_dgram_should_retry(ret))
388656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
389656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				BIO_set_retry_read(b);
390656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				data->_errno = get_last_socket_error();
391656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
392656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
393ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom
394ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom		dgram_reset_rcv_timeout(b);
395656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
396656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
397656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
398656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
399656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_write(BIO *b, const char *in, int inl)
400656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
401656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret;
402656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
403656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	clear_socket_error();
404656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
405221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if ( data->connected )
406221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=writesocket(b->num,in,inl);
407221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
408221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
409221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		int peerlen = sizeof(data->peer);
410221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
411221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (data->peer.sa.sa_family == AF_INET)
412221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			peerlen = sizeof(data->peer.sa_in);
41381c4de7869b646592127e952cda763abf8305069Brian Carlstrom#if OPENSSL_USE_IPV6
414221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else if (data->peer.sa.sa_family == AF_INET6)
415221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			peerlen = sizeof(data->peer.sa_in6);
416221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
417656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
418221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen);
419656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#else
420221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
421656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
422221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
423656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
424656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_clear_retry_flags(b);
425656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ret <= 0)
426656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
42798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		if (BIO_dgram_should_retry(ret))
428656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
429656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			BIO_set_retry_write(b);
430656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->_errno = get_last_socket_error();
431656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
432656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if 0 /* higher layers are responsible for querying MTU, if necessary */
433656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if ( data->_errno == EMSGSIZE)
434656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				/* retrieve the new MTU */
435656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
436656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
437656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
438656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
439656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
440656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
441656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
442656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
443656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
444656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	long ret=1;
445656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int *ip;
446656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	struct sockaddr *to = NULL;
447656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	bio_dgram_data *data = NULL;
44898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#if defined(IP_MTU_DISCOVER) || defined(IP_MTU)
449656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	long sockopt_val = 0;
450656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	unsigned int sockopt_len = 0;
45198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
45298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_LINUX
45398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	socklen_t addr_len;
454221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	union	{
455221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr	sa;
456221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in s4;
457221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
458221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		struct sockaddr_in6 s6;
459221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
460221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		} addr;
46198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
462656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
463656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	data = (bio_dgram_data *)b->ptr;
464656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
465656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	switch (cmd)
466656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
467656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_RESET:
468656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		num=0;
469656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_FILE_SEEK:
470656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
471656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
472656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_FILE_TELL:
473656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_INFO:
474656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
475656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
476656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_SET_FD:
477656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		dgram_clear(b);
478656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->num= *((int *)ptr);
479656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->shutdown=(int)num;
480656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->init=1;
481656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
482656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_C_GET_FD:
483656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (b->init)
484656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
485656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ip=(int *)ptr;
486656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (ip != NULL) *ip=b->num;
487656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret=b->num;
488656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
489656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
490656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret= -1;
491656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
492656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_GET_CLOSE:
493656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=b->shutdown;
494656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
495656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_SET_CLOSE:
496656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		b->shutdown=(int)num;
497656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
498656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_PENDING:
499656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_WPENDING:
500656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
501656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
502656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DUP:
503656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_FLUSH:
504656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=1;
505656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
506656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_CONNECT:
507656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		to = (struct sockaddr *)ptr;
508656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if 0
509656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
510656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("connect"); ret = 0; }
511656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
512656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
513656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
514221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			switch (to->sa_family)
515221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				{
516221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET:
517221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
518221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
519221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
520221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET6:
521221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
522221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
523221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
524221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				default:
525221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa));
526221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
527221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
528656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if 0
529656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
530656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
531656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
532656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* (Linux)kernel sets DF bit on outgoing IP packets */
533656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_MTU_DISCOVER:
53498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_LINUX
535221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		addr_len = (socklen_t)sizeof(addr);
536221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memset((void *)&addr, 0, sizeof(addr));
537221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
53898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
53998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = 0;
54098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
54198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
54298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		sockopt_len = sizeof(sockopt_val);
543221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (addr.sa.sa_family)
54498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
54598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET:
54698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			sockopt_val = IP_PMTUDISC_DO;
54798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
54898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_val, sizeof(sockopt_val))) < 0)
54998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				perror("setsockopt");
55098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
551221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER)
55298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET6:
55398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			sockopt_val = IPV6_PMTUDISC_DO;
55498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
55598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_val, sizeof(sockopt_val))) < 0)
55698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				perror("setsockopt");
55798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
558221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
55998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		default:
56098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = -1;
56198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
56298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
56398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		ret = -1;
56498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
565656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
566656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
567656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_QUERY_MTU:
56898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_LINUX
569221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		addr_len = (socklen_t)sizeof(addr);
570221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memset((void *)&addr, 0, sizeof(addr));
571221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
572656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
57398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = 0;
57498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
575656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
57698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		sockopt_len = sizeof(sockopt_val);
577221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (addr.sa.sa_family)
57898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			{
57998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET:
58098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
58198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_len)) < 0 || sockopt_val < 0)
58298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
58398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = 0;
58498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
58598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			else
58698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
58798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				/* we assume that the transport protocol is UDP and no
58898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 * IP options are used.
58998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 */
59098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				data->mtu = sockopt_val - 8 - 20;
59198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = data->mtu;
59298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
59398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
594221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
59598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		case AF_INET6:
59698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
59798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				&sockopt_len)) < 0 || sockopt_val < 0)
59898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
59998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = 0;
60098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
60198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			else
60298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				{
60398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				/* we assume that the transport protocol is UDP and no
60498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 * IPV6 options are used.
60598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				 */
60698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				data->mtu = sockopt_val - 8 - 40;
60798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				ret = data->mtu;
60898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom				}
60998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
610221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
61198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		default:
61298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			ret = 0;
61398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			break;
61498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom			}
61598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
61698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		ret = 0;
61798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
618656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
61921c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
62021c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom		switch (data->peer.sa.sa_family)
62121c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			{
62221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			case AF_INET:
62321c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				ret = 576 - 20 - 8;
62421c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				break;
62521c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#if OPENSSL_USE_IPV6
62621c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			case AF_INET6:
62721c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#ifdef IN6_IS_ADDR_V4MAPPED
62821c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
62921c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom					ret = 576 - 20 - 8;
63021c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				else
63121c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#endif
63221c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom					ret = 1280 - 40 - 8;
63321c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				break;
63421c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom#endif
63521c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			default:
63621c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				ret = 576 - 20 - 8;
63721c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom				break;
63821c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom			}
63921c841450af61d0a9119cdc863e93d019127bfe1Brian Carlstrom		break;
640656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_MTU:
641656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return data->mtu;
642656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
643656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_MTU:
644656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		data->mtu = num;
645656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret = num;
646656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
647656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_CONNECTED:
648656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		to = (struct sockaddr *)ptr;
649656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
650656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( to != NULL)
651656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
652656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->connected = 1;
653221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			switch (to->sa_family)
654221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				{
655221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET:
656221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in));
657221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
658221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
659221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				case AF_INET6:
660221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
661221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
662221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
663221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				default:
664221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					memcpy(&data->peer,to,sizeof(data->peer.sa));
665221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					break;
666221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
667656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
668656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
669656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
670656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->connected = 0;
671221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			memset(&(data->peer), 0x00, sizeof(data->peer));
672221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
673221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
674221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	case BIO_CTRL_DGRAM_GET_PEER:
675221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (data->peer.sa.sa_family)
676221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
677221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET:
678221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ret=sizeof(data->peer.sa_in);
679221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
680221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
681221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET6:
682221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ret=sizeof(data->peer.sa_in6);
683221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
684221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
685221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			default:
686221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ret=sizeof(data->peer.sa);
687221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
688221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
689221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (num==0 || num>ret)
690221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			num=ret;
691221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memcpy(ptr,&data->peer,(ret=num));
692221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
693221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	case BIO_CTRL_DGRAM_SET_PEER:
694221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		to = (struct sockaddr *) ptr;
695221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		switch (to->sa_family)
696221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
697221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET:
698221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				memcpy(&data->peer,to,sizeof(data->peer.sa_in));
699221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
700221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if OPENSSL_USE_IPV6
701221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			case AF_INET6:
702221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				memcpy(&data->peer,to,sizeof(data->peer.sa_in6));
703221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
704221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
705221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			default:
706221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				memcpy(&data->peer,to,sizeof(data->peer.sa));
707221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				break;
708656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
709656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
71098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
711221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
71298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom		break;
713e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#if defined(SO_RCVTIMEO)
714656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
715e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
716e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
717e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
718e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
719e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
720e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			(void*)&timeout, sizeof(timeout)) < 0)
721e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("setsockopt"); ret = -1; }
722e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		}
723e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
724656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
725656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			sizeof(struct timeval)) < 0)
726656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("setsockopt");	ret = -1; }
727e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
728656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
729656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
730e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
731e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
732e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		int timeout, sz = sizeof(timeout);
733e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
734e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
735e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			(void*)&timeout, &sz) < 0)
736e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("getsockopt"); ret = -1; }
737e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		else
738e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{
739e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_sec = timeout / 1000;
740e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_usec = (timeout % 1000) * 1000;
741e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			ret = sizeof(*tv);
742e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			}
743e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		}
744e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
745656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
746656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ptr, (void *)&ret) < 0)
747656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("getsockopt"); ret = -1; }
748e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
749656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
750e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
751e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#if defined(SO_SNDTIMEO)
752656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
753e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
754e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
755e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
756e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
757e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
758e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			(void*)&timeout, sizeof(timeout)) < 0)
759e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("setsockopt"); ret = -1; }
760e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		}
761e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
762656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			sizeof(struct timeval)) < 0)
764656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("setsockopt");	ret = -1; }
765e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
766656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
767656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
768e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
769e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		{
770e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		int timeout, sz = sizeof(timeout);
771e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		struct timeval *tv = (struct timeval *)ptr;
772e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
773e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			(void*)&timeout, &sz) < 0)
774e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{ perror("getsockopt"); ret = -1; }
775e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		else
776e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			{
777e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_sec = timeout / 1000;
778e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			tv->tv_usec = (timeout % 1000) * 1000;
779e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			ret = sizeof(*tv);
780e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			}
781e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		}
782e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
783656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
784656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ptr, (void *)&ret) < 0)
785656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ perror("getsockopt"); ret = -1; }
786e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
787656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
788e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
789656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
790656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* fall-through */
791656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
792e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#ifdef OPENSSL_SYS_WINDOWS
793e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		if ( data->_errno == WSAETIMEDOUT)
794e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#else
795656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( data->_errno == EAGAIN)
796e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#endif
797656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
798656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 1;
799656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->_errno = 0;
800656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
801656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
802656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 0;
803656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
804656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EMSGSIZE
805656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
806656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if ( data->_errno == EMSGSIZE)
807656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
808656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 1;
809656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			data->_errno = 0;
810656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
811656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 0;
813656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
814656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
815656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	default:
816656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret=0;
817656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
818656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
819656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
820656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
821656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
822656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int dgram_puts(BIO *bp, const char *str)
823656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
824656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int n,ret;
825656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
826656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n=strlen(str);
827656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret=dgram_write(bp,str,n);
828656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(ret);
829656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
830656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
831392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_SCTP
832392aa7cc7d2b122614c5393c3e357da07fd07af3Brian CarlstromBIO_METHOD *BIO_s_datagram_sctp(void)
833392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
834392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(&methods_dgramp_sctp);
835392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
836392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
837392aa7cc7d2b122614c5393c3e357da07fd07af3Brian CarlstromBIO *BIO_new_dgram_sctp(int fd, int close_flag)
838392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
839392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO *bio;
840392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret, optval = 20000;
841392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int auth_data = 0, auth_forward = 0;
842392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned char *p;
843392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authchunk auth;
844392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authchunks *authchunks;
845392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	socklen_t sockopt_len;
846392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
847392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
848392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event event;
849392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
850392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event_subscribe event;
851392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
852392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
853392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
854392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio=BIO_new(BIO_s_datagram_sctp());
855392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (bio == NULL) return(NULL);
856392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO_set_fd(bio,fd,close_flag);
857392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
858392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
859392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
860392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
861392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
862392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
863392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
864392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
865392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
866392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Test if activation was successful. When using accept(),
867392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * SCTP-AUTH has to be activated for the listening socket
868392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * already, otherwise the connected socket won't use it. */
869392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
870392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	authchunks = OPENSSL_malloc(sockopt_len);
871392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(authchunks, 0, sizeof(sockopt_len));
872392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
873392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
874392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
875392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
876392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	     p < (unsigned char*) authchunks + sockopt_len;
877392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	     p += sizeof(uint8_t))
878392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
879392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
880392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
881392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
882392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
883392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_free(authchunks);
884392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
885392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(auth_data);
886392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(auth_forward);
887392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
888392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
889392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
890392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(&event, 0, sizeof(struct sctp_event));
891392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_assoc_id = 0;
892392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_type = SCTP_AUTHENTICATION_EVENT;
893392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_on = 1;
894392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
895392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
896392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
897392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
898392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
899392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
900392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
901392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.sctp_authentication_event = 1;
902392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
903392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
904392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
905392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
906392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
907392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
908392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Disable partial delivery by setting the min size
909392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * larger than the max record size of 2^14 + 2048 + 13
910392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
911392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
912392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	OPENSSL_assert(ret >= 0);
913392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
914392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(bio);
915392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
916392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
917392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_is_sctp(BIO *bio)
918392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
919392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
920392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
921392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
922392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_new(BIO *bi)
923392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
924392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = NULL;
925392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
926392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bi->init=0;
927392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bi->num=0;
928392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data));
929392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (data == NULL)
930392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
931392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(data, 0x00, sizeof(bio_dgram_sctp_data));
932392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_PR_SCTP_NONE
933392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
934392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
935392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    bi->ptr = data;
936392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
937392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bi->flags=0;
938392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(1);
939392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
940392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
941392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_free(BIO *a)
942392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
943392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data;
944392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
945392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (a == NULL) return(0);
946392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ( ! dgram_clear(a))
947392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
948392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
949392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data = (bio_dgram_sctp_data *)a->ptr;
950392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if(data != NULL) OPENSSL_free(data);
951392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
952392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(1);
953392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
954392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
955392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
956392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
957392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
958392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int sockopt_len = 0;
959392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret;
960392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
961392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
962392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY)
963392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
964392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		struct sctp_authkeyid authkeyid;
965392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
966392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* delete key */
967392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
968392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkeyid);
969392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
970392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		      &authkeyid, sockopt_len);
971392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
972392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
973392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
974392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
975392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_read(BIO *b, char *out, int outl)
976392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
977392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret = 0, n = 0, i, optval;
978392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	socklen_t optlen;
979392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
980392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union sctp_notification *snp;
981392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
982392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov;
983392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct cmsghdr *cmsg;
984392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	char cmsgbuf[512];
985392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
986392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (out != NULL)
987392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
988392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		clear_socket_error();
989392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
990392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		do
991392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
992392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
993392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_base = out;
994392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_len = outl;
995392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_name = NULL;
996392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_namelen = 0;
997392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iov = &iov;
998392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iovlen = 1;
999392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_control = cmsgbuf;
1000392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_controllen = 512;
1001392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_flags = 0;
1002392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = recvmsg(b->num, &msg, 0);
1003392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1004392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (msg.msg_controllen > 0)
1005392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1006392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
1007392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					{
1008392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (cmsg->cmsg_level != IPPROTO_SCTP)
1009392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						continue;
1010392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_RCVINFO
1011392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (cmsg->cmsg_type == SCTP_RCVINFO)
1012392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						{
1013392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						struct sctp_rcvinfo *rcvinfo;
1014392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1015392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
1016392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
1017392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
1018392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
1019392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
1020392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
1021392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
1022392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_context = rcvinfo->rcv_context;
1023392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						}
1024392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1025392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_SNDRCV
1026392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (cmsg->cmsg_type == SCTP_SNDRCV)
1027392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						{
1028392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						struct sctp_sndrcvinfo *sndrcvinfo;
1029392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1030392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1031392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
1032392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
1033392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
1034392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
1035392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
1036392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
1037392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
1038392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						}
1039392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1040392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					}
1041392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1042392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1043392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (n <= 0)
1044392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1045392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (n < 0)
1046392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					ret = n;
1047392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				break;
1048392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1049392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1050392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (msg.msg_flags & MSG_NOTIFICATION)
1051392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1052392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				snp = (union sctp_notification*) out;
1053392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
1054392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					{
1055392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1056392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					struct sctp_event event;
1057392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1058392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					struct sctp_event_subscribe event;
1059392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					socklen_t eventsize;
1060392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1061392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					/* If a message has been delayed until the socket
1062392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					 * is dry, it can be sent now.
1063392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					 */
1064392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					if (data->saved_message.length > 0)
1065392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						{
1066392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
1067392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						                 data->saved_message.length);
1068392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						OPENSSL_free(data->saved_message.data);
1069392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						data->saved_message.length = 0;
1070392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom						}
1071392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1072392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					/* disable sender dry event */
1073392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1074392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					memset(&event, 0, sizeof(struct sctp_event));
1075392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.se_assoc_id = 0;
1076392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.se_type = SCTP_SENDER_DRY_EVENT;
1077392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.se_on = 0;
1078392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1079392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					OPENSSL_assert(i >= 0);
1080392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1081392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					eventsize = sizeof(struct sctp_event_subscribe);
1082392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1083392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					OPENSSL_assert(i >= 0);
1084392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1085392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					event.sctp_sender_dry_event = 0;
1086392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1087392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1088392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					OPENSSL_assert(i >= 0);
1089392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1090392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					}
1091392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1092392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
1093392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1094392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					dgram_sctp_handle_auth_free_key_event(b, snp);
1095392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1096392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1097392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (data->handle_notifications != NULL)
1098392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					data->handle_notifications(b, data->notification_context, (void*) out);
1099392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				memset(out, 0, outl);
1101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ret += n;
1104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
1106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret > 0 && !(msg.msg_flags & MSG_EOR))
1108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Partial message read, this should never happen! */
1110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* The buffer was too small, this means the peer sent
1112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * a message that was larger than allowed. */
1113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret == outl)
1114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Test if socket buffer can handle max record
1117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * size (2^14 + 2048 + 13)
1118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			optlen = (socklen_t) sizeof(int);
1120392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
1121392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(ret >= 0);
1122392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(optval >= 18445);
1123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1124392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Test if SCTP doesn't partially deliver below
1125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * max record size (2^14 + 2048 + 13)
1126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			optlen = (socklen_t) sizeof(int);
1128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
1129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			                 &optval, &optlen);
1130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(ret >= 0);
1131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(optval >= 18445);
1132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Partially delivered notification??? Probably a bug.... */
1134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
1135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Everything seems ok till now, so it's most likely
1137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * a message dropped by PR-SCTP.
1138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(out, 0, outl);
1140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			BIO_set_retry_read(b);
1141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return -1;
1142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BIO_clear_retry_flags(b);
1145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0)
1146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (BIO_dgram_should_retry(ret))
1148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				BIO_set_retry_read(b);
1150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				data->_errno = get_last_socket_error();
1151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Test if peer uses SCTP-AUTH before continuing */
1155392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!data->peer_auth_tested)
1156392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1157392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			int ii, auth_data = 0, auth_forward = 0;
1158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			unsigned char *p;
1159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			struct sctp_authchunks *authchunks;
1160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
1162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			authchunks = OPENSSL_malloc(optlen);
1163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(authchunks, 0, sizeof(optlen));
1164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
1165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_assert(ii >= 0);
1166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
1168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				 p < (unsigned char*) authchunks + optlen;
1169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				 p += sizeof(uint8_t))
1170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
1172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
1173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			OPENSSL_free(authchunks);
1176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (!auth_data || !auth_forward)
1178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				BIOerr(BIO_F_DGRAM_SCTP_READ,BIO_R_CONNECT_ERROR);
1180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->peer_auth_tested = 1;
1184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_write(BIO *b, const char *in, int inl)
1190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret;
1192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
1194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
1195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct bio_dgram_sctp_sndinfo handshake_sinfo;
1196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov[1];
1197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct cmsghdr *cmsg;
1199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1200392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
1201392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_sndinfo *sndinfo;
1202392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_prinfo *prinfo;
1203392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1204392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1205392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_sndrcvinfo *sndrcvinfo;
1206392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1207392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1208392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	clear_socket_error();
1209392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1210392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* If we're send anything else than application data,
1211392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * disable all user parameters and flags.
1212392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
1213392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (in[0] != 23) {
1214392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo));
1215392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_SACK_IMMEDIATELY
1216392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
1217392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1218392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sinfo = &handshake_sinfo;
1219392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1220392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1221392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* If we have to send a shutdown alert message and the
1222392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * socket is not dry yet, we have to save it and send it
1223392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * as soon as the socket gets dry.
1224392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
1225392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b))
1226392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1227392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->saved_message.bio = b;
1228392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->saved_message.length = inl;
1229392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->saved_message.data = OPENSSL_malloc(inl);
1230392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(data->saved_message.data, in, inl);
1231392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return inl;
1232392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1233392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1234392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov[0].iov_base = (char *)in;
1235392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov[0].iov_len = inl;
1236392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_name = NULL;
1237392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_namelen = 0;
1238392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iov = iov;
1239392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iovlen = 1;
1240392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_control = (caddr_t)cmsgbuf;
1241392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen = 0;
1242392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_flags = 0;
1243392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1244392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg = (struct cmsghdr *)cmsgbuf;
1245392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_level = IPPROTO_SCTP;
1246392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_type = SCTP_SNDINFO;
1247392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
1248392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
1249392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
1250392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_sid = sinfo->snd_sid;
1251392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_flags = sinfo->snd_flags;
1252392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_ppid = sinfo->snd_ppid;
1253392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndinfo->snd_context = sinfo->snd_context;
1254392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
1255392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1256392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
1257392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_level = IPPROTO_SCTP;
1258392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_type = SCTP_PRINFO;
1259392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
1260392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
1261392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(prinfo, 0, sizeof(struct sctp_prinfo));
1262392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	prinfo->pr_policy = pinfo->pr_policy;
1263392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	prinfo->pr_value = pinfo->pr_value;
1264392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
1265392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1266392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg = (struct cmsghdr *)cmsgbuf;
1267392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_level = IPPROTO_SCTP;
1268392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_type = SCTP_SNDRCV;
1269392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
1270392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1271392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
1272392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_stream = sinfo->snd_sid;
1273392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_flags = sinfo->snd_flags;
1274392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef __FreeBSD__
1275392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_flags |= pinfo->pr_policy;
1276392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1277392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
1278392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_context = sinfo->snd_context;
1279392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
1280392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
1281392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1282392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1283392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = sendmsg(b->num, &msg, 0);
1284392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1285392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIO_clear_retry_flags(b);
1286392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ret <= 0)
1287392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1288392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (BIO_dgram_should_retry(ret))
1289392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1290392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			BIO_set_retry_write(b);
1291392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->_errno = get_last_socket_error();
1292392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1293392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1294392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1295392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1296392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1297392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
1298392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1299392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	long ret=1;
1300392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = NULL;
1301392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int sockopt_len = 0;
1302392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authkeyid authkeyid;
1303392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_authkey *authkey;
1304392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1305392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	data = (bio_dgram_sctp_data *)b->ptr;
1306392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1307392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	switch (cmd)
1308392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1309392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_QUERY_MTU:
1310392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Set to maximum (2^14)
1311392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * and ignore user input to enable transport
1312392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * protocol fragmentation.
1313392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns always 2^14.
1314392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1315392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->mtu = 16384;
1316392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = data->mtu;
1317392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1318392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SET_MTU:
1319392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Set to maximum (2^14)
1320392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * and ignore input to enable transport
1321392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * protocol fragmentation.
1322392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns always 2^14.
1323392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1324392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->mtu = 16384;
1325392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = data->mtu;
1326392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1327392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SET_CONNECTED:
1328392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_CONNECT:
1329392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns always -1. */
1330392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = -1;
1331392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1332392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
1333392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* SCTP doesn't need the DTLS timer
1334392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns always 1.
1335392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1336392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1337392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
1338392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > 0)
1339392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->in_handshake = 1;
1340392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1341392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->in_handshake = 0;
1342392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1343392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
1344392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1345392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
1346392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* New shared key for SCTP AUTH.
1347392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * Returns 0 on success, -1 otherwise.
1348392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1349392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1350392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Get active key */
1351392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkeyid);
1352392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1353392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1354392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1355392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Add new key */
1356392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
1357392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkey = OPENSSL_malloc(sockopt_len);
1358392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(authkey, 0x00, sockopt_len);
1359392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
1360392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef __FreeBSD__
1361392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* This field is missing in FreeBSD 8.2 and earlier,
1362392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * and FreeBSD 8.3 and higher work without it.
1363392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1364392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkey->sca_keylength = 64;
1365392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1366392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
1367392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1368392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
1369392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1370392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1371392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Reset active key */
1372392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1373392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		      &authkeyid, sizeof(struct sctp_authkeyid));
1374392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1375392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1376392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1377392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
1378392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns 0 on success, -1 otherwise. */
1379392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1380392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Get active key */
1381392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockopt_len = sizeof(struct sctp_authkeyid);
1382392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1383392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1384392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1385392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Set active key */
1386392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
1387392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1388392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		      &authkeyid, sizeof(struct sctp_authkeyid));
1389392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ret < 0) break;
1390392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1391392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* CCS has been sent, so remember that and fall through
1392392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * to check if we need to deactivate an old key
1393392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1394392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->ccs_sent = 1;
1395392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1396392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
1397392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns 0 on success, -1 otherwise. */
1398392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1399392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Has this command really been called or is this just a fall-through? */
1400392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
1401392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->ccs_rcvd = 1;
1402392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1403392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* CSS has been both, received and sent, so deactivate an old key */
1404392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (data->ccs_rcvd == 1 && data->ccs_sent == 1)
1405392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1406392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Get active key */
1407392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			sockopt_len = sizeof(struct sctp_authkeyid);
1408392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1409392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0) break;
1410392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1411392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* Deactivate key or delete second last key if
1412392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 * SCTP_AUTHENTICATION_EVENT is not available.
1413392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			 */
1414392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1415392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTH_DEACTIVATE_KEY
1416392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			sockopt_len = sizeof(struct sctp_authkeyid);
1417392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,
1418392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			      &authkeyid, sockopt_len);
1419392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0) break;
1420392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1421392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef SCTP_AUTHENTICATION_EVENT
1422392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (authkeyid.scact_keynumber > 0)
1423392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
1424392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1425392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
1426392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom					  &authkeyid, sizeof(struct sctp_authkeyid));
1427392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				if (ret < 0) break;
1428392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
1429392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1430392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1431392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->ccs_rcvd = 0;
1432392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->ccs_sent = 0;
1433392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1434392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1435392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
1436392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1437392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1438392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_sndinfo);
1439392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1440392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ptr, &(data->sndinfo), num);
1441392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = num;
1442392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1443392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
1444392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1445392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1446392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_sndinfo);
1447392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1448392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&(data->sndinfo), ptr, num);
1449392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1450392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
1451392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1452392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1453392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_rcvinfo);
1454392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1455392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ptr, &data->rcvinfo, num);
1456392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1457392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = num;
1458392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1459392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
1460392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1461392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1462392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_rcvinfo);
1463392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1464392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&(data->rcvinfo), ptr, num);
1465392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1466392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
1467392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1468392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1469392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_prinfo);
1470392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1471392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ptr, &(data->prinfo), num);
1472392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret = num;
1473392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1474392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
1475392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns the size of the copied struct. */
1476392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1477392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			num = sizeof(struct bio_dgram_sctp_prinfo);
1478392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1479392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(&(data->prinfo), ptr, num);
1480392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1481392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
1482392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Returns always 1. */
1483392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (num > 0)
1484392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->save_shutdown = 1;
1485392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1486392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->save_shutdown = 0;
1487392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1488392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1489392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	default:
1490392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* Pass to default ctrl function to
1491392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 * process SCTP unspecific commands
1492392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		 */
1493392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret=dgram_ctrl(b, cmd, num, ptr);
1494392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		break;
1495392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1496392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1497392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1498392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1499392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_sctp_notification_cb(BIO *b,
1500392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom                                   void (*handle_notifications)(BIO *bio, void *context, void *buf),
1501392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom                                   void *context)
1502392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1503392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1504392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1505392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (handle_notifications != NULL)
1506392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1507392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->handle_notifications = handle_notifications;
1508392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		data->notification_context = context;
1509392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1510392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1511392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1512392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1513392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1514392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1515392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1516392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_sctp_wait_for_dry(BIO *b)
1517392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1518392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int is_dry = 0;
1519392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int n, sockflags, ret;
1520392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union sctp_notification snp;
1521392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1522392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov;
1523392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1524392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event event;
1525392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1526392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct sctp_event_subscribe event;
1527392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	socklen_t eventsize;
1528392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1529392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1530392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1531392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* set sender dry event */
1532392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1533392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(&event, 0, sizeof(struct sctp_event));
1534392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_assoc_id = 0;
1535392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_type = SCTP_SENDER_DRY_EVENT;
1536392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.se_on = 1;
1537392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1538392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1539392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	eventsize = sizeof(struct sctp_event_subscribe);
1540392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1541392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ret < 0)
1542392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1543392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1544392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	event.sctp_sender_dry_event = 1;
1545392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1546392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1547392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1548392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ret < 0)
1549392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1550392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1551392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* peek for notification */
1552392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(&snp, 0x00, sizeof(union sctp_notification));
1553392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov.iov_base = (char *)&snp;
1554392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	iov.iov_len = sizeof(union sctp_notification);
1555392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_name = NULL;
1556392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_namelen = 0;
1557392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iov = &iov;
1558392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_iovlen = 1;
1559392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_control = NULL;
1560392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_controllen = 0;
1561392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	msg.msg_flags = 0;
1562392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1563392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = recvmsg(b->num, &msg, MSG_PEEK);
1564392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n <= 0)
1565392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1566392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
1567392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return -1;
1568392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1569392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
1570392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1571392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1572392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* if we find a notification, process it and try again if necessary */
1573392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (msg.msg_flags & MSG_NOTIFICATION)
1574392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1575392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&snp, 0x00, sizeof(union sctp_notification));
1576392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_base = (char *)&snp;
1577392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_len = sizeof(union sctp_notification);
1578392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_name = NULL;
1579392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_namelen = 0;
1580392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iov = &iov;
1581392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iovlen = 1;
1582392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_control = NULL;
1583392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_controllen = 0;
1584392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_flags = 0;
1585392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1586392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = recvmsg(b->num, &msg, 0);
1587392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n <= 0)
1588392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1589392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
1590392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1591392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1592392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return is_dry;
1593392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1594392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1595392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
1596392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1597392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			is_dry = 1;
1598392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1599392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			/* disable sender dry event */
1600392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_EVENT
1601392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(&event, 0, sizeof(struct sctp_event));
1602392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.se_assoc_id = 0;
1603392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.se_type = SCTP_SENDER_DRY_EVENT;
1604392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.se_on = 0;
1605392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1606392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1607392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
1608392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1609392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0)
1610392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1611392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1612392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			event.sctp_sender_dry_event = 0;
1613392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1614392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1615392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1616392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ret < 0)
1617392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1618392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1619392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1620392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
1621392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1622392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			dgram_sctp_handle_auth_free_key_event(b, &snp);
1623392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1624392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1625392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (data->handle_notifications != NULL)
1626392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			data->handle_notifications(b, data->notification_context, (void*) &snp);
1627392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1628392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* found notification, peek again */
1629392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&snp, 0x00, sizeof(union sctp_notification));
1630392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_base = (char *)&snp;
1631392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_len = sizeof(union sctp_notification);
1632392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_name = NULL;
1633392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_namelen = 0;
1634392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iov = &iov;
1635392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iovlen = 1;
1636392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_control = NULL;
1637392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_controllen = 0;
1638392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_flags = 0;
1639392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1640392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* if we have seen the dry already, don't wait */
1641392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_dry)
1642392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1643392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			sockflags = fcntl(b->num, F_GETFL, 0);
1644392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			fcntl(b->num, F_SETFL, O_NONBLOCK);
1645392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1646392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1647392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = recvmsg(b->num, &msg, MSG_PEEK);
1648392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1649392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_dry)
1650392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1651392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			fcntl(b->num, F_SETFL, sockflags);
1652392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1653392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1654392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n <= 0)
1655392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1656392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
1657392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return -1;
1658392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1659392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return is_dry;
1660392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1661392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1662392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1663392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* read anything else */
1664392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return is_dry;
1665392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1666392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1667392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint BIO_dgram_sctp_msg_waiting(BIO *b)
1668392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1669392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int n, sockflags;
1670392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union sctp_notification snp;
1671392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct msghdr msg;
1672392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	struct iovec iov;
1673392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1674392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1675392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Check if there are any messages waiting to be read */
1676392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	do
1677392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
1678392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memset(&snp, 0x00, sizeof(union sctp_notification));
1679392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_base = (char *)&snp;
1680392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		iov.iov_len = sizeof(union sctp_notification);
1681392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_name = NULL;
1682392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_namelen = 0;
1683392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iov = &iov;
1684392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_iovlen = 1;
1685392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_control = NULL;
1686392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_controllen = 0;
1687392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		msg.msg_flags = 0;
1688392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1689392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		sockflags = fcntl(b->num, F_GETFL, 0);
1690392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		fcntl(b->num, F_SETFL, O_NONBLOCK);
1691392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = recvmsg(b->num, &msg, MSG_PEEK);
1692392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		fcntl(b->num, F_SETFL, sockflags);
1693392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1694392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* if notification, process and try again */
1695392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION))
1696392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
1697392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef SCTP_AUTHENTICATION_EVENT
1698392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1699392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				dgram_sctp_handle_auth_free_key_event(b, &snp);
1700392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1701392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1702392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			memset(&snp, 0x00, sizeof(union sctp_notification));
1703392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_base = (char *)&snp;
1704392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iov.iov_len = sizeof(union sctp_notification);
1705392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_name = NULL;
1706392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_namelen = 0;
1707392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iov = &iov;
1708392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_iovlen = 1;
1709392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_control = NULL;
1710392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_controllen = 0;
1711392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			msg.msg_flags = 0;
1712392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = recvmsg(b->num, &msg, 0);
1713392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1714392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (data->handle_notifications != NULL)
1715392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				data->handle_notifications(b, data->notification_context, (void*) &snp);
1716392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1717392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1718392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		} while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
1719392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1720392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* Return 1 if there is a message to be read, return 0 otherwise. */
1721392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n > 0)
1722392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 1;
1723392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1724392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
1725392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1726392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1727392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic int dgram_sctp_puts(BIO *bp, const char *str)
1728392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1729392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int n,ret;
1730392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1731392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n=strlen(str);
1732392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret=dgram_sctp_write(bp,str,n);
1733392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return(ret);
1734392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1735392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1736392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1737e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic int BIO_dgram_should_retry(int i)
1738656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1739656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int err;
1740656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1741656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if ((i == 0) || (i == -1))
1742656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1743656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		err=get_last_socket_error();
1744656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1745ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom#if defined(OPENSSL_SYS_WINDOWS)
1746ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	/* If the socket return value (i) is -1
1747ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * and err is unexpectedly 0 at this point,
1748ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * the error code was overwritten by
1749ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * another system call before this error
1750ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 * handling is called.
1751ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom	 */
1752656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1753656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1754656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return(BIO_dgram_non_fatal_error(err));
1755656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1756656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(0);
1757656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1758656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1759656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint BIO_dgram_non_fatal_error(int err)
1760656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1761656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	switch (err)
1762656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if defined(OPENSSL_SYS_WINDOWS)
1764656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# if defined(WSAEWOULDBLOCK)
1765656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case WSAEWOULDBLOCK:
1766656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1767656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1768656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# if 0 /* This appears to always be an error */
1769656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  if defined(WSAENOTCONN)
1770656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case WSAENOTCONN:
1771656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  endif
1772656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1773656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1774656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1775656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EWOULDBLOCK
1776656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# ifdef WSAEWOULDBLOCK
1777656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  if WSAEWOULDBLOCK != EWOULDBLOCK
1778656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EWOULDBLOCK:
1779656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#  endif
1780656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# else
1781656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EWOULDBLOCK:
1782656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1783656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1784656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1785656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EINTR
1786656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EINTR:
1787656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1788656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1789656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EAGAIN
1790656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#if EWOULDBLOCK != EAGAIN
1791656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EAGAIN:
1792656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project# endif
1793656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1794656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1795656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EPROTO
1796656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EPROTO:
1797656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1798656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1799656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EINPROGRESS
1800656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EINPROGRESS:
1801656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1802656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1803656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifdef EALREADY
1804656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	case EALREADY:
1805656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif
1806656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1807656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return(1);
1808656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* break; */
1809656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	default:
1810656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		break;
1811656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return(0);
1813656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
181498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom
181598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstromstatic void get_current_time(struct timeval *t)
181698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	{
181798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#ifdef OPENSSL_SYS_WIN32
181898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct _timeb tb;
181998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	_ftime(&tb);
182098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_sec = (long)tb.time;
182198d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_usec = (long)tb.millitm * 1000;
182298d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#elif defined(OPENSSL_SYS_VMS)
182398d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	struct timeb tb;
182498d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	ftime(&tb);
182598d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_sec = (long)tb.time;
182698d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	t->tv_usec = (long)tb.millitm * 1000;
182798d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#else
182898d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	gettimeofday(t, NULL);
182998d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom#endif
183098d58bb80c64b02a33662f0ea80351d4a1535267Brian Carlstrom	}
1831ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom
1832ee7afb3c942c4eefef6ed06201eafaf8ec58e2e3Brian Carlstrom#endif
1833