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