|
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