2
* callback.c: A generic callback mechanism
4
/* Portions of this file are subject to the following copyright(s). See
5
* the Net-SNMP's COPYING file for more details and other copyrights
9
* Portions of this file are copyrighted by:
10
* Copyright ļæ½ 2003 Sun Microsystems, Inc. All rights reserved.
11
* Use is subject to license terms specified in the COPYING file
12
* distributed with the Net-SNMP package.
14
/** @defgroup callback A generic callback mechanism
19
#include <net-snmp/net-snmp-config.h>
20
#include <sys/types.h>
29
#include <netinet/in.h>
41
#include <net-snmp/types.h>
42
#include <net-snmp/output_api.h>
43
#include <net-snmp/utilities.h>
45
#include <net-snmp/library/callback.h>
46
#include <net-snmp/library/snmp_api.h>
48
static struct snmp_gen_callback
49
*thecallbacks[MAX_CALLBACK_IDS][MAX_CALLBACK_SUBIDS];
52
* the chicken. or the egg. You pick.
58
* probably not needed? Should be full of 0's anyway?
61
* (poses a problem if you put init_callbacks() inside of
62
* init_snmp() and then want the app to register a callback before
63
* init_snmp() is called in the first place. -- Wes
66
* memset(thecallbacks, 0, sizeof(thecallbacks));
68
DEBUGMSGTL(("callback", "initialized\n"));
72
* This function registers a generic callback function. The major and
73
* minor values are used to set the new_callback function into a global
74
* static multi-dimensional array of type struct snmp_gen_callback.
75
* The function makes sure to append this callback function at the end
76
* of the link list, snmp_gen_callback->next.
78
* @param major is the SNMP callback major type used
79
* - SNMP_CALLBACK_LIBRARY
80
* - SNMP_CALLBACK_APPLICATION
82
* @param minor is the SNMP callback minor type used
83
* - SNMP_CALLBACK_POST_READ_CONFIG
84
* - SNMP_CALLBACK_STORE_DATA
85
* - SNMP_CALLBACK_SHUTDOWN
86
* - SNMP_CALLBACK_POST_PREMIB_READ_CONFIG
87
* - SNMP_CALLBACK_LOGGING
88
* - SNMP_CALLBACK_SESSION_INIT
90
* @param new_callback is the callback function that is registered.
92
* @param arg when not NULL is a void pointer used whenever new_callback
93
* function is exercised.
96
* Returns SNMPERR_GENERR if major is >= MAX_CALLBACK_IDS or minor is >=
97
* MAX_CALLBACK_SUBIDS or a snmp_gen_callback pointer could not be
98
* allocated, otherwise SNMPERR_SUCCESS is returned.
99
* - #define MAX_CALLBACK_IDS 2
100
* - #define MAX_CALLBACK_SUBIDS 16
102
* @see snmp_call_callbacks
103
* @see snmp_unregister_callback
106
snmp_register_callback(int major, int minor, SNMPCallback * new_callback,
109
return netsnmp_register_callback( major, minor, new_callback, arg, 0);
113
netsnmp_register_callback(int major, int minor, SNMPCallback * new_callback,
114
void *arg, int priority)
116
struct snmp_gen_callback *newscp = NULL, *scp = NULL;
117
struct snmp_gen_callback **prevNext = &(thecallbacks[major][minor]);
119
if (major >= MAX_CALLBACK_IDS || minor >= MAX_CALLBACK_SUBIDS) {
120
return SNMPERR_GENERR;
123
if ((newscp = SNMP_MALLOC_STRUCT(snmp_gen_callback)) == NULL) {
124
return SNMPERR_GENERR;
126
newscp->priority = priority;
127
newscp->sc_client_arg = arg;
128
newscp->sc_callback = new_callback;
131
for (scp = thecallbacks[major][minor]; scp != NULL;
133
if (newscp->priority < scp->priority) {
137
prevNext = &(scp->next);
142
DEBUGMSGTL(("callback", "registered (%d,%d) at %p with priority %d\n",
143
major, minor, newscp, priority));
144
return SNMPERR_SUCCESS;
149
* This function calls the callback function for each registered callback of
150
* type major and minor.
152
* @param major is the SNMP callback major type used
154
* @param minor is the SNMP callback minor type used
156
* @param caller_arg is a void pointer which is sent in as the callback's
157
* serverarg parameter, if needed.
159
* @return Returns SNMPERR_GENERR if major is >= MAX_CALLBACK_IDS or
160
* minor is >= MAX_CALLBACK_SUBIDS, otherwise SNMPERR_SUCCESS is returned.
162
* @see snmp_register_callback
163
* @see snmp_unregister_callback
166
snmp_call_callbacks(int major, int minor, void *caller_arg)
168
struct snmp_gen_callback *scp;
169
unsigned int count = 0;
171
if (major >= MAX_CALLBACK_IDS || minor >= MAX_CALLBACK_SUBIDS) {
172
return SNMPERR_GENERR;
175
DEBUGMSGTL(("callback", "START calling callbacks for maj=%d min=%d\n",
179
* for each registered callback of type major and minor
181
for (scp = thecallbacks[major][minor]; scp != NULL; scp = scp->next) {
183
DEBUGMSGTL(("callback", "calling a callback for maj=%d min=%d\n",
189
(*(scp->sc_callback)) (major, minor, caller_arg,
194
DEBUGMSGTL(("callback",
195
"END calling callbacks for maj=%d min=%d (%d called)\n",
196
major, minor, count));
198
return SNMPERR_SUCCESS;
202
snmp_count_callbacks(int major, int minor)
205
struct snmp_gen_callback *scp;
207
if (major >= MAX_CALLBACK_IDS || minor >= MAX_CALLBACK_SUBIDS) {
208
return SNMPERR_GENERR;
211
for (scp = thecallbacks[major][minor]; scp != NULL; scp = scp->next) {
219
snmp_callback_available(int major, int minor)
221
if (major >= MAX_CALLBACK_IDS || minor >= MAX_CALLBACK_SUBIDS) {
222
return SNMPERR_GENERR;
225
if (thecallbacks[major][minor] != NULL) {
226
return SNMPERR_SUCCESS;
229
return SNMPERR_GENERR;
233
* This function unregisters a specified callback function given a major
236
* Note: no bound checking on major and minor.
238
* @param major is the SNMP callback major type used
240
* @param minor is the SNMP callback minor type used
242
* @param target is the callback function that will be unregistered.
244
* @param arg is a void pointer used for comparison against the registered
245
* callback's sc_client_arg variable.
247
* @param matchargs is an integer used to bypass the comparison of arg and the
248
* callback's sc_client_arg variable only when matchargs is set to 0.
252
* Returns the number of callbacks that were unregistered.
254
* @see snmp_register_callback
255
* @see snmp_call_callbacks
259
snmp_unregister_callback(int major, int minor, SNMPCallback * target,
260
void *arg, int matchargs)
262
struct snmp_gen_callback *scp = thecallbacks[major][minor];
263
struct snmp_gen_callback **prevNext = &(thecallbacks[major][minor]);
266
while (scp != NULL) {
267
if ((scp->sc_callback == target) &&
268
(!matchargs || (scp->sc_client_arg == arg))) {
269
DEBUGMSGTL(("callback", "unregistering (%d,%d) at %p\n", major,
271
*prevNext = scp->next;
276
prevNext = &(scp->next);
287
unsigned int i = 0, j = 0;
288
struct snmp_gen_callback *scp = NULL, *next = NULL;
290
DEBUGMSGTL(("callback", "clear callback\n"));
291
for (i = 0; i < MAX_CALLBACK_IDS; i++) {
292
for (j = 0; j < MAX_CALLBACK_SUBIDS; j++) {
293
scp = thecallbacks[i][j];
294
while (scp != NULL) {
296
if (scp->sc_client_arg != NULL)
297
SNMP_FREE(scp->sc_client_arg);
301
thecallbacks[i][j] = NULL;
306
struct snmp_gen_callback *
307
snmp_callback_list(int major, int minor)
309
return (thecallbacks[major][minor]);