GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: show.c,v 1.53 2017/01/21 11:32:04 guenther Exp $ */ |
||
2 |
/* $NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr Exp $ */ |
||
3 |
|||
4 |
/* |
||
5 |
* Copyright (c) 1983, 1988, 1993 |
||
6 |
* The Regents of the University of California. All rights reserved. |
||
7 |
* |
||
8 |
* Redistribution and use in source and binary forms, with or without |
||
9 |
* modification, are permitted provided that the following conditions |
||
10 |
* are met: |
||
11 |
* 1. Redistributions of source code must retain the above copyright |
||
12 |
* notice, this list of conditions and the following disclaimer. |
||
13 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
14 |
* notice, this list of conditions and the following disclaimer in the |
||
15 |
* documentation and/or other materials provided with the distribution. |
||
16 |
* 3. Neither the name of the University nor the names of its contributors |
||
17 |
* may be used to endorse or promote products derived from this software |
||
18 |
* without specific prior written permission. |
||
19 |
* |
||
20 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
21 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
22 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
23 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
24 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
25 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
26 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
27 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
28 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
29 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
30 |
* SUCH DAMAGE. |
||
31 |
*/ |
||
32 |
|||
33 |
#include <sys/socket.h> |
||
34 |
#include <sys/sysctl.h> |
||
35 |
|||
36 |
#include <net/if.h> |
||
37 |
#include <net/if_dl.h> |
||
38 |
#include <net/if_types.h> |
||
39 |
#include <net/route.h> |
||
40 |
#include <netinet/in.h> |
||
41 |
#include <netinet/if_ether.h> |
||
42 |
#include <netmpls/mpls.h> |
||
43 |
#include <arpa/inet.h> |
||
44 |
|||
45 |
#include <err.h> |
||
46 |
#include <errno.h> |
||
47 |
#include <netdb.h> |
||
48 |
#include <stdio.h> |
||
49 |
#include <stddef.h> |
||
50 |
#include <stdlib.h> |
||
51 |
#include <string.h> |
||
52 |
#include <unistd.h> |
||
53 |
#include <limits.h> |
||
54 |
|||
55 |
#include "netstat.h" |
||
56 |
|||
57 |
char *any_ntoa(const struct sockaddr *); |
||
58 |
char *link_print(struct sockaddr *); |
||
59 |
char *label_print(struct sockaddr *); |
||
60 |
|||
61 |
#define ROUNDUP(a) \ |
||
62 |
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) |
||
63 |
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) |
||
64 |
|||
65 |
/* |
||
66 |
* Definitions for showing gateway flags. |
||
67 |
*/ |
||
68 |
struct bits { |
||
69 |
int b_mask; |
||
70 |
char b_val; |
||
71 |
}; |
||
72 |
static const struct bits bits[] = { |
||
73 |
{ RTF_UP, 'U' }, |
||
74 |
{ RTF_GATEWAY, 'G' }, |
||
75 |
{ RTF_HOST, 'H' }, |
||
76 |
{ RTF_REJECT, 'R' }, |
||
77 |
{ RTF_DYNAMIC, 'D' }, |
||
78 |
{ RTF_MODIFIED, 'M' }, |
||
79 |
{ RTF_DONE, 'd' }, /* Completed -- for routing messages only */ |
||
80 |
{ RTF_CLONING, 'C' }, |
||
81 |
{ RTF_MULTICAST,'m' }, |
||
82 |
{ RTF_LLINFO, 'L' }, |
||
83 |
{ RTF_STATIC, 'S' }, |
||
84 |
{ RTF_BLACKHOLE,'B' }, |
||
85 |
{ RTF_PROTO3, '3' }, |
||
86 |
{ RTF_PROTO2, '2' }, |
||
87 |
{ RTF_PROTO1, '1' }, |
||
88 |
{ RTF_CLONED, 'c' }, |
||
89 |
{ RTF_CACHED, 'h' }, |
||
90 |
{ RTF_MPATH, 'P' }, |
||
91 |
{ RTF_MPLS, 'T' }, |
||
92 |
{ RTF_LOCAL, 'l' }, |
||
93 |
{ RTF_BFD, 'F' }, |
||
94 |
{ RTF_BROADCAST,'b' }, |
||
95 |
{ RTF_CONNECTED,'n' }, |
||
96 |
{ 0 } |
||
97 |
}; |
||
98 |
|||
99 |
int WID_DST(int); |
||
100 |
void p_rtentry(struct rt_msghdr *); |
||
101 |
void pr_family(int); |
||
102 |
void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int); |
||
103 |
void p_sockaddr_mpls(struct sockaddr *, struct sockaddr *, int, int); |
||
104 |
void p_flags(int, char *); |
||
105 |
char *routename4(in_addr_t); |
||
106 |
char *routename6(struct sockaddr_in6 *); |
||
107 |
|||
108 |
size_t |
||
109 |
get_sysctl(const int *mib, u_int mcnt, char **buf) |
||
110 |
{ |
||
111 |
160 |
size_t needed; |
|
112 |
|||
113 |
80 |
while (1) { |
|
114 |
✗✓ | 80 |
if (sysctl(mib, mcnt, NULL, &needed, NULL, 0) == -1) |
115 |
err(1, "sysctl-estimate"); |
||
116 |
✓✗ | 80 |
if (needed == 0) |
117 |
break; |
||
118 |
✗✓ | 80 |
if ((*buf = realloc(*buf, needed)) == NULL) |
119 |
err(1, NULL); |
||
120 |
✗✓ | 80 |
if (sysctl(mib, mcnt, *buf, &needed, NULL, 0) == -1) { |
121 |
if (errno == ENOMEM) |
||
122 |
continue; |
||
123 |
err(1, "sysctl"); |
||
124 |
} |
||
125 |
break; |
||
126 |
} |
||
127 |
|||
128 |
160 |
return needed; |
|
129 |
80 |
} |
|
130 |
|||
131 |
/* |
||
132 |
* Print routing tables. |
||
133 |
*/ |
||
134 |
void |
||
135 |
p_rttables(int af, u_int tableid) |
||
136 |
{ |
||
137 |
struct rt_msghdr *rtm; |
||
138 |
160 |
char *buf = NULL, *next, *lim = NULL; |
|
139 |
size_t needed; |
||
140 |
80 |
int mib[7], mcnt; |
|
141 |
struct sockaddr *sa; |
||
142 |
|||
143 |
80 |
mib[0] = CTL_NET; |
|
144 |
80 |
mib[1] = PF_ROUTE; |
|
145 |
80 |
mib[2] = 0; |
|
146 |
80 |
mib[3] = af; |
|
147 |
80 |
mib[4] = NET_RT_DUMP; |
|
148 |
80 |
mib[5] = 0; |
|
149 |
80 |
mib[6] = tableid; |
|
150 |
mcnt = 7; |
||
151 |
|||
152 |
80 |
needed = get_sysctl(mib, mcnt, &buf); |
|
153 |
80 |
lim = buf + needed; |
|
154 |
|||
155 |
80 |
printf("Routing tables\n"); |
|
156 |
|||
157 |
✓✗ | 80 |
if (buf) { |
158 |
✓✓ | 3392 |
for (next = buf; next < lim; next += rtm->rtm_msglen) { |
159 |
1616 |
rtm = (struct rt_msghdr *)next; |
|
160 |
✓✗ | 1616 |
if (rtm->rtm_version != RTM_VERSION) |
161 |
continue; |
||
162 |
1616 |
sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); |
|
163 |
1616 |
p_rtentry(rtm); |
|
164 |
1616 |
} |
|
165 |
} |
||
166 |
80 |
free(buf); |
|
167 |
80 |
} |
|
168 |
|||
169 |
/* |
||
170 |
* column widths; each followed by one space |
||
171 |
* width of destination/gateway column |
||
172 |
* strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 |
||
173 |
*/ |
||
174 |
#define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18) |
||
175 |
|||
176 |
int |
||
177 |
WID_DST(int af) |
||
178 |
{ |
||
179 |
|||
180 |
✓✗ | 6944 |
if (nflag) |
181 |
✗✓✓ | 3472 |
switch (af) { |
182 |
case AF_MPLS: |
||
183 |
return 9; |
||
184 |
case AF_INET6: |
||
185 |
2560 |
return 34; |
|
186 |
default: |
||
187 |
912 |
return 18; |
|
188 |
} |
||
189 |
else |
||
190 |
switch (af) { |
||
191 |
case AF_MPLS: |
||
192 |
return 9; |
||
193 |
default: |
||
194 |
return 18; |
||
195 |
} |
||
196 |
3472 |
} |
|
197 |
|||
198 |
/* |
||
199 |
* Print header for routing table columns. |
||
200 |
*/ |
||
201 |
void |
||
202 |
pr_rthdr(int af, int Aflag) |
||
203 |
{ |
||
204 |
✗✓ | 240 |
if (Aflag) |
205 |
printf("%-*.*s ", PLEN, PLEN, "Address"); |
||
206 |
✗✗✓ | 120 |
switch (af) { |
207 |
case PF_KEY: |
||
208 |
printf("%-18s %-5s %-18s %-5s %-5s %-22s\n", |
||
209 |
"Source", "Port", "Destination", |
||
210 |
"Port", "Proto", "SA(Address/Proto/Type/Direction)"); |
||
211 |
break; |
||
212 |
case PF_MPLS: |
||
213 |
printf("%-9s %-9s %-6s %-18s %-6.6s %5.5s %8.8s %5.5s %4.4s %s\n", |
||
214 |
"In label", "Out label", "Op", "Gateway", |
||
215 |
"Flags", "Refs", "Use", "Mtu", "Prio", "Interface"); |
||
216 |
break; |
||
217 |
default: |
||
218 |
120 |
printf("%-*.*s %-*.*s %-6.6s %5.5s %8.8s %5.5s %4.4s %s", |
|
219 |
120 |
WID_DST(af), WID_DST(af), "Destination", |
|
220 |
✓✓✓✓ |
520 |
WID_GW(af), WID_GW(af), "Gateway", |
221 |
"Flags", "Refs", "Use", "Mtu", "Prio", "Iface"); |
||
222 |
✗✓ | 120 |
if (vflag && !Aflag) |
223 |
printf(" %s", "Label"); |
||
224 |
✓✗ | 240 |
putchar('\n'); |
225 |
break; |
||
226 |
} |
||
227 |
120 |
} |
|
228 |
|||
229 |
static void |
||
230 |
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) |
||
231 |
{ |
||
232 |
int i; |
||
233 |
|||
234 |
✓✓ | 53328 |
for (i = 0; i < RTAX_MAX; i++) { |
235 |
✓✓ | 24240 |
if (addrs & (1 << i)) { |
236 |
8080 |
rti_info[i] = sa; |
|
237 |
16160 |
sa = (struct sockaddr *)((char *)(sa) + |
|
238 |
✓✗ | 24240 |
ROUNDUP(sa->sa_len)); |
239 |
8080 |
} else |
|
240 |
16160 |
rti_info[i] = NULL; |
|
241 |
} |
||
242 |
1616 |
} |
|
243 |
|||
244 |
/* |
||
245 |
* Print a routing table entry. |
||
246 |
*/ |
||
247 |
void |
||
248 |
p_rtentry(struct rt_msghdr *rtm) |
||
249 |
{ |
||
250 |
static int old_af = -1; |
||
251 |
3232 |
struct sockaddr *sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen); |
|
252 |
1616 |
struct sockaddr *mask, *rti_info[RTAX_MAX]; |
|
253 |
1616 |
char ifbuf[IF_NAMESIZE]; |
|
254 |
|||
255 |
✗✓ | 1616 |
if (sa->sa_family == AF_KEY) |
256 |
return; |
||
257 |
|||
258 |
1616 |
get_rtaddrs(rtm->rtm_addrs, sa, rti_info); |
|
259 |
|||
260 |
✗✓✗✗ |
1616 |
if (Fflag && rti_info[RTAX_GATEWAY]->sa_family != sa->sa_family) { |
261 |
return; |
||
262 |
} |
||
263 |
✓✓ | 1616 |
if (old_af != sa->sa_family) { |
264 |
120 |
old_af = sa->sa_family; |
|
265 |
120 |
pr_family(sa->sa_family); |
|
266 |
120 |
pr_rthdr(sa->sa_family, 0); |
|
267 |
120 |
} |
|
268 |
|||
269 |
1616 |
mask = rti_info[RTAX_NETMASK]; |
|
270 |
✗✓ | 1616 |
if ((sa = rti_info[RTAX_DST]) == NULL) |
271 |
return; |
||
272 |
|||
273 |
1616 |
p_sockaddr(sa, mask, rtm->rtm_flags, WID_DST(sa->sa_family)); |
|
274 |
3232 |
p_sockaddr_mpls(sa, rti_info[RTAX_SRC], rtm->rtm_mpls, |
|
275 |
1616 |
WID_DST(sa->sa_family)); |
|
276 |
|||
277 |
3232 |
p_sockaddr(rti_info[RTAX_GATEWAY], NULL, RTF_HOST, |
|
278 |
✓✓ | 4432 |
WID_GW(sa->sa_family)); |
279 |
|||
280 |
1616 |
p_flags(rtm->rtm_flags, "%-6.6s "); |
|
281 |
3232 |
printf("%5u %8llu ", rtm->rtm_rmx.rmx_refcnt, |
|
282 |
1616 |
rtm->rtm_rmx.rmx_pksent); |
|
283 |
✓✓ | 1616 |
if (rtm->rtm_rmx.rmx_mtu) |
284 |
1092 |
printf("%5u ", rtm->rtm_rmx.rmx_mtu); |
|
285 |
else |
||
286 |
524 |
printf("%5s ", "-"); |
|
287 |
✓✗ | 3232 |
putchar((rtm->rtm_rmx.rmx_locks & RTV_MTU) ? 'L' : ' '); |
288 |
3232 |
printf(" %2d %-5.16s", rtm->rtm_priority, |
|
289 |
1616 |
if_indextoname(rtm->rtm_index, ifbuf)); |
|
290 |
✗✓✗✗ |
1616 |
if (vflag && rti_info[RTAX_LABEL]) |
291 |
printf(" %s", ((struct sockaddr_rtlabel *) |
||
292 |
rti_info[RTAX_LABEL])->sr_label); |
||
293 |
✓✗ | 3232 |
putchar('\n'); |
294 |
3232 |
} |
|
295 |
|||
296 |
/* |
||
297 |
* Print address family header before a section of the routing table. |
||
298 |
*/ |
||
299 |
void |
||
300 |
pr_family(int af) |
||
301 |
{ |
||
302 |
char *afname; |
||
303 |
|||
304 |
✓✓✗✗ ✗ |
240 |
switch (af) { |
305 |
case AF_INET: |
||
306 |
afname = "Internet"; |
||
307 |
40 |
break; |
|
308 |
case AF_INET6: |
||
309 |
afname = "Internet6"; |
||
310 |
80 |
break; |
|
311 |
case PF_KEY: |
||
312 |
afname = "Encap"; |
||
313 |
break; |
||
314 |
case AF_MPLS: |
||
315 |
afname = "MPLS"; |
||
316 |
break; |
||
317 |
default: |
||
318 |
afname = NULL; |
||
319 |
break; |
||
320 |
} |
||
321 |
✓✗ | 120 |
if (afname) |
322 |
120 |
printf("\n%s:\n", afname); |
|
323 |
else |
||
324 |
printf("\nProtocol Family %d:\n", af); |
||
325 |
120 |
} |
|
326 |
|||
327 |
void |
||
328 |
p_addr(struct sockaddr *sa, struct sockaddr *mask, int flags) |
||
329 |
{ |
||
330 |
p_sockaddr(sa, mask, flags, WID_DST(sa->sa_family)); |
||
331 |
} |
||
332 |
|||
333 |
void |
||
334 |
p_gwaddr(struct sockaddr *sa, int af) |
||
335 |
{ |
||
336 |
p_sockaddr(sa, 0, RTF_HOST, WID_GW(af)); |
||
337 |
} |
||
338 |
|||
339 |
void |
||
340 |
p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) |
||
341 |
{ |
||
342 |
char *cp; |
||
343 |
|||
344 |
✓✗✓ | 6464 |
switch (sa->sa_family) { |
345 |
case AF_INET6: |
||
346 |
{ |
||
347 |
2352 |
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; |
|
348 |
2352 |
struct in6_addr *in6 = &sa6->sin6_addr; |
|
349 |
|||
350 |
/* |
||
351 |
* XXX: This is a special workaround for KAME kernels. |
||
352 |
* sin6_scope_id field of SA should be set in the future. |
||
353 |
*/ |
||
354 |
✓✓✓✓ ✓✗ |
2976 |
if (IN6_IS_ADDR_LINKLOCAL(in6) || |
355 |
✓✓✓✓ |
2264 |
IN6_IS_ADDR_MC_LINKLOCAL(in6) || |
356 |
✓✓ | 1944 |
IN6_IS_ADDR_MC_INTFACELOCAL(in6)) { |
357 |
/* XXX: override is ok? */ |
||
358 |
728 |
sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *) |
|
359 |
&in6->s6_addr[2]); |
||
360 |
728 |
*(u_short *)&in6->s6_addr[2] = 0; |
|
361 |
728 |
} |
|
362 |
✓✓ | 2352 |
if (flags & RTF_HOST) |
363 |
1312 |
cp = routename((struct sockaddr *)sa6); |
|
364 |
else |
||
365 |
1040 |
cp = netname((struct sockaddr *)sa6, mask); |
|
366 |
break; |
||
367 |
} |
||
368 |
case AF_MPLS: |
||
369 |
return; |
||
370 |
default: |
||
371 |
✓✓ | 880 |
if ((flags & RTF_HOST) || mask == NULL) |
372 |
710 |
cp = routename(sa); |
|
373 |
else |
||
374 |
170 |
cp = netname(sa, mask); |
|
375 |
break; |
||
376 |
} |
||
377 |
✗✓ | 3232 |
if (width < 0) |
378 |
printf("%s", cp); |
||
379 |
else { |
||
380 |
✓✗ | 3232 |
if (nflag) |
381 |
3232 |
printf("%-*s ", width, cp); |
|
382 |
else |
||
383 |
printf("%-*.*s ", width, width, cp); |
||
384 |
} |
||
385 |
6464 |
} |
|
386 |
|||
387 |
static char line[HOST_NAME_MAX+1]; |
||
388 |
static char domain[HOST_NAME_MAX+1]; |
||
389 |
|||
390 |
void |
||
391 |
p_sockaddr_mpls(struct sockaddr *in, struct sockaddr *out, int flags, int width) |
||
392 |
{ |
||
393 |
✗✓ | 3232 |
if (in->sa_family != AF_MPLS) |
394 |
return; |
||
395 |
|||
396 |
if (flags & MPLS_OP_POP || flags == MPLS_OP_LOCAL) { |
||
397 |
printf("%-*s ", width, label_print(in)); |
||
398 |
printf("%-*s ", width, label_print(NULL)); |
||
399 |
} else { |
||
400 |
printf("%-*s ", width, label_print(in)); |
||
401 |
printf("%-*s ", width, label_print(out)); |
||
402 |
} |
||
403 |
|||
404 |
printf("%-6s ", mpls_op(flags)); |
||
405 |
1616 |
} |
|
406 |
|||
407 |
void |
||
408 |
p_flags(int f, char *format) |
||
409 |
{ |
||
410 |
3232 |
char name[33], *flags; |
|
411 |
const struct bits *p = bits; |
||
412 |
|||
413 |
✓✓ | 77568 |
for (flags = name; p->b_mask && flags < &name[sizeof(name) - 2]; p++) |
414 |
✓✓ | 37168 |
if (p->b_mask & f) |
415 |
5784 |
*flags++ = p->b_val; |
|
416 |
1616 |
*flags = '\0'; |
|
417 |
1616 |
printf(format, name); |
|
418 |
1616 |
} |
|
419 |
|||
420 |
char * |
||
421 |
routename(struct sockaddr *sa) |
||
422 |
{ |
||
423 |
char *cp = NULL; |
||
424 |
static int first = 1; |
||
425 |
|||
426 |
✓✓ | 4044 |
if (first) { |
427 |
80 |
first = 0; |
|
428 |
✓✗✓✗ |
160 |
if (gethostname(domain, sizeof(domain)) == 0 && |
429 |
80 |
(cp = strchr(domain, '.'))) |
|
430 |
80 |
(void)strlcpy(domain, cp + 1, sizeof(domain)); |
|
431 |
else |
||
432 |
domain[0] = '\0'; |
||
433 |
cp = NULL; |
||
434 |
80 |
} |
|
435 |
|||
436 |
✗✓ | 2022 |
if (sa->sa_len == 0) { |
437 |
(void)strlcpy(line, "default", sizeof(line)); |
||
438 |
return (line); |
||
439 |
} |
||
440 |
|||
441 |
✓✓✓✗ ✗✗ |
2022 |
switch (sa->sa_family) { |
442 |
case AF_INET: |
||
443 |
518 |
return |
|
444 |
518 |
(routename4(((struct sockaddr_in *)sa)->sin_addr.s_addr)); |
|
445 |
|||
446 |
case AF_INET6: |
||
447 |
{ |
||
448 |
1312 |
struct sockaddr_in6 sin6; |
|
449 |
|||
450 |
1312 |
memset(&sin6, 0, sizeof(sin6)); |
|
451 |
1312 |
memcpy(&sin6, sa, sa->sa_len); |
|
452 |
1312 |
sin6.sin6_family = AF_INET6; |
|
453 |
✓✗✗✓ |
1616 |
if (sa->sa_len == sizeof(struct sockaddr_in6) && |
454 |
✓✓✗✓ |
1616 |
(IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || |
455 |
✗✓✗✗ |
1008 |
IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) || |
456 |
✗✓✗✗ |
1008 |
IN6_IS_ADDR_MC_INTFACELOCAL(&sin6.sin6_addr)) && |
457 |
304 |
sin6.sin6_scope_id == 0) { |
|
458 |
sin6.sin6_scope_id = |
||
459 |
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); |
||
460 |
sin6.sin6_addr.s6_addr[2] = 0; |
||
461 |
sin6.sin6_addr.s6_addr[3] = 0; |
||
462 |
} |
||
463 |
1312 |
return (routename6(&sin6)); |
|
464 |
1312 |
} |
|
465 |
|||
466 |
case AF_LINK: |
||
467 |
192 |
return (link_print(sa)); |
|
468 |
case AF_MPLS: |
||
469 |
return (label_print(sa)); |
||
470 |
case AF_UNSPEC: |
||
471 |
if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) { |
||
472 |
static char name[RTLABEL_LEN]; |
||
473 |
struct sockaddr_rtlabel *sr; |
||
474 |
|||
475 |
sr = (struct sockaddr_rtlabel *)sa; |
||
476 |
(void)strlcpy(name, sr->sr_label, sizeof(name)); |
||
477 |
return (name); |
||
478 |
} |
||
479 |
/* FALLTHROUGH */ |
||
480 |
default: |
||
481 |
(void)snprintf(line, sizeof(line), "(%d) %s", |
||
482 |
sa->sa_family, any_ntoa(sa)); |
||
483 |
break; |
||
484 |
} |
||
485 |
return (line); |
||
486 |
2022 |
} |
|
487 |
|||
488 |
char * |
||
489 |
routename4(in_addr_t in) |
||
490 |
{ |
||
491 |
char *cp = NULL; |
||
492 |
struct in_addr ina; |
||
493 |
struct hostent *hp; |
||
494 |
|||
495 |
✗✓ | 518 |
if (in == INADDR_ANY) |
496 |
cp = "default"; |
||
497 |
✗✓ | 518 |
if (!cp && !nflag) { |
498 |
if ((hp = gethostbyaddr((char *)&in, |
||
499 |
sizeof(in), AF_INET)) != NULL) { |
||
500 |
if ((cp = strchr(hp->h_name, '.')) && |
||
501 |
!strcmp(cp + 1, domain)) |
||
502 |
*cp = '\0'; |
||
503 |
cp = hp->h_name; |
||
504 |
} |
||
505 |
} |
||
506 |
518 |
ina.s_addr = in; |
|
507 |
✗✓ | 1554 |
strlcpy(line, cp ? cp : inet_ntoa(ina), sizeof(line)); |
508 |
|||
509 |
518 |
return (line); |
|
510 |
} |
||
511 |
|||
512 |
char * |
||
513 |
routename6(struct sockaddr_in6 *sin6) |
||
514 |
{ |
||
515 |
int niflags = 0; |
||
516 |
|||
517 |
✓✗ | 2624 |
if (nflag) |
518 |
1312 |
niflags |= NI_NUMERICHOST; |
|
519 |
else |
||
520 |
niflags |= NI_NOFQDN; |
||
521 |
|||
522 |
✗✓ | 2624 |
if (getnameinfo((struct sockaddr *)sin6, sizeof(*sin6), |
523 |
1312 |
line, sizeof(line), NULL, 0, niflags) != 0) |
|
524 |
strncpy(line, "invalid", sizeof(line)); |
||
525 |
|||
526 |
1312 |
return (line); |
|
527 |
} |
||
528 |
|||
529 |
/* |
||
530 |
* Return the name of the network whose address is given. |
||
531 |
* The address is assumed to be that of a net or subnet, not a host. |
||
532 |
*/ |
||
533 |
char * |
||
534 |
netname4(in_addr_t in, in_addr_t mask) |
||
535 |
{ |
||
536 |
int mbits; |
||
537 |
|||
538 |
340 |
in = ntohl(in); |
|
539 |
170 |
mask = ntohl(mask); |
|
540 |
✓✓ | 470 |
mbits = mask ? 33 - ffs(mask) : 0; |
541 |
✓✓ | 170 |
if (in == INADDR_ANY && mask == INADDR_ANY) |
542 |
40 |
strlcpy(line, "default", sizeof(line)); |
|
543 |
#define C(x) ((x) & 0xff) |
||
544 |
✓✓ | 130 |
else if (mbits < 9) |
545 |
56 |
snprintf(line, sizeof(line), "%u/%d", C(in >> 24), mbits); |
|
546 |
✗✓ | 74 |
else if (mbits < 17) |
547 |
snprintf(line, sizeof(line), "%u.%u/%d", |
||
548 |
C(in >> 24) , C(in >> 16), mbits); |
||
549 |
✓✗ | 74 |
else if (mbits < 25) |
550 |
74 |
snprintf(line, sizeof(line), "%u.%u.%u/%d", |
|
551 |
C(in >> 24), C(in >> 16), C(in >> 8), mbits); |
||
552 |
else |
||
553 |
snprintf(line, sizeof(line), "%u.%u.%u.%u/%d", C(in >> 24), |
||
554 |
C(in >> 16), C(in >> 8), C(in), mbits); |
||
555 |
#undef C |
||
556 |
170 |
return (line); |
|
557 |
} |
||
558 |
|||
559 |
char * |
||
560 |
netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask) |
||
561 |
{ |
||
562 |
2080 |
struct sockaddr_in6 sin6; |
|
563 |
u_char *p; |
||
564 |
int masklen, final = 0, illegal = 0; |
||
565 |
int i, lim, flag, error; |
||
566 |
1040 |
char hbuf[NI_MAXHOST]; |
|
567 |
|||
568 |
1040 |
sin6 = *sa6; |
|
569 |
|||
570 |
flag = 0; |
||
571 |
masklen = 0; |
||
572 |
✓✗ | 1040 |
if (mask) { |
573 |
1040 |
lim = mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr); |
|
574 |
1040 |
lim = lim < (int)sizeof(struct in6_addr) ? |
|
575 |
lim : (int)sizeof(struct in6_addr); |
||
576 |
✓✓ | 35360 |
for (p = (u_char *)&mask->sin6_addr, i = 0; i < lim; p++) { |
577 |
✓✓✗✓ |
25872 |
if (final && *p) { |
578 |
illegal++; |
||
579 |
sin6.sin6_addr.s6_addr[i++] = 0x00; |
||
580 |
continue; |
||
581 |
} |
||
582 |
|||
583 |
✓✗✗✗ ✓✗✓✗ ✓✗ |
16640 |
switch (*p & 0xff) { |
584 |
case 0xff: |
||
585 |
6368 |
masklen += 8; |
|
586 |
6368 |
break; |
|
587 |
case 0xfe: |
||
588 |
masklen += 7; |
||
589 |
final++; |
||
590 |
break; |
||
591 |
case 0xfc: |
||
592 |
masklen += 6; |
||
593 |
final++; |
||
594 |
break; |
||
595 |
case 0xf8: |
||
596 |
masklen += 5; |
||
597 |
final++; |
||
598 |
break; |
||
599 |
case 0xf0: |
||
600 |
112 |
masklen += 4; |
|
601 |
112 |
final++; |
|
602 |
112 |
break; |
|
603 |
case 0xe0: |
||
604 |
masklen += 3; |
||
605 |
final++; |
||
606 |
break; |
||
607 |
case 0xc0: |
||
608 |
112 |
masklen += 2; |
|
609 |
112 |
final++; |
|
610 |
112 |
break; |
|
611 |
case 0x80: |
||
612 |
masklen += 1; |
||
613 |
final++; |
||
614 |
break; |
||
615 |
case 0x00: |
||
616 |
10048 |
final++; |
|
617 |
10048 |
break; |
|
618 |
default: |
||
619 |
final++; |
||
620 |
illegal++; |
||
621 |
break; |
||
622 |
} |
||
623 |
|||
624 |
✓✗ | 16640 |
if (!illegal) |
625 |
16640 |
sin6.sin6_addr.s6_addr[i++] &= *p; |
|
626 |
else |
||
627 |
sin6.sin6_addr.s6_addr[i++] = 0x00; |
||
628 |
} |
||
629 |
✗✓ | 2080 |
while (i < (int)sizeof(struct in6_addr)) |
630 |
sin6.sin6_addr.s6_addr[i++] = 0x00; |
||
631 |
} else |
||
632 |
masklen = 128; |
||
633 |
|||
634 |
✗✓✗✗ ✗✗✗✗ ✗✗ |
1040 |
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) |
635 |
return ("default"); |
||
636 |
|||
637 |
✗✓ | 1040 |
if (illegal) |
638 |
warnx("illegal prefixlen"); |
||
639 |
|||
640 |
✓✗ | 1040 |
if (nflag) |
641 |
1040 |
flag |= NI_NUMERICHOST; |
|
642 |
2080 |
error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), |
|
643 |
1040 |
hbuf, sizeof(hbuf), NULL, 0, flag); |
|
644 |
✗✓ | 1040 |
if (error) |
645 |
snprintf(hbuf, sizeof(hbuf), "invalid"); |
||
646 |
|||
647 |
1040 |
snprintf(line, sizeof(line), "%s/%d", hbuf, masklen); |
|
648 |
1040 |
return (line); |
|
649 |
1040 |
} |
|
650 |
|||
651 |
/* |
||
652 |
* Return the name of the network whose address is given. |
||
653 |
* The address is assumed to be that of a net or subnet, not a host. |
||
654 |
*/ |
||
655 |
char * |
||
656 |
netname(struct sockaddr *sa, struct sockaddr *mask) |
||
657 |
{ |
||
658 |
✓✓✗✗ ✗ |
2420 |
switch (sa->sa_family) { |
659 |
case AF_INET: |
||
660 |
340 |
return netname4(((struct sockaddr_in *)sa)->sin_addr.s_addr, |
|
661 |
✓✗ | 510 |
mask->sa_len == 0 ? 0 : |
662 |
170 |
((struct sockaddr_in *)mask)->sin_addr.s_addr); |
|
663 |
case AF_INET6: |
||
664 |
2080 |
return netname6((struct sockaddr_in6 *)sa, |
|
665 |
1040 |
(struct sockaddr_in6 *)mask); |
|
666 |
case AF_LINK: |
||
667 |
return (link_print(sa)); |
||
668 |
case AF_MPLS: |
||
669 |
return (label_print(sa)); |
||
670 |
default: |
||
671 |
snprintf(line, sizeof(line), "af %d: %s", |
||
672 |
sa->sa_family, any_ntoa(sa)); |
||
673 |
break; |
||
674 |
} |
||
675 |
return (line); |
||
676 |
1210 |
} |
|
677 |
|||
678 |
static const char hexlist[] = "0123456789abcdef"; |
||
679 |
|||
680 |
char * |
||
681 |
any_ntoa(const struct sockaddr *sa) |
||
682 |
{ |
||
683 |
static char obuf[240]; |
||
684 |
const char *in = sa->sa_data; |
||
685 |
char *out = obuf; |
||
686 |
int len = sa->sa_len - offsetof(struct sockaddr, sa_data); |
||
687 |
|||
688 |
*out++ = 'Q'; |
||
689 |
do { |
||
690 |
*out++ = hexlist[(*in >> 4) & 15]; |
||
691 |
*out++ = hexlist[(*in++) & 15]; |
||
692 |
*out++ = '.'; |
||
693 |
} while (--len > 0 && (out + 3) < &obuf[sizeof(obuf) - 1]); |
||
694 |
out[-1] = '\0'; |
||
695 |
return (obuf); |
||
696 |
} |
||
697 |
|||
698 |
char * |
||
699 |
link_print(struct sockaddr *sa) |
||
700 |
{ |
||
701 |
384 |
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; |
|
702 |
192 |
u_char *lla = (u_char *)sdl->sdl_data + sdl->sdl_nlen; |
|
703 |
|||
704 |
✓✓✗✓ ✗✗ |
262 |
if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && |
705 |
sdl->sdl_slen == 0) { |
||
706 |
(void)snprintf(line, sizeof(line), "link#%d", sdl->sdl_index); |
||
707 |
return (line); |
||
708 |
} |
||
709 |
✗✓✗ | 192 |
switch (sdl->sdl_type) { |
710 |
case IFT_ETHER: |
||
711 |
case IFT_CARP: |
||
712 |
192 |
return (ether_ntoa((struct ether_addr *)lla)); |
|
713 |
default: |
||
714 |
return (link_ntoa(sdl)); |
||
715 |
} |
||
716 |
192 |
} |
|
717 |
|||
718 |
char * |
||
719 |
mpls_op(u_int32_t type) |
||
720 |
{ |
||
721 |
switch (type & (MPLS_OP_PUSH | MPLS_OP_POP | MPLS_OP_SWAP)) { |
||
722 |
case MPLS_OP_LOCAL: |
||
723 |
return ("LOCAL"); |
||
724 |
case MPLS_OP_POP: |
||
725 |
return ("POP"); |
||
726 |
case MPLS_OP_SWAP: |
||
727 |
return ("SWAP"); |
||
728 |
case MPLS_OP_PUSH: |
||
729 |
return ("PUSH"); |
||
730 |
default: |
||
731 |
return ("?"); |
||
732 |
} |
||
733 |
} |
||
734 |
|||
735 |
char * |
||
736 |
label_print(struct sockaddr *sa) |
||
737 |
{ |
||
738 |
struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)sa; |
||
739 |
|||
740 |
if (smpls) |
||
741 |
(void)snprintf(line, sizeof(line), "%u", |
||
742 |
ntohl(smpls->smpls_label) >> MPLS_LABEL_OFFSET); |
||
743 |
else |
||
744 |
(void)snprintf(line, sizeof(line), "-"); |
||
745 |
|||
746 |
return (line); |
||
747 |
} |
Generated by: GCOVR (Version 3.3) |