Coverage Report

Created: 2026-10-17 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
0
    if (!reginfo)
86
0
        return MIB_REGISTRATION_FAILED;
87
    /*
88
     * Extend the registered OID with space for the instance subid
89
     * (but don't extend the length just yet!)
90
     */
91
    
92
0
    tmp = (oid*)realloc(reginfo->rootoid,
93
0
                                    (reginfo->rootoid_len+1) * sizeof(oid) );
94
0
    if (tmp == NULL) {
95
0
        goto error;
96
0
    }
97
0
    reginfo->rootoid = tmp;
98
0
    reginfo->rootoid[ reginfo->rootoid_len ] = 0;
99
100
0
    h1 = netsnmp_get_instance_handler();
101
0
    h2 = netsnmp_get_scalar_handler();
102
0
    if (h1 && h2) {
103
0
        if (netsnmp_inject_handler(reginfo, h1) == SNMPERR_SUCCESS) {
104
0
            h1 = NULL;
105
0
            if (netsnmp_inject_handler(reginfo, h2) == SNMPERR_SUCCESS)
106
0
                return netsnmp_register_serialize(reginfo);
107
0
        }
108
0
    }
109
0
    error:
110
0
    snmp_log(LOG_ERR, "register scalar failed\n");
111
0
    netsnmp_handler_free(h1);
112
0
    netsnmp_handler_free(h2);
113
0
    netsnmp_handler_registration_free(reginfo);
114
115
0
    return MIB_REGISTRATION_FAILED;
116
0
}
117
118
/**
119
 * This function registers a read only scalar helper handler. This 
120
 * function is very similar to netsnmp_register_scalar the only addition
121
 * is that the "read_only" handler is injected into the handler chain
122
 * prior to injecting the serialize handler and registering reginfo.
123
 *
124
 * @param reginfo a handler registration structure which could get created
125
 *                using netsnmp_create_handler_registration.  Used to register
126
 *                a read only scalar helper handler.
127
 *
128
 * @return  MIB_REGISTERED_OK is returned if the registration was a success.
129
 *    Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
130
 *
131
 * @see netsnmp_register_scalar
132
 * @see netsnmp_get_scalar_handler
133
 *
134
 */
135
 
136
int
137
netsnmp_register_read_only_scalar(netsnmp_handler_registration *reginfo)
138
0
{
139
0
    netsnmp_mib_handler *h1, *h2, *h3;
140
0
    oid *new_oid;
141
142
0
    if (!reginfo)
143
0
        return MIB_REGISTRATION_FAILED;
144
145
    /*
146
     * Extend the registered OID with space for the instance subid
147
     * (but don't extend the length just yet!)
148
     */
149
0
    new_oid = (oid*)realloc(reginfo->rootoid,
150
0
                            (reginfo->rootoid_len+1) * sizeof(oid) );
151
0
    if (!new_oid) {
152
0
        netsnmp_handler_registration_free(reginfo);
153
0
        return MIB_REGISTRATION_FAILED;
154
0
    }
155
0
    reginfo->rootoid = new_oid;
156
0
    reginfo->rootoid[ reginfo->rootoid_len ] = 0;
157
158
0
    h1 = netsnmp_get_instance_handler();
159
0
    h2 = netsnmp_get_scalar_handler();
160
0
    h3 = netsnmp_get_read_only_handler();
161
0
    if (h1 && h2 && h3) {
162
0
        if (netsnmp_inject_handler(reginfo, h1) == SNMPERR_SUCCESS) {
163
0
            h1 = NULL;
164
0
            if (netsnmp_inject_handler(reginfo, h2) == SNMPERR_SUCCESS) {
165
0
                h2 = NULL;
166
0
                if (netsnmp_inject_handler(reginfo, h3) == SNMPERR_SUCCESS)
167
0
                    return netsnmp_register_serialize(reginfo);
168
0
            }
169
0
        }
170
0
    }
171
172
0
    snmp_log(LOG_ERR, "register read only scalar failed\n");
173
0
    netsnmp_handler_free(h1);
174
0
    netsnmp_handler_free(h2);
175
0
    netsnmp_handler_free(h3);
176
0
    netsnmp_handler_registration_free(reginfo);
177
178
0
    return MIB_REGISTRATION_FAILED;
179
0
}
180
181
182
183
int
184
netsnmp_scalar_helper_handler(netsnmp_mib_handler *handler,
185
                                netsnmp_handler_registration *reginfo,
186
                                netsnmp_agent_request_info *reqinfo,
187
                                netsnmp_request_info *requests)
188
0
{
189
190
0
    netsnmp_variable_list *var = requests->requestvb;
191
192
0
    int             ret, cmp;
193
0
    int             namelen;
194
195
0
    DEBUGMSGTL(("helper:scalar", "Got request:\n"));
196
0
    namelen = SNMP_MIN(requests->requestvb->name_length,
197
0
                       reginfo->rootoid_len);
198
0
    cmp = snmp_oid_compare(requests->requestvb->name, namelen,
199
0
                           reginfo->rootoid, reginfo->rootoid_len);
200
201
0
    DEBUGMSGTL(("helper:scalar", "  oid:"));
202
0
    DEBUGMSGOID(("helper:scalar", var->name, var->name_length));
203
0
    DEBUGMSG(("helper:scalar", "\n"));
204
205
0
    switch (reqinfo->mode) {
206
0
    case MODE_GET:
207
0
        if (cmp != 0) {
208
0
            netsnmp_set_request_error(reqinfo, requests,
209
0
                                      SNMP_NOSUCHOBJECT);
210
0
            return SNMP_ERR_NOERROR;
211
0
        } else {
212
0
            reginfo->rootoid[reginfo->rootoid_len++] = 0;
213
0
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
214
0
                                             requests);
215
0
            reginfo->rootoid_len--;
216
0
            return ret;
217
0
        }
218
0
        break;
219
220
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
221
0
    case MODE_SET_RESERVE1:
222
0
    case MODE_SET_RESERVE2:
223
0
    case MODE_SET_ACTION:
224
0
    case MODE_SET_COMMIT:
225
0
    case MODE_SET_UNDO:
226
0
    case MODE_SET_FREE:
227
0
        if (cmp != 0) {
228
0
            netsnmp_set_request_error(reqinfo, requests,
229
0
                                      SNMP_ERR_NOCREATION);
230
0
            return SNMP_ERR_NOERROR;
231
0
        } else {
232
0
            reginfo->rootoid[reginfo->rootoid_len++] = 0;
233
0
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
234
0
                                             requests);
235
0
            reginfo->rootoid_len--;
236
0
            return ret;
237
0
        }
238
0
        break;
239
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
240
241
0
    case MODE_GETNEXT:
242
0
        reginfo->rootoid[reginfo->rootoid_len++] = 0;
243
0
        ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
244
0
        reginfo->rootoid_len--;
245
0
        return ret;
246
0
    }
247
    /*
248
     * got here only if illegal mode found 
249
     */
250
0
    return SNMP_ERR_GENERR;
251
0
}
252
253
/** @} 
254
 */