1 /*
2 * Copyright 1996 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all
9 * supporting documentation, and that the name of M.I.T. not be used
10 * in advertising or publicity pertaining to distribution of the
11 * software without specific, written prior permission. M.I.T. makes
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied
14 * warranty.
15 *
16 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
17 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 #include <sys/types.h>
30 #include <sys/socket.h> /* for PF_LINK */
31 #include <sys/sysctl.h>
32 #include <sys/time.h>
33 #include <sys/mbuf.h>
34
35 #include <err.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sysexits.h>
41 #include <unistd.h>
42 #include <stdbool.h>
43 #include <ctype.h>
44
45 #include <net/if.h>
46 #include <net/if_types.h>
47 #include <net/if_mib.h>
48
49 #include "ifinfo.h"
50
51 static void printit(const struct ifmibdata *, const char *);
52 static const char *iftype(int);
53 static int isit(int, char **, const char *);
54 static printfcn findlink(int);
55
56 static void
usage(const char * argv0)57 usage(const char *argv0)
58 {
59 fprintf(stderr, "%s: usage:\n\t%s [-l]\n", argv0, argv0);
60 exit(EX_USAGE);
61 }
62
63 int
main(int argc,char ** argv)64 main(int argc, char **argv)
65 {
66 int i, maxifno, retval;
67 struct ifmibdata ifmd;
68 int name[6];
69 size_t len;
70 int c;
71 int dolink = 0;
72 void *linkmib;
73 size_t linkmiblen;
74 printfcn pf;
75 char *dname;
76
77 while ((c = getopt(argc, argv, "l")) != -1) {
78 switch(c) {
79 case 'l':
80 dolink = 1;
81 break;
82 default:
83 usage(argv[0]);
84 }
85 }
86
87 retval = 1;
88
89 name[0] = CTL_NET;
90 name[1] = PF_LINK;
91 name[2] = NETLINK_GENERIC;
92 name[3] = IFMIB_SYSTEM;
93 name[4] = IFMIB_IFCOUNT;
94
95 len = sizeof maxifno;
96 if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0)
97 err(EX_OSERR, "sysctl(net.link.generic.system.ifcount)");
98
99 for (i = 1; i <= maxifno; i++) {
100 len = sizeof ifmd;
101 name[3] = IFMIB_IFDATA;
102 name[4] = i;
103 name[5] = IFDATA_GENERAL;
104 if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) {
105 if (errno == ENOENT)
106 continue;
107
108 err(EX_OSERR, "sysctl(net.link.ifdata.%d.general)",
109 i);
110 }
111
112 if (!isit(argc - optind, argv + optind, ifmd.ifmd_name))
113 continue;
114
115 dname = NULL;
116 len = 0;
117 name[5] = IFDATA_DRIVERNAME;
118 if (sysctl(name, 6, NULL, &len, 0, 0) < 0) {
119 warn("sysctl(net.link.ifdata.%d.drivername)", i);
120 } else {
121 if ((dname = malloc(len)) == NULL)
122 err(EX_OSERR, NULL);
123 if (sysctl(name, 6, dname, &len, 0, 0) < 0) {
124 warn("sysctl(net.link.ifdata.%d.drivername)",
125 i);
126 free(dname);
127 dname = NULL;
128 }
129 }
130 printit(&ifmd, dname);
131 free(dname);
132 if (dolink && (pf = findlink(ifmd.ifmd_data.ifi_type))) {
133 name[5] = IFDATA_LINKSPECIFIC;
134 if (sysctl(name, 6, 0, &linkmiblen, 0, 0) < 0)
135 err(EX_OSERR,
136 "sysctl(net.link.ifdata.%d.linkspec) size",
137 i);
138 linkmib = malloc(linkmiblen);
139 if (!linkmib)
140 err(EX_OSERR, "malloc(%lu)",
141 (u_long)linkmiblen);
142 if (sysctl(name, 6, linkmib, &linkmiblen, 0, 0) < 0)
143 err(EX_OSERR,
144 "sysctl(net.link.ifdata.%d.linkspec)",
145 i);
146 pf(linkmib, linkmiblen);
147 free(linkmib);
148 }
149 retval = 0;
150 }
151
152 return retval;
153 }
154
155 /* code after this line copied or based on code from src/sys/kern/subr_prf.c */
156 static inline bool
isbitpos(char c)157 isbitpos(char c)
158 {
159 return (c != '\0' && (c <= ' ' || (c & 0x80) != 0));
160 }
161
162 static inline bool
isprintnospace(char c)163 isprintnospace(char c)
164 {
165 return (isprint(c) && c != ' ');
166 }
167
168 static void
print_bits(uintmax_t num,const char * bitstring)169 print_bits(uintmax_t num, const char *bitstring)
170 {
171 bool first;
172 const char *c;
173 int shift;
174
175 c = ++bitstring;
176 first = true;
177 while (isbitpos(*c)) {
178 if ((*c & 0x80) != 0)
179 shift = *c++ & 0x7f;
180 else
181 shift = *c++ - 1;
182 if (num & (1ULL << shift)) {
183 putchar(first ? (first = false, '<') : ',');
184 for (; isprintnospace(*c); ++c)
185 putchar(*c);
186 } else
187 for (; isprintnospace(*c); ++c)
188 continue;
189 }
190 if (!first) {
191 putchar('>');
192 }
193 }
194 /* code before this line copied or based on code from src/sys/kern/subr_prf.c */
195
196 static void
printit(const struct ifmibdata * ifmd,const char * dname)197 printit(const struct ifmibdata *ifmd, const char *dname)
198 {
199 printf("Interface %.*s", IFNAMSIZ, ifmd->ifmd_name);
200 if (dname != NULL)
201 printf(" (%s)", dname);
202 printf(":\n");
203 printf("\tflags: %x\n", ifmd->ifmd_flags);
204 printf("\tpromiscuous listeners: %d\n", ifmd->ifmd_pcount);
205 printf("\tsend queue length: %d\n", ifmd->ifmd_snd_len);
206 printf("\tsend queue max length: %d\n", ifmd->ifmd_snd_maxlen);
207 printf("\tsend queue drops: %d\n", ifmd->ifmd_snd_drops);
208 printf("\ttype: %s\n", iftype(ifmd->ifmd_data.ifi_type));
209 printf("\taddress length: %d\n", ifmd->ifmd_data.ifi_addrlen);
210 printf("\theader length: %d\n", ifmd->ifmd_data.ifi_hdrlen);
211 printf("\tlink state: %u\n", ifmd->ifmd_data.ifi_link_state);
212 printf("\tvhid: %u\n", ifmd->ifmd_data.ifi_vhid);
213 printf("\tdatalen: %u\n", ifmd->ifmd_data.ifi_datalen);
214 printf("\tmtu: %u\n", ifmd->ifmd_data.ifi_mtu);
215 printf("\tmetric: %u\n", ifmd->ifmd_data.ifi_metric);
216 printf("\tline rate: %lu bit/s\n", ifmd->ifmd_data.ifi_baudrate);
217 printf("\tpackets received: %lu\n", ifmd->ifmd_data.ifi_ipackets);
218 printf("\tinput errors: %lu\n", ifmd->ifmd_data.ifi_ierrors);
219 printf("\tpackets transmitted: %lu\n", ifmd->ifmd_data.ifi_opackets);
220 printf("\toutput errors: %lu\n", ifmd->ifmd_data.ifi_oerrors);
221 printf("\tcollisions: %lu\n", ifmd->ifmd_data.ifi_collisions);
222 printf("\tbytes received: %lu\n", ifmd->ifmd_data.ifi_ibytes);
223 printf("\tbytes transmitted: %lu\n", ifmd->ifmd_data.ifi_obytes);
224 printf("\tmulticasts received: %lu\n", ifmd->ifmd_data.ifi_imcasts);
225 printf("\tmulticasts transmitted: %lu\n", ifmd->ifmd_data.ifi_omcasts);
226 printf("\tinput queue drops: %lu\n", ifmd->ifmd_data.ifi_iqdrops);
227 printf("\tpackets for unknown protocol: %lu\n",
228 ifmd->ifmd_data.ifi_noproto);
229 printf("\tHW offload capabilities: 0x%lx",
230 ifmd->ifmd_data.ifi_hwassist);
231 print_bits(ifmd->ifmd_data.ifi_hwassist, CSUM_BITS);
232 printf("\n");
233 printf("\tuptime at attach or stat reset: %lu\n",
234 ifmd->ifmd_data.ifi_epoch);
235 #ifdef notdef
236 printf("\treceive timing: %lu usec\n", ifmd->ifmd_data.ifi_recvtiming);
237 printf("\ttransmit timing: %lu usec\n",
238 ifmd->ifmd_data.ifi_xmittiming);
239 #endif
240 }
241
242 static const char *const if_types[] = {
243 "reserved",
244 "other",
245 "BBN 1822",
246 "HDH 1822",
247 "X.25 DDN",
248 "X.25",
249 "Ethernet",
250 "ISO 8802-3 CSMA/CD",
251 "ISO 8802-4 Token Bus",
252 "ISO 8802-5 Token Ring",
253 "ISO 8802-6 DQDB MAN",
254 "StarLAN",
255 "Proteon proNET-10",
256 "Proteon proNET-80",
257 "HyperChannel",
258 "FDDI",
259 "LAP-B",
260 "SDLC",
261 "T-1",
262 "CEPT",
263 "Basic rate ISDN",
264 "Primary rate ISDN",
265 "Proprietary P2P",
266 "PPP",
267 "Loopback",
268 "ISO CLNP over IP",
269 "Experimental Ethernet",
270 "XNS over IP",
271 "SLIP",
272 "Ultra Technologies",
273 "DS-3",
274 "SMDS",
275 "Frame Relay",
276 "RS-232 serial",
277 "Parallel printer port",
278 "ARCNET",
279 "ARCNET+",
280 "ATM",
281 "MIOX25",
282 "SONET/SDH",
283 "X25PLE",
284 "ISO 8802-2 LLC",
285 "LocalTalk",
286 "SMDSDXI",
287 "Frame Relay DCE",
288 "V.35",
289 "HSSI",
290 "HIPPI",
291 "Generic Modem",
292 "ATM AAL5",
293 "SONETPATH",
294 "SONETVT",
295 "SMDS InterCarrier Interface",
296 "Proprietary virtual interface",
297 "Proprietary multiplexing",
298 "Generic tunnel interface",
299 "IPv6-to-IPv4 TCP relay capturing interface",
300 "6to4 tunnel interface"
301 };
302 #define NIFTYPES (int)((sizeof if_types)/(sizeof if_types[0]))
303
304 static const char *
iftype(int type)305 iftype(int type)
306 {
307 static char buf[256];
308
309 if (type <= 0 || type >= NIFTYPES) {
310 sprintf(buf, "unknown type %d", type);
311 return buf;
312 }
313
314 return if_types[type];
315 }
316
317 static int
isit(int argc,char ** argv,const char * name)318 isit(int argc, char **argv, const char *name)
319 {
320 if (argc == 0)
321 return 1;
322 for (argc = 0; argv[argc]; argc++) {
323 if (strncmp(argv[argc], name, IFNAMSIZ) == 0)
324 return 1;
325 }
326 return 0;
327 }
328
329 static printfcn
findlink(int type)330 findlink(int type)
331 {
332 switch(type) {
333 case IFT_ETHER:
334 case IFT_ISO88023:
335 case IFT_STARLAN:
336 return print_1650;
337 }
338
339 return 0;
340 }
341