summaryrefslogtreecommitdiff
path: root/REORG.TODO/support/support_format_addrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/support/support_format_addrinfo.c')
-rw-r--r--REORG.TODO/support/support_format_addrinfo.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/REORG.TODO/support/support_format_addrinfo.c b/REORG.TODO/support/support_format_addrinfo.c
new file mode 100644
index 0000000000..eedb030591
--- /dev/null
+++ b/REORG.TODO/support/support_format_addrinfo.c
@@ -0,0 +1,239 @@
+/* Convert struct addrinfo values to a string.
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C 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 2.1 of the License, or (at your option) any later version.
+
+ The GNU C 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 the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/format_nss.h>
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdio.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+static size_t
+socket_address_length (int family)
+{
+ switch (family)
+ {
+ case AF_INET:
+ return sizeof (struct sockaddr_in);
+ case AF_INET6:
+ return sizeof (struct sockaddr_in6);
+ default:
+ return -1;
+ }
+}
+
+static void
+format_ai_flags_1 (FILE *out, struct addrinfo *ai, int flag, const char *name,
+ int * flags_printed)
+{
+ if ((ai->ai_flags & flag) != 0)
+ fprintf (out, " %s", name);
+ *flags_printed |= flag;
+}
+
+static void
+format_ai_flags (FILE *out, struct addrinfo *ai)
+{
+ if (ai == NULL)
+ return;
+
+ if (ai->ai_flags != 0)
+ {
+ fprintf (out, "flags:");
+ int flags_printed = 0;
+#define FLAG(flag) format_ai_flags_1 (out, ai, flag, #flag, &flags_printed)
+ FLAG (AI_PASSIVE);
+ FLAG (AI_CANONNAME);
+ FLAG (AI_NUMERICHOST);
+ FLAG (AI_V4MAPPED);
+ FLAG (AI_ALL);
+ FLAG (AI_ADDRCONFIG);
+ FLAG (AI_IDN);
+ FLAG (AI_CANONIDN);
+ FLAG (AI_IDN_ALLOW_UNASSIGNED);
+ FLAG (AI_IDN_USE_STD3_ASCII_RULES);
+ FLAG (AI_NUMERICSERV);
+#undef FLAG
+ int remaining = ai->ai_flags & ~flags_printed;
+ if (remaining != 0)
+ fprintf (out, " %08x", remaining);
+ fprintf (out, "\n");
+ }
+
+ /* Report flag mismatches within the list. */
+ int flags = ai->ai_flags;
+ int index = 1;
+ ai = ai->ai_next;
+ while (ai != NULL)
+ {
+ if (ai->ai_flags != flags)
+ fprintf (out, "error: flags at %d: 0x%x expected, 0x%x actual\n",
+ index, flags, ai->ai_flags);
+ ai = ai->ai_next;
+ ++index;
+ }
+}
+
+static void
+format_ai_canonname (FILE *out, struct addrinfo *ai)
+{
+ if (ai == NULL)
+ return;
+ if (ai->ai_canonname != NULL)
+ fprintf (out, "canonname: %s\n", ai->ai_canonname);
+
+ /* Report incorrectly set ai_canonname fields on subsequent list
+ entries. */
+ int index = 1;
+ ai = ai->ai_next;
+ while (ai != NULL)
+ {
+ if (ai->ai_canonname != NULL)
+ fprintf (out, "error: canonname set at %d: %s\n",
+ index, ai->ai_canonname);
+ ai = ai->ai_next;
+ ++index;
+ }
+}
+
+static void
+format_ai_one (FILE *out, struct addrinfo *ai)
+{
+ {
+ char type_buf[32];
+ const char *type_str;
+ char proto_buf[32];
+ const char *proto_str;
+
+ /* ai_socktype */
+ switch (ai->ai_socktype)
+ {
+ case SOCK_RAW:
+ type_str = "RAW";
+ break;
+ case SOCK_DGRAM:
+ type_str = "DGRAM";
+ break;
+ case SOCK_STREAM:
+ type_str = "STREAM";
+ break;
+ default:
+ snprintf (type_buf, sizeof (type_buf), "%d", ai->ai_socktype);
+ type_str = type_buf;
+ }
+
+ /* ai_protocol */
+ switch (ai->ai_protocol)
+ {
+ case IPPROTO_IP:
+ proto_str = "IP";
+ break;
+ case IPPROTO_UDP:
+ proto_str = "UDP";
+ break;
+ case IPPROTO_TCP:
+ proto_str = "TCP";
+ break;
+ default:
+ snprintf (proto_buf, sizeof (proto_buf), "%d", ai->ai_protocol);
+ proto_str = proto_buf;
+ }
+ fprintf (out, "address: %s/%s", type_str, proto_str);
+ }
+
+ /* ai_addrlen */
+ if (ai->ai_addrlen != socket_address_length (ai->ai_family))
+ {
+ char *family = support_format_address_family (ai->ai_family);
+ fprintf (out, "error: invalid address length %d for %s\n",
+ ai->ai_addrlen, family);
+ free (family);
+ }
+
+ /* ai_addr */
+ {
+ char buf[128];
+ uint16_t port;
+ const char *ret;
+ switch (ai->ai_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *) ai->ai_addr;
+ ret = inet_ntop (AF_INET, &sin->sin_addr, buf, sizeof (buf));
+ port = sin->sin_port;
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *) ai->ai_addr;
+ ret = inet_ntop (AF_INET6, &sin->sin6_addr, buf, sizeof (buf));
+ port = sin->sin6_port;
+ }
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ ret = NULL;
+ }
+ if (ret == NULL)
+ fprintf (out, "error: inet_top failed: %m\n");
+ else
+ fprintf (out, " %s %u\n", buf, ntohs (port));
+ }
+}
+
+/* Format all the addresses in one address family. */
+static void
+format_ai_family (FILE *out, struct addrinfo *ai, int family)
+{
+ while (ai)
+ {
+ if (ai->ai_family == family)
+ format_ai_one (out, ai);
+ ai = ai->ai_next;
+ }
+}
+
+char *
+support_format_addrinfo (struct addrinfo *ai, int ret)
+{
+ int errno_copy = errno;
+
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+ if (ret != 0)
+ {
+ fprintf (mem.out, "error: %s\n", gai_strerror (ret));
+ if (ret == EAI_SYSTEM)
+ {
+ errno = errno_copy;
+ fprintf (mem.out, "error: %m\n");
+ }
+ }
+ else
+ {
+ format_ai_flags (mem.out, ai);
+ format_ai_canonname (mem.out, ai);
+ format_ai_family (mem.out, ai, AF_INET);
+ format_ai_family (mem.out, ai, AF_INET6);
+ }
+
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}