1 /*
2  * Portions of this file are subject to the following copyright(s).  See
3  * the Net-SNMP's COPYING file for more details and other copyrights
4  * that may apply:
5  *
6  * Portions of this file are copyrighted by:
7  * Copyright (c) 2016 VMware, Inc. All rights reserved.
8  * Use is subject to license terms specified in the COPYING file
9  * distributed with the Net-SNMP package.
10  */
11 
12 #include <net-snmp/net-snmp-config.h>
13 #include <net-snmp/net-snmp-features.h>
14 #include <net-snmp/net-snmp-includes.h>
15 #include <net-snmp/agent/net-snmp-agent-includes.h>
16 #include <net-snmp/agent/snmp_get_statistic.h>
17 #include <stdint.h>
18 
19 netsnmp_feature_provide(helper_statistics);
20 netsnmp_feature_child_of(helper_statistics, mib_helpers);
21 
22 #ifdef NETSNMP_FEATURE_REQUIRE_HELPER_STATISTICS
23 /* if we're not needed, then neither is this */
24 netsnmp_feature_require(statistics);
25 #endif
26 
27 #ifndef NETSNMP_FEATURE_REMOVE_HELPER_STATISTICS
28 static int
netsnmp_get_statistic_helper_handler(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)29 netsnmp_get_statistic_helper_handler(netsnmp_mib_handler *handler,
30                                      netsnmp_handler_registration *reginfo,
31                                      netsnmp_agent_request_info *reqinfo,
32                                      netsnmp_request_info *requests)
33 {
34     if (reqinfo->mode == MODE_GET) {
35         const oid idx = requests->requestvb->name[reginfo->rootoid_len - 2] +
36             (oid)(uintptr_t)handler->myvoid;
37         uint32_t value;
38 
39         if (idx > NETSNMP_STAT_MAX_STATS)
40             return SNMP_ERR_GENERR;
41         value = snmp_get_statistic(idx);
42         snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
43                                  (const u_char*)&value, sizeof(value));
44         return SNMP_ERR_NOERROR;
45     }
46     return SNMP_ERR_GENERR;
47 }
48 
49 static netsnmp_mib_handler *
netsnmp_get_statistic_handler(int offset)50 netsnmp_get_statistic_handler(int offset)
51 {
52     netsnmp_mib_handler *ret =
53         netsnmp_create_handler("get_statistic",
54                                netsnmp_get_statistic_helper_handler);
55     if (ret) {
56         ret->flags |= MIB_HANDLER_AUTO_NEXT;
57         ret->myvoid = (void*)(uintptr_t)offset;
58     }
59     return ret;
60 }
61 
62 int
netsnmp_register_statistic_handler(netsnmp_handler_registration * reginfo,oid start,int begin,int end)63 netsnmp_register_statistic_handler(netsnmp_handler_registration *reginfo,
64                                    oid start, int begin, int end)
65 {
66     netsnmp_mib_handler *handler =
67         netsnmp_get_statistic_handler(begin - start);
68     if (!handler ||
69         (netsnmp_inject_handler(reginfo, handler) != SNMPERR_SUCCESS)) {
70         snmp_log(LOG_ERR, "could not create statistic handler\n");
71         netsnmp_handler_free(handler);
72         netsnmp_handler_registration_free(reginfo);
73         return MIB_REGISTRATION_FAILED;
74     }
75     return netsnmp_register_scalar_group(reginfo, start,
76                                          start + (end - begin));
77 }
78 #else /* !NETSNMP_FEATURE_REMOVE_HELPER_GET_STATISTICS */
79 netsnmp_feature_unused(helper_statistics);
80 #endif /* !NETSNMP_FEATURE_REMOVE_HELPER_GET_STATISTICS */
81