uk_UA: Add alternative month names (bug 10871).
[glibc.git] / support / support_format_addrinfo.c
blobc5e00e516a8279f7a9a4656d0be91ed41bc029fe
1 /* Convert struct addrinfo values to a string.
2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <support/format_nss.h>
21 #include <arpa/inet.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <support/support.h>
26 #include <support/xmemstream.h>
28 static size_t
29 socket_address_length (int family)
31 switch (family)
33 case AF_INET:
34 return sizeof (struct sockaddr_in);
35 case AF_INET6:
36 return sizeof (struct sockaddr_in6);
37 default:
38 return -1;
42 static void
43 format_ai_flags_1 (FILE *out, struct addrinfo *ai, int flag, const char *name,
44 int * flags_printed)
46 if ((ai->ai_flags & flag) != 0)
47 fprintf (out, " %s", name);
48 *flags_printed |= flag;
51 static void
52 format_ai_flags (FILE *out, struct addrinfo *ai)
54 if (ai == NULL)
55 return;
57 if (ai->ai_flags != 0)
59 fprintf (out, "flags:");
60 int flags_printed = 0;
61 #define FLAG(flag) format_ai_flags_1 (out, ai, flag, #flag, &flags_printed)
62 FLAG (AI_PASSIVE);
63 FLAG (AI_CANONNAME);
64 FLAG (AI_NUMERICHOST);
65 FLAG (AI_V4MAPPED);
66 FLAG (AI_ALL);
67 FLAG (AI_ADDRCONFIG);
68 FLAG (AI_IDN);
69 FLAG (AI_CANONIDN);
70 FLAG (AI_IDN_ALLOW_UNASSIGNED);
71 FLAG (AI_IDN_USE_STD3_ASCII_RULES);
72 FLAG (AI_NUMERICSERV);
73 #undef FLAG
74 int remaining = ai->ai_flags & ~flags_printed;
75 if (remaining != 0)
76 fprintf (out, " %08x", remaining);
77 fprintf (out, "\n");
80 /* Report flag mismatches within the list. */
81 int flags = ai->ai_flags;
82 int index = 1;
83 ai = ai->ai_next;
84 while (ai != NULL)
86 if (ai->ai_flags != flags)
87 fprintf (out, "error: flags at %d: 0x%x expected, 0x%x actual\n",
88 index, flags, ai->ai_flags);
89 ai = ai->ai_next;
90 ++index;
94 static void
95 format_ai_canonname (FILE *out, struct addrinfo *ai)
97 if (ai == NULL)
98 return;
99 if (ai->ai_canonname != NULL)
100 fprintf (out, "canonname: %s\n", ai->ai_canonname);
102 /* Report incorrectly set ai_canonname fields on subsequent list
103 entries. */
104 int index = 1;
105 ai = ai->ai_next;
106 while (ai != NULL)
108 if (ai->ai_canonname != NULL)
109 fprintf (out, "error: canonname set at %d: %s\n",
110 index, ai->ai_canonname);
111 ai = ai->ai_next;
112 ++index;
116 static void
117 format_ai_one (FILE *out, struct addrinfo *ai)
120 char type_buf[32];
121 const char *type_str;
122 char proto_buf[32];
123 const char *proto_str;
125 /* ai_socktype */
126 switch (ai->ai_socktype)
128 case SOCK_RAW:
129 type_str = "RAW";
130 break;
131 case SOCK_DGRAM:
132 type_str = "DGRAM";
133 break;
134 case SOCK_STREAM:
135 type_str = "STREAM";
136 break;
137 default:
138 snprintf (type_buf, sizeof (type_buf), "%d", ai->ai_socktype);
139 type_str = type_buf;
142 /* ai_protocol */
143 switch (ai->ai_protocol)
145 case IPPROTO_IP:
146 proto_str = "IP";
147 break;
148 case IPPROTO_UDP:
149 proto_str = "UDP";
150 break;
151 case IPPROTO_TCP:
152 proto_str = "TCP";
153 break;
154 default:
155 snprintf (proto_buf, sizeof (proto_buf), "%d", ai->ai_protocol);
156 proto_str = proto_buf;
158 fprintf (out, "address: %s/%s", type_str, proto_str);
161 /* ai_addrlen */
162 if (ai->ai_addrlen != socket_address_length (ai->ai_family))
164 char *family = support_format_address_family (ai->ai_family);
165 fprintf (out, "error: invalid address length %d for %s\n",
166 ai->ai_addrlen, family);
167 free (family);
170 /* ai_addr */
172 char buf[128];
173 uint16_t port;
174 const char *ret;
175 switch (ai->ai_family)
177 case AF_INET:
179 struct sockaddr_in *sin = (struct sockaddr_in *) ai->ai_addr;
180 ret = inet_ntop (AF_INET, &sin->sin_addr, buf, sizeof (buf));
181 port = sin->sin_port;
183 break;
184 case AF_INET6:
186 struct sockaddr_in6 *sin = (struct sockaddr_in6 *) ai->ai_addr;
187 ret = inet_ntop (AF_INET6, &sin->sin6_addr, buf, sizeof (buf));
188 port = sin->sin6_port;
190 break;
191 default:
192 errno = EAFNOSUPPORT;
193 ret = NULL;
195 if (ret == NULL)
196 fprintf (out, "error: inet_top failed: %m\n");
197 else
198 fprintf (out, " %s %u\n", buf, ntohs (port));
202 /* Format all the addresses in one address family. */
203 static void
204 format_ai_family (FILE *out, struct addrinfo *ai, int family)
206 while (ai)
208 if (ai->ai_family == family)
209 format_ai_one (out, ai);
210 ai = ai->ai_next;
214 char *
215 support_format_addrinfo (struct addrinfo *ai, int ret)
217 int errno_copy = errno;
219 struct xmemstream mem;
220 xopen_memstream (&mem);
221 if (ret != 0)
223 fprintf (mem.out, "error: %s\n", gai_strerror (ret));
224 if (ret == EAI_SYSTEM)
226 errno = errno_copy;
227 fprintf (mem.out, "error: %m\n");
230 else
232 format_ai_flags (mem.out, ai);
233 format_ai_canonname (mem.out, ai);
234 format_ai_family (mem.out, ai, AF_INET);
235 format_ai_family (mem.out, ai, AF_INET6);
238 xfclose_memstream (&mem);
239 return mem.buffer;