systemstats_linux.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:13k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Interface MIB architecture support
  3.  *
  4.  * $Id: systemstats_linux.c,v 1.3.2.6 2005/09/05 22:28:57 tanders Exp $
  5.  */
  6. #include <net-snmp/net-snmp-config.h>
  7. #include <net-snmp/net-snmp-includes.h>
  8. #include <net-snmp/agent/net-snmp-agent-includes.h>
  9. #include <net-snmp/data_access/ipstats.h>
  10. #include <net-snmp/data_access/systemstats.h>
  11. static int _systemstats_v4(netsnmp_container* container, u_int load_flags);
  12. #if defined (INET6)
  13. static int _systemstats_v6(netsnmp_container* container, u_int load_flags);
  14. #endif
  15. void
  16. netsnmp_access_systemstats_arch_init(void)
  17. {
  18.     /*
  19.      * nothing to do
  20.      */
  21. }
  22. /*
  23.   /proc/net/snmp
  24.   Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
  25.   Ip: 2 64 7083534 0 0 0 0 0 6860233 6548963 0 0 1 286623 63322 1 259920 0 0
  26.   
  27.   Icmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
  28.   Icmp: 335 36 254 72 0 0 0 0 9 0 0 0 0 257 0 257 0 0 0 0 0 0 0 0 0 0
  29.   
  30.   Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts
  31.   Tcp: 1 200 120000 -1 5985 55 27 434 10 5365077 5098096 10902 2 4413
  32.   
  33.   Udp: InDatagrams NoPorts InErrors OutDatagrams
  34.   Udp: 1491094 122 0 1466178
  35. */
  36. /*
  37.  *
  38.  * @retval  0 success
  39.  * @retval -1 no container specified
  40.  * @retval -2 could not open file
  41.  * @retval -3 could not create entry (probably malloc)
  42.  * @retval -4 file format error
  43.  */
  44. int
  45. netsnmp_access_systemstats_container_arch_load(netsnmp_container* container,
  46.                                              u_int load_flags)
  47. {
  48.     int rc1;
  49. #if defined (INET6)
  50.     int rc2;
  51. #endif
  52.     if (NULL == container) {
  53.         snmp_log(LOG_ERR, "no container specified/found for access_systemstats_n");
  54.         return -1;
  55.     }
  56.     /*
  57.      * load v4 and v6 stats. Even if one fails, try the other.
  58.      * If they have the same rc, return it. if the differ, return
  59.      * the smaller one. No log messages, since each individual function
  60.      * would have logged its own message.
  61.      */
  62.     rc1 = _systemstats_v4(container, load_flags);
  63. #if defined (INET6)
  64.     rc2 = _systemstats_v6(container, load_flags);
  65.     if ((rc1 == rc2) || (rc1 < rc2))
  66.         return rc1;
  67.         
  68.     return rc2;
  69. #else
  70.     return rc1;
  71. #endif
  72. }
  73. static int
  74. _systemstats_v4(netsnmp_container* container, u_int load_flags)
  75. {
  76.     FILE           *devin;
  77.     char            line[1024];
  78.     netsnmp_systemstats_entry *entry = NULL;
  79.     int             scan_count;
  80.     char           *stats, *start = line;
  81.     int             len;
  82.     uintmax_t       scan_vals[19];
  83.     DEBUGMSGTL(("access:systemstats:container:arch", "load v4 (flags %p)n",
  84.                 load_flags));
  85.     netsnmp_assert(container != NULL); /* load function shoulda checked this */
  86.     if (!(devin = fopen("/proc/net/snmp", "r"))) {
  87.         DEBUGMSGTL(("access:systemstats",
  88.                     "Failed to load Systemstats Table (linux1)n"));
  89.         snmp_log(LOG_ERR, "cannot open /proc/net/snmp ...n");
  90.         return -2;
  91.     }
  92.     /*
  93.      * skip header, but make sure it's the length we expect...
  94.      */
  95.     fgets(line, sizeof(line), devin);
  96.     len = strlen(line);
  97.     if (224 != len) {
  98.         snmp_log(LOG_ERR, "unexpected header length in /proc/net/snmp."
  99.                  " %d != 224n", len);
  100.         return -4;
  101.     }
  102.     /*
  103.      * This file provides the statistics for each systemstats.
  104.      * Read in each line in turn, isolate the systemstats name
  105.      *   and retrieve (or create) the corresponding data structure.
  106.      */
  107.     start = fgets(line, sizeof(line), devin);
  108.     fclose(devin);
  109.     if (start) {
  110.         len = strlen(line);
  111.         if (line[len - 1] == 'n')
  112.             line[len - 1] = '';
  113.         while (*start && *start == ' ')
  114.             start++;
  115.         if ((!*start) || ((stats = strrchr(start, ':')) == NULL)) {
  116.             snmp_log(LOG_ERR,
  117.                      "systemstats data format error 1, line ==|%s|n", line);
  118.             return -4;
  119.         }
  120.         DEBUGMSGTL(("access:systemstats", "processing '%s'n", start));
  121.         *stats++ = 0; /* null terminate name */
  122.         while (*stats == ' ') /* skip spaces before stats */
  123.             stats++;
  124.         entry = netsnmp_access_systemstats_entry_create(1);
  125.         if(NULL == entry) {
  126.             netsnmp_access_systemstats_container_free(container,
  127.                                                       NETSNMP_ACCESS_SYSTEMSTATS_FREE_NOFLAGS);
  128.             return -3;
  129.         }
  130.         /*
  131.          * OK - we've now got (or created) the data structure for
  132.          *      this systemstats, including any "static" information.
  133.          * Now parse the rest of the line (i.e. starting from 'stats')
  134.          *      to extract the relevant statistics, and populate
  135.          *      data structure accordingly.
  136.          */
  137.         memset(scan_vals, 0x0, sizeof(scan_vals));
  138.         scan_count = sscanf(stats,
  139.                             "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu"
  140.                             "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
  141.                             &scan_vals[0],&scan_vals[1],&scan_vals[2],
  142.                             &scan_vals[3],&scan_vals[4],&scan_vals[5],
  143.                             &scan_vals[6],&scan_vals[7],&scan_vals[8],
  144.                             &scan_vals[9],&scan_vals[10],&scan_vals[11],
  145.                             &scan_vals[12],&scan_vals[13],&scan_vals[14],
  146.                             &scan_vals[15],&scan_vals[16],&scan_vals[17],
  147.                             &scan_vals[18]);
  148.         DEBUGMSGTL(("access:systemstats", "  read %d valuesn", scan_count));
  149.         if(scan_count != 19) {
  150.             snmp_log(LOG_ERR,
  151.                      "error scanning systemstats data (expected %d, got %d)n",
  152.                      19, scan_count);
  153.             netsnmp_access_systemstats_entry_free(entry);
  154.             return -4;
  155.         }
  156.         /* entry->stats. = scan_vals[0]; / * Forwarding */
  157.         /* entry->stats. = scan_vals[1]; / * DefaultTTL */
  158.         entry->stats.HCInReceives.low = scan_vals[2] & 0xffffffff;
  159.         entry->stats.HCInReceives.high = scan_vals[2] >> 32;
  160.         entry->stats.InHdrErrors = scan_vals[3];
  161.         entry->stats.InAddrErrors = scan_vals[4];
  162.         entry->stats.HCInForwDatagrams.low = scan_vals[5] & 0xffffffff;
  163.         entry->stats.HCInForwDatagrams.high = scan_vals[5] >> 32;
  164.         entry->stats.InUnknownProtos = scan_vals[6];
  165.         entry->stats.InDiscards = scan_vals[7];
  166.         entry->stats.HCInDelivers.low = scan_vals[8] & 0xffffffff;
  167.         entry->stats.HCInDelivers.high = scan_vals[8] >> 32;
  168.         entry->stats.HCOutRequests.low = scan_vals[9] & 0xffffffff;
  169.         entry->stats.HCOutRequests.high = scan_vals[9] >> 32;
  170.         entry->stats.OutDiscards = scan_vals[10];
  171.         entry->stats.OutNoRoutes = scan_vals[11];
  172.         /* entry->stats. = scan_vals[12]; / * ReasmTimeout */
  173.         entry->stats.ReasmReqds = scan_vals[13];
  174.         entry->stats.ReasmOKs = scan_vals[14];
  175.         entry->stats.ReasmFails = scan_vals[15];
  176.         entry->stats.OutFragOKs = scan_vals[16];
  177.         entry->stats.OutFragFails = scan_vals[17];
  178.         entry->stats.OutFragCreates = scan_vals[18];
  179.         /*
  180.          * add to container
  181.          */
  182.         CONTAINER_INSERT(container, entry);
  183.     }
  184.     return 0;
  185. }
  186.     
  187. #if defined (INET6)
  188. static int
  189. _systemstats_v6(netsnmp_container* container, u_int load_flags)
  190. {
  191.     FILE           *devin;
  192.     char            line[1024];
  193.     netsnmp_systemstats_entry *entry = NULL;
  194.     int             scan_count = 0;
  195.     char           *stats, *start = line;
  196.     int             len, rc;
  197.     uintmax_t       scan_val;
  198.     const char     *filename = "/proc/net/snmp6";
  199.     static int      warned_open = 0;
  200.     DEBUGMSGTL(("access:systemstats:container:arch", "load v6 (flags %p)n",
  201.                 load_flags));
  202.     netsnmp_assert(container != NULL); /* load function shoulda checked this */
  203.     entry = netsnmp_access_systemstats_entry_create(2);
  204.     if(NULL == entry)
  205.         return -3;
  206.     
  207.     /*
  208.      * try to open file. If we can't, that's ok - maybe the module hasn't
  209.      * been loaded yet.
  210.      */
  211.     if (!(devin = fopen(filename, "r"))) {
  212.         DEBUGMSGTL(("access:systemstats",
  213.                     "Failed to load Systemstats Table (linux1)n"));
  214.         if(!warned_open) {
  215.             ++warned_open;
  216.             snmp_log(LOG_ERR, "cannot open %s ...n", filename);
  217.         }
  218.         free(entry);
  219.         return 0;
  220.     }
  221.     /*
  222.      * This file provides the statistics for each systemstats.
  223.      * Read in each line in turn, isolate the systemstats name
  224.      *   and retrieve (or create) the corresponding data structure.
  225.      */
  226.     while (1) {
  227.         start = fgets(line, sizeof(line), devin);
  228.         if (NULL == start)
  229.             break;
  230.         len = strlen(line);
  231.         if (line[len - 1] == 'n')
  232.             line[len - 1] = '';
  233.         if (('I' != line[0]) || ('6' != line[2]))
  234.             continue;
  235.         stats = strrchr(line, ' ');
  236.         if (NULL == stats) {
  237.             snmp_log(LOG_ERR,
  238.                      "systemstats data format error 1, line ==|%s|n", line);
  239.             continue;
  240.         }
  241.         DEBUGMSGTL(("access:systemstats", "processing '%s'n", line));
  242.         /*
  243.          * OK - we've now got (or created) the data structure for
  244.          *      this systemstats, including any "static" information.
  245.          * Now parse the rest of the line (i.e. starting from 'stats')
  246.          *      to extract the relevant statistics, and populate
  247.          *      data structure accordingly.
  248.          */
  249.         scan_val = atoll(stats);
  250.         if (0 == scan_val)
  251.             continue;
  252.         rc = 0;
  253.         if ('I' == line[3]) { /* In */
  254.             if ('A' == line[5]) {
  255.                 entry->stats.InAddrErrors = scan_val;
  256.             } else if ('D' == line[5]) {
  257.                 if ('e' == line[6]) {
  258.                     entry->stats.HCInDelivers.low = scan_val  & 0xffffffff;
  259.                     entry->stats.HCInDelivers.high = scan_val >> 32;
  260.                 } else if ('i' == line[6])
  261.                     entry->stats.InDiscards = scan_val;
  262.                 else
  263.                     rc = 1;
  264.             } else if ('H' == line[5]) {
  265.                 entry->stats.InHdrErrors = scan_val;
  266.             } else if ('M' == line[5]) {
  267.                 entry->stats.HCInMcastPkts.low = scan_val  & 0xffffffff;
  268.                 entry->stats.HCInMcastPkts.high = scan_val >> 32;
  269.             } else if ('N' == line[5]) {
  270.                 entry->stats.InNoRoutes = scan_val;
  271.             } else if ('R' == line[5]) {
  272.                 entry->stats.HCInReceives.low = scan_val & 0xffffffff;
  273.                 entry->stats.HCInReceives.high = scan_val >> 32;
  274.             } else if ('T' == line[5]) {
  275.                 if ('r' == line[6]) {
  276.                     entry->stats.InTruncatedPkts = scan_val  & 0xffffffff;
  277.                 } else if ('o' == line[6])
  278.                     ; /* TooBig isn't in the MIB, so ignore it */
  279.                 else
  280.                     rc = 1;
  281.             } else if ('U' == line[5]) {
  282.                 entry->stats.InUnknownProtos = scan_val;
  283.             } else
  284.                 rc = 1;
  285.         } else if ('O' == line[3]) { /* Out */
  286.             if ('D' == line[6]) {
  287.                 entry->stats.OutDiscards = scan_val;
  288.             } else if ('F' == line[6]) {
  289.                 entry->stats.HCOutForwDatagrams.low = scan_val & 0xffffffff;
  290.                 entry->stats.HCOutForwDatagrams.high = scan_val >> 32;
  291.             } else if ('M' == line[6]) {
  292.                 entry->stats.HCOutMcastPkts.low = scan_val & 0xffffffff;
  293.                 entry->stats.HCOutMcastPkts.high = scan_val >> 32;
  294.             } else if ('N' == line[6]) {
  295.                 entry->stats.OutNoRoutes = scan_val;
  296.             } else if ('R' == line[6]) {
  297.                 entry->stats.HCOutRequests.low = scan_val & 0xffffffff;
  298.                 entry->stats.HCOutRequests.high = scan_val >> 32;
  299.             } else
  300.                 rc = 1;
  301.         } else if ('R' == line[3]) { /* Reasm */
  302.             if ('F' == line[8]) {
  303.                 entry->stats.ReasmFails = scan_val;
  304.             } else if ('O' == line[8]) {
  305.                 entry->stats.ReasmOKs = scan_val;
  306.             } else if ('R' == line[8]) {
  307.                 entry->stats.ReasmReqds = scan_val;
  308.             } else if ('T' == line[8]) {
  309.                 ; /* no mib entry for reasm timeout */
  310.             } else
  311.                 rc = 1;
  312.         } else if ('F' == line[3]) { /* Frag */
  313.             if ('C' == line[7])
  314.                 entry->stats.OutFragCreates = scan_val;
  315.             else if ('O' == line[7])
  316.                 entry->stats.OutFragOKs = scan_val;
  317.             else if ('F' == line[7])
  318.                 entry->stats.OutFragFails = scan_val;
  319.             else
  320.                 rc = 1;
  321.         } else
  322.             rc = 1;
  323.         
  324.         if (rc)
  325.             DEBUGMSGTL(("access:systemstats", "unknown stat %sn", line));
  326.         else
  327.             ++scan_count;
  328.     }
  329.     fclose(devin);
  330.     /*
  331.      * add to container
  332.      */
  333.     CONTAINER_INSERT(container, entry);
  334.     return rc;
  335. }
  336. #endif /* INET6 */