/src/net-snmp/agent/helpers/scalar.c
Line | Count | Source |
1 | | /* Portions of this file are subject to the following copyright(s). See |
2 | | * the Net-SNMP's COPYING file for more details and other copyrights |
3 | | * that may apply: |
4 | | */ |
5 | | /* |
6 | | * Portions of this file are copyrighted by: |
7 | | * Copyright © 2003 Sun Microsystems, 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 | | * Portions of this file are copyrighted by: |
12 | | * Copyright (c) 2016 VMware, Inc. All rights reserved. |
13 | | * Use is subject to license terms specified in the COPYING file |
14 | | * distributed with the Net-SNMP package. |
15 | | */ |
16 | | #include <net-snmp/net-snmp-config.h> |
17 | | |
18 | | #include <net-snmp/net-snmp-includes.h> |
19 | | #include <net-snmp/agent/net-snmp-agent-includes.h> |
20 | | |
21 | | #include <net-snmp/agent/scalar.h> |
22 | | |
23 | | #include <stdlib.h> |
24 | | #ifdef HAVE_STRING_H |
25 | | #include <string.h> |
26 | | #else |
27 | | #include <strings.h> |
28 | | #endif |
29 | | |
30 | | #include <net-snmp/agent/instance.h> |
31 | | #include <net-snmp/agent/serialize.h> |
32 | | #include <net-snmp/agent/read_only.h> |
33 | | |
34 | | /** @defgroup scalar scalar |
35 | | * Process scalars easily. |
36 | | * @ingroup leaf |
37 | | * @{ |
38 | | */ |
39 | | |
40 | | /** |
41 | | * Creates a scalar handler calling netsnmp_create_handler with a |
42 | | * handler name defaulted to "scalar" and access method, |
43 | | * netsnmp_scalar_helper_handler. |
44 | | * |
45 | | * @return Returns a pointer to a netsnmp_mib_handler struct which contains |
46 | | * the handler's name and the access method |
47 | | * |
48 | | * @see netsnmp_get_scalar_handler |
49 | | * @see netsnmp_register_scalar |
50 | | */ |
51 | | netsnmp_mib_handler * |
52 | | netsnmp_get_scalar_handler(void) |
53 | 0 | { |
54 | 0 | return netsnmp_create_handler("scalar", |
55 | 0 | netsnmp_scalar_helper_handler); |
56 | 0 | } |
57 | | |
58 | | /** |
59 | | * This function registers a scalar helper handler. The registered OID, |
60 | | * reginfo->rootoid, space is extended for the instance subid using |
61 | | * realloc() but the reginfo->rootoid_len length is not extended just yet. |
62 | | * .This function subsequently injects the instance, scalar, and serialize |
63 | | * helper handlers before actually registering reginfo. |
64 | | * |
65 | | * Each handler is injected/pushed to the top of the handler chain list |
66 | | * and will be processed last in first out, LIFO. |
67 | | * |
68 | | * @param reginfo a handler registration structure which could get created |
69 | | * using netsnmp_create_handler_registration. Used to register |
70 | | * a scalar helper handler. |
71 | | * |
72 | | * @return MIB_REGISTERED_OK is returned if the registration was a success. |
73 | | * Failures are MIB_REGISTRATION_FAILURE and MIB_DUPLICATE_REGISTRATION. |
74 | | * |
75 | | * @see netsnmp_register_read_only_scalar |
76 | | * @see netsnmp_get_scalar_handler |
77 | | */ |
78 | | |
79 | | int |
80 | | netsnmp_register_scalar(netsnmp_handler_registration *reginfo) |
81 | 0 | { |
82 | 0 | netsnmp_mib_handler *h1 = NULL, *h2 = NULL; |
83 | 0 | oid *tmp; |
84 | | /* |
85 | | * Extend the registered OID with space for the instance subid |
86 | | * (but don't extend the length just yet!) |
87 | | */ |
88 | | |
89 | 0 | tmp = (oid*)realloc(reginfo->rootoid, |
90 | 0 | (reginfo->rootoid_len+1) * sizeof(oid) ); |
91 | 0 | if (tmp == NULL) { |
92 | 0 | goto error; |
93 | 0 | } |
94 | 0 | reginfo->rootoid = tmp; |
95 | 0 | reginfo->rootoid[ reginfo->rootoid_len ] = 0; |
96 | |
|
97 | 0 | h1 = netsnmp_get_instance_handler(); |
98 | 0 | h2 = netsnmp_get_scalar_handler(); |
99 | 0 | if (h1 && h2) { |
100 | 0 | if (netsnmp_inject_handler(reginfo, h1) == SNMPERR_SUCCESS) { |
101 | 0 | h1 = NULL; |
102 | 0 | if (netsnmp_inject_handler(reginfo, h2) == SNMPERR_SUCCESS) |
103 | 0 | return netsnmp_register_serialize(reginfo); |
104 | 0 | } |
105 | 0 | } |
106 | 0 | error: |
107 | 0 | snmp_log(LOG_ERR, "register scalar failed\n"); |
108 | 0 | netsnmp_handler_free(h1); |
109 | 0 | netsnmp_handler_free(h2); |
110 | 0 | netsnmp_handler_registration_free(reginfo); |
111 | |
|
112 | 0 | return MIB_REGISTRATION_FAILED; |
113 | 0 | } |
114 | | |
115 | | /** |
116 | | * This function registers a read only scalar helper handler. This |
117 | | * function is very similar to netsnmp_register_scalar the only addition |
118 | | * is that the "read_only" handler is injected into the handler chain |
119 | | * prior to injecting the serialize handler and registering reginfo. |
120 | | * |
121 | | * @param reginfo a handler registration structure which could get created |
122 | | * using netsnmp_create_handler_registration. Used to register |
123 | | * a read only scalar helper handler. |
124 | | * |
125 | | * @return MIB_REGISTERED_OK is returned if the registration was a success. |
126 | | * Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION. |
127 | | * |
128 | | * @see netsnmp_register_scalar |
129 | | * @see netsnmp_get_scalar_handler |
130 | | * |
131 | | */ |
132 | | |
133 | | int |
134 | | netsnmp_register_read_only_scalar(netsnmp_handler_registration *reginfo) |
135 | 0 | { |
136 | 0 | netsnmp_mib_handler *h1, *h2, *h3; |
137 | | /* |
138 | | * Extend the registered OID with space for the instance subid |
139 | | * (but don't extend the length just yet!) |
140 | | */ |
141 | 0 | reginfo->rootoid = (oid*)realloc(reginfo->rootoid, |
142 | 0 | (reginfo->rootoid_len+1) * sizeof(oid) ); |
143 | 0 | reginfo->rootoid[ reginfo->rootoid_len ] = 0; |
144 | |
|
145 | 0 | h1 = netsnmp_get_instance_handler(); |
146 | 0 | h2 = netsnmp_get_scalar_handler(); |
147 | 0 | h3 = netsnmp_get_read_only_handler(); |
148 | 0 | if (h1 && h2 && h3) { |
149 | 0 | if (netsnmp_inject_handler(reginfo, h1) == SNMPERR_SUCCESS) { |
150 | 0 | h1 = NULL; |
151 | 0 | if (netsnmp_inject_handler(reginfo, h2) == SNMPERR_SUCCESS) { |
152 | 0 | h2 = NULL; |
153 | 0 | if (netsnmp_inject_handler(reginfo, h3) == SNMPERR_SUCCESS) |
154 | 0 | return netsnmp_register_serialize(reginfo); |
155 | 0 | } |
156 | 0 | } |
157 | 0 | } |
158 | | |
159 | 0 | snmp_log(LOG_ERR, "register read only scalar failed\n"); |
160 | 0 | netsnmp_handler_free(h1); |
161 | 0 | netsnmp_handler_free(h2); |
162 | 0 | netsnmp_handler_free(h3); |
163 | 0 | netsnmp_handler_registration_free(reginfo); |
164 | |
|
165 | 0 | return MIB_REGISTRATION_FAILED; |
166 | 0 | } |
167 | | |
168 | | |
169 | | |
170 | | int |
171 | | netsnmp_scalar_helper_handler(netsnmp_mib_handler *handler, |
172 | | netsnmp_handler_registration *reginfo, |
173 | | netsnmp_agent_request_info *reqinfo, |
174 | | netsnmp_request_info *requests) |
175 | 0 | { |
176 | |
|
177 | 0 | netsnmp_variable_list *var = requests->requestvb; |
178 | |
|
179 | 0 | int ret, cmp; |
180 | 0 | int namelen; |
181 | |
|
182 | 0 | DEBUGMSGTL(("helper:scalar", "Got request:\n")); |
183 | 0 | namelen = SNMP_MIN(requests->requestvb->name_length, |
184 | 0 | reginfo->rootoid_len); |
185 | 0 | cmp = snmp_oid_compare(requests->requestvb->name, namelen, |
186 | 0 | reginfo->rootoid, reginfo->rootoid_len); |
187 | |
|
188 | 0 | DEBUGMSGTL(("helper:scalar", " oid:")); |
189 | 0 | DEBUGMSGOID(("helper:scalar", var->name, var->name_length)); |
190 | 0 | DEBUGMSG(("helper:scalar", "\n")); |
191 | |
|
192 | 0 | switch (reqinfo->mode) { |
193 | 0 | case MODE_GET: |
194 | 0 | if (cmp != 0) { |
195 | 0 | netsnmp_set_request_error(reqinfo, requests, |
196 | 0 | SNMP_NOSUCHOBJECT); |
197 | 0 | return SNMP_ERR_NOERROR; |
198 | 0 | } else { |
199 | 0 | reginfo->rootoid[reginfo->rootoid_len++] = 0; |
200 | 0 | ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, |
201 | 0 | requests); |
202 | 0 | reginfo->rootoid_len--; |
203 | 0 | return ret; |
204 | 0 | } |
205 | 0 | break; |
206 | | |
207 | 0 | #ifndef NETSNMP_NO_WRITE_SUPPORT |
208 | 0 | case MODE_SET_RESERVE1: |
209 | 0 | case MODE_SET_RESERVE2: |
210 | 0 | case MODE_SET_ACTION: |
211 | 0 | case MODE_SET_COMMIT: |
212 | 0 | case MODE_SET_UNDO: |
213 | 0 | case MODE_SET_FREE: |
214 | 0 | if (cmp != 0) { |
215 | 0 | netsnmp_set_request_error(reqinfo, requests, |
216 | 0 | SNMP_ERR_NOCREATION); |
217 | 0 | return SNMP_ERR_NOERROR; |
218 | 0 | } else { |
219 | 0 | reginfo->rootoid[reginfo->rootoid_len++] = 0; |
220 | 0 | ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, |
221 | 0 | requests); |
222 | 0 | reginfo->rootoid_len--; |
223 | 0 | return ret; |
224 | 0 | } |
225 | 0 | break; |
226 | 0 | #endif /* NETSNMP_NO_WRITE_SUPPORT */ |
227 | | |
228 | 0 | case MODE_GETNEXT: |
229 | 0 | reginfo->rootoid[reginfo->rootoid_len++] = 0; |
230 | 0 | ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); |
231 | 0 | reginfo->rootoid_len--; |
232 | 0 | return ret; |
233 | 0 | } |
234 | | /* |
235 | | * got here only if illegal mode found |
236 | | */ |
237 | 0 | return SNMP_ERR_GENERR; |
238 | 0 | } |
239 | | |
240 | | /** @} |
241 | | */ |