File: | src/sbin/route/show.c |
Warning: | line 162, column 37 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: show.c,v 1.119 2021/01/30 22:00:06 danj 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 <net/rtable.h> | |||
41 | #include <netinet/in.h> | |||
42 | #include <netinet/if_ether.h> | |||
43 | #include <netmpls/mpls.h> | |||
44 | #include <arpa/inet.h> | |||
45 | ||||
46 | #include <err.h> | |||
47 | #include <errno(*__errno()).h> | |||
48 | #include <netdb.h> | |||
49 | #include <stdio.h> | |||
50 | #include <stddef.h> | |||
51 | #include <stdlib.h> | |||
52 | #include <string.h> | |||
53 | #include <unistd.h> | |||
54 | #include <limits.h> | |||
55 | ||||
56 | #include "show.h" | |||
57 | ||||
58 | char *any_ntoa(const struct sockaddr *); | |||
59 | char *link_print(struct sockaddr *); | |||
60 | char *label_print(struct sockaddr *); | |||
61 | ||||
62 | #define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof (long)) \ | |||
63 | ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) | |||
64 | #define ADVANCE(x, n)(x += (((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1) | (sizeof(long) - 1))) : sizeof(long))) (x += ROUNDUP((n)->sa_len)(((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1) | (sizeof (long) - 1))) : sizeof(long))) | |||
65 | ||||
66 | /* | |||
67 | * Definitions for showing gateway flags. | |||
68 | */ | |||
69 | struct bits { | |||
70 | int b_mask; | |||
71 | char b_val; | |||
72 | }; | |||
73 | static const struct bits bits[] = { | |||
74 | { RTF_UP0x1, 'U' }, | |||
75 | { RTF_GATEWAY0x2, 'G' }, | |||
76 | { RTF_HOST0x4, 'H' }, | |||
77 | { RTF_REJECT0x8, 'R' }, | |||
78 | { RTF_DYNAMIC0x10, 'D' }, | |||
79 | { RTF_MODIFIED0x20, 'M' }, | |||
80 | { RTF_DONE0x40, 'd' }, /* Completed -- for routing messages only */ | |||
81 | { RTF_CLONING0x100, 'C' }, | |||
82 | { RTF_MULTICAST0x200,'m' }, | |||
83 | { RTF_LLINFO0x400, 'L' }, | |||
84 | { RTF_STATIC0x800, 'S' }, | |||
85 | { RTF_BLACKHOLE0x1000,'B' }, | |||
86 | { RTF_PROTO30x2000, '3' }, | |||
87 | { RTF_PROTO20x4000, '2' }, | |||
88 | { RTF_PROTO10x8000, '1' }, | |||
89 | { RTF_CLONED0x10000, 'c' }, | |||
90 | { RTF_CACHED0x20000, 'h' }, | |||
91 | { RTF_MPATH0x40000, 'P' }, | |||
92 | { RTF_MPLS0x100000, 'T' }, | |||
93 | { RTF_LOCAL0x200000, 'l' }, | |||
94 | { RTF_BFD0x1000000, 'F' }, | |||
95 | { RTF_BROADCAST0x400000,'b' }, | |||
96 | { RTF_CONNECTED0x800000,'n' }, | |||
97 | { 0 } | |||
98 | }; | |||
99 | ||||
100 | int WID_DST(int); | |||
101 | void pr_rthdr(int); | |||
102 | void p_rtentry(struct rt_msghdr *); | |||
103 | void pr_family(int); | |||
104 | void p_sockaddr_mpls(struct sockaddr *, struct sockaddr *, int, int); | |||
105 | void p_flags(int, char *); | |||
106 | char *routename4(in_addr_t); | |||
107 | char *routename6(struct sockaddr_in6 *); | |||
108 | char *netname4(in_addr_t, struct sockaddr_in *); | |||
109 | char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); | |||
110 | ||||
111 | size_t | |||
112 | get_sysctl(const int *mib, u_int mcnt, char **buf) | |||
113 | { | |||
114 | size_t needed; | |||
115 | ||||
116 | while (1) { | |||
117 | if (sysctl(mib, mcnt, NULL((void*)0), &needed, NULL((void*)0), 0) == -1) | |||
118 | err(1, "sysctl-estimate"); | |||
119 | if (needed == 0) | |||
120 | break; | |||
121 | if ((*buf = realloc(*buf, needed)) == NULL((void*)0)) | |||
122 | err(1, NULL((void*)0)); | |||
123 | if (sysctl(mib, mcnt, *buf, &needed, NULL((void*)0), 0) == -1) { | |||
124 | if (errno(*__errno()) == ENOMEM12) | |||
125 | continue; | |||
126 | err(1, "sysctl"); | |||
127 | } | |||
128 | break; | |||
129 | } | |||
130 | ||||
131 | return needed; | |||
132 | } | |||
133 | ||||
134 | /* | |||
135 | * Print preferred source address | |||
136 | */ | |||
137 | void | |||
138 | printsource(int af, u_int tableid) | |||
139 | { | |||
140 | struct sockaddr *sa; | |||
141 | char *buf = NULL((void*)0), *next, *lim = NULL((void*)0); | |||
142 | size_t needed; | |||
143 | int mib[7], mcnt, size; | |||
| ||||
144 | ||||
145 | mib[0] = CTL_NET4; | |||
146 | mib[1] = PF_ROUTE17; | |||
147 | mib[2] = 0; | |||
148 | mib[3] = af; | |||
149 | mib[4] = NET_RT_SOURCE7; | |||
150 | mib[5] = tableid; | |||
151 | mcnt = 6; | |||
152 | ||||
153 | needed = get_sysctl(mib, mcnt, &buf); | |||
154 | lim = buf + needed; | |||
155 | ||||
156 | if (pledge("stdio", NULL((void*)0)) == -1) | |||
157 | err(1, "pledge"); | |||
158 | ||||
159 | printf("Preferred source address set for rdomain %d\n", tableid); | |||
160 | ||||
161 | if (buf) { | |||
162 | for (next = buf; next < lim; next += size) { | |||
| ||||
163 | sa = (struct sockaddr *)next; | |||
164 | switch (sa->sa_family) { | |||
165 | case AF_INET2: | |||
166 | size = sizeof(struct sockaddr_in); | |||
167 | printf("IPv4: "); | |||
168 | break; | |||
169 | case AF_INET624: | |||
170 | size = sizeof(struct sockaddr_in6); | |||
171 | printf("IPv6: "); | |||
172 | break; | |||
173 | } | |||
174 | p_sockaddr(sa, NULL((void*)0), RTF_HOST0x4, WID_DST(sa->sa_family)); | |||
175 | printf("\n"); | |||
176 | } | |||
177 | } | |||
178 | free(buf); | |||
179 | ||||
180 | exit(0); | |||
181 | } | |||
182 | /* | |||
183 | * Print routing tables. | |||
184 | */ | |||
185 | void | |||
186 | p_rttables(int af, u_int tableid, char prio) | |||
187 | { | |||
188 | struct rt_msghdr *rtm; | |||
189 | char *buf = NULL((void*)0), *next, *lim = NULL((void*)0); | |||
190 | size_t needed; | |||
191 | int mib[7], mcnt; | |||
192 | ||||
193 | mib[0] = CTL_NET4; | |||
194 | mib[1] = PF_ROUTE17; | |||
195 | mib[2] = 0; | |||
196 | mib[3] = af; | |||
197 | mib[4] = NET_RT_DUMP1; | |||
198 | mib[5] = prio; | |||
199 | mib[6] = tableid; | |||
200 | mcnt = 7; | |||
201 | ||||
202 | needed = get_sysctl(mib, mcnt, &buf); | |||
203 | lim = buf + needed; | |||
204 | ||||
205 | if (pledge("stdio dns", NULL((void*)0)) == -1) | |||
206 | err(1, "pledge"); | |||
207 | ||||
208 | printf("Routing tables\n"); | |||
209 | ||||
210 | if (buf) { | |||
211 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |||
212 | rtm = (struct rt_msghdr *)next; | |||
213 | if (rtm->rtm_version != RTM_VERSION5) | |||
214 | continue; | |||
215 | p_rtentry(rtm); | |||
216 | } | |||
217 | } | |||
218 | free(buf); | |||
219 | } | |||
220 | ||||
221 | /* | |||
222 | * column widths; each followed by one space | |||
223 | * width of destination/gateway column | |||
224 | * strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 | |||
225 | */ | |||
226 | #define WID_GW(af)((af) == 24 ? 30 : 18) ((af) == AF_INET624 ? 30 : 18) | |||
227 | ||||
228 | int | |||
229 | WID_DST(int af) | |||
230 | { | |||
231 | ||||
232 | switch (af) { | |||
233 | case AF_MPLS33: | |||
234 | return 9; | |||
235 | case AF_INET624: | |||
236 | return 34; | |||
237 | default: | |||
238 | return 18; | |||
239 | } | |||
240 | } | |||
241 | ||||
242 | /* | |||
243 | * Print header for routing table columns. | |||
244 | */ | |||
245 | void | |||
246 | pr_rthdr(int af) | |||
247 | { | |||
248 | switch (af) { | |||
249 | case PF_KEY30: | |||
250 | printf("%-18s %-5s %-18s %-5s %-5s %-22s\n", | |||
251 | "Source", "Port", "Destination", | |||
252 | "Port", "Proto", "SA(Address/Proto/Type/Direction)"); | |||
253 | break; | |||
254 | case PF_MPLS33: | |||
255 | printf("%-9s %-9s %-6s %-18s %-6.6s %5.5s %8.8s %5.5s %4.4s %s\n", | |||
256 | "In label", "Out label", "Op", "Gateway", | |||
257 | "Flags", "Refs", "Use", "Mtu", "Prio", "Interface"); | |||
258 | break; | |||
259 | default: | |||
260 | printf("%-*.*s %-*.*s %-6.6s %5.5s %8.8s %5.5s %4.4s %s", | |||
261 | WID_DST(af), WID_DST(af), "Destination", | |||
262 | WID_GW(af)((af) == 24 ? 30 : 18), WID_GW(af)((af) == 24 ? 30 : 18), "Gateway", | |||
263 | "Flags", "Refs", "Use", "Mtu", "Prio", "Iface"); | |||
264 | if (verbose) | |||
265 | printf(" %s", "Label"); | |||
266 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
267 | break; | |||
268 | } | |||
269 | } | |||
270 | ||||
271 | void | |||
272 | get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) | |||
273 | { | |||
274 | int i; | |||
275 | ||||
276 | for (i = 0; i < RTAX_MAX15; i++) { | |||
277 | if (addrs & (1 << i)) { | |||
278 | rti_info[i] = sa; | |||
279 | sa = (struct sockaddr *)((char *)(sa) + | |||
280 | ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof (long) - 1))) : sizeof(long))); | |||
281 | } else | |||
282 | rti_info[i] = NULL((void*)0); | |||
283 | } | |||
284 | } | |||
285 | ||||
286 | /* | |||
287 | * Print a routing table entry. | |||
288 | */ | |||
289 | void | |||
290 | p_rtentry(struct rt_msghdr *rtm) | |||
291 | { | |||
292 | static int old_af = -1; | |||
293 | struct sockaddr *sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen); | |||
294 | struct sockaddr *mask, *rti_info[RTAX_MAX15]; | |||
295 | char ifbuf[IF_NAMESIZE16]; | |||
296 | char *label; | |||
297 | ||||
298 | if (sa->sa_family == AF_KEY30) | |||
299 | return; | |||
300 | ||||
301 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | |||
302 | ||||
303 | if (Fflag && rti_info[RTAX_GATEWAY1]->sa_family != sa->sa_family) { | |||
304 | return; | |||
305 | } | |||
306 | ||||
307 | if (strlen(so_label.rtlabel.sr_label)) { | |||
308 | if (!rti_info[RTAX_LABEL10]) | |||
309 | return; | |||
310 | label = ((struct sockaddr_rtlabel *)rti_info[RTAX_LABEL10])-> | |||
311 | sr_label; | |||
312 | if (strcmp(label, so_label.rtlabel.sr_label)) | |||
313 | return; | |||
314 | } | |||
315 | ||||
316 | if (old_af != sa->sa_family) { | |||
317 | old_af = sa->sa_family; | |||
318 | pr_family(sa->sa_family); | |||
319 | pr_rthdr(sa->sa_family); | |||
320 | } | |||
321 | ||||
322 | mask = rti_info[RTAX_NETMASK2]; | |||
323 | if ((sa = rti_info[RTAX_DST0]) == NULL((void*)0)) | |||
324 | return; | |||
325 | ||||
326 | p_sockaddr(sa, mask, rtm->rtm_flags, WID_DST(sa->sa_family)); | |||
327 | p_sockaddr_mpls(sa, rti_info[RTAX_SRC8], rtm->rtm_mpls, | |||
328 | WID_DST(sa->sa_family)); | |||
329 | ||||
330 | p_sockaddr(rti_info[RTAX_GATEWAY1], NULL((void*)0), RTF_HOST0x4, | |||
331 | WID_GW(sa->sa_family)((sa->sa_family) == 24 ? 30 : 18)); | |||
332 | ||||
333 | p_flags(rtm->rtm_flags, "%-6.6s "); | |||
334 | printf("%5u %8llu ", rtm->rtm_rmx.rmx_refcnt, | |||
335 | rtm->rtm_rmx.rmx_pksent); | |||
336 | if (rtm->rtm_rmx.rmx_mtu) | |||
337 | printf("%5u ", rtm->rtm_rmx.rmx_mtu); | |||
338 | else | |||
339 | printf("%5s ", "-"); | |||
340 | putchar((rtm->rtm_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ')(!__isthreaded ? __sputc((rtm->rtm_rmx.rmx_locks & 0x1 ) ? 'L' : ' ', (&__sF[1])) : (putc)((rtm->rtm_rmx.rmx_locks & 0x1) ? 'L' : ' ', (&__sF[1]))); | |||
341 | printf(" %2d %-5.16s", rtm->rtm_priority, | |||
342 | if_indextoname(rtm->rtm_index, ifbuf)); | |||
343 | if (verbose && rti_info[RTAX_LABEL10]) | |||
344 | printf(" %s", routename(rti_info[RTAX_LABEL10])); | |||
345 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
346 | } | |||
347 | ||||
348 | /* | |||
349 | * Print address family header before a section of the routing table. | |||
350 | */ | |||
351 | void | |||
352 | pr_family(int af) | |||
353 | { | |||
354 | char *afname; | |||
355 | ||||
356 | switch (af) { | |||
357 | case AF_INET2: | |||
358 | afname = "Internet"; | |||
359 | break; | |||
360 | case AF_INET624: | |||
361 | afname = "Internet6"; | |||
362 | break; | |||
363 | case PF_KEY30: | |||
364 | afname = "Encap"; | |||
365 | break; | |||
366 | case AF_MPLS33: | |||
367 | afname = "MPLS"; | |||
368 | break; | |||
369 | default: | |||
370 | afname = NULL((void*)0); | |||
371 | break; | |||
372 | } | |||
373 | if (afname) | |||
374 | printf("\n%s:\n", afname); | |||
375 | else | |||
376 | printf("\nProtocol Family %d:\n", af); | |||
377 | } | |||
378 | ||||
379 | void | |||
380 | p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) | |||
381 | { | |||
382 | char *cp; | |||
383 | ||||
384 | switch (sa->sa_family) { | |||
385 | case AF_INET624: | |||
386 | { | |||
387 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; | |||
388 | #ifdef __KAME__ | |||
389 | struct in6_addr *in6 = &sa6->sin6_addr; | |||
390 | ||||
391 | /* | |||
392 | * XXX: This is a special workaround for KAME kernels. | |||
393 | * sin6_scope_id field of SA should be set in the future. | |||
394 | */ | |||
395 | if ((IN6_IS_ADDR_LINKLOCAL(in6)(((in6)->__u6_addr.__u6_addr8[0] == 0xfe) && (((in6 )->__u6_addr.__u6_addr8[1] & 0xc0) == 0x80)) || | |||
396 | IN6_IS_ADDR_MC_LINKLOCAL(in6)(((in6)->__u6_addr.__u6_addr8[0] == 0xff) && (((in6 )->__u6_addr.__u6_addr8[1] & 0x0f) == 0x02)) || | |||
397 | IN6_IS_ADDR_MC_INTFACELOCAL(in6)(((in6)->__u6_addr.__u6_addr8[0] == 0xff) && (((in6 )->__u6_addr.__u6_addr8[1] & 0x0f) == 0x01))) && | |||
398 | sa6->sin6_scope_id == 0) { | |||
399 | /* XXX: override is ok? */ | |||
400 | sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)(__uint16_t)(__builtin_constant_p(*(u_short *) &in6->__u6_addr .__u6_addr8[2]) ? (__uint16_t)(((__uint16_t)(*(u_short *) & in6->__u6_addr.__u6_addr8[2]) & 0xffU) << 8 | (( __uint16_t)(*(u_short *) &in6->__u6_addr.__u6_addr8[2] ) & 0xff00U) >> 8) : __swap16md(*(u_short *) &in6 ->__u6_addr.__u6_addr8[2])) | |||
401 | &in6->s6_addr[2])(__uint16_t)(__builtin_constant_p(*(u_short *) &in6->__u6_addr .__u6_addr8[2]) ? (__uint16_t)(((__uint16_t)(*(u_short *) & in6->__u6_addr.__u6_addr8[2]) & 0xffU) << 8 | (( __uint16_t)(*(u_short *) &in6->__u6_addr.__u6_addr8[2] ) & 0xff00U) >> 8) : __swap16md(*(u_short *) &in6 ->__u6_addr.__u6_addr8[2])); | |||
402 | *(u_short *)&in6->s6_addr__u6_addr.__u6_addr8[2] = 0; | |||
403 | } | |||
404 | #endif | |||
405 | if (flags & RTF_HOST0x4) | |||
406 | cp = routename((struct sockaddr *)sa6); | |||
407 | else | |||
408 | cp = netname((struct sockaddr *)sa6, mask); | |||
409 | break; | |||
410 | } | |||
411 | case AF_MPLS33: | |||
412 | return; | |||
413 | default: | |||
414 | if ((flags & RTF_HOST0x4) || mask == NULL((void*)0)) | |||
415 | cp = routename(sa); | |||
416 | else | |||
417 | cp = netname(sa, mask); | |||
418 | break; | |||
419 | } | |||
420 | if (width < 0) | |||
421 | printf("%s", cp); | |||
422 | else { | |||
423 | if (nflag) | |||
424 | printf("%-*s ", width, cp); | |||
425 | else | |||
426 | printf("%-*.*s ", width, width, cp); | |||
427 | } | |||
428 | } | |||
429 | ||||
430 | static char line[HOST_NAME_MAX255+1]; | |||
431 | static char domain[HOST_NAME_MAX255+1]; | |||
432 | ||||
433 | void | |||
434 | p_sockaddr_mpls(struct sockaddr *in, struct sockaddr *out, int flags, int width) | |||
435 | { | |||
436 | if (in->sa_family != AF_MPLS33) | |||
437 | return; | |||
438 | ||||
439 | if (flags & MPLS_OP_POP0x1 || flags == MPLS_OP_LOCAL0x0) { | |||
440 | printf("%-*s ", width, label_print(in)); | |||
441 | printf("%-*s ", width, label_print(NULL((void*)0))); | |||
442 | } else { | |||
443 | printf("%-*s ", width, label_print(in)); | |||
444 | printf("%-*s ", width, label_print(out)); | |||
445 | } | |||
446 | ||||
447 | printf("%-6s ", mpls_op(flags)); | |||
448 | } | |||
449 | ||||
450 | void | |||
451 | p_flags(int f, char *format) | |||
452 | { | |||
453 | char name[33], *flags; | |||
454 | const struct bits *p = bits; | |||
455 | ||||
456 | for (flags = name; p->b_mask && flags < &name[sizeof(name) - 2]; p++) | |||
457 | if (p->b_mask & f) | |||
458 | *flags++ = p->b_val; | |||
459 | *flags = '\0'; | |||
460 | printf(format, name); | |||
461 | } | |||
462 | ||||
463 | char * | |||
464 | routename(struct sockaddr *sa) | |||
465 | { | |||
466 | char *cp = NULL((void*)0); | |||
467 | static int first = 1; | |||
468 | ||||
469 | if (first) { | |||
470 | first = 0; | |||
471 | if (gethostname(domain, sizeof(domain)) == 0 && | |||
472 | (cp = strchr(domain, '.'))) | |||
473 | (void)strlcpy(domain, cp + 1, sizeof(domain)); | |||
474 | else | |||
475 | domain[0] = '\0'; | |||
476 | cp = NULL((void*)0); | |||
477 | } | |||
478 | ||||
479 | if (sa->sa_len == 0) { | |||
480 | (void)strlcpy(line, "default", sizeof(line)); | |||
481 | return (line); | |||
482 | } | |||
483 | ||||
484 | switch (sa->sa_family) { | |||
485 | case AF_INET2: | |||
486 | return | |||
487 | (routename4(((struct sockaddr_in *)sa)->sin_addr.s_addr)); | |||
488 | ||||
489 | case AF_INET624: | |||
490 | { | |||
491 | struct sockaddr_in6 sin6; | |||
492 | ||||
493 | memset(&sin6, 0, sizeof(sin6)); | |||
494 | memcpy(&sin6, sa, sa->sa_len); | |||
495 | sin6.sin6_len = sizeof(struct sockaddr_in6); | |||
496 | sin6.sin6_family = AF_INET624; | |||
497 | #ifdef __KAME__ | |||
498 | if (sa->sa_len == sizeof(struct sockaddr_in6) && | |||
499 | (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)(((&sin6.sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe) && (((&sin6.sin6_addr)->__u6_addr.__u6_addr8[1] & 0xc0 ) == 0x80)) || | |||
500 | IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)(((&sin6.sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff) && (((&sin6.sin6_addr)->__u6_addr.__u6_addr8[1] & 0x0f ) == 0x02)) || | |||
501 | IN6_IS_ADDR_MC_INTFACELOCAL(&sin6.sin6_addr)(((&sin6.sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff) && (((&sin6.sin6_addr)->__u6_addr.__u6_addr8[1] & 0x0f ) == 0x01))) && | |||
502 | sin6.sin6_scope_id == 0) { | |||
503 | sin6.sin6_scope_id = | |||
504 | ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2])(__uint16_t)(__builtin_constant_p(*(u_int16_t *)&sin6.sin6_addr .__u6_addr.__u6_addr8[2]) ? (__uint16_t)(((__uint16_t)(*(u_int16_t *)&sin6.sin6_addr.__u6_addr.__u6_addr8[2]) & 0xffU) << 8 | ((__uint16_t)(*(u_int16_t *)&sin6.sin6_addr.__u6_addr .__u6_addr8[2]) & 0xff00U) >> 8) : __swap16md(*(u_int16_t *)&sin6.sin6_addr.__u6_addr.__u6_addr8[2])); | |||
505 | sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = 0; | |||
506 | sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[3] = 0; | |||
507 | } | |||
508 | #endif | |||
509 | return (routename6(&sin6)); | |||
510 | } | |||
511 | ||||
512 | case AF_LINK18: | |||
513 | return (link_print(sa)); | |||
514 | case AF_MPLS33: | |||
515 | return (label_print(sa)); | |||
516 | case AF_UNSPEC0: | |||
517 | if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) { | |||
518 | static char name[RTLABEL_LEN32 + 2]; | |||
519 | struct sockaddr_rtlabel *sr; | |||
520 | ||||
521 | sr = (struct sockaddr_rtlabel *)sa; | |||
522 | snprintf(name, sizeof(name), "\"%s\"", sr->sr_label); | |||
523 | return (name); | |||
524 | } | |||
525 | /* FALLTHROUGH */ | |||
526 | default: | |||
527 | (void)snprintf(line, sizeof(line), "(%d) %s", | |||
528 | sa->sa_family, any_ntoa(sa)); | |||
529 | break; | |||
530 | } | |||
531 | return (line); | |||
532 | } | |||
533 | ||||
534 | char * | |||
535 | routename4(in_addr_t in) | |||
536 | { | |||
537 | char *cp = NULL((void*)0); | |||
538 | struct in_addr ina; | |||
539 | struct hostent *hp; | |||
540 | ||||
541 | if (!cp && !nflag) { | |||
542 | if ((hp = gethostbyaddr((char *)&in, | |||
543 | sizeof(in), AF_INET2)) != NULL((void*)0)) { | |||
544 | if ((cp = strchr(hp->h_name, '.')) && | |||
545 | !strcmp(cp + 1, domain)) | |||
546 | *cp = '\0'; | |||
547 | cp = hp->h_name; | |||
548 | } | |||
549 | } | |||
550 | ina.s_addr = in; | |||
551 | strlcpy(line, cp ? cp : inet_ntoa(ina), sizeof(line)); | |||
552 | ||||
553 | return (line); | |||
554 | } | |||
555 | ||||
556 | char * | |||
557 | routename6(struct sockaddr_in6 *sin6) | |||
558 | { | |||
559 | int niflags = 0; | |||
560 | ||||
561 | if (nflag) | |||
562 | niflags |= NI_NUMERICHOST1; | |||
563 | else | |||
564 | niflags |= NI_NOFQDN4; | |||
565 | ||||
566 | if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, | |||
567 | line, sizeof(line), NULL((void*)0), 0, niflags) != 0) | |||
568 | strncpy(line, "invalid", sizeof(line)); | |||
569 | ||||
570 | return (line); | |||
571 | } | |||
572 | ||||
573 | char * | |||
574 | netname4(in_addr_t in, struct sockaddr_in *maskp) | |||
575 | { | |||
576 | char *cp = NULL((void*)0); | |||
577 | struct hostent *hp; | |||
578 | in_addr_t mask; | |||
579 | int mbits; | |||
580 | ||||
581 | mask = maskp && maskp->sin_len != 0 ? ntohl(maskp->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(maskp->sin_addr.s_addr) ? (__uint32_t)(((__uint32_t)(maskp->sin_addr.s_addr) & 0xff ) << 24 | ((__uint32_t)(maskp->sin_addr.s_addr) & 0xff00) << 8 | ((__uint32_t)(maskp->sin_addr.s_addr ) & 0xff0000) >> 8 | ((__uint32_t)(maskp->sin_addr .s_addr) & 0xff000000) >> 24) : __swap32md(maskp-> sin_addr.s_addr)) : 0; | |||
582 | if (!nflag && in != INADDR_ANY((u_int32_t)(0x00000000))) { | |||
583 | if ((hp = gethostbyaddr((char *)&in, | |||
584 | sizeof(in), AF_INET2)) != NULL((void*)0)) | |||
585 | cp = hp->h_name; | |||
586 | } | |||
587 | if (in == INADDR_ANY((u_int32_t)(0x00000000)) && mask == INADDR_ANY((u_int32_t)(0x00000000))) | |||
588 | cp = "default"; | |||
589 | mbits = mask ? 33 - ffs(mask) : 0; | |||
590 | in = ntohl(in)(__uint32_t)(__builtin_constant_p(in) ? (__uint32_t)(((__uint32_t )(in) & 0xff) << 24 | ((__uint32_t)(in) & 0xff00 ) << 8 | ((__uint32_t)(in) & 0xff0000) >> 8 | ((__uint32_t)(in) & 0xff000000) >> 24) : __swap32md (in)); | |||
591 | if (cp) | |||
592 | strlcpy(line, cp, sizeof(line)); | |||
593 | #define C(x) ((x) & 0xff) | |||
594 | else if (mbits < 9) | |||
595 | snprintf(line, sizeof(line), "%u/%d", C(in >> 24), mbits); | |||
596 | else if (mbits < 17) | |||
597 | snprintf(line, sizeof(line), "%u.%u/%d", | |||
598 | C(in >> 24) , C(in >> 16), mbits); | |||
599 | else if (mbits < 25) | |||
600 | snprintf(line, sizeof(line), "%u.%u.%u/%d", | |||
601 | C(in >> 24), C(in >> 16), C(in >> 8), mbits); | |||
602 | else | |||
603 | snprintf(line, sizeof(line), "%u.%u.%u.%u/%d", C(in >> 24), | |||
604 | C(in >> 16), C(in >> 8), C(in), mbits); | |||
605 | #undef C | |||
606 | return (line); | |||
607 | } | |||
608 | ||||
609 | char * | |||
610 | netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask) | |||
611 | { | |||
612 | struct sockaddr_in6 sin6; | |||
613 | u_char *p; | |||
614 | int masklen, final = 0, illegal = 0; | |||
615 | int i, lim, flag, error; | |||
616 | char hbuf[NI_MAXHOST256]; | |||
617 | ||||
618 | sin6 = *sa6; | |||
619 | ||||
620 | flag = 0; | |||
621 | masklen = 0; | |||
622 | if (mask) { | |||
623 | lim = mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr)__builtin_offsetof(struct sockaddr_in6, sin6_addr); | |||
624 | lim = lim < (int)sizeof(struct in6_addr) ? | |||
625 | lim : (int)sizeof(struct in6_addr); | |||
626 | for (p = (u_char *)&mask->sin6_addr, i = 0; i < lim; p++) { | |||
627 | if (final && *p) { | |||
628 | illegal++; | |||
629 | sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[i++] = 0x00; | |||
630 | continue; | |||
631 | } | |||
632 | ||||
633 | switch (*p & 0xff) { | |||
634 | case 0xff: | |||
635 | masklen += 8; | |||
636 | break; | |||
637 | case 0xfe: | |||
638 | masklen += 7; | |||
639 | final++; | |||
640 | break; | |||
641 | case 0xfc: | |||
642 | masklen += 6; | |||
643 | final++; | |||
644 | break; | |||
645 | case 0xf8: | |||
646 | masklen += 5; | |||
647 | final++; | |||
648 | break; | |||
649 | case 0xf0: | |||
650 | masklen += 4; | |||
651 | final++; | |||
652 | break; | |||
653 | case 0xe0: | |||
654 | masklen += 3; | |||
655 | final++; | |||
656 | break; | |||
657 | case 0xc0: | |||
658 | masklen += 2; | |||
659 | final++; | |||
660 | break; | |||
661 | case 0x80: | |||
662 | masklen += 1; | |||
663 | final++; | |||
664 | break; | |||
665 | case 0x00: | |||
666 | final++; | |||
667 | break; | |||
668 | default: | |||
669 | final++; | |||
670 | illegal++; | |||
671 | break; | |||
672 | } | |||
673 | ||||
674 | if (!illegal) | |||
675 | sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[i++] &= *p; | |||
676 | else | |||
677 | sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[i++] = 0x00; | |||
678 | } | |||
679 | while (i < (int)sizeof(struct in6_addr)) | |||
680 | sin6.sin6_addr.s6_addr__u6_addr.__u6_addr8[i++] = 0x00; | |||
681 | } else | |||
682 | masklen = 128; | |||
683 | ||||
684 | if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6.sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&sin6.sin6_addr)->__u6_addr.__u6_addr8 [4]) == 0) && (*(const u_int32_t *)(const void *)(& (&sin6.sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) && (*(const u_int32_t *)(const void *)(&(&sin6.sin6_addr )->__u6_addr.__u6_addr8[12]) == 0))) | |||
685 | return ("default"); | |||
686 | ||||
687 | if (illegal) | |||
688 | warnx("illegal prefixlen"); | |||
689 | ||||
690 | if (nflag) | |||
691 | flag |= NI_NUMERICHOST1; | |||
692 | error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, | |||
693 | hbuf, sizeof(hbuf), NULL((void*)0), 0, flag); | |||
694 | if (error) | |||
695 | snprintf(hbuf, sizeof(hbuf), "invalid"); | |||
696 | ||||
697 | snprintf(line, sizeof(line), "%s/%d", hbuf, masklen); | |||
698 | return (line); | |||
699 | } | |||
700 | ||||
701 | /* | |||
702 | * Return the name of the network whose address is given. | |||
703 | * The address is assumed to be that of a net or subnet, not a host. | |||
704 | */ | |||
705 | char * | |||
706 | netname(struct sockaddr *sa, struct sockaddr *mask) | |||
707 | { | |||
708 | switch (sa->sa_family) { | |||
709 | case AF_INET2: | |||
710 | return netname4(((struct sockaddr_in *)sa)->sin_addr.s_addr, | |||
711 | (struct sockaddr_in *)mask); | |||
712 | case AF_INET624: | |||
713 | return netname6((struct sockaddr_in6 *)sa, | |||
714 | (struct sockaddr_in6 *)mask); | |||
715 | case AF_LINK18: | |||
716 | return (link_print(sa)); | |||
717 | case AF_MPLS33: | |||
718 | return (label_print(sa)); | |||
719 | default: | |||
720 | snprintf(line, sizeof(line), "af %d: %s", | |||
721 | sa->sa_family, any_ntoa(sa)); | |||
722 | break; | |||
723 | } | |||
724 | return (line); | |||
725 | } | |||
726 | ||||
727 | static const char hexlist[] = "0123456789abcdef"; | |||
728 | ||||
729 | char * | |||
730 | any_ntoa(const struct sockaddr *sa) | |||
731 | { | |||
732 | static char obuf[240]; | |||
733 | const char *in = sa->sa_data; | |||
734 | char *out = obuf; | |||
735 | int len = sa->sa_len - offsetof(struct sockaddr, sa_data)__builtin_offsetof(struct sockaddr, sa_data); | |||
736 | ||||
737 | *out++ = 'Q'; | |||
738 | do { | |||
739 | *out++ = hexlist[(*in >> 4) & 15]; | |||
740 | *out++ = hexlist[(*in++) & 15]; | |||
741 | *out++ = '.'; | |||
742 | } while (--len > 0 && (out + 3) < &obuf[sizeof(obuf) - 1]); | |||
743 | out[-1] = '\0'; | |||
744 | return (obuf); | |||
745 | } | |||
746 | ||||
747 | char * | |||
748 | link_print(struct sockaddr *sa) | |||
749 | { | |||
750 | struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; | |||
751 | u_char *lla = (u_char *)sdl->sdl_data + sdl->sdl_nlen; | |||
752 | ||||
753 | if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && | |||
754 | sdl->sdl_slen == 0) { | |||
755 | (void)snprintf(line, sizeof(line), "link#%d", sdl->sdl_index); | |||
756 | return (line); | |||
757 | } | |||
758 | switch (sdl->sdl_type) { | |||
759 | case IFT_ETHER0x06: | |||
760 | case IFT_CARP0xf7: | |||
761 | return (ether_ntoa((struct ether_addr *)lla)); | |||
762 | default: | |||
763 | return (link_ntoa(sdl)); | |||
764 | } | |||
765 | } | |||
766 | ||||
767 | char * | |||
768 | mpls_op(u_int32_t type) | |||
769 | { | |||
770 | switch (type & (MPLS_OP_PUSH0x2 | MPLS_OP_POP0x1 | MPLS_OP_SWAP0x4)) { | |||
771 | case MPLS_OP_LOCAL0x0: | |||
772 | return ("LOCAL"); | |||
773 | case MPLS_OP_POP0x1: | |||
774 | return ("POP"); | |||
775 | case MPLS_OP_SWAP0x4: | |||
776 | return ("SWAP"); | |||
777 | case MPLS_OP_PUSH0x2: | |||
778 | return ("PUSH"); | |||
779 | default: | |||
780 | return ("?"); | |||
781 | } | |||
782 | } | |||
783 | ||||
784 | char * | |||
785 | label_print(struct sockaddr *sa) | |||
786 | { | |||
787 | struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)sa; | |||
788 | ||||
789 | if (smpls) | |||
790 | (void)snprintf(line, sizeof(line), "%u", | |||
791 | ntohl(smpls->smpls_label)(__uint32_t)(__builtin_constant_p(smpls->smpls_label) ? (__uint32_t )(((__uint32_t)(smpls->smpls_label) & 0xff) << 24 | ((__uint32_t)(smpls->smpls_label) & 0xff00) << 8 | ((__uint32_t)(smpls->smpls_label) & 0xff0000) >> 8 | ((__uint32_t)(smpls->smpls_label) & 0xff000000) >> 24) : __swap32md(smpls->smpls_label)) >> MPLS_LABEL_OFFSET12); | |||
792 | else | |||
793 | (void)snprintf(line, sizeof(line), "-"); | |||
794 | ||||
795 | return (line); | |||
796 | } |