Coverage Report

Created: 2023-09-25 06:12

/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