1/* crypto/bio/bss_rtcp.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59/*- 60 * Written by David L. Jones <jonesd@kcgl1.eng.ohio-state.edu> 61 * Date: 22-JUL-1996 62 * Revised: 25-SEP-1997 Update for 0.8.1, BIO_CTRL_SET -> BIO_C_SET_FD 63 */ 64/* VMS */ 65#include <stdio.h> 66#include <stdlib.h> 67#include <string.h> 68#include <errno.h> 69#include "cryptlib.h" 70#include <openssl/bio.h> 71 72#include <iodef.h> /* VMS IO$_ definitions */ 73#include <starlet.h> 74 75typedef unsigned short io_channel; 76/*************************************************************************/ 77struct io_status { 78 short status, count; 79 long flags; 80}; 81 82/* Should have member alignment inhibited */ 83struct rpc_msg { 84 /* 'A'-app data. 'R'-remote client 'G'-global */ 85 char channel; 86 /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ 87 char function; 88 /* Amount of data returned or max to return */ 89 unsigned short int length; 90 /* variable data */ 91 char data[4092]; 92}; 93#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) 94 95struct rpc_ctx { 96 int filled, pos; 97 struct rpc_msg msg; 98}; 99 100static int rtcp_write(BIO *h, const char *buf, int num); 101static int rtcp_read(BIO *h, char *buf, int size); 102static int rtcp_puts(BIO *h, const char *str); 103static int rtcp_gets(BIO *h, char *str, int size); 104static long rtcp_ctrl(BIO *h, int cmd, long arg1, void *arg2); 105static int rtcp_new(BIO *h); 106static int rtcp_free(BIO *data); 107 108static BIO_METHOD rtcp_method = { 109 BIO_TYPE_FD, 110 "RTCP", 111 rtcp_write, 112 rtcp_read, 113 rtcp_puts, 114 rtcp_gets, 115 rtcp_ctrl, 116 rtcp_new, 117 rtcp_free, 118 NULL, 119}; 120 121BIO_METHOD *BIO_s_rtcp(void) 122{ 123 return (&rtcp_method); 124} 125 126/*****************************************************************************/ 127/* 128 * Decnet I/O routines. 129 */ 130 131#ifdef __DECC 132# pragma message save 133# pragma message disable DOLLARID 134#endif 135 136static int get(io_channel chan, char *buffer, int maxlen, int *length) 137{ 138 int status; 139 struct io_status iosb; 140 status = sys$qiow(0, chan, IO$_READVBLK, &iosb, 0, 0, 141 buffer, maxlen, 0, 0, 0, 0); 142 if ((status & 1) == 1) 143 status = iosb.status; 144 if ((status & 1) == 1) 145 *length = iosb.count; 146 return status; 147} 148 149static int put(io_channel chan, char *buffer, int length) 150{ 151 int status; 152 struct io_status iosb; 153 status = sys$qiow(0, chan, IO$_WRITEVBLK, &iosb, 0, 0, 154 buffer, length, 0, 0, 0, 0); 155 if ((status & 1) == 1) 156 status = iosb.status; 157 return status; 158} 159 160#ifdef __DECC 161# pragma message restore 162#endif 163 164/***************************************************************************/ 165 166static int rtcp_new(BIO *bi) 167{ 168 struct rpc_ctx *ctx; 169 bi->init = 1; 170 bi->num = 0; 171 bi->flags = 0; 172 bi->ptr = OPENSSL_malloc(sizeof(struct rpc_ctx)); 173 ctx = (struct rpc_ctx *)bi->ptr; 174 ctx->filled = 0; 175 ctx->pos = 0; 176 return (1); 177} 178 179static int rtcp_free(BIO *a) 180{ 181 if (a == NULL) 182 return (0); 183 if (a->ptr) 184 OPENSSL_free(a->ptr); 185 a->ptr = NULL; 186 return (1); 187} 188 189static int rtcp_read(BIO *b, char *out, int outl) 190{ 191 int status, length; 192 struct rpc_ctx *ctx; 193 /* 194 * read data, return existing. 195 */ 196 ctx = (struct rpc_ctx *)b->ptr; 197 if (ctx->pos < ctx->filled) { 198 length = ctx->filled - ctx->pos; 199 if (length > outl) 200 length = outl; 201 memmove(out, &ctx->msg.data[ctx->pos], length); 202 ctx->pos += length; 203 return length; 204 } 205 /* 206 * Requst more data from R channel. 207 */ 208 ctx->msg.channel = 'R'; 209 ctx->msg.function = 'G'; 210 ctx->msg.length = sizeof(ctx->msg.data); 211 status = put(b->num, (char *)&ctx->msg, RPC_HDR_SIZE); 212 if ((status & 1) == 0) { 213 return -1; 214 } 215 /* 216 * Read. 217 */ 218 ctx->pos = ctx->filled = 0; 219 status = get(b->num, (char *)&ctx->msg, sizeof(ctx->msg), &length); 220 if ((status & 1) == 0) 221 length = -1; 222 if (ctx->msg.channel != 'R' || ctx->msg.function != 'C') { 223 length = -1; 224 } 225 ctx->filled = length - RPC_HDR_SIZE; 226 227 if (ctx->pos < ctx->filled) { 228 length = ctx->filled - ctx->pos; 229 if (length > outl) 230 length = outl; 231 memmove(out, ctx->msg.data, length); 232 ctx->pos += length; 233 return length; 234 } 235 236 return length; 237} 238 239static int rtcp_write(BIO *b, const char *in, int inl) 240{ 241 int status, i, segment, length; 242 struct rpc_ctx *ctx; 243 /* 244 * Output data, send in chunks no larger that sizeof(ctx->msg.data). 245 */ 246 ctx = (struct rpc_ctx *)b->ptr; 247 for (i = 0; i < inl; i += segment) { 248 segment = inl - i; 249 if (segment > sizeof(ctx->msg.data)) 250 segment = sizeof(ctx->msg.data); 251 ctx->msg.channel = 'R'; 252 ctx->msg.function = 'P'; 253 ctx->msg.length = segment; 254 memmove(ctx->msg.data, &in[i], segment); 255 status = put(b->num, (char *)&ctx->msg, segment + RPC_HDR_SIZE); 256 if ((status & 1) == 0) { 257 i = -1; 258 break; 259 } 260 261 status = get(b->num, (char *)&ctx->msg, sizeof(ctx->msg), &length); 262 if (((status & 1) == 0) || (length < RPC_HDR_SIZE)) { 263 i = -1; 264 break; 265 } 266 if ((ctx->msg.channel != 'R') || (ctx->msg.function != 'C')) { 267 printf("unexpected response when confirming put %c %c\n", 268 ctx->msg.channel, ctx->msg.function); 269 270 } 271 } 272 return (i); 273} 274 275static long rtcp_ctrl(BIO *b, int cmd, long num, void *ptr) 276{ 277 long ret = 1; 278 279 switch (cmd) { 280 case BIO_CTRL_RESET: 281 case BIO_CTRL_EOF: 282 ret = 1; 283 break; 284 case BIO_C_SET_FD: 285 b->num = num; 286 ret = 1; 287 break; 288 case BIO_CTRL_SET_CLOSE: 289 case BIO_CTRL_FLUSH: 290 case BIO_CTRL_DUP: 291 ret = 1; 292 break; 293 case BIO_CTRL_GET_CLOSE: 294 case BIO_CTRL_INFO: 295 case BIO_CTRL_GET: 296 case BIO_CTRL_PENDING: 297 case BIO_CTRL_WPENDING: 298 default: 299 ret = 0; 300 break; 301 } 302 return (ret); 303} 304 305static int rtcp_gets(BIO *bp, char *buf, int size) 306{ 307 return (0); 308} 309 310static int rtcp_puts(BIO *bp, const char *str) 311{ 312 int length; 313 if (str == NULL) 314 return (0); 315 length = strlen(str); 316 if (length == 0) 317 return (0); 318 return rtcp_write(bp, str, length); 319} 320