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 r

⟦701e7c65a⟧ TextFile

    Length: 8339 (0x2093)
    Types: TextFile
    Names: »rasn.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Chans/x40084/rasn.c« 

TextFile

/* rasn.c: incremental ASN1 reader */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/x40084/RCS/rasn.c,v 5.0 90/09/20 15:55:57 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Chans/x40084/RCS/rasn.c,v 5.0 90/09/20 15:55:57 pp Exp Locker: pp $
 *
 * $Log:	rasn.c,v $
 * Revision 5.0  90/09/20  15:55:57  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "util.h"
#include "q.h"
#include <isode/psap.h>
#include <isode/cmd_srch.h>

extern int		log_msgtype;
extern CMD_TABLE        qtbl_mt_type[];
extern char		*remote_site;
extern PE		ps2pe_aux2 ();

static struct qbuf *qbase;
static void add2qb ();
static int check_external ();
static int check_pserr (), qbproc ();
static int attempt_parse (), read_octet_hdr (), read_octet ();
static int proc_body (), proc_hdr (), proc_hdr_aux ();

IFP	asn_procfnx = proc_hdr;
static IFP  hdrfnx, bodyfnx;
static int	ext_type;
#define PENDING (2)
static int bad = 0;

void	asn_init (hf, bf, ext)
IFP	hf, bf;
int	ext;
{
	if (qbase)
		qb_free (qbase);
	qbase = NULL;
	bad = 0;
	hdrfnx = hf;
	bodyfnx = bf;
	asn_procfnx = proc_hdr;
	ext_type = ext;
}


static int proc_hdr (qp)
struct qbuf *qp;
{
        int     retval;

        retval = proc_hdr_aux (qp);

        switch (retval) {
        case OK:
        case DONE:
                PP_NOTICE (("<<< %s Received from %s",
                    rcmd_srch (log_msgtype, qtbl_mt_type),
                    remote_site));

                break;
        }

        return retval;
}



static int proc_hdr_aux (qp)
struct qbuf *qp;
{
	char	*pestr;
	int result;
	int	len;

	add2qb (&qbase, qp);

	pestr = qb2str (qbase);
	len = qbase -> qb_len;
	result = attempt_parse (pestr, &len);
	free (pestr);
	switch (result) {
	    case PENDING:
		return OK;
	    case DONE:
	    case NOTOK:
		return result;
	    case OK:
		break;
	}
		
	PP_TRACE (("Header read, %d bytes", len));
	if ((result = qbproc (qbase, &len, NULLIFP)) != OK)
		return result;
	asn_procfnx = proc_body;
	return proc_body ((struct qbuf *)NULL);
}

static int attempt_parse (str, len)
char	*str;
int	*len;
{
	PS 	ps;
	PE	pe;
	int	type;
	char	*ptr;
	int	len_left;

	if ((ps = ps_alloc (str_open)) == NULLPS) {
		PP_LOG (LLOG_EXCEPTIONS, ("Can't allocate PS"));
		return NOTOK;
	}
	if (str_setup (ps, str, *len, 1) == NOTOK) {
		PP_LOG (LLOG_EXCEPTIONS, ("Can't bind str to PS"));
		return NOTOK;
	}

	if (ext_type) {
		switch (check_external (ps)) {
		    case PENDING:
			return PENDING;
		    default:
		    case NOTOK:
			if (hdrfnx)
				(*hdrfnx) (NULLPE, NOTOK);
			bad = 1;
			*len = 0;
			return OK;
		    case OK:
			break;
		}
	}

	ptr = ps -> ps_ptr;	/* save where we had got to */
	len_left = *len - (ptr - str);

	if ((pe = ps2pe_aux2 (ps, 1, 0)) == NULLPE)
		return check_pserr (ps);

	if (ps -> ps_cnt <= 0) {
		ps_free (ps);
		return PENDING;
	}
	switch (PE_ID(pe -> pe_class, pe -> pe_id)) {
	    case PE_ID (PE_CLASS_CONT, 0):
		type = MT_UMPDU;
		break;
	    case PE_ID (PE_CLASS_CONT, 1):
		type = MT_DMPDU;
		str_setup (ps, ptr, len_left, 1);
		break;
	    case PE_ID (PE_CLASS_CONT, 2):
		type = MT_PMPDU;
		str_setup (ps, ptr, len_left, 1);
		break;
	    default:
		pe_free (pe);
		if (hdrfnx)
			(*hdrfnx) (NULLPE, NOTOK);
		bad = 1;
		*len = 0;
		return OK;
	}
	pe_free (pe);

	if ((pe = ps2pe(ps)) == NULLPE)
		return check_pserr (ps);

	if (hdrfnx)
		(*hdrfnx) (pe, type);

	*len -= ps -> ps_cnt;
	ps_free (ps);
	pe_free (pe);
	return type == MT_UMPDU ? OK : DONE;
}


static int proc_body (qp)
struct qbuf *qp;
{
	int	i;
	static int count, used, depth;
	
	if (qp)
		add2qb (&qbase, qp);
	if (bad) {
		i = qbase -> qb_len;
		return qbproc (qbase, &i, bodyfnx);
	}

	if (qbase -> qb_len && count > 0)
		if ((i = qbproc (qbase, &count, bodyfnx)) != OK)
			return i;

	for (;qbase -> qb_len > 0;) {
		char *pestr = qb2str (qbase);
		used = 0;
		i = read_octet_hdr (pestr, qbase -> qb_len,
				    &depth, &count, &used);
		free (pestr);
	
		switch (i) {
		    case DONE:
			if (ext_type && qbase -> qb_len >= 4)
				used += 4; /* use up the extra two EOC */
			if (qbase -> qb_len - used > 0) {
				PP_LOG(LLOG_EXCEPTIONS,
				       ("Trailing garbage (%d bytes) on end of PDU",
					qbase -> qb_len - used));
			}
			return DONE;
		    case NOTOK:
			return NOTOK;
		    case PENDING:
			return OK;
		    case OK:
			(void) qbproc (qbase, &used, NULLIFP);
			if ((i = qbproc (qbase, &count, bodyfnx)) != OK)
				return i;
			if (qbase -> qb_len <= 0)
				return OK;
			break;
		}
	}
	return OK;
}

static int check_external (ps)
PS	ps;
{
	PE	pe;

	/* EXTERNAL Wrapper */
	if ((pe = ps2pe_aux2 (ps, 1, 0)) == NULLPE)
		return check_pserr (ps);

	if (PE_ID (pe -> pe_class, pe -> pe_id) !=
	    PE_ID (PE_CLASS_UNIV, PE_CONS_EXTN)) {
		PP_LOG (LLOG_EXCEPTIONS,
			("Missing EXTERNAL wrapper; found %s/%d",
			 pe_classlist[pe -> pe_class], pe -> pe_id));
		return NOTOK;
	}
	pe_free (pe);

	if ((pe = ps2pe (ps)) == NULLPE)
		return check_pserr (ps);

	if (PE_ID (pe -> pe_class, pe -> pe_id) !=
	    PE_ID (PE_CLASS_UNIV, PE_PRIM_INT)) {
		PP_LOG (LLOG_EXCEPTIONS,
			("Missing External ID, found %s/%d",
			 pe_classlist[pe -> pe_class], pe -> pe_id));
		return NOTOK;
	}
	/* should check the number here - perhaps later */
	pe_free (pe);

	/* ANY Context 0 wrapper */
	if ((pe = ps2pe_aux2 (ps, 1, 0)) == NULLPE)
		return check_pserr (ps);

	if (PE_ID (pe -> pe_class, pe -> pe_id) !=
	    PE_ID (PE_CLASS_CONT, 0)) {
		PP_LOG (LLOG_EXCEPTIONS,
			("Not an EXTERNAL ANY type; found %s/%d",
			 pe_classlist[pe -> pe_class], pe -> pe_id));
		return NOTOK;
	}

	/* OK EXTERNAL checks out. */
	return OK;
}

static int qbproc (q, len, fnx)
struct qbuf *q;
int	*len;
IFP	fnx;
{
	struct qbuf *qp;
	int	i;

	if (q == NULL || q -> qb_len <= 0)
		return OK;
	if (q -> qb_len != q ->qb_forw -> qb_len &&
	    qb_pullup (q) == NOTOK)
		adios (NULLCP, "qb_pullup failed");

	for (qp = NULL; *len > 0; ) {
		if (qp == NULL &&
		    (qp = q -> qb_forw) == q)
			break;
		i = min(qp -> qb_len, *len);
		if (fnx) {
			int result;
			result = (*fnx) (qp -> qb_data, i);
			if (result != OK)
				return result;
		}
		*len -= i;
		qp -> qb_data += i;
		qp -> qb_len -= i;
		q -> qb_len -= i;
		if (qp -> qb_len <= 0) {
			remque (qp);
			free ((char *)qp);
			qp = NULL;
		}
	}
	return OK;
}

static void add2qb (qpp, qp)
struct qbuf **qpp, *qp;
{
	struct qbuf *q;

	if (*qpp == NULL) {
		*qpp = (struct qbuf *) smalloc (sizeof *qp);
		bzero ((char *)*qpp, sizeof **qpp);
		(*qpp) -> qb_forw = (*qpp) -> qb_back = *qpp;
	}
	for (q = qp -> qb_forw; q != qp; q = qp -> qb_forw) {
		remque (q);
		insque (q, (*qpp) -> qb_back);
		(*qpp) -> qb_len += q -> qb_len;
		qp -> qb_len -= q -> qb_len;
	}
}

static int read_octet_hdr (str, len, depthp, countp, usedp)
char	*str;
int	len;
int	*depthp;
int	*countp;
int	*usedp;
{
	static PS ps;

	*usedp = 0;
	if (len < 1)
		return OK;
	if (ps == NULLPS)
		if ((ps = ps_alloc (str_open)) == NULLPS) {
			PP_LOG (LLOG_EXCEPTIONS, ("Can't setup PS"));
			return NOTOK;
		}
	if (str_setup (ps, str, len, 1) == NOTOK) {
		PP_LOG (LLOG_EXCEPTIONS, ("Can't attach string to PS"));
		return NOTOK;
	}

	return read_octet (ps, depthp, countp, usedp);
}

static int read_octet (ps, depthp, countp, usedp)
PS	ps;
int	*depthp;
int	*countp;
int	*usedp;
{
	PE	pe;

	if ((pe = ps2pe_aux2 (ps, 1, 0)) == NULLPE)
		return check_pserr (ps);

	if (pe -> pe_class == PE_CLASS_UNIV &&
	    pe -> pe_id == PE_UNIV_EOC) {
		pe_free (pe);
		if (*depthp == 0) {
			*usedp = ps -> ps_ptr - ps -> ps_base;
			return DONE;
		}
		else {
			(*depthp) --;
			return  read_octet (ps, depthp, countp, usedp);
		}
	}
	
	if (pe -> pe_class != PE_CLASS_UNIV ||
	    pe -> pe_id != PE_PRIM_OCTS) {
		PP_LOG (LLOG_EXCEPTIONS,
			("Not an OCTET STRING"));
		return NOTOK;
	}
	if (pe -> pe_form != PE_FORM_PRIM) {
		(*depthp) ++;
		return read_octet (ps, depthp, countp, usedp);
	}
	*countp = pe -> pe_len;
	*usedp = ps -> ps_ptr - ps -> ps_base;
	pe_free (pe);
	return OK;
}

static int check_pserr (ps)
PS	ps;
{
	int	retval = PENDING;

	switch (ps -> ps_errno) {
	    case PS_ERR_EOF:
	    case PS_ERR_EOFLEN:
	    case PS_ERR_EOFID:
	    case PS_ERR_NONE:
		break;

	    default:
		PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error: %s",
					  ps_error (ps -> ps_errno)));
		retval = NOTOK;
		break;
	}
	return retval;
}