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