From 733982dd3c6c235ced6713045e36e3928f60147f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Veyret?= Date: Sun, 3 May 2020 21:23:12 +0200 Subject: [PATCH] Manage unix socket --- doc/nullmailer-send.8 | 9 +++++++++ lib/Makefile.am | 2 +- lib/connect.h | 1 + lib/{tcpconnect.cc => socketconnect.cc} | 17 ++++++++++++++++ protocols/protocol.cc | 27 ++++++++++++++++--------- 5 files changed, 46 insertions(+), 10 deletions(-) rename lib/{tcpconnect.cc => socketconnect.cc} (91%) diff --git a/doc/nullmailer-send.8 b/doc/nullmailer-send.8 index 34e5f96..39bb932 100644 --- a/doc/nullmailer-send.8 +++ b/doc/nullmailer-send.8 @@ -134,6 +134,15 @@ Set the SMTP authentication password. .BI source= HOSTNAME Set the source address for connections to the remote host. .TP +.BI unix-socket=\fISOCKETNAME +Set the unix socket to connect to. When this option is set, neither +.B port +nor +.B source +can be used, and +.B hostname +is ignored. +.TP .B auth-login Force SMTP "AUTH LOGIN" mode instead of auto-detecting. .TP diff --git a/lib/Makefile.am b/lib/Makefile.am index 88e5b35..03c9c63 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,7 +13,7 @@ libmisc_a_SOURCES = \ canonicalize.h canonicalize.cc \ configio.h config_path.cc \ config_read.cc config_readlist.cc config_readint.cc config_syserr.cc \ - connect.h tcpconnect.cc \ + connect.h socketconnect.cc \ defines.h \ errcodes.h errcodes.cc \ hostname.h hostname.cc \ diff --git a/lib/connect.h b/lib/connect.h index d3354b0..77ffdf1 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -2,5 +2,6 @@ #define NULLMAILER_CONNECT__H__ extern int tcpconnect(const char* hostname, int port, const char* source); +extern int unixconnect(const char* unix_socket); #endif // NULLMAILER_CONNECT__H__ diff --git a/lib/tcpconnect.cc b/lib/socketconnect.cc similarity index 91% rename from lib/tcpconnect.cc rename to lib/socketconnect.cc index 04d2338..c34a1f4 100644 --- a/lib/tcpconnect.cc +++ b/lib/socketconnect.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -173,3 +174,19 @@ int tcpconnect(const char* hostname, int port, const char* source) } #endif + +int unixconnect(const char* unix_socket) +{ + struct sockaddr_un sa; + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + strncpy(sa.sun_path, unix_socket, sizeof(sa.sun_path) - 1); + int s = socket(PF_UNIX, SOCK_STREAM, 0); + if(s == -1) + return -ERR_SOCKET; + if(connect(s, (sockaddr*)&sa, sizeof(sa)) != 0) { + close(s); + return err_return(errno, ERR_CONN_FAILED); + } + return s; +} diff --git a/protocols/protocol.cc b/protocols/protocol.cc index 6c43d55..5368437 100644 --- a/protocols/protocol.cc +++ b/protocols/protocol.cc @@ -35,6 +35,7 @@ int port = 0; int auth_method = AUTH_DETECT; int use_tls = 0; int use_starttls = 0; +const char* unix_socket = 0; const char* remote = 0; const char* source = 0; const char* cli_help_suffix = ""; @@ -42,6 +43,8 @@ const char* cli_args_usage = "< options 3< mail-file"; const int cli_args_min = 0; const int cli_args_max = 0; cli_option cli_options[] = { + { 0, "unix-socket", cli_option::string, 0, &unix_socket, + "Set the path to the unix socket for the remote", 0 }, { 0, "host", cli_option::string, 0, &remote, "Set the hostname for the remote", 0 }, { 'p', "port", cli_option::integer, 0, &port, @@ -134,17 +137,23 @@ static void parse_options(void) int cli_main(int, char*[]) { parse_options(); - if (remote == 0) - protocol_fail(ERR_USAGE, "Remote host not set"); - if (port == 0) - port = use_tls ? default_tls_port : default_port; - if (port < 0) - protocol_fail(ERR_USAGE, "Invalid value for port"); - if (use_tls || use_starttls) - tls_init(remote); + if (unix_socket == 0) { + if (remote == 0) + protocol_fail(ERR_USAGE, "Remote host not set"); + if (port == 0) + port = use_tls ? default_tls_port : default_port; + if (port < 0) + protocol_fail(ERR_USAGE, "Invalid value for port"); + if (use_tls || use_starttls) + tls_init(remote); + } + else if (port != 0 || source != 0) + protocol_fail(ERR_USAGE, "Both INET and UNIX socket specified"); fdibuf in(3, true); protocol_prep(in); - int fd = tcpconnect(remote, port, source); + int fd = unix_socket == 0 + ? tcpconnect(remote, port, source) + : unixconnect(unix_socket); if(fd < 0) protocol_fail(-fd, "Connect failed"); if (use_tls)