/usr.bin/netstat/if.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 732 lines · 612 code · 53 blank · 67 comment · 120 complexity · 9dc739b52f4c3755da6e336482aba881 MD5 · raw file

  1. /*-
  2. * Copyright (c) 1983, 1988, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 4. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #if 0
  30. #ifndef lint
  31. static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
  32. #endif /* not lint */
  33. #endif
  34. #include <sys/cdefs.h>
  35. __FBSDID("$FreeBSD$");
  36. #include <sys/types.h>
  37. #include <sys/protosw.h>
  38. #include <sys/socket.h>
  39. #include <sys/socketvar.h>
  40. #include <sys/sysctl.h>
  41. #include <sys/time.h>
  42. #include <net/if.h>
  43. #include <net/if_var.h>
  44. #include <net/if_dl.h>
  45. #include <net/if_types.h>
  46. #include <net/ethernet.h>
  47. #include <net/pfvar.h>
  48. #include <net/if_pfsync.h>
  49. #include <netinet/in.h>
  50. #include <netinet/in_var.h>
  51. #include <netipx/ipx.h>
  52. #include <netipx/ipx_if.h>
  53. #include <arpa/inet.h>
  54. #include <err.h>
  55. #include <errno.h>
  56. #include <libutil.h>
  57. #ifdef INET6
  58. #include <netdb.h>
  59. #endif
  60. #include <signal.h>
  61. #include <stdint.h>
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <unistd.h>
  66. #include "netstat.h"
  67. #define YES 1
  68. #define NO 0
  69. static void sidewaysintpr(int, u_long);
  70. static void catchalarm(int);
  71. #ifdef INET6
  72. static char addr_buf[NI_MAXHOST]; /* for getnameinfo() */
  73. #endif
  74. static const char* pfsyncacts[] = {
  75. /* PFSYNC_ACT_CLR */ "clear all request",
  76. /* PFSYNC_ACT_INS */ "state insert",
  77. /* PFSYNC_ACT_INS_ACK */ "state inserted ack",
  78. /* PFSYNC_ACT_UPD */ "state update",
  79. /* PFSYNC_ACT_UPD_C */ "compressed state update",
  80. /* PFSYNC_ACT_UPD_REQ */ "uncompressed state request",
  81. /* PFSYNC_ACT_DEL */ "state delete",
  82. /* PFSYNC_ACT_DEL_C */ "compressed state delete",
  83. /* PFSYNC_ACT_INS_F */ "fragment insert",
  84. /* PFSYNC_ACT_DEL_F */ "fragment delete",
  85. /* PFSYNC_ACT_BUS */ "bulk update mark",
  86. /* PFSYNC_ACT_TDB */ "TDB replay counter update",
  87. /* PFSYNC_ACT_EOF */ "end of frame mark",
  88. };
  89. static void
  90. pfsync_acts_stats(const char *fmt, uint64_t *a)
  91. {
  92. int i;
  93. for (i = 0; i < PFSYNC_ACT_MAX; i++, a++)
  94. if (*a || sflag <= 1)
  95. printf(fmt, *a, pfsyncacts[i], plural(*a));
  96. }
  97. /*
  98. * Dump pfsync statistics structure.
  99. */
  100. void
  101. pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
  102. {
  103. struct pfsyncstats pfsyncstat, zerostat;
  104. size_t len = sizeof(struct pfsyncstats);
  105. if (live) {
  106. if (zflag)
  107. memset(&zerostat, 0, len);
  108. if (sysctlbyname("net.pfsync.stats", &pfsyncstat, &len,
  109. zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
  110. if (errno != ENOENT)
  111. warn("sysctl: net.pfsync.stats");
  112. return;
  113. }
  114. } else
  115. kread(off, &pfsyncstat, len);
  116. printf("%s:\n", name);
  117. #define p(f, m) if (pfsyncstat.f || sflag <= 1) \
  118. printf(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f))
  119. p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n");
  120. p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n");
  121. pfsync_acts_stats("\t %ju %s%s received\n",
  122. &pfsyncstat.pfsyncs_iacts[0]);
  123. p(pfsyncs_badif, "\t\t%ju packet%s discarded for bad interface\n");
  124. p(pfsyncs_badttl, "\t\t%ju packet%s discarded for bad ttl\n");
  125. p(pfsyncs_hdrops, "\t\t%ju packet%s shorter than header\n");
  126. p(pfsyncs_badver, "\t\t%ju packet%s discarded for bad version\n");
  127. p(pfsyncs_badauth, "\t\t%ju packet%s discarded for bad HMAC\n");
  128. p(pfsyncs_badact,"\t\t%ju packet%s discarded for bad action\n");
  129. p(pfsyncs_badlen, "\t\t%ju packet%s discarded for short packet\n");
  130. p(pfsyncs_badval, "\t\t%ju state%s discarded for bad values\n");
  131. p(pfsyncs_stale, "\t\t%ju stale state%s\n");
  132. p(pfsyncs_badstate, "\t\t%ju failed state lookup/insert%s\n");
  133. p(pfsyncs_opackets, "\t%ju packet%s sent (IPv4)\n");
  134. p(pfsyncs_opackets6, "\t%ju packet%s sent (IPv6)\n");
  135. pfsync_acts_stats("\t %ju %s%s sent\n",
  136. &pfsyncstat.pfsyncs_oacts[0]);
  137. p(pfsyncs_onomem, "\t\t%ju failure%s due to mbuf memory error\n");
  138. p(pfsyncs_oerrors, "\t\t%ju send error%s\n");
  139. #undef p
  140. }
  141. /*
  142. * Display a formatted value, or a '-' in the same space.
  143. */
  144. static void
  145. show_stat(const char *fmt, int width, u_long value, short showvalue)
  146. {
  147. const char *lsep, *rsep;
  148. char newfmt[32];
  149. lsep = "";
  150. if (strncmp(fmt, "LS", 2) == 0) {
  151. lsep = " ";
  152. fmt += 2;
  153. }
  154. rsep = " ";
  155. if (strncmp(fmt, "NRS", 3) == 0) {
  156. rsep = "";
  157. fmt += 3;
  158. }
  159. if (showvalue == 0) {
  160. /* Print just dash. */
  161. sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
  162. printf(newfmt, "-");
  163. return;
  164. }
  165. if (hflag) {
  166. char buf[5];
  167. /* Format in human readable form. */
  168. humanize_number(buf, sizeof(buf), (int64_t)value, "",
  169. HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
  170. sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
  171. printf(newfmt, buf);
  172. } else {
  173. /* Construct the format string. */
  174. sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
  175. printf(newfmt, value);
  176. }
  177. }
  178. /*
  179. * Print a description of the network interfaces.
  180. */
  181. void
  182. intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
  183. {
  184. struct ifnet ifnet;
  185. struct ifnethead ifnethead;
  186. union {
  187. struct ifaddr ifa;
  188. struct in_ifaddr in;
  189. #ifdef INET6
  190. struct in6_ifaddr in6;
  191. #endif
  192. struct ipx_ifaddr ipx;
  193. } ifaddr;
  194. u_long ifaddraddr;
  195. u_long ifaddrfound;
  196. u_long opackets;
  197. u_long ipackets;
  198. u_long obytes;
  199. u_long ibytes;
  200. u_long omcasts;
  201. u_long imcasts;
  202. u_long oerrors;
  203. u_long ierrors;
  204. u_long idrops;
  205. u_long collisions;
  206. int drops;
  207. struct sockaddr *sa = NULL;
  208. char name[IFNAMSIZ];
  209. short network_layer;
  210. short link_layer;
  211. if (ifnetaddr == 0) {
  212. printf("ifnet: symbol not defined\n");
  213. return;
  214. }
  215. if (interval1) {
  216. sidewaysintpr(interval1, ifnetaddr);
  217. return;
  218. }
  219. if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead) != 0)
  220. return;
  221. ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
  222. if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
  223. return;
  224. if (!pfunc) {
  225. if (Wflag)
  226. printf("%-7.7s", "Name");
  227. else
  228. printf("%-5.5s", "Name");
  229. printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s %5.5s",
  230. "Mtu", "Network", "Address", "Ipkts", "Ierrs", "Idrop");
  231. if (bflag)
  232. printf(" %10.10s","Ibytes");
  233. printf(" %8.8s %5.5s", "Opkts", "Oerrs");
  234. if (bflag)
  235. printf(" %10.10s","Obytes");
  236. printf(" %5s", "Coll");
  237. if (dflag)
  238. printf(" %s", "Drop");
  239. putchar('\n');
  240. }
  241. ifaddraddr = 0;
  242. while (ifnetaddr || ifaddraddr) {
  243. struct sockaddr_in *sockin;
  244. #ifdef INET6
  245. struct sockaddr_in6 *sockin6;
  246. #endif
  247. char *cp;
  248. int n, m;
  249. network_layer = 0;
  250. link_layer = 0;
  251. if (ifaddraddr == 0) {
  252. if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
  253. return;
  254. strlcpy(name, ifnet.if_xname, sizeof(name));
  255. ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
  256. if (interface != 0 && strcmp(name, interface) != 0)
  257. continue;
  258. cp = strchr(name, '\0');
  259. if (pfunc) {
  260. (*pfunc)(name);
  261. continue;
  262. }
  263. if ((ifnet.if_flags&IFF_UP) == 0)
  264. *cp++ = '*';
  265. *cp = '\0';
  266. ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
  267. }
  268. ifaddrfound = ifaddraddr;
  269. /*
  270. * Get the interface stats. These may get
  271. * overriden below on a per-interface basis.
  272. */
  273. opackets = ifnet.if_opackets;
  274. ipackets = ifnet.if_ipackets;
  275. obytes = ifnet.if_obytes;
  276. ibytes = ifnet.if_ibytes;
  277. omcasts = ifnet.if_omcasts;
  278. imcasts = ifnet.if_imcasts;
  279. oerrors = ifnet.if_oerrors;
  280. ierrors = ifnet.if_ierrors;
  281. idrops = ifnet.if_iqdrops;
  282. collisions = ifnet.if_collisions;
  283. drops = ifnet.if_snd.ifq_drops;
  284. if (ifaddraddr == 0) {
  285. if (Wflag)
  286. printf("%-7.7s", name);
  287. else
  288. printf("%-5.5s", name);
  289. printf(" %5lu ", ifnet.if_mtu);
  290. printf("%-13.13s ", "none");
  291. printf("%-17.17s ", "none");
  292. } else {
  293. if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)
  294. != 0) {
  295. ifaddraddr = 0;
  296. continue;
  297. }
  298. #define CP(x) ((char *)(x))
  299. cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
  300. CP(&ifaddr);
  301. sa = (struct sockaddr *)cp;
  302. if (af != AF_UNSPEC && sa->sa_family != af) {
  303. ifaddraddr =
  304. (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
  305. continue;
  306. }
  307. if (Wflag)
  308. printf("%-7.7s", name);
  309. else
  310. printf("%-5.5s", name);
  311. printf(" %5lu ", ifnet.if_mtu);
  312. switch (sa->sa_family) {
  313. case AF_UNSPEC:
  314. printf("%-13.13s ", "none");
  315. printf("%-15.15s ", "none");
  316. break;
  317. case AF_INET:
  318. sockin = (struct sockaddr_in *)sa;
  319. #ifdef notdef
  320. /* can't use inet_makeaddr because kernel
  321. * keeps nets unshifted.
  322. */
  323. in = inet_makeaddr(ifaddr.in.ia_subnet,
  324. INADDR_ANY);
  325. printf("%-13.13s ", netname(in.s_addr,
  326. ifaddr.in.ia_subnetmask));
  327. #else
  328. printf("%-13.13s ",
  329. netname(htonl(ifaddr.in.ia_subnet),
  330. ifaddr.in.ia_subnetmask));
  331. #endif
  332. printf("%-17.17s ",
  333. routename(sockin->sin_addr.s_addr));
  334. network_layer = 1;
  335. break;
  336. #ifdef INET6
  337. case AF_INET6:
  338. sockin6 = (struct sockaddr_in6 *)sa;
  339. in6_fillscopeid(&ifaddr.in6.ia_addr);
  340. printf("%-13.13s ",
  341. netname6(&ifaddr.in6.ia_addr,
  342. &ifaddr.in6.ia_prefixmask.sin6_addr));
  343. in6_fillscopeid(sockin6);
  344. getnameinfo(sa, sa->sa_len, addr_buf,
  345. sizeof(addr_buf), 0, 0, NI_NUMERICHOST);
  346. printf("%-17.17s ", addr_buf);
  347. network_layer = 1;
  348. break;
  349. #endif /*INET6*/
  350. case AF_IPX:
  351. {
  352. struct sockaddr_ipx *sipx =
  353. (struct sockaddr_ipx *)sa;
  354. u_long net;
  355. char netnum[10];
  356. *(union ipx_net *) &net = sipx->sipx_addr.x_net;
  357. sprintf(netnum, "%lx", (u_long)ntohl(net));
  358. printf("ipx:%-8s ", netnum);
  359. /* printf("ipx:%-8s ", netname(net, 0L)); */
  360. printf("%-17s ",
  361. ipx_phost((struct sockaddr *)sipx));
  362. }
  363. network_layer = 1;
  364. break;
  365. case AF_APPLETALK:
  366. printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
  367. printf("%-11.11s ",atalk_print(sa,0x0b) );
  368. break;
  369. case AF_LINK:
  370. {
  371. struct sockaddr_dl *sdl =
  372. (struct sockaddr_dl *)sa;
  373. char linknum[10];
  374. cp = (char *)LLADDR(sdl);
  375. n = sdl->sdl_alen;
  376. sprintf(linknum, "<Link#%d>", sdl->sdl_index);
  377. m = printf("%-13.13s ", linknum);
  378. }
  379. goto hexprint;
  380. default:
  381. m = printf("(%d)", sa->sa_family);
  382. for (cp = sa->sa_len + (char *)sa;
  383. --cp > sa->sa_data && (*cp == 0);) {}
  384. n = cp - sa->sa_data + 1;
  385. cp = sa->sa_data;
  386. hexprint:
  387. while ((--n >= 0) && (m < 30))
  388. m += printf("%02x%c", *cp++ & 0xff,
  389. n > 0 ? ':' : ' ');
  390. m = 32 - m;
  391. while (m-- > 0)
  392. putchar(' ');
  393. link_layer = 1;
  394. break;
  395. }
  396. /*
  397. * Fixup the statistics for interfaces that
  398. * update stats for their network addresses
  399. */
  400. if (network_layer) {
  401. opackets = ifaddr.in.ia_ifa.if_opackets;
  402. ipackets = ifaddr.in.ia_ifa.if_ipackets;
  403. obytes = ifaddr.in.ia_ifa.if_obytes;
  404. ibytes = ifaddr.in.ia_ifa.if_ibytes;
  405. }
  406. ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
  407. }
  408. show_stat("lu", 8, ipackets, link_layer|network_layer);
  409. show_stat("lu", 5, ierrors, link_layer);
  410. show_stat("lu", 5, idrops, link_layer);
  411. if (bflag)
  412. show_stat("lu", 10, ibytes, link_layer|network_layer);
  413. show_stat("lu", 8, opackets, link_layer|network_layer);
  414. show_stat("lu", 5, oerrors, link_layer);
  415. if (bflag)
  416. show_stat("lu", 10, obytes, link_layer|network_layer);
  417. show_stat("NRSlu", 5, collisions, link_layer);
  418. if (dflag)
  419. show_stat("LSd", 4, drops, link_layer);
  420. putchar('\n');
  421. if (aflag && ifaddrfound) {
  422. /*
  423. * Print family's multicast addresses
  424. */
  425. struct ifmultiaddr *multiaddr;
  426. struct ifmultiaddr ifma;
  427. union {
  428. struct sockaddr sa;
  429. struct sockaddr_in in;
  430. #ifdef INET6
  431. struct sockaddr_in6 in6;
  432. #endif /* INET6 */
  433. struct sockaddr_dl dl;
  434. } msa;
  435. const char *fmt;
  436. TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
  437. if (kread((u_long)multiaddr, (char *)&ifma,
  438. sizeof ifma) != 0)
  439. break;
  440. multiaddr = &ifma;
  441. if (kread((u_long)ifma.ifma_addr, (char *)&msa,
  442. sizeof msa) != 0)
  443. break;
  444. if (msa.sa.sa_family != sa->sa_family)
  445. continue;
  446. fmt = 0;
  447. switch (msa.sa.sa_family) {
  448. case AF_INET:
  449. fmt = routename(msa.in.sin_addr.s_addr);
  450. break;
  451. #ifdef INET6
  452. case AF_INET6:
  453. in6_fillscopeid(&msa.in6);
  454. getnameinfo(&msa.sa, msa.sa.sa_len,
  455. addr_buf, sizeof(addr_buf), 0, 0,
  456. NI_NUMERICHOST);
  457. printf("%*s %-19.19s(refs: %d)\n",
  458. Wflag ? 27 : 25, "",
  459. addr_buf, ifma.ifma_refcount);
  460. break;
  461. #endif /* INET6 */
  462. case AF_LINK:
  463. switch (msa.dl.sdl_type) {
  464. case IFT_ETHER:
  465. case IFT_FDDI:
  466. fmt = ether_ntoa(
  467. (struct ether_addr *)
  468. LLADDR(&msa.dl));
  469. break;
  470. }
  471. break;
  472. }
  473. if (fmt) {
  474. printf("%*s %-17.17s",
  475. Wflag ? 27 : 25, "", fmt);
  476. if (msa.sa.sa_family == AF_LINK) {
  477. printf(" %8lu", imcasts);
  478. printf("%*s",
  479. bflag ? 17 : 6, "");
  480. printf(" %8lu", omcasts);
  481. }
  482. putchar('\n');
  483. }
  484. }
  485. }
  486. }
  487. }
  488. struct iftot {
  489. SLIST_ENTRY(iftot) chain;
  490. char ift_name[IFNAMSIZ]; /* interface name */
  491. u_long ift_ip; /* input packets */
  492. u_long ift_ie; /* input errors */
  493. u_long ift_id; /* input drops */
  494. u_long ift_op; /* output packets */
  495. u_long ift_oe; /* output errors */
  496. u_long ift_co; /* collisions */
  497. u_int ift_dr; /* drops */
  498. u_long ift_ib; /* input bytes */
  499. u_long ift_ob; /* output bytes */
  500. };
  501. u_char signalled; /* set if alarm goes off "early" */
  502. /*
  503. * Print a running summary of interface statistics.
  504. * Repeat display every interval1 seconds, showing statistics
  505. * collected over that interval. Assumes that interval1 is non-zero.
  506. * First line printed at top of screen is always cumulative.
  507. * XXX - should be rewritten to use ifmib(4).
  508. */
  509. static void
  510. sidewaysintpr(int interval1, u_long off)
  511. {
  512. struct ifnet ifnet;
  513. u_long firstifnet;
  514. struct ifnethead ifnethead;
  515. struct itimerval interval_it;
  516. struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
  517. int line;
  518. int oldmask, first;
  519. u_long interesting_off;
  520. if (kread(off, (char *)&ifnethead, sizeof ifnethead) != 0)
  521. return;
  522. firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
  523. if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
  524. printf("malloc failed\n");
  525. exit(1);
  526. }
  527. memset(iftot, 0, sizeof(struct iftot));
  528. interesting = NULL;
  529. interesting_off = 0;
  530. for (off = firstifnet, ip = iftot; off;) {
  531. char name[IFNAMSIZ];
  532. if (kread(off, (char *)&ifnet, sizeof ifnet) != 0)
  533. break;
  534. strlcpy(name, ifnet.if_xname, sizeof(name));
  535. if (interface && strcmp(name, interface) == 0) {
  536. interesting = ip;
  537. interesting_off = off;
  538. }
  539. snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name);
  540. if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
  541. printf("malloc failed\n");
  542. exit(1);
  543. }
  544. memset(ipn, 0, sizeof(struct iftot));
  545. SLIST_NEXT(ip, chain) = ipn;
  546. ip = ipn;
  547. off = (u_long)TAILQ_NEXT(&ifnet, if_link);
  548. }
  549. if (interface && interesting == NULL)
  550. errx(1, "%s: unknown interface", interface);
  551. if ((total = malloc(sizeof(struct iftot))) == NULL) {
  552. printf("malloc failed\n");
  553. exit(1);
  554. }
  555. memset(total, 0, sizeof(struct iftot));
  556. if ((sum = malloc(sizeof(struct iftot))) == NULL) {
  557. printf("malloc failed\n");
  558. exit(1);
  559. }
  560. memset(sum, 0, sizeof(struct iftot));
  561. (void)signal(SIGALRM, catchalarm);
  562. signalled = NO;
  563. interval_it.it_interval.tv_sec = interval1;
  564. interval_it.it_interval.tv_usec = 0;
  565. interval_it.it_value = interval_it.it_interval;
  566. setitimer(ITIMER_REAL, &interval_it, NULL);
  567. first = 1;
  568. banner:
  569. printf("%17s %14s %16s", "input",
  570. interesting ? interesting->ift_name : "(Total)", "output");
  571. putchar('\n');
  572. printf("%10s %5s %5s %10s %10s %5s %10s %5s",
  573. "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes",
  574. "colls");
  575. if (dflag)
  576. printf(" %5.5s", "drops");
  577. putchar('\n');
  578. fflush(stdout);
  579. line = 0;
  580. loop:
  581. if (interesting != NULL) {
  582. ip = interesting;
  583. if (kread(interesting_off, (char *)&ifnet, sizeof ifnet) != 0) {
  584. printf("???\n");
  585. exit(1);
  586. };
  587. if (!first) {
  588. show_stat("lu", 10, ifnet.if_ipackets - ip->ift_ip, 1);
  589. show_stat("lu", 5, ifnet.if_ierrors - ip->ift_ie, 1);
  590. show_stat("lu", 5, ifnet.if_iqdrops - ip->ift_id, 1);
  591. show_stat("lu", 10, ifnet.if_ibytes - ip->ift_ib, 1);
  592. show_stat("lu", 10, ifnet.if_opackets - ip->ift_op, 1);
  593. show_stat("lu", 5, ifnet.if_oerrors - ip->ift_oe, 1);
  594. show_stat("lu", 10, ifnet.if_obytes - ip->ift_ob, 1);
  595. show_stat("NRSlu", 5,
  596. ifnet.if_collisions - ip->ift_co, 1);
  597. if (dflag)
  598. show_stat("LSu", 5,
  599. ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
  600. }
  601. ip->ift_ip = ifnet.if_ipackets;
  602. ip->ift_ie = ifnet.if_ierrors;
  603. ip->ift_id = ifnet.if_iqdrops;
  604. ip->ift_ib = ifnet.if_ibytes;
  605. ip->ift_op = ifnet.if_opackets;
  606. ip->ift_oe = ifnet.if_oerrors;
  607. ip->ift_ob = ifnet.if_obytes;
  608. ip->ift_co = ifnet.if_collisions;
  609. ip->ift_dr = ifnet.if_snd.ifq_drops;
  610. } else {
  611. sum->ift_ip = 0;
  612. sum->ift_ie = 0;
  613. sum->ift_id = 0;
  614. sum->ift_ib = 0;
  615. sum->ift_op = 0;
  616. sum->ift_oe = 0;
  617. sum->ift_ob = 0;
  618. sum->ift_co = 0;
  619. sum->ift_dr = 0;
  620. for (off = firstifnet, ip = iftot;
  621. off && SLIST_NEXT(ip, chain) != NULL;
  622. ip = SLIST_NEXT(ip, chain)) {
  623. if (kread(off, (char *)&ifnet, sizeof ifnet) != 0) {
  624. off = 0;
  625. continue;
  626. }
  627. sum->ift_ip += ifnet.if_ipackets;
  628. sum->ift_ie += ifnet.if_ierrors;
  629. sum->ift_id += ifnet.if_iqdrops;
  630. sum->ift_ib += ifnet.if_ibytes;
  631. sum->ift_op += ifnet.if_opackets;
  632. sum->ift_oe += ifnet.if_oerrors;
  633. sum->ift_ob += ifnet.if_obytes;
  634. sum->ift_co += ifnet.if_collisions;
  635. sum->ift_dr += ifnet.if_snd.ifq_drops;
  636. off = (u_long)TAILQ_NEXT(&ifnet, if_link);
  637. }
  638. if (!first) {
  639. show_stat("lu", 10, sum->ift_ip - total->ift_ip, 1);
  640. show_stat("lu", 5, sum->ift_ie - total->ift_ie, 1);
  641. show_stat("lu", 5, sum->ift_id - total->ift_id, 1);
  642. show_stat("lu", 10, sum->ift_ib - total->ift_ib, 1);
  643. show_stat("lu", 10, sum->ift_op - total->ift_op, 1);
  644. show_stat("lu", 5, sum->ift_oe - total->ift_oe, 1);
  645. show_stat("lu", 10, sum->ift_ob - total->ift_ob, 1);
  646. show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1);
  647. if (dflag)
  648. show_stat("LSu", 5,
  649. sum->ift_dr - total->ift_dr, 1);
  650. }
  651. *total = *sum;
  652. }
  653. if (!first)
  654. putchar('\n');
  655. fflush(stdout);
  656. if ((noutputs != 0) && (--noutputs == 0))
  657. exit(0);
  658. oldmask = sigblock(sigmask(SIGALRM));
  659. while (!signalled)
  660. sigpause(0);
  661. signalled = NO;
  662. sigsetmask(oldmask);
  663. line++;
  664. first = 0;
  665. if (line == 21)
  666. goto banner;
  667. else
  668. goto loop;
  669. /*NOTREACHED*/
  670. }
  671. /*
  672. * Set a flag to indicate that a signal from the periodic itimer has been
  673. * caught.
  674. */
  675. static void
  676. catchalarm(int signo __unused)
  677. {
  678. signalled = YES;
  679. }