DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T f

⟦74233c714⟧ TextFile

    Length: 11565 (0x2d2d)
    Types: TextFile
    Names: »fd2tpkt.c«

Derivation

└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape
    └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« 
        └─⟦d3ac74d73⟧ 
            └─⟦this⟧ »isode-5.0/tsap/fd2tpkt.c« 

TextFile

/* fd2tpkt.c - read/write a TPDU thru a socket */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/tsap/RCS/fd2tpkt.c,v 6.0 89/03/18 23:45:09 mrose Rel $";
#endif

/* 
 * $Header: /f/osi/tsap/RCS/fd2tpkt.c,v 6.0 89/03/18 23:45:09 mrose Rel $
 *
 *
 * $Log:	fd2tpkt.c,v $
 * Revision 6.0  89/03/18  23:45:09  mrose
 * Release 5.0
 * 
 */

/*
 *				  NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


/* LINTLIBRARY */

#include <stdio.h>
#include <signal.h>
#include "tpkt.h"
#include "tailor.h"

/* \f

 */

struct tsapkt *fd2tpkt (fd, initfnx, readfnx)
int	fd;
IFP	initfnx,
	readfnx;
{
    register struct tsapkt *t;

    if ((t = newtpkt (0)) == NULL)
	return NULL;

    if ((t -> t_errno = fd2tpktaux (fd, t, initfnx, readfnx)) != OK) {
	if (t -> t_vdata != NULL)
	    free (t -> t_vdata), t -> t_vdata = NULL, t -> t_vlen = 0;

	if (t -> t_qbuf)
	    free ((char *) t -> t_qbuf), t -> t_qbuf = NULL;
    }

#ifdef	DEBUG
    if (tsap_log -> ll_events & LLOG_PDUS)
	tpkt2text (tsap_log, t, 1);
#endif

    return t;
}

/* \f

 */

static int  fd2tpktaux (fd, t, initfnx, readfnx)
int	fd;
register struct tsapkt *t;
IFP	initfnx,
	readfnx;
{
    register int    code,
                    len,
                    vlen;
    register char  *vptr;

    if ((code = (*initfnx) (fd, t)) != OK)
	return code;
    if (t -> t_li > TPDU_MAXLEN (t))
	return DR_LENGTH;

    switch (TPDU_CODE (t)) {
	case TPDU_CR:
	case TPDU_CC:
	    if (t -> t_li < TPDU_MINLEN (t, CR))
		return DR_LENGTH;
	    if (readx (fd, (char *) &t -> t_cr, CR_SIZE (t), readfnx)
		    != CR_SIZE (t))
		return DR_NETWORK;

	    if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, CR)) {
		if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL)
		    return DR_CONGEST;
		if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx)
			!= t -> t_vlen)
		    return DR_NETWORK;
		for (; vlen > 0; vptr += len, vlen -= len) {
		    int	    ilen;
		    
		    if (vlen < 2)
			return DR_LENGTH;
		    code = *vptr++ & 0xff;
		    len = *vptr++ & 0xff;
		    if ((vlen -= 2) < len)
			return DR_LENGTH;

		    switch (code) {
			case VDAT_TSAP_SRV:
			    if ((ilen = len) > sizeof t -> t_called)
				ilen = sizeof t -> t_called;
			    bcopy (vptr, t -> t_called,
					t -> t_calledlen = ilen);
			    break;

			case VDAT_TSAP_CLI:
			    if ((ilen = len) > sizeof t -> t_calling)
				ilen = sizeof t -> t_calling;
			    bcopy (vptr, t -> t_calling,
					t -> t_callinglen = ilen);
			    break;

			case VDAT_SIZE:
			    if (len != 1)
				return DR_LENGTH;
			    t -> t_tpdusize = *vptr & 0xff;
			    break;

			case VDAT_OPTIONS:
			    if (len != 1)
				return DR_LENGTH;
			    t -> t_options = *vptr & 0xff;
			    break;

			case VDAT_ALTERNATE:
			    {
				register int i;
				register char *ap;

				for (ap = vptr, i = len; i > 0; ap++, i--)
				    t -> t_cr.cr_alternate |=
						1 << ((*ap >> 4) & 0x0f);
			    }
			    break;

			case VDAT_VRSN:
			case VDAT_SECURITY:
			case VDAT_CHECKSUM:
			case VDAT_ACKTIME:
			case VDAT_THROUGHPUT:
			case VDAT_ERRORATE:
			case VDAT_PRIORITY:
			case VDAT_DELAY:
			case VDAT_TTR:
			    break;

			default: 	/* IS 8073 says to ignore it on CRs */
			    SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP,
			       ("unknown option 0x%x (length 0x%x) in %s TPDU",
				code, len,
				TPDU_CODE (t) == TPDU_CR ? "CR" : "CC"));
			    if (TPDU_CODE (t) == TPDU_CR)
				break;
			    return DR_PROTOCOL;
		    }
		}
	    }
	    break;

	case TPDU_DR:
	    if (t -> t_li < TPDU_MINLEN (t, DR))
		return DR_LENGTH;
	    if (readx (fd, (char *) &t -> t_dr, DR_SIZE (t), readfnx)
		    != DR_SIZE (t))
		return DR_NETWORK;

	    if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, DR)) {
		if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL)
		    return DR_CONGEST;
		if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx)
			!= t -> t_vlen)
		    return DR_NETWORK;
		for (; vlen > 0; vptr += len, vlen -= len) {
		    if (vlen < 2)
			return DR_LENGTH;
		    code = *vptr++ & 0xff;
		    len = *vptr++ & 0xff;
		    if ((vlen -= 2) < len)
			return DR_LENGTH;

		    switch (code) {
			case VDAT_ADDITIONAL:
			case VDAT_CHECKSUM:
			    break;

			default: 
			    return DR_PROTOCOL;
		    }
		}
	    }
	    break;

	case TPDU_DT:
	    if (t -> t_li < TPDU_MINLEN (t, DT))
		return DR_LENGTH;
	    if (readx (fd, (char *) &t -> t_dt, DT_SIZE (t), readfnx)
		    != DT_SIZE (t))
		return DR_NETWORK;

	    if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, DT)) {
		if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL)
		    return DR_CONGEST;
		if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx)
			!= t -> t_vlen)
		    return DR_NETWORK;
		for (; vlen > 0; vptr += len, vlen -= len) {
		    if (vlen < 2)
			return DR_LENGTH;
		    code = *vptr++ & 0xff;
		    len = *vptr++ & 0xff;
		    if ((vlen -= 2) < len)
			return DR_LENGTH;

		    switch (code) {
			case VDAT_CHECKSUM:
			    break;

			default: 
			    return DR_PROTOCOL;
		    }
		}
	    }
	    break;

	case TPDU_ED: 
	    if (t -> t_li < TPDU_MINLEN (t, ED))
		return DR_LENGTH;
	    if (readx (fd, (char *) &t -> t_ed, ED_SIZE (t), readfnx)
		    != ED_SIZE (t))
		return DR_NETWORK;
	    t -> t_ed.ed_nr = ntohs (t -> t_ed.ed_nr);

	    if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, ED)) {
		if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL)
		    return DR_CONGEST;
		if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx)
			!= t -> t_vlen)
		    return DR_NETWORK;

		for (; vlen > 0; vptr += len, vlen -= len) {
		    if (vlen < 2)
			return DR_LENGTH;
		    code = *vptr++ & 0xff;
		    len = *vptr++ & 0xff;
		    if ((vlen -= 2) < len)
			return DR_LENGTH;

		    switch (code) {
			case VDAT_CHECKSUM:
			case VDAT_SUBSEQ:
			case VDAT_FLOWCTL:
			    break;

			default: 
			    return DR_PROTOCOL;
		    }
		}
	    }
	    break;

	case TPDU_ER:
	    if (t -> t_li < TPDU_MINLEN (t, ER))
		return DR_LENGTH;
	    if (readx (fd, (char *) &t -> t_er, ER_SIZE (t), readfnx)
		    != ER_SIZE (t))
		return DR_NETWORK;

	    if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, ER)) {
		if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL)
		    return DR_CONGEST;
		if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx)
			!= t -> t_vlen)
		    return DR_NETWORK;
		for (; vlen > 0; vptr += len, vlen -= len) {
		    if (vlen < 2)
			return DR_LENGTH;
		    code = *vptr++ & 0xff;
		    len = *vptr++ & 0xff;
		    if ((vlen -= 2) < len)
			return DR_LENGTH;

		    switch (code) {
			case VDAT_INVALID:
			case VDAT_CHECKSUM:
			    break;

			default: 
			    return DR_PROTOCOL;
		    }
		}
	    }
	    break;

	default: 
	    return DR_PROTOCOL;
    }

    if (len = TPDU_USRLEN (t)) {
	if ((t -> t_qbuf = (struct qbuf *)
			    malloc (sizeof *t -> t_qbuf + (unsigned) len))
		== NULL)
	    return DR_CONGEST;
	t -> t_qbuf -> qb_forw = t -> t_qbuf -> qb_back = t -> t_qbuf;
	if (readx (fd, t -> t_qbuf -> qb_data = t -> t_qbuf -> qb_base,
		t -> t_qbuf -> qb_len = len, readfnx) != len)
	    return DR_NETWORK;
    }

    return OK;
}

/* \f

 */

static int  readx (fd, buffer, n, readfnx)
int	fd;
char    *buffer;
int	n;
IFP	readfnx;
{
    register int    i,
                    cc;
    register char   *bp;

    for (bp = buffer, i = n; i > 0; bp += cc, i -= cc) {
	switch (cc = (*readfnx) (fd, bp, i)) {
	    case NOTOK: 
		return (i = bp - buffer) ? i : NOTOK;

	    case OK: 
		break;

	    default: 
		continue;
	}
	break;
    }

    return (bp - buffer);
}

/* \f

 */

int	tpkt2fd (fd, t, writefnx)
int	fd;
register struct tsapkt *t;
IFP	writefnx;
{
    SBV	    smask;
    int     i,
	    ilen,
            ulen;
    char   *cp,
	   *vptr,
           *outptr;
    register struct udvec  *uv;
    SFP	    pstat;

    if (t -> t_errno != OK)
	return t -> t_errno;

    if (t -> t_vrsn != TPKT_VRSN)
	if (t -> t_vrsn)
	    return DR_PROTOCOL;
	else
	    t -> t_vrsn = TPKT_VRSN;

    if (t -> t_vdata != NULL) {
	free (t -> t_vdata);
	t -> t_vdata = NULL;
    }
    t -> t_vlen = 0;

    for (ulen = 0, uv = t -> t_udvec; uv -> uv_base; uv++)
	ulen += uv -> uv_len;

    switch (TPDU_CODE (t)) {
	case TPDU_CR:
	case TPDU_CC:
	    if ((vptr = t -> t_vdata =
		    malloc ((unsigned) (3 + 7 + (2 + t -> t_callinglen)
				 + (2 + t -> t_calledlen) + 3))) == NULL)
		return DR_CONGEST;
	    if (t -> t_options) {
		*vptr++ = VDAT_OPTIONS;
		*vptr++ = 1;
		*vptr++ = t -> t_options;
		t -> t_vlen += 3;
	    }
	    if (CR_CLASS (t) != CR_CLASS_TP0 && t -> t_cr.cr_alternate) {
		/* XXX: this doesn't preserve the order of alternates */
		*vptr++ = VDAT_ALTERNATE;
		cp = vptr++;
		if (t -> t_cr.cr_alternate & ALT_TP0)
		    *vptr++ = CR_CLASS_TP0;
		if (t -> t_cr.cr_alternate & ALT_TP1)
		    *vptr++ = CR_CLASS_TP1;
		if (t -> t_cr.cr_alternate & ALT_TP2)
		    *vptr++ = CR_CLASS_TP2;
		if (t -> t_cr.cr_alternate & ALT_TP3)
		    *vptr++ = CR_CLASS_TP3;
		if (t -> t_cr.cr_alternate & ALT_TP4)
		    *vptr++ = CR_CLASS_TP4;
		i = (vptr - cp) - 1;
		*cp = i & 0xff;
		t -> t_vlen += (2 + i) & 0xff;
	    }
	    if (t -> t_callinglen > 0) {
		*vptr++ = VDAT_TSAP_CLI;
		*vptr++ = t -> t_callinglen;
		bcopy (t -> t_calling, vptr, t -> t_callinglen);
		vptr += t -> t_callinglen;
		t -> t_vlen += 2 + t -> t_callinglen;
	    }
	    if (t -> t_calledlen > 0) {
		*vptr++ = VDAT_TSAP_SRV;
		*vptr++ = t -> t_calledlen;
		bcopy (t -> t_called, vptr, t -> t_calledlen);
		vptr += t -> t_calledlen;
		t -> t_vlen += 2 + t -> t_calledlen;
	    }
	    if (t -> t_tpdusize) {
		*vptr++ = VDAT_SIZE;
		*vptr++ = 1;
		*vptr++ = t -> t_tpdusize;
		t -> t_vlen += 3;
	    }
	    if (t -> t_vlen == 0) {
		free (t -> t_vdata);
		t -> t_vdata = NULL;
	    }
	    t -> t_li = TPDU_MINLEN (t, CR) + t -> t_vlen;
	    outptr = (char *) &t -> t_cr;
	    ilen = CR_SIZE (t);
	    break;

	case TPDU_DR: 
	    t -> t_li = TPDU_MINLEN (t, DR) + t -> t_vlen;
	    outptr = (char *) &t -> t_dr;
	    ilen = DR_SIZE (t);
	    break;

	case TPDU_DT: 
	    t -> t_li = TPDU_MINLEN (t, DT) + t -> t_vlen;
	    outptr = (char *) &t -> t_dt;
	    ilen = DT_SIZE (t);
	    break;

	case TPDU_ED: 
	    t -> t_li = TPDU_MINLEN (t, ED) + t -> t_vlen;
	    t -> t_ed.ed_nr = htons (t -> t_ed.ed_nr);
	    outptr = (char *) &t -> t_ed;
	    ilen = ED_SIZE (t);
	    break;

	case TPDU_ER: 
	    t -> t_li = TPDU_MINLEN (t, ER) + t -> t_vlen;
	    outptr = (char *) &t -> t_er;
	    ilen = ER_SIZE (t);
	    if (ulen > 0)
		return DR_PROTOCOL;
	    break;

	default: 
	    return DR_PROTOCOL;
    }

    t -> t_length = htons (t -> t_li + 5 + ulen);

#ifdef	DEBUG
    if (tsap_log -> ll_events & LLOG_PDUS)
	tpkt2text (tsap_log, t, 0);
#endif

    pstat = signal (SIGPIPE, SIG_IGN);
    smask = sigioblock ();

    i = (*writefnx) (fd, t, outptr, ilen);

    (void) sigiomask (smask);
    (void) signal (SIGPIPE, pstat);

    if (i != NOTOK)
	i = OK;
    else
	if (t -> t_errno == DR_UNKNOWN)
	    t -> t_errno = DR_NETWORK;

    return i;
}

/* \f

 */

struct tsapkt *newtpkt (code)
int	code;
{
    register struct tsapkt *t;

    t = (struct tsapkt *) calloc (1, sizeof *t);
    if (t == NULL)
	return NULL;

    t -> t_vrsn = TPKT_VRSN;
    t -> t_code = code;

    return t;
}


int	freetpkt (t)
register struct tsapkt *t;
{
    if (t == NULL)
	return;

    if (t -> t_vdata)
	free (t -> t_vdata);

    if (t -> t_qbuf)
	free ((char *) t -> t_qbuf);

    free ((char *) t);
}