1251881Speter/*-
2251881Speter * Copyright (c) 2012 maksim yevmenkin <emax@freebsd.org>
3251881Speter * All rights reserved.
4251881Speter *
5251881Speter * Redistribution and use in source and binary forms, with or without
6251881Speter * modification, are permitted providing that the following conditions
7251881Speter * are met:
8251881Speter * 1. Redistributions of source code must retain the above copyright
9251881Speter *    notice, this list of conditions and the following disclaimer.
10251881Speter * 2. Redistributions in binary form must reproduce the above copyright
11251881Speter *    notice, this list of conditions and the following disclaimer in the
12251881Speter *    documentation and/or other materials provided with the distribution.
13251881Speter *
14251881Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15251881Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16251881Speter * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17251881Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18251881Speter * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22251881Speter * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23251881Speter * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24251881Speter * POSSIBILITY OF SUCH DAMAGE.
25251881Speter */
26251881Speter
27251881Speter/* gcc -Wall -ggdb ifpifa.c -lkvm -o ifpifa */
28251881Speter
29251881Speter#include <sys/types.h>
30251881Speter#include <sys/callout.h>
31251881Speter#include <sys/cdefs.h>
32251881Speter#include <sys/param.h>
33251881Speter#include <sys/protosw.h>
34251881Speter#include <sys/queue.h>
35251881Speter#include <sys/socket.h>
36251881Speter#include <sys/socketvar.h>
37251881Speter
38251881Speter#include <net/if.h>
39251881Speter#include <net/if_var.h>
40251881Speter#include <net/if_dl.h>
41251881Speter#include <net/if_types.h>
42251881Speter#include <net/ethernet.h>
43251881Speter#include <netinet/in.h>
44251881Speter#include <netinet/in_var.h>
45251881Speter#include <arpa/inet.h>
46251881Speter
47251881Speter#include <err.h>
48251881Speter#include <fcntl.h>
49251881Speter#include <kvm.h>
50251881Speter#include <limits.h>
51251881Speter#include <nlist.h>
52251881Speter#include <stdio.h>
53251881Speter#include <stdlib.h>
54251881Speter#include <string.h>
55251881Speter
56251881Speter__FBSDID("$FreeBSD: releng/10.3/tools/tools/ifpifa/ifpifa.c 236645 2012-06-05 22:02:27Z emax $");
57251881Speter
58251881Speterstatic struct nlist	nl[] = {
59251881Speter#define N_IFNET         0
60251881Speter        { .n_name = "_ifnet", },
61251881Speter	{ .n_name = NULL, },
62251881Speter};
63251881Speter
64251881Speterstatic int
65251881Speterkread(kvm_t *kd, u_long addr, char *buffer, int size)
66251881Speter{
67251881Speter	if (kd == NULL || buffer == NULL)
68251881Speter		return (-1);
69251881Speter
70251881Speter	if (kvm_read(kd, addr, buffer, size) != size) {
71251881Speter		warnx("kvm_read: %s", kvm_geterr(kd));
72251881Speter		return (-1);
73251881Speter	}
74251881Speter
75251881Speter	return (0);
76251881Speter}
77251881Speter
78251881Speterint
79251881Spetermain(void)
80251881Speter{
81251881Speter	kvm_t *kd;
82251881Speter	char errbuf[_POSIX2_LINE_MAX];
83251881Speter	u_long ifnetaddr, ifnetaddr_next;
84251881Speter	u_long ifaddraddr, ifaddraddr_next;
85251881Speter        struct ifnet ifnet;
86251881Speter        struct ifnethead ifnethead;
87251881Speter        union {
88251881Speter		struct ifaddr ifa;
89251881Speter		struct in_ifaddr in;
90251881Speter		struct in6_ifaddr in6;
91251881Speter        } ifaddr;
92251881Speter	union {
93251881Speter		struct sockaddr	*sa;
94251881Speter		struct sockaddr_dl *sal;
95251881Speter		struct sockaddr_in *sa4;
96251881Speter		struct sockaddr_in6 *sa6;
97251881Speter	} sa;
98251881Speter	char addr[INET6_ADDRSTRLEN];
99251881Speter
100251881Speter	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
101251881Speter	if (kd == NULL) {
102251881Speter		warnx("kvm_openfiles: %s", errbuf);
103251881Speter		exit(0);
104251881Speter	}
105251881Speter
106251881Speter	if (kvm_nlist(kd, nl) < 0) {
107251881Speter                warnx("kvm_nlist: %s", kvm_geterr(kd));
108251881Speter                goto out;
109251881Speter        }
110251881Speter
111251881Speter	if (nl[N_IFNET].n_type == 0) {
112251881Speter		warnx("kvm_nlist: no namelist");
113251881Speter		goto out;
114251881Speter	}
115251881Speter
116251881Speter	if (kread(kd, nl[N_IFNET].n_value,
117251881Speter		  (char *) &ifnethead, sizeof(ifnethead)) != 0)
118251881Speter		goto out;
119251881Speter
120251881Speter	for (ifnetaddr = (u_long) TAILQ_FIRST(&ifnethead);
121251881Speter	     ifnetaddr != 0;
122251881Speter	     ifnetaddr = ifnetaddr_next) {
123251881Speter		if (kread(kd, ifnetaddr, (char *) &ifnet, sizeof(ifnet)) != 0)
124251881Speter			goto out;
125251881Speter		ifnetaddr_next = (u_long) TAILQ_NEXT(&ifnet, if_link);
126251881Speter
127251881Speter		printf("%s\n", ifnet.if_xname);
128251881Speter
129251881Speter		for (ifaddraddr = (u_long) TAILQ_FIRST(&ifnet.if_addrhead);
130251881Speter		     ifaddraddr != 0;
131251881Speter		     ifaddraddr = ifaddraddr_next) {
132251881Speter			if (kread(kd, ifaddraddr,
133251881Speter				  (char *) &ifaddr, sizeof(ifaddr)) != 0)
134251881Speter				goto out;
135251881Speter
136251881Speter			ifaddraddr_next = (u_long)
137251881Speter				TAILQ_NEXT(&ifaddr.ifa, ifa_link);
138251881Speter
139251881Speter			sa.sa = (struct sockaddr *)(
140251881Speter				(unsigned char *) ifaddr.ifa.ifa_addr -
141251881Speter				(unsigned char *) ifaddraddr +
142251881Speter				(unsigned char *) &ifaddr);
143251881Speter
144251881Speter			switch (sa.sa->sa_family) {
145251881Speter			case AF_LINK:
146251881Speter				switch (sa.sal->sdl_type) {
147251881Speter				case IFT_ETHER:
148251881Speter				case IFT_FDDI:
149251881Speter	     				ether_ntoa_r((struct ether_addr * )
150251881Speter						LLADDR(sa.sal), addr);
151251881Speter					break;
152251881Speter
153251881Speter				case IFT_LOOP:
154251881Speter					strcpy(addr, "loopback");
155251881Speter					break;
156251881Speter
157251881Speter				default:
158251881Speter					snprintf(addr, sizeof(addr),
159251881Speter						 "<Link type %#x>",
160251881Speter						sa.sal->sdl_type);
161251881Speter					break;
162251881Speter				}
163251881Speter				break;
164251881Speter
165251881Speter			case AF_INET:
166251881Speter				inet_ntop(AF_INET, &sa.sa4->sin_addr,
167251881Speter					addr, sizeof(addr));
168251881Speter				break;
169251881Speter
170251881Speter			case AF_INET6:
171251881Speter				inet_ntop(AF_INET6, &sa.sa6->sin6_addr,
172251881Speter					addr, sizeof(addr));
173251881Speter				break;
174251881Speter
175251881Speter			default:
176251881Speter				snprintf(addr, sizeof(addr), "family=%d",
177251881Speter					sa.sa->sa_family);
178251881Speter				break;
179251881Speter			}
180251881Speter
181251881Speter			printf("\t%s ifa_refcnt=%u\n",
182251881Speter				addr, ifaddr.ifa.ifa_refcnt);
183251881Speter		}
184251881Speter	}
185251881Speterout:
186251881Speter	kvm_close(kd);
187251881Speter
188251881Speter	return (0);
189251881Speter}
190251881Speter
191251881Speter