static int dgram_write(BIO *b, const char *in, int inl) { int ret; bio_dgram_data *data = (bio_dgram_data *)b->ptr; clear_socket_error(); if ( data->connected ) ret=writesocket(b->num,in,inl); else #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer)); #else ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer)); #endif BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) { BIO_set_retry_write(b); data->_errno = get_last_socket_error(); #if 0 /* higher layers are responsible for querying MTU, if necessary */ if ( data->_errno == EMSGSIZE) /* retrieve the new MTU */ BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); #endif } } return(ret); }
static int fd_read(BIO *b, char *out,int outl) #endif { int ret=0; if (out != NULL) { #ifndef BIO_FD clear_socket_error(); ret=readsocket(b->num,out,outl); #else clear_sys_error(); ret=read(b->num,out,outl); #endif BIO_clear_retry_flags(b); if (ret <= 0) { #ifndef BIO_FD if (BIO_sock_should_retry(ret)) #else if (BIO_fd_should_retry(ret)) #endif BIO_set_retry_read(b); } } return(ret); }
static int conn_read(BIO *b, char *out, int outl) { int ret=0; BIO_CONNECT *data; data=(BIO_CONNECT *)b->ptr; if (data->state != BIO_CONN_S_OK) { ret=conn_state(b,data); if (ret <= 0) return(ret); } if (out != NULL) { clear_socket_error(); ret=readsocket(b->num,out,outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) BIO_set_retry_read(b); } } return(ret); }
static int dgram_read(BIO *b, char *out, int outl) { int ret=0; bio_dgram_data *data = (bio_dgram_data *)b->ptr; struct sockaddr peer; int peerlen = sizeof(peer); if (out != NULL) { clear_socket_error(); memset(&peer, 0x00, peerlen); /* Last arg in recvfrom is signed on some platforms and * unsigned on others. It is of type socklen_t on some * but this is not universal. Cast to (void *) to avoid * compiler warnings. */ ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen); if ( ! data->connected && ret > 0) BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_dgram_should_retry(ret)) { BIO_set_retry_read(b); data->_errno = get_last_socket_error(); } } } return(ret); }
ssize_t _gst_send (int fd, PTR buffer, size_t size, int flags) { #ifdef HAVE_SOCKETS ssize_t result; int save_errno = errno; for (;;) { result = send (FD_TO_SOCKET (fd), buffer, size, flags); if (is_socket_error (EFAULT)) abort (); if (is_socket_error (EINTR)) clear_socket_error (); else break; } if (errno == EINTR) errno = save_errno; return result; #else errno = ENOSYS; return -1; #endif }
static int dgram_read(BIO *b, char *out, int outl) { int ret=0; bio_dgram_data *data = (bio_dgram_data *)b->ptr; struct { /* * See commentary in b_sock.c. <appro> */ union { size_t s; int i; } len; union { struct TINYCLR_SSL_SOCKADDR sa; struct TINYCLR_SSL_SOCKADDR_IN sa_in; #if OPENSSL_USE_IPV6 struct sockaddr_in6 sa_in6; #endif } peer; } sa; sa.len.s=0; sa.len.i=sizeof(sa.peer); if (out != NULL) { clear_socket_error(); TINYCLR_SSL_MEMSET(&sa.peer, 0x00, sizeof(sa.peer)); dgram_adjust_rcv_timeout(b); #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_ARM) || defined(OPENSSL_SYS_SH) ret=TINYCLR_SSL_RECVFROM(b->num,out,outl,0,&sa.peer.sa,(int *)&sa.len); #else ret=TINYCLR_SSL_RECVFROM(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len); #endif if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) { OPENSSL_assert(sa.len.s<=sizeof(sa.peer)); sa.len.i = (int)sa.len.s; } dgram_reset_rcv_timeout(b); if ( ! data->connected && ret >= 0) BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer); BIO_clear_retry_flags(b); if (ret < 0) { if (BIO_dgram_should_retry(ret)) { BIO_set_retry_read(b); data->_errno = get_last_socket_error(); } } } return(ret); }
static int sock_write(BIO *b, const char *in, int inl) { int ret; clear_socket_error(); ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) BIO_set_retry_write(b); } return (ret); }
static int dgram_read(BIO *b, char *out, int outl) { int ret=0; bio_dgram_data *data = (bio_dgram_data *)b->ptr; struct { /* * See commentary in b_sock.c. <appro> */ union { size_t s; int i; } len; union { struct sockaddr sa; struct sockaddr_in sa_in; #if OPENSSL_USE_IPV6 struct sockaddr_in6 sa_in6; #endif } peer; } sa; sa.len.s=0; sa.len.i=sizeof(sa.peer); if (out != NULL) { clear_socket_error(); memset(&sa.peer, 0x00, sizeof(sa.peer)); dgram_adjust_rcv_timeout(b); ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len); if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) { OPENSSL_assert(sa.len.s<=sizeof(sa.peer)); sa.len.i = (int)sa.len.s; } if ( ! data->connected && ret >= 0) BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer); BIO_clear_retry_flags(b); if (ret < 0) { if (BIO_dgram_should_retry(ret)) { BIO_set_retry_read(b); data->_errno = get_last_socket_error(); } } dgram_reset_rcv_timeout(b); } return(ret); }
static int sock_read(BIO *b, char *out, int outl) { int ret = 0; if (out != NULL) { clear_socket_error(); ret = readsocket(b->num, out, outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) BIO_set_retry_read(b); } } return (ret); }
static int dgram_write(BIO *b, const char *in, int inl) { int ret; bio_dgram_data *data = (bio_dgram_data *)b->ptr; clear_socket_error(); if ( data->connected ) ret=writesocket(b->num,in,inl); else { int peerlen = sizeof(data->peer); if (data->peer.sa.sa_family == AF_INET) peerlen = sizeof(data->peer.sa_in); #if OPENSSL_USE_IVP6 else if (data->peer.sa.sa_family == AF_INET6) peerlen = sizeof(data->peer.sa_in6); #endif #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) ret=TINYCLR_SSL_SENDTO(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen); #else ret=TINYCLR_SSL_SENDTO(b->num, in, inl, 0, &data->peer.sa, peerlen); #endif } BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_dgram_should_retry(ret)) { BIO_set_retry_write(b); data->_errno = get_last_socket_error(); #if 0 /* higher layers are responsible for querying MTU, if necessary */ if ( data->_errno == EMSGSIZE) /* retrieve the new MTU */ BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); #endif } } return(ret); }
static int conn_write(BIO *b, const char *in, int inl) { int ret; BIO_CONNECT *data; data=(BIO_CONNECT *)b->ptr; if (data->state != BIO_CONN_S_OK) { ret=conn_state(b,data); if (ret <= 0) return(ret); } clear_socket_error(); ret=writesocket(b->num,in,inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) BIO_set_retry_write(b); } return(ret); }
static int fd_write(BIO *b, const char *in, int inl) #endif { int ret; #ifndef BIO_FD clear_socket_error(); ret=writesocket(b->num,in,inl); #else clear_sys_error(); ret=write(b->num,in,inl); #endif BIO_clear_retry_flags(b); if (ret <= 0) { #ifndef BIO_FD if (BIO_sock_should_retry(ret)) #else if (BIO_fd_should_retry(ret)) #endif BIO_set_retry_write(b); } return(ret); }
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) { clear_socket_error(); do { memset(&data->rcvinfo, 0x00, 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); OPENSSL_free(data->saved_message.data); 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)); OPENSSL_assert(i >= 0); #else eventsize = sizeof(struct sctp_event_subscribe); i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize); OPENSSL_assert(i >= 0); event.sctp_sender_dry_event = 0; i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)); OPENSSL_assert(i >= 0); #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); OPENSSL_assert(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); OPENSSL_assert(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 = get_last_socket_error(); } } /* 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 = OPENSSL_malloc(optlen); memset(authchunks, 0, sizeof(optlen)); ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen); OPENSSL_assert(ii >= 0); for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t); 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; } OPENSSL_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 clear_socket_error(); /* If we're send anything else than application data, * disable all user parameters and flags. */ if (in[0] != 23) { memset(&handshake_sinfo, 0x00, 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; data->saved_message.length = inl; data->saved_message.data = OPENSSL_malloc(inl); memcpy(data->saved_message.data, in, 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; #ifdef __FreeBSD__ sndrcvinfo->sinfo_flags |= pinfo->pr_policy; #endif 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 = get_last_socket_error(); } } return(ret); }