PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/net-snmp-5.7.1/apps/snmpnetstat/main.c

#
C | 539 lines | 319 code | 40 blank | 180 comment | 59 complexity | 31bb8c380642502d8c4ec656d889bea0 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /* $OpenBSD: main.c,v 1.52 2005/02/10 14:25:08 itojun Exp $ */
  2. /* $NetBSD: main.c,v 1.9 1996/05/07 02:55:02 thorpej Exp $ */
  3. /*
  4. * Copyright (c) 1983, 1988, 1993
  5. * Regents of the University of California. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the University nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. #ifndef lint
  32. char copyright[] =
  33. "@(#) Copyright (c) 1983, 1988, 1993\n\
  34. Regents of the University of California. All rights reserved.\n";
  35. #endif /* not lint */
  36. #ifdef INHERITED_CODE
  37. #ifndef lint
  38. #if 0
  39. static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94";
  40. #else
  41. static char *rcsid = "$OpenBSD: main.c,v 1.52 2005/02/10 14:25:08 itojun Exp $";
  42. #endif
  43. #endif /* not lint */
  44. #endif
  45. #include <net-snmp/net-snmp-config.h>
  46. #include <net-snmp/net-snmp-includes.h>
  47. #include <net-snmp/utilities.h>
  48. #if HAVE_NETDB_H
  49. #include <netdb.h>
  50. #endif
  51. #include "main.h"
  52. #include "netstat.h"
  53. #if HAVE_WINSOCK_H
  54. #include "winstub.h"
  55. #endif
  56. int Aflag; /* show addresses of protocol control block */
  57. int aflag; /* show all sockets (including servers) */
  58. int bflag; /* show bytes instead of packets */
  59. int dflag; /* show i/f dropped packets */
  60. int gflag; /* show group (multicast) routing or stats */
  61. int iflag; /* show interfaces */
  62. int lflag; /* show routing table with use and ref */
  63. int mflag; /* show memory stats */
  64. int nflag; /* show addresses numerically */
  65. int oflag; /* Open/Net-BSD style octet output */
  66. int pflag; /* show given protocol */
  67. int qflag; /* only display non-zero values for output */
  68. int rflag; /* show routing tables (or routing stats) */
  69. int Sflag; /* show source address in routing table */
  70. int sflag; /* show protocol statistics */
  71. int tflag; /* show i/f watchdog timers */
  72. int vflag; /* be verbose */
  73. int interval; /* repeat interval for i/f stats */
  74. char *intrface; /* desired i/f for stats, or NULL for all i/fs */
  75. int af; /* address family */
  76. int max_getbulk = 32; /* specifies the max-repeaters value to use with GETBULK requests */
  77. char *progname = NULL;
  78. /*
  79. * struct nlist nl[] - Omitted
  80. */
  81. typedef void (stringfun)(const char*);
  82. struct protox {
  83. /* pr_index/pr_sindex - Omitted */
  84. int pr_wanted; /* 1 if wanted, 0 otherwise */
  85. stringfun *pr_cblocks; /* control blocks printing routine */
  86. stringfun *pr_stats; /* statistics printing routine */
  87. const char *pr_name; /* well-known name */
  88. } protox[] = {
  89. { 1, tcpprotopr, tcp_stats, "tcp" },
  90. { 1, udpprotopr, udp_stats, "udp" },
  91. { 1, (stringfun*)0, ip_stats, "ip" }, /* protopr Omitted */
  92. { 1, (stringfun*)0, icmp_stats, "icmp" },
  93. /* igmp/ah/esp/ipencap/etherip/ipcomp/carp/pfsync/pim - Omitted */
  94. { 0, (stringfun*)0, (stringfun*)0, NULL }
  95. };
  96. struct protox ip6protox[] = {
  97. { 1, tcp6protopr, (stringfun*)0, "tcp6" },
  98. { 1, udp6protopr, (stringfun*)0, "udp6" },
  99. { 1, (stringfun*)0, ip6_stats, "ip6" },/* ip6protopr Omitted */
  100. { 1, (stringfun*)0, icmp6_stats, "icmp6" },
  101. /* pim6/rip6 - Omitted */
  102. { 0, (stringfun*)0, (stringfun*)0, NULL }
  103. };
  104. /* {ipx,ns,atalk}protox Omitted */
  105. struct protox *protoprotox[] = {
  106. protox, ip6protox, NULL
  107. };
  108. static void printproto(struct protox *, const char *);
  109. static void usage(void);
  110. static struct protox *name2protox(const char *);
  111. static struct protox *knownname(const char *);
  112. netsnmp_session *ss;
  113. struct protox *tp = NULL; /* for printing cblocks & stats */
  114. static void
  115. optProc( int argc, char *const *argv, int opt )
  116. {
  117. switch (opt) {
  118. case 'C':
  119. while (*optarg) {
  120. switch (*optarg++) {
  121. /* case 'A': *BSD: display PCB addresses
  122. Linux: protocol family
  123. Aflag = 1;
  124. break;
  125. */
  126. case 'a':
  127. aflag = 1;
  128. break;
  129. case 'b':
  130. bflag = 1;
  131. break;
  132. case 'd':
  133. dflag = 1;
  134. break;
  135. case 'f':
  136. if (!*optarg)
  137. optarg = argv[optind++];
  138. if (strcmp(optarg, "inet") == 0)
  139. af = AF_INET;
  140. else if (strcmp(optarg, "inet6") == 0)
  141. af = AF_INET6;
  142. /*
  143. else if (strcmp(optarg, "local") == 0)
  144. af = AF_LOCAL;
  145. else if (strcmp(optarg, "unix") == 0)
  146. af = AF_UNIX;
  147. else if (strcmp(optarg, "ipx") == 0)
  148. af = AF_IPX;
  149. else if (strcmp(optarg, "ns") == 0)
  150. af = AF_NS;
  151. else if (strcmp(optarg, "encap") == 0)
  152. af = PF_KEY;
  153. else if (strcmp(optarg, "atalk") == 0)
  154. af = AF_APPLETALK;
  155. */
  156. else {
  157. (void)fprintf(stderr,
  158. "%s: %s: unknown address family\n",
  159. progname, optarg);
  160. exit(1);
  161. }
  162. return;
  163. case 'g':
  164. gflag = 1;
  165. break;
  166. case 'I':
  167. iflag = 1;
  168. if (!*optarg)
  169. optarg = argv[optind++];
  170. intrface = optarg;
  171. return;
  172. case 'i':
  173. iflag = 1;
  174. break;
  175. /* case 'L': FreeBSD: Display listen queue lengths
  176. NetBSD: Suppress link-level routes */
  177. /* case 'l': OpenBSD: Wider IPv6 display
  178. Linux: Listening sockets only
  179. lflag = 1;
  180. break;
  181. case 'M': *BSD: Memory image
  182. Linux: Masqueraded connections
  183. memf = optarg;
  184. break;
  185. */
  186. case 'm':
  187. mflag = 1;
  188. break;
  189. /* case 'N': *BSD: Kernel image
  190. nlistf = optarg;
  191. break;
  192. */
  193. case 'n':
  194. nflag = 1;
  195. break;
  196. case 'o':
  197. oflag = 1;
  198. break;
  199. /* case 'P': NetBSD:
  200. OpenBSD: dump PCB block */
  201. case 'p':
  202. if (!*optarg)
  203. optarg = argv[optind++];
  204. if ((tp = name2protox(optarg)) == NULL) {
  205. (void)fprintf(stderr,
  206. "%s: %s: unknown protocol\n",
  207. progname, optarg);
  208. exit(1);
  209. }
  210. pflag = 1;
  211. return;
  212. /* case 'q': NetBSD: IRQ information
  213. OpenBSD: Suppress inactive I/Fs
  214. qflag = 1;
  215. break;
  216. */
  217. case 'r':
  218. rflag = 1;
  219. break;
  220. case 'R':
  221. if (optind < argc) {
  222. if (argv[optind]) {
  223. max_getbulk = atoi(argv[optind]);
  224. if (max_getbulk == 0) {
  225. usage();
  226. fprintf(stderr, "Bad -CR option: %s\n",
  227. argv[optind]);
  228. exit(1);
  229. }
  230. }
  231. } else {
  232. usage();
  233. fprintf(stderr, "Bad -CR option: no argument given\n");
  234. exit(1);
  235. }
  236. optind++;
  237. break;
  238. case 'S': /* FreeBSD:
  239. NetBSD: Semi-numeric display
  240. OpenBSD: Show route source selector */
  241. Sflag = 1;
  242. break;
  243. case 's':
  244. ++sflag;
  245. break;
  246. /* case 't': FreeBSD:
  247. OpenBSD: Display watchdog timers
  248. tflag = 1;
  249. break;
  250. case 'u': OpenBSD: unix sockets only
  251. af = AF_UNIX;
  252. break;
  253. */
  254. case 'v':
  255. vflag = 1;
  256. break;
  257. case 'w':
  258. if (!*optarg)
  259. optarg = argv[optind++];
  260. interval = atoi(optarg);
  261. iflag = 1;
  262. return;
  263. case '?':
  264. default:
  265. usage();
  266. }
  267. }
  268. break; /* End of '-Cx' switch */
  269. /*
  270. * Backward compatability for the main display modes
  271. * (where this doesn't clash with standard SNMP flags)
  272. */
  273. case 'i':
  274. iflag = 1;
  275. break;
  276. case 'R':
  277. rflag = 1; /* -r sets the retry count */
  278. break;
  279. case 's':
  280. ++sflag;
  281. break;
  282. }
  283. }
  284. int
  285. main(int argc, char *argv[])
  286. {
  287. netsnmp_session session;
  288. struct protoent *p;
  289. char *cp;
  290. af = AF_UNSPEC;
  291. cp = strrchr( argv[0], '/' );
  292. if (cp)
  293. progname = cp+1;
  294. else
  295. progname = argv[0];
  296. switch (snmp_parse_args( argc, argv, &session, "C:iRs", optProc)) {
  297. case NETSNMP_PARSE_ARGS_ERROR:
  298. exit(1);
  299. case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
  300. exit(0);
  301. case NETSNMP_PARSE_ARGS_ERROR_USAGE:
  302. usage();
  303. exit(1);
  304. default:
  305. break;
  306. }
  307. /*
  308. * Check argc vs optind ??
  309. */
  310. argv += optind;
  311. argc -= optind;
  312. /*
  313. * Open an SNMP session.
  314. */
  315. SOCK_STARTUP;
  316. ss = snmp_open(&session);
  317. if (ss == NULL) {
  318. /*
  319. * diagnose snmp_open errors with the input netsnmp_session pointer
  320. */
  321. snmp_sess_perror("snmpnetstat", &session);
  322. SOCK_CLEANUP;
  323. exit(1);
  324. }
  325. /*
  326. * Omitted:
  327. * Privilege handling
  328. * "Backward Compatibility"
  329. * Kernel namelis handling
  330. */
  331. if (mflag) {
  332. /*
  333. mbpr(nl[N_MBSTAT].n_value, nl[N_MBPOOL].n_value,
  334. nl[N_MCLPOOL].n_value);
  335. */
  336. exit(0);
  337. }
  338. if (pflag) {
  339. printproto(tp, tp->pr_name);
  340. exit(0);
  341. }
  342. /*
  343. * Keep file descriptors open to avoid overhead
  344. * of open/close on each call to get* routines.
  345. */
  346. sethostent(1);
  347. setnetent(1);
  348. if (iflag) {
  349. intpr(interval);
  350. exit(0);
  351. }
  352. if (rflag) {
  353. /*
  354. if (sflag)
  355. rt_stats();
  356. else
  357. */
  358. routepr();
  359. exit(0);
  360. }
  361. /*
  362. if (gflag) {
  363. if (sflag) {
  364. if (af == AF_INET || af == AF_UNSPEC)
  365. mrt_stats(nl[N_MRTPROTO].n_value,
  366. nl[N_MRTSTAT].n_value);
  367. #ifdef NETSNMP_ENABLE_IPV6
  368. if (af == AF_INET6 || af == AF_UNSPEC)
  369. mrt6_stats(nl[N_MRT6PROTO].n_value,
  370. nl[N_MRT6STAT].n_value);
  371. #endif
  372. }
  373. else {
  374. if (af == AF_INET || af == AF_UNSPEC)
  375. mroutepr(nl[N_MRTPROTO].n_value,
  376. nl[N_MFCHASHTBL].n_value,
  377. nl[N_MFCHASH].n_value,
  378. nl[N_VIFTABLE].n_value);
  379. #ifdef NETSNMP_ENABLE_IPV6
  380. if (af == AF_INET6 || af == AF_UNSPEC)
  381. mroute6pr(nl[N_MRT6PROTO].n_value,
  382. nl[N_MF6CTABLE].n_value,
  383. nl[N_MIF6TABLE].n_value);
  384. #endif
  385. }
  386. exit(0);
  387. }
  388. */
  389. if (af == AF_INET || af == AF_UNSPEC) {
  390. setprotoent(1);
  391. setservent(1);
  392. /* ugh, this is O(MN) ... why do we do this? */
  393. while ((p = getprotoent())) {
  394. for (tp = protox; tp->pr_name; tp++)
  395. if (strcmp(tp->pr_name, p->p_name) == 0)
  396. break;
  397. if (tp->pr_name == NULL || tp->pr_wanted == 0)
  398. continue;
  399. printproto(tp, p->p_name);
  400. }
  401. endprotoent();
  402. }
  403. if (af == AF_INET6 || af == AF_UNSPEC)
  404. for (tp = ip6protox; tp->pr_name; tp++)
  405. printproto(tp, tp->pr_name);
  406. /*
  407. if (af == AF_IPX || af == AF_UNSPEC)
  408. for (tp = ipxprotox; tp->pr_name; tp++)
  409. printproto(tp, tp->pr_name);
  410. if (af == AF_NS || af == AF_UNSPEC)
  411. for (tp = nsprotox; tp->pr_name; tp++)
  412. printproto(tp, tp->pr_name);
  413. if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
  414. unixpr(nl[N_UNIXSW].n_value);
  415. if (af == AF_APPLETALK || af == AF_UNSPEC)
  416. for (tp = atalkprotox; tp->pr_name; tp++)
  417. printproto(tp, tp->pr_name);
  418. */
  419. exit(0);
  420. }
  421. /*
  422. * Print out protocol statistics or control blocks (per sflag).
  423. * Namelist checks - Omitted
  424. */
  425. static void
  426. printproto(struct protox *tp, const char *name)
  427. {
  428. void (*pr)(const char *);
  429. if (sflag) {
  430. pr = tp->pr_stats;
  431. } else {
  432. pr = tp->pr_cblocks;
  433. }
  434. if (pr != NULL)
  435. (*pr)(name);
  436. }
  437. /*
  438. * Read kernel memory - Omitted
  439. */
  440. const char *
  441. plural(int n)
  442. {
  443. return (n != 1 ? "s" : "");
  444. }
  445. /*
  446. * Find the protox for the given "well-known" name.
  447. */
  448. static struct protox *
  449. knownname(const char *name)
  450. {
  451. struct protox **tpp, *tp;
  452. for (tpp = protoprotox; *tpp; tpp++)
  453. for (tp = *tpp; tp->pr_name; tp++)
  454. if (strcmp(tp->pr_name, name) == 0)
  455. return (tp);
  456. return (NULL);
  457. }
  458. /*
  459. * Find the protox corresponding to name.
  460. */
  461. static struct protox *
  462. name2protox(const char *name)
  463. {
  464. struct protox *tp;
  465. char **alias; /* alias from p->aliases */
  466. struct protoent *p;
  467. /*
  468. * Try to find the name in the list of "well-known" names. If that
  469. * fails, check if name is an alias for an Internet protocol.
  470. */
  471. if ((tp = knownname(name)))
  472. return (tp);
  473. setprotoent(1); /* make protocol lookup cheaper */
  474. while ((p = getprotoent())) {
  475. /* netsnmp_assert: name not same as p->name */
  476. for (alias = p->p_aliases; *alias; alias++)
  477. if (strcmp(name, *alias) == 0) {
  478. endprotoent();
  479. return (knownname(p->p_name));
  480. }
  481. }
  482. endprotoent();
  483. return (NULL);
  484. }
  485. static void
  486. usage(void)
  487. {
  488. (void)fprintf(stderr,
  489. "usage: %s [snmp_opts] [-Can] [-Cf address_family]\n", progname);
  490. (void)fprintf(stderr,
  491. " %s [snmp_opts] [-CbdgimnrSs] [-Cf address_family]\n", progname);
  492. (void)fprintf(stderr,
  493. " %s [snmp_opts] [-Cbdn] [-CI interface] [-Cw wait]\n", progname);
  494. (void)fprintf(stderr,
  495. " %s [snmp_opts] [-Cs] [-Cp protocol]\n", progname);
  496. (void)fprintf(stderr,
  497. " %s [snmp_opts] [-Ca] [-Cf address_family] [-Ci | -CI interface]\n", progname);
  498. exit(1);
  499. }