tools/llvm: Do not build with symbols
[minix3.git] / lib / libutil / sockaddr_snprintf.c
blobed21020c8fde654ccd0154a4a5408815351e22fc
1 /* $NetBSD: sockaddr_snprintf.c,v 1.10 2013/06/07 17:23:26 christos Exp $ */
3 /*-
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 #if defined(LIBC_SCCS) && !defined(lint)
33 __RCSID("$NetBSD: sockaddr_snprintf.c,v 1.10 2013/06/07 17:23:26 christos Exp $");
34 #endif /* LIBC_SCCS and not lint */
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <sys/un.h>
40 #include <netinet/in.h>
41 #if !defined(__minix)
42 #include <netatalk/at.h>
43 #include <net/if_dl.h>
44 #endif
46 #include <stdio.h>
47 #include <string.h>
48 #include <errno.h>
49 #include <stdlib.h>
50 #include <util.h>
51 #include <netdb.h>
53 #if !defined(__minix)
54 static int
55 debug_at(char *str, size_t len, const struct sockaddr_at *sat)
57 return snprintf(str, len, "sat_len=%u, sat_family=%u, sat_port=%u, "
58 "sat_addr.s_net=%u, sat_addr.s_node=%u, "
59 "sat_range.r_netrange.nr_phase=%u, "
60 "sat_range.r_netrange.nr_firstnet=%u, "
61 "sat_range.r_netrange.nr_lastnet=%u",
62 sat->sat_len, sat->sat_family, sat->sat_port,
63 sat->sat_addr.s_net, sat->sat_addr.s_node,
64 sat->sat_range.r_netrange.nr_phase,
65 sat->sat_range.r_netrange.nr_firstnet,
66 sat->sat_range.r_netrange.nr_lastnet);
69 static int
70 debug_in(char *str, size_t len, const struct sockaddr_in *sin)
72 return snprintf(str, len, "sin_len=%u, sin_family=%u, sin_port=%u, "
73 "sin_addr.s_addr=%08x",
74 sin->sin_len, sin->sin_family, sin->sin_port,
75 sin->sin_addr.s_addr);
78 static int
79 debug_in6(char *str, size_t len, const struct sockaddr_in6 *sin6)
81 const uint8_t *s = sin6->sin6_addr.s6_addr;
83 return snprintf(str, len, "sin6_len=%u, sin6_family=%u, sin6_port=%u, "
84 "sin6_flowinfo=%u, "
85 "sin6_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
86 "%02x:%02x:%02x:%02x:%02x:%02x, sin6_scope_id=%u",
87 sin6->sin6_len, sin6->sin6_family, sin6->sin6_port,
88 sin6->sin6_flowinfo, s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5],
89 s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb], s[0xc], s[0xd],
90 s[0xe], s[0xf], sin6->sin6_scope_id);
93 static int
94 debug_un(char *str, size_t len, const struct sockaddr_un *sun)
96 return snprintf(str, len, "sun_len=%u, sun_family=%u, sun_path=%*s",
97 sun->sun_len, sun->sun_family, (int)sizeof(sun->sun_path),
98 sun->sun_path);
101 static int
102 debug_dl(char *str, size_t len, const struct sockaddr_dl *sdl)
104 const uint8_t *s = (const void *)sdl->sdl_data;
106 return snprintf(str, len, "sdl_len=%u, sdl_family=%u, sdl_index=%u, "
107 "sdl_type=%u, sdl_nlen=%u, sdl_alen=%u, sdl_slen=%u, sdl_data="
108 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
109 sdl->sdl_len, sdl->sdl_family, sdl->sdl_index,
110 sdl->sdl_type, sdl->sdl_nlen, sdl->sdl_alen, sdl->sdl_slen,
111 s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5],
112 s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb]);
114 #endif /* !defined(__minix) */
117 sockaddr_snprintf(char * const sbuf, const size_t len, const char * const fmt,
118 const struct sockaddr * const sa)
120 const void *a = NULL;
121 #if !defined(__minix)
122 char abuf[1024], nbuf[1024], *addr = NULL, *w = NULL;
123 #else
124 char abuf[1024], nbuf[1024], *addr = NULL;
125 #endif /* !defined(__minix) */
126 char Abuf[1024], pbuf[32], *name = NULL, *port = NULL;
127 char *ebuf = &sbuf[len - 1], *buf = sbuf;
128 const char *ptr, *s;
129 int p = -1;
130 #if !defined(__minix)
131 const struct sockaddr_at *sat = NULL;
132 #endif /* !defined(__minix) */
133 const struct sockaddr_in *sin4 = NULL;
134 #if !defined(__minix)
135 const struct sockaddr_in6 *sin6 = NULL;
136 const struct sockaddr_un *sun = NULL;
137 const struct sockaddr_dl *sdl = NULL;
138 #endif /* !defined(__minix) */
139 int na = 1;
141 #define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
142 while (/*CONSTCOND*/0)
143 #define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
144 while (/*CONSTCOND*/0)
145 #define ADDNA() do { if (na) ADDS("N/A"); } \
146 while (/*CONSTCOND*/0)
148 switch (sa->sa_family) {
149 case AF_UNSPEC:
150 goto done;
151 #if !defined(__minix)
152 case AF_APPLETALK:
153 sat = ((const struct sockaddr_at *)(const void *)sa);
154 p = ntohs(sat->sat_port);
155 (void)snprintf(addr = abuf, sizeof(abuf), "%u.%u",
156 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
157 (void)snprintf(port = pbuf, sizeof(pbuf), "%d", p);
158 break;
159 case AF_LOCAL:
160 sun = ((const struct sockaddr_un *)(const void *)sa);
161 (void)strlcpy(addr = abuf, sun->sun_path, SUN_LEN(sun));
162 break;
163 #endif /* !defined(__minix) */
164 case AF_INET:
165 sin4 = ((const struct sockaddr_in *)(const void *)sa);
166 p = ntohs(sin4->sin_port);
167 a = &sin4->sin_addr;
168 break;
169 #if !defined(__minix)
170 case AF_INET6:
171 sin6 = ((const struct sockaddr_in6 *)(const void *)sa);
172 p = ntohs(sin6->sin6_port);
173 a = &sin6->sin6_addr;
174 break;
175 case AF_LINK:
176 sdl = ((const struct sockaddr_dl *)(const void *)sa);
177 (void)strlcpy(addr = abuf, link_ntoa(sdl), sizeof(abuf));
178 if ((w = strchr(addr, ':')) != 0) {
179 *w++ = '\0';
180 addr = w;
182 break;
183 #endif /* !defined(__minix) */
184 default:
185 errno = EAFNOSUPPORT;
186 return -1;
189 if (addr == abuf)
190 name = addr;
192 #if !defined(__minix)
193 if (a && getnameinfo(sa, (socklen_t)sa->sa_len, addr = abuf,
194 #else
195 if (a && getnameinfo(sa, (socklen_t)len, addr = abuf,
196 #endif /* !defined(__minix) */
197 (unsigned int)sizeof(abuf), NULL, 0,
198 NI_NUMERICHOST|NI_NUMERICSERV) != 0)
199 return -1;
201 for (ptr = fmt; *ptr; ptr++) {
202 if (*ptr != '%') {
203 ADDC(*ptr);
204 continue;
206 next_char:
207 switch (*++ptr) {
208 case '?':
209 na = 0;
210 goto next_char;
211 case 'a':
212 ADDS(addr);
213 break;
214 case 'p':
215 if (p != -1) {
216 (void)snprintf(nbuf, sizeof(nbuf), "%d", p);
217 ADDS(nbuf);
218 } else
219 ADDNA();
220 break;
221 case 'f':
222 (void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family);
223 ADDS(nbuf);
224 break;
225 case 'l':
226 #if !defined(__minix)
227 (void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_len);
228 #else
229 (void)snprintf(nbuf, sizeof(nbuf), "%d", len);
230 #endif /* !defined(__minix) */
231 ADDS(nbuf);
232 break;
233 case 'A':
234 if (name)
235 ADDS(name);
236 else if (!a)
237 ADDNA();
238 else {
239 #if !defined(__minix)
240 getnameinfo(sa, (socklen_t)sa->sa_len,
241 #else
242 getnameinfo(sa, (socklen_t)len,
243 #endif /* !defined(__minix) */
244 name = Abuf,
245 (unsigned int)sizeof(nbuf), NULL, 0, 0);
246 ADDS(name);
248 break;
249 case 'P':
250 if (port)
251 ADDS(port);
252 else if (p == -1)
253 ADDNA();
254 else {
255 #if !defined(__minix)
256 getnameinfo(sa, (socklen_t)sa->sa_len, NULL, 0,
257 #else
258 getnameinfo(sa, (socklen_t)len, NULL, 0,
259 #endif /* !defined(__minix) */
260 port = pbuf,
261 (unsigned int)sizeof(pbuf), 0);
262 ADDS(port);
264 break;
265 #if !defined(__minix)
266 case 'I':
267 if (sdl && addr != abuf) {
268 ADDS(abuf);
269 } else {
270 ADDNA();
272 break;
273 case 'F':
274 if (sin6) {
275 (void)snprintf(nbuf, sizeof(nbuf), "%d",
276 sin6->sin6_flowinfo);
277 ADDS(nbuf);
278 break;
279 } else {
280 ADDNA();
282 break;
283 case 'S':
284 if (sin6) {
285 (void)snprintf(nbuf, sizeof(nbuf), "%d",
286 sin6->sin6_scope_id);
287 ADDS(nbuf);
288 break;
289 } else {
290 ADDNA();
292 break;
293 case 'R':
294 if (sat) {
295 const struct netrange *n =
296 &sat->sat_range.r_netrange;
297 (void)snprintf(nbuf, sizeof(nbuf),
298 "%d:[%d,%d]", n->nr_phase , n->nr_firstnet,
299 n->nr_lastnet);
300 ADDS(nbuf);
301 } else {
302 ADDNA();
304 break;
305 case 'D':
306 switch (sa->sa_family) {
307 case AF_APPLETALK:
308 debug_at(nbuf, sizeof(nbuf), sat);
309 break;
310 case AF_LOCAL:
311 debug_un(nbuf, sizeof(nbuf), sun);
312 break;
313 case AF_INET:
314 debug_in(nbuf, sizeof(nbuf), sin4);
315 break;
316 case AF_INET6:
317 debug_in6(nbuf, sizeof(nbuf), sin6);
318 break;
319 case AF_LINK:
320 debug_dl(nbuf, sizeof(nbuf), sdl);
321 break;
322 default:
323 abort();
325 ADDS(nbuf);
326 break;
327 #endif /* !defined(__minix) */
328 default:
329 ADDC('%');
330 if (na == 0)
331 ADDC('?');
332 if (*ptr == '\0')
333 goto done;
334 /*FALLTHROUGH*/
335 case '%':
336 ADDC(*ptr);
337 break;
339 na = 1;
341 done:
342 if (buf < ebuf)
343 *buf = '\0';
344 else if (len != 0)
345 sbuf[len - 1] = '\0';
346 return (int)(buf - sbuf);