summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2015-02-09 10:55:33 +0000
committerjsing <>2015-02-09 10:55:33 +0000
commitb1708fb06623ef1ece520a3f98163861f92085de (patch)
tree648f25d5e344ebd23f976121600816e0d5ef44d7
parentb6cf79472f84871a9cffc9c9ee7643d17e8943a4 (diff)
downloadopenbsd-b1708fb06623ef1ece520a3f98163861f92085de.tar.gz
openbsd-b1708fb06623ef1ece520a3f98163861f92085de.tar.bz2
openbsd-b1708fb06623ef1ece520a3f98163861f92085de.zip
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@
-rw-r--r--src/lib/libcrypto/bio/bio.h59
-rw-r--r--src/lib/libcrypto/bio/bss_dgram.c995
-rw-r--r--src/lib/libssl/src/crypto/bio/bio.h59
-rw-r--r--src/lib/libssl/src/crypto/bio/bss_dgram.c995
4 files changed, 4 insertions, 2104 deletions
diff --git a/src/lib/libcrypto/bio/bio.h b/src/lib/libcrypto/bio/bio.h
index 6868959599..339a5c456b 100644
--- a/src/lib/libcrypto/bio/bio.h
+++ b/src/lib/libcrypto/bio/bio.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bio.h,v 1.27 2014/07/20 02:24:21 guenther Exp $ */ 1/* $OpenBSD: bio.h,v 1.28 2015/02/09 10:55:33 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -68,9 +68,6 @@
68 68
69#include <openssl/crypto.h> 69#include <openssl/crypto.h>
70 70
71#ifndef OPENSSL_NO_SCTP
72# include <stdint.h>
73#endif
74 71
75#ifdef __cplusplus 72#ifdef __cplusplus
76extern "C" { 73extern "C" {
@@ -99,9 +96,6 @@ extern "C" {
99#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */ 96#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */
100#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */ 97#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
101#define BIO_TYPE_DGRAM (21|0x0400|0x0100) 98#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
102#ifndef OPENSSL_NO_SCTP
103#define BIO_TYPE_DGRAM_SCTP (24|0x0400|0x0100)
104#endif
105#define BIO_TYPE_ASN1 (22|0x0200) /* filter */ 99#define BIO_TYPE_ASN1 (22|0x0200) /* filter */
106#define BIO_TYPE_COMP (23|0x0200) /* filter */ 100#define BIO_TYPE_COMP (23|0x0200) /* filter */
107 101
@@ -171,20 +165,6 @@ extern "C" {
171#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to 165#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to
172 * adjust socket timeouts */ 166 * adjust socket timeouts */
173 167
174#ifndef OPENSSL_NO_SCTP
175/* SCTP stuff */
176#define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50
177#define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51
178#define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52
179#define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53
180#define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60
181#define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61
182#define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62
183#define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63
184#define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64
185#define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65
186#define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70
187#endif
188 168
189/* modifiers */ 169/* modifiers */
190#define BIO_FP_READ 0x02 170#define BIO_FP_READ 0x02
@@ -347,30 +327,6 @@ typedef struct bio_f_buffer_ctx_struct {
347/* Prefix and suffix callback in ASN1 BIO */ 327/* Prefix and suffix callback in ASN1 BIO */
348typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg); 328typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
349 329
350#ifndef OPENSSL_NO_SCTP
351/* SCTP parameter structs */
352struct bio_dgram_sctp_sndinfo {
353 uint16_t snd_sid;
354 uint16_t snd_flags;
355 uint32_t snd_ppid;
356 uint32_t snd_context;
357};
358
359struct bio_dgram_sctp_rcvinfo {
360 uint16_t rcv_sid;
361 uint16_t rcv_ssn;
362 uint16_t rcv_flags;
363 uint32_t rcv_ppid;
364 uint32_t rcv_tsn;
365 uint32_t rcv_cumtsn;
366 uint32_t rcv_context;
367};
368
369struct bio_dgram_sctp_prinfo {
370 uint16_t pr_policy;
371 uint32_t pr_value;
372};
373#endif
374 330
375/* connect BIO stuff */ 331/* connect BIO stuff */
376#define BIO_CONN_S_BEFORE 1 332#define BIO_CONN_S_BEFORE 1
@@ -664,9 +620,6 @@ BIO_METHOD *BIO_f_buffer(void);
664BIO_METHOD *BIO_f_nbio_test(void); 620BIO_METHOD *BIO_f_nbio_test(void);
665#ifndef OPENSSL_NO_DGRAM 621#ifndef OPENSSL_NO_DGRAM
666BIO_METHOD *BIO_s_datagram(void); 622BIO_METHOD *BIO_s_datagram(void);
667#ifndef OPENSSL_NO_SCTP
668BIO_METHOD *BIO_s_datagram_sctp(void);
669#endif
670#endif 623#endif
671 624
672/* BIO_METHOD *BIO_f_ber(void); */ 625/* BIO_METHOD *BIO_f_ber(void); */
@@ -709,16 +662,6 @@ int BIO_set_tcp_ndelay(int sock, int turn_on);
709 662
710BIO *BIO_new_socket(int sock, int close_flag); 663BIO *BIO_new_socket(int sock, int close_flag);
711BIO *BIO_new_dgram(int fd, int close_flag); 664BIO *BIO_new_dgram(int fd, int close_flag);
712#ifndef OPENSSL_NO_SCTP
713BIO *BIO_new_dgram_sctp(int fd, int close_flag);
714int BIO_dgram_is_sctp(BIO *bio);
715int
716BIO_dgram_sctp_notification_cb(BIO *b,
717 void (*handle_notifications)(BIO *bio, void *context, void *buf),
718void *context);
719int BIO_dgram_sctp_wait_for_dry(BIO *b);
720int BIO_dgram_sctp_msg_waiting(BIO *b);
721#endif
722BIO *BIO_new_fd(int fd, int close_flag); 665BIO *BIO_new_fd(int fd, int close_flag);
723BIO *BIO_new_connect(char *host_port); 666BIO *BIO_new_connect(char *host_port);
724BIO *BIO_new_accept(char *host_port); 667BIO *BIO_new_accept(char *host_port);
diff --git a/src/lib/libcrypto/bio/bss_dgram.c b/src/lib/libcrypto/bio/bss_dgram.c
index ecf12fcb33..a07834b62c 100644
--- a/src/lib/libcrypto/bio/bss_dgram.c
+++ b/src/lib/libcrypto/bio/bss_dgram.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bss_dgram.c,v 1.39 2015/01/12 02:15:23 doug Exp $ */ 1/* $OpenBSD: bss_dgram.c,v 1.40 2015/02/09 10:55:33 jsing Exp $ */
2/* 2/*
3 * DTLS implementation written by Nagendra Modadugu 3 * DTLS implementation written by Nagendra Modadugu
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -74,12 +74,6 @@
74 74
75#ifndef OPENSSL_NO_DGRAM 75#ifndef OPENSSL_NO_DGRAM
76 76
77#ifndef OPENSSL_NO_SCTP
78#include <netinet/sctp.h>
79#include <fcntl.h>
80#define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00
81#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
82#endif
83 77
84static int dgram_write(BIO *h, const char *buf, int num); 78static int dgram_write(BIO *h, const char *buf, int num);
85static int dgram_read(BIO *h, char *buf, int size); 79static int dgram_read(BIO *h, char *buf, int size);
@@ -89,18 +83,6 @@ static int dgram_new(BIO *h);
89static int dgram_free(BIO *data); 83static int dgram_free(BIO *data);
90static int dgram_clear(BIO *bio); 84static int dgram_clear(BIO *bio);
91 85
92#ifndef OPENSSL_NO_SCTP
93static int dgram_sctp_write(BIO *h, const char *buf, int num);
94static int dgram_sctp_read(BIO *h, char *buf, int size);
95static int dgram_sctp_puts(BIO *h, const char *str);
96static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
97static int dgram_sctp_new(BIO *h);
98static int dgram_sctp_free(BIO *data);
99#ifdef SCTP_AUTHENTICATION_EVENT
100static void dgram_sctp_handle_auth_free_key_event(BIO *b,
101 union sctp_notification *snp);
102#endif
103#endif
104 86
105static int BIO_dgram_should_retry(int s); 87static int BIO_dgram_should_retry(int s);
106 88
@@ -115,18 +97,6 @@ static BIO_METHOD methods_dgramp = {
115 .destroy = dgram_free 97 .destroy = dgram_free
116}; 98};
117 99
118#ifndef OPENSSL_NO_SCTP
119static BIO_METHOD methods_dgramp_sctp = {
120 .type = BIO_TYPE_DGRAM_SCTP,
121 .name = "datagram sctp socket",
122 .bwrite = dgram_sctp_write,
123 .bread = dgram_sctp_read,
124 .bputs = dgram_sctp_puts,
125 .ctrl = dgram_sctp_ctrl,
126 .create = dgram_sctp_new,
127 .destroy = dgram_sctp_free
128};
129#endif
130 100
131typedef struct bio_dgram_data_st { 101typedef struct bio_dgram_data_st {
132 union { 102 union {
@@ -141,35 +111,6 @@ typedef struct bio_dgram_data_st {
141 struct timeval socket_timeout; 111 struct timeval socket_timeout;
142} bio_dgram_data; 112} bio_dgram_data;
143 113
144#ifndef OPENSSL_NO_SCTP
145typedef struct bio_dgram_sctp_save_message_st {
146 BIO *bio;
147 char *data;
148 int length;
149} bio_dgram_sctp_save_message;
150
151typedef struct bio_dgram_sctp_data_st {
152 union {
153 struct sockaddr sa;
154 struct sockaddr_in sa_in;
155 struct sockaddr_in6 sa_in6;
156 } peer;
157 unsigned int connected;
158 unsigned int _errno;
159 unsigned int mtu;
160 struct bio_dgram_sctp_sndinfo sndinfo;
161 struct bio_dgram_sctp_rcvinfo rcvinfo;
162 struct bio_dgram_sctp_prinfo prinfo;
163 void (*handle_notifications)(BIO *bio, void *context, void *buf);
164 void* notification_context;
165 int in_handshake;
166 int ccs_rcvd;
167 int ccs_sent;
168 int save_shutdown;
169 int peer_auth_tested;
170 bio_dgram_sctp_save_message saved_message;
171} bio_dgram_sctp_data;
172#endif
173 114
174BIO_METHOD * 115BIO_METHOD *
175BIO_s_datagram(void) 116BIO_s_datagram(void)
@@ -686,940 +627,6 @@ dgram_puts(BIO *bp, const char *str)
686 return (ret); 627 return (ret);
687} 628}
688 629
689#ifndef OPENSSL_NO_SCTP
690BIO_METHOD *
691BIO_s_datagram_sctp(void)
692{
693 return (&methods_dgramp_sctp);
694}
695
696BIO *
697BIO_new_dgram_sctp(int fd, int close_flag)
698{
699 BIO *bio;
700 int ret, optval = 20000;
701 int auth_data = 0, auth_forward = 0;
702 unsigned char *p;
703 struct sctp_authchunk auth;
704 struct sctp_authchunks *authchunks;
705 socklen_t sockopt_len;
706#ifdef SCTP_AUTHENTICATION_EVENT
707#ifdef SCTP_EVENT
708 struct sctp_event event;
709#else
710 struct sctp_event_subscribe event;
711#endif
712#endif
713
714 bio = BIO_new(BIO_s_datagram_sctp());
715 if (bio == NULL)
716 return (NULL);
717 BIO_set_fd(bio, fd, close_flag);
718
719 /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
720 auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
721 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
722 if (ret < 0)
723 goto err;
724 auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
725 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
726 if (ret < 0)
727 goto err;
728
729 /* Test if activation was successful. When using accept(),
730 * SCTP-AUTH has to be activated for the listening socket
731 * already, otherwise the connected socket won't use it. */
732 sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
733 authchunks = calloc(1, sockopt_len);
734 if (authchunks == NULL)
735 goto err;
736 ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
737 if (ret < 0) {
738 free(authchunks);
739 goto err;
740 }
741
742 for (p = (unsigned char*) authchunks->gauth_chunks;
743 p < (unsigned char*) authchunks + sockopt_len;
744 p += sizeof(uint8_t)) {
745 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
746 auth_data = 1;
747 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
748 auth_forward = 1;
749 }
750
751 free(authchunks);
752
753 OPENSSL_assert(auth_data);
754 OPENSSL_assert(auth_forward);
755
756#ifdef SCTP_AUTHENTICATION_EVENT
757#ifdef SCTP_EVENT
758 memset(&event, 0, sizeof(struct sctp_event));
759 event.se_assoc_id = 0;
760 event.se_type = SCTP_AUTHENTICATION_EVENT;
761 event.se_on = 1;
762 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
763 if (ret < 0)
764 goto err;
765#else
766 sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
767 ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
768 if (ret < 0)
769 goto err;
770
771 event.sctp_authentication_event = 1;
772
773 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
774 if (ret < 0)
775 goto err;
776#endif
777#endif
778
779 /* Disable partial delivery by setting the min size
780 * larger than the max record size of 2^14 + 2048 + 13
781 */
782 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
783 if (ret < 0)
784 goto err;
785
786 return (bio);
787
788err:
789 BIO_vfree(bio);
790 return (NULL);
791}
792
793int
794BIO_dgram_is_sctp(BIO *bio)
795{
796 return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
797}
798
799static int
800dgram_sctp_new(BIO *bi)
801{
802 bio_dgram_sctp_data *data = NULL;
803
804 bi->init = 0;
805 bi->num = 0;
806 data = calloc(1, sizeof(bio_dgram_sctp_data));
807 if (data == NULL)
808 return 0;
809#ifdef SCTP_PR_SCTP_NONE
810 data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
811#endif
812 bi->ptr = data;
813
814 bi->flags = 0;
815 return (1);
816}
817
818static int
819dgram_sctp_free(BIO *a)
820{
821 bio_dgram_sctp_data *data;
822
823 if (a == NULL)
824 return (0);
825 if (! dgram_clear(a))
826 return 0;
827
828 data = (bio_dgram_sctp_data *)a->ptr;
829 if (data != NULL) {
830 free(data->saved_message.data);
831 free(data);
832 a->ptr = NULL;
833 }
834
835 return (1);
836}
837
838#ifdef SCTP_AUTHENTICATION_EVENT
839void
840dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
841{
842 int ret;
843 struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
844
845 if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) {
846 struct sctp_authkeyid authkeyid;
847
848 /* delete key */
849 authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
850 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
851 &authkeyid, sizeof(struct sctp_authkeyid));
852 }
853}
854#endif
855
856static int
857dgram_sctp_read(BIO *b, char *out, int outl)
858{
859 int ret = 0, n = 0, i, optval;
860 socklen_t optlen;
861 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
862 union sctp_notification *snp;
863 struct msghdr msg;
864 struct iovec iov;
865 struct cmsghdr *cmsg;
866 char cmsgbuf[512];
867
868 if (out != NULL) {
869 errno = 0;
870
871 do {
872 memset(&data->rcvinfo, 0, sizeof(struct bio_dgram_sctp_rcvinfo));
873 iov.iov_base = out;
874 iov.iov_len = outl;
875 msg.msg_name = NULL;
876 msg.msg_namelen = 0;
877 msg.msg_iov = &iov;
878 msg.msg_iovlen = 1;
879 msg.msg_control = cmsgbuf;
880 msg.msg_controllen = 512;
881 msg.msg_flags = 0;
882 n = recvmsg(b->num, &msg, 0);
883
884 if (msg.msg_controllen > 0) {
885 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
886 if (cmsg->cmsg_level != IPPROTO_SCTP)
887 continue;
888#ifdef SCTP_RCVINFO
889 if (cmsg->cmsg_type == SCTP_RCVINFO) {
890 struct sctp_rcvinfo *rcvinfo;
891
892 rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
893 data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
894 data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
895 data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
896 data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
897 data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
898 data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
899 data->rcvinfo.rcv_context = rcvinfo->rcv_context;
900 }
901#endif
902#ifdef SCTP_SNDRCV
903 if (cmsg->cmsg_type == SCTP_SNDRCV) {
904 struct sctp_sndrcvinfo *sndrcvinfo;
905
906 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
907 data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
908 data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
909 data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
910 data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
911 data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
912 data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
913 data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
914 }
915#endif
916 }
917 }
918
919 if (n <= 0) {
920 if (n < 0)
921 ret = n;
922 break;
923 }
924
925 if (msg.msg_flags & MSG_NOTIFICATION) {
926 snp = (union sctp_notification*) out;
927 if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
928#ifdef SCTP_EVENT
929 struct sctp_event event;
930#else
931 struct sctp_event_subscribe event;
932 socklen_t eventsize;
933#endif
934 /* If a message has been delayed until the socket
935 * is dry, it can be sent now.
936 */
937 if (data->saved_message.length > 0) {
938 dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
939 data->saved_message.length);
940 free(data->saved_message.data);
941 data->saved_message.data = NULL;
942 data->saved_message.length = 0;
943 }
944
945 /* disable sender dry event */
946#ifdef SCTP_EVENT
947 memset(&event, 0, sizeof(struct sctp_event));
948 event.se_assoc_id = 0;
949 event.se_type = SCTP_SENDER_DRY_EVENT;
950 event.se_on = 0;
951 i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
952 if (i < 0) {
953 ret = i;
954 break;
955 }
956#else
957 eventsize = sizeof(struct sctp_event_subscribe);
958 i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
959 if (i < 0) {
960 ret = i;
961 break;
962 }
963
964 event.sctp_sender_dry_event = 0;
965
966 i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
967 if (i < 0) {
968 ret = i;
969 break;
970 }
971#endif
972 }
973
974#ifdef SCTP_AUTHENTICATION_EVENT
975 if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
976 dgram_sctp_handle_auth_free_key_event(b, snp);
977#endif
978
979 if (data->handle_notifications != NULL)
980 data->handle_notifications(b, data->notification_context, (void*) out);
981
982 memset(out, 0, outl);
983 } else
984 ret += n;
985 }
986 while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
987
988 if (ret > 0 && !(msg.msg_flags & MSG_EOR)) {
989 /* Partial message read, this should never happen! */
990
991 /* The buffer was too small, this means the peer sent
992 * a message that was larger than allowed. */
993 if (ret == outl)
994 return -1;
995
996 /* Test if socket buffer can handle max record
997 * size (2^14 + 2048 + 13)
998 */
999 optlen = (socklen_t) sizeof(int);
1000 ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
1001 if (ret >= 0)
1002 OPENSSL_assert(optval >= 18445);
1003
1004 /* Test if SCTP doesn't partially deliver below
1005 * max record size (2^14 + 2048 + 13)
1006 */
1007 optlen = (socklen_t) sizeof(int);
1008 ret = getsockopt(b->num, IPPROTO_SCTP,
1009 SCTP_PARTIAL_DELIVERY_POINT, &optval, &optlen);
1010 if (ret >= 0)
1011 OPENSSL_assert(optval >= 18445);
1012
1013 /* Partially delivered notification??? Probably a bug.... */
1014 OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
1015
1016 /* Everything seems ok till now, so it's most likely
1017 * a message dropped by PR-SCTP.
1018 */
1019 memset(out, 0, outl);
1020 BIO_set_retry_read(b);
1021 return -1;
1022 }
1023
1024 BIO_clear_retry_flags(b);
1025 if (ret < 0) {
1026 if (BIO_dgram_should_retry(ret)) {
1027 BIO_set_retry_read(b);
1028 data->_errno = errno;
1029 }
1030 }
1031
1032 /* Test if peer uses SCTP-AUTH before continuing */
1033 if (!data->peer_auth_tested) {
1034 int ii, auth_data = 0, auth_forward = 0;
1035 unsigned char *p;
1036 struct sctp_authchunks *authchunks;
1037
1038 optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
1039 authchunks = calloc(1, optlen);
1040 if (authchunks == NULL) {
1041 BIOerr(BIO_F_DGRAM_SCTP_READ,
1042 ERR_R_MALLOC_ERROR);
1043 return (-1);
1044 }
1045 ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
1046 if (ii >= 0) {
1047 for (p = (unsigned char*) authchunks->gauth_chunks;
1048 p < (unsigned char*) authchunks + optlen;
1049 p += sizeof(uint8_t)) {
1050 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
1051 auth_data = 1;
1052 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
1053 auth_forward = 1;
1054 }
1055 }
1056
1057 free(authchunks);
1058
1059 if (!auth_data || !auth_forward) {
1060 BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR);
1061 return -1;
1062 }
1063
1064 data->peer_auth_tested = 1;
1065 }
1066 }
1067 return (ret);
1068}
1069
1070static int
1071dgram_sctp_write(BIO *b, const char *in, int inl)
1072{
1073 int ret;
1074 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1075 struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
1076 struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
1077 struct bio_dgram_sctp_sndinfo handshake_sinfo;
1078 struct iovec iov[1];
1079 struct msghdr msg;
1080 struct cmsghdr *cmsg;
1081#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1082 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
1083 struct sctp_sndinfo *sndinfo;
1084 struct sctp_prinfo *prinfo;
1085#else
1086 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1087 struct sctp_sndrcvinfo *sndrcvinfo;
1088#endif
1089
1090 errno = 0;
1091
1092 /* If we're send anything else than application data,
1093 * disable all user parameters and flags.
1094 */
1095 if (in[0] != 23) {
1096 memset(&handshake_sinfo, 0, sizeof(struct bio_dgram_sctp_sndinfo));
1097#ifdef SCTP_SACK_IMMEDIATELY
1098 handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
1099#endif
1100 sinfo = &handshake_sinfo;
1101 }
1102
1103 /* If we have to send a shutdown alert message and the
1104 * socket is not dry yet, we have to save it and send it
1105 * as soon as the socket gets dry.
1106 */
1107 if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b)) {
1108 data->saved_message.bio = b;
1109 free(data->saved_message.data);
1110 data->saved_message.data = malloc(inl);
1111 if (data->saved_message.data == NULL) {
1112 data->_errno = ENOMEM;
1113 return -1;
1114 }
1115 memcpy(data->saved_message.data, in, inl);
1116 data->saved_message.length = inl;
1117 return inl;
1118 }
1119
1120 iov[0].iov_base = (char *)in;
1121 iov[0].iov_len = inl;
1122 msg.msg_name = NULL;
1123 msg.msg_namelen = 0;
1124 msg.msg_iov = iov;
1125 msg.msg_iovlen = 1;
1126 msg.msg_control = (caddr_t)cmsgbuf;
1127 msg.msg_controllen = 0;
1128 msg.msg_flags = 0;
1129#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1130 cmsg = (struct cmsghdr *)cmsgbuf;
1131 cmsg->cmsg_level = IPPROTO_SCTP;
1132 cmsg->cmsg_type = SCTP_SNDINFO;
1133 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
1134 sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
1135 memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
1136 sndinfo->snd_sid = sinfo->snd_sid;
1137 sndinfo->snd_flags = sinfo->snd_flags;
1138 sndinfo->snd_ppid = sinfo->snd_ppid;
1139 sndinfo->snd_context = sinfo->snd_context;
1140 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
1141
1142 cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
1143 cmsg->cmsg_level = IPPROTO_SCTP;
1144 cmsg->cmsg_type = SCTP_PRINFO;
1145 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
1146 prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
1147 memset(prinfo, 0, sizeof(struct sctp_prinfo));
1148 prinfo->pr_policy = pinfo->pr_policy;
1149 prinfo->pr_value = pinfo->pr_value;
1150 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
1151#else
1152 cmsg = (struct cmsghdr *)cmsgbuf;
1153 cmsg->cmsg_level = IPPROTO_SCTP;
1154 cmsg->cmsg_type = SCTP_SNDRCV;
1155 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
1156 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1157 memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
1158 sndrcvinfo->sinfo_stream = sinfo->snd_sid;
1159 sndrcvinfo->sinfo_flags = sinfo->snd_flags;
1160 sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
1161 sndrcvinfo->sinfo_context = sinfo->snd_context;
1162 sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
1163 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
1164#endif
1165
1166 ret = sendmsg(b->num, &msg, 0);
1167
1168 BIO_clear_retry_flags(b);
1169 if (ret <= 0) {
1170 if (BIO_dgram_should_retry(ret)) {
1171 BIO_set_retry_write(b);
1172
1173 data->_errno = errno;
1174 }
1175 }
1176 return (ret);
1177}
1178
1179static long
1180dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
1181{
1182 long ret = 1;
1183 bio_dgram_sctp_data *data = NULL;
1184 socklen_t sockopt_len = 0;
1185 struct sctp_authkeyid authkeyid;
1186
1187 data = (bio_dgram_sctp_data *)b->ptr;
1188
1189 switch (cmd) {
1190 case BIO_CTRL_DGRAM_QUERY_MTU:
1191 /* Set to maximum (2^14)
1192 * and ignore user input to enable transport
1193 * protocol fragmentation.
1194 * Returns always 2^14.
1195 */
1196 data->mtu = 16384;
1197 ret = data->mtu;
1198 break;
1199 case BIO_CTRL_DGRAM_SET_MTU:
1200 /* Set to maximum (2^14)
1201 * and ignore input to enable transport
1202 * protocol fragmentation.
1203 * Returns always 2^14.
1204 */
1205 data->mtu = 16384;
1206 ret = data->mtu;
1207 break;
1208 case BIO_CTRL_DGRAM_SET_CONNECTED:
1209 case BIO_CTRL_DGRAM_CONNECT:
1210 /* Returns always -1. */
1211 ret = -1;
1212 break;
1213 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
1214 /* SCTP doesn't need the DTLS timer
1215 * Returns always 1.
1216 */
1217 break;
1218 case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
1219 if (num > 0)
1220 data->in_handshake = 1;
1221 else
1222 data->in_handshake = 0;
1223
1224 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
1225 break;
1226 case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
1227 {
1228 struct sctp_authkey *authkey;
1229
1230 /* New shared key for SCTP AUTH.
1231 * Returns 0 on success, -1 otherwise.
1232 */
1233
1234 /* Get active key */
1235 sockopt_len = sizeof(struct sctp_authkeyid);
1236 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1237 &authkeyid, &sockopt_len);
1238 if (ret < 0)
1239 break;
1240
1241 /* Add new key */
1242 sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
1243 authkey = calloc(1, sockopt_len);
1244 if (authkey == NULL) {
1245 ret = -1;
1246 break;
1247 }
1248 authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
1249 authkey->sca_keylength = 64;
1250 memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
1251
1252 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey,
1253 sockopt_len);
1254 free(authkey);
1255 if (ret < 0)
1256 break;
1257
1258 /* Reset active key */
1259 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1260 &authkeyid, sizeof(struct sctp_authkeyid));
1261 if (ret < 0)
1262 break;
1263 }
1264 break;
1265 case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
1266 /* Returns 0 on success, -1 otherwise. */
1267
1268 /* Get active key */
1269 sockopt_len = sizeof(struct sctp_authkeyid);
1270 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1271 &authkeyid, &sockopt_len);
1272 if (ret < 0)
1273 break;
1274
1275 /* Set active key */
1276 authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
1277 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1278 &authkeyid, sizeof(struct sctp_authkeyid));
1279 if (ret < 0)
1280 break;
1281
1282 /* CCS has been sent, so remember that and fall through
1283 * to check if we need to deactivate an old key
1284 */
1285 data->ccs_sent = 1;
1286
1287 case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
1288 /* Returns 0 on success, -1 otherwise. */
1289
1290 /* Has this command really been called or is this just a fall-through? */
1291 if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
1292 data->ccs_rcvd = 1;
1293
1294 /* CSS has been both, received and sent, so deactivate an old key */
1295 if (data->ccs_rcvd == 1 && data->ccs_sent == 1) {
1296 /* Get active key */
1297 sockopt_len = sizeof(struct sctp_authkeyid);
1298 ret = getsockopt(b->num, IPPROTO_SCTP,
1299 SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1300 if (ret < 0)
1301 break;
1302
1303 /* Deactivate key or delete second last key if
1304 * SCTP_AUTHENTICATION_EVENT is not available.
1305 */
1306 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1307#ifdef SCTP_AUTH_DEACTIVATE_KEY
1308 sockopt_len = sizeof(struct sctp_authkeyid);
1309 ret = setsockopt(b->num, IPPROTO_SCTP,
1310 SCTP_AUTH_DEACTIVATE_KEY, &authkeyid, sockopt_len);
1311 if (ret < 0)
1312 break;
1313#endif
1314#ifndef SCTP_AUTHENTICATION_EVENT
1315 if (authkeyid.scact_keynumber > 0) {
1316 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1317 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
1318 &authkeyid, sizeof(struct sctp_authkeyid));
1319 if (ret < 0)
1320 break;
1321 }
1322#endif
1323
1324 data->ccs_rcvd = 0;
1325 data->ccs_sent = 0;
1326 }
1327 break;
1328 case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
1329 /* Returns the size of the copied struct. */
1330 if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1331 num = sizeof(struct bio_dgram_sctp_sndinfo);
1332
1333 memcpy(ptr, &(data->sndinfo), num);
1334 ret = num;
1335 break;
1336 case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
1337 /* Returns the size of the copied struct. */
1338 if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1339 num = sizeof(struct bio_dgram_sctp_sndinfo);
1340
1341 memcpy(&(data->sndinfo), ptr, num);
1342 break;
1343 case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
1344 /* Returns the size of the copied struct. */
1345 if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1346 num = sizeof(struct bio_dgram_sctp_rcvinfo);
1347
1348 memcpy(ptr, &data->rcvinfo, num);
1349
1350 ret = num;
1351 break;
1352 case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
1353 /* Returns the size of the copied struct. */
1354 if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1355 num = sizeof(struct bio_dgram_sctp_rcvinfo);
1356
1357 memcpy(&(data->rcvinfo), ptr, num);
1358 break;
1359 case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
1360 /* Returns the size of the copied struct. */
1361 if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1362 num = sizeof(struct bio_dgram_sctp_prinfo);
1363
1364 memcpy(ptr, &(data->prinfo), num);
1365 ret = num;
1366 break;
1367 case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
1368 /* Returns the size of the copied struct. */
1369 if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1370 num = sizeof(struct bio_dgram_sctp_prinfo);
1371
1372 memcpy(&(data->prinfo), ptr, num);
1373 break;
1374 case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
1375 /* Returns always 1. */
1376 if (num > 0)
1377 data->save_shutdown = 1;
1378 else
1379 data->save_shutdown = 0;
1380 break;
1381
1382 default:
1383 /* Pass to default ctrl function to
1384 * process SCTP unspecific commands
1385 */
1386 ret = dgram_ctrl(b, cmd, num, ptr);
1387 break;
1388 }
1389 return (ret);
1390}
1391
1392int
1393BIO_dgram_sctp_notification_cb(BIO *b,
1394 void (*handle_notifications)(BIO *bio, void *context, void *buf),
1395 void *context)
1396{
1397 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1398
1399 if (handle_notifications != NULL) {
1400 data->handle_notifications = handle_notifications;
1401 data->notification_context = context;
1402 } else
1403 return -1;
1404
1405 return 0;
1406}
1407
1408int
1409BIO_dgram_sctp_wait_for_dry(BIO *b)
1410{
1411 int is_dry = 0;
1412 int n, sockflags, ret;
1413 union sctp_notification snp;
1414 struct msghdr msg;
1415 struct iovec iov;
1416#ifdef SCTP_EVENT
1417 struct sctp_event event;
1418#else
1419 struct sctp_event_subscribe event;
1420 socklen_t eventsize;
1421#endif
1422 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1423
1424 /* set sender dry event */
1425#ifdef SCTP_EVENT
1426 memset(&event, 0, sizeof(struct sctp_event));
1427 event.se_assoc_id = 0;
1428 event.se_type = SCTP_SENDER_DRY_EVENT;
1429 event.se_on = 1;
1430 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1431#else
1432 eventsize = sizeof(struct sctp_event_subscribe);
1433 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1434 if (ret < 0)
1435 return -1;
1436
1437 event.sctp_sender_dry_event = 1;
1438
1439 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1440#endif
1441 if (ret < 0)
1442 return -1;
1443
1444 /* peek for notification */
1445 memset(&snp, 0, sizeof(union sctp_notification));
1446 iov.iov_base = (char *)&snp;
1447 iov.iov_len = sizeof(union sctp_notification);
1448 msg.msg_name = NULL;
1449 msg.msg_namelen = 0;
1450 msg.msg_iov = &iov;
1451 msg.msg_iovlen = 1;
1452 msg.msg_control = NULL;
1453 msg.msg_controllen = 0;
1454 msg.msg_flags = 0;
1455
1456 n = recvmsg(b->num, &msg, MSG_PEEK);
1457 if (n <= 0) {
1458 if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
1459 return -1;
1460 else
1461 return 0;
1462 }
1463
1464 /* if we find a notification, process it and try again if necessary */
1465 while (msg.msg_flags & MSG_NOTIFICATION) {
1466 memset(&snp, 0, sizeof(union sctp_notification));
1467 iov.iov_base = (char *)&snp;
1468 iov.iov_len = sizeof(union sctp_notification);
1469 msg.msg_name = NULL;
1470 msg.msg_namelen = 0;
1471 msg.msg_iov = &iov;
1472 msg.msg_iovlen = 1;
1473 msg.msg_control = NULL;
1474 msg.msg_controllen = 0;
1475 msg.msg_flags = 0;
1476
1477 n = recvmsg(b->num, &msg, 0);
1478 if (n <= 0) {
1479 if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
1480 return -1;
1481 else
1482 return is_dry;
1483 }
1484
1485 if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
1486 is_dry = 1;
1487
1488 /* disable sender dry event */
1489#ifdef SCTP_EVENT
1490 memset(&event, 0, sizeof(struct sctp_event));
1491 event.se_assoc_id = 0;
1492 event.se_type = SCTP_SENDER_DRY_EVENT;
1493 event.se_on = 0;
1494 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1495#else
1496 eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
1497 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1498 if (ret < 0)
1499 return -1;
1500
1501 event.sctp_sender_dry_event = 0;
1502
1503 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1504#endif
1505 if (ret < 0)
1506 return -1;
1507 }
1508
1509#ifdef SCTP_AUTHENTICATION_EVENT
1510 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1511 dgram_sctp_handle_auth_free_key_event(b, &snp);
1512#endif
1513
1514 if (data->handle_notifications != NULL)
1515 data->handle_notifications(b, data->notification_context, (void*) &snp);
1516
1517 /* found notification, peek again */
1518 memset(&snp, 0, sizeof(union sctp_notification));
1519 iov.iov_base = (char *)&snp;
1520 iov.iov_len = sizeof(union sctp_notification);
1521 msg.msg_name = NULL;
1522 msg.msg_namelen = 0;
1523 msg.msg_iov = &iov;
1524 msg.msg_iovlen = 1;
1525 msg.msg_control = NULL;
1526 msg.msg_controllen = 0;
1527 msg.msg_flags = 0;
1528
1529 /* if we have seen the dry already, don't wait */
1530 if (is_dry) {
1531 sockflags = fcntl(b->num, F_GETFL, 0);
1532 fcntl(b->num, F_SETFL, O_NONBLOCK);
1533 }
1534
1535 n = recvmsg(b->num, &msg, MSG_PEEK);
1536
1537 if (is_dry) {
1538 fcntl(b->num, F_SETFL, sockflags);
1539 }
1540
1541 if (n <= 0) {
1542 if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
1543 return -1;
1544 else
1545 return is_dry;
1546 }
1547 }
1548
1549 /* read anything else */
1550 return is_dry;
1551}
1552
1553int
1554BIO_dgram_sctp_msg_waiting(BIO *b)
1555{
1556 int n, sockflags;
1557 union sctp_notification snp;
1558 struct msghdr msg;
1559 struct iovec iov;
1560 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1561
1562 /* Check if there are any messages waiting to be read */
1563 do
1564 {
1565 memset(&snp, 0, sizeof(union sctp_notification));
1566 iov.iov_base = (char *)&snp;
1567 iov.iov_len = sizeof(union sctp_notification);
1568 msg.msg_name = NULL;
1569 msg.msg_namelen = 0;
1570 msg.msg_iov = &iov;
1571 msg.msg_iovlen = 1;
1572 msg.msg_control = NULL;
1573 msg.msg_controllen = 0;
1574 msg.msg_flags = 0;
1575
1576 sockflags = fcntl(b->num, F_GETFL, 0);
1577 fcntl(b->num, F_SETFL, O_NONBLOCK);
1578 n = recvmsg(b->num, &msg, MSG_PEEK);
1579 fcntl(b->num, F_SETFL, sockflags);
1580
1581 /* if notification, process and try again */
1582 if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) {
1583#ifdef SCTP_AUTHENTICATION_EVENT
1584 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1585 dgram_sctp_handle_auth_free_key_event(b, &snp);
1586#endif
1587
1588 memset(&snp, 0, sizeof(union sctp_notification));
1589 iov.iov_base = (char *)&snp;
1590 iov.iov_len = sizeof(union sctp_notification);
1591 msg.msg_name = NULL;
1592 msg.msg_namelen = 0;
1593 msg.msg_iov = &iov;
1594 msg.msg_iovlen = 1;
1595 msg.msg_control = NULL;
1596 msg.msg_controllen = 0;
1597 msg.msg_flags = 0;
1598 n = recvmsg(b->num, &msg, 0);
1599
1600 if (data->handle_notifications != NULL)
1601 data->handle_notifications(b, data->notification_context, (void*) &snp);
1602 }
1603
1604 } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
1605
1606 /* Return 1 if there is a message to be read, return 0 otherwise. */
1607 if (n > 0)
1608 return 1;
1609 else
1610 return 0;
1611}
1612
1613static int
1614dgram_sctp_puts(BIO *bp, const char *str)
1615{
1616 int n, ret;
1617
1618 n = strlen(str);
1619 ret = dgram_sctp_write(bp, str, n);
1620 return (ret);
1621}
1622#endif
1623 630
1624static int 631static int
1625BIO_dgram_should_retry(int i) 632BIO_dgram_should_retry(int i)
diff --git a/src/lib/libssl/src/crypto/bio/bio.h b/src/lib/libssl/src/crypto/bio/bio.h
index 6868959599..339a5c456b 100644
--- a/src/lib/libssl/src/crypto/bio/bio.h
+++ b/src/lib/libssl/src/crypto/bio/bio.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bio.h,v 1.27 2014/07/20 02:24:21 guenther Exp $ */ 1/* $OpenBSD: bio.h,v 1.28 2015/02/09 10:55:33 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -68,9 +68,6 @@
68 68
69#include <openssl/crypto.h> 69#include <openssl/crypto.h>
70 70
71#ifndef OPENSSL_NO_SCTP
72# include <stdint.h>
73#endif
74 71
75#ifdef __cplusplus 72#ifdef __cplusplus
76extern "C" { 73extern "C" {
@@ -99,9 +96,6 @@ extern "C" {
99#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */ 96#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */
100#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */ 97#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
101#define BIO_TYPE_DGRAM (21|0x0400|0x0100) 98#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
102#ifndef OPENSSL_NO_SCTP
103#define BIO_TYPE_DGRAM_SCTP (24|0x0400|0x0100)
104#endif
105#define BIO_TYPE_ASN1 (22|0x0200) /* filter */ 99#define BIO_TYPE_ASN1 (22|0x0200) /* filter */
106#define BIO_TYPE_COMP (23|0x0200) /* filter */ 100#define BIO_TYPE_COMP (23|0x0200) /* filter */
107 101
@@ -171,20 +165,6 @@ extern "C" {
171#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to 165#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to
172 * adjust socket timeouts */ 166 * adjust socket timeouts */
173 167
174#ifndef OPENSSL_NO_SCTP
175/* SCTP stuff */
176#define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50
177#define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51
178#define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52
179#define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53
180#define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60
181#define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61
182#define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62
183#define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63
184#define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64
185#define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65
186#define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70
187#endif
188 168
189/* modifiers */ 169/* modifiers */
190#define BIO_FP_READ 0x02 170#define BIO_FP_READ 0x02
@@ -347,30 +327,6 @@ typedef struct bio_f_buffer_ctx_struct {
347/* Prefix and suffix callback in ASN1 BIO */ 327/* Prefix and suffix callback in ASN1 BIO */
348typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg); 328typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
349 329
350#ifndef OPENSSL_NO_SCTP
351/* SCTP parameter structs */
352struct bio_dgram_sctp_sndinfo {
353 uint16_t snd_sid;
354 uint16_t snd_flags;
355 uint32_t snd_ppid;
356 uint32_t snd_context;
357};
358
359struct bio_dgram_sctp_rcvinfo {
360 uint16_t rcv_sid;
361 uint16_t rcv_ssn;
362 uint16_t rcv_flags;
363 uint32_t rcv_ppid;
364 uint32_t rcv_tsn;
365 uint32_t rcv_cumtsn;
366 uint32_t rcv_context;
367};
368
369struct bio_dgram_sctp_prinfo {
370 uint16_t pr_policy;
371 uint32_t pr_value;
372};
373#endif
374 330
375/* connect BIO stuff */ 331/* connect BIO stuff */
376#define BIO_CONN_S_BEFORE 1 332#define BIO_CONN_S_BEFORE 1
@@ -664,9 +620,6 @@ BIO_METHOD *BIO_f_buffer(void);
664BIO_METHOD *BIO_f_nbio_test(void); 620BIO_METHOD *BIO_f_nbio_test(void);
665#ifndef OPENSSL_NO_DGRAM 621#ifndef OPENSSL_NO_DGRAM
666BIO_METHOD *BIO_s_datagram(void); 622BIO_METHOD *BIO_s_datagram(void);
667#ifndef OPENSSL_NO_SCTP
668BIO_METHOD *BIO_s_datagram_sctp(void);
669#endif
670#endif 623#endif
671 624
672/* BIO_METHOD *BIO_f_ber(void); */ 625/* BIO_METHOD *BIO_f_ber(void); */
@@ -709,16 +662,6 @@ int BIO_set_tcp_ndelay(int sock, int turn_on);
709 662
710BIO *BIO_new_socket(int sock, int close_flag); 663BIO *BIO_new_socket(int sock, int close_flag);
711BIO *BIO_new_dgram(int fd, int close_flag); 664BIO *BIO_new_dgram(int fd, int close_flag);
712#ifndef OPENSSL_NO_SCTP
713BIO *BIO_new_dgram_sctp(int fd, int close_flag);
714int BIO_dgram_is_sctp(BIO *bio);
715int
716BIO_dgram_sctp_notification_cb(BIO *b,
717 void (*handle_notifications)(BIO *bio, void *context, void *buf),
718void *context);
719int BIO_dgram_sctp_wait_for_dry(BIO *b);
720int BIO_dgram_sctp_msg_waiting(BIO *b);
721#endif
722BIO *BIO_new_fd(int fd, int close_flag); 665BIO *BIO_new_fd(int fd, int close_flag);
723BIO *BIO_new_connect(char *host_port); 666BIO *BIO_new_connect(char *host_port);
724BIO *BIO_new_accept(char *host_port); 667BIO *BIO_new_accept(char *host_port);
diff --git a/src/lib/libssl/src/crypto/bio/bss_dgram.c b/src/lib/libssl/src/crypto/bio/bss_dgram.c
index ecf12fcb33..a07834b62c 100644
--- a/src/lib/libssl/src/crypto/bio/bss_dgram.c
+++ b/src/lib/libssl/src/crypto/bio/bss_dgram.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bss_dgram.c,v 1.39 2015/01/12 02:15:23 doug Exp $ */ 1/* $OpenBSD: bss_dgram.c,v 1.40 2015/02/09 10:55:33 jsing Exp $ */
2/* 2/*
3 * DTLS implementation written by Nagendra Modadugu 3 * DTLS implementation written by Nagendra Modadugu
4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 4 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -74,12 +74,6 @@
74 74
75#ifndef OPENSSL_NO_DGRAM 75#ifndef OPENSSL_NO_DGRAM
76 76
77#ifndef OPENSSL_NO_SCTP
78#include <netinet/sctp.h>
79#include <fcntl.h>
80#define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00
81#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
82#endif
83 77
84static int dgram_write(BIO *h, const char *buf, int num); 78static int dgram_write(BIO *h, const char *buf, int num);
85static int dgram_read(BIO *h, char *buf, int size); 79static int dgram_read(BIO *h, char *buf, int size);
@@ -89,18 +83,6 @@ static int dgram_new(BIO *h);
89static int dgram_free(BIO *data); 83static int dgram_free(BIO *data);
90static int dgram_clear(BIO *bio); 84static int dgram_clear(BIO *bio);
91 85
92#ifndef OPENSSL_NO_SCTP
93static int dgram_sctp_write(BIO *h, const char *buf, int num);
94static int dgram_sctp_read(BIO *h, char *buf, int size);
95static int dgram_sctp_puts(BIO *h, const char *str);
96static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
97static int dgram_sctp_new(BIO *h);
98static int dgram_sctp_free(BIO *data);
99#ifdef SCTP_AUTHENTICATION_EVENT
100static void dgram_sctp_handle_auth_free_key_event(BIO *b,
101 union sctp_notification *snp);
102#endif
103#endif
104 86
105static int BIO_dgram_should_retry(int s); 87static int BIO_dgram_should_retry(int s);
106 88
@@ -115,18 +97,6 @@ static BIO_METHOD methods_dgramp = {
115 .destroy = dgram_free 97 .destroy = dgram_free
116}; 98};
117 99
118#ifndef OPENSSL_NO_SCTP
119static BIO_METHOD methods_dgramp_sctp = {
120 .type = BIO_TYPE_DGRAM_SCTP,
121 .name = "datagram sctp socket",
122 .bwrite = dgram_sctp_write,
123 .bread = dgram_sctp_read,
124 .bputs = dgram_sctp_puts,
125 .ctrl = dgram_sctp_ctrl,
126 .create = dgram_sctp_new,
127 .destroy = dgram_sctp_free
128};
129#endif
130 100
131typedef struct bio_dgram_data_st { 101typedef struct bio_dgram_data_st {
132 union { 102 union {
@@ -141,35 +111,6 @@ typedef struct bio_dgram_data_st {
141 struct timeval socket_timeout; 111 struct timeval socket_timeout;
142} bio_dgram_data; 112} bio_dgram_data;
143 113
144#ifndef OPENSSL_NO_SCTP
145typedef struct bio_dgram_sctp_save_message_st {
146 BIO *bio;
147 char *data;
148 int length;
149} bio_dgram_sctp_save_message;
150
151typedef struct bio_dgram_sctp_data_st {
152 union {
153 struct sockaddr sa;
154 struct sockaddr_in sa_in;
155 struct sockaddr_in6 sa_in6;
156 } peer;
157 unsigned int connected;
158 unsigned int _errno;
159 unsigned int mtu;
160 struct bio_dgram_sctp_sndinfo sndinfo;
161 struct bio_dgram_sctp_rcvinfo rcvinfo;
162 struct bio_dgram_sctp_prinfo prinfo;
163 void (*handle_notifications)(BIO *bio, void *context, void *buf);
164 void* notification_context;
165 int in_handshake;
166 int ccs_rcvd;
167 int ccs_sent;
168 int save_shutdown;
169 int peer_auth_tested;
170 bio_dgram_sctp_save_message saved_message;
171} bio_dgram_sctp_data;
172#endif
173 114
174BIO_METHOD * 115BIO_METHOD *
175BIO_s_datagram(void) 116BIO_s_datagram(void)
@@ -686,940 +627,6 @@ dgram_puts(BIO *bp, const char *str)
686 return (ret); 627 return (ret);
687} 628}
688 629
689#ifndef OPENSSL_NO_SCTP
690BIO_METHOD *
691BIO_s_datagram_sctp(void)
692{
693 return (&methods_dgramp_sctp);
694}
695
696BIO *
697BIO_new_dgram_sctp(int fd, int close_flag)
698{
699 BIO *bio;
700 int ret, optval = 20000;
701 int auth_data = 0, auth_forward = 0;
702 unsigned char *p;
703 struct sctp_authchunk auth;
704 struct sctp_authchunks *authchunks;
705 socklen_t sockopt_len;
706#ifdef SCTP_AUTHENTICATION_EVENT
707#ifdef SCTP_EVENT
708 struct sctp_event event;
709#else
710 struct sctp_event_subscribe event;
711#endif
712#endif
713
714 bio = BIO_new(BIO_s_datagram_sctp());
715 if (bio == NULL)
716 return (NULL);
717 BIO_set_fd(bio, fd, close_flag);
718
719 /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
720 auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
721 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
722 if (ret < 0)
723 goto err;
724 auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
725 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
726 if (ret < 0)
727 goto err;
728
729 /* Test if activation was successful. When using accept(),
730 * SCTP-AUTH has to be activated for the listening socket
731 * already, otherwise the connected socket won't use it. */
732 sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
733 authchunks = calloc(1, sockopt_len);
734 if (authchunks == NULL)
735 goto err;
736 ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
737 if (ret < 0) {
738 free(authchunks);
739 goto err;
740 }
741
742 for (p = (unsigned char*) authchunks->gauth_chunks;
743 p < (unsigned char*) authchunks + sockopt_len;
744 p += sizeof(uint8_t)) {
745 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
746 auth_data = 1;
747 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
748 auth_forward = 1;
749 }
750
751 free(authchunks);
752
753 OPENSSL_assert(auth_data);
754 OPENSSL_assert(auth_forward);
755
756#ifdef SCTP_AUTHENTICATION_EVENT
757#ifdef SCTP_EVENT
758 memset(&event, 0, sizeof(struct sctp_event));
759 event.se_assoc_id = 0;
760 event.se_type = SCTP_AUTHENTICATION_EVENT;
761 event.se_on = 1;
762 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
763 if (ret < 0)
764 goto err;
765#else
766 sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
767 ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
768 if (ret < 0)
769 goto err;
770
771 event.sctp_authentication_event = 1;
772
773 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
774 if (ret < 0)
775 goto err;
776#endif
777#endif
778
779 /* Disable partial delivery by setting the min size
780 * larger than the max record size of 2^14 + 2048 + 13
781 */
782 ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
783 if (ret < 0)
784 goto err;
785
786 return (bio);
787
788err:
789 BIO_vfree(bio);
790 return (NULL);
791}
792
793int
794BIO_dgram_is_sctp(BIO *bio)
795{
796 return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP);
797}
798
799static int
800dgram_sctp_new(BIO *bi)
801{
802 bio_dgram_sctp_data *data = NULL;
803
804 bi->init = 0;
805 bi->num = 0;
806 data = calloc(1, sizeof(bio_dgram_sctp_data));
807 if (data == NULL)
808 return 0;
809#ifdef SCTP_PR_SCTP_NONE
810 data->prinfo.pr_policy = SCTP_PR_SCTP_NONE;
811#endif
812 bi->ptr = data;
813
814 bi->flags = 0;
815 return (1);
816}
817
818static int
819dgram_sctp_free(BIO *a)
820{
821 bio_dgram_sctp_data *data;
822
823 if (a == NULL)
824 return (0);
825 if (! dgram_clear(a))
826 return 0;
827
828 data = (bio_dgram_sctp_data *)a->ptr;
829 if (data != NULL) {
830 free(data->saved_message.data);
831 free(data);
832 a->ptr = NULL;
833 }
834
835 return (1);
836}
837
838#ifdef SCTP_AUTHENTICATION_EVENT
839void
840dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
841{
842 int ret;
843 struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
844
845 if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) {
846 struct sctp_authkeyid authkeyid;
847
848 /* delete key */
849 authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
850 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
851 &authkeyid, sizeof(struct sctp_authkeyid));
852 }
853}
854#endif
855
856static int
857dgram_sctp_read(BIO *b, char *out, int outl)
858{
859 int ret = 0, n = 0, i, optval;
860 socklen_t optlen;
861 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
862 union sctp_notification *snp;
863 struct msghdr msg;
864 struct iovec iov;
865 struct cmsghdr *cmsg;
866 char cmsgbuf[512];
867
868 if (out != NULL) {
869 errno = 0;
870
871 do {
872 memset(&data->rcvinfo, 0, sizeof(struct bio_dgram_sctp_rcvinfo));
873 iov.iov_base = out;
874 iov.iov_len = outl;
875 msg.msg_name = NULL;
876 msg.msg_namelen = 0;
877 msg.msg_iov = &iov;
878 msg.msg_iovlen = 1;
879 msg.msg_control = cmsgbuf;
880 msg.msg_controllen = 512;
881 msg.msg_flags = 0;
882 n = recvmsg(b->num, &msg, 0);
883
884 if (msg.msg_controllen > 0) {
885 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
886 if (cmsg->cmsg_level != IPPROTO_SCTP)
887 continue;
888#ifdef SCTP_RCVINFO
889 if (cmsg->cmsg_type == SCTP_RCVINFO) {
890 struct sctp_rcvinfo *rcvinfo;
891
892 rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
893 data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
894 data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
895 data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
896 data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
897 data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
898 data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
899 data->rcvinfo.rcv_context = rcvinfo->rcv_context;
900 }
901#endif
902#ifdef SCTP_SNDRCV
903 if (cmsg->cmsg_type == SCTP_SNDRCV) {
904 struct sctp_sndrcvinfo *sndrcvinfo;
905
906 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
907 data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
908 data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
909 data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
910 data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
911 data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
912 data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
913 data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
914 }
915#endif
916 }
917 }
918
919 if (n <= 0) {
920 if (n < 0)
921 ret = n;
922 break;
923 }
924
925 if (msg.msg_flags & MSG_NOTIFICATION) {
926 snp = (union sctp_notification*) out;
927 if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
928#ifdef SCTP_EVENT
929 struct sctp_event event;
930#else
931 struct sctp_event_subscribe event;
932 socklen_t eventsize;
933#endif
934 /* If a message has been delayed until the socket
935 * is dry, it can be sent now.
936 */
937 if (data->saved_message.length > 0) {
938 dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
939 data->saved_message.length);
940 free(data->saved_message.data);
941 data->saved_message.data = NULL;
942 data->saved_message.length = 0;
943 }
944
945 /* disable sender dry event */
946#ifdef SCTP_EVENT
947 memset(&event, 0, sizeof(struct sctp_event));
948 event.se_assoc_id = 0;
949 event.se_type = SCTP_SENDER_DRY_EVENT;
950 event.se_on = 0;
951 i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
952 if (i < 0) {
953 ret = i;
954 break;
955 }
956#else
957 eventsize = sizeof(struct sctp_event_subscribe);
958 i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
959 if (i < 0) {
960 ret = i;
961 break;
962 }
963
964 event.sctp_sender_dry_event = 0;
965
966 i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
967 if (i < 0) {
968 ret = i;
969 break;
970 }
971#endif
972 }
973
974#ifdef SCTP_AUTHENTICATION_EVENT
975 if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
976 dgram_sctp_handle_auth_free_key_event(b, snp);
977#endif
978
979 if (data->handle_notifications != NULL)
980 data->handle_notifications(b, data->notification_context, (void*) out);
981
982 memset(out, 0, outl);
983 } else
984 ret += n;
985 }
986 while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));
987
988 if (ret > 0 && !(msg.msg_flags & MSG_EOR)) {
989 /* Partial message read, this should never happen! */
990
991 /* The buffer was too small, this means the peer sent
992 * a message that was larger than allowed. */
993 if (ret == outl)
994 return -1;
995
996 /* Test if socket buffer can handle max record
997 * size (2^14 + 2048 + 13)
998 */
999 optlen = (socklen_t) sizeof(int);
1000 ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
1001 if (ret >= 0)
1002 OPENSSL_assert(optval >= 18445);
1003
1004 /* Test if SCTP doesn't partially deliver below
1005 * max record size (2^14 + 2048 + 13)
1006 */
1007 optlen = (socklen_t) sizeof(int);
1008 ret = getsockopt(b->num, IPPROTO_SCTP,
1009 SCTP_PARTIAL_DELIVERY_POINT, &optval, &optlen);
1010 if (ret >= 0)
1011 OPENSSL_assert(optval >= 18445);
1012
1013 /* Partially delivered notification??? Probably a bug.... */
1014 OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));
1015
1016 /* Everything seems ok till now, so it's most likely
1017 * a message dropped by PR-SCTP.
1018 */
1019 memset(out, 0, outl);
1020 BIO_set_retry_read(b);
1021 return -1;
1022 }
1023
1024 BIO_clear_retry_flags(b);
1025 if (ret < 0) {
1026 if (BIO_dgram_should_retry(ret)) {
1027 BIO_set_retry_read(b);
1028 data->_errno = errno;
1029 }
1030 }
1031
1032 /* Test if peer uses SCTP-AUTH before continuing */
1033 if (!data->peer_auth_tested) {
1034 int ii, auth_data = 0, auth_forward = 0;
1035 unsigned char *p;
1036 struct sctp_authchunks *authchunks;
1037
1038 optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
1039 authchunks = calloc(1, optlen);
1040 if (authchunks == NULL) {
1041 BIOerr(BIO_F_DGRAM_SCTP_READ,
1042 ERR_R_MALLOC_ERROR);
1043 return (-1);
1044 }
1045 ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
1046 if (ii >= 0) {
1047 for (p = (unsigned char*) authchunks->gauth_chunks;
1048 p < (unsigned char*) authchunks + optlen;
1049 p += sizeof(uint8_t)) {
1050 if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
1051 auth_data = 1;
1052 if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
1053 auth_forward = 1;
1054 }
1055 }
1056
1057 free(authchunks);
1058
1059 if (!auth_data || !auth_forward) {
1060 BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR);
1061 return -1;
1062 }
1063
1064 data->peer_auth_tested = 1;
1065 }
1066 }
1067 return (ret);
1068}
1069
1070static int
1071dgram_sctp_write(BIO *b, const char *in, int inl)
1072{
1073 int ret;
1074 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1075 struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
1076 struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
1077 struct bio_dgram_sctp_sndinfo handshake_sinfo;
1078 struct iovec iov[1];
1079 struct msghdr msg;
1080 struct cmsghdr *cmsg;
1081#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1082 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))];
1083 struct sctp_sndinfo *sndinfo;
1084 struct sctp_prinfo *prinfo;
1085#else
1086 char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
1087 struct sctp_sndrcvinfo *sndrcvinfo;
1088#endif
1089
1090 errno = 0;
1091
1092 /* If we're send anything else than application data,
1093 * disable all user parameters and flags.
1094 */
1095 if (in[0] != 23) {
1096 memset(&handshake_sinfo, 0, sizeof(struct bio_dgram_sctp_sndinfo));
1097#ifdef SCTP_SACK_IMMEDIATELY
1098 handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
1099#endif
1100 sinfo = &handshake_sinfo;
1101 }
1102
1103 /* If we have to send a shutdown alert message and the
1104 * socket is not dry yet, we have to save it and send it
1105 * as soon as the socket gets dry.
1106 */
1107 if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b)) {
1108 data->saved_message.bio = b;
1109 free(data->saved_message.data);
1110 data->saved_message.data = malloc(inl);
1111 if (data->saved_message.data == NULL) {
1112 data->_errno = ENOMEM;
1113 return -1;
1114 }
1115 memcpy(data->saved_message.data, in, inl);
1116 data->saved_message.length = inl;
1117 return inl;
1118 }
1119
1120 iov[0].iov_base = (char *)in;
1121 iov[0].iov_len = inl;
1122 msg.msg_name = NULL;
1123 msg.msg_namelen = 0;
1124 msg.msg_iov = iov;
1125 msg.msg_iovlen = 1;
1126 msg.msg_control = (caddr_t)cmsgbuf;
1127 msg.msg_controllen = 0;
1128 msg.msg_flags = 0;
1129#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
1130 cmsg = (struct cmsghdr *)cmsgbuf;
1131 cmsg->cmsg_level = IPPROTO_SCTP;
1132 cmsg->cmsg_type = SCTP_SNDINFO;
1133 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
1134 sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
1135 memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
1136 sndinfo->snd_sid = sinfo->snd_sid;
1137 sndinfo->snd_flags = sinfo->snd_flags;
1138 sndinfo->snd_ppid = sinfo->snd_ppid;
1139 sndinfo->snd_context = sinfo->snd_context;
1140 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
1141
1142 cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
1143 cmsg->cmsg_level = IPPROTO_SCTP;
1144 cmsg->cmsg_type = SCTP_PRINFO;
1145 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
1146 prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
1147 memset(prinfo, 0, sizeof(struct sctp_prinfo));
1148 prinfo->pr_policy = pinfo->pr_policy;
1149 prinfo->pr_value = pinfo->pr_value;
1150 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
1151#else
1152 cmsg = (struct cmsghdr *)cmsgbuf;
1153 cmsg->cmsg_level = IPPROTO_SCTP;
1154 cmsg->cmsg_type = SCTP_SNDRCV;
1155 cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
1156 sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
1157 memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
1158 sndrcvinfo->sinfo_stream = sinfo->snd_sid;
1159 sndrcvinfo->sinfo_flags = sinfo->snd_flags;
1160 sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
1161 sndrcvinfo->sinfo_context = sinfo->snd_context;
1162 sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
1163 msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
1164#endif
1165
1166 ret = sendmsg(b->num, &msg, 0);
1167
1168 BIO_clear_retry_flags(b);
1169 if (ret <= 0) {
1170 if (BIO_dgram_should_retry(ret)) {
1171 BIO_set_retry_write(b);
1172
1173 data->_errno = errno;
1174 }
1175 }
1176 return (ret);
1177}
1178
1179static long
1180dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
1181{
1182 long ret = 1;
1183 bio_dgram_sctp_data *data = NULL;
1184 socklen_t sockopt_len = 0;
1185 struct sctp_authkeyid authkeyid;
1186
1187 data = (bio_dgram_sctp_data *)b->ptr;
1188
1189 switch (cmd) {
1190 case BIO_CTRL_DGRAM_QUERY_MTU:
1191 /* Set to maximum (2^14)
1192 * and ignore user input to enable transport
1193 * protocol fragmentation.
1194 * Returns always 2^14.
1195 */
1196 data->mtu = 16384;
1197 ret = data->mtu;
1198 break;
1199 case BIO_CTRL_DGRAM_SET_MTU:
1200 /* Set to maximum (2^14)
1201 * and ignore input to enable transport
1202 * protocol fragmentation.
1203 * Returns always 2^14.
1204 */
1205 data->mtu = 16384;
1206 ret = data->mtu;
1207 break;
1208 case BIO_CTRL_DGRAM_SET_CONNECTED:
1209 case BIO_CTRL_DGRAM_CONNECT:
1210 /* Returns always -1. */
1211 ret = -1;
1212 break;
1213 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
1214 /* SCTP doesn't need the DTLS timer
1215 * Returns always 1.
1216 */
1217 break;
1218 case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
1219 if (num > 0)
1220 data->in_handshake = 1;
1221 else
1222 data->in_handshake = 0;
1223
1224 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int));
1225 break;
1226 case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
1227 {
1228 struct sctp_authkey *authkey;
1229
1230 /* New shared key for SCTP AUTH.
1231 * Returns 0 on success, -1 otherwise.
1232 */
1233
1234 /* Get active key */
1235 sockopt_len = sizeof(struct sctp_authkeyid);
1236 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1237 &authkeyid, &sockopt_len);
1238 if (ret < 0)
1239 break;
1240
1241 /* Add new key */
1242 sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t);
1243 authkey = calloc(1, sockopt_len);
1244 if (authkey == NULL) {
1245 ret = -1;
1246 break;
1247 }
1248 authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
1249 authkey->sca_keylength = 64;
1250 memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
1251
1252 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey,
1253 sockopt_len);
1254 free(authkey);
1255 if (ret < 0)
1256 break;
1257
1258 /* Reset active key */
1259 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1260 &authkeyid, sizeof(struct sctp_authkeyid));
1261 if (ret < 0)
1262 break;
1263 }
1264 break;
1265 case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
1266 /* Returns 0 on success, -1 otherwise. */
1267
1268 /* Get active key */
1269 sockopt_len = sizeof(struct sctp_authkeyid);
1270 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1271 &authkeyid, &sockopt_len);
1272 if (ret < 0)
1273 break;
1274
1275 /* Set active key */
1276 authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
1277 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
1278 &authkeyid, sizeof(struct sctp_authkeyid));
1279 if (ret < 0)
1280 break;
1281
1282 /* CCS has been sent, so remember that and fall through
1283 * to check if we need to deactivate an old key
1284 */
1285 data->ccs_sent = 1;
1286
1287 case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
1288 /* Returns 0 on success, -1 otherwise. */
1289
1290 /* Has this command really been called or is this just a fall-through? */
1291 if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
1292 data->ccs_rcvd = 1;
1293
1294 /* CSS has been both, received and sent, so deactivate an old key */
1295 if (data->ccs_rcvd == 1 && data->ccs_sent == 1) {
1296 /* Get active key */
1297 sockopt_len = sizeof(struct sctp_authkeyid);
1298 ret = getsockopt(b->num, IPPROTO_SCTP,
1299 SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
1300 if (ret < 0)
1301 break;
1302
1303 /* Deactivate key or delete second last key if
1304 * SCTP_AUTHENTICATION_EVENT is not available.
1305 */
1306 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1307#ifdef SCTP_AUTH_DEACTIVATE_KEY
1308 sockopt_len = sizeof(struct sctp_authkeyid);
1309 ret = setsockopt(b->num, IPPROTO_SCTP,
1310 SCTP_AUTH_DEACTIVATE_KEY, &authkeyid, sockopt_len);
1311 if (ret < 0)
1312 break;
1313#endif
1314#ifndef SCTP_AUTHENTICATION_EVENT
1315 if (authkeyid.scact_keynumber > 0) {
1316 authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
1317 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
1318 &authkeyid, sizeof(struct sctp_authkeyid));
1319 if (ret < 0)
1320 break;
1321 }
1322#endif
1323
1324 data->ccs_rcvd = 0;
1325 data->ccs_sent = 0;
1326 }
1327 break;
1328 case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
1329 /* Returns the size of the copied struct. */
1330 if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1331 num = sizeof(struct bio_dgram_sctp_sndinfo);
1332
1333 memcpy(ptr, &(data->sndinfo), num);
1334 ret = num;
1335 break;
1336 case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
1337 /* Returns the size of the copied struct. */
1338 if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
1339 num = sizeof(struct bio_dgram_sctp_sndinfo);
1340
1341 memcpy(&(data->sndinfo), ptr, num);
1342 break;
1343 case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
1344 /* Returns the size of the copied struct. */
1345 if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1346 num = sizeof(struct bio_dgram_sctp_rcvinfo);
1347
1348 memcpy(ptr, &data->rcvinfo, num);
1349
1350 ret = num;
1351 break;
1352 case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
1353 /* Returns the size of the copied struct. */
1354 if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
1355 num = sizeof(struct bio_dgram_sctp_rcvinfo);
1356
1357 memcpy(&(data->rcvinfo), ptr, num);
1358 break;
1359 case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
1360 /* Returns the size of the copied struct. */
1361 if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1362 num = sizeof(struct bio_dgram_sctp_prinfo);
1363
1364 memcpy(ptr, &(data->prinfo), num);
1365 ret = num;
1366 break;
1367 case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
1368 /* Returns the size of the copied struct. */
1369 if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
1370 num = sizeof(struct bio_dgram_sctp_prinfo);
1371
1372 memcpy(&(data->prinfo), ptr, num);
1373 break;
1374 case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
1375 /* Returns always 1. */
1376 if (num > 0)
1377 data->save_shutdown = 1;
1378 else
1379 data->save_shutdown = 0;
1380 break;
1381
1382 default:
1383 /* Pass to default ctrl function to
1384 * process SCTP unspecific commands
1385 */
1386 ret = dgram_ctrl(b, cmd, num, ptr);
1387 break;
1388 }
1389 return (ret);
1390}
1391
1392int
1393BIO_dgram_sctp_notification_cb(BIO *b,
1394 void (*handle_notifications)(BIO *bio, void *context, void *buf),
1395 void *context)
1396{
1397 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
1398
1399 if (handle_notifications != NULL) {
1400 data->handle_notifications = handle_notifications;
1401 data->notification_context = context;
1402 } else
1403 return -1;
1404
1405 return 0;
1406}
1407
1408int
1409BIO_dgram_sctp_wait_for_dry(BIO *b)
1410{
1411 int is_dry = 0;
1412 int n, sockflags, ret;
1413 union sctp_notification snp;
1414 struct msghdr msg;
1415 struct iovec iov;
1416#ifdef SCTP_EVENT
1417 struct sctp_event event;
1418#else
1419 struct sctp_event_subscribe event;
1420 socklen_t eventsize;
1421#endif
1422 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1423
1424 /* set sender dry event */
1425#ifdef SCTP_EVENT
1426 memset(&event, 0, sizeof(struct sctp_event));
1427 event.se_assoc_id = 0;
1428 event.se_type = SCTP_SENDER_DRY_EVENT;
1429 event.se_on = 1;
1430 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1431#else
1432 eventsize = sizeof(struct sctp_event_subscribe);
1433 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1434 if (ret < 0)
1435 return -1;
1436
1437 event.sctp_sender_dry_event = 1;
1438
1439 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1440#endif
1441 if (ret < 0)
1442 return -1;
1443
1444 /* peek for notification */
1445 memset(&snp, 0, sizeof(union sctp_notification));
1446 iov.iov_base = (char *)&snp;
1447 iov.iov_len = sizeof(union sctp_notification);
1448 msg.msg_name = NULL;
1449 msg.msg_namelen = 0;
1450 msg.msg_iov = &iov;
1451 msg.msg_iovlen = 1;
1452 msg.msg_control = NULL;
1453 msg.msg_controllen = 0;
1454 msg.msg_flags = 0;
1455
1456 n = recvmsg(b->num, &msg, MSG_PEEK);
1457 if (n <= 0) {
1458 if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
1459 return -1;
1460 else
1461 return 0;
1462 }
1463
1464 /* if we find a notification, process it and try again if necessary */
1465 while (msg.msg_flags & MSG_NOTIFICATION) {
1466 memset(&snp, 0, sizeof(union sctp_notification));
1467 iov.iov_base = (char *)&snp;
1468 iov.iov_len = sizeof(union sctp_notification);
1469 msg.msg_name = NULL;
1470 msg.msg_namelen = 0;
1471 msg.msg_iov = &iov;
1472 msg.msg_iovlen = 1;
1473 msg.msg_control = NULL;
1474 msg.msg_controllen = 0;
1475 msg.msg_flags = 0;
1476
1477 n = recvmsg(b->num, &msg, 0);
1478 if (n <= 0) {
1479 if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
1480 return -1;
1481 else
1482 return is_dry;
1483 }
1484
1485 if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
1486 is_dry = 1;
1487
1488 /* disable sender dry event */
1489#ifdef SCTP_EVENT
1490 memset(&event, 0, sizeof(struct sctp_event));
1491 event.se_assoc_id = 0;
1492 event.se_type = SCTP_SENDER_DRY_EVENT;
1493 event.se_on = 0;
1494 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
1495#else
1496 eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
1497 ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
1498 if (ret < 0)
1499 return -1;
1500
1501 event.sctp_sender_dry_event = 0;
1502
1503 ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
1504#endif
1505 if (ret < 0)
1506 return -1;
1507 }
1508
1509#ifdef SCTP_AUTHENTICATION_EVENT
1510 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1511 dgram_sctp_handle_auth_free_key_event(b, &snp);
1512#endif
1513
1514 if (data->handle_notifications != NULL)
1515 data->handle_notifications(b, data->notification_context, (void*) &snp);
1516
1517 /* found notification, peek again */
1518 memset(&snp, 0, sizeof(union sctp_notification));
1519 iov.iov_base = (char *)&snp;
1520 iov.iov_len = sizeof(union sctp_notification);
1521 msg.msg_name = NULL;
1522 msg.msg_namelen = 0;
1523 msg.msg_iov = &iov;
1524 msg.msg_iovlen = 1;
1525 msg.msg_control = NULL;
1526 msg.msg_controllen = 0;
1527 msg.msg_flags = 0;
1528
1529 /* if we have seen the dry already, don't wait */
1530 if (is_dry) {
1531 sockflags = fcntl(b->num, F_GETFL, 0);
1532 fcntl(b->num, F_SETFL, O_NONBLOCK);
1533 }
1534
1535 n = recvmsg(b->num, &msg, MSG_PEEK);
1536
1537 if (is_dry) {
1538 fcntl(b->num, F_SETFL, sockflags);
1539 }
1540
1541 if (n <= 0) {
1542 if ((n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
1543 return -1;
1544 else
1545 return is_dry;
1546 }
1547 }
1548
1549 /* read anything else */
1550 return is_dry;
1551}
1552
1553int
1554BIO_dgram_sctp_msg_waiting(BIO *b)
1555{
1556 int n, sockflags;
1557 union sctp_notification snp;
1558 struct msghdr msg;
1559 struct iovec iov;
1560 bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
1561
1562 /* Check if there are any messages waiting to be read */
1563 do
1564 {
1565 memset(&snp, 0, sizeof(union sctp_notification));
1566 iov.iov_base = (char *)&snp;
1567 iov.iov_len = sizeof(union sctp_notification);
1568 msg.msg_name = NULL;
1569 msg.msg_namelen = 0;
1570 msg.msg_iov = &iov;
1571 msg.msg_iovlen = 1;
1572 msg.msg_control = NULL;
1573 msg.msg_controllen = 0;
1574 msg.msg_flags = 0;
1575
1576 sockflags = fcntl(b->num, F_GETFL, 0);
1577 fcntl(b->num, F_SETFL, O_NONBLOCK);
1578 n = recvmsg(b->num, &msg, MSG_PEEK);
1579 fcntl(b->num, F_SETFL, sockflags);
1580
1581 /* if notification, process and try again */
1582 if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) {
1583#ifdef SCTP_AUTHENTICATION_EVENT
1584 if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
1585 dgram_sctp_handle_auth_free_key_event(b, &snp);
1586#endif
1587
1588 memset(&snp, 0, sizeof(union sctp_notification));
1589 iov.iov_base = (char *)&snp;
1590 iov.iov_len = sizeof(union sctp_notification);
1591 msg.msg_name = NULL;
1592 msg.msg_namelen = 0;
1593 msg.msg_iov = &iov;
1594 msg.msg_iovlen = 1;
1595 msg.msg_control = NULL;
1596 msg.msg_controllen = 0;
1597 msg.msg_flags = 0;
1598 n = recvmsg(b->num, &msg, 0);
1599
1600 if (data->handle_notifications != NULL)
1601 data->handle_notifications(b, data->notification_context, (void*) &snp);
1602 }
1603
1604 } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION));
1605
1606 /* Return 1 if there is a message to be read, return 0 otherwise. */
1607 if (n > 0)
1608 return 1;
1609 else
1610 return 0;
1611}
1612
1613static int
1614dgram_sctp_puts(BIO *bp, const char *str)
1615{
1616 int n, ret;
1617
1618 n = strlen(str);
1619 ret = dgram_sctp_write(bp, str, n);
1620 return (ret);
1621}
1622#endif
1623 630
1624static int 631static int
1625BIO_dgram_should_retry(int i) 632BIO_dgram_should_retry(int i)