|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 8339 (0x2093)
Types: TextFile
Names: »rasn.c«
└─⟦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«
/* 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;
}