155714Skris/* crypto/bio/bss_rtcp.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280297Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280297Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280297Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280297Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280297Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280297Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59280297Sjkim/*-
60280297Sjkim * Written by David L. Jones <jonesd@kcgl1.eng.ohio-state.edu>
6155714Skris * Date:   22-JUL-1996
62280297Sjkim * Revised: 25-SEP-1997         Update for 0.8.1, BIO_CTRL_SET -> BIO_C_SET_FD
6355714Skris */
6455714Skris/* VMS */
6555714Skris#include <stdio.h>
6655714Skris#include <stdlib.h>
6755714Skris#include <string.h>
6855714Skris#include <errno.h>
6955714Skris#include "cryptlib.h"
7055714Skris#include <openssl/bio.h>
7155714Skris
72280297Sjkim#include <iodef.h>              /* VMS IO$_ definitions */
7355714Skris#include <starlet.h>
7455714Skris
7555714Skristypedef unsigned short io_channel;
7655714Skris/*************************************************************************/
77280297Sjkimstruct io_status {
78280297Sjkim    short status, count;
79280297Sjkim    long flags;
80280297Sjkim};
8155714Skris
82280297Sjkim/* Should have member alignment inhibited */
83280297Sjkimstruct rpc_msg {
84280297Sjkim    /* 'A'-app data. 'R'-remote client 'G'-global */
85280297Sjkim    char channel;
86280297Sjkim    /* 'G'-get, 'P'-put, 'C'-confirm, 'X'-close */
87280297Sjkim    char function;
88280297Sjkim    /* Amount of data returned or max to return */
89280297Sjkim    unsigned short int length;
90280297Sjkim    /* variable data */
91280297Sjkim    char data[4092];
9255714Skris};
9355714Skris#define RPC_HDR_SIZE (sizeof(struct rpc_msg) - 4092)
9455714Skris
9555714Skrisstruct rpc_ctx {
9655714Skris    int filled, pos;
9755714Skris    struct rpc_msg msg;
9855714Skris};
9955714Skris
100280297Sjkimstatic int rtcp_write(BIO *h, const char *buf, int num);
101280297Sjkimstatic int rtcp_read(BIO *h, char *buf, int size);
102280297Sjkimstatic int rtcp_puts(BIO *h, const char *str);
103280297Sjkimstatic int rtcp_gets(BIO *h, char *str, int size);
104280297Sjkimstatic long rtcp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
10555714Skrisstatic int rtcp_new(BIO *h);
10655714Skrisstatic int rtcp_free(BIO *data);
10755714Skris
108280297Sjkimstatic BIO_METHOD rtcp_method = {
109280297Sjkim    BIO_TYPE_FD,
110280297Sjkim    "RTCP",
111280297Sjkim    rtcp_write,
112280297Sjkim    rtcp_read,
113280297Sjkim    rtcp_puts,
114280297Sjkim    rtcp_gets,
115280297Sjkim    rtcp_ctrl,
116280297Sjkim    rtcp_new,
117280297Sjkim    rtcp_free,
118280297Sjkim    NULL,
119280297Sjkim};
12055714Skris
12155714SkrisBIO_METHOD *BIO_s_rtcp(void)
122280297Sjkim{
123280297Sjkim    return (&rtcp_method);
124280297Sjkim}
125280297Sjkim
12655714Skris/*****************************************************************************/
127280297Sjkim/*
128280297Sjkim * Decnet I/O routines.
12955714Skris */
13055714Skris
13155714Skris#ifdef __DECC
132280297Sjkim# pragma message save
133280297Sjkim# pragma message disable DOLLARID
13455714Skris#endif
13555714Skris
136280297Sjkimstatic int get(io_channel chan, char *buffer, int maxlen, int *length)
13755714Skris{
13855714Skris    int status;
13955714Skris    struct io_status iosb;
140280297Sjkim    status = sys$qiow(0, chan, IO$_READVBLK, &iosb, 0, 0,
141280297Sjkim                      buffer, maxlen, 0, 0, 0, 0);
142280297Sjkim    if ((status & 1) == 1)
143280297Sjkim        status = iosb.status;
144280297Sjkim    if ((status & 1) == 1)
145280297Sjkim        *length = iosb.count;
14655714Skris    return status;
14755714Skris}
14855714Skris
149280297Sjkimstatic int put(io_channel chan, char *buffer, int length)
15055714Skris{
15155714Skris    int status;
15255714Skris    struct io_status iosb;
153280297Sjkim    status = sys$qiow(0, chan, IO$_WRITEVBLK, &iosb, 0, 0,
154280297Sjkim                      buffer, length, 0, 0, 0, 0);
155280297Sjkim    if ((status & 1) == 1)
156280297Sjkim        status = iosb.status;
15755714Skris    return status;
15855714Skris}
15955714Skris
16055714Skris#ifdef __DECC
161280297Sjkim# pragma message restore
16255714Skris#endif
16355714Skris
16455714Skris/***************************************************************************/
16555714Skris
16655714Skrisstatic int rtcp_new(BIO *bi)
16755714Skris{
16855714Skris    struct rpc_ctx *ctx;
169280297Sjkim    bi->init = 1;
170280297Sjkim    bi->num = 0;
171280297Sjkim    bi->flags = 0;
172280297Sjkim    bi->ptr = OPENSSL_malloc(sizeof(struct rpc_ctx));
173306195Sjkim    if (bi->ptr == NULL)
174306195Sjkim        return (0);
175280297Sjkim    ctx = (struct rpc_ctx *)bi->ptr;
176280297Sjkim    ctx->filled = 0;
177280297Sjkim    ctx->pos = 0;
178280297Sjkim    return (1);
17955714Skris}
18055714Skris
18155714Skrisstatic int rtcp_free(BIO *a)
18255714Skris{
183280297Sjkim    if (a == NULL)
184280297Sjkim        return (0);
185280297Sjkim    if (a->ptr)
186280297Sjkim        OPENSSL_free(a->ptr);
187280297Sjkim    a->ptr = NULL;
188280297Sjkim    return (1);
18955714Skris}
190280297Sjkim
19155714Skrisstatic int rtcp_read(BIO *b, char *out, int outl)
19255714Skris{
19355714Skris    int status, length;
19455714Skris    struct rpc_ctx *ctx;
19555714Skris    /*
19655714Skris     * read data, return existing.
19755714Skris     */
198280297Sjkim    ctx = (struct rpc_ctx *)b->ptr;
199280297Sjkim    if (ctx->pos < ctx->filled) {
200280297Sjkim        length = ctx->filled - ctx->pos;
201280297Sjkim        if (length > outl)
202280297Sjkim            length = outl;
203280297Sjkim        memmove(out, &ctx->msg.data[ctx->pos], length);
204280297Sjkim        ctx->pos += length;
205280297Sjkim        return length;
20655714Skris    }
20755714Skris    /*
20855714Skris     * Requst more data from R channel.
20955714Skris     */
21055714Skris    ctx->msg.channel = 'R';
21155714Skris    ctx->msg.function = 'G';
21255714Skris    ctx->msg.length = sizeof(ctx->msg.data);
213280297Sjkim    status = put(b->num, (char *)&ctx->msg, RPC_HDR_SIZE);
214280297Sjkim    if ((status & 1) == 0) {
215280297Sjkim        return -1;
21655714Skris    }
21755714Skris    /*
21855714Skris     * Read.
21955714Skris     */
22055714Skris    ctx->pos = ctx->filled = 0;
221280297Sjkim    status = get(b->num, (char *)&ctx->msg, sizeof(ctx->msg), &length);
222280297Sjkim    if ((status & 1) == 0)
223280297Sjkim        length = -1;
224280297Sjkim    if (ctx->msg.channel != 'R' || ctx->msg.function != 'C') {
225280297Sjkim        length = -1;
22655714Skris    }
22755714Skris    ctx->filled = length - RPC_HDR_SIZE;
228280297Sjkim
229280297Sjkim    if (ctx->pos < ctx->filled) {
230280297Sjkim        length = ctx->filled - ctx->pos;
231280297Sjkim        if (length > outl)
232280297Sjkim            length = outl;
233280297Sjkim        memmove(out, ctx->msg.data, length);
234280297Sjkim        ctx->pos += length;
235280297Sjkim        return length;
23655714Skris    }
23755714Skris
23855714Skris    return length;
23955714Skris}
24055714Skris
24168651Skrisstatic int rtcp_write(BIO *b, const char *in, int inl)
24255714Skris{
24355714Skris    int status, i, segment, length;
24455714Skris    struct rpc_ctx *ctx;
24555714Skris    /*
24655714Skris     * Output data, send in chunks no larger that sizeof(ctx->msg.data).
24755714Skris     */
248280297Sjkim    ctx = (struct rpc_ctx *)b->ptr;
249280297Sjkim    for (i = 0; i < inl; i += segment) {
250280297Sjkim        segment = inl - i;
251280297Sjkim        if (segment > sizeof(ctx->msg.data))
252280297Sjkim            segment = sizeof(ctx->msg.data);
253280297Sjkim        ctx->msg.channel = 'R';
254280297Sjkim        ctx->msg.function = 'P';
255280297Sjkim        ctx->msg.length = segment;
256280297Sjkim        memmove(ctx->msg.data, &in[i], segment);
257280297Sjkim        status = put(b->num, (char *)&ctx->msg, segment + RPC_HDR_SIZE);
258280297Sjkim        if ((status & 1) == 0) {
259280297Sjkim            i = -1;
260280297Sjkim            break;
261280297Sjkim        }
26255714Skris
263280297Sjkim        status = get(b->num, (char *)&ctx->msg, sizeof(ctx->msg), &length);
264280297Sjkim        if (((status & 1) == 0) || (length < RPC_HDR_SIZE)) {
265280297Sjkim            i = -1;
266280297Sjkim            break;
267280297Sjkim        }
268280297Sjkim        if ((ctx->msg.channel != 'R') || (ctx->msg.function != 'C')) {
269280297Sjkim            printf("unexpected response when confirming put %c %c\n",
270280297Sjkim                   ctx->msg.channel, ctx->msg.function);
27155714Skris
272280297Sjkim        }
27355714Skris    }
274280297Sjkim    return (i);
27555714Skris}
27655714Skris
27768651Skrisstatic long rtcp_ctrl(BIO *b, int cmd, long num, void *ptr)
278280297Sjkim{
279280297Sjkim    long ret = 1;
28055714Skris
281280297Sjkim    switch (cmd) {
282280297Sjkim    case BIO_CTRL_RESET:
283280297Sjkim    case BIO_CTRL_EOF:
284280297Sjkim        ret = 1;
285280297Sjkim        break;
286280297Sjkim    case BIO_C_SET_FD:
287280297Sjkim        b->num = num;
288280297Sjkim        ret = 1;
289280297Sjkim        break;
290280297Sjkim    case BIO_CTRL_SET_CLOSE:
291280297Sjkim    case BIO_CTRL_FLUSH:
292280297Sjkim    case BIO_CTRL_DUP:
293280297Sjkim        ret = 1;
294280297Sjkim        break;
295280297Sjkim    case BIO_CTRL_GET_CLOSE:
296280297Sjkim    case BIO_CTRL_INFO:
297280297Sjkim    case BIO_CTRL_GET:
298280297Sjkim    case BIO_CTRL_PENDING:
299280297Sjkim    case BIO_CTRL_WPENDING:
300280297Sjkim    default:
301280297Sjkim        ret = 0;
302280297Sjkim        break;
303280297Sjkim    }
304280297Sjkim    return (ret);
305280297Sjkim}
30655714Skris
30755714Skrisstatic int rtcp_gets(BIO *bp, char *buf, int size)
308280297Sjkim{
309280297Sjkim    return (0);
310280297Sjkim}
31155714Skris
31268651Skrisstatic int rtcp_puts(BIO *bp, const char *str)
31355714Skris{
31455714Skris    int length;
315280297Sjkim    if (str == NULL)
316280297Sjkim        return (0);
317280297Sjkim    length = strlen(str);
318280297Sjkim    if (length == 0)
319280297Sjkim        return (0);
320280297Sjkim    return rtcp_write(bp, str, length);
32155714Skris}
322