Coverage Report

Created: 2026-02-14 06:37

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
     * 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
 */