#include <stdio.h>
#include <errno.h>
#define USE_SOCKETS
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
#include <openssl/bio.h>
#ifndef OPENSSL_NO_DGRAM
static int dgram_new(BIO *bi)
{
- bio_dgram_data *data = NULL;
+ bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data));
- bi->init = 0;
- bi->num = 0;
- data = OPENSSL_malloc(sizeof(*data));
if (data == NULL)
return 0;
- memset(data, 0, sizeof(*data));
+ bi->init = 0;
+ bi->num = 0;
bi->ptr = data;
-
bi->flags = 0;
return (1);
}
/* Calculate time left until timer expires */
memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
- timeleft.tv_sec -= timenow.tv_sec;
- timeleft.tv_usec -= timenow.tv_usec;
- if (timeleft.tv_usec < 0) {
+ if (timeleft.tv_usec < timenow.tv_usec) {
+ timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec;
timeleft.tv_sec--;
- timeleft.tv_usec += 1000000;
+ } else {
+ timeleft.tv_usec -= timenow.tv_usec;
}
-
- if (timeleft.tv_sec < 0) {
+ if (timeleft.tv_sec < timenow.tv_sec) {
timeleft.tv_sec = 0;
timeleft.tv_usec = 1;
+ } else {
+ timeleft.tv_sec -= timenow.tv_sec;
}
/*
perror("setsockopt");
ret = -1;
}
-# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTUDISCOVER)
+# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined (IP_PMTUDISC_PROBE)
if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT),
(ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
&sockopt_val, sizeof(sockopt_val))) < 0) {
* connected socket won't use it.
*/
sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
- authchunks = OPENSSL_malloc(sockopt_len);
+ authchunks = OPENSSL_zalloc(sockopt_len);
if (!authchunks) {
BIO_vfree(bio);
return (NULL);
}
- memset(authchunks, 0, sockopt_len);
- ret =
- getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks,
+ ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks,
&sockopt_len);
-
if (ret < 0) {
OPENSSL_free(authchunks);
BIO_vfree(bio);
bi->init = 0;
bi->num = 0;
- data = OPENSSL_malloc(sizeof(*data));
+ data = OPENSSL_zalloc(sizeof(*data));
if (data == NULL)
return 0;
- memset(data, 0, sizeof(*data));
# ifdef SCTP_PR_SCTP_NONE
data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
# endif
* it can be sent now.
*/
if (data->saved_message.length > 0) {
- dgram_sctp_write(data->saved_message.bio,
+ i = dgram_sctp_write(data->saved_message.bio,
data->saved_message.data,
data->saved_message.length);
+ if (i < 0) {
+ ret = i;
+ break;
+ }
OPENSSL_free(data->saved_message.data);
data->saved_message.data = NULL;
data->saved_message.length = 0;
return (ret);
}
+/*
+ * dgram_sctp_write - send message on SCTP socket
+ * @b: BIO to write to
+ * @in: data to send
+ * @inl: amount of bytes in @in to send
+ *
+ * Returns -1 on error or the sent amount of bytes on success
+ */
static int dgram_sctp_write(BIO *b, const char *in, int inl)
{
int ret;
* 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)) {
- char *tmp;
- data->saved_message.bio = b;
- if ((tmp = OPENSSL_malloc(inl)) == NULL) {
- BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_FAILURE);
+ if (data->save_shutdown) {
+ ret = BIO_dgram_sctp_wait_for_dry(b);
+ if (ret < 0) {
return -1;
}
- OPENSSL_free(data->saved_message.data);
- data->saved_message.data = tmp;
- memcpy(data->saved_message.data, in, inl);
- data->saved_message.length = inl;
- return inl;
+ if (ret == 0) {
+ char *tmp;
+ data->saved_message.bio = b;
+ if ((tmp = OPENSSL_malloc(inl)) == NULL) {
+ BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ OPENSSL_free(data->saved_message.data);
+ data->saved_message.data = tmp;
+ memcpy(data->saved_message.data, in, inl);
+ data->saved_message.length = inl;
+ return inl;
+ }
}
iov[0].iov_base = (char *)in;
return 0;
}
+/*
+ * BIO_dgram_sctp_wait_for_dry - Wait for SCTP SENDER_DRY event
+ * @b: The BIO to check for the dry event
+ *
+ * Wait until the peer confirms all packets have been received, and so that
+ * our kernel doesn't have anything to send anymore. This is only received by
+ * the peer's kernel, not the application.
+ *
+ * Returns:
+ * -1 on error
+ * 0 when not dry yet
+ * 1 when dry
+ */
int BIO_dgram_sctp_wait_for_dry(BIO *b)
{
int is_dry = 0;