summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-11-01 10:56:08 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-11-01 10:56:08 +0200
commit4e7bcdbae346a26c1addf266a23c1f6cdc74533f (patch)
tree30f6721129f8a7688814b9dc88727e810770fbda
parenta5e929972db1342beec4b8f577399f2d8d9a76c2 (diff)
downloadmailutils-4e7bcdbae346a26c1addf266a23c1f6cdc74533f.tar.gz
mailutils-4e7bcdbae346a26c1addf266a23c1f6cdc74533f.tar.bz2
Improve socket and SMTP client API
Split formatting functions into two distinct families. Functions prefixed with mu_sys_sockadrr deal with struct sockaddr, wherease those starting with mu_sockaddr deal with struct mu_sockaddr. Introduce special format for SMTP EHLO. When sending EHLO to the remote party, use IP address in square brackets if hostname is empty. * libmailutils/sockaddr/Makefile.am (libsockaddr_la_SOURCES): Add fromsock.c * libmailutils/sockaddr/fromsock.c: New function. * libmailutils/sockaddr/str.c (mu_sockaddr_format): Rewrite. (mu_sys_sockaddr_format,mu_sys_sockaddr_to_astr): New functions. * include/mailutils/debug.h (mu_sockaddr_to_astr): Remove prototype. * include/mailutils/sockaddr.h (mu_sockaddr_format): New enum. (mu_sockaddr_format): change signature. (mu_sys_sockaddr_format,mu_sys_sockaddr_to_astr): New prototypes. (mu_sockaddr_from_socket): New prototype. * include/mailutils/stream.h (MU_IOCTL_TCPSTREAM): New ioctl family; (MU_IOCTL_TCP_GETSOCKNAME): New ioctl opcode. * comsat/comsat.c: Use mu_sys_sockaddr_ interface to handle struct sockaddr. * lib/tcpwrap.c: Likewise. * libmailutils/server/ipsrv.c: Likewise. * libmailutils/server/msrv.c: Likewise. * libmailutils/stream/tcp.c (_tcp_ioctl): Handle MU_IOCTL_TCPSTREAM. * libproto/mailer/smtp_ehlo.c (mu_smtp_ehlo): If hostname is empty, use IP address in square brackets.
-rw-r--r--comsat/comsat.c3
-rw-r--r--include/mailutils/debug.h4
-rw-r--r--include/mailutils/sockaddr.h18
-rw-r--r--include/mailutils/stream.h9
-rw-r--r--lib/tcpwrap.c2
-rw-r--r--libmailutils/server/ipsrv.c4
-rw-r--r--libmailutils/server/msrv.c6
-rw-r--r--libmailutils/sockaddr/Makefile.am1
-rw-r--r--libmailutils/sockaddr/fromsock.c38
-rw-r--r--libmailutils/sockaddr/str.c85
-rw-r--r--libmailutils/stream/tcp.c19
-rw-r--r--libproto/mailer/smtp_ehlo.c43
12 files changed, 193 insertions, 39 deletions
diff --git a/comsat/comsat.c b/comsat/comsat.c
index a60258a7b..d0fd5ad8b 100644
--- a/comsat/comsat.c
+++ b/comsat/comsat.c
@@ -18,6 +18,7 @@
#include "comsat.h"
#include "mailutils/syslog.h"
#include "mailutils/cli.h"
+#include "mailutils/sockaddr.h"
#ifndef PATH_DEV
# define PATH_DEV "/dev"
@@ -371,7 +372,7 @@ comsat_connection (int fd, struct sockaddr *sa, int salen,
return 0;
if (pconf->transcript)
{
- char *p = mu_sockaddr_to_astr (sa, salen);
+ char *p = mu_sys_sockaddr_to_astr (sa, salen);
mu_diag_output (MU_DIAG_INFO,
ngettext ("received %lu byte from %s",
"received %lu bytes from %s",
diff --git a/include/mailutils/debug.h b/include/mailutils/debug.h
index 8ec2e88c7..ab06e49e5 100644
--- a/include/mailutils/debug.h
+++ b/include/mailutils/debug.h
@@ -52,10 +52,6 @@ extern int mu_debug_line_info;
((a) == 0 ? MU_DEBUG_LEVEL_UPTO (b) : \
MU_DEBUG_LEVEL_UPTO (b) & ~MU_DEBUG_LEVEL_UPTO ((a) - 1))
-
-struct sockaddr;
-char *mu_sockaddr_to_astr (const struct sockaddr *sa, int salen);
-
size_t mu_debug_register_category (char *name);
size_t mu_debug_next_handle (void);
diff --git a/include/mailutils/sockaddr.h b/include/mailutils/sockaddr.h
index 953ab26fe..8525b87ae 100644
--- a/include/mailutils/sockaddr.h
+++ b/include/mailutils/sockaddr.h
@@ -56,15 +56,27 @@ void mu_sockaddr_free_list (struct mu_sockaddr *addr);
struct mu_sockaddr *mu_sockaddr_insert (struct mu_sockaddr *anchor,
struct mu_sockaddr *addr,
int before);
-const char *mu_sockaddr_str (struct mu_sockaddr *addr);
+enum mu_sockaddr_format
+ {
+ mu_sockaddr_format_default,
+ mu_sockaddr_format_ehlo
+ };
-int mu_sockaddr_format (char **pbuf, const struct sockaddr *sa,
- socklen_t salen);
+int mu_sys_sockaddr_format (char **pbuf,
+ enum mu_sockaddr_format fmt,
+ const struct sockaddr *sa, socklen_t salen);
+char *mu_sys_sockaddr_to_astr (const struct sockaddr *sa, int salen);
+
+int mu_sockaddr_format (struct mu_sockaddr *sa, char **pbuf,
+ enum mu_sockaddr_format fmt);
+
+const char *mu_sockaddr_str (struct mu_sockaddr *addr);
int mu_sockaddr_from_node (struct mu_sockaddr **retval, const char *node,
const char *serv, struct mu_sockaddr_hints *hints);
int mu_sockaddr_from_url (struct mu_sockaddr **retval, mu_url_t url,
struct mu_sockaddr_hints *hints);
+int mu_sockaddr_from_socket (struct mu_sockaddr **retval, int fd);
int mu_str_is_ipv4 (const char *addr);
int mu_str_is_ipv6 (const char *addr);
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index 4e82b9239..53dce6f46 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -79,6 +79,7 @@ enum mu_buffer_type
*/
#define MU_IOCTL_TLSSTREAM 13 /* TLS stream */
#define MU_IOCTL_WORDWRAPSTREAM 14 /* Word-wrapper stream */
+#define MU_IOCTL_TCPSTREAM 15 /* TCP stream */
/* Opcodes common for various families */
#define MU_IOCTL_OP_GET 0
@@ -244,6 +245,14 @@ int mu_ioctl_logstream_set_locus_deprecated (void) MU_DEPRECATED;
/* Get current column */
#define MU_IOCTL_WORDWRAP_GET_COLUMN 4
+ /* TCP streams */
+
+ /* Get socket name.
+ Arg: struct mu_sockaddr **
+ */
+#define MU_IOCTL_TCP_GETSOCKNAME 0
+
+
struct mu_nullstream_pattern
{
char *pattern;
diff --git a/lib/tcpwrap.c b/lib/tcpwrap.c
index 35709fb36..d09d72d8d 100644
--- a/lib/tcpwrap.c
+++ b/lib/tcpwrap.c
@@ -103,7 +103,7 @@ mu_tcp_wrapper_prefork (int fd, struct sockaddr *sa, int salen,
&& sa->sa_family == AF_INET
&& !mu_tcpwrapper_access (fd))
{
- char *p = mu_sockaddr_to_astr (sa, salen);
+ char *p = mu_sys_sockaddr_to_astr (sa, salen);
mu_error (_("access from %s blocked by TCP wrappers"), p);
free (p);
return 1;
diff --git a/libmailutils/server/ipsrv.c b/libmailutils/server/ipsrv.c
index 4f9b28ccd..dd188f125 100644
--- a/libmailutils/server/ipsrv.c
+++ b/libmailutils/server/ipsrv.c
@@ -396,7 +396,7 @@ mu_ip_tcp_accept (mu_ip_server_t srv, void *call_data)
IDENTSTR (srv), strerror (rc)));
if (res == mu_acl_result_deny)
{
- char *p = mu_sockaddr_to_astr (&client.sa, size);
+ char *p = mu_sys_sockaddr_to_astr (&client.sa, size);
mu_diag_output (MU_DIAG_INFO, "Denying connection from %s", p);
free (p);
@@ -479,7 +479,7 @@ mu_ip_udp_accept (mu_ip_server_t srv, void *call_data)
IDENTSTR (srv), strerror (rc)));
if (res == mu_acl_result_deny)
{
- char *p = mu_sockaddr_to_astr (&client.sa, salen);
+ char *p = mu_sys_sockaddr_to_astr (&client.sa, salen);
mu_diag_output (MU_DIAG_INFO, "Denying connection from %s", p);
free (p);
return 0;
diff --git a/libmailutils/server/msrv.c b/libmailutils/server/msrv.c
index be0e52e11..8cd1cc86a 100644
--- a/libmailutils/server/msrv.c
+++ b/libmailutils/server/msrv.c
@@ -679,7 +679,7 @@ mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen)
rc = mu_acl_check_sockaddr (msrv->acl, s, salen, &res);
if (rc)
{
- char *p = mu_sockaddr_to_astr (s, salen);
+ char *p = mu_sys_sockaddr_to_astr (s, salen);
mu_error (_("access from %s blocked: cannot check ACLs: %s"),
p, mu_strerror (rc));
free (p);
@@ -689,7 +689,7 @@ mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen)
{
case mu_acl_result_undefined:
{
- char *p = mu_sockaddr_to_astr (s, salen);
+ char *p = mu_sys_sockaddr_to_astr (s, salen);
mu_diag_output (MU_DIAG_INFO,
_("%s: undefined ACL result; access allowed"),
p);
@@ -702,7 +702,7 @@ mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen)
case mu_acl_result_deny:
{
- char *p = mu_sockaddr_to_astr (s, salen);
+ char *p = mu_sys_sockaddr_to_astr (s, salen);
mu_error (_("access from %s blocked"), p);
free (p);
return 1;
diff --git a/libmailutils/sockaddr/Makefile.am b/libmailutils/sockaddr/Makefile.am
index 961696815..4c98100a3 100644
--- a/libmailutils/sockaddr/Makefile.am
+++ b/libmailutils/sockaddr/Makefile.am
@@ -22,6 +22,7 @@ libsockaddr_la_SOURCES = \
create.c\
free.c\
fromnode.c\
+ fromsock.c\
insert.c\
ipaddr.c\
str.c\
diff --git a/libmailutils/sockaddr/fromsock.c b/libmailutils/sockaddr/fromsock.c
new file mode 100644
index 000000000..5d3f79a34
--- /dev/null
+++ b/libmailutils/sockaddr/fromsock.c
@@ -0,0 +1,38 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <mailutils/sockaddr.h>
+#include <mailutils/errno.h>
+#include <mailutils/error.h>
+
+int
+mu_sockaddr_from_socket (struct mu_sockaddr **retval, int fd)
+{
+ int rc;
+ struct sockaddr addr;
+ socklen_t len = sizeof (addr);
+ rc = getsockname (fd, &addr, &len);
+ if (rc)
+ return rc;
+ return mu_sockaddr_create (retval, &addr, len);
+}
diff --git a/libmailutils/sockaddr/str.c b/libmailutils/sockaddr/str.c
index dd6e865f8..d78c329be 100644
--- a/libmailutils/sockaddr/str.c
+++ b/libmailutils/sockaddr/str.c
@@ -38,7 +38,9 @@ static char *default_sockaddr_text = "[not enogh memory]";
"" : (sa)->sun_path)
int
-mu_sockaddr_format (char **pbuf, const struct sockaddr *sa, socklen_t salen)
+mu_sys_sockaddr_format (char **pbuf,
+ enum mu_sockaddr_format fmt,
+ const struct sockaddr *sa, socklen_t salen)
{
int rc = MU_ERR_FAILURE;
@@ -54,23 +56,51 @@ mu_sockaddr_format (char **pbuf, const struct sockaddr *sa, socklen_t salen)
host, sizeof (host), srv, sizeof (srv),
NI_NUMERICHOST|NI_NUMERICSERV) == 0)
{
- if (sa->sa_family == AF_INET6)
- rc = mu_asprintf (pbuf, "inet6://[%s]:%s", host, srv);
- else
- rc = mu_asprintf (pbuf, "inet://%s:%s", host, srv);
+ switch (fmt)
+ {
+ case mu_sockaddr_format_default:
+ if (sa->sa_family == AF_INET6)
+ rc = mu_asprintf (pbuf, "inet6://[%s]:%s", host, srv);
+ else
+ rc = mu_asprintf (pbuf, "inet://%s:%s", host, srv);
+ break;
+
+ case mu_sockaddr_format_ehlo:
+ rc = mu_asprintf (pbuf, "[%s]", host);
+ break;
+ }
}
else
- rc = mu_asprintf (pbuf, "%s://[getnameinfo failed]",
- sa->sa_family == AF_INET ?
- "inet" : "inet6");
+ {
+ switch (fmt)
+ {
+ case mu_sockaddr_format_default:
+ rc = mu_asprintf (pbuf, "%s://[getnameinfo failed]",
+ sa->sa_family == AF_INET ?
+ "inet" : "inet6");
+ break;
+
+ case mu_sockaddr_format_ehlo:
+ return MU_ERR_FAILURE;
+ }
+ }
break;
}
#else
case AF_INET:
{
struct sockaddr_in *s_in = (struct sockaddr_in *)sa;
- rc = mu_asprintf (pbuf, "inet://%s:%hu",
- inet_ntoa (s_in->sin_addr), s_in->sin_port);
+ switch (fmt)
+ {
+ case mu_sockaddr_format_default:
+ rc = mu_asprintf (pbuf, "inet://%s:%hu",
+ inet_ntoa (s_in->sin_addr), s_in->sin_port);
+ break;
+
+ case mu_sockaddr_format_ehlo:
+ rc = mu_asprintf (pbuf, "[%s]", inet_ntoa (s_in->sin_addr));
+ break;
+ }
break;
}
#endif
@@ -78,10 +108,19 @@ mu_sockaddr_format (char **pbuf, const struct sockaddr *sa, socklen_t salen)
case AF_UNIX:
{
struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
- if (S_UN_NAME (s_un, salen)[0] == 0)
- rc = mu_asprintf (pbuf, "unix://[anonymous socket]");
- else
- rc = mu_asprintf (pbuf, "unix://%s", s_un->sun_path);
+
+ switch (fmt)
+ {
+ case mu_sockaddr_format_default:
+ if (S_UN_NAME (s_un, salen)[0] == 0)
+ rc = mu_asprintf (pbuf, "unix://[anonymous socket]");
+ else
+ rc = mu_asprintf (pbuf, "unix://%s", s_un->sun_path);
+ break;
+
+ case mu_sockaddr_format_ehlo:
+ rc = mu_asprintf (pbuf, "localhost");
+ }
break;
}
@@ -92,19 +131,27 @@ mu_sockaddr_format (char **pbuf, const struct sockaddr *sa, socklen_t salen)
}
char *
-mu_sockaddr_to_astr (const struct sockaddr *sa, int salen)
+mu_sys_sockaddr_to_astr (const struct sockaddr *sa, int salen)
{
char *buf = NULL;
- mu_sockaddr_format (&buf, sa, salen);
+ mu_sys_sockaddr_format (&buf, mu_sockaddr_format_default, sa, salen);
return buf;
}
+int
+mu_sockaddr_format (struct mu_sockaddr *sa, char **pbuf,
+ enum mu_sockaddr_format fmt)
+{
+ return mu_sys_sockaddr_format (pbuf, fmt, sa->addr, sa->addrlen);
+}
+
const char *
mu_sockaddr_str (struct mu_sockaddr *sa)
{
- if (!sa->str && mu_sockaddr_format (&sa->str, sa->addr, sa->addrlen))
- return default_sockaddr_text;
- return sa->str;
+ if (!sa->str
+ && mu_sockaddr_format (sa, &sa->str, mu_sockaddr_format_default))
+ return default_sockaddr_text;
+ return sa->str;
}
diff --git a/libmailutils/stream/tcp.c b/libmailutils/stream/tcp.c
index 2bfae34bb..718135539 100644
--- a/libmailutils/stream/tcp.c
+++ b/libmailutils/stream/tcp.c
@@ -177,6 +177,25 @@ _tcp_ioctl (mu_stream_t stream, int code, int opcode, void *ptr)
}
}
break;
+
+ case MU_IOCTL_TCPSTREAM:
+ switch (opcode)
+ {
+ case MU_IOCTL_TCP_GETSOCKNAME:
+ if (!ptr)
+ return EINVAL;
+ if (!tcp->source_addr)
+ {
+ int rc = mu_sockaddr_from_socket (&tcp->source_addr, tcp->fd);
+ if (rc)
+ return rc;
+ }
+ return mu_sockaddr_copy ((struct mu_sockaddr **)ptr,
+ tcp->source_addr);
+ default:
+ return EINVAL;
+ }
+ break;
default:
return ENOSYS;
diff --git a/libproto/mailer/smtp_ehlo.c b/libproto/mailer/smtp_ehlo.c
index 591a8de21..3f0af6681 100644
--- a/libproto/mailer/smtp_ehlo.c
+++ b/libproto/mailer/smtp_ehlo.c
@@ -26,6 +26,8 @@
#include <mailutils/list.h>
#include <mailutils/util.h>
#include <mailutils/smtp.h>
+#include <mailutils/io.h>
+#include <mailutils/sockaddr.h>
#include <mailutils/sys/smtp.h>
static int
@@ -58,14 +60,43 @@ mu_smtp_ehlo (mu_smtp_t smtp)
char *host;
char *p;
- status = mu_get_host_name (&host);
- MU_SMTP_CHECK_ERROR (smtp, status);
- p = strchr (host, '.');
- if (p)
- p++;
+ if (mu_get_host_name (&host) == 0)
+ {
+ if (host[0] == 0)
+ {
+ free (host);
+ host = p = NULL;
+ }
+ else
+ {
+ p = strchr (host, '.');
+ if (p)
+ p++;
+ else
+ p = host;
+ }
+ }
else
- p = host;
+ p = NULL;
+
+ if (!p)
+ {
+ struct mu_sockaddr *addr;
+
+ status = mu_stream_ioctl (smtp->carrier, MU_IOCTL_TCPSTREAM,
+ MU_IOCTL_TCP_GETSOCKNAME,
+ &addr);
+ if (status == 0)
+ {
+ status = mu_sockaddr_format (addr, &host,
+ mu_sockaddr_format_ehlo);
+ mu_sockaddr_free (addr);
+ p = host;
+ }
+ MU_SMTP_CHECK_ERROR (smtp, status);
+ }
status = mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, p);
+ free (host);
MU_SMTP_CHECK_ERROR (smtp, status);
}

Return to:

Send suggestions and report system problems to the System administrator.