/usr.bin/netstat/main.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 825 lines · 721 code · 42 blank · 62 comment · 168 complexity · b033237761b5407ec77dbb876278f8b8 MD5 · raw file

  1. /*-
  2. * Copyright (c) 1983, 1988, 1993
  3. * 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. #ifndef lint
  30. char const copyright[] =
  31. "@(#) Copyright (c) 1983, 1988, 1993\n\
  32. Regents of the University of California. All rights reserved.\n";
  33. #endif /* not lint */
  34. #if 0
  35. #ifndef lint
  36. static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94";
  37. #endif /* not lint */
  38. #endif
  39. #include <sys/cdefs.h>
  40. __FBSDID("$FreeBSD$");
  41. #include <sys/param.h>
  42. #include <sys/file.h>
  43. #include <sys/protosw.h>
  44. #include <sys/socket.h>
  45. #include <sys/socketvar.h>
  46. #include <netinet/in.h>
  47. #ifdef NETGRAPH
  48. #include <netgraph/ng_socket.h>
  49. #endif
  50. #include <ctype.h>
  51. #include <err.h>
  52. #include <errno.h>
  53. #include <kvm.h>
  54. #include <limits.h>
  55. #include <netdb.h>
  56. #include <nlist.h>
  57. #include <paths.h>
  58. #include <stdint.h>
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include <unistd.h>
  63. #include "netstat.h"
  64. static struct nlist nl[] = {
  65. #define N_IFNET 0
  66. { .n_name = "_ifnet" },
  67. #define N_RTSTAT 1
  68. { .n_name = "_rtstat" },
  69. #define N_RTREE 2
  70. { .n_name = "_rt_tables"},
  71. #define N_MRTSTAT 3
  72. { .n_name = "_mrtstat" },
  73. #define N_MFCHASHTBL 4
  74. { .n_name = "_mfchashtbl" },
  75. #define N_VIFTABLE 5
  76. { .n_name = "_viftable" },
  77. #define N_IPX 6
  78. { .n_name = "_ipxpcb_list"},
  79. #define N_IPXSTAT 7
  80. { .n_name = "_ipxstat"},
  81. #define N_SPXSTAT 8
  82. { .n_name = "_spx_istat"},
  83. #define N_DDPSTAT 9
  84. { .n_name = "_ddpstat"},
  85. #define N_DDPCB 10
  86. { .n_name = "_ddpcb"},
  87. #define N_NGSOCKS 11
  88. { .n_name = "_ngsocklist"},
  89. #define N_IP6STAT 12
  90. { .n_name = "_ip6stat" },
  91. #define N_ICMP6STAT 13
  92. { .n_name = "_icmp6stat" },
  93. #define N_IPSECSTAT 14
  94. { .n_name = "_ipsec4stat" },
  95. #define N_IPSEC6STAT 15
  96. { .n_name = "_ipsec6stat" },
  97. #define N_PIM6STAT 16
  98. { .n_name = "_pim6stat" },
  99. #define N_MRT6STAT 17
  100. { .n_name = "_mrt6stat" },
  101. #define N_MF6CTABLE 18
  102. { .n_name = "_mf6ctable" },
  103. #define N_MIF6TABLE 19
  104. { .n_name = "_mif6table" },
  105. #define N_PFKEYSTAT 20
  106. { .n_name = "_pfkeystat" },
  107. #define N_MBSTAT 21
  108. { .n_name = "_mbstat" },
  109. #define N_MBTYPES 22
  110. { .n_name = "_mbtypes" },
  111. #define N_NMBCLUSTERS 23
  112. { .n_name = "_nmbclusters" },
  113. #define N_NMBUFS 24
  114. { .n_name = "_nmbufs" },
  115. #define N_MBHI 25
  116. { .n_name = "_mbuf_hiwm" },
  117. #define N_CLHI 26
  118. { .n_name = "_clust_hiwm" },
  119. #define N_NCPUS 27
  120. { .n_name = "_smp_cpus" },
  121. #define N_PAGESZ 28
  122. { .n_name = "_pagesize" },
  123. #define N_MBPSTAT 29
  124. { .n_name = "_mb_statpcpu" },
  125. #define N_RTTRASH 30
  126. { .n_name = "_rttrash" },
  127. #define N_MBLO 31
  128. { .n_name = "_mbuf_lowm" },
  129. #define N_CLLO 32
  130. { .n_name = "_clust_lowm" },
  131. #define N_CARPSTAT 33
  132. { .n_name = "_carpstats" },
  133. #define N_PFSYNCSTAT 34
  134. { .n_name = "_pfsyncstats" },
  135. #define N_AHSTAT 35
  136. { .n_name = "_ahstat" },
  137. #define N_ESPSTAT 36
  138. { .n_name = "_espstat" },
  139. #define N_IPCOMPSTAT 37
  140. { .n_name = "_ipcompstat" },
  141. #define N_TCPSTAT 38
  142. { .n_name = "_tcpstat" },
  143. #define N_UDPSTAT 39
  144. { .n_name = "_udpstat" },
  145. #define N_IPSTAT 40
  146. { .n_name = "_ipstat" },
  147. #define N_ICMPSTAT 41
  148. { .n_name = "_icmpstat" },
  149. #define N_IGMPSTAT 42
  150. { .n_name = "_igmpstat" },
  151. #define N_PIMSTAT 43
  152. { .n_name = "_pimstat" },
  153. #define N_TCBINFO 44
  154. { .n_name = "_tcbinfo" },
  155. #define N_UDBINFO 45
  156. { .n_name = "_udbinfo" },
  157. #define N_DIVCBINFO 46
  158. { .n_name = "_divcbinfo" },
  159. #define N_RIPCBINFO 47
  160. { .n_name = "_ripcbinfo" },
  161. #define N_UNP_COUNT 48
  162. { .n_name = "_unp_count" },
  163. #define N_UNP_GENCNT 49
  164. { .n_name = "_unp_gencnt" },
  165. #define N_UNP_DHEAD 50
  166. { .n_name = "_unp_dhead" },
  167. #define N_UNP_SHEAD 51
  168. { .n_name = "_unp_shead" },
  169. #define N_RIP6STAT 52
  170. { .n_name = "_rip6stat" },
  171. #define N_SCTPSTAT 53
  172. { .n_name = "_sctpstat" },
  173. #define N_MFCTABLESIZE 54
  174. { .n_name = "_mfctablesize" },
  175. #define N_ARPSTAT 55
  176. { .n_name = "_arpstat" },
  177. #define N_UNP_SPHEAD 56
  178. { .n_name = "unp_sphead" },
  179. { .n_name = NULL },
  180. };
  181. struct protox {
  182. int pr_index; /* index into nlist of cb head */
  183. int pr_sindex; /* index into nlist of stat block */
  184. u_char pr_wanted; /* 1 if wanted, 0 otherwise */
  185. void (*pr_cblocks)(u_long, const char *, int, int);
  186. /* control blocks printing routine */
  187. void (*pr_stats)(u_long, const char *, int, int);
  188. /* statistics printing routine */
  189. void (*pr_istats)(char *); /* per/if statistics printing routine */
  190. const char *pr_name; /* well-known name */
  191. int pr_usesysctl; /* non-zero if we use sysctl, not kvm */
  192. int pr_protocol;
  193. } protox[] = {
  194. { N_TCBINFO, N_TCPSTAT, 1, protopr,
  195. tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
  196. { N_UDBINFO, N_UDPSTAT, 1, protopr,
  197. udp_stats, NULL, "udp", 1, IPPROTO_UDP },
  198. #ifdef SCTP
  199. { -1, N_SCTPSTAT, 1, sctp_protopr,
  200. sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP },
  201. #endif
  202. #ifdef SDP
  203. { -1, -1, 1, protopr,
  204. NULL, NULL, "sdp", 1, IPPROTO_TCP },
  205. #endif
  206. { N_DIVCBINFO, -1, 1, protopr,
  207. NULL, NULL, "divert", 1, IPPROTO_DIVERT },
  208. { N_RIPCBINFO, N_IPSTAT, 1, protopr,
  209. ip_stats, NULL, "ip", 1, IPPROTO_RAW },
  210. { N_RIPCBINFO, N_ICMPSTAT, 1, protopr,
  211. icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP },
  212. { N_RIPCBINFO, N_IGMPSTAT, 1, protopr,
  213. igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
  214. #ifdef IPSEC
  215. { -1, N_IPSECSTAT, 1, NULL, /* keep as compat */
  216. ipsec_stats, NULL, "ipsec", 0, 0},
  217. { -1, N_AHSTAT, 1, NULL,
  218. ah_stats, NULL, "ah", 0, 0},
  219. { -1, N_ESPSTAT, 1, NULL,
  220. esp_stats, NULL, "esp", 0, 0},
  221. { -1, N_IPCOMPSTAT, 1, NULL,
  222. ipcomp_stats, NULL, "ipcomp", 0, 0},
  223. #endif
  224. { N_RIPCBINFO, N_PIMSTAT, 1, protopr,
  225. pim_stats, NULL, "pim", 1, IPPROTO_PIM },
  226. { -1, N_CARPSTAT, 1, NULL,
  227. carp_stats, NULL, "carp", 1, 0 },
  228. { -1, N_PFSYNCSTAT, 1, NULL,
  229. pfsync_stats, NULL, "pfsync", 1, 0 },
  230. { -1, N_ARPSTAT, 1, NULL,
  231. arp_stats, NULL, "arp", 1, 0 },
  232. { -1, -1, 0, NULL,
  233. NULL, NULL, NULL, 0, 0 }
  234. };
  235. #ifdef INET6
  236. struct protox ip6protox[] = {
  237. { N_TCBINFO, N_TCPSTAT, 1, protopr,
  238. tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
  239. { N_UDBINFO, N_UDPSTAT, 1, protopr,
  240. udp_stats, NULL, "udp", 1, IPPROTO_UDP },
  241. { N_RIPCBINFO, N_IP6STAT, 1, protopr,
  242. ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW },
  243. { N_RIPCBINFO, N_ICMP6STAT, 1, protopr,
  244. icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 },
  245. #ifdef SDP
  246. { -1, -1, 1, protopr,
  247. NULL, NULL, "sdp", 1, IPPROTO_TCP },
  248. #endif
  249. #ifdef IPSEC
  250. { -1, N_IPSEC6STAT, 1, NULL,
  251. ipsec_stats, NULL, "ipsec6", 0, 0 },
  252. #endif
  253. #ifdef notyet
  254. { -1, N_PIM6STAT, 1, NULL,
  255. pim6_stats, NULL, "pim6", 1, 0 },
  256. #endif
  257. { -1, N_RIP6STAT, 1, NULL,
  258. rip6_stats, NULL, "rip6", 1, 0 },
  259. { -1, -1, 0, NULL,
  260. NULL, NULL, NULL, 0, 0 }
  261. };
  262. #endif /*INET6*/
  263. #ifdef IPSEC
  264. struct protox pfkeyprotox[] = {
  265. { -1, N_PFKEYSTAT, 1, NULL,
  266. pfkey_stats, NULL, "pfkey", 0, 0 },
  267. { -1, -1, 0, NULL,
  268. NULL, NULL, NULL, 0, 0 }
  269. };
  270. #endif
  271. struct protox atalkprotox[] = {
  272. { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
  273. ddp_stats, NULL, "ddp", 0, 0 },
  274. { -1, -1, 0, NULL,
  275. NULL, NULL, NULL, 0, 0 }
  276. };
  277. #ifdef NETGRAPH
  278. struct protox netgraphprotox[] = {
  279. { N_NGSOCKS, -1, 1, netgraphprotopr,
  280. NULL, NULL, "ctrl", 0, 0 },
  281. { N_NGSOCKS, -1, 1, netgraphprotopr,
  282. NULL, NULL, "data", 0, 0 },
  283. { -1, -1, 0, NULL,
  284. NULL, NULL, NULL, 0, 0 }
  285. };
  286. #endif
  287. #ifdef IPX
  288. struct protox ipxprotox[] = {
  289. { N_IPX, N_IPXSTAT, 1, ipxprotopr,
  290. ipx_stats, NULL, "ipx", 0, 0 },
  291. { N_IPX, N_SPXSTAT, 1, ipxprotopr,
  292. spx_stats, NULL, "spx", 0, 0 },
  293. { -1, -1, 0, NULL,
  294. NULL, NULL, 0, 0, 0 }
  295. };
  296. #endif
  297. struct protox *protoprotox[] = {
  298. protox,
  299. #ifdef INET6
  300. ip6protox,
  301. #endif
  302. #ifdef IPSEC
  303. pfkeyprotox,
  304. #endif
  305. #ifdef IPX
  306. ipxprotox,
  307. #endif
  308. atalkprotox, NULL };
  309. static void printproto(struct protox *, const char *);
  310. static void usage(void);
  311. static struct protox *name2protox(const char *);
  312. static struct protox *knownname(const char *);
  313. static kvm_t *kvmd;
  314. static char *nlistf = NULL, *memf = NULL;
  315. int Aflag; /* show addresses of protocol control block */
  316. int aflag; /* show all sockets (including servers) */
  317. int Bflag; /* show information about bpf consumers */
  318. int bflag; /* show i/f total bytes in/out */
  319. int dflag; /* show i/f dropped packets */
  320. int gflag; /* show group (multicast) routing or stats */
  321. int hflag; /* show counters in human readable format */
  322. int iflag; /* show interfaces */
  323. int Lflag; /* show size of listen queues */
  324. int mflag; /* show memory stats */
  325. int noutputs = 0; /* how much outputs before we exit */
  326. int numeric_addr; /* show addresses numerically */
  327. int numeric_port; /* show ports numerically */
  328. static int pflag; /* show given protocol */
  329. int Qflag; /* show netisr information */
  330. int rflag; /* show routing tables (or routing stats) */
  331. int sflag; /* show protocol statistics */
  332. int Wflag; /* wide display */
  333. int Tflag; /* TCP Information */
  334. int xflag; /* extra information, includes all socket buffer info */
  335. int zflag; /* zero stats */
  336. int interval; /* repeat interval for i/f stats */
  337. char *interface; /* desired i/f for stats, or NULL for all i/fs */
  338. int unit; /* unit number for above */
  339. int af; /* address family */
  340. int live; /* true if we are examining a live system */
  341. int
  342. main(int argc, char *argv[])
  343. {
  344. struct protox *tp = NULL; /* for printing cblocks & stats */
  345. int ch;
  346. af = AF_UNSPEC;
  347. while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:Qq:rSTsuWw:xz"))
  348. != -1)
  349. switch(ch) {
  350. case 'A':
  351. Aflag = 1;
  352. break;
  353. case 'a':
  354. aflag = 1;
  355. break;
  356. case 'B':
  357. Bflag = 1;
  358. break;
  359. case 'b':
  360. bflag = 1;
  361. break;
  362. case 'd':
  363. dflag = 1;
  364. break;
  365. case 'f':
  366. if (strcmp(optarg, "ipx") == 0)
  367. af = AF_IPX;
  368. else if (strcmp(optarg, "inet") == 0)
  369. af = AF_INET;
  370. #ifdef INET6
  371. else if (strcmp(optarg, "inet6") == 0)
  372. af = AF_INET6;
  373. #endif
  374. #ifdef IPSEC
  375. else if (strcmp(optarg, "pfkey") == 0)
  376. af = PF_KEY;
  377. #endif
  378. else if (strcmp(optarg, "unix") == 0)
  379. af = AF_UNIX;
  380. else if (strcmp(optarg, "atalk") == 0)
  381. af = AF_APPLETALK;
  382. #ifdef NETGRAPH
  383. else if (strcmp(optarg, "ng") == 0
  384. || strcmp(optarg, "netgraph") == 0)
  385. af = AF_NETGRAPH;
  386. #endif
  387. else if (strcmp(optarg, "link") == 0)
  388. af = AF_LINK;
  389. else {
  390. errx(1, "%s: unknown address family", optarg);
  391. }
  392. break;
  393. case 'g':
  394. gflag = 1;
  395. break;
  396. case 'h':
  397. hflag = 1;
  398. break;
  399. case 'I': {
  400. char *cp;
  401. iflag = 1;
  402. for (cp = interface = optarg; isalpha(*cp); cp++)
  403. continue;
  404. unit = atoi(cp);
  405. break;
  406. }
  407. case 'i':
  408. iflag = 1;
  409. break;
  410. case 'L':
  411. Lflag = 1;
  412. break;
  413. case 'M':
  414. memf = optarg;
  415. break;
  416. case 'm':
  417. mflag = 1;
  418. break;
  419. case 'N':
  420. nlistf = optarg;
  421. break;
  422. case 'n':
  423. numeric_addr = numeric_port = 1;
  424. break;
  425. case 'p':
  426. if ((tp = name2protox(optarg)) == NULL) {
  427. errx(1,
  428. "%s: unknown or uninstrumented protocol",
  429. optarg);
  430. }
  431. pflag = 1;
  432. break;
  433. case 'Q':
  434. Qflag = 1;
  435. break;
  436. case 'q':
  437. noutputs = atoi(optarg);
  438. if (noutputs != 0)
  439. noutputs++;
  440. break;
  441. case 'r':
  442. rflag = 1;
  443. break;
  444. case 's':
  445. ++sflag;
  446. break;
  447. case 'S':
  448. numeric_addr = 1;
  449. break;
  450. case 'u':
  451. af = AF_UNIX;
  452. break;
  453. case 'W':
  454. case 'l':
  455. Wflag = 1;
  456. break;
  457. case 'w':
  458. interval = atoi(optarg);
  459. iflag = 1;
  460. break;
  461. case 'T':
  462. Tflag = 1;
  463. break;
  464. case 'x':
  465. xflag = 1;
  466. break;
  467. case 'z':
  468. zflag = 1;
  469. break;
  470. case '?':
  471. default:
  472. usage();
  473. }
  474. argv += optind;
  475. argc -= optind;
  476. #define BACKWARD_COMPATIBILITY
  477. #ifdef BACKWARD_COMPATIBILITY
  478. if (*argv) {
  479. if (isdigit(**argv)) {
  480. interval = atoi(*argv);
  481. if (interval <= 0)
  482. usage();
  483. ++argv;
  484. iflag = 1;
  485. }
  486. if (*argv) {
  487. nlistf = *argv;
  488. if (*++argv)
  489. memf = *argv;
  490. }
  491. }
  492. #endif
  493. /*
  494. * Discard setgid privileges if not the running kernel so that bad
  495. * guys can't print interesting stuff from kernel memory.
  496. */
  497. live = (nlistf == NULL && memf == NULL);
  498. if (!live)
  499. setgid(getgid());
  500. if (xflag && Tflag)
  501. errx(1, "-x and -T are incompatible, pick one.");
  502. if (Bflag) {
  503. if (!live)
  504. usage();
  505. bpf_stats(interface);
  506. exit(0);
  507. }
  508. if (mflag) {
  509. if (!live) {
  510. if (kread(0, NULL, 0) == 0)
  511. mbpr(kvmd, nl[N_MBSTAT].n_value);
  512. } else
  513. mbpr(NULL, 0);
  514. exit(0);
  515. }
  516. if (Qflag) {
  517. if (!live) {
  518. if (kread(0, NULL, 0) == 0)
  519. netisr_stats(kvmd);
  520. } else
  521. netisr_stats(NULL);
  522. exit(0);
  523. }
  524. #if 0
  525. /*
  526. * Keep file descriptors open to avoid overhead
  527. * of open/close on each call to get* routines.
  528. */
  529. sethostent(1);
  530. setnetent(1);
  531. #else
  532. /*
  533. * This does not make sense any more with DNS being default over
  534. * the files. Doing a setXXXXent(1) causes a tcp connection to be
  535. * used for the queries, which is slower.
  536. */
  537. #endif
  538. kread(0, NULL, 0);
  539. if (iflag && !sflag) {
  540. intpr(interval, nl[N_IFNET].n_value, NULL);
  541. exit(0);
  542. }
  543. if (rflag) {
  544. if (sflag)
  545. rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
  546. else
  547. routepr(nl[N_RTREE].n_value);
  548. exit(0);
  549. }
  550. if (gflag) {
  551. if (sflag) {
  552. if (af == AF_INET || af == AF_UNSPEC)
  553. mrt_stats(nl[N_MRTSTAT].n_value);
  554. #ifdef INET6
  555. if (af == AF_INET6 || af == AF_UNSPEC)
  556. mrt6_stats(nl[N_MRT6STAT].n_value);
  557. #endif
  558. } else {
  559. if (af == AF_INET || af == AF_UNSPEC)
  560. mroutepr(nl[N_MFCHASHTBL].n_value,
  561. nl[N_MFCTABLESIZE].n_value,
  562. nl[N_VIFTABLE].n_value);
  563. #ifdef INET6
  564. if (af == AF_INET6 || af == AF_UNSPEC)
  565. mroute6pr(nl[N_MF6CTABLE].n_value,
  566. nl[N_MIF6TABLE].n_value);
  567. #endif
  568. }
  569. exit(0);
  570. }
  571. if (tp) {
  572. printproto(tp, tp->pr_name);
  573. exit(0);
  574. }
  575. if (af == AF_INET || af == AF_UNSPEC)
  576. for (tp = protox; tp->pr_name; tp++)
  577. printproto(tp, tp->pr_name);
  578. #ifdef INET6
  579. if (af == AF_INET6 || af == AF_UNSPEC)
  580. for (tp = ip6protox; tp->pr_name; tp++)
  581. printproto(tp, tp->pr_name);
  582. #endif /*INET6*/
  583. #ifdef IPSEC
  584. if (af == PF_KEY || af == AF_UNSPEC)
  585. for (tp = pfkeyprotox; tp->pr_name; tp++)
  586. printproto(tp, tp->pr_name);
  587. #endif /*IPSEC*/
  588. #ifdef IPX
  589. if (af == AF_IPX || af == AF_UNSPEC) {
  590. for (tp = ipxprotox; tp->pr_name; tp++)
  591. printproto(tp, tp->pr_name);
  592. }
  593. #endif /* IPX */
  594. if (af == AF_APPLETALK || af == AF_UNSPEC)
  595. for (tp = atalkprotox; tp->pr_name; tp++)
  596. printproto(tp, tp->pr_name);
  597. #ifdef NETGRAPH
  598. if (af == AF_NETGRAPH || af == AF_UNSPEC)
  599. for (tp = netgraphprotox; tp->pr_name; tp++)
  600. printproto(tp, tp->pr_name);
  601. #endif /* NETGRAPH */
  602. if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
  603. unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
  604. nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value,
  605. nl[N_UNP_SPHEAD].n_value);
  606. exit(0);
  607. }
  608. /*
  609. * Print out protocol statistics or control blocks (per sflag).
  610. * If the interface was not specifically requested, and the symbol
  611. * is not in the namelist, ignore this one.
  612. */
  613. static void
  614. printproto(tp, name)
  615. struct protox *tp;
  616. const char *name;
  617. {
  618. void (*pr)(u_long, const char *, int, int);
  619. u_long off;
  620. if (sflag) {
  621. if (iflag) {
  622. if (tp->pr_istats)
  623. intpr(interval, nl[N_IFNET].n_value,
  624. tp->pr_istats);
  625. else if (pflag)
  626. printf("%s: no per-interface stats routine\n",
  627. tp->pr_name);
  628. return;
  629. } else {
  630. pr = tp->pr_stats;
  631. if (!pr) {
  632. if (pflag)
  633. printf("%s: no stats routine\n",
  634. tp->pr_name);
  635. return;
  636. }
  637. if (tp->pr_usesysctl && live)
  638. off = 0;
  639. else if (tp->pr_sindex < 0) {
  640. if (pflag)
  641. printf(
  642. "%s: stats routine doesn't work on cores\n",
  643. tp->pr_name);
  644. return;
  645. } else
  646. off = nl[tp->pr_sindex].n_value;
  647. }
  648. } else {
  649. pr = tp->pr_cblocks;
  650. if (!pr) {
  651. if (pflag)
  652. printf("%s: no PCB routine\n", tp->pr_name);
  653. return;
  654. }
  655. if (tp->pr_usesysctl && live)
  656. off = 0;
  657. else if (tp->pr_index < 0) {
  658. if (pflag)
  659. printf(
  660. "%s: PCB routine doesn't work on cores\n",
  661. tp->pr_name);
  662. return;
  663. } else
  664. off = nl[tp->pr_index].n_value;
  665. }
  666. if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
  667. af != AF_UNSPEC))
  668. (*pr)(off, name, af, tp->pr_protocol);
  669. }
  670. /*
  671. * Read kernel memory, return 0 on success.
  672. */
  673. int
  674. kread(u_long addr, void *buf, size_t size)
  675. {
  676. char errbuf[_POSIX2_LINE_MAX];
  677. if (kvmd == NULL) {
  678. kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
  679. setgid(getgid());
  680. if (kvmd != NULL) {
  681. if (kvm_nlist(kvmd, nl) < 0) {
  682. if (nlistf)
  683. errx(1, "%s: kvm_nlist: %s", nlistf,
  684. kvm_geterr(kvmd));
  685. else
  686. errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
  687. }
  688. if (nl[0].n_type == 0) {
  689. if (nlistf)
  690. errx(1, "%s: no namelist", nlistf);
  691. else
  692. errx(1, "no namelist");
  693. }
  694. } else {
  695. warnx("kvm not available: %s", errbuf);
  696. return(-1);
  697. }
  698. }
  699. if (!buf)
  700. return (0);
  701. if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
  702. warnx("%s", kvm_geterr(kvmd));
  703. return (-1);
  704. }
  705. return (0);
  706. }
  707. const char *
  708. plural(uintmax_t n)
  709. {
  710. return (n != 1 ? "s" : "");
  711. }
  712. const char *
  713. plurales(uintmax_t n)
  714. {
  715. return (n != 1 ? "es" : "");
  716. }
  717. const char *
  718. pluralies(uintmax_t n)
  719. {
  720. return (n != 1 ? "ies" : "y");
  721. }
  722. /*
  723. * Find the protox for the given "well-known" name.
  724. */
  725. static struct protox *
  726. knownname(const char *name)
  727. {
  728. struct protox **tpp, *tp;
  729. for (tpp = protoprotox; *tpp; tpp++)
  730. for (tp = *tpp; tp->pr_name; tp++)
  731. if (strcmp(tp->pr_name, name) == 0)
  732. return (tp);
  733. return (NULL);
  734. }
  735. /*
  736. * Find the protox corresponding to name.
  737. */
  738. static struct protox *
  739. name2protox(const char *name)
  740. {
  741. struct protox *tp;
  742. char **alias; /* alias from p->aliases */
  743. struct protoent *p;
  744. /*
  745. * Try to find the name in the list of "well-known" names. If that
  746. * fails, check if name is an alias for an Internet protocol.
  747. */
  748. if ((tp = knownname(name)) != NULL)
  749. return (tp);
  750. setprotoent(1); /* make protocol lookup cheaper */
  751. while ((p = getprotoent()) != NULL) {
  752. /* assert: name not same as p->name */
  753. for (alias = p->p_aliases; *alias; alias++)
  754. if (strcmp(name, *alias) == 0) {
  755. endprotoent();
  756. return (knownname(p->p_name));
  757. }
  758. }
  759. endprotoent();
  760. return (NULL);
  761. }
  762. static void
  763. usage(void)
  764. {
  765. (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
  766. "usage: netstat [-AaLnSTWx] [-f protocol_family | -p protocol]\n"
  767. " [-M core] [-N system]",
  768. " netstat -i | -I interface [-abdhnW] [-f address_family]\n"
  769. " [-M core] [-N system]",
  770. " netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]",
  771. " netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n"
  772. " [-M core] [-N system]",
  773. " netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
  774. " [-M core] [-N system]",
  775. " netstat -m [-M core] [-N system]",
  776. " netstat -B [-I interface]",
  777. " netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
  778. " netstat -rs [-s] [-M core] [-N system]",
  779. " netstat -g [-W] [-f address_family] [-M core] [-N system]",
  780. " netstat -gs [-s] [-f address_family] [-M core] [-N system]",
  781. " netstat -Q");
  782. exit(1);
  783. }