|
|
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 a
Length: 11871 (0x2e5f)
Types: TextFile
Names: »ad_mgt.c«
└─⟦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«
/* 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