/src/net-snmp/agent/helpers/bulk_to_next.c
Line | Count | Source (jump to first uncovered line) |
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 | | #include <net-snmp/net-snmp-config.h> |
12 | | |
13 | | #include <net-snmp/net-snmp-includes.h> |
14 | | #include <net-snmp/agent/net-snmp-agent-includes.h> |
15 | | |
16 | | #include <net-snmp/agent/bulk_to_next.h> |
17 | | |
18 | | /** @defgroup bulk_to_next bulk_to_next |
19 | | * Convert GETBULK requests into GETNEXT requests for the handler. |
20 | | * The only purpose of this handler is to convert a GETBULK request |
21 | | * to a GETNEXT request. It is inserted into handler chains where |
22 | | * the handler has not set the HANDLER_CAN_GETBULK flag. |
23 | | * @ingroup utilities |
24 | | * @{ |
25 | | */ |
26 | | |
27 | | /** returns a bulk_to_next handler that can be injected into a given |
28 | | * handler chain. |
29 | | */ |
30 | | netsnmp_mib_handler * |
31 | | netsnmp_get_bulk_to_next_handler(void) |
32 | 2.61k | { |
33 | 2.61k | netsnmp_mib_handler *handler = |
34 | 2.61k | netsnmp_create_handler("bulk_to_next", |
35 | 2.61k | netsnmp_bulk_to_next_helper); |
36 | | |
37 | 2.61k | if (NULL != handler) |
38 | 2.61k | handler->flags |= MIB_HANDLER_AUTO_NEXT; |
39 | | |
40 | 2.61k | return handler; |
41 | 2.61k | } |
42 | | |
43 | | /** takes answered requests and decrements the repeat count and |
44 | | * updates the requests to the next to-do varbind in the list */ |
45 | | void |
46 | | netsnmp_bulk_to_next_fix_requests(netsnmp_request_info *requests) |
47 | 0 | { |
48 | 0 | netsnmp_request_info *request; |
49 | | /* |
50 | | * Make sure that: |
51 | | * - repeats remain |
52 | | * - last handler provided an answer |
53 | | * - answer didn't exceed range end (ala check_getnext_results) |
54 | | * - there is a next variable |
55 | | * then |
56 | | * update the varbinds for the next request series |
57 | | */ |
58 | 0 | for (request = requests; request; request = request->next) { |
59 | 0 | if (request->repeat > 0 && |
60 | 0 | request->requestvb->type != ASN_NULL && |
61 | 0 | request->requestvb->type != ASN_PRIV_RETRY && |
62 | 0 | (snmp_oid_compare(request->requestvb->name, |
63 | 0 | request->requestvb->name_length, |
64 | 0 | request->range_end, |
65 | 0 | request->range_end_len) < 0) && |
66 | 0 | request->requestvb->next_variable ) { |
67 | 0 | request->repeat--; |
68 | 0 | snmp_set_var_objid(request->requestvb->next_variable, |
69 | 0 | request->requestvb->name, |
70 | 0 | request->requestvb->name_length); |
71 | 0 | request->requestvb = request->requestvb->next_variable; |
72 | 0 | request->requestvb->type = ASN_PRIV_RETRY; |
73 | | /* |
74 | | * if inclusive == 2, it was set in check_getnext_results for |
75 | | * the previous requestvb. Now that we've moved on, clear it. |
76 | | */ |
77 | 0 | if (2 == request->inclusive) |
78 | 0 | request->inclusive = 0; |
79 | 0 | } |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | | /** @internal Implements the bulk_to_next handler */ |
84 | | int |
85 | | netsnmp_bulk_to_next_helper(netsnmp_mib_handler *handler, |
86 | | netsnmp_handler_registration *reginfo, |
87 | | netsnmp_agent_request_info *reqinfo, |
88 | | netsnmp_request_info *requests) |
89 | 0 | { |
90 | |
|
91 | 0 | int ret = SNMP_ERR_NOERROR; |
92 | | |
93 | | /* |
94 | | * this code depends on AUTO_NEXT being set |
95 | | */ |
96 | 0 | netsnmp_assert(handler->flags & MIB_HANDLER_AUTO_NEXT); |
97 | | |
98 | | /* |
99 | | * don't do anything for any modes besides GETBULK. Just return, and |
100 | | * the agent will call the next handler (AUTO_NEXT). |
101 | | * |
102 | | * for GETBULK, we munge the mode, call the next handler ourselves |
103 | | * (setting AUTO_NEXT_OVERRRIDE so the agent knows what we did), |
104 | | * restore the mode and fix up the requests. |
105 | | */ |
106 | 0 | if(MODE_GETBULK == reqinfo->mode) { |
107 | |
|
108 | 0 | DEBUGIF("bulk_to_next") { |
109 | 0 | netsnmp_request_info *req = requests; |
110 | 0 | while(req) { |
111 | 0 | DEBUGMSGTL(("bulk_to_next", "Got request: ")); |
112 | 0 | DEBUGMSGOID(("bulk_to_next", req->requestvb->name, |
113 | 0 | req->requestvb->name_length)); |
114 | 0 | DEBUGMSG(("bulk_to_next", "\n")); |
115 | 0 | req = req->next; |
116 | 0 | } |
117 | 0 | } |
118 | |
|
119 | 0 | reqinfo->mode = MODE_GETNEXT; |
120 | 0 | ret = |
121 | 0 | netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); |
122 | 0 | reqinfo->mode = MODE_GETBULK; |
123 | | |
124 | | /* |
125 | | * update the varbinds for the next request series |
126 | | */ |
127 | 0 | netsnmp_bulk_to_next_fix_requests(requests); |
128 | | |
129 | | /* |
130 | | * let agent handler know that we've already called next handler |
131 | | */ |
132 | 0 | handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; |
133 | 0 | } |
134 | |
|
135 | 0 | return ret; |
136 | 0 | } |
137 | | |
138 | | /** initializes the bulk_to_next helper which then registers a bulk_to_next |
139 | | * handler as a run-time injectable handler for configuration file |
140 | | * use. |
141 | | */ |
142 | | void |
143 | | netsnmp_init_bulk_to_next_helper(void) |
144 | 2.61k | { |
145 | 2.61k | netsnmp_mib_handler *hnd = netsnmp_get_bulk_to_next_handler(); |
146 | 2.61k | if (!hnd) |
147 | 0 | return; |
148 | | |
149 | 2.61k | netsnmp_register_handler_by_name("bulk_to_next", hnd); |
150 | 2.61k | } |
151 | | /** @} */ |
152 | | |