|
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; }