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 x

⟦7997989e4⟧ TextFile

    Length: 20750 (0x510e)
    Types: TextFile
    Names: »x400inext.c«

Derivation

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

TextFile

/* x400inext.c: X400(1988) extensions handling - inbound */

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

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Chans/x40088/RCS/x400inext.c,v 5.0 90/09/20 15:58:41 pp Exp Locker: pp $
 *
 * $Log:	x400inext.c,v $
 * Revision 5.0  90/09/20  15:58:41  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "util.h"
#include "chan.h"
#include "q.h"
#include "adr.h"
#include "or.h"
#include "prm.h"
#include "dr.h"
#include "retcode.h"
#include <isode/rtsap.h>
#include "Extensions-types.h"
#include "Transfer-types.h"

extern void
	decode_Extensions_LatestDeliveryTime (),
	decode_Extensions_PhysicalRenditionAttributes (),
	decode_Extensions_RecipientNumberForAdvice (),
	decode_Extensions_RequestedDeliveryMethod (),
	decode_Extensions_PhysicalDeliveryModes ();
#if PP_DEBUG > 0
extern void print_Extensions_LatestDeliveryTime (),
	print_Extensions_PhysicalRenditionAttributes (),
	print_Extensions_RecipientNumberForAdvice (),
	print_Extensions_RequestedDeliveryMethod (),
	print_Extensions_PhysicalDeliveryModes ();
#else
#define print_Extensions_LatestDeliveryTime NULLIFP
#define	print_Extensions_PhysicalRenditionAttributes NULLIFP
#define	print_Extensions_RecipientNumberForAdvice NULLIFP
#define	print_Extensions_RequestedDeliveryMethod NULLIFP
#define	print_Extensions_PhysicalDeliveryModes NULLIFP
#endif

static void	decode_ext_time ();




void	do_local_extension ();
void	do_global_extension ();

static Extension *flatten_ext ();
static void	ext_recip_reassign ();
static void	ext_dlxp ();
static void	ext_conv ();
static void	ext_ora ();
static void	ext_dlexph ();
static void 	ext_inttrace ();

static int	pe2crit ();

static DLHistory *ext_decode_dlh  ();

#define decode_singleint(type, ip, critp, defcrit, pfnx, dfnx, ffnx, label, ext) \
	{ \
	struct type *genp; \
\
	PP_PDU (pfnx, ext -> value, label, PDU_READ); \
	if (dfnx (ext -> value, 1, NULLIP, NULLVP, &genp) == NOTOK) \
		adios (NULLCP, "Can't parse %s value [%s]", label, PY_pepy); \
\
	(ip) = genp -> parm; \
	(critp) = pe2crit (ext -> criticality, defcrit); \
	ffnx (genp); \
	}

static void decode_extension (value, crit, defcrit, pfnx, dfnx, ffnx,
			      label, decoder, ext)
caddr_t	value;
int	*crit;
int	defcrit;
IFP	pfnx, dfnx, ffnx;
VFP	decoder;
char	*label;
struct type_MTA_ExtensionField *ext;
{
	caddr_t *genp;

#if PP_DEBUG > 0
	if (pfnx && pp_log_norm -> ll_events & LLOG_PDUS)
		_vpdu (pp_log_norm, pfnx, ext -> value, label, PDU_READ);
#endif
	if ((*dfnx) (ext -> value, 1, NULLIP, NULLVP, &genp) == NOTOK)
		adios (NULLCP, "Can't parse %s value [%s]", label, PY_pepy);

	(*decoder) (value, genp);

	*crit = pe2crit (ext -> criticality, defcrit);

	(*ffnx) (genp);
}

extern OR_ptr do_or_address ();

#define bit_ison(x,y)	(bit_test(x,y) == 1)

load_pm_extensions (qp, ext)
Q_struct *qp;
struct type_MTA_Extensions *ext;
{
	struct type_MTA_Extensions *ep;

	for (ep = ext; ep; ep = ep -> next) {
		switch (ep -> ExtensionField -> type -> offset) {
		    case type_MTA_ExtensionType_local:
			do_local_extension (&qp -> per_message_extensions,
					    ep -> ExtensionField);
			break;

		    case type_MTA_ExtensionType_global:
			do_global_extension (ep -> ExtensionField ->
					     type -> un.global,
					     qp, ep -> ExtensionField);
			break;

		    default:
			PP_LOG (LLOG_EXCEPTIONS,
				("Unknown extension type %d",
				 ep -> ExtensionField -> type -> offset));
			break;
		}
	}
}

squash_ext (qbp, value)
struct qbuf **qbp;
PE	value;
{
	char	*cp;
	int	len;
	PS	ps;

	if ((ps = ps_alloc (str_open)) == NULLPS)
		adios (NULLCP, "Can't allocate PS");

	len = ps_get_abs (value);
	cp = smalloc (len);

	if (str_setup (ps, cp, len, 1) == NOTOK)
		adios (NULLCP, "Can't setup stream [%s]",
		       ps_error (ps -> ps_errno));

	if (pe2ps (ps, value) == NOTOK)
		adios (NULLCP, "pe2ps failed [%s]", ps_error (ps -> ps_errno));
	
	ps_free (ps);

	*qbp = str2qb (cp, len, 1);
	free (cp);
}

static Extension *flatten_ext (ext)
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep;

	ep = (Extension *)smalloc (sizeof *ep);
	if (ext -> type -> offset == type_MTA_ExtensionType_global) {
		ep -> ext_int = ext -> type -> un.global;
		ep -> ext_oid = NULLOID;
	}
	else {
		ep -> ext_int = EXT_OID_FORM;
		ep -> ext_oid = oid_cpy (ext -> type -> un.local);
	}
		
	squash_ext (&ep -> ext_value, ext -> value);
	ep -> ext_criticality = pe2crit (ext -> criticality,
					 CRITICAL_NONE);
	ep -> ext_next = NULL;
	return ep;
}

void do_local_extension (elist, ext)
Extension **elist;
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep, **epp;

	PP_LOG (LLOG_EXCEPTIONS, ("Unknown local extension %s",
				  sprintoid (ext -> type -> un.local)));

	ep = flatten_ext (ext);
	for (epp = elist; *epp;
	     epp = &(*epp) -> ext_next)
		continue;
	*epp = ep;
}

static void ext_security (qbp, critp, defcrit, ext)
struct qbuf **qbp;
int	*critp;
int	defcrit;
struct type_MTA_ExtensionField *ext;
{
	squash_ext (qbp, ext -> value);

	*critp = pe2crit (ext -> criticality, defcrit);
}

static void do_global_extension (n, qp, ext)
int	n;
Q_struct *qp;
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep, **epp;

	switch (n) {
	    case EXT_RECIPIENT_REASSIGNMENT_PROHIBITED:
		decode_singleint (type_Extensions_RecipientReassignmentProhibited,
			       qp -> recip_reassign_prohibited,
			       qp -> recip_reassign_crit,
			       EXT_RECIPIENT_REASSIGNMENT_PROHIBITED_DC,
			       print_Extensions_RecipientReassignmentProhibited,
			       decode_Extensions_RecipientReassignmentProhibited,
			       free_Extensions_RecipientReassignmentProhibited,
			       "Extension.RecipientReassignmentProhibited",
			       ext);
		break;

	    case EXT_DL_EXPANSION_PROHIBITED:
		decode_singleint (type_Extensions_DLExpansionProhibited,
			       qp -> dl_expansion_prohibited,
			       qp -> dl_expansion_crit,
			       EXT_DL_EXPANSION_PROHIBITED_DC,
			       print_Extensions_DLExpansionProhibited,
			       decode_Extensions_DLExpansionProhibited,
			       free_Extensions_DLExpansionProhibited,
			       "Extension.DLExpansionProhibited",
			       ext);
		break;

	    case EXT_LATEST_DELIVERY_TIME:
		decode_extension (&qp -> latest_time,
				  &qp -> latest_time_crit,
				  EXT_LATEST_DELIVERY_TIME_DC,
				  print_Extensions_LatestDeliveryTime,
				  decode_Extensions_LatestDeliveryTime,
				  free_Extensions_LatestDeliveryTime,
				  "Extensions.LatestDeliveryTime",
				  decode_ext_time,
				  ext);
		break;

	    case EXT_CONVERSION_WITH_LOSS_PROHIBITED:
		decode_singleint (type_Extensions_ConversionWithLossProhibited,
			       qp -> conversion_with_loss_prohibited,
			       qp -> conversion_with_loss_crit,
			       EXT_CONVERSION_WITH_LOSS_PROHIBITED_DC,
			       print_Extensions_ConversionWithLossProhibited,
			       decode_Extensions_ConversionWithLossProhibited,
			       free_Extensions_ConversionWithLossProhibited,
			       "Extensions.ConversionWithLossProhibited",
			       ext);
		break;

	    case EXT_DL_EXPANSION_HISTORY:
		ext_dlexph (qp, ext);
		break;

	    case EXT_ORIGINATOR_RETURN_ADDRESS:
		ext_ora (qp, ext);
		break;

	    case EXT_INTERNAL_TRACE_INFORMATION:
		ext_inttrace (&qp -> trace, ext);
		break;

	    case EXT_ORIGINATOR_CERTIFICATE:
		ext_security (&qp -> originator_certificate,
			      &qp -> originator_certificate_crit,
			      EXT_ORIGINATOR_CERTIFICATE_DC,
			      ext);
		break;

	    case EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER:
		ext_security (&qp -> algorithm_identifier,
			      &qp -> algorithm_identifier_crit,
			      EXT_CONTENT_CONFIDENTIALITY_ALGORITHM_IDENTIFIER_DC,
			      ext);
		break;
	    case EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK:
		ext_security (&qp -> message_origin_auth_check,
			      &qp -> message_origin_auth_check_crit,
			      EXT_MESSAGE_ORIGIN_AUTHENTICATION_CHECK_DC,
			      ext);
		break;
	    case EXT_MESSAGE_SECURITY_LABEL:
		ext_security (&qp -> security_label,
			      &qp -> security_label_crit,
			      EXT_MESSAGE_SECURITY_LABEL,
			      ext);
		break;
	    default:
		PP_NOTICE (("Unknown global extension type %d", n));
		/* fall */
	    case EXT_CONTENT_CORRELATOR:
		ep = flatten_ext (ext);
		for (epp = &qp -> per_message_extensions; *epp;
		     epp = &(*epp) -> ext_next)
			continue;
		*epp = ep;
		break;

	}
}

static void ext_ora (qp, ext)
Q_struct *qp;
struct type_MTA_ExtensionField *ext;
{
	struct type_Extensions_OriginatorReturnAddress *ora;
	OR_ptr or;
	char	buf[BUFSIZ];

	PP_PDU (print_Extensions_OriginatorReturnAddress,
		ext -> value, "Extensions.OriginatorReturnAddress",
		PDU_READ);

	if (decode_Extensions_OriginatorReturnAddress (ext -> value, 1,
						       NULLIP, NULLVP,
						       &ora) == NOTOK)
		adios (NULLCP, "Can't parse originator return address [%s]",
		       PY_pepy);

	or = do_or_address (ora -> standard__attributes,
			    ora -> domain__defined__attributes,
			    ora -> extension__attributes);
	or_or2std (or, buf, 0);
	or_free (or);

	qp -> originator_return_address = fn_new (buf, NULLCP);

	qp -> originator_return_address_crit = pe2crit (ext -> criticality,
							EXT_ORIGINATOR_RETURN_ADDRESS_DC);
	free_Extensions_OriginatorReturnAddress (ora);
}

static void ext_dlexph (qp, ext)
Q_struct	*qp;
struct type_MTA_ExtensionField *ext;
{
	struct type_Extensions_DLExpansionHistory *dlh, *dlhp;
	DLHistory *dp;

	PP_PDU (print_Extensions_DLExpansionHistory, ext -> value,
		"Extensions.DLExpansionHistory", PDU_READ);

	if (decode_Extensions_DLExpansionHistory (ext -> value, 1,
						  NULLIP, NULLVP,
						  &dlh) == NOTOK)
		adios (NULLCP, "Can't parse DLExpansionHistory value [%s]",
		       PY_pepy);
	for (dlhp = dlh; dlhp; dlhp = dlhp -> next) {
		dp = ext_decode_dlh (dlhp -> DLExpansion);
		dlh_add (&qp -> dl_expansion_history, dp);
	}
	qp -> dl_expansion_history_crit = pe2crit (ext -> criticality,
						   EXT_DL_EXPANSION_HISTORY_DC);
	free_Extensions_DLExpansionHistory (dlh);
}

static DLHistory *ext_decode_dlh (dlp)
struct type_Extensions_DLExpansion *dlp;
{
	char	buf[BUFSIZ];
	UTC	ut;
	OR_ptr	or;
	DLHistory *dp;

	load_time (&ut, dlp -> dl__expansion__time);
	or = do_or_address (dlp -> address -> standard__attributes,
			    dlp -> address -> domain__defined,
			    dlp -> address -> extension__attributes);
	or_or2std (or, buf, 0);
	or_free (or);

	dp = dlh_new (buf, NULLCP, ut);
	free ((char *)ut);
	return dp;
}

static void decode_ext_time (utc, genp)
UTC	*utc;
struct type_UNIV_UTCTime *genp;
{
	load_time (utc, genp);
}


static void ext_inttrace (trace, ext)
Trace	**trace;
struct type_MTA_ExtensionField *ext;
{
	struct type_Extensions_InternalTraceInformation *intt, *ip;

	PP_PDU (print_Extensions_InternalTraceInformation,
		ext -> value, "Extension.InternalTraceInformation",
		PDU_READ);

	if (decode_Extensions_InternalTraceInformation (ext -> value, 1,
							NULLIP, NULLVP,
							&intt) == NOTOK)
		adios (NULLCP, "Can't parse InternalTraceInformation [%s]",
		       PY_pepy);

	for (ip = intt; ip; ip = ip -> next) {
		struct type_Extensions_InternalTraceInformationElement *te;
		struct type_Extensions_MTASuppliedInformation *msi;
		Trace *tp;

		te = ip -> InternalTraceInformationElement;
		tp = trace_new ();
		load_gdi (&tp -> trace_DomId,
			  te -> global__domain__identifier);
		tp -> trace_mta = qb2str (te -> mta__name);
		msi = te -> mta__supplied__information;
		if (msi -> arrival__time)
			load_time (&tp -> trace_DomSinfo.dsi_time,
				   msi -> arrival__time);
		if (msi -> routing__action)
			tp -> trace_DomSinfo.dsi_action =
				msi -> routing__action -> parm;
		if (msi -> deferred__time)
			load_time (&tp -> trace_DomSinfo.dsi_deferred,
				   msi -> deferred__time);
		if (msi -> other__actions) {
			if (bit_ison (msi -> other__actions,
				      bit_MTA_OtherActions_redirected))
				tp -> trace_DomSinfo.dsi_other_actions |=
					ACTION_REDIRECTED;
			if (bit_ison (msi -> other__actions,
				      bit_MTA_OtherActions_dl__operation))
				tp -> trace_DomSinfo.dsi_other_actions |=
					ACTION_EXPANDED;
		}
		if (msi -> attempted) {
			switch (msi -> attempted -> offset) {
			    case choice_Extensions_1_mta:
				tp -> trace_DomSinfo.dsi_attempted_mta =
					qb2str (msi -> attempted -> un.mta);
				break;
			    case choice_Extensions_1_domain:
				load_gdi (&tp -> trace_DomSinfo.dsi_attempted_md,
					  msi -> attempted -> un.domain);
				break;
				

			    default:
				break;
			}
		}
		trace_add (trace, tp);
	}
}

static void decode_ext_pdm (value, genp)
int	*value;
PE	genp;
{
#define setbit(t,v) \
	(*value) |= (bit_ison(genp, (t)) ? (v) : 0)

	setbit (bit_Extensions_PhysicalDeliveryModes_ordinary__mail,
		AD_PM_ORD);
	setbit (bit_Extensions_PhysicalDeliveryModes_special__delivery,
		AD_PM_SPEC);
	setbit (bit_Extensions_PhysicalDeliveryModes_express__mail,
		AD_PM_EXPR);
	setbit (bit_Extensions_PhysicalDeliveryModes_counter__collection,
		AD_PM_CNT);
	setbit (bit_Extensions_PhysicalDeliveryModes_counter__collection__with__telephone__advice,
		AD_PM_CNT_PHONE);
	setbit (bit_Extensions_PhysicalDeliveryModes_counter__collection__with__telex__advice,
		AD_PM_CNT_TLX);
	setbit (bit_Extensions_PhysicalDeliveryModes_counter__collection__with__teletex__advice,
		AD_PM_CNT_TTX);
	setbit (bit_Extensions_PhysicalDeliveryModes_bureau__fax__delivery,
		AD_PM_CNT_BUREAU);
#undef setbit
}

static void decode_ext_pra (value, gen)
OID	*value;
OID	gen;
{
	*value = oid_cpy (gen);
}
static void decode_ext_rnfa (value, genp)
char	**value;
struct qbuf *genp;
{
	*value = qb2str (genp);
}

static void decode_ext_rdm (value, genp)
int	value[AD_RDM_MAX];
struct type_Extensions_RequestedDeliveryMethod *genp;
{
	int i;
	
	for (i = 0; i < AD_RDM_MAX && genp;
	     i++, genp = genp -> next)
		value[i] = genp -> element_Extensions_0;
}

do_global_ext_prf (n, ad, ext)
int	n;
ADDR	*ad;
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep, **epp;

	switch (n) {
	    case EXT_MESSAGE_TOKEN:
		ext_security (&ad -> ad_message_token,
			      &ad -> ad_message_token_crit,
			      EXT_MESSAGE_TOKEN_DC,
			      ext);
		break;
	    case EXT_CONTENT_INTEGRITY_CHECK:
		ext_security (&ad -> ad_content_integrity,
			      &ad -> ad_content_integrity_crit,
			      EXT_CONTENT_INTEGRITY_CHECK_DC,
			      ext);
		break;
	    case EXT_PROOF_OF_DELIVERY_REQUEST:
		decode_singleint (type_Extensions_ProofOfDeliveryRequest,
			       ad -> ad_proof_delivery,
			       ad -> ad_proof_delivery_crit,
			       EXT_PROOF_OF_DELIVERY_REQUEST_DC,
			       print_Extensions_ProofOfDeliveryRequest,
			       decode_Extensions_ProofOfDeliveryRequest,
			       free_Extensions_ProofOfDeliveryRequest,
			       "Extensions.ProofOfDeliveryRequest",
			       ext);
		break;
	    case EXT_PHYSICAL_FORWARDING_PROHIBITED:
		decode_singleint (type_Extensions_PhysicalForwardingProhibited,
			       ad -> ad_phys_forward,
			       ad -> ad_phys_forward_crit,
			       EXT_PHYSICAL_FORWARDING_PROHIBITED_DC,
			       print_Extensions_PhysicalForwardingProhibited,
			       decode_Extensions_PhysicalForwardingProhibited,
			       free_Extensions_PhysicalForwardingProhibited,
			       "Extensions.PhysicalForwardingProhibited",
			       ext);
		break;
	    case EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST:
		decode_singleint (type_Extensions_PhysicalForwardingAddressRequest,
				  ad -> ad_phys_fw_ad_req,
				  ad -> ad_phys_fw_ad_crit,
				  EXT_PHYSICAL_FORWARDING_ADDRESS_REQUEST_DC,
				  print_Extensions_PhysicalForwardingAddressRequest,
				  decode_Extensions_PhysicalForwardingAddressRequest,
				  free_Extensions_PhysicalForwardingAddressRequest,
				  "Extensions.PhysicalForwardingAddressRequest",
				  ext);
		break;
	    case EXT_REGISTERED_MAIL:
		decode_singleint (type_Extensions_RegisteredMailType,
				  ad -> ad_reg_mail_type,
				  ad -> ad_reg_mail_type_crit,
				  EXT_REGISTERED_MAIL_DC,
				  print_Extensions_RegisteredMailType,
				  decode_Extensions_RegisteredMailType,
				  free_Extensions_RegisteredMailType,
				  "Extensions.RegisteredMailType",
				  ext);
		break;
	    case EXT_PHYSICAL_DELIVERY_REPORT_REQUEST:
		decode_singleint (type_Extensions_PhysicalDeliveryReportRequest,
				  ad -> ad_pd_report_request,
				  ad -> ad_pd_report_request_crit,
				  EXT_PHYSICAL_DELIVERY_REPORT_REQUEST_DC,
				  print_Extensions_PhysicalDeliveryReportRequest,
				  decode_Extensions_PhysicalDeliveryReportRequest,
				  free_Extensions_PhysicalDeliveryReportRequest,
				  "Extensions.PhysicalDeliveryReportRequest",
				  ext);
		break;
	    case EXT_PHYSICAL_RENDITION_ATTRIBUTES:
		decode_extension (&ad -> ad_phys_rendition_attribs,
				  &ad -> ad_phys_rendition_attribs_crit,
				  EXT_PHYSICAL_RENDITION_ATTRIBUTES_DC,
				  print_Extensions_PhysicalRenditionAttributes,
				  decode_Extensions_PhysicalRenditionAttributes,
				  free_Extensions_PhysicalRenditionAttributes,
				  "Extensions.PhysicalRenditionAttributes",
				  decode_ext_pra,
				  ext);
		break;
	    case EXT_RECIPIENT_NUMBER_FOR_ADVICE:
		decode_extension (&ad -> ad_recip_number_for_advice,
				  &ad -> ad_recip_number_for_advice_crit,
				  EXT_RECIPIENT_NUMBER_FOR_ADVICE_DC,
				  print_Extensions_RecipientNumberForAdvice,
				  decode_Extensions_RecipientNumberForAdvice,
				  free_Extensions_RecipientNumberForAdvice,
				  "Extensions.RecipientNumberForAdvice",
				  decode_ext_rnfa,
				  ext);
		break;
	    case EXT_REQUESTED_DELIVERY_METHOD:
		decode_extension (ad -> ad_req_del,
				  &ad -> ad_req_del_crit,
				  EXT_REQUESTED_DELIVERY_METHOD_DC,
				  print_Extensions_RequestedDeliveryMethod,
				  decode_Extensions_RequestedDeliveryMethod,
				  free_Extensions_RequestedDeliveryMethod,
				  "Extensions.RequestedDeliveryMethod",
				  decode_ext_rdm,
				  ext);
		break;
	    case EXT_PHYSICAL_DELIVERY_MODES:
		decode_extension (&ad -> ad_phys_modes,
				  &ad -> ad_phys_modes_crit,
				  EXT_PHYSICAL_DELIVERY_MODES_DC,
				  print_Extensions_PhysicalDeliveryModes,
				  decode_Extensions_PhysicalDeliveryModes,
				  free_Extensions_PhysicalDeliveryModes,
				  "Extensions.PhysicalDeliveryModes",
				  decode_ext_pdm,
				  ext);
		break;
	    default:
		PP_NOTICE (("Unknown global extension type %d", n));
		/* fall */
	    case EXT_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT:
		ep = flatten_ext (ext);
		for (epp = &ad -> ad_per_recip_ext_list; *epp;
		     epp = &(*epp) -> ext_next)
			continue;
		*epp = ep;
		break;
	}
}

static int	pe2crit (pe, defcrit)
PE	pe;
int	defcrit;
{
	char	*str;
	int	len, n;

	if (pe == NULLPE)
		return defcrit;
	str = bitstr2strb (pe, &len);
	n = strb2int(str, len);
	free (str);
	return n;
}

do_global_repe_prf (n, dr, ext)
int	n;
DRmpdu *dr;
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep, **epp;

	switch (n) {
	    case EXT_INTERNAL_TRACE_INFORMATION:
		ext_inttrace (&dr -> dr_trace, ext);
		break;
	    case EXT_MESSAGE_SECURITY_LABEL:
		ext_security (&dr -> dr_security_label,
			      &dr -> dr_security_label_crit,
			      EXT_MESSAGE_SECURITY_LABEL_DC,
			      ext);
		break;
	    case EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK:
		ext_security (&dr -> dr_report_origin_auth_check,
			      &dr -> dr_report_origin_auth_check_crit,
			      EXT_REPORT_ORIGIN_AUTHENTICATION_CHECK_DC,
			      ext);
		break;
	    case EXT_REPORTING_MTA_CERTIFICATE:
		ext_security (&dr -> dr_reporting_mta_certificate,
			      &dr -> dr_reporting_mta_certificate_crit,
			      EXT_REPORTING_MTA_CERTIFICATE_DC,
			      ext);
		break;
	    case EXT_ORIGINATOR_AND_DL_EXPANSION_HISTORY:
	    case EXT_REPORT_DL_NAME:
	    default:
		ep = flatten_ext (ext);
		for (epp = &dr -> dr_per_envelope_extensions; *epp;
		     epp = &(*epp) -> ext_next)
			continue;
		*epp = ep;
		break;
	}		
}

do_global_cont_prf (n, dr, ext)
int	n;
DRmpdu *dr;
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep, **epp;

	switch (n) {
	    case EXT_CONTENT_CORRELATOR:
	    default:
		ep = flatten_ext (ext);
		for (epp = &dr -> dr_per_envelope_extensions; *epp;
		     epp = &(*epp) -> ext_next)
			continue;
		*epp = ep;
		break;
	}		
}

do_global_rr_prf (n, rr, ext)
int	n;
Rrinfo *rr;
struct type_MTA_ExtensionField *ext;
{
	Extension	*ep, **epp;

	switch (n) {
	    case EXT_RECIPIENT_CERTIFICATE:
		ext_security (&rr -> rr_report_origin_authentication_check,
			      &rr -> rr_report_origin_authentication_check_crit,
			      EXT_RECIPIENT_CERTIFICATE_DC,
			      ext);
		break;

	    case EXT_REDIRECTION_HISTORY:
	    case EXT_PHYSICAL_FORWARDING_ADDRESS:
	    case EXT_PROOF_OF_DELIVERY:
	    default:
		ep = flatten_ext (ext);
		for (epp = &rr -> rr_per_recip_extensions; *epp;
		     epp = &(*epp) -> ext_next)
			continue;
		*epp = ep;
		break;
	}		
}