mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 05:38:06 +00:00
snapshot-19990322
This commit is contained in:
parent
f0ecb1fb5d
commit
6ff2c5cf25
@ -2371,6 +2371,40 @@ Apologies for any names omitted.
|
|||||||
Bugfix: \username was broken. Frank Dziuba was the first
|
Bugfix: \username was broken. Frank Dziuba was the first
|
||||||
to notice.
|
to notice.
|
||||||
|
|
||||||
|
19990321
|
||||||
|
|
||||||
|
Workaround: from now on, Postfix on Solaris uses stream
|
||||||
|
pipes instead of UNIX-domain sockets. Despite workarounds,
|
||||||
|
the latter were causing more trouble than anything else on
|
||||||
|
all systems combined.
|
||||||
|
|
||||||
|
19990322
|
||||||
|
|
||||||
|
Portability: the makedefs would mis-identify IRIX 6.5.x as
|
||||||
|
IRIX 5.x. Fix by Brian Truelsen of Maersk Mc-Kinney Moller
|
||||||
|
Institute for Production Technology, Denmark.
|
||||||
|
|
||||||
|
Feature: reject_unknown_recipient_domain restriction for
|
||||||
|
recipient addresses. For the sake of symmetry, we now also
|
||||||
|
have reject_unknown_sender_domain. This means the old
|
||||||
|
reject_unknown_address restriction is being phased out.
|
||||||
|
Suggested by Rask Ingemann Lambertsen [XXX affiliation to
|
||||||
|
be determined].
|
||||||
|
|
||||||
|
Feature: unknown sender/recipient domain restrictions now
|
||||||
|
distinguish between soft errors (always: 450) and hard
|
||||||
|
errors (configurable with the unknown_address_reject_code
|
||||||
|
parameter, default: 450; use 550 at your own risk).
|
||||||
|
|
||||||
|
Feature: no HELO junk mail restrictions means that no syntax
|
||||||
|
check will be done on HELO/EHLO hostname arguments.
|
||||||
|
|
||||||
|
Bugfix: the initial Solaris workaround for UNIX-domain
|
||||||
|
sockets could cause the queue manager to block if Postfix
|
||||||
|
ran into a delivery agent process limit. After another code
|
||||||
|
rewrite that problem is eliminated. Thanks to Chris
|
||||||
|
Cappuccio, Empire Net, for assistance with testing.
|
||||||
|
|
||||||
Future:
|
Future:
|
||||||
|
|
||||||
Planned: must be able to list the same hash table in
|
Planned: must be able to list the same hash table in
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
Incompatible changes with postfix-alpha-19990317:
|
Major changes with snapshot-19990322:
|
||||||
=================================================
|
=====================================
|
||||||
|
|
||||||
|
- The UNIX-domain socket workaround for Solaris was fixed
|
||||||
|
after one day of review. More testing is welcome.
|
||||||
|
|
||||||
|
- reject_unknown_{sender,recipient}_domain restrictions that
|
||||||
|
distinguish between hard (always 450) and soft (configurable,
|
||||||
|
default 450) lookup errors.
|
||||||
|
|
||||||
|
Incompatible changes with postfix-19990317:
|
||||||
|
===========================================
|
||||||
|
|
||||||
- You MUST install the new version of /etc/postfix/postfix-script.
|
- You MUST install the new version of /etc/postfix/postfix-script.
|
||||||
|
|
||||||
@ -7,8 +17,8 @@ Incompatible changes with postfix-alpha-19990317:
|
|||||||
MUST specify the R flag in order to generate a Return-Path: message
|
MUST specify the R flag in order to generate a Return-Path: message
|
||||||
header (as needed by, for example, cyrus).
|
header (as needed by, for example, cyrus).
|
||||||
|
|
||||||
Major changes since postfix-beta-19990122-pl01:
|
Major changes with postfix-19990317:
|
||||||
===============================================
|
====================================
|
||||||
|
|
||||||
A detailed record of changes is given in the HISTORY file.
|
A detailed record of changes is given in the HISTORY file.
|
||||||
|
|
||||||
|
@ -704,6 +704,8 @@ extern int var_unk_name_code;
|
|||||||
#define DEF_NON_FQDN_CODE 504
|
#define DEF_NON_FQDN_CODE 504
|
||||||
extern int var_non_fqdn_code;
|
extern int var_non_fqdn_code;
|
||||||
|
|
||||||
|
#define REJECT_UNKNOWN_SENDDOM "reject_unknown_sender_domain"
|
||||||
|
#define REJECT_UNKNOWN_RCPTDOM "reject_unknown_recipient_domain"
|
||||||
#define REJECT_UNKNOWN_ADDRESS "reject_unknown_address"
|
#define REJECT_UNKNOWN_ADDRESS "reject_unknown_address"
|
||||||
#define VAR_UNK_ADDR_CODE "unknown_address_reject_code"
|
#define VAR_UNK_ADDR_CODE "unknown_address_reject_code"
|
||||||
#define DEF_UNK_ADDR_CODE 450
|
#define DEF_UNK_ADDR_CODE 450
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Version of this program.
|
* Version of this program.
|
||||||
*/
|
*/
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "Snapshot-19990321"
|
#define DEF_MAIL_VERSION "Snapshot-19990322"
|
||||||
extern char *var_mail_version;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@ -353,7 +353,7 @@ network address.
|
|||||||
|
|
||||||
<dt> Example:
|
<dt> Example:
|
||||||
|
|
||||||
<dd> <b>smtpd_sender_restrictions = reject_unknown_address</b>
|
<dd> <b>smtpd_sender_restrictions = reject_unknown_sender_domain</b>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
@ -361,12 +361,13 @@ network address.
|
|||||||
|
|
||||||
<dl compact>
|
<dl compact>
|
||||||
|
|
||||||
<a name="reject_unknown_address">
|
<a name="reject_unknown_sender_domain">
|
||||||
|
|
||||||
<dt> <b>reject_unknown_address</b> <dd> Reject the request when
|
<dt> <b>reject_unknown_sender_domain</b> <dd> Reject the request
|
||||||
the sender mail address has no DNS A or MX record. The
|
when the sender mail address has no DNS A or MX record. The
|
||||||
<b>unknown_address_reject_code </b> parameter specifies the response
|
<b>unknown_address_reject_code </b> parameter specifies the response
|
||||||
code for rejected requests (default: <b>450</b>).
|
code for rejected requests (default: <b>450</b>). The response
|
||||||
|
is always <b>450</b> in case of a temporary DNS error.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
@ -506,6 +507,16 @@ for rejected requests (default: <b>550</b>).
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
<a name="reject_unknown_recipient_domain">
|
||||||
|
|
||||||
|
<dt> <b>reject_unknown_recipient_domain</b> <dd> Reject the request
|
||||||
|
when the recipient mail address has no DNS A or MX record. The
|
||||||
|
<b>unknown_address_reject_code </b> parameter specifies the response
|
||||||
|
code for rejected requests (default: <b>450</b>). The response
|
||||||
|
is always <b>450</b> in case of a temporary DNS error.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
|
||||||
<a name="reject_non_fqdn_recipient">
|
<a name="reject_non_fqdn_recipient">
|
||||||
|
|
||||||
<dt> <b>reject_non_fqdn_recipient</b> <dd> Reject the request when
|
<dt> <b>reject_non_fqdn_recipient</b> <dd> Reject the request when
|
||||||
@ -515,7 +526,7 @@ response code to rejected requests (default: <b>504</b>).
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<dt> <b><a href="#reject_unknown_address">reject_unknown_address</a></b>
|
<dt> <b><a href="#reject_unknown_sender_domain">reject_unknown_sender_domain</a></b>
|
||||||
|
|
||||||
<dt> <b><a href="#reject_non_fqdn_sender">reject_non_fqdn_sender</a></b>
|
<dt> <b><a href="#reject_non_fqdn_sender">reject_non_fqdn_sender</a></b>
|
||||||
|
|
||||||
|
@ -137,12 +137,12 @@ case "$SYSTEM.$RELEASE" in
|
|||||||
CCARGS="$CCARGS -DPATH_DB_H='<db/db.h>'"
|
CCARGS="$CCARGS -DPATH_DB_H='<db/db.h>'"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
IRIX*.5*) SYSTYPE=IRIX5
|
IRIX*.5.*) SYSTYPE=IRIX5
|
||||||
# Use the native compiler by default
|
# Use the native compiler by default
|
||||||
: ${CC=cc}
|
: ${CC=cc}
|
||||||
RANLIB=echo
|
RANLIB=echo
|
||||||
;;
|
;;
|
||||||
IRIX*.6*) SYSTYPE=IRIX6
|
IRIX*.6.*) SYSTYPE=IRIX6
|
||||||
# Use the native compiler by default, and allow nested comments.
|
# Use the native compiler by default, and allow nested comments.
|
||||||
: ${CC="cc -woff 1009,1116,1412"}
|
: ${CC="cc -woff 1009,1116,1412"}
|
||||||
RANLIB=echo
|
RANLIB=echo
|
||||||
|
@ -133,10 +133,8 @@
|
|||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
#include <sane_accept.h>
|
#include <sane_accept.h>
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
#include <myflock.h>
|
#include <myflock.h>
|
||||||
#include <safe_open.h>
|
#include <safe_open.h>
|
||||||
#endif
|
|
||||||
#include <listen.h>
|
#include <listen.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
@ -167,12 +165,8 @@ static char *multi_server_name;
|
|||||||
static char **multi_server_argv;
|
static char **multi_server_argv;
|
||||||
static void (*multi_server_accept) (int, char *);
|
static void (*multi_server_accept) (int, char *);
|
||||||
static void (*multi_server_onexit) (void);
|
static void (*multi_server_onexit) (void);
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
static VSTREAM *multi_server_lock;
|
static VSTREAM *multi_server_lock;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* multi_server_exit - normal termination */
|
/* multi_server_exit - normal termination */
|
||||||
|
|
||||||
static NORETURN multi_server_exit(void)
|
static NORETURN multi_server_exit(void)
|
||||||
@ -231,11 +225,9 @@ static void multi_server_execute(int unused_event, char *context)
|
|||||||
{
|
{
|
||||||
VSTREAM *stream = (VSTREAM *) context;
|
VSTREAM *stream = (VSTREAM *) context;
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (multi_server_lock != 0
|
if (multi_server_lock != 0
|
||||||
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not bother the application when the client disconnected.
|
* Do not bother the application when the client disconnected.
|
||||||
@ -290,11 +282,9 @@ static void multi_server_accept_local(int unused_event, char *context)
|
|||||||
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
|
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
|
||||||
|
|
||||||
fd = LOCAL_ACCEPT(listen_fd);
|
fd = LOCAL_ACCEPT(listen_fd);
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (multi_server_lock != 0
|
if (multi_server_lock != 0
|
||||||
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
msg_fatal("accept connection: %m");
|
msg_fatal("accept connection: %m");
|
||||||
@ -331,11 +321,9 @@ static void multi_server_accept_inet(int unused_event, char *context)
|
|||||||
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
|
time_left = event_cancel_timer(multi_server_timeout, (char *) 0);
|
||||||
|
|
||||||
fd = inet_accept(listen_fd);
|
fd = inet_accept(listen_fd);
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (multi_server_lock != 0
|
if (multi_server_lock != 0
|
||||||
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
msg_fatal("accept connection: %m");
|
msg_fatal("accept connection: %m");
|
||||||
@ -366,12 +354,8 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
|||||||
MAIL_SERVER_LOOP_FN loop = 0;
|
MAIL_SERVER_LOOP_FN loop = 0;
|
||||||
int key;
|
int key;
|
||||||
char *transport = 0;
|
char *transport = 0;
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
char *lock_path;
|
char *lock_path;
|
||||||
VSTRING *why;
|
VSTRING *why;
|
||||||
|
|
||||||
#endif
|
|
||||||
int alone = 0;
|
int alone = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -519,7 +503,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
|||||||
* Illustrated volume 2 page 532. We avoid select() collisions with an
|
* Illustrated volume 2 page 532. We avoid select() collisions with an
|
||||||
* external lock file.
|
* external lock file.
|
||||||
*/
|
*/
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (stream == 0 && !alone) {
|
if (stream == 0 && !alone) {
|
||||||
lock_path = concatenate(DEF_PID_DIR, "/", transport,
|
lock_path = concatenate(DEF_PID_DIR, "/", transport,
|
||||||
".", service_name, (char *) 0);
|
".", service_name, (char *) 0);
|
||||||
@ -531,7 +514,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
|||||||
myfree(lock_path);
|
myfree(lock_path);
|
||||||
vstring_free(why);
|
vstring_free(why);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run pre-jail initialization.
|
* Run pre-jail initialization.
|
||||||
@ -587,11 +569,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
|||||||
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
|
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
|
||||||
while (var_use_limit == 0 || use_count < var_use_limit || client_count > 0) {
|
while (var_use_limit == 0 || use_count < var_use_limit || client_count > 0) {
|
||||||
delay = loop ? loop() : -1;
|
delay = loop ? loop() : -1;
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (multi_server_lock != 0
|
if (multi_server_lock != 0
|
||||||
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_EXCLUSIVE) < 0)
|
&& myflock(vstream_fileno(multi_server_lock), MYFLOCK_EXCLUSIVE) < 0)
|
||||||
msg_fatal("select lock: %m");
|
msg_fatal("select lock: %m");
|
||||||
#endif
|
|
||||||
event_loop(delay);
|
event_loop(delay);
|
||||||
}
|
}
|
||||||
multi_server_exit();
|
multi_server_exit();
|
||||||
|
@ -124,10 +124,8 @@
|
|||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
#include <sane_accept.h>
|
#include <sane_accept.h>
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
#include <myflock.h>
|
#include <myflock.h>
|
||||||
#include <safe_open.h>
|
#include <safe_open.h>
|
||||||
#endif
|
|
||||||
#include <listen.h>
|
#include <listen.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
@ -157,12 +155,8 @@ static char *single_server_name;
|
|||||||
static char **single_server_argv;
|
static char **single_server_argv;
|
||||||
static void (*single_server_accept) (int, char *);
|
static void (*single_server_accept) (int, char *);
|
||||||
static void (*single_server_onexit) (void);
|
static void (*single_server_onexit) (void);
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
static VSTREAM *single_server_lock;
|
static VSTREAM *single_server_lock;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* single_server_exit - normal termination */
|
/* single_server_exit - normal termination */
|
||||||
|
|
||||||
static NORETURN single_server_exit(void)
|
static NORETURN single_server_exit(void)
|
||||||
@ -258,11 +252,9 @@ static void single_server_accept_local(int unused_event, char *context)
|
|||||||
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
|
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
|
||||||
|
|
||||||
fd = LOCAL_ACCEPT(listen_fd);
|
fd = LOCAL_ACCEPT(listen_fd);
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (single_server_lock != 0
|
if (single_server_lock != 0
|
||||||
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
msg_fatal("accept connection: %m");
|
msg_fatal("accept connection: %m");
|
||||||
@ -297,11 +289,9 @@ static void single_server_accept_inet(int unused_event, char *context)
|
|||||||
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
|
time_left = event_cancel_timer(single_server_timeout, (char *) 0);
|
||||||
|
|
||||||
fd = inet_accept(listen_fd);
|
fd = inet_accept(listen_fd);
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (single_server_lock != 0
|
if (single_server_lock != 0
|
||||||
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
msg_fatal("accept connection: %m");
|
msg_fatal("accept connection: %m");
|
||||||
@ -332,12 +322,8 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
|||||||
MAIL_SERVER_LOOP_FN loop = 0;
|
MAIL_SERVER_LOOP_FN loop = 0;
|
||||||
int key;
|
int key;
|
||||||
char *transport = 0;
|
char *transport = 0;
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
char *lock_path;
|
char *lock_path;
|
||||||
VSTRING *why;
|
VSTRING *why;
|
||||||
|
|
||||||
#endif
|
|
||||||
int alone = 0;
|
int alone = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -485,7 +471,6 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
|||||||
* Illustrated volume 2 page 532. We avoid select() collisions with an
|
* Illustrated volume 2 page 532. We avoid select() collisions with an
|
||||||
* external lock file.
|
* external lock file.
|
||||||
*/
|
*/
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (stream == 0 && !alone) {
|
if (stream == 0 && !alone) {
|
||||||
lock_path = concatenate(DEF_PID_DIR, "/", transport,
|
lock_path = concatenate(DEF_PID_DIR, "/", transport,
|
||||||
".", service_name, (char *) 0);
|
".", service_name, (char *) 0);
|
||||||
@ -497,7 +482,6 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
|||||||
myfree(lock_path);
|
myfree(lock_path);
|
||||||
vstring_free(why);
|
vstring_free(why);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run pre-jail initialization.
|
* Run pre-jail initialization.
|
||||||
@ -553,11 +537,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
|||||||
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
|
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
|
||||||
while (var_use_limit == 0 || use_count < var_use_limit) {
|
while (var_use_limit == 0 || use_count < var_use_limit) {
|
||||||
delay = loop ? loop() : -1;
|
delay = loop ? loop() : -1;
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (single_server_lock != 0
|
if (single_server_lock != 0
|
||||||
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_EXCLUSIVE) < 0)
|
&& myflock(vstream_fileno(single_server_lock), MYFLOCK_EXCLUSIVE) < 0)
|
||||||
msg_fatal("select lock: %m");
|
msg_fatal("select lock: %m");
|
||||||
#endif
|
|
||||||
event_loop(delay);
|
event_loop(delay);
|
||||||
}
|
}
|
||||||
single_server_exit();
|
single_server_exit();
|
||||||
|
@ -132,10 +132,8 @@
|
|||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
#include <sane_accept.h>
|
#include <sane_accept.h>
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
#include <myflock.h>
|
#include <myflock.h>
|
||||||
#include <safe_open.h>
|
#include <safe_open.h>
|
||||||
#endif
|
|
||||||
#include <listen.h>
|
#include <listen.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
@ -164,12 +162,8 @@ static char *trigger_server_name;
|
|||||||
static char **trigger_server_argv;
|
static char **trigger_server_argv;
|
||||||
static void (*trigger_server_accept) (int, char *);
|
static void (*trigger_server_accept) (int, char *);
|
||||||
static void (*trigger_server_onexit) (void);
|
static void (*trigger_server_onexit) (void);
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
static VSTREAM *trigger_server_lock;
|
static VSTREAM *trigger_server_lock;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* trigger_server_exit - normal termination */
|
/* trigger_server_exit - normal termination */
|
||||||
|
|
||||||
static NORETURN trigger_server_exit(void)
|
static NORETURN trigger_server_exit(void)
|
||||||
@ -239,11 +233,9 @@ static void trigger_server_accept_fifo(int unused_event, char *context)
|
|||||||
char *myname = "trigger_server_accept_fifo";
|
char *myname = "trigger_server_accept_fifo";
|
||||||
int listen_fd = (int) context;
|
int listen_fd = (int) context;
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (trigger_server_lock != 0
|
if (trigger_server_lock != 0
|
||||||
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: trigger arrived", myname);
|
msg_info("%s: trigger arrived", myname);
|
||||||
@ -291,11 +283,9 @@ static void trigger_server_accept_local(int unused_event, char *context)
|
|||||||
time_left = event_cancel_timer(trigger_server_timeout, (char *) 0);
|
time_left = event_cancel_timer(trigger_server_timeout, (char *) 0);
|
||||||
|
|
||||||
fd = LOCAL_ACCEPT(listen_fd);
|
fd = LOCAL_ACCEPT(listen_fd);
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (trigger_server_lock != 0
|
if (trigger_server_lock != 0
|
||||||
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
|
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_NONE) < 0)
|
||||||
msg_fatal("select unlock: %m");
|
msg_fatal("select unlock: %m");
|
||||||
#endif
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
msg_fatal("accept connection: %m");
|
msg_fatal("accept connection: %m");
|
||||||
@ -333,12 +323,8 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
|||||||
char buf[TRIGGER_BUF_SIZE];
|
char buf[TRIGGER_BUF_SIZE];
|
||||||
int len;
|
int len;
|
||||||
char *transport = 0;
|
char *transport = 0;
|
||||||
|
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
char *lock_path;
|
char *lock_path;
|
||||||
VSTRING *why;
|
VSTRING *why;
|
||||||
|
|
||||||
#endif
|
|
||||||
int alone = 0;
|
int alone = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -500,7 +486,6 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
|||||||
* Illustrated volume 2 page 532. We avoid select() collisions with an
|
* Illustrated volume 2 page 532. We avoid select() collisions with an
|
||||||
* external lock file.
|
* external lock file.
|
||||||
*/
|
*/
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (stream == 0 && !alone) {
|
if (stream == 0 && !alone) {
|
||||||
lock_path = concatenate(DEF_PID_DIR, "/", transport,
|
lock_path = concatenate(DEF_PID_DIR, "/", transport,
|
||||||
".", service_name, (char *) 0);
|
".", service_name, (char *) 0);
|
||||||
@ -512,7 +497,6 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
|||||||
myfree(lock_path);
|
myfree(lock_path);
|
||||||
vstring_free(why);
|
vstring_free(why);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run pre-jail initialization.
|
* Run pre-jail initialization.
|
||||||
@ -565,11 +549,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
|||||||
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
|
close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC);
|
||||||
while (var_use_limit == 0 || use_count < var_use_limit) {
|
while (var_use_limit == 0 || use_count < var_use_limit) {
|
||||||
delay = loop ? loop() : -1;
|
delay = loop ? loop() : -1;
|
||||||
#ifndef NO_SELECT_COLLISION
|
|
||||||
if (trigger_server_lock != 0
|
if (trigger_server_lock != 0
|
||||||
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_EXCLUSIVE) < 0)
|
&& myflock(vstream_fileno(trigger_server_lock), MYFLOCK_EXCLUSIVE) < 0)
|
||||||
msg_fatal("select lock: %m");
|
msg_fatal("select lock: %m");
|
||||||
#endif
|
|
||||||
event_loop(delay);
|
event_loop(delay);
|
||||||
}
|
}
|
||||||
trigger_server_exit();
|
trigger_server_exit();
|
||||||
|
@ -280,13 +280,26 @@ char *var_always_bcc;
|
|||||||
*/
|
*/
|
||||||
char *smtpd_path;
|
char *smtpd_path;
|
||||||
|
|
||||||
|
/* collapse_args - put arguments together again */
|
||||||
|
|
||||||
|
static void collapse_args(int argc, SMTPD_TOKEN *argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 2; i < argc; i++) {
|
||||||
|
vstring_strcat(argv[1].vstrval, " ");
|
||||||
|
vstring_strcat(argv[1].vstrval, argv[i].strval);
|
||||||
|
}
|
||||||
|
argv[1].strval = vstring_str(argv[1].vstrval);
|
||||||
|
}
|
||||||
|
|
||||||
/* helo_cmd - process HELO command */
|
/* helo_cmd - process HELO command */
|
||||||
|
|
||||||
static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc < 2) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Syntax: HELO hostname");
|
smtpd_chat_reply(state, "501 Syntax: HELO hostname");
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -296,6 +309,7 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "503 Duplicate HELO/EHLO");
|
smtpd_chat_reply(state, "503 Duplicate HELO/EHLO");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
collapse_args(argc, argv);
|
||||||
if (SMTPD_STAND_ALONE(state) == 0
|
if (SMTPD_STAND_ALONE(state) == 0
|
||||||
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
|
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
|
||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
@ -313,7 +327,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc < 2) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Syntax: EHLO hostname");
|
smtpd_chat_reply(state, "501 Syntax: EHLO hostname");
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -323,6 +337,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "503 Error: duplicate HELO/EHLO");
|
smtpd_chat_reply(state, "503 Error: duplicate HELO/EHLO");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
collapse_args(argc, argv);
|
||||||
if (SMTPD_STAND_ALONE(state) == 0
|
if (SMTPD_STAND_ALONE(state) == 0
|
||||||
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
|
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
|
||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
@ -758,9 +773,7 @@ static int noop_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
|
|
||||||
static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||||
{
|
{
|
||||||
VSTRING *buf;
|
|
||||||
char *err = 0;
|
char *err = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The SMTP standard (RFC 821) disallows unquoted special characters in
|
* The SMTP standard (RFC 821) disallows unquoted special characters in
|
||||||
@ -772,18 +785,9 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "501 Syntax: VRFY address");
|
smtpd_chat_reply(state, "501 Syntax: VRFY address");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
collapse_args(argc, argv);
|
||||||
/*
|
|
||||||
* Yuck. All input is tokenized. Now put it back together again.
|
|
||||||
*/
|
|
||||||
buf = vstring_alloc(100);
|
|
||||||
for (i = 1; i < argc; i++) {
|
|
||||||
vstring_strcat(buf, " ");
|
|
||||||
vstring_strcat(buf, argv[i].strval);
|
|
||||||
}
|
|
||||||
if (SMTPD_STAND_ALONE(state) == 0)
|
if (SMTPD_STAND_ALONE(state) == 0)
|
||||||
err = smtpd_check_rcpt(state, vstring_str(buf));
|
err = smtpd_check_rcpt(state, argv[1].strval);
|
||||||
vstring_free(buf);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End untokenize.
|
* End untokenize.
|
||||||
|
@ -108,11 +108,16 @@
|
|||||||
/* Reject the request when the HELO/EHLO hostname has no A or MX record.
|
/* Reject the request when the HELO/EHLO hostname has no A or MX record.
|
||||||
/* The \fIunknown_hostname_reject_code\fR configuration
|
/* The \fIunknown_hostname_reject_code\fR configuration
|
||||||
/* parameter specifies the reject status code (default: 450).
|
/* parameter specifies the reject status code (default: 450).
|
||||||
/* .IP reject_unknown_address
|
/* .IP reject_unknown_sender_domain
|
||||||
/* Reject the request when the resolved sender address has no
|
/* Reject the request when the resolved sender address has no
|
||||||
/* DNS A or MX record.
|
/* DNS A or MX record.
|
||||||
/* The \fIunknown_address_reject_code\fR configuration parameter
|
/* The \fIunknown_address_reject_code\fR configuration parameter
|
||||||
/* specifies the reject status code (default: 450).
|
/* specifies the reject status code (default: 450).
|
||||||
|
/* .IP reject_unknown_recipient_domain
|
||||||
|
/* Reject the request when the resolved recipient address has no
|
||||||
|
/* DNS A or MX record.
|
||||||
|
/* The \fIunknown_address_reject_code\fR configuration parameter
|
||||||
|
/* specifies the reject status code (default: 450).
|
||||||
/* .IP check_relay_domains
|
/* .IP check_relay_domains
|
||||||
/* Allow the request when either the client hostname or the resolved
|
/* Allow the request when either the client hostname or the resolved
|
||||||
/* recipient domain matches the \fIrelay_domains\fR configuration
|
/* recipient domain matches the \fIrelay_domains\fR configuration
|
||||||
@ -577,7 +582,8 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, char *name)
|
|||||||
if (dns_status != DNS_OK)
|
if (dns_status != DNS_OK)
|
||||||
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||||
"%d <%s>: Domain not found",
|
"%d <%s>: Domain not found",
|
||||||
var_unk_addr_code, name));
|
dns_status == DNS_NOTFOUND ?
|
||||||
|
var_unk_addr_code : 450, name));
|
||||||
return (SMTPD_CHECK_DUNNO);
|
return (SMTPD_CHECK_DUNNO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1197,6 +1203,10 @@ static int generic_checks(SMTPD_STATE *state, char *name,
|
|||||||
*status = reject_unknown_address(state, state->sender);
|
*status = reject_unknown_address(state, state->sender);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
if (strcasecmp(name, REJECT_UNKNOWN_SENDDOM) == 0) {
|
||||||
|
*status = reject_unknown_address(state, state->sender);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) {
|
if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) {
|
||||||
if (*state->sender)
|
if (*state->sender)
|
||||||
*status = reject_non_fqdn_address(state, state->sender);
|
*status = reject_non_fqdn_address(state, state->sender);
|
||||||
@ -1336,6 +1346,8 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
|
|||||||
status = permit_mx_backup(state, recipient);
|
status = permit_mx_backup(state, recipient);
|
||||||
} else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) {
|
} else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) {
|
||||||
status = check_relay_domains(state, recipient);
|
status = check_relay_domains(state, recipient);
|
||||||
|
} else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
|
||||||
|
status = reject_unknown_address(state, recipient);
|
||||||
} else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) {
|
} else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) {
|
||||||
status = reject_non_fqdn_address(state, recipient);
|
status = reject_non_fqdn_address(state, recipient);
|
||||||
} else if (generic_checks(state, name, &cpp, &status, recipient) == 0) {
|
} else if (generic_checks(state, name, &cpp, &status, recipient) == 0) {
|
||||||
|
@ -83,3 +83,13 @@ mail foo@friend.bad.domain
|
|||||||
client_restrictions reject_maps_rbl
|
client_restrictions reject_maps_rbl
|
||||||
client spike.porcupine.org 168.100.189.2
|
client spike.porcupine.org 168.100.189.2
|
||||||
client foo 127.0.0.2
|
client foo 127.0.0.2
|
||||||
|
#
|
||||||
|
# unknown sender/recipient domain
|
||||||
|
#
|
||||||
|
unknown_address_reject_code 550
|
||||||
|
recipient_restrictions reject_unknown_recipient_domain,reject_unknown_sender_domain
|
||||||
|
mail wietse@porcupine.org
|
||||||
|
rcpt wietse@porcupine.org
|
||||||
|
rcpt wietse@no.recipient.domain
|
||||||
|
mail wietse@no.sender.domain
|
||||||
|
rcpt wietse@porcupine.org
|
||||||
|
@ -172,3 +172,22 @@ OK
|
|||||||
>>> client foo 127.0.0.2
|
>>> client foo 127.0.0.2
|
||||||
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 550 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
|
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 550 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
|
||||||
550 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
|
550 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
|
||||||
|
>>> #
|
||||||
|
>>> # unknown sender/recipient domain
|
||||||
|
>>> #
|
||||||
|
>>> unknown_address_reject_code 550
|
||||||
|
OK
|
||||||
|
>>> recipient_restrictions reject_unknown_recipient_domain,reject_unknown_sender_domain
|
||||||
|
OK
|
||||||
|
>>> mail wietse@porcupine.org
|
||||||
|
OK
|
||||||
|
>>> rcpt wietse@porcupine.org
|
||||||
|
OK
|
||||||
|
>>> rcpt wietse@no.recipient.domain
|
||||||
|
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 550 <no.recipient.domain>: Domain not found
|
||||||
|
550 <no.recipient.domain>: Domain not found
|
||||||
|
>>> mail wietse@no.sender.domain
|
||||||
|
OK
|
||||||
|
>>> rcpt wietse@porcupine.org
|
||||||
|
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 550 <no.sender.domain>: Domain not found
|
||||||
|
550 <no.sender.domain>: Domain not found
|
||||||
|
@ -55,7 +55,8 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
|||||||
timed_connect.h timed_wait.h trigger.h username.h valid_hostname.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 \
|
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
|
||||||
dict_unix.h dict_pcre.h
|
dict_unix.h dict_pcre.h
|
||||||
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c
|
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
||||||
|
stream_test.c
|
||||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||||
-Wunused
|
-Wunused
|
||||||
@ -68,7 +69,7 @@ TESTPROG= dict_open events exec_command fifo_open fifo_rdonly_bug \
|
|||||||
fifo_rdwr_bug fifo_trigger fsspace fullname inet_addr_host \
|
fifo_rdwr_bug fifo_trigger fsspace fullname inet_addr_host \
|
||||||
inet_addr_local mac_parse make_dirs msg_syslog \
|
inet_addr_local mac_parse make_dirs msg_syslog \
|
||||||
mystrtok peer_name sigdelay translit valid_hostname vstream_popen \
|
mystrtok peer_name sigdelay translit valid_hostname vstream_popen \
|
||||||
vstring vstring_vstream doze select_bug
|
vstring vstring_vstream doze select_bug stream_test
|
||||||
|
|
||||||
LIB_DIR = ../lib
|
LIB_DIR = ../lib
|
||||||
INC_DIR = ../include
|
INC_DIR = ../include
|
||||||
@ -237,6 +238,9 @@ depend: $(MAKES)
|
|||||||
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
|
done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
|
||||||
@make Makefile
|
@make Makefile
|
||||||
|
|
||||||
|
stream_test: stream_test.c $(LIB)
|
||||||
|
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
|
|
||||||
tests: valid_hostname_test
|
tests: valid_hostname_test
|
||||||
|
|
||||||
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
|
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
|
||||||
@ -664,15 +668,6 @@ select_bug.o: msg.h
|
|||||||
select_bug.o: vstream.h
|
select_bug.o: vstream.h
|
||||||
select_bug.o: vbuf.h
|
select_bug.o: vbuf.h
|
||||||
select_bug.o: msg_vstream.h
|
select_bug.o: msg_vstream.h
|
||||||
sendfd_test.o: sendfd_test.c
|
|
||||||
sendfd_test.o: sys_defs.h
|
|
||||||
sendfd_test.o: sendfd_test.c
|
|
||||||
sendfd_test.o: iostuff.h
|
|
||||||
sendfd_test.o: msg.h
|
|
||||||
sendfd_test.o: msg_vstream.h
|
|
||||||
sendfd_test.o: vstream.h
|
|
||||||
sendfd_test.o: vbuf.h
|
|
||||||
sendfd_test.o: listen.h
|
|
||||||
set_eugid.o: set_eugid.c
|
set_eugid.o: set_eugid.c
|
||||||
set_eugid.o: sys_defs.h
|
set_eugid.o: sys_defs.h
|
||||||
set_eugid.o: msg.h
|
set_eugid.o: msg.h
|
||||||
@ -707,6 +702,16 @@ stream_listen.o: sys_defs.h
|
|||||||
stream_listen.o: msg.h
|
stream_listen.o: msg.h
|
||||||
stream_listen.o: listen.h
|
stream_listen.o: listen.h
|
||||||
stream_listen.o: iostuff.h
|
stream_listen.o: iostuff.h
|
||||||
|
stream_test.o: stream_test.c
|
||||||
|
stream_test.o: sys_defs.h
|
||||||
|
stream_test.o: stream_test.c
|
||||||
|
stream_test.o: iostuff.h
|
||||||
|
stream_test.o: msg.h
|
||||||
|
stream_test.o: msg_vstream.h
|
||||||
|
stream_test.o: vstream.h
|
||||||
|
stream_test.o: vbuf.h
|
||||||
|
stream_test.o: listen.h
|
||||||
|
stream_test.o: connect.h
|
||||||
stream_trigger.o: stream_trigger.c
|
stream_trigger.o: stream_trigger.c
|
||||||
stream_trigger.o: sys_defs.h
|
stream_trigger.o: sys_defs.h
|
||||||
stream_trigger.o: msg.h
|
stream_trigger.o: msg.h
|
||||||
|
Binary file not shown.
@ -41,10 +41,16 @@
|
|||||||
/* System library. */
|
/* System library. */
|
||||||
|
|
||||||
#include <sys_defs.h>
|
#include <sys_defs.h>
|
||||||
|
|
||||||
|
#ifdef STREAM_CONNECTIONS
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stropts.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@ -57,46 +63,41 @@ int stream_connect(const char *path, int block_mode, int unused_timeout)
|
|||||||
{
|
{
|
||||||
#ifdef STREAM_CONNECTIONS
|
#ifdef STREAM_CONNECTIONS
|
||||||
char *myname = "stream_connect";
|
char *myname = "stream_connect";
|
||||||
struct stat st;
|
int pair[2];
|
||||||
int fd;
|
int fifo;
|
||||||
int flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The requested file system object must exist, otherwise we can't reach
|
* The requested file system object must exist, otherwise we can't reach
|
||||||
* the server.
|
* the server.
|
||||||
*/
|
*/
|
||||||
if (block_mode == NON_BLOCKING)
|
if ((fifo = open(path, O_WRONLY | O_NONBLOCK, 0)) < 0)
|
||||||
flags = O_RDWR | O_NONBLOCK;
|
|
||||||
else
|
|
||||||
flags = O_RDWR;
|
|
||||||
if ((fd = open(path, flags, 0)) < 0)
|
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Horror. If the open() result is a regular file, no server was
|
* Create a pipe, and send one pipe end to the server.
|
||||||
* listening. In this case we simulate what would have happened with
|
|
||||||
* UNIX-domain sockets.
|
|
||||||
*/
|
*/
|
||||||
if (fstat(fd, &st) < 0)
|
if (pipe(pair) < 0)
|
||||||
msg_fatal("%s: fstat: %m", myname);
|
msg_fatal("%s: pipe: %m", myname);
|
||||||
if (S_ISREG(st.st_mode)) {
|
if (ioctl(fifo, I_SENDFD, pair[1]) < 0)
|
||||||
close(fd);
|
msg_fatal("%s: send file descriptor: %m", myname);
|
||||||
errno = ECONNREFUSED;
|
close(pair[1]);
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is for {unix,inet}_connect() compatibility.
|
* This is for {unix,inet}_connect() compatibility.
|
||||||
*/
|
*/
|
||||||
if (block_mode == NON_BLOCKING)
|
if (block_mode == NON_BLOCKING)
|
||||||
non_blocking(fd, NON_BLOCKING);
|
non_blocking(pair[0], NON_BLOCKING);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No trouble detected, so far.
|
* Cleanup.
|
||||||
*/
|
*/
|
||||||
return (fd);
|
close(fifo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keep the other end of the pipe.
|
||||||
|
*/
|
||||||
|
return (pair[0]);
|
||||||
#else
|
#else
|
||||||
msg_fatal("stream connections are not implemented");
|
msg_fatal("stream connections are not implemented");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,16 +29,13 @@
|
|||||||
/* .IP backlog
|
/* .IP backlog
|
||||||
/* This argument exists for compatibility and is ignored.
|
/* This argument exists for compatibility and is ignored.
|
||||||
/* .IP block_mode
|
/* .IP block_mode
|
||||||
/* This argument exists for compatibility and is ignored.
|
/* Either NON_BLOCKING or BLOCKING. This does not affect the
|
||||||
/* blocking mode.
|
/* mode of accepted connections.
|
||||||
/* .IP fd
|
/* .IP fd
|
||||||
/* File descriptor returned by stream_listen().
|
/* File descriptor returned by stream_listen().
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* Fatal errors: stream_listen() aborts upon any system call failure.
|
/* Fatal errors: stream_listen() aborts upon any system call failure.
|
||||||
/* stream_accept() leaves all error handling up to the caller.
|
/* stream_accept() leaves all error handling up to the caller.
|
||||||
/* BUGS
|
|
||||||
/* This implementation leaks one file descriptor. This is fixed when
|
|
||||||
/* endpoints become objects rather than file descriptors.
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -71,46 +68,15 @@
|
|||||||
|
|
||||||
/* stream_listen - create stream listener */
|
/* stream_listen - create stream listener */
|
||||||
|
|
||||||
int stream_listen(const char *path, int unused_backlog,
|
int stream_listen(const char *path, int unused_backlog, int block_mode)
|
||||||
int unused_block_mode)
|
|
||||||
{
|
{
|
||||||
#ifdef STREAM_CONNECTIONS
|
#ifdef STREAM_CONNECTIONS
|
||||||
char *myname = "stream_listen";
|
|
||||||
static int pair[2];
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize: create the specified endpoint with the right permissions.
|
* We can't specify a listen backlog, however, sending file descriptors
|
||||||
|
* across a FIFO gives us a backlog buffer of 460 on Solaris 2.4/SPARC.
|
||||||
*/
|
*/
|
||||||
#define PERMS 0666
|
return (fifo_listen(path, 0666, block_mode));
|
||||||
if (unlink(path) && errno != ENOENT)
|
|
||||||
msg_fatal("%s: remove %s: %m", myname, path);
|
|
||||||
if ((fd = open(path, PERMS, O_CREAT | O_TRUNC | O_WRONLY)) < 0)
|
|
||||||
msg_fatal("%s: create file %s: %m", myname, path);
|
|
||||||
if (fchmod(fd, PERMS) < 0)
|
|
||||||
msg_fatal("%s: chmod 0%o: %m", myname, PERMS);
|
|
||||||
if (close(fd) < 0)
|
|
||||||
msg_fatal("%s: close file %s: %m", myname, path);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Associate one pipe end with the file just created. See: Richard
|
|
||||||
* Stevens, Advanced Programming in the UNIX Environment Ch. 15.5.1
|
|
||||||
*
|
|
||||||
* On Solaris 2.4/SPARC, this gives us a "listen queue" of some 460
|
|
||||||
* connections.
|
|
||||||
*/
|
|
||||||
if (pipe(pair) < 0)
|
|
||||||
msg_fatal("%s: create pipe: %m", myname);
|
|
||||||
if (ioctl(pair[1], I_PUSH, "connld") < 0)
|
|
||||||
msg_fatal("%s: push connld module: %m", myname);
|
|
||||||
if (fattach(pair[1], path) < 0)
|
|
||||||
msg_fatal("%s: fattach %s: %m", myname, path);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return one end, and leak the other. This will be fixed when all
|
|
||||||
* endpoints are objects instead of bare file descriptors.
|
|
||||||
*/
|
|
||||||
return (pair[0]);
|
|
||||||
#else
|
#else
|
||||||
msg_fatal("stream connections are not implemented");
|
msg_fatal("stream connections are not implemented");
|
||||||
#endif
|
#endif
|
||||||
@ -131,6 +97,6 @@ int stream_accept(int fd)
|
|||||||
return (-1);
|
return (-1);
|
||||||
return (fdinfo.fd);
|
return (fdinfo.fd);
|
||||||
#else
|
#else
|
||||||
msg_fatal("stream connections are not implemented");
|
msg_fatal("stream connections are not implemented");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "msg_vstream.h"
|
#include "msg_vstream.h"
|
||||||
#include "listen.h"
|
#include "listen.h"
|
||||||
|
#include "connect.h"
|
||||||
|
|
||||||
#define FIFO "/tmp/test-fifo"
|
#define FIFO "/tmp/test-fifo"
|
||||||
|
|
||||||
@ -33,9 +34,9 @@ static NORETURN usage(void)
|
|||||||
|
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct strrecvfd fdinfo;
|
|
||||||
int server_fd;
|
int server_fd;
|
||||||
int client_fd;
|
int client_fd;
|
||||||
|
int fd;
|
||||||
int print_fstats = 0;
|
int print_fstats = 0;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
int ch;
|
int ch;
|
||||||
@ -63,43 +64,39 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server_fd = fifo_listen(FIFO, 0600, NON_BLOCKING);
|
server_fd = stream_listen(FIFO, 0, 0);
|
||||||
if (readable(server_fd))
|
if (readable(server_fd))
|
||||||
msg_fatal("server fd is readable after create");
|
msg_fatal("server fd is readable after create");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect in client.
|
* Connect in client.
|
||||||
*/
|
*/
|
||||||
if ((client_fd = open(FIFO, O_RDWR, NON_BLOCKING)) < 0)
|
|
||||||
msg_fatal("open %s as client: %m", FIFO);
|
|
||||||
if (readable(server_fd))
|
|
||||||
msg_warn("server fd is readable after client open");
|
|
||||||
if (print_fstats)
|
|
||||||
print_fstat(0);
|
|
||||||
if (ioctl(client_fd, I_RECVFD, &fdinfo) < 0)
|
|
||||||
msg_fatal("receive fd: %m");
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
msg_info("send attempt %d", i);
|
msg_info("connect attempt %d", i);
|
||||||
while (!writable(client_fd))
|
if ((client_fd = stream_connect(FIFO, 0, 0)) < 0)
|
||||||
msg_info("wait for client fd to become writable");
|
msg_fatal("open %s as client: %m", FIFO);
|
||||||
if (ioctl(client_fd, I_SENDFD, 0) < 0)
|
if (readable(server_fd))
|
||||||
msg_fatal("send fd to server: %m");
|
msg_info("server fd is readable after client open");
|
||||||
|
if (close(client_fd) < 0)
|
||||||
|
msg_fatal("close client fd: %m");
|
||||||
}
|
}
|
||||||
if (close(client_fd) < 0)
|
|
||||||
msg_fatal("close client fd: %m");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accept in server.
|
* Accept in server.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
msg_info("receive attempt %d", i);
|
msg_info("receive attempt %d", i);
|
||||||
while (!readable(server_fd))
|
if (!readable(server_fd)) {
|
||||||
msg_info("wait for server fd to become writable");
|
msg_info("wait for server fd to become readable");
|
||||||
if (ioctl(server_fd, I_RECVFD, &fdinfo) < 0)
|
read_wait(server_fd, -1);
|
||||||
|
}
|
||||||
|
if ((fd = stream_accept(server_fd)) < 0)
|
||||||
msg_fatal("receive fd: %m");
|
msg_fatal("receive fd: %m");
|
||||||
if (print_fstats)
|
if (print_fstats)
|
||||||
print_fstat(fdinfo.fd);
|
print_fstat(fd);
|
||||||
if (close(fdinfo.fd) < 0)
|
if (close(fd) < 0)
|
||||||
msg_fatal("close received fd: %m");
|
msg_fatal("close received fd: %m");
|
||||||
}
|
}
|
||||||
|
if (close(server_fd) < 0)
|
||||||
|
msg_fatal("close server fd");
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user