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 a

⟦818e50cd7⟧ TextFile

    Length: 11871 (0x2e5f)
    Types: TextFile
    Names: »ad_mgt.c«

Derivation

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

TextFile

/* ad_mgt.c: address management routines */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Src/submit/RCS/ad_mgt.c,v 5.0 90/09/20 16:22:25 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Src/submit/RCS/ad_mgt.c,v 5.0 90/09/20 16:22:25 pp Exp Locker: pp $
 *
 * $Log:	ad_mgt.c,v $
 * Revision 5.0  90/09/20  16:22:25  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "util.h"
#include <varargs.h>
#include "retcode.h"
#include <isode/cmd_srch.h>
#include "q.h"
#include "dr.h"
#include "ap.h"

extern Q_struct		Qstruct;
extern CHAN             *ch_inbound;
extern int		mgt_adtype;
extern int		accept_all;
extern char		*mgt_inhost;
extern char             *username;
extern void		x400_add(), rfc822_add(), err_abrt(), pro_reply();


/* -- globals -- */
ADDR                    *ad_recip;       /* recipient list */
ADDR                    *ad_originator;  /* address of sender */
int                     ad_extend;
int			adr_count = 0;


/* -- local routines -- */
int			rplose();
int			validate_sender();
void			ad_init();
void			validate_recip();

static int		bad_address();
static int		do_recip_more();
static int		recip_gather();
static int		recip_parse();
static void		ad_print();
static void		do_sender_dr_outchan();
static void		set_return_chan();
static	void		fixup_badsender ();



/* ---------------------  Begin  Routines  -------------------------------- */




void ad_init()   /* -- initialise the linked list -- */
{
	PP_TRACE (("submit/ad_init()"));

	adr_count = 0;
	if (ad_recip != NULLADDR)               adr_tfree (ad_recip);
	if (ad_originator != NULLADDR)          adr_tfree (ad_originator);
	ad_originator                           = NULLADDR;
	ad_recip                                = NULLADDR;
	ad_extend                               = 1;
}




int validate_sender()   /* -- read in sender and validate -- */
{
	int             retval;
	RP_Buf          rpbuf,
			*rp = &rpbuf;
	ADDR            *ad = NULLADDR;

	PP_TRACE (("submit/validate_sender (%d)", mgt_adtype));
	rp -> rp_val = RP_OK;

	if ((retval = rd_adr (stdin, TRUE, &ad)) == RP_DONE)
		err_abrt (retval, "Error reading sender");


	if (rp_isbad (retval)) {
		if (ad == NULLADDR)
			err_abrt (RP_EOF, "No sender given");

		err_abrt (retval, "Invalid sender '%s'",
			  isstr (ad -> ad_value) ? ad -> ad_value : "(none)");
	}


	ad -> ad_resp             = FALSE;
	ad -> ad_status           = AD_STAT_DONE;
	ad -> ad_extension        = NULL;
	ad -> ad_no               = NULL;
	ad -> ad_type             = mgt_adtype;
	ad_extend               = 1;   /* -- reset -- */



	if (Qstruct.msgtype == MT_DMPDU)
		ad -> ad_resp	= TRUE;



	/* --- *** --- 
	if bad sender address && MT_UMPDU && mode == accept all 
		then	Accept a bad sender BUT generate a non DR back 
			to that bad address. 

	if bad sender address && MT_DMPDU && mode == accept all 
		then	Reject the message and the incomming channel 
			should resubmit it to postmaster.

	else abort.
	NO FOR THE TIME BEING ALWAYS ABORT.
	--- *** ---  */

	if (rp_isbad (retval = ad_parse (ad, rp, ch_inbound -> ch_ad_order))) {
		if (accept_all && Qstruct.msgtype == MT_UMPDU
		    && ad -> ad_r400adr && ad -> ad_r822adr) {
			ad -> ad_status = AD_STAT_DRREQUIRED;
		}
		else {
			PP_LOG(LLOG_EXCEPTIONS,
				("Unparseable sender '%s'", ad->ad_value));
			err_abrt ((int)rp -> rp_val, rp -> rp_line);
		}
	}

	PP_NOTICE (("Sender '%s'", ad -> ad_value));


	/* -- Patch up the local x400adr -- */

	if (ad -> ad_type == AD_822_TYPE) {
		x400_add (ad);
		if (ch_inbound -> ch_access == CH_MTS &&
		    tb_checkauth (ad -> ad_r822adr, ch_inbound,
				  username, NULLCP) == NOTOK)
			err_abrt (RP_USER,
				  "User %s not allowed to submit as %s",
				  ad -> ad_r822adr, username);
	}
	else if (ad -> ad_type == AD_X400_TYPE) {
		rfc822_add (ad);
		if (ch_inbound -> ch_access == CH_MTS &&
		    tb_checkauth (ad -> ad_r400adr, ch_inbound,
				  username, NULLCP) == NOTOK)
			err_abrt (RP_USER,
				  "User %s not allowed to submit as %s",
				  ad -> ad_r400adr , username);
	}



	/* --- *** ---
	if ordinary message then bind originator to ch_chan_out.
	Otherwise it is an incomming X400 DR and the orig is already bound.
	So need to calculate a reformatter list.
	E.g a DR from the ITL to arpa_mhs@pyr1.cs.ucl.ac.uk should not
	have ad -> outchan pointing to x400out but to smtp, with
	outhost=pyr1.cs.ucl.ac.uk. Then a check is done on the smtp
	channel and that outchan is then taken as the one to send the
	DR to.
	 --- *** --- */

	if (Qstruct.msgtype == MT_DMPDU) {
	    ad -> ad_resp = FALSE;
    	    do_sender_dr_outchan (ad);
	    ad_originator = ad;
	    return RP_OK;
	}

	set_return_chan (ad, ch_inbound, NULLCP);
	if (ad -> ad_status == AD_STAT_DRREQUIRED &&
	    ad -> ad_type == AD_822_TYPE)
		fixup_badsender (ad);
	ad_originator = ad;
	return (RP_OK);
}


static void fixup_badsender (ad)
ADDR	*ad;
{
	AP_ptr local, domain, route, new = NULLAP, tree;
	char	*cp;

	if (ad -> ad_outchan == NULL ||
	    ad -> ad_outchan -> li_mta == NULLCP)
		err_abrt (RP_MECH, "No outchan set for bad sender!");

	ap_s2p (ad -> ad_r822adr, &tree, (AP_ptr *)0, (AP_ptr *)0,
		&local, &domain, &route);

	if (route == NULLAP)
		route = ap_new (AP_DOMAIN, ad -> ad_outchan -> li_mta);
	else {
		new = ap_new (AP_DOMAIN, ad -> ad_outchan -> li_mta);
		new -> ap_next = route;
		route = new;
	}

	cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, route);
	free (ad -> ad_r822adr);
	ap_sqdelete (tree, NULLAP);
	if (new)
		ap_free (new);
	ad -> ad_r822adr = cp;
}

static void set_return_chan (ad, chan, host)
ADDR 	*ad;
CHAN	*chan;
char	*host;
{
	LIST_RCHAN 	*ch;
	char		*in_host;

	if (chan == NULLCHAN || ad == NULLADDR) { 
		PP_LOG (LLOG_EXCEPTIONS, 
			("set_return_chan is called with NULL fields"));
		return;
	}

	PP_TRACE (("set_return_chan (chan='%s', host='%s', drchan='%s')", 
		chan -> ch_name ? chan -> ch_name : "", 
		host ? host : "", 
		chan -> ch_chan_out ? chan -> ch_chan_out : ""));

	if (host != NULLCP && isstr (host))
		in_host = host; 
	else 
		in_host = mgt_inhost;

	if (isstr (ch_inbound -> ch_chan_out) && isstr (chan -> ch_chan_out))
		ch = list_rchan_new (in_host, chan -> ch_chan_out);
	else
		ch = list_rchan_new (in_host, chan -> ch_name);

	if (ad -> ad_outchan)
		list_rchan_free (ad -> ad_outchan);
	ad -> ad_outchan = ch;
}


static void do_sender_dr_outchan (ad)
ADDR    *ad;
{
	PP_TRACE (("do_sender_dr_outchan (%s)", ad -> ad_value));

	if (ad -> ad_outchan == NULLIST_RCHAN ||
	    ad -> ad_outchan -> li_chan == NULLCHAN) {
		PP_LOG (LLOG_EXCEPTIONS, ("DR has no channel"));
		return;
	}

	if (fillin_orig_outchan (ad) == NOTOK)
		err_abrt (RP_BAD, "Can't find channel for DR");

	set_return_chan (ad, ad -> ad_outchan -> li_chan,
			ad -> ad_outchan -> li_mta);
	list_rchan_free (ad -> ad_fmtchan);
	ad -> ad_fmtchan = NULL;
	return;
}


/* -- read recip, & validate before adding to list. -- */
void validate_recip()		
{
	int     retval;
	RP_Buf  rbuf;
	RP_Buf  *rp = &rbuf;

	PP_TRACE (("submit/validate_recip()"));

	if (rp_isbad (retval = recip_gather(rp)))
		err_abrt (retval, rp -> rp_line);

	if (ad_recip == NULLADDR)
		err_abrt (RP_USER, "No valid addresses found");

	ad_print (ad_recip);
}

static int bad_address (ad, rp)
ADDR	*ad;
RP_Buf	*rp;
{
	int	retval = rp -> rp_val;

	if (rp_gbval (retval) == RP_BTNO &&
	    retval != RP_BHST &&
	    retval != RP_DHST)
			return retval;	/* temp failure */

	if (accept_all && Qstruct.msgtype != MT_DMPDU) {
		ad -> ad_parse_stat = retval;
		ad -> ad_status = AD_STAT_DRREQUIRED; 
		ad -> ad_reason =  DRR_UNABLE_TO_TRANSFER; 
		ad -> ad_diagnostic = DRD_UNRECOGNISED_OR; 
		ad -> ad_add_info = strdup (rp -> rp_line);
		pro_reply (RP_AOK,
			   "Recipient failed to parse: DR to be generated");
	}
	else if (accept_all && Qstruct.msgtype == MT_DMPDU) {
		pro_reply (retval, rp -> rp_line);
	}
	else {
		ad -> ad_resp = FALSE;
		ad -> ad_status = AD_STAT_DONE;
		pro_reply (retval, rp -> rp_line);
	}

	return RP_OK;
}


/* ---------------------  Static  Routines  ------------------------------- */




/* --- *** Start Description *** ---


Following Recipient Static Routines:

	- Reads a list of addresses.
	- For each Recipient address:
		- Parse & Normalise
		- Calculate the reformatter list
		- Add to a new list.


--- *** End Description *** --- */




static int recip_gather(rp)
RP_Buf *rp;
{
	int             retval;
	ADDR            *ad;

	PP_TRACE (("submit/recip_gather()"));

	for (;;) {

		ad = NULLADDR;

		retval = rd_adr (stdin, TRUE, &ad);

		switch (retval) {
		    case RP_OK:
			retval = do_recip_more (ad, rp);
			if (rp_isbad (retval))
				return (retval);
			break;

		    case RP_DONE:
			return RP_DONE;

		    default:
			PP_TRACE (("submit/recip_gather(def=%s)",
				 rp_valstr (retval)));
			return rplose (rp, retval, "Error reading address");
		}

	}                       /* -- end of for -- */
}




static int do_recip_more (ad, rp)
ADDR    *ad;
RP_Buf  *rp;
{
	int     retval;


	PP_TRACE (("do_recip_more (number='%d' status='%d' resp='%d')",
		ad -> ad_no, ad -> ad_status, ad -> ad_resp));

	ad -> ad_no = ad_extend++;
	if (ad -> ad_extension == 0)
		ad -> ad_extension = ad -> ad_no;
	ad -> ad_type = mgt_adtype;

	switch (ad -> ad_status) {
	case AD_STAT_DRWRITTEN:
		if (ad -> ad_resp == FALSE) {
			set_return_chan (ad, ch_inbound, NULLCP);
			pro_reply (RP_AOK, "DR '%s'", ad -> ad_value);
			break;
		}
		else if (ad -> ad_no != DR_FILENO_DEFAULT)
			ad -> ad_status = AD_STAT_DONE;
		/* fall */

	case AD_STAT_PEND:
		retval = recip_parse (ad, rp);
		if (rp_isbad (retval)) {
			if (rp_isbad (bad_address (ad, rp)))
				return retval;
			break;
		}

		pro_reply (RP_AOK, "Nice address");
		break;

	default:
		pro_reply (RP_AOK, "Skip '%s'", ad -> ad_value);
		break;

	}

	adr_add (&ad_recip, ad);
	adr_count ++;
	return (RP_OK);
}


static int recip_parse (ad, rp)
ADDR    *ad;
RP_Buf  *rp;
{
	int     retval;

	PP_TRACE (("submit/recip_parse()"));

	retval = ad_parse (ad, rp, ch_inbound  -> ch_ad_order);

	if (rp_isbad (retval) && ad -> ad_orig_req_alt != NULLCP) {
		PP_TRACE(("attempting ad_orig_req_alt '%s'", 
			  ad -> ad_orig_req_alt));
		if (ad -> ad_value != NULLCP) free (ad -> ad_value);
		ad -> ad_value = strdup (ad -> ad_orig_req_alt);
		if (ad -> ad_r400adr != NULLCP) {
			free(ad -> ad_r400adr);
			ad -> ad_r400adr = NULLCP;
		}
		if (ad -> ad_r822adr != NULLCP) {
			free(ad -> ad_r822adr);
			ad -> ad_r822adr = NULLCP;
		}
		retval = ad_parse (ad, rp, ch_inbound -> ch_ad_order);
	}

	if (!accept_all && rp_isbad (retval)) {
		PP_TRACE (("recip_parse failed (%s %s)",
			   rp_valstr((int)rp -> rp_val),
			   rp -> rp_line));
		return retval;
	}


	/* -- Patch up the local x400adr -- */

	if (ad -> ad_r400adr == NULLCP && ad -> ad_type == AD_822_TYPE)
		x400_add (ad);

	if (ad -> ad_r822adr == NULLCP && ad -> ad_type == AD_X400_TYPE)
		rfc822_add (ad);

	return (retval);
}




static void ad_print (ad)
ADDR           *ad;
{
	if (ad == NULLADDR)
		return;

	PP_NOTICE (("Recipient '%s'  mta '%s'",
		ad -> ad_type == AD_X400_TYPE ? ad -> ad_r400adr :
		ad -> ad_type == AD_822_TYPE  ? ad -> ad_r822adr : ad->ad_value,
		(ad -> ad_outchan && ad -> ad_outchan -> li_mta) ?
				ad -> ad_outchan -> li_mta : "<unknown>"));

	ad_print (ad -> ad_next);
}



#ifdef lint
/* VARARGS3 */
int rplose (rp, val, str)
RP_Buf  *rp;
int     val;
char    *str;
{
	return rplose (rp, val, str);
}
#else
int rplose (va_alist)
va_dcl
{
	va_list ap;
	RP_Buf  *rp;
	int     val;
	char    buf[BUFSIZ];

	va_start (ap);

	rp = va_arg (ap, RP_Buf *);
	val = va_arg (ap, int);

	_asprintf (buf, NULLCP, ap);

	PP_LOG (LLOG_EXCEPTIONS, ("rplose (%s, '%s')",
				  rp_valstr (val), buf));

	rp -> rp_val = val;
	(void) strncpy (rp -> rp_line, buf, sizeof (rp -> rp_line) - 1);

	va_end (ap);

	return val;
}
#endif