1 /* $NetBSD: sockaddr_snprintf.c,v 1.9 2015/01/23 03:29:18 christos Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
35 #include <sys/cdefs.h>
36 #if defined(LIBC_SCCS) && !defined(lint)
37 __RCSID("$NetBSD: sockaddr_snprintf.c,v 1.9 2015/01/23 03:29:18 christos Exp $");
38 #endif /* LIBC_SCCS and not lint */
40 #include <sys/param.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
45 #include <netinet/in.h>
47 #undef HAVE_NETATALK_AT_H
49 #ifdef HAVE_NETATALK_AT_H
50 #include <netatalk/at.h>
52 #ifdef HAVE_NET_IF_DL_H
53 #include <net/if_dl.h>
65 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
66 #define SLEN(a) (a)->a ## _len
73 return sizeof(struct sockaddr_in
);
75 return sizeof(struct sockaddr_in6
);
77 return sizeof(struct sockaddr_un
);
78 #ifdef HAVE_NET_IF_DL_H
80 return sizeof(struct sockaddr_dl
);
82 #ifdef HAVE_NETATALK_AT_H
84 return sizeof(struct sockaddr_at
);
87 return sizeof(struct sockaddr_storage
);
91 #define SLEN(a) socklen((a)->a ## _family)
94 #ifdef HAVE_NETATALK_AT_H
96 debug_at(char *str
, size_t len
, const struct sockaddr_at
*sat
)
98 return snprintf(str
, len
, "sat_len=%u, sat_family=%u, sat_port=%u, "
99 "sat_addr.s_net=%u, sat_addr.s_node=%u, "
100 "sat_range.r_netrange.nr_phase=%u, "
101 "sat_range.r_netrange.nr_firstnet=%u, "
102 "sat_range.r_netrange.nr_lastnet=%u",
103 SLEN(sat
), sat
->sat_family
, sat
->sat_port
,
104 sat
->sat_addr
.s_net
, sat
->sat_addr
.s_node
,
105 sat
->sat_range
.r_netrange
.nr_phase
,
106 sat
->sat_range
.r_netrange
.nr_firstnet
,
107 sat
->sat_range
.r_netrange
.nr_lastnet
);
112 debug_in(char *str
, size_t len
, const struct sockaddr_in
*sin
)
114 return snprintf(str
, len
, "sin_len=%u, sin_family=%u, sin_port=%u, "
115 "sin_addr.s_addr=%08x",
116 SLEN(sin
), sin
->sin_family
, sin
->sin_port
,
117 sin
->sin_addr
.s_addr
);
121 debug_in6(char *str
, size_t len
, const struct sockaddr_in6
*sin6
)
123 const uint8_t *s
= sin6
->sin6_addr
.s6_addr
;
125 return snprintf(str
, len
, "sin6_len=%u, sin6_family=%u, sin6_port=%u, "
127 "sin6_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
128 "%02x:%02x:%02x:%02x:%02x:%02x, sin6_scope_id=%u",
129 SLEN(sin6
), sin6
->sin6_family
, sin6
->sin6_port
,
130 sin6
->sin6_flowinfo
, s
[0x0], s
[0x1], s
[0x2], s
[0x3], s
[0x4], s
[0x5],
131 s
[0x6], s
[0x7], s
[0x8], s
[0x9], s
[0xa], s
[0xb], s
[0xc], s
[0xd],
132 s
[0xe], s
[0xf], sin6
->sin6_scope_id
);
136 debug_un(char *str
, size_t len
, const struct sockaddr_un
*sun
)
138 return snprintf(str
, len
, "sun_len=%u, sun_family=%u, sun_path=%*s",
139 SLEN(sun
), sun
->sun_family
, (int)sizeof(sun
->sun_path
),
143 #ifdef HAVE_NET_IF_DL_H
145 debug_dl(char *str
, size_t len
, const struct sockaddr_dl
*sdl
)
147 const uint8_t *s
= (const void *)sdl
->sdl_data
;
149 return snprintf(str
, len
, "sdl_len=%u, sdl_family=%u, sdl_index=%u, "
150 "sdl_type=%u, sdl_nlen=%u, sdl_alen=%u, sdl_slen=%u, sdl_data="
151 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
152 SLEN(sdl
), sdl
->sdl_family
, sdl
->sdl_index
,
153 sdl
->sdl_type
, sdl
->sdl_nlen
, sdl
->sdl_alen
, sdl
->sdl_slen
,
154 s
[0x0], s
[0x1], s
[0x2], s
[0x3], s
[0x4], s
[0x5],
155 s
[0x6], s
[0x7], s
[0x8], s
[0x9], s
[0xa], s
[0xb]);
160 sockaddr_snprintf(char * const sbuf
, const size_t len
, const char * const fmt
,
161 const struct sockaddr
* const sa
)
163 const void *a
= NULL
;
164 char abuf
[1024], nbuf
[1024], *addr
= NULL
;
166 char Abuf
[1024], pbuf
[32], *name
= NULL
, *port
= NULL
;
167 char *ebuf
= &sbuf
[len
- 1], *buf
= sbuf
;
170 #ifdef HAVE_NETATALK_AT_H
171 const struct sockaddr_at
*sat
= NULL
;
173 const struct sockaddr_in
*sin4
= NULL
;
174 const struct sockaddr_in6
*sin6
= NULL
;
175 const struct sockaddr_un
*sun
= NULL
;
176 #ifdef HAVE_NET_IF_DL_H
177 const struct sockaddr_dl
*sdl
= NULL
;
182 #define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
183 while (/*CONSTCOND*/0)
184 #define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
185 while (/*CONSTCOND*/0)
186 #define ADDNA() do { if (na) ADDS("N/A"); } \
187 while (/*CONSTCOND*/0)
189 switch (sa
->sa_family
) {
192 #ifdef HAVE_NETATALK_AT_H
194 sat
= ((const struct sockaddr_at
*)(const void *)sa
);
195 p
= ntohs(sat
->sat_port
);
196 (void)snprintf(addr
= abuf
, sizeof(abuf
), "%u.%u",
197 ntohs(sat
->sat_addr
.s_net
), sat
->sat_addr
.s_node
);
198 (void)snprintf(port
= pbuf
, sizeof(pbuf
), "%d", p
);
202 sun
= ((const struct sockaddr_un
*)(const void *)sa
);
203 (void)strlcpy(addr
= abuf
, sun
->sun_path
, sizeof(abuf
));
206 sin4
= ((const struct sockaddr_in
*)(const void *)sa
);
207 p
= ntohs(sin4
->sin_port
);
211 sin6
= ((const struct sockaddr_in6
*)(const void *)sa
);
212 p
= ntohs(sin6
->sin6_port
);
213 a
= &sin6
->sin6_addr
;
215 #ifdef HAVE_NET_IF_DL_H
217 sdl
= ((const struct sockaddr_dl
*)(const void *)sa
);
218 (void)strlcpy(addr
= abuf
, link_ntoa(sdl
), sizeof(abuf
));
219 if ((w
= strchr(addr
, ':')) != 0) {
226 errno
= EAFNOSUPPORT
;
233 if (a
&& getnameinfo(sa
, (socklen_t
)SLEN(sa
), addr
= abuf
,
234 (unsigned int)sizeof(abuf
), NULL
, 0,
235 NI_NUMERICHOST
|NI_NUMERICSERV
) != 0)
238 for (ptr
= fmt
; *ptr
; ptr
++) {
253 (void)snprintf(nbuf
, sizeof(nbuf
), "%d", p
);
259 (void)snprintf(nbuf
, sizeof(nbuf
), "%d", sa
->sa_family
);
263 (void)snprintf(nbuf
, sizeof(nbuf
), "%d", SLEN(sa
));
272 getnameinfo(sa
, (socklen_t
)SLEN(sa
),
274 (unsigned int)sizeof(nbuf
), NULL
, 0, 0);
284 getnameinfo(sa
, (socklen_t
)SLEN(sa
), NULL
, 0,
286 (unsigned int)sizeof(pbuf
), 0);
291 #ifdef HAVE_NET_IF_DL_H
292 if (sdl
&& addr
!= abuf
) {
302 (void)snprintf(nbuf
, sizeof(nbuf
), "%d",
303 sin6
->sin6_flowinfo
);
312 (void)snprintf(nbuf
, sizeof(nbuf
), "%d",
313 sin6
->sin6_scope_id
);
321 #ifdef HAVE_NETATALK_AT_H
323 const struct netrange
*n
=
324 &sat
->sat_range
.r_netrange
;
325 (void)snprintf(nbuf
, sizeof(nbuf
),
326 "%d:[%d,%d]", n
->nr_phase
, n
->nr_firstnet
,
336 switch (sa
->sa_family
) {
337 #ifdef HAVE_NETATALK_AT_H
339 debug_at(nbuf
, sizeof(nbuf
), sat
);
343 debug_un(nbuf
, sizeof(nbuf
), sun
);
346 debug_in(nbuf
, sizeof(nbuf
), sin4
);
349 debug_in6(nbuf
, sizeof(nbuf
), sin6
);
351 #ifdef HAVE_NET_IF_DL_H
353 debug_dl(nbuf
, sizeof(nbuf
), sdl
);
378 sbuf
[len
- 1] = '\0';
379 return (int)(buf
- sbuf
);