Coverage Report

Created: 2026-02-26 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/agent/helpers/stash_to_next.c
Line
Count
Source
1
#include <net-snmp/net-snmp-config.h>
2
3
#include <net-snmp/net-snmp-features.h>
4
#include <net-snmp/net-snmp-includes.h>
5
#include <net-snmp/agent/net-snmp-agent-includes.h>
6
7
netsnmp_feature_provide(stash_to_next);
8
netsnmp_feature_child_of(stash_to_next, mib_helpers);
9
10
#ifdef NETSNMP_FEATURE_REQUIRE_STASH_TO_NEXT
11
netsnmp_feature_require(oid_stash);
12
netsnmp_feature_require(oid_stash_add_data);
13
#endif
14
15
#ifndef NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT
16
#include <net-snmp/agent/stash_to_next.h>
17
18
#include <net-snmp/agent/stash_cache.h>
19
20
/** @defgroup stash_to_next stash_to_next
21
 *  Convert GET_STASH requests into GETNEXT requests for the handler.
22
 *  The purpose of this handler is to convert a GET_STASH auto-cache request
23
 *  to a series of GETNEXT requests.  It can be inserted into a handler chain
24
 *  where the lower-level handlers don't process such requests themselves.
25
 *  @ingroup utilities
26
 *  @{
27
 */
28
29
/** returns a stash_to_next handler that can be injected into a given
30
 *  handler chain.
31
 */
32
netsnmp_mib_handler *
33
netsnmp_get_stash_to_next_handler(void)
34
3.32k
{
35
3.32k
    netsnmp_mib_handler *handler =
36
3.32k
        netsnmp_create_handler("stash_to_next",
37
3.32k
                               netsnmp_stash_to_next_helper);
38
39
3.32k
    if (NULL != handler)
40
3.32k
        handler->flags |= MIB_HANDLER_AUTO_NEXT;
41
42
3.32k
    return handler;
43
3.32k
}
44
45
/** @internal Implements the stash_to_next handler */
46
int
47
netsnmp_stash_to_next_helper(netsnmp_mib_handler *handler,
48
                            netsnmp_handler_registration *reginfo,
49
                            netsnmp_agent_request_info *reqinfo,
50
                            netsnmp_request_info *requests)
51
0
{
52
53
0
    int             ret = SNMP_ERR_NOERROR;
54
0
    int             namelen;
55
0
    int             finished = 0;
56
0
    netsnmp_oid_stash_node **cinfo;
57
0
    netsnmp_variable_list   *vb;
58
0
    netsnmp_request_info    *reqtmp;
59
60
    /*
61
     * this code depends on AUTO_NEXT being set
62
     */
63
0
    netsnmp_assert(handler->flags & MIB_HANDLER_AUTO_NEXT);
64
65
    /*
66
     * Don't do anything for any modes except GET_STASH. Just return,
67
     * and the agent will call the next handler (AUTO_NEXT).
68
     *
69
     * If the handler chain already supports GET_STASH, we don't
70
     * need to do anything here either.  Once again, we just return
71
     * and the agent will call the next handler (AUTO_NEXT).
72
     *
73
     * Otherwise, we munge the mode to GET_NEXT, and call the
74
     * next handler ourselves, repeatedly until we've retrieved the
75
     * full contents of the table or subtree.
76
     *   Then restore the mode and return to the calling handler 
77
     * (setting AUTO_NEXT_OVERRRIDE so the agent knows what we did).
78
     */
79
0
    if (MODE_GET_STASH == reqinfo->mode) {
80
0
        if ( reginfo->modes & HANDLER_CAN_STASH ) {
81
0
            return ret;
82
0
        }
83
0
        cinfo  = netsnmp_extract_stash_cache( reqinfo );
84
0
        reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info);
85
0
        vb = reqtmp->requestvb = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
86
0
        vb->type = ASN_NULL;
87
0
        snmp_set_var_objid( vb, reginfo->rootoid, reginfo->rootoid_len );
88
89
0
        reqinfo->mode = MODE_GETNEXT;
90
0
        while (!finished) {
91
0
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, reqtmp);
92
0
            namelen = SNMP_MIN(vb->name_length, reginfo->rootoid_len);
93
0
            if ( !snmp_oid_compare( reginfo->rootoid, reginfo->rootoid_len,
94
0
                                   vb->name, namelen) &&
95
0
                 vb->type != ASN_NULL && vb->type != SNMP_ENDOFMIBVIEW ) {
96
                /*
97
                 * This result is relevant so save it, and prepare
98
                 * the request varbind for the next query.
99
                 */
100
0
                netsnmp_oid_stash_add_data( cinfo, vb->name, vb->name_length,
101
0
                                            snmp_clone_varbind( vb ));
102
                    /*
103
                     * Tidy up the response structure,
104
                     *  ready for retrieving the next entry
105
                     */
106
0
                netsnmp_free_all_list_data(reqtmp->parent_data);
107
0
                reqtmp->parent_data = NULL;
108
0
                reqtmp->processed = 0;
109
0
                vb->type = ASN_NULL;
110
0
            } else {
111
0
                finished = 1;
112
0
            }
113
0
        }
114
0
        reqinfo->mode = MODE_GET_STASH;
115
116
        /*
117
         * let the handler chain processing know that we've already
118
         * called the next handler
119
         */
120
0
        handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
121
0
    }
122
123
0
    return ret;
124
0
}
125
/**  @} */
126
127
#else  /* ! NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT */
128
netsnmp_feature_unused(stash_to_next);
129
#endif /* ! NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT */