Annotation of src/usr.bin/netstat/show.c, Revision 1.40
1.40 ! mikeb 1: /* $OpenBSD: show.c,v 1.39 2013/11/13 21:19:30 deraadt Exp $ */
1.1 claudio 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/param.h>
34: #include <sys/protosw.h>
35: #include <sys/socket.h>
36: #include <sys/sysctl.h>
37:
38: #include <net/if.h>
1.40 ! mikeb 39: #include <net/if_var.h>
1.1 claudio 40: #include <net/if_dl.h>
41: #include <net/if_types.h>
42: #include <net/pfkeyv2.h>
43: #include <net/route.h>
44: #include <netinet/in.h>
45: #include <netinet/if_ether.h>
46: #include <netinet/ip_ipsp.h>
1.13 claudio 47: #include <netmpls/mpls.h>
1.1 claudio 48: #include <arpa/inet.h>
49:
50: #include <err.h>
51: #include <errno.h>
52: #include <netdb.h>
53: #include <stdio.h>
54: #include <stddef.h>
55: #include <stdlib.h>
56: #include <string.h>
57: #include <unistd.h>
58:
59: #include "netstat.h"
60:
61: char *any_ntoa(const struct sockaddr *);
62: char *link_print(struct sockaddr *);
1.30 claudio 63: char *label_print(struct sockaddr *);
1.1 claudio 64:
65: #define ROUNDUP(a) \
66: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
67: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
68:
69: #define PFKEYV2_CHUNK sizeof(u_int64_t)
70:
71: /*
72: * Definitions for showing gateway flags.
73: */
74: struct bits {
75: int b_mask;
76: char b_val;
77: };
78: static const struct bits bits[] = {
79: { RTF_UP, 'U' },
80: { RTF_GATEWAY, 'G' },
81: { RTF_HOST, 'H' },
82: { RTF_REJECT, 'R' },
83: { RTF_BLACKHOLE, 'B' },
84: { RTF_DYNAMIC, 'D' },
85: { RTF_MODIFIED, 'M' },
86: { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
87: { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
88: { RTF_CLONING, 'C' },
89: { RTF_XRESOLVE, 'X' },
90: { RTF_LLINFO, 'L' },
91: { RTF_STATIC, 'S' },
92: { RTF_PROTO1, '1' },
93: { RTF_PROTO2, '2' },
94: { RTF_PROTO3, '3' },
95: { RTF_CLONED, 'c' },
1.18 claudio 96: { RTF_MPATH, 'P' },
1.25 michele 97: { RTF_MPLS, 'T' },
1.1 claudio 98: { 0 }
99: };
100:
101: void p_rtentry(struct rt_msghdr *);
102: void p_pfkentry(struct sadb_msg *);
103: void pr_family(int);
104: void p_encap(struct sockaddr *, struct sockaddr *, int);
105: void p_protocol(struct sadb_protocol *, struct sockaddr *, struct
1.13 claudio 106: sadb_protocol *, int);
1.1 claudio 107: void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
1.17 michele 108: void p_sockaddr_mpls(struct sockaddr *, struct sockaddr *, int, int);
1.1 claudio 109: void p_flags(int, char *);
110: char *routename4(in_addr_t);
111: char *routename6(struct sockaddr_in6 *);
112: void index_pfk(struct sadb_msg *, void **);
113:
114: /*
115: * Print routing tables.
116: */
117: void
1.35 mikeb 118: p_rttables(int af, u_int tableid)
1.1 claudio 119: {
120: struct rt_msghdr *rtm;
121: struct sadb_msg *msg;
122: char *buf = NULL, *next, *lim = NULL;
123: size_t needed;
1.34 claudio 124: int mib[7], mcnt;
1.1 claudio 125: struct sockaddr *sa;
126:
127: mib[0] = CTL_NET;
128: mib[1] = PF_ROUTE;
129: mib[2] = 0;
130: mib[3] = af;
131: mib[4] = NET_RT_DUMP;
132: mib[5] = 0;
1.35 mikeb 133: mib[6] = tableid;
134: mcnt = 7;
1.38 deraadt 135: while (1) {
136: if (sysctl(mib, mcnt, NULL, &needed, NULL, 0) == -1)
137: err(1, "route-sysctl-estimate");
138: if (needed == 0)
139: break;
140: if ((buf = realloc(buf, needed)) == NULL)
1.1 claudio 141: err(1, NULL);
1.38 deraadt 142: if (sysctl(mib, mcnt, buf, &needed, NULL, 0) == -1) {
143: if (errno == ENOMEM)
144: continue;
1.1 claudio 145: err(1, "sysctl of routing table");
1.38 deraadt 146: }
1.1 claudio 147: lim = buf + needed;
1.38 deraadt 148: break;
1.1 claudio 149: }
150:
151: printf("Routing tables\n");
152:
153: if (buf) {
154: for (next = buf; next < lim; next += rtm->rtm_msglen) {
155: rtm = (struct rt_msghdr *)next;
1.8 claudio 156: if (rtm->rtm_version != RTM_VERSION)
157: continue;
1.23 chris 158: sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
1.1 claudio 159: if (af != AF_UNSPEC && sa->sa_family != af)
160: continue;
161: p_rtentry(rtm);
162: }
163: free(buf);
164: buf = NULL;
165: }
166:
167: if (af != 0 && af != PF_KEY)
168: return;
169:
170: mib[0] = CTL_NET;
171: mib[1] = PF_KEY;
172: mib[2] = PF_KEY_V2;
173: mib[3] = NET_KEY_SPD_DUMP;
174: mib[4] = mib[5] = 0;
1.38 deraadt 175: while (1) {
176: if (sysctl(mib, 4, NULL, &needed, NULL, 0) == -1) {
177: if (errno == ENOPROTOOPT)
178: return;
179: err(1, "spd-sysctl-estimate");
180: }
181: if (needed == 0)
182: break;
183: if ((buf = realloc(buf, needed)) == NULL)
1.1 claudio 184: err(1, NULL);
1.38 deraadt 185: if (sysctl(mib, 4, buf, &needed, NULL, 0) == -1) {
186: if (errno == ENOMEM)
187: continue;
1.1 claudio 188: err(1,"sysctl of spd");
1.38 deraadt 189: }
1.1 claudio 190: lim = buf + needed;
1.38 deraadt 191: break;
1.1 claudio 192: }
193:
194: if (buf) {
195: printf("\nEncap:\n");
196:
197: for (next = buf; next < lim; next += msg->sadb_msg_len *
198: PFKEYV2_CHUNK) {
199: msg = (struct sadb_msg *)next;
200: if (msg->sadb_msg_len == 0)
201: break;
202: p_pfkentry(msg);
203: }
204: free(buf);
205: buf = NULL;
206: }
207: }
208:
1.12 deraadt 209: /*
1.1 claudio 210: * column widths; each followed by one space
211: * width of destination/gateway column
212: * strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4
213: */
214: #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18)
215:
1.39 deraadt 216: static int
1.13 claudio 217: WID_DST(int af)
218: {
219:
220: if (nflag)
221: switch (af) {
222: case AF_MPLS:
1.30 claudio 223: return 9;
1.13 claudio 224: case AF_INET6:
225: return 34;
226: default:
227: return 18;
228: }
229: else
230: switch (af) {
231: case AF_MPLS:
1.30 claudio 232: return 9;
1.13 claudio 233: default:
234: return 18;
235: }
236: }
237:
1.1 claudio 238: /*
239: * Print header for routing table columns.
240: */
241: void
242: pr_rthdr(int af, int Aflag)
243: {
244: if (Aflag)
245: printf("%-*.*s ", PLEN, PLEN, "Address");
1.13 claudio 246: switch (af) {
247: case PF_KEY:
1.1 claudio 248: printf("%-18s %-5s %-18s %-5s %-5s %-22s\n",
249: "Source", "Port", "Destination",
250: "Port", "Proto", "SA(Address/Proto/Type/Direction)");
1.13 claudio 251: break;
252: case PF_MPLS:
1.30 claudio 253: printf("%-9s %-9s %-6s %-18s %-6.6s %5.5s %8.8s %5.5s %4.4s %s\n",
1.13 claudio 254: "In label", "Out label", "Op", "Gateway",
255: "Flags", "Refs", "Use", "Mtu", "Prio", "Interface");
256: break;
257: default:
1.32 bluhm 258: printf("%-*.*s %-*.*s %-6.6s %5.5s %8.8s %5.5s %4.4s %s",
1.13 claudio 259: WID_DST(af), WID_DST(af), "Destination",
260: WID_GW(af), WID_GW(af), "Gateway",
261: "Flags", "Refs", "Use", "Mtu", "Prio", "Iface");
1.33 bluhm 262: if (vflag && !Aflag)
1.32 bluhm 263: printf(" %s", "Label");
264: putchar('\n');
1.13 claudio 265: break;
266: }
1.1 claudio 267: }
268:
269: static void
270: get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
271: {
272: int i;
273:
274: for (i = 0; i < RTAX_MAX; i++) {
275: if (addrs & (1 << i)) {
276: rti_info[i] = sa;
277: sa = (struct sockaddr *)((char *)(sa) +
278: ROUNDUP(sa->sa_len));
279: } else
280: rti_info[i] = NULL;
281: }
282: }
283:
284: /*
285: * Print a routing table entry.
286: */
287: void
288: p_rtentry(struct rt_msghdr *rtm)
289: {
290: static int old_af = -1;
1.22 chris 291: struct sockaddr *sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
1.1 claudio 292: struct sockaddr *mask, *rti_info[RTAX_MAX];
293: char ifbuf[IF_NAMESIZE];
294:
295: if (sa->sa_family == AF_KEY)
296: return;
297:
1.5 pyr 298: get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
299: if (Fflag && rti_info[RTAX_GATEWAY]->sa_family != sa->sa_family) {
300: return;
301: }
1.1 claudio 302: if (old_af != sa->sa_family) {
303: old_af = sa->sa_family;
304: pr_family(sa->sa_family);
305: pr_rthdr(sa->sa_family, 0);
306: }
307:
308: mask = rti_info[RTAX_NETMASK];
309: if ((sa = rti_info[RTAX_DST]) == NULL)
310: return;
311:
312: p_sockaddr(sa, mask, rtm->rtm_flags, WID_DST(sa->sa_family));
1.19 michele 313: p_sockaddr_mpls(sa, rti_info[RTAX_SRC], rtm->rtm_mpls,
1.17 michele 314: WID_DST(sa->sa_family));
315:
1.1 claudio 316: p_sockaddr(rti_info[RTAX_GATEWAY], NULL, RTF_HOST,
317: WID_GW(sa->sa_family));
1.30 claudio 318:
1.1 claudio 319: p_flags(rtm->rtm_flags, "%-6.6s ");
1.13 claudio 320: printf("%5u %8llu ", rtm->rtm_rmx.rmx_refcnt,
1.1 claudio 321: rtm->rtm_rmx.rmx_pksent);
322: if (rtm->rtm_rmx.rmx_mtu)
1.13 claudio 323: printf("%5u ", rtm->rtm_rmx.rmx_mtu);
1.1 claudio 324: else
1.13 claudio 325: printf("%5s ", "-");
1.1 claudio 326: putchar((rtm->rtm_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
1.32 bluhm 327: printf(" %2d %-5.16s", rtm->rtm_priority,
1.13 claudio 328: if_indextoname(rtm->rtm_index, ifbuf));
1.32 bluhm 329: if (vflag && rti_info[RTAX_LABEL])
330: printf(" %s", ((struct sockaddr_rtlabel *)
331: rti_info[RTAX_LABEL])->sr_label);
1.1 claudio 332: putchar('\n');
333: }
334:
335: /*
336: * Print a pfkey/encap entry.
337: */
338: void
339: p_pfkentry(struct sadb_msg *msg)
340: {
1.13 claudio 341: static int old = 0;
1.1 claudio 342: struct sadb_address *saddr;
343: struct sadb_protocol *sap, *saft;
344: struct sockaddr *sa, *mask;
345: void *headers[SADB_EXT_MAX + 1];
346:
347: if (!old) {
348: pr_rthdr(PF_KEY, 0);
349: old++;
350: }
351:
352: bzero(headers, sizeof(headers));
353: index_pfk(msg, headers);
354:
355: /* These are always set */
356: saddr = headers[SADB_X_EXT_SRC_FLOW];
357: sa = (struct sockaddr *)(saddr + 1);
358: saddr = headers[SADB_X_EXT_SRC_MASK];
359: mask = (struct sockaddr *)(saddr + 1);
360: p_encap(sa, mask, WID_DST(sa->sa_family));
361:
362: /* These are always set, too. */
363: saddr = headers[SADB_X_EXT_DST_FLOW];
364: sa = (struct sockaddr *)(saddr + 1);
365: saddr = headers[SADB_X_EXT_DST_MASK];
366: mask = (struct sockaddr *)(saddr + 1);
367: p_encap(sa, mask, WID_DST(sa->sa_family));
368:
369: /* Bypass and deny flows do not set SADB_EXT_ADDRESS_DST! */
370: sap = headers[SADB_X_EXT_PROTOCOL];
371: saft = headers[SADB_X_EXT_FLOW_TYPE];
372: saddr = headers[SADB_EXT_ADDRESS_DST];
373: if (saddr)
374: sa = (struct sockaddr *)(saddr + 1);
375: else
376: sa = NULL;
377: p_protocol(sap, sa, saft, msg->sadb_msg_satype);
378:
379: printf("\n");
380: }
381:
382: /*
383: * Print address family header before a section of the routing table.
384: */
385: void
386: pr_family(int af)
387: {
388: char *afname;
389:
390: switch (af) {
391: case AF_INET:
392: afname = "Internet";
393: break;
394: case AF_INET6:
395: afname = "Internet6";
396: break;
397: case PF_KEY:
398: afname = "Encap";
399: break;
1.13 claudio 400: case AF_MPLS:
401: afname = "MPLS";
402: break;
1.1 claudio 403: case AF_APPLETALK:
404: afname = "AppleTalk";
405: break;
406: default:
407: afname = NULL;
408: break;
409: }
410: if (afname)
411: printf("\n%s:\n", afname);
412: else
413: printf("\nProtocol Family %d:\n", af);
414: }
415:
416: void
417: p_addr(struct sockaddr *sa, struct sockaddr *mask, int flags)
418: {
419: p_sockaddr(sa, mask, flags, WID_DST(sa->sa_family));
420: }
421:
422: void
423: p_gwaddr(struct sockaddr *sa, int af)
424: {
425: p_sockaddr(sa, 0, RTF_HOST, WID_GW(af));
426: }
427:
428: void
429: p_encap(struct sockaddr *sa, struct sockaddr *mask, int width)
430: {
1.13 claudio 431: char *cp;
432: unsigned short port = 0;
1.1 claudio 433:
1.2 todd 434: if (mask)
435: cp = netname(sa, mask);
436: else
437: cp = routename(sa);
1.1 claudio 438: switch (sa->sa_family) {
1.9 claudio 439: case AF_INET:
440: port = ntohs(((struct sockaddr_in *)sa)->sin_port);
441: break;
1.2 todd 442: case AF_INET6:
443: port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
1.1 claudio 444: break;
445: }
446: if (width < 0)
447: printf("%s", cp);
448: else {
449: if (nflag)
450: printf("%-*s %-5u ", width, cp, port);
451: else
452: printf("%-*.*s %-5u ", width, width, cp, port);
453: }
454: }
455:
456: void
457: p_protocol(struct sadb_protocol *sap, struct sockaddr *sa, struct sadb_protocol
458: *saft, int proto)
459: {
460: printf("%-6u", sap->sadb_protocol_proto);
1.9 claudio 461:
1.1 claudio 462: if (sa)
463: p_sockaddr(sa, NULL, 0, -1);
464: else
465: printf("none");
466:
467: switch (proto) {
468: case SADB_SATYPE_ESP:
469: printf("/esp");
470: break;
471: case SADB_SATYPE_AH:
472: printf("/ah");
473: break;
474: case SADB_X_SATYPE_IPCOMP:
475: printf("/ipcomp");
476: break;
477: case SADB_X_SATYPE_IPIP:
478: printf("/ipip");
479: break;
480: default:
481: printf("/<unknown>");
482: }
483:
484: switch(saft->sadb_protocol_proto) {
485: case SADB_X_FLOW_TYPE_USE:
486: printf("/use");
487: break;
488: case SADB_X_FLOW_TYPE_REQUIRE:
489: printf("/require");
490: break;
491: case SADB_X_FLOW_TYPE_ACQUIRE:
492: printf("/acquire");
493: break;
494: case SADB_X_FLOW_TYPE_DENY:
495: printf("/deny");
496: break;
497: case SADB_X_FLOW_TYPE_BYPASS:
498: printf("/bypass");
499: break;
500: case SADB_X_FLOW_TYPE_DONTACQ:
501: printf("/dontacq");
502: break;
503: default:
504: printf("/<unknown type>");
505: }
506:
507: switch(saft->sadb_protocol_direction) {
508: case IPSP_DIRECTION_IN:
509: printf("/in");
510: break;
511: case IPSP_DIRECTION_OUT:
512: printf("/out");
513: break;
514: default:
515: printf("/<unknown>");
516: }
517: }
518:
519: void
520: p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
521: {
522: char *cp;
523:
524: switch (sa->sa_family) {
525: case AF_INET6:
526: {
527: struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
528: struct in6_addr *in6 = &sa6->sin6_addr;
529:
530: /*
531: * XXX: This is a special workaround for KAME kernels.
532: * sin6_scope_id field of SA should be set in the future.
533: */
534: if (IN6_IS_ADDR_LINKLOCAL(in6) ||
1.3 itojun 535: IN6_IS_ADDR_MC_LINKLOCAL(in6) ||
536: IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
1.1 claudio 537: /* XXX: override is ok? */
538: sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)
539: &in6->s6_addr[2]);
540: *(u_short *)&in6->s6_addr[2] = 0;
541: }
542: if (flags & RTF_HOST)
543: cp = routename((struct sockaddr *)sa6);
544: else
545: cp = netname((struct sockaddr *)sa6, mask);
546: break;
547: }
1.16 michele 548: case AF_MPLS:
1.17 michele 549: return;
1.1 claudio 550: default:
551: if ((flags & RTF_HOST) || mask == NULL)
552: cp = routename(sa);
553: else
554: cp = netname(sa, mask);
555: break;
556: }
557: if (width < 0)
558: printf("%s", cp);
559: else {
560: if (nflag)
561: printf("%-*s ", width, cp);
562: else
563: printf("%-*.*s ", width, width, cp);
564: }
565: }
566:
1.17 michele 567: static char line[MAXHOSTNAMELEN];
568: static char domain[MAXHOSTNAMELEN];
569:
570: void
571: p_sockaddr_mpls(struct sockaddr *in, struct sockaddr *out, int flags, int width)
572: {
573: if (in->sa_family != AF_MPLS)
574: return;
575:
1.30 claudio 576: if (flags & MPLS_OP_POP || flags == MPLS_OP_LOCAL) {
577: printf("%-*s ", width, label_print(in));
578: printf("%-*s ", width, label_print(NULL));
579: } else {
580: printf("%-*s ", width, label_print(in));
581: printf("%-*s ", width, label_print(out));
582: }
1.17 michele 583:
1.30 claudio 584: printf("%-6s ", mpls_op(flags));
1.17 michele 585: }
586:
1.1 claudio 587: void
588: p_flags(int f, char *format)
589: {
590: char name[33], *flags;
591: const struct bits *p = bits;
592:
593: for (flags = name; p->b_mask && flags < &name[sizeof(name) - 2]; p++)
594: if (p->b_mask & f)
595: *flags++ = p->b_val;
596: *flags = '\0';
597: printf(format, name);
598: }
599:
600: char *
601: routename(struct sockaddr *sa)
602: {
603: char *cp = NULL;
604: static int first = 1;
605:
606: if (first) {
607: first = 0;
608: if (gethostname(domain, sizeof(domain)) == 0 &&
609: (cp = strchr(domain, '.')))
610: (void)strlcpy(domain, cp + 1, sizeof(domain));
611: else
612: domain[0] = '\0';
613: cp = NULL;
614: }
615:
616: if (sa->sa_len == 0) {
617: (void)strlcpy(line, "default", sizeof(line));
618: return (line);
619: }
620:
621: switch (sa->sa_family) {
622: case AF_INET:
623: return
624: (routename4(((struct sockaddr_in *)sa)->sin_addr.s_addr));
625:
626: case AF_INET6:
627: {
628: struct sockaddr_in6 sin6;
629:
630: memset(&sin6, 0, sizeof(sin6));
631: memcpy(&sin6, sa, sa->sa_len);
632: sin6.sin6_len = sizeof(struct sockaddr_in6);
633: sin6.sin6_family = AF_INET6;
634: if (sa->sa_len == sizeof(struct sockaddr_in6) &&
635: (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
1.3 itojun 636: IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) ||
637: IN6_IS_ADDR_MC_INTFACELOCAL(&sin6.sin6_addr)) &&
1.1 claudio 638: sin6.sin6_scope_id == 0) {
639: sin6.sin6_scope_id =
640: ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
641: sin6.sin6_addr.s6_addr[2] = 0;
642: sin6.sin6_addr.s6_addr[3] = 0;
643: }
644: return (routename6(&sin6));
645: }
646:
647: case AF_LINK:
648: return (link_print(sa));
1.13 claudio 649: case AF_MPLS:
1.30 claudio 650: return (label_print(sa));
1.1 claudio 651: case AF_UNSPEC:
652: if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) {
653: static char name[RTLABEL_LEN];
654: struct sockaddr_rtlabel *sr;
655:
656: sr = (struct sockaddr_rtlabel *)sa;
1.9 claudio 657: (void)strlcpy(name, sr->sr_label, sizeof(name));
1.1 claudio 658: return (name);
659: }
660: /* FALLTHROUGH */
661: default:
662: (void)snprintf(line, sizeof(line), "(%d) %s",
663: sa->sa_family, any_ntoa(sa));
664: break;
665: }
666: return (line);
667: }
668:
669: char *
670: routename4(in_addr_t in)
671: {
672: char *cp = NULL;
673: struct in_addr ina;
674: struct hostent *hp;
675:
676: if (in == INADDR_ANY)
677: cp = "default";
678: if (!cp && !nflag) {
679: if ((hp = gethostbyaddr((char *)&in,
680: sizeof(in), AF_INET)) != NULL) {
681: if ((cp = strchr(hp->h_name, '.')) &&
682: !strcmp(cp + 1, domain))
683: *cp = '\0';
684: cp = hp->h_name;
685: }
686: }
687: ina.s_addr = in;
688: strlcpy(line, cp ? cp : inet_ntoa(ina), sizeof(line));
689:
690: return (line);
691: }
692:
693: char *
694: routename6(struct sockaddr_in6 *sin6)
695: {
696: int niflags = 0;
697:
698: if (nflag)
699: niflags |= NI_NUMERICHOST;
700: else
701: niflags |= NI_NOFQDN;
702:
703: if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
704: line, sizeof(line), NULL, 0, niflags) != 0)
705: strncpy(line, "invalid", sizeof(line));
706:
707: return (line);
708: }
709:
710: /*
711: * Return the name of the network whose address is given.
712: * The address is assumed to be that of a net or subnet, not a host.
713: */
714: char *
715: netname4(in_addr_t in, in_addr_t mask)
716: {
717: char *cp = NULL;
718: struct netent *np = NULL;
719: int mbits;
720:
721: in = ntohl(in);
722: mask = ntohl(mask);
723: if (!nflag && in != INADDR_ANY) {
724: if ((np = getnetbyaddr(in, AF_INET)) != NULL)
725: cp = np->n_name;
726: }
1.28 dlg 727: if (in == INADDR_ANY && mask == INADDR_ANY)
1.1 claudio 728: cp = "default";
729: mbits = mask ? 33 - ffs(mask) : 0;
730: if (cp)
731: strlcpy(line, cp, sizeof(line));
732: #define C(x) ((x) & 0xff)
733: else if (mbits < 9)
734: snprintf(line, sizeof(line), "%u/%d", C(in >> 24), mbits);
735: else if (mbits < 17)
736: snprintf(line, sizeof(line), "%u.%u/%d",
737: C(in >> 24) , C(in >> 16), mbits);
738: else if (mbits < 25)
739: snprintf(line, sizeof(line), "%u.%u.%u/%d",
740: C(in >> 24), C(in >> 16), C(in >> 8), mbits);
741: else
742: snprintf(line, sizeof(line), "%u.%u.%u.%u/%d", C(in >> 24),
743: C(in >> 16), C(in >> 8), C(in), mbits);
744: #undef C
745: return (line);
746: }
747:
748: char *
749: netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask)
750: {
751: struct sockaddr_in6 sin6;
752: u_char *p;
753: int masklen, final = 0, illegal = 0;
754: int i, lim, flag, error;
755: char hbuf[NI_MAXHOST];
756:
757: sin6 = *sa6;
758:
759: flag = 0;
760: masklen = 0;
761: if (mask) {
762: lim = mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr);
1.4 claudio 763: lim = lim < (int)sizeof(struct in6_addr) ?
1.1 claudio 764: lim : sizeof(struct in6_addr);
765: for (p = (u_char *)&mask->sin6_addr, i = 0; i < lim; p++) {
766: if (final && *p) {
767: illegal++;
768: sin6.sin6_addr.s6_addr[i++] = 0x00;
769: continue;
770: }
771:
772: switch (*p & 0xff) {
773: case 0xff:
774: masklen += 8;
775: break;
776: case 0xfe:
777: masklen += 7;
778: final++;
779: break;
780: case 0xfc:
781: masklen += 6;
782: final++;
783: break;
784: case 0xf8:
785: masklen += 5;
786: final++;
787: break;
788: case 0xf0:
789: masklen += 4;
790: final++;
791: break;
792: case 0xe0:
793: masklen += 3;
794: final++;
795: break;
796: case 0xc0:
797: masklen += 2;
798: final++;
799: break;
800: case 0x80:
801: masklen += 1;
802: final++;
803: break;
804: case 0x00:
805: final++;
806: break;
807: default:
808: final++;
809: illegal++;
810: break;
811: }
812:
813: if (!illegal)
814: sin6.sin6_addr.s6_addr[i++] &= *p;
815: else
816: sin6.sin6_addr.s6_addr[i++] = 0x00;
817: }
818: while (i < sizeof(struct in6_addr))
819: sin6.sin6_addr.s6_addr[i++] = 0x00;
820: } else
821: masklen = 128;
822:
823: if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr))
824: return ("default");
825:
826: if (illegal)
827: warnx("illegal prefixlen");
828:
829: if (nflag)
830: flag |= NI_NUMERICHOST;
831: error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
832: hbuf, sizeof(hbuf), NULL, 0, flag);
833: if (error)
834: snprintf(hbuf, sizeof(hbuf), "invalid");
835:
836: snprintf(line, sizeof(line), "%s/%d", hbuf, masklen);
837: return (line);
838: }
839:
840: /*
841: * Return the name of the network whose address is given.
842: * The address is assumed to be that of a net or subnet, not a host.
843: */
844: char *
845: netname(struct sockaddr *sa, struct sockaddr *mask)
846: {
847: switch (sa->sa_family) {
848: case AF_INET:
849: return netname4(((struct sockaddr_in *)sa)->sin_addr.s_addr,
1.29 claudio 850: mask->sa_len == 0 ? 0 :
1.1 claudio 851: ((struct sockaddr_in *)mask)->sin_addr.s_addr);
852: case AF_INET6:
853: return netname6((struct sockaddr_in6 *)sa,
854: (struct sockaddr_in6 *)mask);
855: case AF_LINK:
856: return (link_print(sa));
1.13 claudio 857: case AF_MPLS:
1.30 claudio 858: return (label_print(sa));
1.1 claudio 859: default:
860: snprintf(line, sizeof(line), "af %d: %s",
861: sa->sa_family, any_ntoa(sa));
862: break;
863: }
864: return (line);
865: }
866:
867: static const char hexlist[] = "0123456789abcdef";
868:
869: char *
870: any_ntoa(const struct sockaddr *sa)
871: {
872: static char obuf[240];
873: const char *in = sa->sa_data;
874: char *out = obuf;
875: int len = sa->sa_len - offsetof(struct sockaddr, sa_data);
876:
877: *out++ = 'Q';
878: do {
879: *out++ = hexlist[(*in >> 4) & 15];
880: *out++ = hexlist[(*in++) & 15];
881: *out++ = '.';
882: } while (--len > 0 && (out + 3) < &obuf[sizeof(obuf) - 1]);
883: out[-1] = '\0';
884: return (obuf);
885: }
886:
887: char *
888: link_print(struct sockaddr *sa)
889: {
890: struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
891: u_char *lla = (u_char *)sdl->sdl_data + sdl->sdl_nlen;
892:
893: if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
894: sdl->sdl_slen == 0) {
895: (void)snprintf(line, sizeof(line), "link#%d", sdl->sdl_index);
896: return (line);
897: }
898: switch (sdl->sdl_type) {
899: case IFT_ETHER:
900: case IFT_CARP:
901: return (ether_ntoa((struct ether_addr *)lla));
902: default:
903: return (link_ntoa(sdl));
904: }
1.13 claudio 905: }
906:
907: char *
1.30 claudio 908: mpls_op(u_int32_t type)
1.13 claudio 909: {
1.16 michele 910: switch (type & (MPLS_OP_PUSH | MPLS_OP_POP | MPLS_OP_SWAP)) {
1.21 michele 911: case MPLS_OP_LOCAL:
912: return ("LOCAL");
1.13 claudio 913: case MPLS_OP_POP:
914: return ("POP");
915: case MPLS_OP_SWAP:
916: return ("SWAP");
917: case MPLS_OP_PUSH:
918: return ("PUSH");
919: default:
920: return ("?");
921: }
922: }
923:
924: char *
1.30 claudio 925: label_print(struct sockaddr *sa)
1.13 claudio 926: {
1.30 claudio 927: struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)sa;
1.13 claudio 928:
1.30 claudio 929: if (smpls)
930: (void)snprintf(line, sizeof(line), "%u",
931: ntohl(smpls->smpls_label) >> MPLS_LABEL_OFFSET);
932: else
933: (void)snprintf(line, sizeof(line), "-");
1.13 claudio 934:
935: return (line);
1.1 claudio 936: }
937:
938: void
939: index_pfk(struct sadb_msg *msg, void **headers)
940: {
941: struct sadb_ext *ext;
942:
943: for (ext = (struct sadb_ext *)(msg + 1);
944: (size_t)((u_int8_t *)ext - (u_int8_t *)msg) <
945: msg->sadb_msg_len * PFKEYV2_CHUNK && ext->sadb_ext_len > 0;
946: ext = (struct sadb_ext *)((u_int8_t *)ext +
947: ext->sadb_ext_len * PFKEYV2_CHUNK)) {
948: switch (ext->sadb_ext_type) {
949: case SADB_EXT_ADDRESS_SRC:
950: headers[SADB_EXT_ADDRESS_SRC] = (void *)ext;
951: break;
952: case SADB_EXT_ADDRESS_DST:
953: headers[SADB_EXT_ADDRESS_DST] = (void *)ext;
954: break;
955: case SADB_X_EXT_PROTOCOL:
956: headers[SADB_X_EXT_PROTOCOL] = (void *)ext;
957: break;
958: case SADB_X_EXT_SRC_FLOW:
959: headers[SADB_X_EXT_SRC_FLOW] = (void *)ext;
960: break;
961: case SADB_X_EXT_DST_FLOW:
962: headers[SADB_X_EXT_DST_FLOW] = (void *)ext;
963: break;
964: case SADB_X_EXT_SRC_MASK:
965: headers[SADB_X_EXT_SRC_MASK] = (void *)ext;
966: break;
967: case SADB_X_EXT_DST_MASK:
968: headers[SADB_X_EXT_DST_MASK] = (void *)ext;
969: break;
970: case SADB_X_EXT_FLOW_TYPE:
971: headers[SADB_X_EXT_FLOW_TYPE] = (void *)ext;
1.26 deraadt 972: break;
1.1 claudio 973: default:
974: /* Ignore. */
975: break;
976: }
977: }
978: }