diff options
Diffstat (limited to 'libmailutils/sockaddr')
-rw-r--r-- | libmailutils/sockaddr/Makefile.am | 31 | ||||
-rw-r--r-- | libmailutils/sockaddr/copy.c | 36 | ||||
-rw-r--r-- | libmailutils/sockaddr/create.c | 47 | ||||
-rw-r--r-- | libmailutils/sockaddr/free.c | 50 | ||||
-rw-r--r-- | libmailutils/sockaddr/fromnode.c | 253 | ||||
-rw-r--r-- | libmailutils/sockaddr/insert.c | 64 | ||||
-rw-r--r-- | libmailutils/sockaddr/ipaddr.c | 88 | ||||
-rw-r--r-- | libmailutils/sockaddr/str.c | 109 | ||||
-rw-r--r-- | libmailutils/sockaddr/unlink.c | 45 | ||||
-rw-r--r-- | libmailutils/sockaddr/url.c | 130 |
10 files changed, 853 insertions, 0 deletions
diff --git a/libmailutils/sockaddr/Makefile.am b/libmailutils/sockaddr/Makefile.am new file mode 100644 index 000000000..dcfb18446 --- /dev/null +++ b/libmailutils/sockaddr/Makefile.am @@ -0,0 +1,31 @@ +# GNU Mailutils -- a suite of utilities for electronic mail +# Copyright (C) 2011 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/>. + +noinst_LTLIBRARIES = libsockaddr.la + +libsockaddr_la_SOURCES = \ + copy.c\ + create.c\ + free.c\ + fromnode.c\ + insert.c\ + ipaddr.c\ + str.c\ + unlink.c\ + url.c + +INCLUDES = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils diff --git a/libmailutils/sockaddr/copy.c b/libmailutils/sockaddr/copy.c new file mode 100644 index 000000000..5e28e7857 --- /dev/null +++ b/libmailutils/sockaddr/copy.c @@ -0,0 +1,36 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <stdlib.h> +#include <mailutils/sockaddr.h> + +int +mu_sockaddr_copy (struct mu_sockaddr **pnew, struct mu_sockaddr *old) +{ + if (!old) + { + *pnew = NULL; + return 0; + } + return mu_sockaddr_create (pnew, old->addr, old->addrlen); +} + + diff --git a/libmailutils/sockaddr/create.c b/libmailutils/sockaddr/create.c new file mode 100644 index 000000000..5b49471e6 --- /dev/null +++ b/libmailutils/sockaddr/create.c @@ -0,0 +1,47 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <stdlib.h> +#include <errno.h> +#include <string.h> +#include <mailutils/sockaddr.h> + +int +mu_sockaddr_create (struct mu_sockaddr **res, + struct sockaddr *addr, socklen_t len) +{ + struct mu_sockaddr *sa; + + sa = calloc (1, sizeof (*sa)); + if (!sa) + return ENOMEM; + sa->addr = malloc (len); + if (!sa->addr) + { + free (sa); + return ENOMEM; + } + memcpy (sa->addr, addr, len); + sa->addrlen = len; + *res = sa; + return 0; +} + diff --git a/libmailutils/sockaddr/free.c b/libmailutils/sockaddr/free.c new file mode 100644 index 000000000..2a31ec36d --- /dev/null +++ b/libmailutils/sockaddr/free.c @@ -0,0 +1,50 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <stdlib.h> +#include <mailutils/sockaddr.h> + +void +mu_sockaddr_free (struct mu_sockaddr *addr) +{ + if (!addr) + return; + free (addr->addr); + free (addr->str); +} + +void +mu_sockaddr_free_list (struct mu_sockaddr *addr) +{ + if (!addr) + return; + if (addr->prev) + addr->prev->next = NULL; + while (addr) + { + struct mu_sockaddr *next = addr->next; + mu_sockaddr_free (addr); + addr = next; + } +} + + + diff --git a/libmailutils/sockaddr/fromnode.c b/libmailutils/sockaddr/fromnode.c new file mode 100644 index 000000000..d79b9523a --- /dev/null +++ b/libmailutils/sockaddr/fromnode.c @@ -0,0 +1,253 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <sys/un.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <mailutils/sockaddr.h> +#include <mailutils/url.h> +#include <mailutils/io.h> +#include <mailutils/errno.h> +#include <mailutils/error.h> +#include <mailutils/nls.h> + +static struct mu_sockaddr * +match_sa (struct mu_sockaddr *list, struct sockaddr *sa, socklen_t len) +{ + for (; list; list = list->next) + if (len == list->addrlen && memcmp (list->addr, sa, len) == 0) + break; + return list; +} + +int +mu_sockaddr_from_node (struct mu_sockaddr **retval, const char *node, + const char *serv, struct mu_sockaddr_hints *mh) +{ + int rc; + + if (!mh) + { + static struct mu_sockaddr_hints nullhints = { 0, AF_UNSPEC }; + mh = &nullhints; + } + + if (mh->family == AF_UNIX) + { + size_t slen; + struct sockaddr_un s_un; + + if (!node) + return MU_ERR_NONAME; + slen = strlen (node); + if (slen >= sizeof s_un.sun_path) + return MU_ERR_BUFSPACE; + + s_un.sun_family = AF_UNIX; + strcpy(s_un.sun_path, node); + return mu_sockaddr_create (retval, (struct sockaddr*) &s_un, + sizeof (s_un)); + } + else +#ifdef MAILUTILS_IPV6 + { + struct addrinfo hints; + struct addrinfo *res, *ap; + char portbuf[64]; + struct mu_sockaddr *tail = NULL; + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = mh->family; + hints.ai_socktype = mh->socktype; + hints.ai_protocol = mh->protocol; + + if (!node) + { + if (mh->flags & MU_AH_PASSIVE) + hints.ai_flags |= AI_PASSIVE; + else + return MU_ERR_NONAME; + } + if (!serv && mh->port) + { + snprintf (portbuf, sizeof portbuf, "%hu", mh->port); + serv = portbuf; + } + + rc = getaddrinfo (node, serv, &hints, &res); + + switch (rc) + { + case 0: + break; + + case EAI_FAIL: + return MU_ERR_GETHOSTBYNAME; + + case EAI_FAMILY: + return MU_ERR_FAMILY; + + case EAI_NONAME: + return MU_ERR_NONAME; + + case EAI_SERVICE: + return MU_ERR_SERVICE; + + case EAI_SYSTEM: + mu_error (_("%s:%s: cannot parse address: %s"), + node, serv, mu_strerror (errno)); + return errno; + + case EAI_BADFLAGS: + return MU_ERR_BADFLAGS; + + case EAI_SOCKTYPE: + return MU_ERR_SOCKTYPE; + + case EAI_MEMORY: + return ENOMEM; + + default: + mu_error ("%s:%s: %s", node, serv, gai_strerror (rc)); + return MU_ERR_FAILURE; + } + + *retval = NULL; + for (ap = res; ap; ap = ap->ai_next) + if (mh->family == AF_UNSPEC || ap->ai_addr->sa_family == mh->family) + { + struct mu_sockaddr *sa; + + if (match_sa (*retval, ap->ai_addr, ap->ai_addrlen)) + continue; + rc = mu_sockaddr_create (&sa, ap->ai_addr, ap->ai_addrlen); + if (rc) + { + mu_sockaddr_free_list (*retval); + freeaddrinfo (res); + return rc; + } + if (tail) + mu_sockaddr_insert (tail, sa, 0); + else + *retval = sa; + tail = sa; + } + freeaddrinfo (res); + } +#else + if (mh->family == AF_INET) + { + short port; + struct hostent *hp; + struct mu_sockaddr *tail = NULL; + char **p; + + if (serv) + { + char *end; + unsigned long n = strtoul (serv, &end, 10); + + if (*end) + { + struct servent *sp; + const char *proto; + + if (mh->protocol) + { + struct protoent *pp = getprotobynumber (mh->protocol); + if (!pp) + return EINVAL; + proto = pp->p_name; + } + else + proto = NULL; + + sp = getservbyname (serv, proto); + if (!sp) + return MU_ERR_SERVICE; + port = sp->s_port; + } + else if (n == 0 || (port = n) != n) + return MU_ERR_PARSE; /* FIXME: need MU_ERR_RANGE? */ + } + else if (mh->port) + port = htons (mh->port); + else + return MU_ERR_NONAME; + + if (!node) + { + struct sockaddr_in s_in; + + if (!(mh->flags & MU_AH_PASSIVE)) + return MU_ERR_NONAME; + + s_in.sin_family = AF_INET; + s_in.sin_addr.s_addr = INADDR_ANY; + s_in.sin_port = port; + return mu_sockaddr_create (retval, (struct sockaddr*)&s_in, + sizeof (s_in)); + } + + hp = gethostbyname (node); + if (!hp) + return MU_ERR_GETHOSTBYNAME; + + if (hp->h_addrtype != AF_INET || hp->h_length != 4) + return MU_ERR_FAMILY; + + for (p = hp->h_addr_list; *p; p++) + { + struct mu_sockaddr *sa; + struct sockaddr_in s_in; + + s_in.sin_family = AF_INET; + memcpy(&s_in.sin_addr, *p, 4); + s_in.sin_port = port; + + rc = mu_sockaddr_create (&sa, (struct sockaddr*)&s_in, + sizeof (s_in)); + if (rc) + { + mu_sockaddr_free_list (*retval); + return rc; + } + if (tail) + mu_sockaddr_insert (tail, sa, 0); + else + *retval = sa; + tail = sa; + } + } + else + return MU_ERR_FAMILY; +#endif + return 0; +} diff --git a/libmailutils/sockaddr/insert.c b/libmailutils/sockaddr/insert.c new file mode 100644 index 000000000..dbac151c1 --- /dev/null +++ b/libmailutils/sockaddr/insert.c @@ -0,0 +1,64 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <stdlib.h> +#include <mailutils/sockaddr.h> + +static void +set_next (struct mu_sockaddr *sp, struct mu_sockaddr *tgt) +{ + for (; sp->next; sp = sp->next) + ; + sp->next = tgt; + if (tgt) + tgt->prev = sp; +} + +struct mu_sockaddr * +mu_sockaddr_insert (struct mu_sockaddr *anchor, struct mu_sockaddr *addr, + int before) +{ + struct mu_sockaddr *ret = anchor; + + if (!anchor) + { + addr->prev = NULL; + set_next (addr, NULL); + return addr; + } + + if (before) + { + if (anchor->prev) + anchor = anchor->prev; + else + { + addr->prev = NULL; + set_next (addr, anchor); + return addr; + } + } + + set_next (addr, anchor->next); + anchor->next = addr; + addr->prev = anchor; + return ret; +} diff --git a/libmailutils/sockaddr/ipaddr.c b/libmailutils/sockaddr/ipaddr.c new file mode 100644 index 000000000..6b14b4c29 --- /dev/null +++ b/libmailutils/sockaddr/ipaddr.c @@ -0,0 +1,88 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <string.h> +#include <mailutils/sockaddr.h> +#include <mailutils/cctype.h> + +int +mu_str_is_ipv4 (const char *addr) +{ + int dot_count = 0; + int digit_count = 0; + + for (; *addr; addr++) + { + if (!mu_isascii (*addr)) + return 0; + if (*addr == '.') + { + if (++dot_count > 3) + break; + digit_count = 0; + } + else if (!(mu_isdigit (*addr) && ++digit_count <= 3)) + return 0; + } + + return (dot_count == 3); +} + +int +mu_str_is_ipv6 (const char *addr) +{ + int col_count = 0; /* Number of colons */ + int dcol = 0; /* Did we encounter a double-colon? */ + int dig_count = 0; /* Number of digits in the last group */ + + for (; *addr; addr++) + { + if (!mu_isascii (*addr)) + return 0; + else if (mu_isxdigit (*addr)) + { + if (++dig_count > 4) + return 0; + } + else if (*addr == ':') + { + if (col_count && dig_count == 0 && ++dcol > 1) + return 0; + if (++col_count > 7) + return 0; + dig_count = 0; + } + else + return 0; + } + + return (col_count == 7 || dcol); +} + +int +mu_str_is_ipaddr (const char *addr) +{ + if (strchr (addr, '.')) + return mu_str_is_ipv4(addr); + else if (strchr (addr, ':')) + return mu_str_is_ipv6(addr); + return 0; +} diff --git a/libmailutils/sockaddr/str.c b/libmailutils/sockaddr/str.c new file mode 100644 index 000000000..949f21ef9 --- /dev/null +++ b/libmailutils/sockaddr/str.c @@ -0,0 +1,109 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <sys/un.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +#include <mailutils/sockaddr.h> +#include <mailutils/errno.h> +#include <mailutils/io.h> + +static char *default_sockaddr_text = "[not enogh memory]"; + +#define S_UN_NAME(sa, salen) \ + ((salen < mu_offsetof(struct sockaddr_un,sun_path)) ? \ + "" : (sa)->sun_path) + +int +mu_sockaddr_format (char **pbuf, const struct sockaddr *sa, socklen_t salen) +{ + int rc = MU_ERR_FAILURE; + + switch (sa->sa_family) + { +#ifdef MAILUTILS_IPV6 + case AF_INET: + case AF_INET6: + { + char host[NI_MAXHOST]; + char srv[NI_MAXSERV]; + if (getnameinfo (sa, 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); + } + else + rc = mu_asprintf (pbuf, "%s://[getnameinfo failed]", + sa->sa_family == AF_INET ? + "inet" : "inet6"); + 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); + break; + } +#endif + + 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); + break; + } + + default: + rc = mu_asprintf (pbuf, "family:%d", sa->sa_family); + } + return rc; +} + +char * +mu_sockaddr_to_astr (const struct sockaddr *sa, int salen) +{ + char *buf = NULL; + mu_sockaddr_format (&buf, sa, salen); + return buf; +} + +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; +} + + diff --git a/libmailutils/sockaddr/unlink.c b/libmailutils/sockaddr/unlink.c new file mode 100644 index 000000000..65808f568 --- /dev/null +++ b/libmailutils/sockaddr/unlink.c @@ -0,0 +1,45 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <stdlib.h> +#include <mailutils/sockaddr.h> + +struct mu_sockaddr * +mu_sockaddr_unlink (struct mu_sockaddr *addr) +{ + struct mu_sockaddr *p; + + if (!addr) + return NULL; + + p = addr->prev; + if (p) + p->next = addr->next; + + p = addr->next; + if (p) + p->prev = addr->prev; + + addr->prev = addr->next = NULL; + + return p; +} + diff --git a/libmailutils/sockaddr/url.c b/libmailutils/sockaddr/url.c new file mode 100644 index 000000000..0eaf870be --- /dev/null +++ b/libmailutils/sockaddr/url.c @@ -0,0 +1,130 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 2011 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 <sys/un.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <mailutils/sockaddr.h> +#include <mailutils/url.h> +#include <mailutils/io.h> +#include <mailutils/errno.h> +#include <mailutils/nls.h> +#include <mailutils/kwd.h> + +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, sizeof(hints), 0); + 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); +} |