20150112
- Support for UTF-8 casefolding in match_lists. Instead of
- using strcasecmp(), casefold all string constant patterns
- during initialization, and casefold a search string at the
- beginning of the search, and use strcmp() for comparison.
- Files: util/casefold.c util/dict.h, util/dict_utf8.c,
+ Infrastructure: support for UTF-8 casefolding in match_lists.
+ Instead of using strcasecmp(), casefold all fixed-string
+ patterns during initialization, casefold a search string
+ at the beginning of the search, and use strcmp() for
+ comparison. Files: util/casefold.c util/dict.h, util/dict_utf8.c,
util/match_list.c, util/match_list.h, util/match_ops.c,
util/stringops.h, global/addr_match_list.c, global/domain_list.c,
global/namadr_list.c, global/string_list.c.
+
+20150113
+
+ Cleanup: show the configuration parameter name in error
+ messages while parsing or searching match_list-based features
+ such as mydestination, relay_domains and a few dozen more.
+ Files: cleanup/cleanup_init.c, flush/flush.c,
+ global/addr_match_list.c, global/debug_peer.c,
+ global/domain_list.c, global/flush_clnt.c,
+ global/match_parent_style.c, global/namadr_list.c,
+ global/resolve_local.c, global/string_list.c, global/user_acl.[hc],
+ postdrop/postdrop.c, postqueue/postqueue.c,
+ postscreen/postscreen.c, qmqpd/qmqpd.c, sendmail/sendmail.c.,
+ smtp/smtp.c, smtp/smtp_sasl_glue.c, smtpd/smtpd.c,
+ smtpd/smtpd_check.c, trivial-rewrite/resolve.c,
+ util/match_list.[hc], util/match_ops.c.
+
+ Cleanup: apply printable() to all bounce(8) service
+ string-valued protocol fields. File: bounce/bounce.c.
+
+ Apparenly the UCI 4.8 ucasemap_utf8FoldCase() function does
+ not complain about UTF-8 syntax errors, so we add our own
+ redundant check. File: util/casefold.c.
Things to do after the stable release:
- Add context argument for better match_list diagnostics.
-
- Expose UTF8 flag in server_acl API. Some applications such
- as postscreen don't need UTF8 support.
-
- Expose UTF8 flag in match_list API. Some applications
- such as address lists don't need UTF8 support.
-
- Implement UTF8 casefolding in match_list for non-table
- patterns.
-
UTF8 DNS[BW]L domain name.
Consolidate maps flags in mail_params.h instead of having
msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
return (-1);
}
- printable(STR(dsn_envid), '?');
+ VS_NEUTER(encoding);
+ VS_NEUTER(sender);
+ VS_NEUTER(dsn_envid);
if (msg_verbose)
msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x",
myname, flags, service_name, STR(queue_name), STR(queue_id),
msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
return (-1);
}
- printable(STR(dsn_envid), '?');
+ VS_NEUTER(encoding);
+ VS_NEUTER(sender);
+ VS_NEUTER(dsn_envid);
+ VS_NEUTER(verp_delims);
if (strlen(STR(verp_delims)) != 2) {
- msg_warn("malformed verp delimiter string: %s",
- printable(STR(verp_delims), '?'));
+ msg_warn("malformed verp delimiter string: %s", STR(verp_delims));
return (-1);
}
if (msg_verbose)
msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
return (-1);
}
- printable(STR(dsn_envid), '?');
+ VS_NEUTER(encoding);
+ VS_NEUTER(sender);
+ VS_NEUTER(dsn_envid);
VS_NEUTER(rcpt_buf->address);
VS_NEUTER(rcpt_buf->orig_addr);
VS_NEUTER(rcpt_buf->dsn_orcpt);
maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
if (*var_masq_exceptions)
cleanup_masq_exceptions =
- string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions);
+ string_list_init(VAR_MASQ_EXCEPTIONS, MATCH_FLAG_RETURN,
+ var_masq_exceptions);
if (*var_masq_classes)
cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table,
var_masq_classes);
var_masq_exceptions = argv[1];
cleanup_masq_exceptions =
- string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions);
+ string_list_init(VAR_MASQ_EXCEPTIONS, MATCH_FLAG_RETURN,
+ var_masq_exceptions);
masq_domains = argv_split(argv[2], CHARS_COMMA_SP);
addr = vstring_alloc(1);
if (strchr(argv[3], '@') == 0)
static void pre_jail_init(char *unused_name, char **unused_argv)
{
- flush_domains = domain_list_init(MATCH_FLAG_RETURN
+ flush_domains = domain_list_init(VAR_FFLUSH_DOMAINS, MATCH_FLAG_RETURN
| match_parent_style(VAR_FFLUSH_DOMAINS),
var_fflush_domains);
}
#ifdef TEST
-#include <msg.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <msg.h>
#include <vstream.h>
#include <vstring_vstream.h>
#include <msg_vstream.h>
+#include <dict.h>
#include <stringops.h> /* util_utf8_enable */
static void usage(char *progname)
usage(argv[0]);
dict_allow_surrogate = 1;
util_utf8_enable = 1;
- list = addr_match_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
+ list = addr_match_list_init("command line", MATCH_FLAG_PARENT
+ | MATCH_FLAG_RETURN, argv[optind]);
addr = argv[optind + 1];
if (strcmp(addr, "-") == 0) {
VSTRING *buf = vstring_alloc(100);
*/
#define ADDR_MATCH_LIST MATCH_LIST
-#define addr_match_list_init(f, p) \
- match_list_init((f), (p), 1, match_hostaddr)
+#define addr_match_list_init(o, f, p) \
+ match_list_init((o), (f), (p), 1, match_hostaddr)
#define addr_match_list_match(l, a) \
match_list_match((l), (a))
#define addr_match_list_free match_list_free
domainlist = cfg_get_str(parser, "domain", "", 0, 0);
if (*domainlist) {
- ctx->domain = string_list_init(MATCH_FLAG_RETURN, domainlist);
+ ctx->domain = string_list_init(parser->name, MATCH_FLAG_RETURN,
+ domainlist);
if (ctx->domain == 0)
/*
*/
if (*var_debug_peer_list)
debug_peer_list =
- namadr_list_init(MATCH_FLAG_RETURN
+ namadr_list_init(VAR_DEBUG_PEER_LIST, MATCH_FLAG_RETURN
| match_parent_style(VAR_DEBUG_PEER_LIST),
var_debug_peer_list);
}
#ifdef TEST
-#include <msg.h>
#include <stdlib.h>
#include <unistd.h>
+#include <msg.h>
#include <vstream.h>
#include <msg_vstream.h>
+#include <dict.h>
#include <stringops.h> /* util_utf8_enable */
static void usage(char *progname)
usage(argv[0]);
dict_allow_surrogate = 1;
util_utf8_enable = 1;
- list = domain_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
+ list = domain_list_init("command line", MATCH_FLAG_PARENT
+ | MATCH_FLAG_RETURN, argv[optind]);
host = argv[optind + 1];
vstream_printf("%s: %s\n", host, domain_list_match(list, host) ?
"YES" : list->error == 0 ? "NO" : "ERROR");
*/
#define DOMAIN_LIST MATCH_LIST
-#define domain_list_init(f, p) match_list_init((f), (p), 1, match_hostname)
+#define domain_list_init(o, f, p)\
+ match_list_init((o), (f), (p), 1, match_hostname)
#define domain_list_match match_list_match
#define domain_list_free match_list_free
void flush_init(void)
{
- flush_domains = domain_list_init(MATCH_FLAG_RETURN
+ flush_domains = domain_list_init(VAR_FFLUSH_DOMAINS, MATCH_FLAG_RETURN
| match_parent_style(VAR_FFLUSH_DOMAINS),
var_fflush_domains);
}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20150112"
+#define MAIL_RELEASE_DATE "20150113"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT
*/
if (match_par_dom_list == 0)
match_par_dom_list =
- string_list_init(MATCH_FLAG_NONE, var_par_dom_match);
+ string_list_init(VAR_PAR_DOM_MATCH, MATCH_FLAG_NONE,
+ var_par_dom_match);
/*
* Look up the parent domain matching policy.
#ifdef TEST
-#include <msg.h>
#include <stdlib.h>
#include <unistd.h>
+#include <msg.h>
#include <vstream.h>
#include <msg_vstream.h>
#include <dict.h>
usage(argv[0]);
dict_allow_surrogate = 1;
util_utf8_enable = 1;
- list = namadr_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
+ list = namadr_list_init("command line", MATCH_FLAG_PARENT
+ | MATCH_FLAG_RETURN, argv[optind]);
host = argv[optind + 1];
addr = argv[optind + 2];
vstream_printf("%s/%s: %s\n", host, addr,
*/
#define NAMADR_LIST MATCH_LIST
-#define namadr_list_init(f, p) \
- match_list_init((f), (p), 2, match_hostname, match_hostaddr)
+#define namadr_list_init(o, f, p) \
+ match_list_init((o), (f), (p), 2, match_hostname, match_hostaddr)
#define namadr_list_match match_list_match
#define namadr_list_free match_list_free
dummy/168.100.189.2: NO
dummy/168.100.189.3: YES
dummy/168.100.189.16: NO
-./namadr_list: warning: bad net/mask pattern: "168.100.189.0/98"
+./namadr_list: warning: command line: bad net/mask pattern: "168.100.189.0/98"
dummy/168.100.189.16: ERROR
-./namadr_list: warning: bad net/mask pattern: "168.100.589.0/28"
+./namadr_list: warning: command line: bad net/mask pattern: "168.100.589.0/28"
dummy/168.100.189.16: ERROR
dummy/168.100.989.16: NO
./namadr_list: error: unsupported dictionary type: 2001
./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7 is unavailable. unsupported dictionary type: 2001
-./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7: table lookup problem
+./namadr_list: warning: command line: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7: table lookup problem
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: ERROR
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO
-./namadr_list: warning: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
+./namadr_list: warning: command line: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: ERROR
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: YES
dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: NO
bar/168.100.189.3: NO
baz/168.100.189.3: YES
x.x.x/127.0.0.1: NO
-./namadr_list: warning: bad net/mask pattern: "be/be"
+./namadr_list: warning: command line: bad net/mask pattern: "be/be"
x.x.x/127.0.0.1: ERROR
x.x.x/127.0.0.1: NO
-./namadr_list: warning: bad address pattern: "be:be"
+./namadr_list: warning: command line: bad address pattern: "be:be"
x.x.x/::1: ERROR
foo/168.100.189.3: YES
bar/168.100.189.3: NO
bar/168.100.189.3: NO
foo/168.100.189.3: YES
bar/168.100.189.3: NO
-./namadr_list: warning: fail:1: table lookup problem
+./namadr_list: warning: command line: fail:1: table lookup problem
bar/168.100.189.3: ERROR
-./namadr_list: warning: fail:1: table lookup problem
+./namadr_list: warning: command line: fail:1: table lookup problem
bar/168.100.189.3: ERROR
./namadr_list: error: open file /tmp/nosuchfile: No such file or directory
./namadr_list: warning: non-existent:/tmp/nosuchfile is unavailable. open file /tmp/nosuchfile: No such file or directory
-./namadr_list: warning: non-existent:/tmp/nosuchfile: table lookup problem
+./namadr_list: warning: command line: non-existent:/tmp/nosuchfile: table lookup problem
bar/168.100.189.3: ERROR
/* Allow on-the-fly update to make testing easier. */
if (resolve_local_list)
string_list_free(resolve_local_list);
- resolve_local_list = string_list_init(MATCH_FLAG_RETURN, var_mydest);
+ resolve_local_list = string_list_init(VAR_MYDEST, MATCH_FLAG_RETURN,
+ var_mydest);
}
/* resolve_local - match domain against list of local destinations */
mydestination=example.com destination=example.com YES
mydestination=example.net destination=example.com NO
-unknown: warning: fail:1_resolve_local: table lookup problem
+unknown: warning: mydestination: fail:1_resolve_local: table lookup problem
mydestination=fail:1_resolve_local destination=example.com ERROR
mydestination=fail:1_resolve_local destination=example.com.. NO
mydestination=fail:1_resolve_local destination= NO
addr_match_list_free(server_acl_mynetworks_host);
}
server_acl_mynetworks =
- addr_match_list_init(MATCH_FLAG_RETURN | match_parent_style(origin),
- mynetworks);
+ addr_match_list_init(origin, MATCH_FLAG_RETURN
+ | match_parent_style(origin), mynetworks);
if (warn_compat_break_mynetworks_style)
server_acl_mynetworks_host =
- addr_match_list_init(MATCH_FLAG_RETURN | match_parent_style(origin),
- mynetworks_host());
+ addr_match_list_init(origin, MATCH_FLAG_RETURN
+ | match_parent_style(origin), mynetworks_host());
}
/* server_acl_parse - parse access list */
} else if (STREQ(cmd, VAR_SERVER_ACL)) {
UPDATE_VAR(var_server_acl, value);
} else if (STREQ(cmd, "address")) {
- server_acl_pre_jail_init(var_mynetworks, VAR_SERVER_ACL);
+ server_acl_pre_jail_init(var_mynetworks, VAR_MYNETWORKS);
argv = server_acl_parse(var_server_acl, VAR_SERVER_ACL);
ret = server_acl_eval(value, argv, VAR_SERVER_ACL);
argv_free(argv);
168.100.189.3: permit
> mynetworks=fail:1
> address=168.100.189.4
-unknown: warning: fail:1: table lookup problem
+unknown: warning: mynetworks: fail:1: table lookup problem
unknown: warning: server_acl: permit_mynetworks: mynetworks lookup error -- ignoring the remainder of this access list
168.100.189.4: error
> server_acl=fail:1,reject
#ifdef TEST
-#include <msg.h>
#include <stdlib.h>
#include <unistd.h>
+#include <msg.h>
#include <vstream.h>
#include <vstring.h>
#include <msg_vstream.h>
+#include <dict.h>
#include <stringops.h> /* util_utf8_enable */
static void usage(char *progname)
usage(argv[0]);
dict_allow_surrogate = 1;
util_utf8_enable = 1;
- list = string_list_init(MATCH_FLAG_RETURN, argv[optind]);
+ list = string_list_init("command line", MATCH_FLAG_RETURN, argv[optind]);
string = argv[optind + 1];
vstream_printf("%s: %s\n", string, string_list_match(list, string) ?
"YES" : list->error == 0 ? "NO" : "ERROR");
*/
#define STRING_LIST MATCH_LIST
-#define string_list_init(f, p) match_list_init((f), (p), 1, match_string)
+#define string_list_init(o, f, p) \
+ match_list_init((o), (f), (p), 1, match_string)
#define string_list_match match_list_match
#define string_list_free match_list_free
/* SYNOPSIS
/* #include <user_acl.h>
/*
-/* const char *check_user_acl_byuid(acl, uid)
+/* const char *check_user_acl_byuid(pname, acl, uid)
+/* cobnst char *pname;
/* const char *acl;
/* uid_t uid;
/* DESCRIPTION
/* calls.
/*
/* Arguments:
+/* .IP pname
+/* The parameter name of the acl.
/* .IP acl
/* Authorized user name list suitable for input to string_list_init(3).
/* .IP uid
/* check_user_acl_byuid - check user authorization */
-const char *check_user_acl_byuid(char *acl, uid_t uid)
+const char *check_user_acl_byuid(const char *pname, const char *acl, uid_t uid)
{
struct mypasswd *mypwd;
STRING_LIST *list;
name = mypwd->pw_name;
}
- list = string_list_init(MATCH_FLAG_NONE, acl);
+ list = string_list_init(pname, MATCH_FLAG_NONE, acl);
if ((matched = string_list_match(list, name)) == 0) {
if (!who)
who = vstring_alloc(10);
/*
* External interface
*/
-extern const char *check_user_acl_byuid(char *, uid_t);
+extern const char *check_user_acl_byuid(const char *, const char *, uid_t);
/* AUTHOR(S)
/* Wietse Venema
* or in the daemon process?
*/
mail_dict_init();
- if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0)
+ if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl,
+ uid)) != 0)
msg_fatal("User %s(%ld) is not allowed to submit mail",
errstr, (long) uid);
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
- && (errstr = check_user_acl_byuid(var_showq_acl, uid)) != 0)
+ && (errstr = check_user_acl_byuid(VAR_SHOWQ_ACL, var_showq_acl,
+ uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to view the mail queue",
errstr, (long) uid);
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
- && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
+ && (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl,
+ uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to flush the mail queue",
errstr, (long) uid);
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
- && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
+ && (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl,
+ uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to flush the mail queue",
errstr, (long) uid);
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
- && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
+ && (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl,
+ uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to flush the mail queue",
errstr, (long) uid);
psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
/* Ignore smtpd_forbid_cmds lookup errors. Non-critical feature. */
if (*var_psc_forbid_cmds)
- psc_forbid_cmds = string_list_init(MATCH_FLAG_RETURN,
+ psc_forbid_cmds = string_list_init(VAR_PSC_FORBID_CMDS,
+ MATCH_FLAG_RETURN,
var_psc_forbid_cmds);
if (*var_psc_dnsbl_reply)
psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY,
msg_fatal("bad %s value: %s", VAR_PSC_BARLF_ACTION,
var_psc_barlf_action);
/* Fail "closed" on error. */
- psc_wlist_if = addr_match_list_init(MATCH_FLAG_RETURN, var_psc_wlist_if);
+ psc_wlist_if = addr_match_list_init(VAR_PSC_WLIST_IF, MATCH_FLAG_RETURN,
+ var_psc_wlist_if);
/*
* Start the cache maintenance pseudo thread last. Early cleanup makes
{
debug_peer_init();
qmqpd_clients =
- namadr_list_init(MATCH_FLAG_RETURN
+ namadr_list_init(VAR_QMQPD_CLIENTS, MATCH_FLAG_RETURN
| match_parent_style(VAR_QMQPD_CLIENTS),
var_qmqpd_clients);
}
* Access control is enforced in the postdrop command. The code here
* merely produces a more user-friendly interface.
*/
- if ((errstr = check_user_acl_byuid(var_submit_acl, uid)) != 0)
+ if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL,
+ var_submit_acl, uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to submit mail", errstr, (long) uid);
msg_fatal_status(EX_USAGE,
"stand-alone mode requires no recipient");
/* The actual enforcement happens in the postdrop command. */
- if ((errstr = check_user_acl_byuid(var_submit_acl, uid = getuid())) != 0)
+ if ((errstr = check_user_acl_byuid(VAR_SUBMIT_ACL, var_submit_acl,
+ uid = getuid())) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to submit mail",
errstr, (long) uid);
* Session cache domain list.
*/
if (*var_smtp_cache_dest)
- smtp_cache_dest = string_list_init(MATCH_FLAG_RETURN, var_smtp_cache_dest);
+ smtp_cache_dest = string_list_init(VAR_SMTP_CACHE_DEST,
+ MATCH_FLAG_RETURN,
+ var_smtp_cache_dest);
/*
* EHLO keyword filter.
* Initialize optional supported mechanism matchlist
*/
if (*var_smtp_sasl_mechs)
- smtp_sasl_mechs = string_list_init(MATCH_FLAG_NONE,
+ smtp_sasl_mechs = string_list_init(VAR_SMTP_SASL_MECHS,
+ MATCH_FLAG_NONE,
var_smtp_sasl_mechs);
/*
* Initialize blacklist/etc. patterns before entering the chroot jail, in
* case they specify a filename pattern.
*/
- smtpd_noop_cmds = string_list_init(MATCH_FLAG_RETURN, var_smtpd_noop_cmds);
- smtpd_forbid_cmds = string_list_init(MATCH_FLAG_RETURN, var_smtpd_forbid_cmds);
- verp_clients = namadr_list_init(MATCH_FLAG_RETURN, var_verp_clients);
- xclient_hosts = namadr_list_init(MATCH_FLAG_RETURN, var_xclient_hosts);
- xforward_hosts = namadr_list_init(MATCH_FLAG_RETURN, var_xforward_hosts);
- hogger_list = namadr_list_init(MATCH_FLAG_RETURN
+ smtpd_noop_cmds = string_list_init(VAR_SMTPD_NOOP_CMDS, MATCH_FLAG_RETURN,
+ var_smtpd_noop_cmds);
+ smtpd_forbid_cmds = string_list_init(VAR_SMTPD_FORBID_CMDS,
+ MATCH_FLAG_RETURN,
+ var_smtpd_forbid_cmds);
+ verp_clients = namadr_list_init(VAR_VERP_CLIENTS, MATCH_FLAG_RETURN,
+ var_verp_clients);
+ xclient_hosts = namadr_list_init(VAR_XCLIENT_HOSTS, MATCH_FLAG_RETURN,
+ var_xclient_hosts);
+ xforward_hosts = namadr_list_init(VAR_XFORWARD_HOSTS, MATCH_FLAG_RETURN,
+ var_xforward_hosts);
+ hogger_list = namadr_list_init(VAR_SMTPD_HOGGERS, MATCH_FLAG_RETURN
| match_parent_style(VAR_SMTPD_HOGGERS),
var_smtpd_hoggers);
if (*var_smtpd_sasl_exceptions_networks)
sasl_exceptions_networks =
- namadr_list_init(MATCH_FLAG_RETURN,
+ namadr_list_init(VAR_SMTPD_SASL_EXCEPTIONS_NETWORKS,
+ MATCH_FLAG_RETURN,
var_smtpd_sasl_exceptions_networks);
#else
msg_warn("%s is true, but SASL support is not compiled in",
* Pre-open access control lists before going to jail.
*/
mynetworks_curr =
- namadr_list_init(MATCH_FLAG_RETURN | match_parent_style(VAR_MYNETWORKS),
- var_mynetworks);
+ namadr_list_init(VAR_MYNETWORKS, MATCH_FLAG_RETURN
+ | match_parent_style(VAR_MYNETWORKS), var_mynetworks);
mynetworks_new =
- namadr_list_init(MATCH_FLAG_RETURN | match_parent_style(VAR_MYNETWORKS),
- mynetworks_host());
+ namadr_list_init(VAR_MYNETWORKS, MATCH_FLAG_RETURN
+ | match_parent_style(VAR_MYNETWORKS), mynetworks_host());
relay_domains =
- domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
+ domain_list_init(VAR_RELAY_DOMAINS,
+ match_parent_style(VAR_RELAY_DOMAINS),
var_relay_domains);
perm_mx_networks =
- namadr_list_init(MATCH_FLAG_RETURN
+ namadr_list_init(VAR_PERM_MX_NETWORKS, MATCH_FLAG_RETURN
| match_parent_style(VAR_PERM_MX_NETWORKS),
var_perm_mx_networks);
#ifdef USE_TLS
| DICT_FLAG_UTF8_REQUEST);
#ifdef TEST
- virt_alias_doms = string_list_init(MATCH_FLAG_NONE, var_virt_alias_doms);
- virt_mailbox_doms = string_list_init(MATCH_FLAG_NONE, var_virt_mailbox_doms);
+ virt_alias_doms = string_list_init(VAR_VIRT_ALIAS_DOMS, MATCH_FLAG_NONE,
+ var_virt_alias_doms);
+ virt_mailbox_doms = string_list_init(VAR_VIRT_MAILBOX_DOMS, MATCH_FLAG_NONE,
+ var_virt_mailbox_doms);
#endif
access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS);
/*
* Optional permit logging.
*/
- smtpd_acl_perm_log = string_list_init(MATCH_FLAG_RETURN,
+ smtpd_acl_perm_log = string_list_init(VAR_SMTPD_ACL_PERM_LOG,
+ MATCH_FLAG_RETURN,
var_smtpd_acl_perm_log);
}
#define UPDATE_MAPS(ptr, var, val, lock) \
{ if (ptr) maps_free(ptr); ptr = maps_create(var, val, lock); }
-#define UPDATE_LIST(ptr, val) \
+#define UPDATE_LIST(ptr, var, val) \
{ if (ptr) string_list_free(ptr); \
- ptr = string_list_init(MATCH_FLAG_NONE, val); }
+ ptr = string_list_init(var, MATCH_FLAG_NONE, val); }
case 2:
if (strcasecmp(args->argv[0], VAR_MYDEST) == 0) {
}
if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_DOMS) == 0) {
UPDATE_STRING(var_virt_alias_doms, args->argv[1]);
- UPDATE_LIST(virt_alias_doms, var_virt_alias_doms);
+ UPDATE_LIST(virt_alias_doms, VAR_VIRT_ALIAS_DOMS,
+ var_virt_alias_doms);
smtpd_resolve_init(100);
resp = 0;
break;
}
if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_DOMS) == 0) {
UPDATE_STRING(var_virt_mailbox_doms, args->argv[1]);
- UPDATE_LIST(virt_mailbox_doms, var_virt_mailbox_doms);
+ UPDATE_LIST(virt_mailbox_doms, VAR_VIRT_MAILBOX_DOMS,
+ var_virt_mailbox_doms);
smtpd_resolve_init(100);
resp = 0;
break;
/* NOT: UPDATE_STRING */
namadr_list_free(mynetworks_curr);
mynetworks_curr =
- namadr_list_init(MATCH_FLAG_RETURN
+ namadr_list_init(VAR_MYNETWORKS, MATCH_FLAG_RETURN
| match_parent_style(VAR_MYNETWORKS),
args->argv[1]);
smtpd_resolve_init(100);
/* NOT: UPDATE_STRING */
domain_list_free(relay_domains);
relay_domains =
- domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
+ domain_list_init(VAR_RELAY_DOMAINS,
+ match_parent_style(VAR_RELAY_DOMAINS),
args->argv[1]);
smtpd_resolve_init(100);
resp = 0;
UPDATE_STRING(var_perm_mx_networks, args->argv[1]);
domain_list_free(perm_mx_networks);
perm_mx_networks =
- namadr_list_init(MATCH_FLAG_RETURN
+ namadr_list_init(VAR_PERM_MX_NETWORKS, MATCH_FLAG_RETURN
| match_parent_style(VAR_PERM_MX_NETWORKS),
args->argv[1]);
resp = 0;
>>> recipient_restrictions permit_mynetworks
OK
>>> rcpt reject@dunno.domain
-./smtpd_check: warning: fail:1_mynetworks: table lookup problem
+./smtpd_check: warning: mynetworks: fail:1_mynetworks: table lookup problem
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <reject@dunno.domain>: Temporary lookup failure; from=<reject@dunno.domain> to=<reject@dunno.domain> proto=SMTP helo=<foobar>
451 4.3.0 <reject@dunno.domain>: Temporary lookup failure
>>> #
>>> # Expect REJECT (server configuration error)
>>> #
>>> rcpt reject@dunno.domain
-./smtpd_check: warning: non-null host address bits in "168.100.189.1/27", perhaps you should use "168.100.189.0/27" instead
+./smtpd_check: warning: mynetworks: non-null host address bits in "168.100.189.1/27", perhaps you should use "168.100.189.0/27" instead
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <reject@dunno.domain>: Temporary lookup failure; from=<reject@dunno.domain> to=<reject@dunno.domain> proto=SMTP helo=<foobar>
451 4.3.0 <reject@dunno.domain>: Temporary lookup failure
>>> #
>>> mydestination fail:1_mydestination
OK
>>> rcpt user@example.com
-./smtpd_check: warning: fail:1_mydestination: table lookup problem
+./smtpd_check: warning: mydestination: fail:1_mydestination: table lookup problem
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <user@example.com>: Temporary lookup failure; from=<> to=<user@example.com> proto=SMTP helo=<foobar>
451 4.3.0 <user@example.com>: Temporary lookup failure
>>> #
if (*var_virt_alias_doms)
virt_alias_doms =
- string_list_init(MATCH_FLAG_RETURN, var_virt_alias_doms);
+ string_list_init(VAR_VIRT_ALIAS_DOMS, MATCH_FLAG_RETURN,
+ var_virt_alias_doms);
if (*var_virt_mailbox_doms)
virt_mailbox_doms =
- string_list_init(MATCH_FLAG_RETURN, var_virt_mailbox_doms);
+ string_list_init(VAR_VIRT_MAILBOX_DOMS, MATCH_FLAG_RETURN,
+ var_virt_mailbox_doms);
if (*var_relay_domains)
relay_domains =
- domain_list_init(MATCH_FLAG_RETURN
+ domain_list_init(VAR_RELAY_DOMAINS, MATCH_FLAG_RETURN
| match_parent_style(VAR_RELAY_DOMAINS),
var_relay_domains);
/*
/* Arguments:
/* .IP utf8_request
-/* Perform UTF-8 case folding.
+/* Boolean parameter that enables UTF-8 case folding. This is
+/* ignored when compiled without EAI support.
/* .IP src
/* Null-terminated input string.
/* .IP dest
#ifdef NO_EAI
/*
- * ASCII mode only
+ * ASCII mode only.
*/
vstring_strcpy(dest, src);
return (lowercase(STR(dest)));
int n;
/*
- * All-ASCII input.
+ * All-ASCII input, or ASCII mode only.
*/
if (utf8_req == 0 || allascii(src)) {
vstring_strcpy(dest, src);
return (lowercase(STR(dest)));
}
+ /*
+ * ICU 4.8 ucasemap_utf8FoldCase() does not complain about UTF-8 syntax
+ * errors. XXX Is this behavior guaranteed or accidental? We don't know,
+ * therefore must check it here.
+ */
+ if (valid_utf8_string(src, strlen(src)) == 0) {
+ if (err)
+ *err = "malformed UTF-8 or invalid codepoint";
+ return (0);
+ }
+
/*
* One-time initialization. With ICU 4.8 this works while chrooted.
*/
/*
* Report the result. With ICU 4.8, there are no casefolding errors for
* the entire RFC 3629 Unicode range (code points U+0000..U+10FFFF
- * including surrogates).
+ * including surrogates), nor are there casefolding errors for bad UTF-8
+ * input. XXX Is this behavior guaranteed or accidental? We don't know,
+ * therefore we have the UTF-8 syntax check (and range check) above.
*/
if (U_SUCCESS(error) == 0) {
if (err)
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
bp = STR(buffer);
- msg_info("> %s", bp);
+ vstream_printf("> %s\n", bp);
cmd = mystrtok(&bp, CHARS_SPACE);
if (cmd == 0 || *cmd == '#')
continue;
*/
if (strcmp(cmd, "fold") == 0) {
if ((conv_res = casefold(utf8_req, dest, bp, &fold_err)) != 0)
- msg_info("\"%s\" ->fold \"%s\"", bp, conv_res);
+ vstream_printf("\"%s\" ->fold \"%s\"\n", bp, conv_res);
else
- msg_warn("cannot casefold \"%s\": %s", bp, fold_err);
+ vstream_printf("cannot casefold \"%s\": %s\n", bp, fold_err);
}
/*
&& first <= last) {
for (codepoint = first; codepoint <= last; codepoint++) {
if (codepoint >= 0xD800 && codepoint <= 0xDFFF) {
- msg_warn("skipping surrogate range");
+ vstream_printf("skipping surrogate range\n");
codepoint = 0xDFFF;
} else {
encode_utf8(buffer, codepoint);
if (msg_verbose)
- msg_info("U+%X -> %s", codepoint, STR(buffer));
+ vstream_printf("U+%X -> %s\n", codepoint, STR(buffer));
if (valid_utf8_string(STR(buffer), LEN(buffer)) == 0)
- msg_fatal("bad utf-8 encoding for U+%X", codepoint);
+ msg_fatal("bad utf-8 encoding for U+%X\n", codepoint);
if (casefold(utf8_req, dest, STR(buffer), &fold_err) == 0)
- msg_warn("casefold error for U+%X: %s",
- codepoint, fold_err);
+ vstream_printf("casefold error for U+%X: %s\n",
+ codepoint, fold_err);
}
}
- msg_info("range completed: 0x%x..0x%x", first, last);
+ vstream_printf("range completed: 0x%x..0x%x\n", first, last);
}
/*
&& sscanf(bp, "%255s", STR(buffer)) == 1) {
if (geteuid() == 0) {
if (chdir(STR(buffer)) < 0)
- msg_fatal("chdir(%s): %m", STR(buffer));
+ msg_fatal("chdir(%s): %m\n", STR(buffer));
if (chroot(STR(buffer)) < 0)
- msg_fatal("chroot(%s): %m", STR(buffer));
- msg_info("chroot %s completed", STR(buffer));
+ msg_fatal("chroot(%s): %m\n", STR(buffer));
+ vstream_printf("chroot %s completed\n", STR(buffer));
}
}
* Usage
*/
else {
- msg_info("Usage: %s chroot <path> | fold <text> | range <first> <last> | verbose <int>",
- argv[0]);
+ vstream_printf("Usage: %s chroot <path> | fold <text> | range <first> <last> | verbose <int>\n",
+ argv[0]);
}
+ vstream_fflush(VSTREAM_OUT);
}
exit(0);
}
fold x。example.com
fold x.example.com
fold x。example.com
+# Bad UTF-8
+fold yyy\80\80\80
+fold \80\80\80xxx
-./casefold: > # Ignored when not running as root.
-./casefold: > chroot /tmp
-./casefold: > # Casefold U+0000 .. U+10FFFF excluding surrogates.
-./casefold: > range 0x0 0xD7FF
-./casefold: range completed: 0x0..0xd7ff
-./casefold: > range 0xD800 0xD800
-./casefold: warning: skipping surrogate range
-./casefold: range completed: 0xd800..0xd800
-./casefold: > range 0xDFFF 0xDFFF
-./casefold: warning: skipping surrogate range
-./casefold: range completed: 0xdfff..0xdfff
-./casefold: > range 0xE000 0x10FFFF
-./casefold: range completed: 0xe000..0x10ffff
-./casefold: > # Demonstrate that range is not a noop.
-./casefold: > verbose 1
-./casefold: > range 0xE000 0xE007
-./casefold: U+E000 ->
-./casefold: U+E001 ->
-./casefold: U+E002 ->
-./casefold: U+E003 ->
-./casefold: U+E004 ->
-./casefold: U+E005 ->
-./casefold: U+E006 ->
-./casefold: U+E007 ->
-./casefold: range completed: 0xe000..0xe007
-./casefold: > verbose 0
-./casefold: > # Upper-case greek -> lower-case greek.
-./casefold: > fold Δημοσθένους.example.com
-./casefold: "Δημοσθένους.example.com" ->fold "δημοσθένουσ.example.com"
-./casefold: > # Upper-case ASCII -> lower-case ASCII.
-./casefold: > fold HeLlO.ExAmPlE.CoM
-./casefold: "HeLlO.ExAmPlE.CoM" ->fold "hello.example.com"
-./casefold: > # Folding does not change aliases for '.'.
-./casefold: > fold x。example.com
-./casefold: "x。example.com" ->fold "x。example.com"
-./casefold: > fold x.example.com
-./casefold: "x.example.com" ->fold "x.example.com"
-./casefold: > fold x。example.com
-./casefold: "x。example.com" ->fold "x。example.com"
+> # Ignored when not running as root.
+> chroot /tmp
+> # Casefold U+0000 .. U+10FFFF excluding surrogates.
+> range 0x0 0xD7FF
+range completed: 0x0..0xd7ff
+> range 0xD800 0xD800
+skipping surrogate range
+range completed: 0xd800..0xd800
+> range 0xDFFF 0xDFFF
+skipping surrogate range
+range completed: 0xdfff..0xdfff
+> range 0xE000 0x10FFFF
+range completed: 0xe000..0x10ffff
+> # Demonstrate that range is not a noop.
+> verbose 1
+> range 0xE000 0xE007
+U+E000 ->
+U+E001 ->
+U+E002 ->
+U+E003 ->
+U+E004 ->
+U+E005 ->
+U+E006 ->
+U+E007 ->
+range completed: 0xe000..0xe007
+> verbose 0
+> # Upper-case greek -> lower-case greek.
+> fold Δημοσθένους.example.com
+"Δημοσθένους.example.com" ->fold "δημοσθένουσ.example.com"
+> # Upper-case ASCII -> lower-case ASCII.
+> fold HeLlO.ExAmPlE.CoM
+"HeLlO.ExAmPlE.CoM" ->fold "hello.example.com"
+> # Folding does not change aliases for '.'.
+> fold x。example.com
+"x。example.com" ->fold "x。example.com"
+> fold x.example.com
+"x.example.com" ->fold "x.example.com"
+> fold x。example.com
+"x。example.com" ->fold "x。example.com"
+> # Bad UTF-8
+> fold yyy\80\80\80
+cannot casefold "yyy\80\80\80": malformed UTF-8 or invalid codepoint
+> fold \80\80\80xxx
+cannot casefold "\80\80\80xxx": malformed UTF-8 or invalid codepoint
/*
/* DICT *dict_utf8_activate(
/* DICT *dict)
-/*
+/* AUXILIARY FUNCTIONS
/* char *dict_utf8_check_fold(
/* DICT *dict,
/* const char *string,
/* paths in application code). Attempts to store non-UTF-8
/* keys or values are skipped while reporting a non-error
/* status, attempts to look up or delete non-UTF-8 keys are
-/* skipped while reporting a non-error status, and attempts
-/* to look up a non-UTF-8 value are flagged while reporting a
-/* configuration error.
+/* skipped while reporting a non-error status, and lookup
+/* results that contain a non-UTF-8 value are blocked while
+/* reporting a configuration error.
/*
/* The dict_utf8_check* functions may be invoked to perform
/* UTF-8 validity checks when util_utf8_enable is non-zero.
/* SYNOPSIS
/* #include <match_list.h>
/*
-/* MATCH_LIST *match_list_init(flags, pattern_list, count, func,...)
+/* MATCH_LIST *match_list_init(pname, flags, pattern_list, count, func,...)
+/* const char *pname;
/* int flags;
/* const char *pattern_list;
/* int count;
/* void match_list_free(list)
/* MATCH_LIST *list;
/* DESCRIPTION
-/* This module implements a framework for tests for list membership.
-/* The actual tests are done by user-supplied functions. With
-/* util_utf8_enable non-zero, string comparison supports UTF-8.
+/* This module implements a framework for tests for list
+/* membership. The actual tests are done by user-supplied
+/* functions.
/*
/* Patterns are separated by whitespace and/or commas. A pattern
/* is either a string, a file name (in which case the contents
/* of the file are substituted for the file name) or a type:name
-/* lookup table specification. In order to reverse the result of
-/* a pattern match, precede a pattern with an exclamation point (!).
+/* lookup table specification. In order to reverse the result
+/* of a pattern match, precede a pattern with an exclamation
+/* point (!).
/*
-/* match_list_init() performs initializations. The flags argument
-/* specifies the bit-wise OR of zero or more of the following:
+/* match_list_init() performs initializations. When the global
+/* util_utf8_enable variable is non-zero, and when the code
+/* is compiled with EAI support, string comparison will use
+/* caseless UTF-8 mode. Otherwise, only ASCII characters will
+/* be casefolded.
+/*
+/* match_list_match() matches strings against the specified
+/* pattern list, passing the first string to the first function
+/* given to match_list_init(), the second string to the second
+/* function, and so on.
+/*
+/* match_list_free() releases storage allocated by match_list_init().
+/*
+/* Arguments:
+/* .IP pname
+/* Parameter name or other identiying information that is
+/* prepended to error messages.
+/* .IP flags
+/* Specifies the bit-wise OR of zero or more of the following:
/* .RS
/* .IP MATCH_FLAG_PARENT
-/* The hostname pattern foo.com matches any name within the domain
-/* foo.com. If this flag is cleared, foo.com matches itself
-/* only, and .foo.com matches any name below the domain foo.com.
+/* The hostname pattern foo.com matches any name within the
+/* domain foo.com. If this flag is cleared, foo.com matches
+/* itself only, and .foo.com matches any name below the domain
+/* foo.com.
/* .IP MATCH_FLAG_RETURN
/* Request that match_list_match() logs a warning and returns
/* zero (with list->error set to a non-zero dictionary error
/* code) instead of raising a fatal run-time error.
/* .RE
/* Specify MATCH_FLAG_NONE to request none of the above.
-/* The pattern_list argument specifies a list of patterns. The third
-/* argument specifies how many match functions follow.
-/*
-/* match_list_match() matches strings against the specified pattern
-/* list, passing the first string to the first function given to
-/* match_list_init(), the second string to the second function, and
-/* so on.
-/*
-/* match_list_free() releases storage allocated by match_list_init().
+/* .IP pattern_list
+/* A list of patterns.
+/* .IP count
+/* Specifies how many match functions follow.
+/* .IP list
+/* Pattern list produced by match_list_init().
+/* .IP string
+/* Search string.
/* DIAGNOSTICS
/* Fatal error: unable to open or read a match_list file; invalid
-/* match_list pattern.
+/* match_list pattern; casefold error (UTF-8 mode only).
/* SEE ALSO
/* host_match(3) match hosts by name or by address
/* LICENSE
const char *utf8_err;
/*
- * No DICT_FLAG_FOLD_FIX here, because we casefold the search string at
- * the beginning of a search. String constant patterns are casefolded
- * during match_list initialization.
+ * We do not use DICT_FLAG_FOLD_FIX, because we casefold the search
+ * string at the beginning of a search, and we use strcmp() for string
+ * comparison. This works because string patterns are casefolded during
+ * match_list initialization, and databases are supposed to fold case
+ * upon creation.
*/
#define OPEN_FLAGS O_RDONLY
#define DICT_FLAGS (DICT_FLAG_LOCK | DICT_FLAG_UTF8_REQUEST)
while ((start = mystrtokq(&bp, delim, CHARS_BRACE)) != 0) {
if (*start == '#') {
msg_warn("%s: comment at end of line is not supported: %s %s",
- myname, start, bp);
+ match_list->pname, start, bp);
break;
}
for (match = init_match, item = start; *item == '!'; item++)
match = !match;
if (*item == 0)
- msg_fatal("%s: no pattern after '!'", myname);
+ /* No graceful degradation for this... */
+ msg_fatal("%s: no pattern after '!'", match_list->pname);
if (*item == '/') { /* /file/name */
if ((fp = vstream_fopen(item, O_RDONLY, 0)) == 0) {
+ /* Replace unusable pattern with pseudo table. */
vstring_sprintf(buf, "%s:%s", DICT_TYPE_NOFILE, item);
if (dict_handle(STR(buf)) == 0)
dict_register(STR(buf),
if (casefold(util_utf8_enable, match_list->fold_buf, match ?
item : STR(vstring_sprintf(buf, "!%s", item)),
&utf8_err) == 0) {
+ /* Replace unusable pattern with pseudo table. */
vstring_sprintf(match_list->fold_buf, "%s:%s",
DICT_TYPE_NOUTF8, item);
if (dict_handle(STR(match_list->fold_buf)) == 0)
dict_register(STR(match_list->fold_buf),
- dict_surrogate(DICT_TYPE_NOFILE, item,
+ dict_surrogate(DICT_TYPE_NOUTF8, item,
OPEN_FLAGS, DICT_FLAGS,
"casefold error: %s",
utf8_err));
/* match_list_init - initialize pattern list */
-MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,...)
+MATCH_LIST *match_list_init(const char *pname, int flags,
+ const char *patterns, int match_count,...)
{
MATCH_LIST *list;
char *saved_patterns;
msg_panic("match_list_init: bad flags 0x%x", flags);
list = (MATCH_LIST *) mymalloc(sizeof(*list));
+ list->pname = mystrdup(pname);
list->flags = flags;
list->match_count = match_count;
list->match_func =
void match_list_free(MATCH_LIST *list)
{
/* XXX Should decrement map refcounts. */
+ myfree(list->pname);
argv_free(list->patterns);
myfree((void *) list->match_func);
myfree((void *) list->match_args);
typedef int (*MATCH_LIST_FN) (MATCH_LIST *, const char *, const char *);
struct MATCH_LIST {
+ char *pname; /* used in error messages */
int flags; /* processing options */
ARGV *patterns; /* one pattern each */
int match_count; /* match function/argument count */
#define MATCH_FLAG_RETURN (1<<1)
#define MATCH_FLAG_ALL (MATCH_FLAG_PARENT | MATCH_FLAG_RETURN)
-extern MATCH_LIST *match_list_init(int, const char *, int,...);
+extern MATCH_LIST *match_list_init(const char *, int, const char *, int,...);
extern int match_list_match(MATCH_LIST *,...);
extern void match_list_free(MATCH_LIST *);
/*--*/
#endif
-
vstring_vsprintf(buf, fmt, ap);
va_end(ap);
if (list->flags & MATCH_FLAG_RETURN) {
- msg_warn("%s", vstring_str(buf));
+ msg_warn("%s: %s", list->pname, vstring_str(buf));
} else {
- msg_fatal("%s", vstring_str(buf));
+ msg_fatal("%s: %s", list->pname, vstring_str(buf));
}
vstring_free(buf);
return (0);
DICT *dict;
if (msg_verbose)
- msg_info("%s: %s ~? %s", myname, string, pattern);
+ msg_info("%s: %s: %s ~? %s", myname, list->pname, string, pattern);
/*
* Try dictionary lookup: exact match.
DICT *dict;
if (msg_verbose)
- msg_info("%s: %s ~? %s", myname, name, pattern);
+ msg_info("%s: %s: %s ~? %s", myname, list->pname, name, pattern);
/*
* Try dictionary lookup: exact match and parent domains.
if (entry == name || (dict->flags & DICT_FLAG_FIXED)) {
match = (dict_get(dict, entry) != 0);
if (msg_verbose > 1)
- msg_info("%s: lookup %s:%s %s: %s",
- myname, dict->type, dict->name, entry,
- match ? "found" : "notfound");
+ msg_info("%s: %s: lookup %s:%s %s: %s",
+ myname, list->pname, dict->type, dict->name,
+ entry, match ? "found" : "notfound");
if (match != 0)
break;
if ((list->error = dict->error) != 0)
int rc;
if (msg_verbose)
- msg_info("%s: %s ~? %s", myname, addr, pattern);
+ msg_info("%s: %s: %s ~? %s", myname, list->pname, addr, pattern);
#define V4_ADDR_STRING_CHARS "01234567890."
#define V6_ADDR_STRING_CHARS V4_ADDR_STRING_CHARS "abcdefABCDEF:"
/* in its input with the given replacement.
/*
/* util_utf8_enable controls whether UTF8 is considered printable.
-/* By default, non-ASCII text is replaced.
+/* With util_utf8_enable equal to zero, non-ASCII text is replaced.
/*
/* Arguments:
/* .IP buffer