aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS9
-rw-r--r--fetchmail.c173
-rw-r--r--fetchmail.h16
-rw-r--r--fetchmail.man14
-rw-r--r--interface.c86
-rw-r--r--options.c4
-rw-r--r--rcfile_y.y16
-rw-r--r--sample.rcfile16
8 files changed, 153 insertions, 181 deletions
diff --git a/NEWS b/NEWS
index b2ea6cf2..6e57b94e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,13 +1,12 @@
- To Do:
-
-Try to change the daemon-mode loop so the poll comes before the wait,
-not after it.
-
Release Notes:
------------------------------------------------------------------------------
fetchmail-2.9 ()
+features --
+
+* `interface' and `monitor' options are now per-server.
+
bugs --
* Stricter parsing of greeting message for the host name; eliminates some
diff --git a/fetchmail.c b/fetchmail.c
index 529f18ec..d0865dcf 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -61,10 +61,6 @@ int check_only; /* if --probe was set */
int cmd_batchlimit; /* if --batchlimit was set */
int cmd_fetchlimit; /* if --fetchlimit was set */
char *cmd_logfile; /* if --logfile was set */
-char *interface; /* interface required specification */
-char *cmd_interface; /* if --interface was set */
-char *monitor; /* monitored interface for activity */
-char *cmd_monitor; /* if --monitor was set */
/* miscellaneous global controls */
char *rcfile; /* path name of rc file */
@@ -178,16 +174,6 @@ int main (int argc, char **argv)
printf("SMTP message batch limit is %d.\n", batchlimit);
else if (outlevel == O_VERBOSE)
printf("No SMTP message batch limit.\n");
-#ifdef linux
- if (interface)
- printf("TCP/IP interface requirements for %s.\n", interface);
- else if (outlevel == O_VERBOSE)
- printf("No TCP/IP interface requirements specified.\n");
- if (monitor)
- printf("Polling loop will monitor %s.\n", monitor);
- else if (outlevel == O_VERBOSE)
- printf("No monitor interface specified.\n");
-#endif
for (ctl = querylist; ctl; ctl = ctl->next) {
if (ctl->active && !(implicitmode && ctl->server.skip))
dump_params(ctl);
@@ -374,69 +360,6 @@ int main (int argc, char **argv)
* reflect the status of that transaction.
*/
do {
- if (poll_interval)
- {
-#ifdef linux
- if (monitor)
- {
- /*
- * Allow some time for the link to quiesce.
- * Note: this delay is important! Don't remove it casually!
- */
- sleep(3);
- interface_note_activity();
- }
-#endif
- if (outlevel == O_VERBOSE)
- {
- time_t now;
-
- time(&now);
- fprintf(stderr, "fetchmail: sleeping at %s", ctime(&now));
- }
-
- /*
- * We can't use sleep(3) here because we need an alarm(3)
- * equivalent in order to implement server nonresponse timeout.
- * We'll just assume setitimer(2) is available since fetchmail
- * has to have a BSDoid socket layer to work at all.
- */
- {
- struct itimerval ntimeout;
-
- ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
- ntimeout.it_value.tv_sec = poll_interval;
- ntimeout.it_value.tv_usec = 0;
-
- setitimer(ITIMER_REAL,&ntimeout,NULL);
- signal(SIGALRM, donothing);
- pause();
- signal(SIGALRM, SIG_IGN);
- if (lastsig == SIGUSR1
- || ((poll_interval && !getuid()) && lastsig == SIGHUP))
- {
-#ifdef SYS_SIGLIST_DECLARED
- error(0, 0, "awakened by %s", sys_siglist[lastsig]);
-#else
- error(0, 0, "awakened by signal %d", lastsig);
-#endif
- }
- }
-
- if (outlevel == O_VERBOSE)
- {
- time_t now;
-
- time(&now);
- fprintf(stderr, "fetchmail: awakened at %s", ctime(&now));
- }
- }
-
-#ifdef linux
- if (!interface_approve())
- continue;
-#endif
-
#ifdef HAVE_RES_SEARCH
sethostent(TRUE); /* use TCP/IP for mailserver queries */
#endif /* HAVE_RES_SEARCH */
@@ -446,6 +369,12 @@ int main (int argc, char **argv)
{
if (ctl->active && !(implicitmode && ctl->server.skip))
{
+#ifdef linux
+ /* interface_check does its own error logging */
+ if (!interface_check(&ctl->server))
+ continue;
+#endif /* linux */
+
#ifdef HAVE_GETHOSTBYNAME
/*
* This functions partly as an optimization and partly
@@ -508,6 +437,56 @@ int main (int argc, char **argv)
fclose(ctl->smtp_sockfp);
ctl->smtp_sockfp = (FILE *)NULL;
}
+
+ /*
+ * OK, we've polled. Now sleep.
+ */
+ if (poll_interval)
+ {
+ if (outlevel == O_VERBOSE)
+ {
+ time_t now;
+
+ time(&now);
+ fprintf(stderr, "fetchmail: sleeping at %s", ctime(&now));
+ }
+
+ /*
+ * We can't use sleep(3) here because we need an alarm(3)
+ * equivalent in order to implement server nonresponse timeout.
+ * We'll just assume setitimer(2) is available since fetchmail
+ * has to have a BSDoid socket layer to work at all.
+ */
+ {
+ struct itimerval ntimeout;
+
+ ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
+ ntimeout.it_value.tv_sec = poll_interval;
+ ntimeout.it_value.tv_usec = 0;
+
+ setitimer(ITIMER_REAL,&ntimeout,NULL);
+ signal(SIGALRM, donothing);
+ pause();
+ signal(SIGALRM, SIG_IGN);
+ if (lastsig == SIGUSR1
+ || ((poll_interval && !getuid()) && lastsig == SIGHUP))
+ {
+#ifdef SYS_SIGLIST_DECLARED
+ error(0, 0, "awakened by %s", sys_siglist[lastsig]);
+#else
+ error(0, 0, "awakened by signal %d", lastsig);
+#endif
+ }
+ }
+
+ if (outlevel == O_VERBOSE)
+ {
+ time_t now;
+
+ time(&now);
+ fprintf(stderr, "fetchmail: awakened at %s", ctime(&now));
+ }
+ }
} while
(poll_interval);
@@ -649,6 +628,11 @@ static int load_params(int argc, char **argv, int optind)
if (ctl->server.envelope == (char *)NULL)
ctl->server.envelope = "X-Envelope-To:";
+#ifdef linux
+ /* interface_check does its own error logging */
+ interface_parse(&ctl->server);
+#endif /* linux */
+
/* sanity checks */
if (ctl->server.port < 0)
{
@@ -674,31 +658,6 @@ static int load_params(int argc, char **argv, int optind)
if (cmd_logfile)
logfile = cmd_logfile;
- /* if cmd_interface was explicitly set, use it to override interface */
- if (cmd_interface)
- interface = cmd_interface;
-
- /* if cmd_monitor was explicitly set, use it to override monitor */
- if (cmd_monitor)
- monitor = cmd_monitor;
-
- if (interface)
-#ifdef linux
- interface_parse();
-#else
- {
- (void) fprintf(stderr,
- "interface specification supported only on Linux\n");
- exit(PS_SYNTAX);
- }
- if (monitor)
- {
- (void) fprintf(stderr,
- "monitor supported only on Linux\n");
- exit(PS_SYNTAX);
- }
-#endif
-
return(implicitmode);
}
@@ -904,6 +863,16 @@ void dump_params (struct query *ctl)
if (count > 1)
printf(" Envelope header is assumed to be: %s\n", ctl->server.envelope);
}
+#ifdef linux
+ if (ctl->server.interface)
+ printf("TCP/IP interface requirements for %s.\n", ctl->server.interface);
+ else if (outlevel == O_VERBOSE)
+ printf("No TCP/IP interface requirements specified.\n");
+ if (ctl->server.monitor)
+ printf("Polling loop will monitor %s.\n", ctl->server.monitor);
+ else if (outlevel == O_VERBOSE)
+ printf("No monitor interface specified.\n");
+#endif
if (ctl->server.protocol > P_POP2)
if (!ctl->oldsaved)
diff --git a/fetchmail.h b/fetchmail.h
index d969945c..b7f64fff 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -68,6 +68,13 @@ struct hostdata /* shared among all user connections to given server */
char *envelope;
int skip;
+#ifdef linux
+ char *interface;
+ char *monitor;
+ int monitor_io;
+ struct ipair *inter;
+#endif /* linux */
+
/* computed for internal use */
#ifdef HAVE_GETHOSTBYNAME
char *canonical_name; /* DNS canonical name of server host */
@@ -150,10 +157,6 @@ extern int quitmode; /* if --quit was set */
extern int check_only; /* if --check was set */
extern int cmd_batchlimit; /* if --batchlimit was set */
extern char *cmd_logfile; /* if --logfile was set */
-extern char *interface; /* interface required specification */
-extern char *cmd_interface; /* if --interface was set */
-extern char *monitor; /* monitored interface for activity */
-extern char *cmd_monitor; /* if --monitor was set */
/* these get computed */
extern int batchlimit; /* if --batchlimit was set */
@@ -219,9 +222,8 @@ int daemonize(const char *, void (*)(int));
int prc_parse_file(const char *);
int prc_filecheck(const char *);
-void interface_parse(void);
-void interface_note_activity(void);
-int interface_approve(void);
+void interface_parse(struct hostdata *);
+int interface_check(struct hostdata *);
char *getpassword(char *);
diff --git a/fetchmail.man b/fetchmail.man
index 0460dc8a..db92a7a0 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -544,6 +544,8 @@ Legal server options are:
timeout
envelope
aka
+ interface
+ monitor
Legal user options are
@@ -650,13 +652,11 @@ or reverse it by saying `user esr here is eric there'
.PP
For backward compatibility, the word `server' is a synonym for `poll'.
.PP
-There are currently four valid global option statements;
-\&`set batchlimit = ' followed by a number and sets the same global
-specified by the --batchlimit option, `set logfile = ' followed by a
-string sets the same global specified by --logfile, `set interface = '
-followed by a string sets the same global specified by --interface, and
-`set monitor = ' followed by a string sets the same global specified by
---monitor. In all cases, a command-line option will override.
+There are currently two valid global option statements; \&`set
+batchlimit = ' followed by a number and sets the same global specified
+by the --batchlimit option, and `set logfile = ' followed by a string
+sets the same global specified by --logfile. In both cases, a
+command-line option will override.
.PP
Basic format is:
diff --git a/interface.c b/interface.c
index dce5267e..abfe2e6d 100644
--- a/interface.c
+++ b/interface.c
@@ -21,16 +21,16 @@
#include <linux/netdevice.h>
#include "fetchmail.h"
-static struct in_addr interface_address;
-static struct in_addr interface_mask;
-
-static int monitor_io = 0;
-
typedef struct {
struct in_addr addr, dstaddr, netmask;
int rx_packets, tx_packets;
} ifinfo_t;
+struct ipair {
+ struct in_addr interface_address;
+ struct in_addr interface_mask;
+};
+
/* Get active network interface information. Return non-zero upon success. */
static int _get_ifinfo_(int socket_fd, FILE *stats_file, const char *ifname,
@@ -99,34 +99,27 @@ static int get_ifinfo(const char *ifname, ifinfo_t *ifinfo)
return(result);
}
-/* Parse 'interface' specification. */
-
-void interface_parse(void)
+void interface_parse(struct hostdata *hp)
+/* parse 'interface' specification. */
{
- int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ int socket_fd;
char *cp1, *cp2;
struct ifreq request;
- /* in the event we point to a null string, make pointer null */
- if (interface && !*interface)
- interface = NULL;
- if (monitor && !*monitor)
- monitor = NULL;
-
- /* if no interface specification present, all done */
- if (!interface)
- return;
+ if (!hp->interface)
+ return;
/* find and isolate just the IP address */
- if (!(cp1 = strchr(interface, '/')))
+ if (!(cp1 = strchr(hp->interface, '/')))
(void) error(PS_SYNTAX, 0, "missing IP interface address");
*cp1++ = '\000';
/* validate specified interface exists */
- strcpy(request.ifr_name, interface);
+ strcpy(request.ifr_name, hp->interface);
+ socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (ioctl(socket_fd, SIOCGIFFLAGS, &request) < 0)
(void) error(PS_SYNTAX, 0, "no such interface device '%s'",
- interface);
+ hp->interface);
close(socket_fd);
/* find and isolate just the netmask */
@@ -136,57 +129,52 @@ void interface_parse(void)
*cp2++ = '\000';
/* convert IP address and netmask */
- if (!inet_aton(cp1, &interface_address))
+ hp->inter = xmalloc(sizeof(struct ipair));
+ if (!inet_aton(cp1, &hp->inter->interface_address))
(void) error(PS_SYNTAX, 0, "invalid IP interface address");
- if (!inet_aton(cp2, &interface_mask))
+ if (!inet_aton(cp2, &hp->inter->interface_mask))
(void) error(PS_SYNTAX, 0, "invalid IP interface mask");
/* apply the mask now to the IP address (range) required */
- interface_address.s_addr &= interface_mask.s_addr;
+ hp->inter->interface_address.s_addr &= hp->inter->interface_mask.s_addr;
return;
}
-/* Save interface I/O counts. */
-
-void interface_note_activity(void)
-{
- ifinfo_t ifinfo;
-
- /* get the current I/O stats for the monitored link */
- if (monitor && get_ifinfo(monitor, &ifinfo))
- monitor_io = ifinfo.rx_packets + ifinfo.tx_packets;
-}
-
-/* Return TRUE if OK to poll, FALSE otherwise. */
-
-int interface_approve(void)
+int interface_check(struct hostdata *hp)
+/* return TRUE if OK to poll, FALSE otherwise */
{
ifinfo_t ifinfo;
/* check interface IP address (range), if specified */
- if (interface) {
+ if (hp->interface) {
/* get interface info */
- if (!get_ifinfo(interface, &ifinfo)) {
- (void) error(0, 0, "skipping poll, %s down",
- interface);
+ if (!get_ifinfo(hp->interface, &ifinfo)) {
+ (void) error(0, 0, "skipping poll of %s, %s down",
+ hp->names->id, hp->interface);
return(FALSE);
}
/* check the IP address (range) */
- if ((ifinfo.addr.s_addr & interface_mask.s_addr) !=
- interface_address.s_addr) {
+ if ((ifinfo.addr.s_addr & hp->inter->interface_mask.s_addr) !=
+ hp->inter->interface_address.s_addr) {
(void) error(0, 0,
- "skipping poll, %s IP address excluded",
- interface);
+ "skipping poll of %s, %s IP address excluded",
+ hp->names->id, hp->interface);
return(FALSE);
}
}
/* if monitoring, check link for activity if it is up */
- if (monitor && get_ifinfo(monitor, &ifinfo) &&
- monitor_io == ifinfo.rx_packets + ifinfo.tx_packets) {
- (void) error(0, 0, "skipping poll, %s inactive", monitor);
+ if (hp->monitor && get_ifinfo(hp->monitor, &ifinfo) &&
+ hp->monitor_io == ifinfo.rx_packets + ifinfo.tx_packets) {
+ (void) error(0, 0,
+ "skipping poll of %s, %s inactive",
+ hp->names->id, hp->monitor);
return(FALSE);
}
+ /* get the current I/O stats for the monitored link */
+ if (hp->monitor && get_ifinfo(hp->monitor, &ifinfo))
+ hp->monitor_io = ifinfo.rx_packets + ifinfo.tx_packets;
+
return(TRUE);
}
#endif /* linux */
diff --git a/options.c b/options.c
index 5bf97888..bbd42cf6 100644
--- a/options.c
+++ b/options.c
@@ -268,11 +268,11 @@ struct query *ctl; /* option record to be initialized */
#ifdef linux
case 'I':
case LA_INTERFACE:
- cmd_interface = optarg;
+ ctl->server.interface = xstrdup(optarg);
break;
case 'M':
case LA_MONITOR:
- cmd_monitor = optarg;
+ ctl->server.monitor = xstrdup(optarg);
break;
#endif
diff --git a/rcfile_y.y b/rcfile_y.y
index b23afdc7..3fe804a8 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -68,8 +68,6 @@ statement_list : statement
/* future global options should also have the form SET <name> <value> */
statement : SET BATCHLIMIT MAP NUMBER {batchlimit = $4;}
| SET LOGFILE MAP STRING {logfile = xstrdup($4);}
- | SET INTERFACE MAP STRING {interface = xstrdup($4);}
- | SET MONITOR MAP STRING {monitor = xstrdup($4);}
/*
* The way the next two productions are written depends on the fact that
@@ -117,6 +115,20 @@ serv_option : AKA alias_list
| AUTHENTICATE KERBEROS {current.server.authenticate = A_KERBEROS;}
| TIMEOUT NUMBER {current.server.timeout = $2;}
| ENVELOPE STRING {current.server.envelope = xstrdup($2);}
+ | INTERFACE STRING {
+#ifdef linux
+ current.server.interface = xstrdup($2);
+#else
+ fprintf(stderr, "fetchmail: interface option is only supported under Linux\n");
+#endif /* linux */
+ }
+ | MONITOR STRING {
+#ifdef linux
+ current.server.monitor = xstrdup($2);
+#else
+ fprintf(stderr, "fetchmail: monitor option is only supported under Linux\n");
+#endif /* linux */
+ }
;
/*
diff --git a/sample.rcfile b/sample.rcfile
index d9822f01..c6da6f4b 100644
--- a/sample.rcfile
+++ b/sample.rcfile
@@ -28,6 +28,8 @@
# envelope -- must be followed by an envelope header name
# aka -- must be followed by one or more server aliases
# localdomains -- must be followed by one or more domain names
+# interface -- must be followed by device/IP address/mask
+# monitor -- must be followed by IP address
#
# username (or user) -- must be followed by a name
# is -- must be followed by one or more names
@@ -63,8 +65,6 @@
#
# set batchlimit = -- must be followed by a number
# set logfile = -- must be followed by a string
-# set interface = -- must be followed by IP address
-# set monitor = -- must be followed by IP address
#
# The noise keywords `and', `with', `has', `wants', and `options' are ignored
# anywhere in an entry; they can be used to make it resemble English. The
@@ -76,18 +76,20 @@
# This is what the developer's .fetchmailrc looks like:
set batchlimit = 0 # I forward to sendmail
-set interface = sl0/10.0.2.15 # SLIRP's default IP address
-defaults password not_blowing_my_cover;
+defaults
+ interface "sl0/10.0.2.15" # SLIRP standard address
+ user esr is esr fetchmail-friends magic-numbers here
+ fetchall
# Use this for production
poll locke.ccil.org with protocol APOP:
- user esr there with password my_apop_secret is esr here;
+ password my_apop_secret;
# Use this to test IMAP
skip locke protocol IMAP:
- user esr here is esr there;
+ password my_remote_password;
# Use this to test against POP2 using a local server
skip localhost protocol pop2:
- user esr here is esr there;
+ password my_local_password;