PageRenderTime 65ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/snmp/agent/mibgroup/mibII/tcp.c

https://gitlab.com/envieidoc/tomato
C | 596 lines | 489 code | 54 blank | 53 comment | 21 complexity | c35c8b601c89d70edb29dc92f908c158 MD5 | raw file
  1. /*
  2. * TCP MIB group implementation - tcp.c
  3. *
  4. */
  5. #include <net-snmp/net-snmp-config.h>
  6. #if HAVE_STRING_H
  7. #include <string.h>
  8. #endif
  9. #if HAVE_STDLIB_H
  10. #include <stdlib.h>
  11. #endif
  12. #if HAVE_UNISTD_H
  13. #include <unistd.h>
  14. #endif
  15. #if HAVE_SYS_PARAM_H
  16. #include <sys/param.h>
  17. #endif
  18. #if HAVE_SYS_PROTOSW_H
  19. #include <sys/protosw.h>
  20. #endif
  21. #if HAVE_SYS_SYSMP_H
  22. #include <sys/sysmp.h>
  23. #endif
  24. #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
  25. #define _KERNEL 1
  26. #define _I_DEFINED_KERNEL
  27. #endif
  28. #if HAVE_SYS_SOCKET_H
  29. #include <sys/socket.h>
  30. #endif
  31. #if HAVE_WINSOCK_H
  32. #include <winsock.h>
  33. #endif
  34. #if HAVE_NETINET_IN_H
  35. #include <netinet/in.h>
  36. #endif
  37. #if HAVE_NET_IF_H
  38. #include <net/if.h>
  39. #endif
  40. #if HAVE_NET_IF_VAR_H
  41. #include <net/if_var.h>
  42. #endif
  43. #ifdef _I_DEFINED_KERNEL
  44. #undef _KERNEL
  45. #endif
  46. #if HAVE_SYS_STREAM_H
  47. #include <sys/stream.h>
  48. #endif
  49. #if HAVE_NET_ROUTE_H
  50. #include <net/route.h>
  51. #endif
  52. #if HAVE_NETINET_IN_SYSTM_H
  53. #include <netinet/in_systm.h>
  54. #endif
  55. #if HAVE_NETINET_IP_H
  56. #include <netinet/ip.h>
  57. #endif
  58. #if HAVE_SYS_QUEUE_H
  59. #include <sys/queue.h>
  60. #endif
  61. #if HAVE_NETINET_IP_VAR_H
  62. #include <netinet/ip_var.h>
  63. #endif
  64. #ifdef INET6
  65. #if HAVE_NETINET6_IP6_VAR_H
  66. #include <netinet6/ip6_var.h>
  67. #endif
  68. #endif
  69. #if HAVE_SYS_SOCKETVAR_H
  70. #include <sys/socketvar.h>
  71. #endif
  72. #if HAVE_NETINET_IN_PCB_H
  73. #include <netinet/in_pcb.h>
  74. #endif
  75. #if HAVE_INET_MIB2_H
  76. #include <inet/mib2.h>
  77. #endif
  78. #if HAVE_SYS_SYSCTL_H
  79. #include <sys/sysctl.h>
  80. #endif
  81. #if HAVE_ARPA_INET_H
  82. #include <arpa/inet.h>
  83. #endif
  84. #if defined(osf4) || defined(aix4) || defined(hpux10)
  85. /*
  86. * these are undefed to remove a stupid warning on osf compilers
  87. * because they get redefined with a slightly different notation of the
  88. * same value. -- Wes
  89. */
  90. #undef TCP_NODELAY
  91. #undef TCP_MAXSEG
  92. #endif
  93. #if HAVE_NETINET_TCP_H
  94. #include <netinet/tcp.h>
  95. #endif
  96. #if HAVE_NETINET_TCPIP_H
  97. #include <netinet/tcpip.h>
  98. #endif
  99. #if HAVE_NETINET_TCP_TIMER_H
  100. #include <netinet/tcp_timer.h>
  101. #endif
  102. #if HAVE_NETINET_TCP_VAR_H
  103. #include <netinet/tcp_var.h>
  104. #endif
  105. #if HAVE_NETINET_TCP_FSM_H
  106. #include <netinet/tcp_fsm.h>
  107. #endif
  108. #if HAVE_SYS_TCPIPSTATS_H
  109. #include <sys/tcpipstats.h>
  110. #endif
  111. #if HAVE_DMALLOC_H
  112. #include <dmalloc.h>
  113. #endif
  114. #include <net-snmp/net-snmp-includes.h>
  115. #include <net-snmp/agent/net-snmp-agent-includes.h>
  116. #include <net-snmp/agent/auto_nlist.h>
  117. #ifdef solaris2
  118. #include "kernel_sunos5.h"
  119. #else
  120. #include "kernel.h"
  121. #endif
  122. #ifdef linux
  123. #include "kernel_linux.h"
  124. #endif
  125. #include "util_funcs.h"
  126. #ifdef hpux
  127. #include <sys/mib.h>
  128. #include <netinet/mib_kern.h>
  129. #endif /* hpux */
  130. #ifdef cygwin
  131. #define WIN32
  132. #include <windows.h>
  133. #endif
  134. #include "tcp.h"
  135. #include "tcpTable.h"
  136. #include "sysORTable.h"
  137. #ifndef MIB_STATS_CACHE_TIMEOUT
  138. #define MIB_STATS_CACHE_TIMEOUT 5
  139. #endif
  140. #ifndef TCP_STATS_CACHE_TIMEOUT
  141. #define TCP_STATS_CACHE_TIMEOUT MIB_STATS_CACHE_TIMEOUT
  142. #endif
  143. marker_t tcp_stats_cache_marker = NULL;
  144. /*********************
  145. *
  146. * Kernel & interface information,
  147. * and internal forward declarations
  148. *
  149. *********************/
  150. #ifdef freebsd4
  151. static unsigned int hz;
  152. #endif
  153. /*********************
  154. *
  155. * Initialisation & common implementation functions
  156. *
  157. *********************/
  158. struct variable3 tcp_variables[] = {
  159. {TCPRTOALGORITHM, ASN_INTEGER, RONLY, var_tcp, 1, {1}},
  160. {TCPRTOMIN, ASN_INTEGER, RONLY, var_tcp, 1, {2}},
  161. #ifndef sunV3
  162. {TCPRTOMAX, ASN_INTEGER, RONLY, var_tcp, 1, {3}},
  163. #endif
  164. {TCPMAXCONN, ASN_INTEGER, RONLY, var_tcp, 1, {4}},
  165. #ifndef sunV3
  166. {TCPACTIVEOPENS, ASN_COUNTER, RONLY, var_tcp, 1, {5}},
  167. {TCPPASSIVEOPENS, ASN_COUNTER, RONLY, var_tcp, 1, {6}},
  168. {TCPATTEMPTFAILS, ASN_COUNTER, RONLY, var_tcp, 1, {7}},
  169. {TCPESTABRESETS, ASN_COUNTER, RONLY, var_tcp, 1, {8}},
  170. #endif
  171. {TCPCURRESTAB, ASN_GAUGE, RONLY, var_tcp, 1, {9}},
  172. #ifndef sunV3
  173. {TCPINSEGS, ASN_COUNTER, RONLY, var_tcp, 1, {10}},
  174. {TCPOUTSEGS, ASN_COUNTER, RONLY, var_tcp, 1, {11}},
  175. {TCPRETRANSSEGS, ASN_COUNTER, RONLY, var_tcp, 1, {12}},
  176. #endif
  177. #ifdef WIN32
  178. {TCPCONNSTATE, ASN_INTEGER, RWRITE, var_tcpEntry, 3, {13, 1, 1}},
  179. #else
  180. {TCPCONNSTATE, ASN_INTEGER, RONLY, var_tcpEntry, 3, {13, 1, 1}},
  181. #endif
  182. {TCPCONNLOCALADDRESS, ASN_IPADDRESS, RONLY, var_tcpEntry, 3,
  183. {13, 1, 2}},
  184. {TCPCONNLOCALPORT, ASN_INTEGER, RONLY, var_tcpEntry, 3, {13, 1, 3}},
  185. {TCPCONNREMADDRESS, ASN_IPADDRESS, RONLY, var_tcpEntry, 3, {13, 1, 4}},
  186. {TCPCONNREMPORT, ASN_INTEGER, RONLY, var_tcpEntry, 3, {13, 1, 5}},
  187. {TCPINERRS, ASN_COUNTER, RONLY, var_tcp, 1, {14}},
  188. {TCPOUTRSTS, ASN_COUNTER, RONLY, var_tcp, 1, {15}}
  189. };
  190. /*
  191. * Define the OID pointer to the top of the mib tree that we're
  192. * registering underneath, and the OID for the MIB module
  193. */
  194. oid tcp_variables_oid[] = { SNMP_OID_MIB2, 6 };
  195. oid tcp_module_oid[] = { SNMP_OID_MIB2, 49 };
  196. void
  197. init_tcp(void)
  198. {
  199. /*
  200. * register ourselves with the agent to handle our mib tree
  201. */
  202. REGISTER_MIB("mibII/tcp", tcp_variables, variable3,
  203. tcp_variables_oid);
  204. REGISTER_SYSOR_ENTRY(tcp_module_oid,
  205. "The MIB module for managing TCP implementations");
  206. #ifdef TCPSTAT_SYMBOL
  207. auto_nlist(TCPSTAT_SYMBOL, 0, 0);
  208. #endif
  209. #ifdef TCP_SYMBOL
  210. auto_nlist(TCP_SYMBOL, 0, 0);
  211. #endif
  212. #if freebsd4
  213. hz = sysconf(_SC_CLK_TCK); /* get ticks/s from system */
  214. #endif
  215. #ifdef solaris2
  216. init_kernel_sunos5();
  217. #endif
  218. }
  219. /*********************
  220. *
  221. * System specific implementation functions
  222. *
  223. *********************/
  224. #ifdef linux
  225. #define TCP_STAT_STRUCTURE struct tcp_mib
  226. #define USES_SNMP_DESIGNED_TCPSTAT
  227. #undef TCPSTAT_SYMBOL
  228. #endif
  229. #ifdef solaris2
  230. #define TCP_STAT_STRUCTURE mib2_tcp_t
  231. #define USES_SNMP_DESIGNED_TCPSTAT
  232. #endif
  233. #ifdef hpux11
  234. #define TCP_STAT_STRUCTURE int
  235. #endif
  236. #ifdef WIN32
  237. #include <iphlpapi.h>
  238. #define TCP_STAT_STRUCTURE MIB_TCPSTATS
  239. #endif
  240. #ifdef HAVE_SYS_TCPIPSTATS_H
  241. #define TCP_STAT_STRUCTURE struct kna
  242. #define USES_TRADITIONAL_TCPSTAT
  243. #endif
  244. #if !defined(TCP_STAT_STRUCTURE)
  245. #define TCP_STAT_STRUCTURE struct tcpstat
  246. #define USES_TRADITIONAL_TCPSTAT
  247. #endif
  248. long read_tcp_stat(TCP_STAT_STRUCTURE *, int);
  249. u_char *
  250. var_tcp(struct variable *vp,
  251. oid * name,
  252. size_t * length,
  253. int exact, size_t * var_len, WriteMethod ** write_method)
  254. {
  255. static TCP_STAT_STRUCTURE tcpstat;
  256. static long ret_value;
  257. #ifdef TCPTV_NEEDS_HZ
  258. /*
  259. * I don't know of any such system now, but maybe they'll figure
  260. * it out some day.
  261. */
  262. int hz = 1000;
  263. #endif
  264. if (header_generic(vp, name, length, exact, var_len, write_method) ==
  265. MATCH_FAILED)
  266. return NULL;
  267. ret_value = read_tcp_stat(&tcpstat, vp->magic);
  268. if (ret_value < 0)
  269. return NULL;
  270. #ifdef HAVE_SYS_TCPIPSTATS_H
  271. /*
  272. * This actually reads statistics for *all* the groups together,
  273. * so we need to isolate the TCP-specific bits.
  274. */
  275. #define tcpstat tcpstat.tcpstat
  276. #endif
  277. switch (vp->magic) {
  278. #ifdef USES_SNMP_DESIGNED_TCPSTAT
  279. case TCPRTOALGORITHM:
  280. return (u_char *) & tcpstat.tcpRtoAlgorithm;
  281. case TCPRTOMIN:
  282. return (u_char *) & tcpstat.tcpRtoMin;
  283. case TCPRTOMAX:
  284. return (u_char *) & tcpstat.tcpRtoMax;
  285. case TCPMAXCONN:
  286. return (u_char *) & tcpstat.tcpMaxConn;
  287. case TCPACTIVEOPENS:
  288. return (u_char *) & tcpstat.tcpActiveOpens;
  289. case TCPPASSIVEOPENS:
  290. return (u_char *) & tcpstat.tcpPassiveOpens;
  291. case TCPATTEMPTFAILS:
  292. return (u_char *) & tcpstat.tcpAttemptFails;
  293. case TCPESTABRESETS:
  294. return (u_char *) & tcpstat.tcpEstabResets;
  295. case TCPCURRESTAB:
  296. return (u_char *) & tcpstat.tcpCurrEstab;
  297. case TCPINSEGS:
  298. return (u_char *) & tcpstat.tcpInSegs;
  299. case TCPOUTSEGS:
  300. return (u_char *) & tcpstat.tcpOutSegs;
  301. case TCPRETRANSSEGS:
  302. return (u_char *) & tcpstat.tcpRetransSegs;
  303. case TCPINERRS:
  304. #ifdef solaris2
  305. return (u_char *) & ret_value;
  306. #elif defined(linux)
  307. if (tcpstat.tcpInErrsValid)
  308. return (u_char *) & tcpstat.tcpInErrs;
  309. return NULL;
  310. #else
  311. return NULL;
  312. #endif
  313. case TCPOUTRSTS:
  314. #ifdef linux
  315. if (tcpstat.tcpOutRstsValid)
  316. return (u_char *) & tcpstat.tcpOutRsts;
  317. return NULL;
  318. #else
  319. return NULL;
  320. #endif
  321. #endif
  322. #ifdef USES_TRADITIONAL_TCPSTAT
  323. case TCPRTOALGORITHM: /* Assume Van Jacobsen's algorithm */
  324. long_return = 4;
  325. return (u_char *) & long_return;
  326. case TCPRTOMIN:
  327. #ifdef TCPTV_NEEDS_HZ
  328. long_return = TCPTV_MIN;
  329. #else
  330. long_return = TCPTV_MIN / PR_SLOWHZ * 1000;
  331. #endif
  332. return (u_char *) & long_return;
  333. case TCPRTOMAX:
  334. #ifdef TCPTV_NEEDS_HZ
  335. long_return = TCPTV_REXMTMAX;
  336. #else
  337. long_return = TCPTV_REXMTMAX / PR_SLOWHZ * 1000;
  338. #endif
  339. return (u_char *) & long_return;
  340. case TCPMAXCONN:
  341. return NULL;
  342. case TCPACTIVEOPENS:
  343. return (u_char *) & tcpstat.tcps_connattempt;
  344. case TCPPASSIVEOPENS:
  345. return (u_char *) & tcpstat.tcps_accepts;
  346. /*
  347. * NB: tcps_drops is actually the sum of the two MIB
  348. * counters tcpAttemptFails and tcpEstabResets.
  349. */
  350. case TCPATTEMPTFAILS:
  351. return (u_char *) & tcpstat.tcps_conndrops;
  352. case TCPESTABRESETS:
  353. return (u_char *) & tcpstat.tcps_drops;
  354. case TCPCURRESTAB:
  355. long_return = TCP_Count_Connections();
  356. return (u_char *) & long_return;
  357. case TCPINSEGS:
  358. return (u_char *) & tcpstat.tcps_rcvtotal;
  359. case TCPOUTSEGS:
  360. /*
  361. * RFC 1213 defines this as the number of segments sent
  362. * "excluding those containing only retransmitted octets"
  363. */
  364. long_return = tcpstat.tcps_sndtotal - tcpstat.tcps_sndrexmitpack;
  365. return (u_char *) & long_return;
  366. case TCPRETRANSSEGS:
  367. return (u_char *) & tcpstat.tcps_sndrexmitpack;
  368. case TCPINERRS:
  369. long_return = tcpstat.tcps_rcvbadsum + tcpstat.tcps_rcvbadoff
  370. #ifdef STRUCT_TCPSTAT_HAS_TCPS_RCVMEMDROP
  371. + tcpstat.tcps_rcvmemdrop
  372. #endif
  373. + tcpstat.tcps_rcvshort;
  374. return (u_char *) & long_return;
  375. case TCPOUTRSTS:
  376. long_return = tcpstat.tcps_sndctrl - tcpstat.tcps_closed;
  377. return (u_char *) & long_return;
  378. #endif
  379. #ifdef WIN32
  380. case TCPRTOALGORITHM:
  381. return (u_char *) & tcpstat.dwRtoAlgorithm;
  382. case TCPRTOMIN:
  383. return (u_char *) & tcpstat.dwRtoMin;
  384. case TCPRTOMAX:
  385. return (u_char *) & tcpstat.dwRtoMax;
  386. case TCPMAXCONN:
  387. return (u_char *) & tcpstat.dwMaxConn;
  388. case TCPACTIVEOPENS:
  389. return (u_char *) & tcpstat.dwActiveOpens;
  390. case TCPPASSIVEOPENS:
  391. return (u_char *) & tcpstat.dwPassiveOpens;
  392. case TCPATTEMPTFAILS:
  393. return (u_char *) & tcpstat.dwAttemptFails;
  394. case TCPESTABRESETS:
  395. return (u_char *) & tcpstat.dwEstabResets;
  396. case TCPCURRESTAB:
  397. return (u_char *) & tcpstat.dwCurrEstab;
  398. case TCPINSEGS:
  399. return (u_char *) & tcpstat.dwInSegs;
  400. case TCPOUTSEGS:
  401. return (u_char *) & tcpstat.dwOutSegs;
  402. case TCPRETRANSSEGS:
  403. return (u_char *) & tcpstat.dwRetransSegs;
  404. case TCPINERRS:
  405. return (u_char *) & tcpstat.dwInErrs;
  406. case TCPOUTRSTS:
  407. return (u_char *) & tcpstat.dwOutRsts;
  408. #endif
  409. default:
  410. DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_tcp\n", vp->magic));
  411. }
  412. return NULL;
  413. #ifdef HAVE_SYS_TCPIPSTATS_H
  414. #undef tcpstat
  415. #endif
  416. }
  417. /*********************
  418. *
  419. * Internal implementation functions
  420. *
  421. *********************/
  422. long
  423. read_tcp_stat(TCP_STAT_STRUCTURE * tcpstat, int magic)
  424. {
  425. long ret_value = -1;
  426. #if (defined(CAN_USE_SYSCTL) && defined(TCPCTL_STATS))
  427. static int sname[4] =
  428. { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_STATS };
  429. size_t len = sizeof(*tcpstat);
  430. #endif
  431. #ifdef solaris2
  432. static mib2_ip_t ipstat;
  433. #endif
  434. #ifdef hpux11
  435. int fd;
  436. struct nmparms p;
  437. unsigned int ulen;
  438. int ret;
  439. if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) < 0)
  440. return (-1); /* error */
  441. switch (magic) {
  442. case TCPRTOALGORITHM:
  443. p.objid = ID_tcpRtoAlgorithm;
  444. break;
  445. case TCPRTOMIN:
  446. p.objid = ID_tcpRtoMin;
  447. break;
  448. case TCPRTOMAX:
  449. p.objid = ID_tcpRtoMax;
  450. break;
  451. case TCPMAXCONN:
  452. p.objid = ID_tcpMaxConn;
  453. break;
  454. case TCPACTIVEOPENS:
  455. p.objid = ID_tcpActiveOpens;
  456. break;
  457. case TCPPASSIVEOPENS:
  458. p.objid = ID_tcpPassiveOpens;
  459. break;
  460. case TCPATTEMPTFAILS:
  461. p.objid = ID_tcpAttemptFails;
  462. break;
  463. case TCPESTABRESETS:
  464. p.objid = ID_tcpEstabResets;
  465. break;
  466. case TCPCURRESTAB:
  467. p.objid = ID_tcpCurrEstab;
  468. break;
  469. case TCPINSEGS:
  470. p.objid = ID_tcpInSegs;
  471. break;
  472. case TCPOUTSEGS:
  473. p.objid = ID_tcpOutSegs;
  474. break;
  475. case TCPRETRANSSEGS:
  476. p.objid = ID_tcpRetransSegs;
  477. break;
  478. case TCPINERRS:
  479. p.objid = ID_tcpInErrs;
  480. break;
  481. case TCPOUTRSTS:
  482. p.objid = ID_tcpOutRsts;
  483. break;
  484. default:
  485. *tcpstat = 0;
  486. close_mib(fd);
  487. return (0);
  488. }
  489. p.buffer = (void *) tcpstat;
  490. ulen = sizeof(TCP_STAT_STRUCTURE);
  491. p.len = &ulen;
  492. ret_value = get_mib_info(fd, &p);
  493. close_mib(fd);
  494. return (ret_value); /* 0: ok, < 0: error */
  495. #else /* hpux11 */
  496. if (tcp_stats_cache_marker &&
  497. (!atime_ready
  498. (tcp_stats_cache_marker, TCP_STATS_CACHE_TIMEOUT * 1000)))
  499. #ifdef solaris2
  500. return (magic == TCPINERRS ? ipstat.tcpInErrs : 0);
  501. #else
  502. return 0;
  503. #endif
  504. if (tcp_stats_cache_marker)
  505. atime_setMarker(tcp_stats_cache_marker);
  506. else
  507. tcp_stats_cache_marker = atime_newMarker();
  508. #ifdef linux
  509. ret_value = linux_read_tcp_stat(tcpstat);
  510. #endif
  511. #ifdef solaris2
  512. if (magic == TCPINERRS) {
  513. if (getMibstat
  514. (MIB_IP, &ipstat, sizeof(mib2_ip_t), GET_FIRST,
  515. &Get_everything, NULL) < 0)
  516. ret_value = -1;
  517. else
  518. ret_value = ipstat.tcpInErrs;
  519. } else
  520. ret_value = getMibstat(MIB_TCP, tcpstat, sizeof(mib2_tcp_t),
  521. GET_FIRST, &Get_everything, NULL);
  522. #endif
  523. #ifdef WIN32
  524. ret_value = GetTcpStatistics(tcpstat);
  525. #endif
  526. #ifdef HAVE_SYS_TCPIPSTATS_H
  527. ret_value = sysmp(MP_SAGET, MPSA_TCPIPSTATS, tcpstat, sizeof *tcpstat);
  528. #endif
  529. #if defined(CAN_USE_SYSCTL) && defined(TCPCTL_STATS)
  530. ret_value = sysctl(sname, 4, tcpstat, &len, 0, 0);
  531. #endif
  532. #ifdef TCPSTAT_SYMBOL
  533. if (auto_nlist(TCPSTAT_SYMBOL, (char *) tcpstat, sizeof(*tcpstat)))
  534. ret_value = 0;
  535. #endif
  536. if (ret_value == -1) {
  537. free(tcp_stats_cache_marker);
  538. tcp_stats_cache_marker = NULL;
  539. }
  540. return ret_value;
  541. #endif /* hpux11 */
  542. }