Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  transport.c

  Sprache: C
 

/*++
/* NAME
/* transport 3
/* SUMMARY
/* transport mapping
/* SYNOPSIS
/* #include "transport.h"
/*
/* TRANSPORT_INFO *transport_pre_init(maps_name, maps)
/* const char *maps_name;
/* const char *maps;
/*
/* void transport_post_init(info)
/* TRANSPORT_INFO *info;
/*
/* int transport_lookup(info, address, rcpt_domain, channel, nexthop)
/* TRANSPORT_INFO *info;
/* const char *address;
/* const char *rcpt_domain;
/* VSTRING *channel;
/* VSTRING *nexthop;
/*
/* void transport_free(info);
/* TRANSPORT_INFO * info;
/* DESCRIPTION
/* This module implements access to the table that maps transport
/* user@domain addresses to (channel, nexthop) tuples.
/*
/* transport_pre_init() performs initializations that should be
/* done before the process enters the chroot jail, and
/* before calling transport_lookup().
/*
/* transport_post_init() can be invoked after entering the chroot
/* jail, and must be called before calling transport_lookup().
/*
/* transport_lookup() finds the channel and nexthop for the given
/* domain, and returns 1 if something was found. Otherwise, 0
/* is returned.
/* DIAGNOSTICS
/* info->transport_path->error is non-zero when the lookup
/* should be tried again.
/* SEE ALSO
/* maps(3), multi-dictionary search
/* strip_addr(3), strip extension from address
/* transport(5), format of transport map
/* CONFIGURATION PARAMETERS
/* transport_maps, names of maps to be searched.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <string.h>

/* Utility library. */

#include <msg.h>
#include <stringops.h>
#include <mymalloc.h>
#include <vstring.h>
#include <split_at.h>
#include <dict.h>
#include <events.h>

/* Global library. */

#include <strip_addr.h>
#include <mail_params.h>
#include <mail_addr_find.h>
#include <match_parent_style.h>
#include <mail_proto.h>

/* Application-specific. */

#include "transport.h"

static int transport_match_parent_style;

#define STR(x) vstring_str(x)

static void transport_wildcard_init(TRANSPORT_INFO *);

/* transport_pre_init - pre-jail initialization */

TRANSPORT_INFO *transport_pre_init(const char *transport_maps_name,
               const char *transport_maps)
{
    TRANSPORT_INFO *tp;

    tp = (TRANSPORT_INFO *) mymalloc(sizeof(*tp));
    tp->transport_path = maps_create(transport_maps_name, transport_maps,
         DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
         | DICT_FLAG_NO_REGSUB
         | DICT_FLAG_UTF8_REQUEST);
    tp->wildcard_channel = tp->wildcard_nexthop = 0;
    tp->wildcard_errno = 0;
    tp->expire = 0;
    return (tp);
}

/* transport_post_init - post-jail initialization */

void    transport_post_init(TRANSPORT_INFO *tp)
{
    transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS);
    transport_wildcard_init(tp);
}

/* transport_free - destroy transport info */

void    transport_free(TRANSPORT_INFO *tp)
{
    if (tp->transport_path)
 maps_free(tp->transport_path);
    if (tp->wildcard_channel)
 vstring_free(tp->wildcard_channel);
    if (tp->wildcard_nexthop)
 vstring_free(tp->wildcard_nexthop);
    myfree((void *) tp);
}

/* update_entry - update from transport table entry */

static void update_entry(const char *new_channel, const char *new_nexthop,
            const char *rcpt_domain, VSTRING *channel,
            VSTRING *nexthop)
{

    /*
     * :[nexthop] means don't change the channel, and don't change the
     * nexthop unless a non-default nexthop is specified. Thus, a right-hand
     * side of ":" is the transport table equivalent of a NOOP.
     */

    if (*new_channel == 0) {   /* :[nexthop] */
 if (*new_nexthop != 0)
     vstring_strcpy(nexthop, new_nexthop);
    }

    /*
     * transport[:[nexthop]] means change the channel, and reset the nexthop
     * to the default unless a non-default nexthop is specified.
     */

    else {
 vstring_strcpy(channel, new_channel);
 if (*new_nexthop != 0)
     vstring_strcpy(nexthop, new_nexthop);
 else if (strcmp(STR(channel), MAIL_SERVICE_ERROR) != 0
   && strcmp(STR(channel), MAIL_SERVICE_RETRY) != 0)
     vstring_strcpy(nexthop, rcpt_domain);
 else
     vstring_strcpy(nexthop, "Address is undeliverable");
    }
}

/* parse_transport_entry - parse transport table entry */

static void parse_transport_entry(const char *value, const char *rcpt_domain,
              VSTRING *channel, VSTRING *nexthop)
{
    char   *saved_value;
    const char *host;

#define FOUND  1
#define NOTFOUND 0

    /*
     * It would be great if we could specify a recipient address in the
     * lookup result. Unfortunately, we cannot simply run the result through
     * a parser that recognizes "transport:user@domain" because the lookup
     * result can have arbitrary content (especially in the case of the error
     * mailer).
     */

    saved_value = mystrdup(value);
    host = split_at(saved_value, ':');
    update_entry(saved_value, host ? host : "", rcpt_domain, channel, nexthop);
    myfree(saved_value);
}

/* transport_wildcard_init - (re) initialize wild-card lookup result */

static void transport_wildcard_init(TRANSPORT_INFO *tp)
{
    VSTRING *channel = vstring_alloc(10);
    VSTRING *nexthop = vstring_alloc(10);
    const char *value;

    /*
     * Both channel and nexthop may be zero-length strings. Therefore we must
     * use something else to represent "wild-card does not exist". We use
     * null VSTRING pointers, for historical reasons.
     */

    if (tp->wildcard_channel)
 vstring_free(tp->wildcard_channel);
    if (tp->wildcard_nexthop)
 vstring_free(tp->wildcard_nexthop);

    /*
     * Technically, the wildcard lookup pattern is redundant. A static map
     * (keys always match, result is fixed string) could achieve the same:
     * 
     * transport_maps = hash:/etc/postfix/transport static:xxx:yyy
     * 
     * But the user interface of such an approach would be less intuitive. We
     * tolerate the continued existence of wildcard lookup patterns because
     * of human interface considerations.
     */

#define WILDCARD "*"
#define FULL  0
#define PARTIAL  DICT_FLAG_FIXED

    if ((value = maps_find(tp->transport_path, WILDCARD, FULL)) != 0) {
 parse_transport_entry(value, "", channel, nexthop);
 tp->wildcard_errno = 0;
 tp->wildcard_channel = channel;
 tp->wildcard_nexthop = nexthop;
 if (msg_verbose)
     msg_info("wildcard_{chan:hop}={%s:%s}",
       vstring_str(channel), vstring_str(nexthop));
    } else {
 tp->wildcard_errno = tp->transport_path->error;
 vstring_free(channel);
 vstring_free(nexthop);
 tp->wildcard_channel = 0;
 tp->wildcard_nexthop = 0;
    }
    tp->expire = event_time() + 30;  /* XXX make configurable */
}

/* transport_lookup - map a transport domain */

int     transport_lookup(TRANSPORT_INFO *tp, const char *addr,
            const char *rcpt_domain,
            VSTRING *channel, VSTRING *nexthop)
{
    char   *ratsign = 0;
    const char *value;

#define STREQ(x,y) (strcmp((x), (y)) == 0)
#define DISCARD_EXTENSION ((char **) 0)

    /*
     * The null recipient is rewritten to the local mailer daemon address.
     */

    if (*addr == 0) {
 msg_warn("transport_lookup: null address - skipping table lookup");
 return (NOTFOUND);
    }

    /*
     * Look up the full and extension-stripped address, then match the domain
     * and subdomains. Try the external form before the backwards-compatible
     * internal form.
     */

#define LOOKUP_STRATEGY \
 (MA_FIND_FULL | MA_FIND_NOEXT | MA_FIND_DOMAIN | \
 (transport_match_parent_style == MATCH_FLAG_PARENT ? \
  MA_FIND_PDMS : MA_FIND_PDDMDS))

    if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0)
 msg_panic("transport_lookup: bad address: \"%s\"", addr);

    if ((value = mail_addr_find_strategy(tp->transport_path, addr, (char **) 0,
      LOOKUP_STRATEGY)) != 0) {
 parse_transport_entry(value, rcpt_domain, channel, nexthop);
 return (FOUND);
    }
    if (tp->transport_path->error != 0)
 return (NOTFOUND);

    /*
     * Fall back to the wild-card entry.
     */

    if (tp->wildcard_errno || event_time() > tp->expire)
 transport_wildcard_init(tp);
    if (tp->wildcard_errno) {
 tp->transport_path->error = tp->wildcard_errno;
 return (NOTFOUND);
    } else if (tp->wildcard_channel) {
 update_entry(STR(tp->wildcard_channel), STR(tp->wildcard_nexthop),
       rcpt_domain, channel, nexthop);
 return (FOUND);
    }

    /*
     * We really did not find it.
     */

    return (NOTFOUND);
}

#ifdef TEST

 /*
  * Proof-of-concept test program. Read an address from stdin, and spit out
  * the lookup result.
  */


#include <string.h>

#include <mail_conf.h>
#include <vstream.h>
#include <vstring_vstream.h>

static NORETURN usage(const char *progname)
{
    msg_fatal("usage: %s [-v] database", progname);
}

int     main(int argc, char **argv)
{
    VSTRING *buffer = vstring_alloc(100);
    VSTRING *channel = vstring_alloc(100);
    VSTRING *nexthop = vstring_alloc(100);
    TRANSPORT_INFO *tp;
    char   *bp;
    char   *addr_field;
    char   *rcpt_domain;
    char   *expect_channel;
    char   *expect_nexthop;
    int     status;
    int     ch;
    int     errs = 0;

    /*
     * Parse JCL.
     */

    while ((ch = GETOPT(argc, argv, "v")) > 0) {
 switch (ch) {
 case 'v':
     msg_verbose++;
     break;
 default:
     usage(argv[0]);
 }
    }
    if (argc != optind + 1)
 usage(argv[0]);

    /*
     * Initialize.
     */

#define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0)

    mail_conf_read();    /* XXX eliminate dependency. */
    UPDATE(var_rcpt_delim, "+");
    UPDATE(var_mydomain, "localdomain");
    UPDATE(var_myorigin, "localhost.localdomain");
    UPDATE(var_mydest, "localhost.localdomain");

    tp = transport_pre_init("transport map", argv[optind]);
    transport_post_init(tp);

    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
 bp = STR(buffer);

 /*
  * Parse the input and expectations. XXX We can't expect empty
  * fields, so require '-' instead.
 */

 if ((addr_field = mystrtok(&bp, ":")) == 0)
     msg_fatal("no address field");
 if ((rcpt_domain = strrchr(addr_field, '@')) == 0)
     msg_fatal("no recipient domain");
 rcpt_domain += 1;
 expect_channel = mystrtok(&bp, ":");
 expect_nexthop = mystrtok(&bp, ":");
 if ((expect_channel != 0) != (expect_nexthop != 0))
     msg_fatal("specify both channel and nexthop, or specify neither");
 if (expect_channel) {
     if (strcmp(expect_channel, "-") == 0)
  *expect_channel = 0;
     if (strcmp(expect_nexthop, "-") == 0)
  *expect_nexthop = 0;
     vstring_strcpy(channel, "DEFAULT");
     vstring_strcpy(nexthop, rcpt_domain);
 }
 if (mystrtok(&bp, ":") != 0)
     msg_fatal("garbage after nexthop field");

 /*
  * Lookups.
 */

 status = transport_lookup(tp, addr_field, rcpt_domain,
      channel, nexthop);

 /*
  * Enforce expectations.
 */

 if (expect_nexthop && status) {
     vstream_printf("%s:%s -> %s:%s \n",
      addr_field, rcpt_domain,
      STR(channel), STR(nexthop));
     vstream_fflush(VSTREAM_OUT);
     if (strcmp(expect_channel, STR(channel)) != 0) {
  msg_warn("expect channel '%s' but got '%s'",
    expect_channel, STR(channel));
  errs = 1;
     }
     if (strcmp(expect_nexthop, STR(nexthop)) != 0) {
  msg_warn("expect nexthop '%s' but got '%s'",
    expect_nexthop, STR(nexthop));
  errs = 1;
     }
 } else if (expect_nexthop && !status) {
     vstream_printf("%s:%s -> %s\n", addr_field, rcpt_domain,
      tp->transport_path->error ?
      "(try again)" : "(not found)");
     vstream_fflush(VSTREAM_OUT);
     msg_warn("expect channel '%s' but got none", expect_channel);
     msg_warn("expect nexthop '%s' but got none", expect_nexthop);
     errs = 1;
 } else if (!status) {
     vstream_printf("%s:%s -> %s\n", addr_field, rcpt_domain,
      tp->transport_path->error ?
      "(try again)" : "(not found)");
 }
    }
    transport_free(tp);
    vstring_free(nexthop);
    vstring_free(channel);
    vstring_free(buffer);
    exit(errs != 0);
}

#endif

Messung V0.5 in Prozent
C=74 H=95 G=84

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142