/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* layer above tcp (for rpc's use).
*
* There is a record marking layer between the xdr stream
* and the tcp transport level. A record is composed on one or more
* record fragments. A record fragment is a thirty-two bit header followed
* by n bytes of data, where n is contained in the header. The header
* is represented as a htonl(u_long). The high order bit encodes
* whether or not the fragment is the last fragment of the record
* (1 => fragment is last, 0 => more fragments to follow.
* The other 31 bits encode the byte length of the fragment.
*/
#include <sys/bootdebug.h>
extern long lseek();
static bool_t xdrrec_getint32();
static bool_t xdrrec_putint32();
static bool_t xdrrec_getbytes();
static bool_t xdrrec_putbytes();
static uint_t xdrrec_getpos();
static bool_t xdrrec_setpos();
static int32_t *xdrrec_inline();
static void xdrrec_destroy();
static struct xdr_ops *xdrrec_ops();
static bool_t fill_input_buf();
static bool_t get_input_bytes();
static bool_t set_input_fragment();
static bool_t skip_input_bytes();
static uint_t fix_buf_size();
/*
* A record is composed of one or more record fragments.
* A record fragment is a four-byte header followed by zero to
* 2**32-1 bytes. The header is treated as a long unsigned and is
* are a byte count of the fragment. The highest order bit is a boolean:
* 1 => this fragment is the last fragment of the record,
* 0 => this fragment is followed by more fragment(s).
*
* meet the needs of xdr and rpc based on tcp.
*/
typedef struct rec_strm {
/*
* out-goung bits
*/
int (*writeit)();
/*
* in-coming bits
*/
int (*readit)();
} RECSTREAM;
/*
* Create an xdr handle for xdrrec
* xdrrec_create fills in xdrs. Sendsize and recvsize are
* send and recv buffer sizes (0 => use default).
* tcp_handle is an opaque handle that is passed as the first parameter to
* the procedures readit and writeit. Readit and writeit are read and
* write respectively. They are like the system
* calls expect that they take an opaque handle rather than an fd.
*/
void
{
dprintf("xdrrec_create: out of memory\n");
/*
* This is bad. Should rework xdrrec_create to
* return a handle, and in this case return NULL
*/
return;
}
/*
* adjust sizes and allocate buffer quad byte aligned
*/
dprintf("xdrrec_create: out of memory\n");
return;
}
/*
* now the rest ...
*/
}
/*
* The routines defined below are the xdr ops which will go into the
* xdr handle filled in by xdrrec_create.
*/
static bool_t
{
/* first try the inline, fast case */
} else {
return (FALSE);
}
return (TRUE);
}
static bool_t
{
/*
* this case should almost never happen so the code is
* inefficient
*/
return (FALSE);
}
return (TRUE);
}
/*
* We need to be a little smarter here because we don't want to induce any
* pathological behavior in inetboot's networking stack. The algorithm we
* pursue is to try to consume the entire fragment exactly instead of
* blindly requesting the max to fill the input buffer.
*/
static bool_t /* must manage buffers, fragments, and records */
{
int current;
int frag_len;
while (len > 0) {
if (current == 0) {
return (FALSE);
if (!set_input_fragment(rstrm))
return (FALSE);
continue;
}
return (FALSE);
}
return (TRUE);
}
static bool_t
{
while (len > 0) {
return (FALSE);
}
}
return (TRUE);
}
static uint_t
{
if (pos != -1)
case XDR_ENCODE:
break;
case XDR_DECODE:
break;
default:
break;
}
}
static bool_t
{
if ((int)currpos != -1)
case XDR_ENCODE:
return (TRUE);
}
break;
case XDR_DECODE:
return (TRUE);
}
break;
}
return (FALSE);
}
static int32_t *
{
case XDR_ENCODE:
}
break;
case XDR_DECODE:
}
break;
}
return (buf);
}
static void
{
}
/*
* Exported routines to manage xdr records
*/
/*
* Before reading (deserializing from the stream, one should always call
* this procedure to guarantee proper record alignment.
*/
{
return (FALSE);
return (FALSE);
}
return (TRUE);
}
#ifdef notneeded
/*
* Look ahead fuction.
* Returns TRUE iff there is no more input in the buffer
* after consuming the rest of the current record.
*/
{
return (TRUE);
return (TRUE);
}
return (TRUE);
return (FALSE);
}
#endif /* notneeded */
/*
* The client must tell the package when an end-of-record has occurred.
* The second paraemters tells whether the record should be flushed to the
* (output) tcp stream. (This let's the package support batched or
* pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
*/
{
}
return (TRUE);
}
/*
* Internal useful routines
*/
static bool_t
{
!= (int)len)
return (FALSE);
return (TRUE);
}
static bool_t /* knows nothing about records! Only about input buffers */
{
uintptr_t i;
int len;
where += i;
#ifdef DEBUG
#endif
return (FALSE);
return (TRUE);
}
static bool_t
{
while (len > 0) {
#ifdef DEBUG
printf("get_input_bytes: len = %d, frag_len = %d, current %d\n",
#endif
/*
* set_input_bytes doesn't know how large the fragment is, we
* need to get the header so just grab a header's size worth
*/
if (frag_len == 0)
if (current == 0) {
return (FALSE);
continue;
}
}
return (TRUE);
}
static bool_t /* next four bytes of the input stream are treated as a header */
{
return (FALSE);
#ifdef DEBUG
printf("set_input_fragment: frag_len = %d, last frag = %s\n",
#endif
return (TRUE);
}
static bool_t /* consumes input bytes; knows nothing about records! */
{
#ifdef DEBUG
#endif
while (cnt > 0) {
if (current == 0) {
return (FALSE);
continue;
}
}
return (TRUE);
}
static uint_t
{
if (s < 100)
s = 4000;
return (RNDUP(s));
}
static struct xdr_ops *
{
}
return (&ops);
}