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 /libmailutils/sockaddr | |
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.
Diffstat (limited to 'libmailutils/sockaddr')
-rw-r--r-- | libmailutils/sockaddr/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/sockaddr/fromsock.c | 38 | ||||
-rw-r--r-- | libmailutils/sockaddr/str.c | 85 |
3 files changed, 105 insertions, 19 deletions
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; } |