diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-11-01 10:56:08 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-11-01 10:56:08 +0200 |
commit | 4e7bcdbae346a26c1addf266a23c1f6cdc74533f (patch) | |
tree | 30f6721129f8a7688814b9dc88727e810770fbda | |
parent | a5e929972db1342beec4b8f577399f2d8d9a76c2 (diff) | |
download | mailutils-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.c | 3 | ||||
-rw-r--r-- | include/mailutils/debug.h | 4 | ||||
-rw-r--r-- | include/mailutils/sockaddr.h | 18 | ||||
-rw-r--r-- | include/mailutils/stream.h | 9 | ||||
-rw-r--r-- | lib/tcpwrap.c | 2 | ||||
-rw-r--r-- | libmailutils/server/ipsrv.c | 4 | ||||
-rw-r--r-- | libmailutils/server/msrv.c | 6 | ||||
-rw-r--r-- | libmailutils/sockaddr/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/sockaddr/fromsock.c | 38 | ||||
-rw-r--r-- | libmailutils/sockaddr/str.c | 85 | ||||
-rw-r--r-- | libmailutils/stream/tcp.c | 19 | ||||
-rw-r--r-- | libproto/mailer/smtp_ehlo.c | 43 |
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); } |