-TMYSQL
-TMYSQL_NAME
-TNAMADR_LIST
+-TNAME_CODE
-TNAME_MASK
-TPEER_NAME
-TPGSQL_NAME
is accepted (and thus, before a cleanup server connection
is available). Files: smtpd/{smtpd,smtpd_state,smtpd_check}.c.
+20031204
+
+ Bugfix: conf/post-install didn't skip non-existent obsolete
+ files. Victor Duchovni.
+
+ Minor cleanups of the xclient error messages; xclient
+ command lookup tables. File: smtpd/smtpd.c.
+
Open problems:
High: when virtual aliasing is turned off after content
case $flags in *r*) recursive="-R";; *) recursive=;; esac
case $flags in *o*) obsolete_flag=1;; *) obsolete_flag=;; esac
# Flag obsolete objects. XXX Solaris 2..9 does not have "test -e".
- if [ -n "$obsolete_flag" -a -r $path ]
+ if [ -n "$obsolete_flag" ]
then
- obsolete="$obsolete $path"
+ test -r $path && obsolete="$obsolete $path"
continue;
fi
# Create missing directories with proper owner/group/mode settings.
htable_delete(anvil_remote_map, anvil_remote->ident,
(void (*) (char *)) 0);
ANVIL_REMOTE_FREE(anvil_remote);
+
+ if (msg_verbose)
+ msg_info("%s: anvil_remote_map used=%d",
+ myname, anvil_remote_map->used);
}
/* anvil_remote_lookup - dump address status */
} else if (msg_verbose)
msg_info("client socket not found for fd=%d",
vstream_fileno(client_stream));
+
+ if (msg_verbose)
+ msg_info("%s: anvil_local_map used=%d",
+ myname, anvil_local_map->used);
}
/* anvil_service - perform service for client */
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20031203"
+#define MAIL_RELEASE_DATE "20031204"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
#include <watchdog.h>
#include <iostuff.h>
#include <split_at.h>
+#include <name_code.h>
/* Global library. */
char *arg_val;
int update_namaddr = 0;
int function;
+ int code;
+ static NAME_CODE xclient_functions[] = {
+ XCLIENT_OVERRIDE, FUNC_OVERRIDE,
+ XCLIENT_FORWARD, FUNC_FORWARD,
+ 0, -1,
+ };
+ static NAME_CODE xclient_codes[] = {
+ "OK", SMTPD_PEER_CODE_OK,
+ "PERM", SMTPD_PEER_CODE_PERM,
+ "TEMP", SMTPD_PEER_CODE_TEMP,
+ 0, -1,
+ };
/*
* Sanity checks. The XCLIENT command does not override its own access
*/
arg_val = argv[1].strval;
printable(arg_val, '?');
- if (STREQ(arg_val, XCLIENT_OVERRIDE)) {
- function = FUNC_OVERRIDE;
- } else if (STREQ(arg_val, XCLIENT_FORWARD)) {
- function = FUNC_FORWARD;
- if (state->xclient.used == 0)
- smtpd_xclient_preset(state);
- } else { /* error */
+ if ((function = name_code(xclient_functions, arg_val)) < 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 Bad %s function: %s",
XCLIENT_CMD, arg_val);
return (-1);
}
+ if (function == FUNC_FORWARD && state->xclient.used == 0)
+ smtpd_xclient_preset(state);
/*
* Iterate over all NAME=VALUE attributes. An empty value means the
if (*raw_value && !valid_hostaddr(cooked_value, DONT_GRIPE)) {
if (!valid_hostname(cooked_value, DONT_GRIPE)) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 Bad hostname syntax: %s",
- cooked_value);
+ smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+ XCLIENT_NAME, raw_value);
return (-1);
}
UPD_STR_ATTR(state, function, name, cooked_value);
if (*raw_value) {
if (!valid_hostaddr(cooked_value, DONT_GRIPE)) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 Bad address syntax: %s",
- cooked_value);
+ smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+ XCLIENT_ADDR, raw_value);
return (-1);
}
UPD_STR_ATTR(state, function, addr, cooked_value);
* the hostname lookup status is not OK.
*/
else if (STREQ(arg_val, XCLIENT_CODE)) {
- if (STREQ(cooked_value, "OK")) {
- UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_OK);
- } else if (STREQ(cooked_value, "TEMP")) {
- UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_TEMP);
- UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
- update_namaddr = 1;
- } else if (STREQ(cooked_value, "PERM")) {
- UPD_INT_ATTR(state, function, peer_code, SMTPD_PEER_CODE_PERM);
- UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
- update_namaddr = 1;
- } else {
- state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 Bad hostname status: %s",
- cooked_value);
- return (-1);
+ if (*raw_value) {
+ if ((code = name_code(xclient_codes, cooked_value)) < 0) {
+ state->error_mask |= MAIL_ERROR_PROTOCOL;
+ smtpd_chat_reply(state, "501 Bad %s value: %s",
+ XCLIENT_CODE, raw_value);
+ return (-1);
+ }
+ UPD_INT_ATTR(state, function, peer_code, code);
+ if (code != SMTPD_PEER_CODE_OK) {
+ UPD_STR_ATTR(state, function, name, CLIENT_NAME_UNKNOWN);
+ update_namaddr = 1;
+ }
}
}
if (*raw_value) {
if (strlen(cooked_value) > VALID_HOSTNAME_LEN) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 Bad HELO syntax: %s",
- cooked_value);
+ smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+ XCLIENT_HELO, raw_value);
return (-1);
}
neuter(cooked_value, "<>()\\\";:@", '?');
if (*raw_value) {
if (*cooked_value == 0 || strlen(cooked_value) > 64) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 Bad protocol syntax: %s",
- cooked_value);
+ smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+ XCLIENT_PROTO, raw_value);
return (-1);
}
neuter(cooked_value, "[]<>()\\\";:@", '?');
/* smtpd_xclient_preset() takes the result from smtpd_xclient_init()
/* and sets all fields to the same "unknown" value that regular
/* client attributes would have.
-*/
+/*
/* smtpd_xclient_reset() restores the state from smtpd_xclient_init().
/* LICENSE
/* .ad
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
write_buf.c write_wait.c auto_clnt.c attr_clnt.c attr_scan_plain.c \
- attr_print_plain.c sane_connect.c neuter.c
+ attr_print_plain.c sane_connect.c neuter.c name_code.c
OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
write_buf.o write_wait.o auto_clnt.o attr_clnt.o attr_scan_plain.o \
- attr_print_plain.o sane_connect.o $(STRCASE) neuter.o
+ attr_print_plain.o sane_connect.o $(STRCASE) neuter.o name_code.o
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
dict_cidr.h dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
split_at.h stat_as.h stringops.h sys_defs.h timed_connect.h \
timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \
vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \
- auto_clnt.h attr_clnt.h sane_connect.h
+ auto_clnt.h attr_clnt.h sane_connect.h name_code.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
attr_print_plain.o: vstream.h
attr_print_plain.o: vbuf.h
attr_print_plain.o: htable.h
-attr_print_plain.o: base64_code.h
-attr_print_plain.o: vstring.h
attr_print_plain.o: attr.h
attr_scan0.o: attr_scan0.c
attr_scan0.o: sys_defs.h
mystrtok.o: stringops.h
mystrtok.o: vstring.h
mystrtok.o: vbuf.h
+name_code.o: name_code.c
+name_code.o: sys_defs.h
+name_code.o: name_code.h
name_mask.o: name_mask.c
name_mask.o: sys_defs.h
name_mask.o: msg.h
#include <mymalloc.h>
#include <vstream.h>
#include <htable.h>
-#include <base64_code.h>
#include <attr.h>
#define STR(x) vstring_str(x)
--- /dev/null
+/*++
+/* NAME
+/* name_code 3
+/* SUMMARY
+/* name to number table mapping
+/* SYNOPSIS
+/* #include <name_code.h>
+/*
+/* typedef struct {
+/* .in +4
+/* const char *name;
+/* int code;
+/* .in -4
+/* } NAME_CODE;
+/*
+/* int name_code(table, name)
+/* NAME_CODE *table;
+/* const char *name;
+/*
+/* const char *str_name_code(table, code)
+/* NAME_CODE *table;
+/* int code;
+/* DESCRIPTION
+/* This module does simple name<->number mapping. The process
+/* is controlled by a table of (name, code) values.
+/* The table is terminated with a null pointer and a code that
+/* corresponds to "name not found".
+/*
+/* name_code() looks up the code that corresponds with the name.
+/* The lookup is case insensitive.
+/*
+/* str_name_code() translates a number to its equivalend string.
+/* DIAGNOSTICS
+/* When the search fails, the result is the "name not found" code
+/* or the null pointer, respectively.
+/* 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
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <name_code.h>
+
+/* name_code - look up code by name */
+
+int name_code(NAME_CODE *table, const char *name)
+{
+ NAME_CODE *np;
+
+ for (np = table; np->name; np++)
+ if (strcasecmp(name, np->name) == 0)
+ break;
+ return (np->code);
+}
+
+/* str_name_code - look up name by code */
+
+const char *str_name_code(NAME_CODE *table, int code)
+{
+ NAME_CODE *np;
+
+ for (np = table; np->name; np++)
+ if (code == np->code)
+ break;
+ return (np->name);
+}
--- /dev/null
+#ifndef _NAME_CODE_H_INCLUDED_
+#define _NAME_CODE_H_INCLUDED_
+
+/*++
+/* NAME
+/* name_mask 3h
+/* SUMMARY
+/* name to number table mapping
+/* SYNOPSIS
+/* #include <name_code.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+typedef struct {
+ const char *name;
+ int code;
+} NAME_CODE;
+
+extern int name_code(NAME_CODE *, const char *);
+extern const char *str_name_code(NAME_CODE *, int);
+
+/* 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
+/*--*/
+
+#endif