summaryrefslogtreecommitdiff
path: root/lib/libcrypto/bio/bss_dgram.c
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2015-02-09 10:55:34 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2015-02-09 10:55:34 +0000
commit95251fcce2725cc6008aa90d6a9b57745574ff1a (patch)
tree0386ca55285360abfbda407f2ec8610ad6126bf6 /lib/libcrypto/bio/bss_dgram.c
parenta725554be70ff9ce930ed2c9c3865e280b509385 (diff)
Jettison SCTP support in BIO dgram.
OpenBSD does not have SCTP support and it sees little use in the wild. OPENSSL_NO_SCTP is already specified via opensslfeatures.h, hence this is a code removal only and symbols should remain unchanged. ok beck@ miod@ tedu@
Diffstat (limited to 'lib/libcrypto/bio/bss_dgram.c')
-rw-r--r--lib/libcrypto/bio/bss_dgram.c995
1 files changed, 1 insertions, 994 deletions
diff --git a/lib/libcrypto/bio/bss_dgram.c b/lib/libcrypto/bio/bss_dgram.c
index ecf12fcb331..a07834b62ce 100644
--- a/lib/libcrypto/bio/bss_dgram.c
+++ b/lib/libcrypto/bio/bss_dgram.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bss_dgram.c,v 1.39 2015/01/12 02:15:23 doug Exp $ */
+/* $OpenBSD: bss_dgram.c,v 1.40 2015/02/09 10:55:33 jsing Exp $ */
/*
* DTLS implementation written by Nagendra Modadugu
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -74,12 +74,6 @@
#ifndef OPENSSL_NO_DGRAM
-#ifndef OPENSSL_NO_SCTP
-#include <netinet/sctp.h>
-#include <fcntl.h>
-#define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00
-#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
-#endif
static int dgram_write(BIO *h, const char *buf, int num);
static int dgram_read(BIO *h, char *buf, int size);
@@ -89,18 +83,6 @@ static int dgram_new(BIO *h);
static int dgram_free(BIO *data);
static int dgram_clear(BIO *bio);
-#ifndef OPENSSL_NO_SCTP
-static int dgram_sctp_write(BIO *h, const char *buf, int num);
-static int dgram_sctp_read(BIO *h, char *buf, int size);
-static int dgram_sctp_puts(BIO *h, const char *str);
-static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
-static int dgram_sctp_new(BIO *h);
-static int dgram_sctp_free(BIO *data);
-#ifdef SCTP_AUTHENTICATION_EVENT
-static void dgram_sctp_handle_auth_free_key_event(BIO *b,
- union sctp_notification *snp);
-#endif
-#endif
static int BIO_dgram_should_retry(int s);
@@ -115,18 +97,6 @@ static BIO_METHOD methods_dgramp = {
.destroy = dgram_free
};
-#ifndef OPENSSL_NO_SCTP
-static BIO_METHOD methods_dgramp_sctp = {
- .type = BIO_TYPE_DGRAM_SCTP,
- .name = "datagram sctp socket",
- .bwrite = dgram_sctp_write,
- .bread = dgram_sctp_read,
- .bputs = dgram_sctp_puts,
- .ctrl = dgram_sctp_ctrl,
- .create = dgram_sctp_new,
- .destroy = dgram_sctp_free
-};
-#endif
typedef struct bio_dgram_data_st {
union {
@@ -141,35 +111,6 @@ typedef struct bio_dgram_data_st {
struct timeval socket_timeout;
} bio_dgram_data;
-#ifndef OPENSSL_NO_SCTP
-typedef struct bio_dgram_sctp_save_message_st {
- BIO *bio;
- char *data;
- int length;
-} bio_dgram_sctp_save_message;
-
-typedef struct bio_dgram_sctp_data_st {
- union {
- struct sockaddr sa;
- struct sockaddr_in sa_in;
- struct sockaddr_in6 sa_in6;
- } peer;
- unsigned int connected;
- unsigned int _errno;
- unsigned int mtu;
- struct bio_dgram_sctp_sndinfo sndinfo;
- struct bio_dgram_sctp_rcvinfo rcvinfo;
- struct bio_dgram_sctp_prinfo prinfo;
- void (*handle_notifications)(BIO *bio, void *context, void *buf);
- void* notification_context;
- int in_handshake;
- int ccs_rcvd;
- int ccs_sent;
- int save_shutdown;
- int peer_auth_tested;
- bio_dgram_sctp_save_message saved_message;
-} bio_dgram_sctp_data;
-#endif
BIO_METHOD *
BIO_s_datagram(void)
@@ -686,940 +627,6 @@ dgram_puts(BIO *bp, const char *str)
return (ret);
}
-#ifndef OPENSSL_NO_SCTP
-BIO_METHOD *
-BIO_s_datagram_sctp(void)
-{
- return (&methods_dgramp_sctp);
-}
-
-BIO *
-BIO_new_dgram_sctp(int fd, int close_flag)
-{
- BIO *bio;
- int ret, optval = 20000;
- int auth_data = 0, auth_forward = 0;
- unsigned char *p;
- struct sctp_authchunk auth;
- struct sctp_authchunks *authchunks;
- socklen_t sockopt_len;
-#ifdef SCTP_AUTHENTICATION_EVENT
-#ifdef SCTP_EVENT
- struct sctp_event event;
-#else
- struct sctp_event_subscribe event;
-#endif
-#endif
-
- bio = BIO_new(BIO_s_datagram_sctp());
- if (bio == NULL)
- return (NULL);
- BIO_set_fd(bio, fd, close_flag);
-
- /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
- auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
- ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
- if (ret < 0)
- goto err;
- auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
- ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
- if (ret < 0)
- goto err;
-
- /* Test if activation was successful. When using accept(),
- * SCTP-AUTH has to be activated for the listening socket
- * already, otherwise the connected socket won't use it. */
- sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
- authchunks = calloc(1, sockopt_len);
- if (authchunks == NULL)
- goto err;
- ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
- if (ret < 0) {
- free(authchunks);
- goto err;
- }
-
- for (p = (unsigned char*) authchunks->gauth_chunks;
- p < (unsigned char*) authchunks + sockopt_len;
- p += sizeof(uint8_t)) {
- if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
- auth_data = 1;
- if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
- auth_forward = 1;
- }
-
- free(authchunks);
-
- OPENSSL_assert(auth_data);
- OPENSSL_assert(auth_forward);
-
-#ifdef SCTP_AUTHENTICATION_EVENT
-#ifdef SCTP_EVENT
- memset(&event, 0, sizeof(struct sctp_event));
- event.se_assoc_id = 0;
- event.se_type = SCTP_AUTHENTICATION_EVENT;
- event.se_on = 1;
- ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
- if (ret < 0)
- goto err;
-#else
- sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
- ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
- if (ret < 0)
- goto err;
-
- event.sctp_authentication_event = 1;
-
- ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
- if (ret < 0)
- goto err;
-#endif
-#endif
-
- /* Disable partial delivery by setting the min size
- * larger than the max record size of 2^14 + 2048 + 13
- */
- ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
- if (ret < 0)
- goto err;
-
- return (bio);
-
-err:
- BIO_vfree(bio);
- return (NULL);
-}
-
-int
-BIO_dgram_is_sctp(BIO *bio)
-{
- return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
-}
-
-static int
-dgram_sctp_new(BIO *bi)
-{
- bio_dgram_sctp_data *data = NULL;
-
- bi->init = 0;
- bi->num = 0;
- data = calloc(1, sizeof(bio_dgram_sctp_data));
- if (data == NULL)
- return 0;
-#ifdef SCTP_PR_SCTP_NONE
- data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
-#endif
- bi->ptr = data;
-
- bi->flags = 0;
- return (1);
-}
-
-static int
-dgram_sctp_free(BIO *a)
-{
- bio_dgram_sctp_data *data;
-
- if (a == NULL)
- return (0);
- if (! dgram_clear(a))
- return 0;
-
- data = (bio_dgram_sctp_data *)a->ptr;
- if (data != NULL) {
- free(data->saved_message.data);
- free(data);
- a->ptr = NULL;
- }
-
- return (1);
-}
-
-#ifdef SCTP_AUTHENTICATION_EVENT
-void
-dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
-{
- int ret;
- struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
-
- if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) {
- struct sctp_authkeyid authkeyid;
-
- /* delete key */
- authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
- &authkeyid, sizeof(struct sctp_authkeyid));
- }
-}
-#endif
-
-static int
-dgram_sctp_read(BIO *b, char *out, int outl)
-{
- int ret = 0, n = 0, i, optval;
- socklen_t optlen;
- bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
- union sctp_notification *snp;
- struct msghdr msg;
- struct iovec iov;
- struct cmsghdr *cmsg;
- char cmsgbuf[512];
-
- if (out != NULL) {
- errno = 0;
-
- do {
- memset(&data->rcvinfo, 0, sizeof(struct bio_dgram_sctp_rcvinfo));
- iov.iov_base = out;
- iov.iov_len = outl;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = cmsgbuf;
- msg.msg_controllen = 512;
- msg.msg_flags = 0;
- n = recvmsg(b->num, &msg, 0);
-
- if (msg.msg_controllen > 0) {
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level != IPPROTO_SCTP)
- continue;
-#ifdef SCTP_RCVINFO
- if (cmsg->cmsg_type == SCTP_RCVINFO) {
- struct sctp_rcvinfo *rcvinfo;
-
- rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
- data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
- data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
- data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
- data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
- data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
- data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
- data->rcvinfo.rcv_context = rcvinfo->rcv_context;
- }
-#endif
-#ifdef SCTP_SNDRCV
- if (cmsg->cmsg_type == SCTP_SNDRCV) {
- struct sctp_sndrcvinfo *sndrcvinfo;
-
- sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
- data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
- data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
- data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
- data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
- data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
- data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
- data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
- }
-#endif
- }
- }
-
- if (n <= 0) {
- if (n < 0)
- ret = n;
- break;
- }
-
- if (msg.msg_flags & MSG_NOTIFICATION) {
- snp = (union sctp_notification*) out;
- if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
-#ifdef SCTP_EVENT
- struct sctp_event event;
-#else
- struct sctp_event_subscribe event;
- socklen_t eventsize;
-#endif
- /* If a message has been delayed until the socket
- * is dry, it can be sent now.
- */
- if (data->saved_message.length > 0) {
- dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
- data->saved_message.length);
- free(data->saved_message.data);
- data->saved_message.data = NULL;
- data->saved_message.length = 0;
- }
-
- /* disable sender dry event */
-#ifdef SCTP_EVENT
- memset(&event, 0, sizeof(struct sctp_event));
- event.se_assoc_id = 0;
- event.se_type = SCTP_SENDER_DRY_EVENT;
- event.se_on = 0;
- i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
- if (i < 0) {
- ret = i;
- break;
- }
-#else
- eventsize = sizeof(struct sctp_event_subscribe);
- i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
- if (i < 0) {
- ret = i;
- break;
- }
-
- event.sctp_sender_dry_event = 0;
-
- i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
- if (i < 0) {
- ret = i;
- break;
- }
-#endif
- }
-
-#ifdef SCTP_AUTHENTICATION_EVENT
- if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
- dgram_sctp_handle_auth_free_key_event(b, snp);
-#endif
-
- if (data->handle_notifications != NULL)
- data->handle_notifications(b, data->notification_context, (void*) out);
-
- memset(out, 0, outl);
- } else
- ret += n;
- }
- while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
-
- if (ret > 0 && !(msg.msg_flags & MSG_EOR)) {
- /* Partial message read, this should never happen! */
-
- /* The buffer was too small, this means the peer sent
- * a message that was larger than allowed. */
- if (ret == outl)
- return -1;
-
- /* Test if socket buffer can handle max record
- * size (2^14 + 2048 + 13)
- */
- optlen = (socklen_t) sizeof(int);
- ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
- if (ret >= 0)
- OPENSSL_assert(optval >= 18445);
-
- /* Test if SCTP doesn't partially deliver below
- * max record size (2^14 + 2048 + 13)
- */
- optlen = (socklen_t) sizeof(int);
- ret = getsockopt(b->num, IPPROTO_SCTP,
- SCTP_PARTIAL_DELIVERY_POINT, &optval, &optlen);
- if (ret >= 0)
- OPENSSL_assert(optval >= 18445);
-
- /* Partially delivered notification??? Probably a bug.... */
- OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
-
- /* Everything seems ok till now, so it's most likely
- * a message dropped by PR-SCTP.
- */
- memset(out, 0, outl);
- BIO_set_retry_read(b);
- return -1;
- }
-
- BIO_clear_retry_flags(b);
- if (ret < 0) {
- if (BIO_dgram_should_retry(ret)) {
- BIO_set_retry_read(b);
- data->_errno = errno;
- }
- }
-
- /* Test if peer uses SCTP-AUTH before continuing */
- if (!data->peer_auth_tested) {
- int ii, auth_data = 0, auth_forward = 0;
- unsigned char *p;
- struct sctp_authchunks *authchunks;
-
- optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
- authchunks = calloc(1, optlen);
- if (authchunks == NULL) {
- BIOerr(BIO_F_DGRAM_SCTP_READ,
- ERR_R_MALLOC_ERROR);
- return (-1);
- }
- ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
- if (ii >= 0) {
- for (p = (unsigned char*) authchunks->gauth_chunks;
- p < (unsigned char*) authchunks + optlen;
- p += sizeof(uint8_t)) {
- if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
- auth_data = 1;
- if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
- auth_forward = 1;
- }
- }
-
- free(authchunks);
-
- if (!auth_data || !auth_forward) {
- BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR);
- return -1;
- }
-
- data->peer_auth_tested = 1;
- }
- }
- return (ret);
-}
-
-static int
-dgram_sctp_write(BIO *b, const char *in, int inl)
-{
- int ret;
- bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
- struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
- struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
- struct bio_dgram_sctp_sndinfo handshake_sinfo;
- struct iovec iov[1];
- struct msghdr msg;
- struct cmsghdr *cmsg;
-#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
- char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
- struct sctp_sndinfo *sndinfo;
- struct sctp_prinfo *prinfo;
-#else
- char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
- struct sctp_sndrcvinfo *sndrcvinfo;
-#endif
-
- errno = 0;
-
- /* If we're send anything else than application data,
- * disable all user parameters and flags.
- */
- if (in[0] != 23) {
- memset(&handshake_sinfo, 0, sizeof(struct bio_dgram_sctp_sndinfo));
-#ifdef SCTP_SACK_IMMEDIATELY
- handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
-#endif
- sinfo = &handshake_sinfo;
- }
-
- /* If we have to send a shutdown alert message and the
- * socket is not dry yet, we have to save it and send it
- * as soon as the socket gets dry.
- */
- if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b)) {
- data->saved_message.bio = b;
- free(data->saved_message.data);
- data->saved_message.data = malloc(inl);
- if (data->saved_message.data == NULL) {
- data->_errno = ENOMEM;
- return -1;
- }
- memcpy(data->saved_message.data, in, inl);
- data->saved_message.length = inl;
- return inl;
- }
-
- iov[0].iov_base = (char *)in;
- iov[0].iov_len = inl;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_control = (caddr_t)cmsgbuf;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
- cmsg = (struct cmsghdr *)cmsgbuf;
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_SNDINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
- sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
- memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
- sndinfo->snd_sid = sinfo->snd_sid;
- sndinfo->snd_flags = sinfo->snd_flags;
- sndinfo->snd_ppid = sinfo->snd_ppid;
- sndinfo->snd_context = sinfo->snd_context;
- msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
-
- cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_PRINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
- prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
- memset(prinfo, 0, sizeof(struct sctp_prinfo));
- prinfo->pr_policy = pinfo->pr_policy;
- prinfo->pr_value = pinfo->pr_value;
- msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
-#else
- cmsg = (struct cmsghdr *)cmsgbuf;
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_SNDRCV;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
- sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
- memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
- sndrcvinfo->sinfo_stream = sinfo->snd_sid;
- sndrcvinfo->sinfo_flags = sinfo->snd_flags;
- sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
- sndrcvinfo->sinfo_context = sinfo->snd_context;
- sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
- msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
-#endif
-
- ret = sendmsg(b->num, &msg, 0);
-
- BIO_clear_retry_flags(b);
- if (ret <= 0) {
- if (BIO_dgram_should_retry(ret)) {
- BIO_set_retry_write(b);
-
- data->_errno = errno;
- }
- }
- return (ret);
-}
-
-static long
-dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
-{
- long ret = 1;
- bio_dgram_sctp_data *data = NULL;
- socklen_t sockopt_len = 0;
- struct sctp_authkeyid authkeyid;
-
- data = (bio_dgram_sctp_data *)b->ptr;
-
- switch (cmd) {
- case BIO_CTRL_DGRAM_QUERY_MTU:
- /* Set to maximum (2^14)
- * and ignore user input to enable transport
- * protocol fragmentation.
- * Returns always 2^14.
- */
- data->mtu = 16384;
- ret = data->mtu;
- break;
- case BIO_CTRL_DGRAM_SET_MTU:
- /* Set to maximum (2^14)
- * and ignore input to enable transport
- * protocol fragmentation.
- * Returns always 2^14.
- */
- data->mtu = 16384;
- ret = data->mtu;
- break;
- case BIO_CTRL_DGRAM_SET_CONNECTED:
- case BIO_CTRL_DGRAM_CONNECT:
- /* Returns always -1. */
- ret = -1;
- break;
- case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
- /* SCTP doesn't need the DTLS timer
- * Returns always 1.
- */
- break;
- case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
- if (num > 0)
- data->in_handshake = 1;
- else
- data->in_handshake = 0;
-
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
- break;
- case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
- {
- struct sctp_authkey *authkey;
-
- /* New shared key for SCTP AUTH.
- * Returns 0 on success, -1 otherwise.
- */
-
- /* Get active key */
- sockopt_len = sizeof(struct sctp_authkeyid);
- ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
- &authkeyid, &sockopt_len);
- if (ret < 0)
- break;
-
- /* Add new key */
- sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
- authkey = calloc(1, sockopt_len);
- if (authkey == NULL) {
- ret = -1;
- break;
- }
- authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
- authkey->sca_keylength = 64;
- memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
-
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey,
- sockopt_len);
- free(authkey);
- if (ret < 0)
- break;
-
- /* Reset active key */
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
- &authkeyid, sizeof(struct sctp_authkeyid));
- if (ret < 0)
- break;
- }
- break;
- case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
- /* Returns 0 on success, -1 otherwise. */
-
- /* Get active key */
- sockopt_len = sizeof(struct sctp_authkeyid);
- ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
- &authkeyid, &sockopt_len);
- if (ret < 0)
- break;
-
- /* Set active key */
- authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
- &authkeyid, sizeof(struct sctp_authkeyid));
- if (ret < 0)
- break;
-
- /* CCS has been sent, so remember that and fall through
- * to check if we need to deactivate an old key
- */
- data->ccs_sent = 1;
-
- case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
- /* Returns 0 on success, -1 otherwise. */
-
- /* Has this command really been called or is this just a fall-through? */
- if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
- data->ccs_rcvd = 1;
-
- /* CSS has been both, received and sent, so deactivate an old key */
- if (data->ccs_rcvd == 1 && data->ccs_sent == 1) {
- /* Get active key */
- sockopt_len = sizeof(struct sctp_authkeyid);
- ret = getsockopt(b->num, IPPROTO_SCTP,
- SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
- if (ret < 0)
- break;
-
- /* Deactivate key or delete second last key if
- * SCTP_AUTHENTICATION_EVENT is not available.
- */
- authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
-#ifdef SCTP_AUTH_DEACTIVATE_KEY
- sockopt_len = sizeof(struct sctp_authkeyid);
- ret = setsockopt(b->num, IPPROTO_SCTP,
- SCTP_AUTH_DEACTIVATE_KEY, &authkeyid, sockopt_len);
- if (ret < 0)
- break;
-#endif
-#ifndef SCTP_AUTHENTICATION_EVENT
- if (authkeyid.scact_keynumber > 0) {
- authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
- &authkeyid, sizeof(struct sctp_authkeyid));
- if (ret < 0)
- break;
- }
-#endif
-
- data->ccs_rcvd = 0;
- data->ccs_sent = 0;
- }
- break;
- case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
- /* Returns the size of the copied struct. */
- if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
- num = sizeof(struct bio_dgram_sctp_sndinfo);
-
- memcpy(ptr, &(data->sndinfo), num);
- ret = num;
- break;
- case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
- /* Returns the size of the copied struct. */
- if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
- num = sizeof(struct bio_dgram_sctp_sndinfo);
-
- memcpy(&(data->sndinfo), ptr, num);
- break;
- case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
- /* Returns the size of the copied struct. */
- if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
- num = sizeof(struct bio_dgram_sctp_rcvinfo);
-
- memcpy(ptr, &data->rcvinfo, num);
-
- ret = num;
- break;
- case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
- /* Returns the size of the copied struct. */
- if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
- num = sizeof(struct bio_dgram_sctp_rcvinfo);
-
- memcpy(&(data->rcvinfo), ptr, num);
- break;
- case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
- /* Returns the size of the copied struct. */
- if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
- num = sizeof(struct bio_dgram_sctp_prinfo);
-
- memcpy(ptr, &(data->prinfo), num);
- ret = num;
- break;
- case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
- /* Returns the size of the copied struct. */
- if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
- num = sizeof(struct bio_dgram_sctp_prinfo);
-
- memcpy(&(data->prinfo), ptr, num);
- break;
- case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
- /* Returns always 1. */
- if (num > 0)
- data->save_shutdown = 1;
- else
- data->save_shutdown = 0;
- break;
-
- default:
- /* Pass to default ctrl function to
- * process SCTP unspecific commands
- */
- ret = dgram_ctrl(b, cmd, num, ptr);
- break;
- }
- return (ret);
-}
-
-int
-BIO_dgram_sctp_notification_cb(BIO *b,
- void (*handle_notifications)(BIO *bio, void *context, void *buf),
- void *context)
-{
- bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
-
- if (handle_notifications != NULL) {
- data->handle_notifications = handle_notifications;
- data->notification_context = context;
- } else
- return -1;
-
- return 0;
-}
-
-int
-BIO_dgram_sctp_wait_for_dry(BIO *b)
-{
- int is_dry = 0;
- int n, sockflags, ret;
- union sctp_notification snp;
- struct msghdr msg;
- struct iovec iov;
-#ifdef SCTP_EVENT
- struct sctp_event event;
-#else
- struct sctp_event_subscribe event;
- socklen_t eventsize;
-#endif
- bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
-
- /* set sender dry event */
-#ifdef SCTP_EVENT
- memset(&event, 0, sizeof(struct sctp_event));
- event.se_assoc_id = 0;
- event.se_type = SCTP_SENDER_DRY_EVENT;
- event.se_on = 1;
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
-#else
- eventsize = sizeof(struct sctp_event_subscribe);
- ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
- if (ret < 0)
- return -1;
-
- event.sctp_sender_dry_event = 1;
-
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
-#endif
- if (ret < 0)
- return -1;
-
- /* peek for notification */
- memset(&snp, 0, sizeof(union sctp_notification));
- iov.iov_base = (char *)&snp;
- iov.iov_len = sizeof(union sctp_notification);
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- n = recvmsg(b->num, &msg, MSG_PEEK);
- if (n <= 0) {
- if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
- return -1;
- else
- return 0;
- }
-
- /* if we find a notification, process it and try again if necessary */
- while (msg.msg_flags & MSG_NOTIFICATION) {
- memset(&snp, 0, sizeof(union sctp_notification));
- iov.iov_base = (char *)&snp;
- iov.iov_len = sizeof(union sctp_notification);
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- n = recvmsg(b->num, &msg, 0);
- if (n <= 0) {
- if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
- return -1;
- else
- return is_dry;
- }
-
- if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
- is_dry = 1;
-
- /* disable sender dry event */
-#ifdef SCTP_EVENT
- memset(&event, 0, sizeof(struct sctp_event));
- event.se_assoc_id = 0;
- event.se_type = SCTP_SENDER_DRY_EVENT;
- event.se_on = 0;
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
-#else
- eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
- ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
- if (ret < 0)
- return -1;
-
- event.sctp_sender_dry_event = 0;
-
- ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
-#endif
- if (ret < 0)
- return -1;
- }
-
-#ifdef SCTP_AUTHENTICATION_EVENT
- if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
- dgram_sctp_handle_auth_free_key_event(b, &snp);
-#endif
-
- if (data->handle_notifications != NULL)
- data->handle_notifications(b, data->notification_context, (void*) &snp);
-
- /* found notification, peek again */
- memset(&snp, 0, sizeof(union sctp_notification));
- iov.iov_base = (char *)&snp;
- iov.iov_len = sizeof(union sctp_notification);
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- /* if we have seen the dry already, don't wait */
- if (is_dry) {
- sockflags = fcntl(b->num, F_GETFL, 0);
- fcntl(b->num, F_SETFL, O_NONBLOCK);
- }
-
- n = recvmsg(b->num, &msg, MSG_PEEK);
-
- if (is_dry) {
- fcntl(b->num, F_SETFL, sockflags);
- }
-
- if (n <= 0) {
- if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
- return -1;
- else
- return is_dry;
- }
- }
-
- /* read anything else */
- return is_dry;
-}
-
-int
-BIO_dgram_sctp_msg_waiting(BIO *b)
-{
- int n, sockflags;
- union sctp_notification snp;
- struct msghdr msg;
- struct iovec iov;
- bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
-
- /* Check if there are any messages waiting to be read */
- do
- {
- memset(&snp, 0, sizeof(union sctp_notification));
- iov.iov_base = (char *)&snp;
- iov.iov_len = sizeof(union sctp_notification);
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- sockflags = fcntl(b->num, F_GETFL, 0);
- fcntl(b->num, F_SETFL, O_NONBLOCK);
- n = recvmsg(b->num, &msg, MSG_PEEK);
- fcntl(b->num, F_SETFL, sockflags);
-
- /* if notification, process and try again */
- if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) {
-#ifdef SCTP_AUTHENTICATION_EVENT
- if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
- dgram_sctp_handle_auth_free_key_event(b, &snp);
-#endif
-
- memset(&snp, 0, sizeof(union sctp_notification));
- iov.iov_base = (char *)&snp;
- iov.iov_len = sizeof(union sctp_notification);
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
- n = recvmsg(b->num, &msg, 0);
-
- if (data->handle_notifications != NULL)
- data->handle_notifications(b, data->notification_context, (void*) &snp);
- }
-
- } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
-
- /* Return 1 if there is a message to be read, return 0 otherwise. */
- if (n > 0)
- return 1;
- else
- return 0;
-}
-
-static int
-dgram_sctp_puts(BIO *bp, const char *str)
-{
- int n, ret;
-
- n = strlen(str);
- ret = dgram_sctp_write(bp, str, n);
- return (ret);
-}
-#endif
static int
BIO_dgram_should_retry(int i)