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/* Written by David L. Jones <jonesd@kcgl1.eng.ohio-state.edu> 60 * Date: 22-JUL-1996 61 * Revised: 25-SEP-1997 Update for 0.8.1, BIO_CTRL_SET -> BIO_C_SET_FD 62 */ 63/* VMS */ 64#include <stdio.h> 65#include <stdlib.h> 66#include <string.h> 67#include <errno.h> 68#include "cryptlib.h" 69#include <openssl/bio.h> 70 71#include <iodef.h> /* VMS IO$_ definitions */ 72#include <starlet.h> 73 74typedef unsigned short io_channel; 75/*************************************************************************/ 76struct io_status { short status, count; long flags; }; 77 78struct rpc_msg { /* Should have member alignment inhibited */ 79 char channel; /* 'A'-app data. 'R'-remote client 'G'-global */ 80 char function; /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */ 81 unsigned short int length; /* Amount of data returned or max to return */ 82 char data[4092]; /* variable data */ 83}; 84#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092) 85 86struct rpc_ctx { 87 int filled, pos; 88 struct rpc_msg msg; 89}; 90 91static int rtcp_write(BIO *h,const char *buf,int num); 92static int rtcp_read(BIO *h,char *buf,int size); 93static int rtcp_puts(BIO *h,const char *str); 94static int rtcp_gets(BIO *h,char *str,int size); 95static long rtcp_ctrl(BIO *h,int cmd,long arg1,void *arg2); 96static int rtcp_new(BIO *h); 97static int rtcp_free(BIO *data); 98 99static BIO_METHOD rtcp_method= 100 { 101 BIO_TYPE_FD, 102 "RTCP", 103 rtcp_write, 104 rtcp_read, 105 rtcp_puts, 106 rtcp_gets, 107 rtcp_ctrl, 108 rtcp_new, 109 rtcp_free, 110 NULL, 111 }; 112 113BIO_METHOD *BIO_s_rtcp(void) 114 { 115 return(&rtcp_method); 116 } 117/*****************************************************************************/ 118/* Decnet I/O routines. 119 */ 120 121#ifdef __DECC 122#pragma message save 123#pragma message disable DOLLARID 124#endif 125 126static int get ( io_channel chan, char *buffer, int maxlen, int *length ) 127{ 128 int status; 129 struct io_status iosb; 130 status = sys$qiow ( 0, chan, IO$_READVBLK, &iosb, 0, 0, 131 buffer, maxlen, 0, 0, 0, 0 ); 132 if ( (status&1) == 1 ) status = iosb.status; 133 if ( (status&1) == 1 ) *length = iosb.count; 134 return status; 135} 136 137static int put ( io_channel chan, char *buffer, int length ) 138{ 139 int status; 140 struct io_status iosb; 141 status = sys$qiow ( 0, chan, IO$_WRITEVBLK, &iosb, 0, 0, 142 buffer, length, 0, 0, 0, 0 ); 143 if ( (status&1) == 1 ) status = iosb.status; 144 return status; 145} 146 147#ifdef __DECC 148#pragma message restore 149#endif 150 151/***************************************************************************/ 152 153static int rtcp_new(BIO *bi) 154{ 155 struct rpc_ctx *ctx; 156 bi->init=1; 157 bi->num=0; 158 bi->flags = 0; 159 bi->ptr=OPENSSL_malloc(sizeof(struct rpc_ctx)); 160 ctx = (struct rpc_ctx *) bi->ptr; 161 ctx->filled = 0; 162 ctx->pos = 0; 163 return(1); 164} 165 166static int rtcp_free(BIO *a) 167{ 168 if (a == NULL) return(0); 169 if ( a->ptr ) OPENSSL_free ( a->ptr ); 170 a->ptr = NULL; 171 return(1); 172} 173 174static int rtcp_read(BIO *b, char *out, int outl) 175{ 176 int status, length; 177 struct rpc_ctx *ctx; 178 /* 179 * read data, return existing. 180 */ 181 ctx = (struct rpc_ctx *) b->ptr; 182 if ( ctx->pos < ctx->filled ) { 183 length = ctx->filled - ctx->pos; 184 if ( length > outl ) length = outl; 185 memmove ( out, &ctx->msg.data[ctx->pos], length ); 186 ctx->pos += length; 187 return length; 188 } 189 /* 190 * Requst more data from R channel. 191 */ 192 ctx->msg.channel = 'R'; 193 ctx->msg.function = 'G'; 194 ctx->msg.length = sizeof(ctx->msg.data); 195 status = put ( b->num, (char *) &ctx->msg, RPC_HDR_SIZE ); 196 if ( (status&1) == 0 ) { 197 return -1; 198 } 199 /* 200 * Read. 201 */ 202 ctx->pos = ctx->filled = 0; 203 status = get ( b->num, (char *) &ctx->msg, sizeof(ctx->msg), &length ); 204 if ( (status&1) == 0 ) length = -1; 205 if ( ctx->msg.channel != 'R' || ctx->msg.function != 'C' ) { 206 length = -1; 207 } 208 ctx->filled = length - RPC_HDR_SIZE; 209 210 if ( ctx->pos < ctx->filled ) { 211 length = ctx->filled - ctx->pos; 212 if ( length > outl ) length = outl; 213 memmove ( out, ctx->msg.data, length ); 214 ctx->pos += length; 215 return length; 216 } 217 218 return length; 219} 220 221static int rtcp_write(BIO *b, const char *in, int inl) 222{ 223 int status, i, segment, length; 224 struct rpc_ctx *ctx; 225 /* 226 * Output data, send in chunks no larger that sizeof(ctx->msg.data). 227 */ 228 ctx = (struct rpc_ctx *) b->ptr; 229 for ( i = 0; i < inl; i += segment ) { 230 segment = inl - i; 231 if ( segment > sizeof(ctx->msg.data) ) segment = sizeof(ctx->msg.data); 232 ctx->msg.channel = 'R'; 233 ctx->msg.function = 'P'; 234 ctx->msg.length = segment; 235 memmove ( ctx->msg.data, &in[i], segment ); 236 status = put ( b->num, (char *) &ctx->msg, segment + RPC_HDR_SIZE ); 237 if ((status&1) == 0 ) { i = -1; break; } 238 239 status = get ( b->num, (char *) &ctx->msg, sizeof(ctx->msg), &length ); 240 if ( ((status&1) == 0) || (length < RPC_HDR_SIZE) ) { i = -1; break; } 241 if ( (ctx->msg.channel != 'R') || (ctx->msg.function != 'C') ) { 242 printf("unexpected response when confirming put %c %c\n", 243 ctx->msg.channel, ctx->msg.function ); 244 245 } 246 } 247 return(i); 248} 249 250static long rtcp_ctrl(BIO *b, int cmd, long num, void *ptr) 251 { 252 long ret=1; 253 254 switch (cmd) 255 { 256 case BIO_CTRL_RESET: 257 case BIO_CTRL_EOF: 258 ret = 1; 259 break; 260 case BIO_C_SET_FD: 261 b->num = num; 262 ret = 1; 263 break; 264 case BIO_CTRL_SET_CLOSE: 265 case BIO_CTRL_FLUSH: 266 case BIO_CTRL_DUP: 267 ret=1; 268 break; 269 case BIO_CTRL_GET_CLOSE: 270 case BIO_CTRL_INFO: 271 case BIO_CTRL_GET: 272 case BIO_CTRL_PENDING: 273 case BIO_CTRL_WPENDING: 274 default: 275 ret=0; 276 break; 277 } 278 return(ret); 279 } 280 281static int rtcp_gets(BIO *bp, char *buf, int size) 282 { 283 return(0); 284 } 285 286static int rtcp_puts(BIO *bp, const char *str) 287{ 288 int length; 289 if (str == NULL) return(0); 290 length = strlen ( str ); 291 if ( length == 0 ) return (0); 292 return rtcp_write ( bp,str, length ); 293} 294 295