]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libnetbsd/sockaddr_snprintf.c
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / lib / libnetbsd / sockaddr_snprintf.c
1 /*      $NetBSD: sockaddr_snprintf.c,v 1.14 2016/12/29 18:30:55 christos Exp $  */
2
3 /*-
4  * Copyright (c) 2004, 2016 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
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.
18  *
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.
30  */
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42
43 #include <netinet/in.h>
44 #ifdef HAVE_NET_IF_DL_H
45 #include <net/if_dl.h>
46 #endif
47
48 #include <stdio.h>
49 #include <string.h>
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <util.h>
53 #include <libutil.h>
54 #include <netdb.h>
55
56 #ifdef BSD4_4
57 # define SALEN(sa)      ((sa)->sa ## _len)
58 #else
59 # define SALEN(sa)      ((unsigned)sizeof(*sa))
60 #endif
61
62 static int
63 debug_in(char *str, size_t len, const struct sockaddr_in *sin)
64 {
65         return snprintf(str, len, "sin_len=%u, sin_family=%u, sin_port=%u, "
66             "sin_addr.s_addr=%08x",
67             SALEN(sin), sin->sin_family, sin->sin_port,
68             sin->sin_addr.s_addr);
69 }
70
71 static int
72 debug_in6(char *str, size_t len, const struct sockaddr_in6 *sin6)
73 {
74         const uint8_t *s = sin6->sin6_addr.s6_addr;
75
76         return snprintf(str, len, "sin6_len=%u, sin6_family=%u, sin6_port=%u, "
77             "sin6_flowinfo=%u, "
78             "sin6_addr=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
79             "%02x:%02x:%02x:%02x:%02x:%02x, sin6_scope_id=%u",
80             SALEN(sin6), sin6->sin6_family, sin6->sin6_port,
81             sin6->sin6_flowinfo, s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5],
82             s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb], s[0xc], s[0xd],
83             s[0xe], s[0xf], sin6->sin6_scope_id);
84 }
85
86 static int
87 debug_un(char *str, size_t len, const struct sockaddr_un *sun)
88 {
89         return snprintf(str, len, "sun_len=%u, sun_family=%u, sun_path=%*s",
90             SALEN(sun), sun->sun_family, (int)sizeof(sun->sun_path),
91             sun->sun_path);
92 }
93
94 #ifdef HAVE_NET_IF_DL_H
95 static int
96 debug_dl(char *str, size_t len, const struct sockaddr_dl *sdl)
97 {
98         const uint8_t *s = (const void *)sdl->sdl_data;
99
100         return snprintf(str, len, "sdl_len=%u, sdl_family=%u, sdl_index=%u, "
101             "sdl_type=%u, sdl_nlen=%u, sdl_alen=%u, sdl_slen=%u, sdl_data="
102             "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
103             SALEN(sdl), sdl->sdl_family, sdl->sdl_index,
104             sdl->sdl_type, sdl->sdl_nlen, sdl->sdl_alen, sdl->sdl_slen,
105             s[0x0], s[0x1], s[0x2], s[0x3], s[0x4], s[0x5],
106             s[0x6], s[0x7], s[0x8], s[0x9], s[0xa], s[0xb]);
107 }
108 #endif
109
110 int
111 sockaddr_snprintf(char * const sbuf, const size_t len, const char * const fmt,
112     const struct sockaddr * const sa)
113 {
114         const void *a = NULL;
115         char abuf[1024], nbuf[1024], *addr = NULL;
116         char Abuf[1024], pbuf[32], *name = NULL, *port = NULL;
117         char *ebuf = &sbuf[len - 1], *buf = sbuf;
118         const char *ptr, *s;
119         size_t salen;
120         int p = -1;
121         const struct sockaddr_in *sin4 = NULL;
122         const struct sockaddr_in6 *sin6 = NULL;
123         const struct sockaddr_un *sun = NULL;
124 #ifdef HAVE_NET_IF_DL_H
125         const struct sockaddr_dl *sdl = NULL;
126         char *w = NULL;
127 #endif
128         int na = 1;
129
130 #define ADDC(c) do { if (buf < ebuf) *buf++ = c; else buf++; } \
131         while (/*CONSTCOND*/0)
132 #define ADDS(p) do { for (s = p; *s; s++) ADDC(*s); } \
133         while (/*CONSTCOND*/0)
134 #define ADDNA() do { if (na) ADDS("N/A"); } \
135         while (/*CONSTCOND*/0)
136
137         switch (sa->sa_family) {
138         case AF_UNSPEC:
139                 goto done;
140         case AF_LOCAL:
141                 salen = sizeof(*sun);
142                 sun = ((const struct sockaddr_un *)(const void *)sa);
143                 (void)strlcpy(addr = abuf, sun->sun_path, sizeof(abuf));
144                 break;
145         case AF_INET:
146                 salen = sizeof(*sin4);
147                 sin4 = ((const struct sockaddr_in *)(const void *)sa);
148                 p = ntohs(sin4->sin_port);
149                 a = &sin4->sin_addr;
150                 break;
151         case AF_INET6:
152                 salen = sizeof(*sin6);
153                 sin6 = ((const struct sockaddr_in6 *)(const void *)sa);
154                 p = ntohs(sin6->sin6_port);
155                 a = &sin6->sin6_addr;
156                 break;
157 #ifdef HAVE_NET_IF_DL_H
158         case AF_LINK:
159                 sdl = ((const struct sockaddr_dl *)(const void *)sa);
160                 addr = abuf;
161                 if (sdl->sdl_slen == 0 && sdl->sdl_nlen == 0
162                     && sdl->sdl_alen == 0) {
163                         salen = sizeof(*sdl);
164                         (void)snprintf(abuf, sizeof(abuf), "link#%hu",
165                             sdl->sdl_index);
166                 } else {
167                         salen = sdl->sdl_slen + sdl->sdl_nlen +  sdl->sdl_alen;
168                         if (salen < sizeof(*sdl))
169                                 salen = sizeof(*sdl);
170                         (void)strlcpy(abuf, link_ntoa(sdl), sizeof(abuf));
171                         if ((w = strchr(addr, ':')) != NULL) {
172                             *w++ = '\0';
173                             addr = w;
174                         }
175                 }
176                 break;
177 #endif
178         default:
179                 errno = EAFNOSUPPORT;
180                 return -1;
181         }
182
183         if (addr == abuf)
184                 name = addr;
185
186         if (a && getnameinfo(sa, (socklen_t)salen, addr = abuf,
187             (unsigned int)sizeof(abuf), NULL, 0,
188             NI_NUMERICHOST|NI_NUMERICSERV) != 0)
189                 return -1;
190
191         for (ptr = fmt; *ptr; ptr++) {
192                 if (*ptr != '%') {
193                         ADDC(*ptr);
194                         continue;
195                 }
196           next_char:
197                 switch (*++ptr) {
198                 case '?':
199                         na = 0;
200                         goto next_char;
201                 case 'a':
202                         ADDS(addr);
203                         break;
204                 case 'p':
205                         if (p != -1) {
206                                 (void)snprintf(nbuf, sizeof(nbuf), "%d", p);
207                                 ADDS(nbuf);
208                         } else
209                                 ADDNA();
210                         break;
211                 case 'f':
212                         (void)snprintf(nbuf, sizeof(nbuf), "%d", sa->sa_family);
213                         ADDS(nbuf);
214                         break;
215                 case 'l':
216                         (void)snprintf(nbuf, sizeof(nbuf), "%zu", salen);
217                         ADDS(nbuf);
218                         break;
219                 case 'A':
220                         if (name)
221                                 ADDS(name);
222                         else if (!a)
223                                 ADDNA();
224                         else {
225                                 getnameinfo(sa, (socklen_t)salen, name = Abuf,
226                                         (unsigned int)sizeof(nbuf), NULL, 0, 0);
227                                 ADDS(name);
228                         }
229                         break;
230                 case 'P':
231                         if (port)
232                                 ADDS(port);
233                         else if (p == -1)
234                                 ADDNA();
235                         else {
236                                 getnameinfo(sa, (socklen_t)salen, NULL, 0,
237                                         port = pbuf,
238                                         (unsigned int)sizeof(pbuf), 0);
239                                 ADDS(port);
240                         }
241                         break;
242                 case 'I':
243 #ifdef HAVE_NET_IF_DL_H
244                         if (sdl && addr != abuf) {
245                                 ADDS(abuf);
246                         } else
247 #endif
248                         {
249                                 ADDNA();
250                         }
251                         break;
252                 case 'F':
253                         if (sin6) {
254                                 (void)snprintf(nbuf, sizeof(nbuf), "%d",
255                                     sin6->sin6_flowinfo);
256                                 ADDS(nbuf);
257                                 break;
258                         } else {
259                                 ADDNA();
260                         }
261                         break;
262                 case 'S':
263                         if (sin6) {
264                                 (void)snprintf(nbuf, sizeof(nbuf), "%d",
265                                     sin6->sin6_scope_id);
266                                 ADDS(nbuf);
267                                 break;
268                         } else {
269                                 ADDNA();
270                         }
271                         break;
272                 case 'R':
273                         {
274                                 ADDNA();
275                         }
276                         break;
277                 case 'D':
278                         switch (sa->sa_family) {
279                         case AF_LOCAL:
280                                 debug_un(nbuf, sizeof(nbuf), sun);
281                                 break;
282                         case AF_INET:
283                                 debug_in(nbuf, sizeof(nbuf), sin4);
284                                 break;
285                         case AF_INET6:
286                                 debug_in6(nbuf, sizeof(nbuf), sin6);
287                                 break;
288 #ifdef HAVE_NET_IF_DL_H
289                         case AF_LINK:
290                                 debug_dl(nbuf, sizeof(nbuf), sdl);
291                                 break;
292 #endif
293                         default:
294                                 abort();
295                         }
296                         ADDS(nbuf);
297                         break;
298                 default:
299                         ADDC('%');
300                         if (na == 0)
301                                 ADDC('?');
302                         if (*ptr == '\0')
303                                 goto done;
304                         /*FALLTHROUGH*/
305                 case '%':
306                         ADDC(*ptr);
307                         break;
308                 }
309                 na = 1;
310         }
311 done:
312         if (buf < ebuf)
313                 *buf = '\0';
314         else if (len != 0)
315                 sbuf[len - 1] = '\0';
316         return (int)(buf - sbuf);
317 }