aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2005-06-04 17:22:05 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2005-06-04 17:22:05 +0000
commite462754c736fbf815b20acea417333564f6b9981 (patch)
tree318824cab7988ea0acefb5e7463ff92d6fcfef05
parent9263a485750e02a7115f71c086cc289ac5924dce (diff)
downloadmailfromd-e462754c736fbf815b20acea417333564f6b9981.tar.gz
mailfromd-e462754c736fbf815b20acea417333564f6b9981.tar.bz2
Moved to src/
git-svn-id: file:///svnroot/mailfromd/trunk@18 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--daemon.c195
-rw-r--r--dns.c194
-rw-r--r--mailfrom.h43
-rw-r--r--main.c1398
-rw-r--r--obstack.c498
-rw-r--r--obstack.h519
-rw-r--r--snprintf.c830
-rw-r--r--snprintf.h203
8 files changed, 0 insertions, 3880 deletions
diff --git a/daemon.c b/daemon.c
deleted file mode 100644
index 25e51a62..00000000
--- a/daemon.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-
-#ifndef _PATH_DEVNULL
-# define _PATH_DEVNULL "/dev/null"
-#endif
-
-/*
- According to Unix-FAQ maintained by Andrew Gierth:
-
- 1.fork() so the parent can exit, this returns control to the command
- line or shell invoking your program. This step is required so that the
- new process is guaranteed not to be a process group leader. The next
- step, setsid(), fails if you're a process group leader.
-
- 2.setsid() to become a process group and session group leader. Since a
- controlling terminal is associated with a session, and this new session
- has not yet acquired a controlling terminal our process now has no
- controlling terminal, which is a Good Thing for daemons.
-
- 3.fork() again so the parent, (the session group leader), can exit. This
- means that we, as a non-session group leader, can never regain a
- controlling terminal.
-
- 4.chdir("/") to ensure that our process doesn't keep any directory in use.
- Failure to do this could make it so that an administrator couldn't unmount
- a filesystem, because it was our current directory.
- [Equivalently, we could change to any directory containing files important
- to the daemon's operation.]
-
- 5.umask(0) so that we have complete control over the permissions of
- anything we write. We don't know what umask we may have inherited.
- [This step is optional]
-
- 6.close() fds 0, 1, and 2. This releases the standard in, out, and error
- we inherited from our parent process. We have no way of knowing where
- these fds might have been redirected to. Note that many daemons use
- sysconf() to determine the limit _SC_OPEN_MAX. _SC_OPEN_MAX tells you the
- maximun open files/process. Then in a loop, the daemon can close all
- possible file descriptors. You have to decide if you need to do this or not.
- If you think that there might be file-descriptors open you should close
- them, since there's a limit on number of concurrent file descriptors.
-
- 7.Establish new open descriptors for stdin, stdout and stderr. Even if
- you don't plan to use them, it is still a good idea to have them open.
- The precise handling of these is a matter of taste; if you have a logfile,
- for example, you might wish to open it as stdout or stderr, and open
- `/dev/null' as stdin; alternatively, you could open `/dev/console' as
- stderr and/or stdout, and `/dev/null' as stdin, or any other combination
- that makes sense for your particular daemon. */
-
-#define MAXFD 64
-
-void
-waitdaemon_timeout (int signo ARG_UNUSED)
-{
- int left;
-
- left = alarm (0);
- signal (SIGALRM, SIG_DFL);
- if (left == 0)
- {
- fprintf (stderr, "timed out waiting for child\n");
- exit (1);
- }
-}
-
-/* waitdaemon is like daemon, but optionally the parent pause up
- until maxwait before exiting. Return -1, on error, otherwise
- waitdaemon will return the pid of the parent. */
-
-int
-waitdaemon (int nochdir, int noclose, int maxwait)
-{
- int fd;
- pid_t childpid;
- pid_t ppid;
-
- ppid = getpid ();
-
- switch (childpid = fork ())
- {
- case -1: /* Something went wrong. */
- return (-1);
-
- case 0: /* In the child. */
- break;
-
- default: /* In the parent. */
- if (maxwait > 0)
- {
- signal (SIGALRM, waitdaemon_timeout);
- alarm (maxwait);
- pause ();
- }
- _exit(0);
- }
-
- if (setsid () == -1)
- return -1;
-
- /* SIGHUP is ignore because when the session leader terminates
- all process in the session (the second child) are sent the SIGHUP. */
- signal (SIGHUP, SIG_IGN);
-
- switch (fork ())
- {
- case 0:
- break;
-
- case -1:
- return -1;
-
- default:
- _exit (0);
- }
-
- if (!nochdir)
- chdir ("/");
-
- if (!noclose)
- {
- int i;
- long fdlimit = -1;
-
-#if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
- fdlimit = sysconf (_SC_OPEN_MAX);
-#elif defined (HAVE_GETDTABLESIZE)
- fdlimit = getdtablesize ();
-#endif
-
- if (fdlimit == -1)
- fdlimit = MAXFD;
-
- for (i = 0; i < fdlimit; i++)
- close (i);
-
- fd = open (_PATH_DEVNULL, O_RDWR, 0);
- if (fd != -1)
- {
- dup2 (fd, STDIN_FILENO);
- dup2 (fd, STDOUT_FILENO);
- dup2 (fd, STDERR_FILENO);
- if (fd > 2)
- close (fd);
- }
- }
- return ppid;
-}
-
-int
-daemon (int nochdir, int noclose)
-{
- return (waitdaemon (nochdir, noclose, 0) == -1) ? -1 : 0;
-}
diff --git a/dns.c b/dns.c
deleted file mode 100644
index 2cbe4e92..00000000
--- a/dns.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/* This file is part of mailfrom filter.
- Copyright (C) 2005, Sergey Poznyakoff
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <resolv.h>
-#include <arpa/nameser.h>
-#include <netdb.h>
-#include <pthread.h>
-#include <mailutils/mailutils.h>
-#include "mailfrom.h"
-
-struct mx_buffer {
- unsigned pref;
- char *name;
-};
-
-static int
-comp_pref(const void *a, const void *b)
-{
- const struct mx_buffer *ma = a, *mb = b;
- if (ma->pref > mb->pref)
- return 1;
- else if (ma->pref < mb->pref)
- return -1;
- return 0;
-}
-
-static void
-free_mx_buffer(struct mx_buffer *mx_buffer, int nmx)
-{
- int i;
- for (i = 0; i < nmx; i++)
- free(mx_buffer[i].name);
-}
-
-static getmx_status
-_getmx(char *host, char *answer, size_t answer_size, mxbuf_t mxbuf)
-{
- int n, nmx, i, count;
- ns_msg msg;
- struct mx_buffer mx_buffer[MAXMXCOUNT];
-
- debug(100,("Getting MX records for %s", host));
- n = res_query (host, C_IN, T_MX, answer, answer_size);
- if (n < 0) {
- debug(10, ("res_query failed (errno=%s, h_errno=%d)",
- mu_strerror(errno), h_errno));
- switch (h_errno) {
- case NO_DATA:
- case NO_RECOVERY:
- case HOST_NOT_FOUND:
- return getmx_not_found;
-
- case TRY_AGAIN:
- case -1:
- return getmx_temp_failure;
-
- default:
- mu_error("res_nsearch(%s) failed with unexpected h_errno %d",
- host, h_errno);
- return getmx_failure;
- }
- }
-
- if (ns_initparse(answer, n, &msg) < 0) {
- debug(2,("ns_initparse(host %s) failed", host));
- return getmx_failure;
- }
-
- /* Get number of MXs */
- count = ns_msg_count(msg, ns_s_an);
- if (count == 0)
- return getmx_not_found;
-
- /* Collect MX records */
- for (i = nmx = 0; i < count; i++) {
- ns_rr rr;
-
- if (ns_parserr(&msg, ns_s_an, i, &rr) < 0) {
- debug(2,("ns_parserrd(%d) failed (host %s)",
- i, host));
- free_mx_buffer(mx_buffer, nmx);
- return getmx_failure;
- }
- if (ns_rr_type(rr) == ns_t_mx) {
- int s;
- char tname[NS_MAXDNAME];
- const u_char *rdata;
- int rdlen;
-
- rdata = ns_rr_rdata(rr);
- rdlen = ns_rr_rdlen(rr);
-
- s = dn_expand(ns_msg_base(msg), ns_msg_end(msg),
- rdata+NS_INT16SZ, tname, sizeof tname);
- if (s < 0) {
- debug(2,("dn_expand failed"));
- free_mx_buffer(mx_buffer, nmx);
- return getmx_failure;
- }
- mx_buffer[nmx].pref = ns_get16(rdata);
- mx_buffer[nmx].name = strdup(tname);
- debug(100,("MX %u %s", mx_buffer[nmx].pref,
- mx_buffer[nmx].name));
- if (nmx++ > MAXMXCOUNT)
- break;
- }
- }
-
- /* Sort according to preference value */
- qsort(mx_buffer, nmx, sizeof mx_buffer[0], comp_pref);
-
- /* Prepare return value */
- memset(mxbuf, 0, sizeof(mxbuf_t));
- for (i = 0; i < nmx; i++)
- mxbuf[i] = mx_buffer[i].name;
- return getmx_success;
-}
-
-static int
-is_ipaddr(char *str)
-{
- for (; *str; str++)
- if (!(isdigit(*str) || *str == '.'))
- return 0;
- return 1;
-}
-
-static pthread_mutex_t getmx_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-getmx_status
-getmx(char *host, mxbuf_t mxbuf)
-{
- char hbuf[NI_MAXHOST];
- getmx_status status = getmx_failure;
-
- pthread_mutex_lock(&getmx_mutex);
- if (is_ipaddr(host)) {
- struct sockaddr_in sa;
- memset(&sa, 0, sizeof sa);
- sa.sin_family = AF_INET;
- if (inet_aton(host, &sa.sin_addr)
- && getnameinfo((struct sockaddr *)&sa, sizeof sa,
- hbuf, sizeof(hbuf),
- NULL, 0,
- 0) == 0
- && !is_ipaddr(hbuf))
- host = hbuf;
- else
- host = NULL;
- }
-
- if (host) {
- unsigned char *answer = malloc(MAXPACKET);
- if (!answer)
- status = getmx_failure;
- else {
- char *p;
-
- for (p = hbuf; p; ) {
- status = _getmx(p, answer, MAXPACKET, mxbuf);
- if (status == getmx_success)
- break;
- p = strchr(p, '.');
- if (!p)
- break;
- p++;
- }
- free(answer);
- }
- }
- pthread_mutex_unlock(&getmx_mutex);
- return status;
-}
-
diff --git a/mailfrom.h b/mailfrom.h
deleted file mode 100644
index 0dd25e44..00000000
--- a/mailfrom.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* This file is part of mailfrom filter.
- Copyright (C) 2005, Sergey Poznyakoff
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA */
-
-# ifndef MAXPACKET
-# define MAXPACKET 8192 /* max packet size used internally by BIND */
-# endif /* ! MAXPACKET */
-
-typedef enum {
- getmx_success,
- getmx_not_found,
- getmx_failure,
- getmx_temp_failure,
-} getmx_status;
-
-#define MAXMXCOUNT 32
-typedef char *mxbuf_t[MAXMXCOUNT];
-
-#define DEFAULT_PIDFILE LOCALSTATEDIR "/mailfromd.pid"
-
-#define debug(lev,c) do if (debug_level >= lev) {\
- debug_log("%s:%lu:%s: ", __FILE__, __LINE__, __FUNCTION__); \
- debug_log c; \
-} while (0)
-
-extern int debug_level;
-
-extern getmx_status getmx(char *ipstr, mxbuf_t mxbuf);
-
diff --git a/main.c b/main.c
deleted file mode 100644
index a3c08c0f..00000000
--- a/main.c
+++ /dev/null
@@ -1,1398 +0,0 @@
-/* This file is part of mailfrom filter.
- Copyright (C) 2005, Sergey Poznyakoff
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#define obstack_chunk_alloc malloc
-#define obstack_chunk_free free
-#include <obstack.h>
-#include <syslog.h>
-#include <pwd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pthread.h>
-
-#ifdef HAVE_SYSEXITS_H
-# include <sysexits.h>
-#else
-# define EX_OK 0 /* successful termination */
-# define EX__BASE 64 /* base value for error messages */
-# define EX_USAGE 64 /* command line usage error */
-# define EX_DATAERR 65 /* data format error */
-# define EX_NOINPUT 66 /* cannot open input */
-# define EX_NOUSER 67 /* addressee unknown */
-# define EX_NOHOST 68 /* host name unknown */
-# define EX_UNAVAILABLE 69 /* service unavailable */
-# define EX_SOFTWARE 70 /* internal software error */
-# define EX_OSERR 71 /* system error (e.g., can't fork) */
-# define EX_OSFILE 72 /* critical OS file missing */
-# define EX_CANTCREAT 73 /* can't create (user) output file */
-# define EX_IOERR 74 /* input/output error */
-# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
-# define EX_PROTOCOL 76 /* remote error in protocol */
-# define EX_NOPERM 77 /* permission denied */
-# define EX_CONFIG 78 /* configuration error */
-# define EX__MAX 78 /* maximum listed value */
-#endif
-
-#include <mailutils/mailutils.h>
-#include <mailutils/argp.h>
-#include <libmilter/mfapi.h>
-
-#include "mailfrom.h"
-
-
-/* Verification methods */
-typedef sfsistat (*method_fp)(SMFICTX *ctx, char *email, char *client_addr);
-
-static sfsistat method_standard(SMFICTX *ctx, char *email, char *client_addr);
-static sfsistat method_strict(SMFICTX *ctx, char *email, char *client_addr);
-
-struct method_tab {
- char *name;
- method_fp handler;
-};
-
-struct method_tab method_tab[] = {
- { "standard", method_standard },
- { "strict", method_strict },
- NULL
-};
-
-static method_fp method = method_standard;
-
-static method_fp
-find_method(char *name)
-{
- struct method_tab *p;
-
- for (p = method_tab; p->name; p++)
- if (strcmp(p->name, name) == 0)
- return p->handler;
- return NULL;
-}
-
-
-/* An actions is described by "action function", that actually performs
- what should be done, and "action data", that supply necessary data to
- the function.
-
- Action data may be of the following two types: */
-
-/* 1. Return action. Describes what value to return to Milter and, optionally,
- how to set the SMTP reply state. */
-struct return_action {
- sfsistat status; /* Return status */
- char *code; /* State code. Three digits, e.g. "550" */
- char *xcode; /* Extended state code, e.g. "5.5.3" */
- char *message; /* Textual message */
-};
-
-/* 2. Header action. Instructs mainfromd to add this header to the message */
-struct header_action {
- char *name; /* Header name */
- char *value; /* Header value */
-};
-
-/* Combine both structures */
-union action_data {
- struct return_action ret;
- struct header_action hdr;
-};
-
-/* Action function has the following type */
-typedef sfsistat (*action_fp)(SMFICTX *ctx, union action_data *data);
-
-/* Handy macro used to create bitmaps of allowed return values */
-#define MAP(c) (1<<(c))
-
-/* Actions and corresponding closures. Apart from function/data pare, we
- define a textual default action, and a map of allowed Milter return
- codes.
- All variables are in BSS. They are initialized to their values (either
- explicit or default) by parse_opt() function below. */
-action_fp action_success;
-union action_data action_success_data;
-#define action_success_default "return:accept"
-#define action_success_map MAP(SMFIS_ACCEPT)|MAP(SMFIS_CONTINUE)
-
-action_fp action_failure;
-union action_data action_failure_data;
-#define action_failure_default "return:accept"
-#define action_failure_map MAP(SMFIS_ACCEPT)|MAP(SMFIS_CONTINUE)|\
- MAP(SMFIS_DISCARD)|MAP(SMFIS_REJECT)
-
-action_fp action_bad_sender;
-union action_data action_bad_sender_data;
-#define action_bad_sender_default "return:reject"
-#define action_bad_sender_map MAP(SMFIS_DISCARD)|MAP(SMFIS_REJECT)
-
-action_fp action_temp_failure;
-union action_data action_temp_failure_data;
-#define action_temp_failure_default "return:tempfail"
-#define action_temp_failure_map MAP(SMFIS_ACCEPT)|MAP(SMFIS_CONTINUE)|\
- MAP(SMFIS_DISCARD)|MAP(SMFIS_REJECT)|\
- MAP(SMFIS_TEMPFAIL)
-
-/* Add_header keeps the header to be added for mlfi_eom() function */
-struct header_action *add_header;
-
-
-/* Configurable options */
-int do_transcript; /* Enable session transript */
-int debug_level; /* Debugging level */
-int test_mode; /* Enable test mode */
-int log_to_stderr; /* Use stderr for logging */
-char *smtp_domain; /* Default SMTP domain for EHLO command */
-char *portspec = DEFAULT_SOCKET; /* Communication socket specification */
-int force_remove; /* Remove local communication socket if it already
- exists */
-int foreground; /* Stay in foreground */
-
-char *pidfile = DEFAULT_PIDFILE;
-char *user = DEFAULT_USER; /* Switch to this user privileges after startup */
-/* I/O settings */
-unsigned io_timeout = 3;
-unsigned io_attempts = 3;
-
-
-/* Logging & debugging */
-static const char *sfsistat_str(sfsistat stat);
-
-int
-syslog_printer (int prio, const char *fmt, va_list ap)
-{
-#ifdef HAVE_VSYSLOG
- vsyslog (prio, fmt, ap);
-#else
- char buf[128];
- vsnprintf (buf, sizeof buf, fmt, ap);
- syslog (prio, "%s", buf);
-#endif
- return 0;
-}
-
-int
-syslog_error_printer (const char *fmt, va_list ap)
-{
- return syslog_printer(LOG_ERR, fmt, ap);
-}
-
-void
-vlogmsg(int prio, char *fmt, va_list ap)
-{
- if (log_to_stderr) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- } else
- syslog_printer(prio, fmt, ap);
-}
-
-void
-logmsg(int prio, char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogmsg(prio, fmt, ap);
- va_end(ap);
-}
-
-void
-transcript(char *prefix, char *msg)
-{
- if (do_transcript) {
- int len = strlen(msg);
- if (msg[len-1] == '\n') {
- --len;
- if (len > 0 && msg[len-1] == '\r')
- --len;
- }
- if (len)
- logmsg(LOG_INFO, "%s %*.*s", prefix, len, len, msg);
- }
-}
-
-void
-debug_log(char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vlogmsg(LOG_DEBUG, fmt, ap);
- va_end(ap);
-}
-
-
-/* Sendmail class file support */
-
-static list_t domain_list;
-
-static int
-compare_string(const void *item, const void *value)
-{
- return strcmp(item, value);
-}
-
-/* Read domains from sendmail-style domain file NAME and store them in
- DOMAIN_LIST */
-void
-read_domain_file(char *name)
-{
- FILE *fp;
- char buf[256];
- char *p;
-
- fp = fopen(name, "r");
- if (!fp) {
- mu_error("cannot open file `%s': %s",
- name, mu_strerror(errno));
- return;
- }
-
- if (!domain_list) {
- list_create(&domain_list);
- list_set_comparator(domain_list, compare_string);
- }
-
- while (p = fgets(buf, sizeof buf, fp)) {
- char *q;
-
- while (*p && isspace(*p))
- p++;
- if (*p == '#')
- continue;
-
- for (q = p + strlen(p) - 1; q > p && isspace(*q); q--)
- *q = 0;
-
- if (*p == 0)
- continue;
-
- list_append(domain_list, strdup(p));
- }
-
- fclose(fp);
-}
-
-/* Return true if we relay domain NAME */
-int
-relayed_domain_p(char *name)
-{
- char *p;
-
- for (p = strchr(name, '.'); p; p = strchr(p+1, '.'))
- if (list_locate(domain_list, p+1, NULL) == 0) {
- debug(10,("%s is in relayed domain %s",
- name, p+1));
- return 1;
- }
- return 0;
-}
-
-/* Return true if CLIENT represents a host we relay. CLIENT is a dotted-quad
- IP address. */
-int
-host_in_relayed_domain_p(char *client)
-{
- int rc;
- struct sockaddr_in sa;
- char hbuf[NI_MAXHOST];
-
- if (list_is_empty(domain_list))
- return 0;
-
- memset(&sa, 0, sizeof sa);
- sa.sin_family = AF_INET;
- if (inet_aton(client, &sa.sin_addr) == 0)
- return 0;
- rc = getnameinfo((struct sockaddr *)&sa, sizeof sa,
- hbuf, sizeof(hbuf),
- NULL, 0,
- 0);
- if (rc)
- return 0;
- return relayed_domain_p(hbuf);
-}
-
-
-/* Action functions */
-
-/* Return */
-static sfsistat
-action_return(SMFICTX *ctx, union action_data *data)
-{
- if (data->ret.code)
- smfi_setreply(ctx, data->ret.code, data->ret.xcode,
- data->ret.message);
- return data->ret.status;
-}
-
-/* Add header */
-static sfsistat
-action_add(SMFICTX *ctx, union action_data *data)
-{
- add_header = &data->hdr;
- return SMFIS_CONTINUE;
-}
-
-
-/* SMTP I/O functions */
-
-#define MLFIPRIV(ctx) ((struct smtp_io_data*) smfi_getpriv(ctx))
-
-struct smtp_io_data {
- SMFICTX *ctx; /* Milter context */
- stream_t stream; /* I/O stream */
- size_t send_off; /* Send offset */
- size_t recv_off; /* Receive offset */
- struct obstack stk; /* Obstack for keeping commands/replies */
- char *command; /* Last issued command */
- char *reply; /* Last received reply */
- char *start; /* First line of the reply, if it was multiline */
- char buf[128]; /* Input buffer */
- size_t level; /* Number of bytes in buf */
- int code; /* Reply code */
-};
-
-void
-smtp_io_data_init(struct smtp_io_data *dat, SMFICTX *ctx, stream_t stream)
-{
- obstack_init(&dat->stk);
- dat->send_off = dat->recv_off = 0;
- dat->stream = stream;
- dat->start = dat->command = dat->reply = NULL;
- dat->level = 0;
- dat->ctx = ctx;
- if (ctx) /* save the private data */
- smfi_setpriv(ctx, dat);
-}
-
-void
-smtp_io_data_destroy(struct smtp_io_data *dat)
-{
- if (dat) {
- stream_close (dat->stream);
- stream_destroy(&dat->stream, stream_get_owner(dat->stream));
- obstack_free(&dat->stk, NULL);
- if (dat->ctx)
- smfi_setpriv(dat->ctx, NULL);
- }
-}
-
-void
-smtp_stream_wait(stream_t stream, int flags)
-{
- struct timeval tv;
- tv.tv_sec = io_timeout;
- tv.tv_usec = 0;
- stream_wait(stream, &flags, &tv);
-}
-
-void
-smtp_wait(struct smtp_io_data *dat, int flags)
-{
- return smtp_stream_wait(dat->stream, flags);
-}
-
-int
-smtp_send(struct smtp_io_data *dat, char *command)
-{
- int attempt = 0;
- size_t len = strlen(command);
-
- transcript("SEND:", command);
- do {
- size_t nb;
- int rc = stream_write(dat->stream, command, len,
- dat->send_off, &nb);
- if (rc == 0) {
- dat->send_off += nb;
- len -= nb;
- command += nb;
- } else if (rc == EAGAIN) {
- if (attempt > io_attempts) {
- mu_error ("stream_write timed out");
- return -1;
- } else {
- smtp_wait(dat, MU_STREAM_READY_WR);
- attempt++;
- continue;
- }
- } else {
- mu_error ("stream_write: %s", mu_strerror (rc));
- return -1;
- }
- } while (len > 0);
- return 0;
-}
-
-int
-smtp_send2(struct smtp_io_data *dat, char *command, char *arg)
-{
- int rc;
-
- obstack_grow(&dat->stk, command, strlen(command));
- if (arg)
- obstack_grow(&dat->stk, arg, strlen(arg));
- obstack_1grow(&dat->stk, 0);
- dat->command = obstack_finish(&dat->stk);
-
- rc = smtp_send(dat, dat->command);
- if (rc == 0)
- rc = smtp_send(dat, "\r\n");
- return rc;
-}
-
-int
-smtp_send3(struct smtp_io_data *dat, char *command, char *arg1, char *arg2)
-{
- int rc;
-
- obstack_grow(&dat->stk, command, strlen(command));
- obstack_grow(&dat->stk, arg1, strlen(arg1));
- obstack_grow(&dat->stk, arg2, strlen(arg2));
- obstack_1grow(&dat->stk, 0);
- dat->command = obstack_finish(&dat->stk);
-
- rc = smtp_send(dat, dat->command);
- if (rc == 0)
- rc = smtp_send(dat, "\r\n");
-
- return rc;
-}
-
-int
-smtp_recvline(struct smtp_io_data *dat)
-{
- size_t attempt = 0;
- for (;;) {
- char *p;
-
- if (dat->level == 0) {
- int rc = stream_read(dat->stream,
- dat->buf, sizeof dat->buf,
- dat->recv_off, &dat->level);
- if (rc == 0) {
- if (dat->level == 0) {
- mu_error("stream_read: read 0 bytes");
- return -1;
- }
- dat->recv_off += dat->level;
- } else if (rc == EAGAIN) {
- if (attempt > io_attempts) {
- mu_error("stream_read timed out");
- return -1;
- }
- smtp_wait(dat, MU_STREAM_READY_RD);
- continue;
- } else {
- mu_error ("stream_read: %s", mu_strerror (rc));
- return -1;
- }
- }
- attempt = 0;
-
- p = memchr(dat->buf, '\n', dat->level);
- if (!p) {
- obstack_grow(&dat->stk, dat->buf, dat->level);
- dat->level = 0;
- continue;
- } else {
- size_t len = p - dat->buf + 1;
- obstack_grow(&dat->stk, dat->buf, len);
- obstack_1grow(&dat->stk, 0);
- dat->reply = obstack_finish(&dat->stk);
- dat->level -= len;
- memmove(dat->buf, dat->buf + len, dat->level);
- break;
- }
- }
- return 0;
-}
-
-int
-smtp_recv(struct smtp_io_data *dat)
-{
- char *p;
- dat->start = NULL;
- do {
- int code;
- int rc = smtp_recvline(dat);
- if (rc)
- return -1;
- transcript("RECV:", dat->reply);
- code = strtoul (dat->reply, &p, 0);
- if (p - dat->reply != 3 || (*p != '-' && *p != ' ')) {
- mu_error("Unexpected reply from server: %s",
- dat->reply);
- return -1;
- } else if (!dat->start) {
- dat->start = dat->reply;
- dat->code = code;
- } else if (dat->code != code) {
- mu_error("Unexpected reply code from server: %d",
- code);
- return -1;
- }
- } while (*p == '-');
- obstack_1grow (&dat->stk, 0);
- obstack_finish (&dat->stk);
- return 0;
-}
-
-
-/* Milter-specific functions */
-
-void
-log_status(sfsistat status, SMFICTX *ctx, struct smtp_io_data *io)
-{
- if (debug_level >= 1) {
- char *id = smfi_getsymval(ctx, "i");
- const char *str = sfsistat_str(status);
- if (status != SMFIS_ACCEPT && io) {
- if (str)
- logmsg(LOG_INFO,
- "%s: %s, command=%s, reply=%s",
- id ? id : "(nil)", str,
- io->command, io->reply);
- else
- logmsg(LOG_INFO,
- "%s: status %d, command=%s, reply=%s",
- id ? id : "(nil)", status,
- io->command, io->reply);
- } else {
- if (str)
- logmsg(LOG_INFO,
- "%s: %s", id ? id : "(nil)", str);
- else
- logmsg(LOG_INFO,
- "%s: status %d",
- id ? id : "(nil)", status);
- }
- }
-}
-
-sfsistat
-run_action(SMFICTX *ctx, getmx_status rc)
-{
- sfsistat status;
-
- switch (rc) {
- case getmx_temp_failure:
- status = action_temp_failure(ctx, &action_temp_failure_data);
- break;
-
- case getmx_failure:
- status = action_failure(ctx, &action_failure_data);
- break;
-
- case getmx_not_found:
- status = action_bad_sender(ctx, &action_bad_sender_data);
- break;
-
- case getmx_success:
- status = action_success(ctx, &action_success_data);
- }
- log_status(status, ctx, NULL);
- return status;
-}
-
-/* Verify whether EMAIL address is served by host CLIENT_ADDR. */
-getmx_status
-check_on_host(SMFICTX *ctx, char *email, char *client_addr)
-{
- int rc;
- stream_t stream;
- struct smtp_io_data io;
- getmx_status status = getmx_success;
- int count = 0;
-
- debug(10, ("email = %s, client_addr = %s", email, client_addr));
- rc = tcp_stream_create (&stream, client_addr, 25, MU_STREAM_NONBLOCK);
- if (rc) {
- mu_error ("tcp_stream_create: %s", mu_strerror (rc));
- return getmx_temp_failure;
- }
-
- while (rc = stream_open(stream)) {
- if ((rc == EAGAIN || rc == EINPROGRESS)
- && count <= io_attempts) {
- count++;
- smtp_stream_wait(stream, MU_STREAM_READY_WR);
- continue;
- }
- mu_error("stream_open: %s, %d", mu_strerror(rc), count);
- stream_destroy(&stream, stream_get_owner(stream));
- if (rc == EAGAIN || rc == EINPROGRESS)
- return getmx_temp_failure;
- else
- return getmx_failure;
- }
- debug(100,("stream opened"));
-
- smtp_io_data_init(&io, ctx, stream);
-
- do {
- char *buf;
- char *descr;
- if (smtp_recv(&io) || io.