/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011-2021 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
. */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct mu_kwd famtab[] = {
{ "unix", AF_UNIX },
{ "local", AF_UNIX },
{ "inet4", AF_INET },
#ifdef MAILUTILS_IPV6
{ "inet6", AF_INET6 },
{ "inet", AF_UNSPEC },
#else
{ "inet", AF_INET },
#endif
{ NULL }
};
int
mu_sockaddr_from_url (struct mu_sockaddr **retval, mu_url_t url,
struct mu_sockaddr_hints *mh)
{
int rc;
const char *scheme;
const char *node = NULL, *serv = NULL;
struct mu_sockaddr_hints hints;
if (mh)
memcpy (&hints, mh, sizeof (hints));
else
{
memset (&hints, 0, sizeof(hints));
hints.family = AF_UNSPEC;
hints.socktype = SOCK_STREAM;
hints.protocol = IPPROTO_TCP;
}
if (hints.family == AF_UNSPEC)
{
rc = mu_url_sget_scheme (url, &scheme);
if (rc)
return rc;
if (mu_kwd_xlat_name (famtab, scheme, &hints.family))
{
if (hints.flags & MU_AH_DETECT_FAMILY)
{
int flags = 0;
mu_url_get_flags (url, &flags);
#ifdef MAILUTILS_IPV6
if (flags & MU_URL_IPV6)
hints.family = AF_INET6;
else
#endif
if (flags & (MU_URL_HOST|MU_URL_PORT))
hints.family = AF_INET;
else if (flags & MU_URL_PATH)
hints.family = AF_UNIX;
else
return MU_ERR_FAMILY;
}
else
return MU_ERR_FAMILY;
}
}
if (hints.family == AF_UNIX)
{
rc = mu_url_sget_path (url, &node);
if (rc)
{
if (rc == MU_ERR_NOENT)
{
rc = mu_url_sget_host (url, &node);
if (rc == MU_ERR_NOENT)
return MU_ERR_NONAME;
}
if (rc)
return rc;
}
}
else
{
#ifdef MAILUTILS_IPV6
if (hints.family == AF_UNSPEC)
hints.family = mu_url_has_flag (url, MU_URL_IPV6) ? AF_INET6 : AF_INET;
#endif
rc = mu_url_sget_host (url, &node);
if (rc && rc != MU_ERR_NOENT)
return MU_ERR_NONAME;
rc = mu_url_sget_portstr (url, &serv);
if (rc && rc != MU_ERR_NOENT)
return MU_ERR_NONAME;
}
return mu_sockaddr_from_node (retval, node, serv, &hints);
}