Coverage Report

Created: 2025-08-11 06:35

/src/net-snmp/agent/mibgroup/agentx/master.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  AgentX master agent
3
 */
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
6
 * that may apply:
7
 */
8
/*
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.
13
 */
14
15
16
#include <net-snmp/net-snmp-config.h>
17
#include <net-snmp/net-snmp-features.h>
18
#ifdef HAVE_IO_H
19
#include <io.h>
20
#endif
21
22
#include <stdio.h>
23
#include <sys/types.h>
24
#ifdef HAVE_STDLIB_H
25
#include <stdlib.h>
26
#endif
27
#ifdef HAVE_STRING_H
28
#include <string.h>
29
#else
30
#include <strings.h>
31
#endif
32
#ifdef HAVE_NETINET_IN_H
33
#include <netinet/in.h>
34
#endif
35
#ifdef HAVE_SYS_SOCKET_H
36
#include <sys/socket.h>
37
#endif
38
#include <errno.h>
39
40
#ifdef HAVE_UNISTD_H
41
#include <unistd.h>
42
#endif
43
#ifdef HAVE_SYS_STAT_H
44
#include <sys/stat.h>
45
#endif
46
47
#define SNMP_NEED_REQUEST_LIST
48
#include <net-snmp/net-snmp-includes.h>
49
#include <net-snmp/agent/net-snmp-agent-includes.h>
50
#include "snmpd.h"
51
#include "agentx/protocol.h"
52
#include "agentx/master_admin.h"
53
54
netsnmp_feature_require(handler_mark_requests_as_delegated);
55
netsnmp_feature_require(unix_socket_paths);
56
netsnmp_feature_require(free_agent_snmp_session_by_session);
57
58
void
59
real_init_master(void)
60
0
{
61
0
    netsnmp_session sess, *session = NULL;
62
0
    char *agentx_sockets;
63
0
    char *cp1;
64
65
0
    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) != MASTER_AGENT)
66
0
        return;
67
68
0
    if (netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
69
0
                              NETSNMP_DS_AGENT_X_SOCKET)) {
70
0
       agentx_sockets = strdup(netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
71
0
                                                     NETSNMP_DS_AGENT_X_SOCKET));
72
#ifdef NETSNMP_AGENTX_DOM_SOCK_ONLY
73
       if (agentx_sockets[0] != '/') {
74
           /* unix:/path */
75
           if (agentx_sockets[5] != '/') {
76
               snmp_log(LOG_ERR,
77
                    "Error: %s transport is not supported, disabling agentx/master.\n", agentx_sockets);
78
               SNMP_FREE(agentx_sockets);
79
               return;
80
           }
81
       }
82
#endif
83
0
    } else {
84
0
        agentx_sockets = strdup("");
85
0
    }
86
87
88
0
    DEBUGMSGTL(("agentx/master", "initializing...\n"));
89
0
    snmp_sess_init(&sess);
90
0
    sess.version = AGENTX_VERSION_1;
91
0
    sess.flags |= SNMP_FLAGS_STREAM_SOCKET;
92
0
    sess.timeout = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
93
0
                                      NETSNMP_DS_AGENT_AGENTX_TIMEOUT);
94
0
    sess.retries = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
95
0
                                      NETSNMP_DS_AGENT_AGENTX_RETRIES);
96
97
0
#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
98
0
    {
99
0
  int agentx_dir_perm =
100
0
      netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
101
0
             NETSNMP_DS_AGENT_X_DIR_PERM);
102
0
  if (agentx_dir_perm == 0)
103
0
      agentx_dir_perm = NETSNMP_AGENT_DIRECTORY_MODE;
104
0
  netsnmp_unix_create_path_with_mode(agentx_dir_perm);
105
0
    }
106
0
#endif
107
108
0
    cp1 = agentx_sockets;
109
0
    while (cp1) {
110
0
        netsnmp_transport *t;
111
        /*
112
         *  If the AgentX socket string contains multiple descriptors,
113
         *  then pick this apart and handle them one by one.
114
         *
115
         */
116
0
        sess.peername = cp1;
117
0
        cp1 = strchr(sess.peername, ',');
118
0
        if (cp1 != NULL) {
119
0
            *cp1++ = '\0';
120
0
  }
121
122
        /*
123
         *  Let 'snmp_open' interpret the descriptor.
124
         */
125
0
        sess.local_port = AGENTX_PORT;      /* Indicate server & set default port */
126
0
        sess.callback = handle_master_agentx_packet;
127
0
        errno = 0;
128
0
        t = netsnmp_transport_open_server("agentx", sess.peername);
129
0
        if (t == NULL) {
130
            /*
131
             * diagnose snmp_open errors with the input netsnmp_session
132
             * pointer.
133
             */
134
0
            char buf[1024];
135
0
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
136
0
                                        NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
137
0
                snprintf(buf, sizeof(buf),
138
0
                         "Error: Couldn't open a master agentx socket to "
139
0
                         "listen on (%s)", sess.peername);
140
0
                snmp_sess_perror(buf, &sess);
141
0
                exit(1);
142
0
            } else {
143
0
                snprintf(buf, sizeof(buf),
144
0
                         "Warning: Couldn't open a master agentx socket to "
145
0
                         "listen on (%s)", sess.peername);
146
0
                netsnmp_sess_log_error(LOG_WARNING, buf, &sess);
147
0
            }
148
0
        } else {
149
0
#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
150
0
            if (t->domain == netsnmp_UnixDomain && t->local != NULL) {
151
                /*
152
                 * Apply any settings to the ownership/permissions of the
153
                 * AgentX socket
154
                 */
155
0
                int agentx_sock_perm =
156
0
                    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
157
0
                                       NETSNMP_DS_AGENT_X_SOCK_PERM);
158
0
                int agentx_sock_user =
159
0
                    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
160
0
                                       NETSNMP_DS_AGENT_X_SOCK_USER);
161
0
                int agentx_sock_group =
162
0
                    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
163
0
                                       NETSNMP_DS_AGENT_X_SOCK_GROUP);
164
165
0
                char name[sizeof(struct sockaddr_un) + 1];
166
0
                memcpy(name, t->local, t->local_length);
167
0
                name[t->local_length] = '\0';
168
169
0
                if (agentx_sock_perm != 0)
170
0
                    chmod(name, agentx_sock_perm);
171
172
0
                if (agentx_sock_user || agentx_sock_group) {
173
                    /*
174
                     * If either of user or group haven't been set,
175
                     *  then leave them unchanged.
176
                     */
177
0
                    if (agentx_sock_user == 0 )
178
0
                        agentx_sock_user = -1;
179
0
                    if (agentx_sock_group == 0 )
180
0
                        agentx_sock_group = -1;
181
0
                    NETSNMP_IGNORE_RESULT(chown(name, agentx_sock_user,
182
0
                                                agentx_sock_group));
183
0
                }
184
0
            }
185
0
#endif
186
0
            session =
187
0
                snmp_add_full(&sess, t, NULL, agentx_parse, NULL, NULL,
188
0
                              agentx_realloc_build, agentx_check_packet, NULL);
189
            /* snmp_add_full() frees 't' upon failure. */
190
0
            if (!session)
191
0
                t = NULL;
192
0
        }
193
0
        if (session == NULL) {
194
0
            netsnmp_transport_free(t);
195
0
        }
196
0
    }
197
198
0
#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
199
0
    netsnmp_unix_dont_create_path();
200
0
#endif
201
202
0
    SNMP_FREE(agentx_sockets);
203
0
    DEBUGMSGTL(("agentx/master", "initializing...   DONE\n"));
204
0
}
205
206
        /*
207
         * Handle the response from an AgentX subagent,
208
         *   merging the answers back into the original query
209
         */
210
int
211
agentx_got_response(int operation,
212
                    netsnmp_session * session,
213
                    int reqid, netsnmp_pdu *pdu, void *magic)
214
0
{
215
0
    netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) magic;
216
0
    int             i, ret;
217
0
    netsnmp_request_info *requests, *request;
218
0
    netsnmp_variable_list *var;
219
220
0
    cache = netsnmp_handler_check_cache(cache);
221
0
    if (!cache) {
222
0
        DEBUGMSGTL(("agentx/master", "response too late on session %8p\n",
223
0
                    session));
224
        /* response is too late, free the cache */
225
0
        if (magic)
226
0
            netsnmp_free_delegated_cache((netsnmp_delegated_cache*) magic);
227
0
        return 1;
228
0
    }
229
0
    requests = cache->requests;
230
231
0
    switch (operation) {
232
0
    case NETSNMP_CALLBACK_OP_TIMED_OUT:{
233
0
            struct session_list *s = snmp_sess_pointer(session);
234
0
            DEBUGMSGTL(("agentx/master", "timeout on session %8p req=0x%x\n",
235
0
                        session, (unsigned)reqid));
236
237
0
            netsnmp_handler_mark_requests_as_delegated(requests,
238
0
                                       REQUEST_IS_NOT_DELEGATED);
239
0
            netsnmp_set_request_error(cache->reqinfo, requests,
240
                                      /* XXXWWW: should be index=0 */
241
0
                                      SNMP_ERR_GENERR);
242
243
            /*
244
             * This is a bit sledgehammer because the other sessions on this
245
             * transport may be okay (e.g. some thread in the subagent has
246
             * wedged, but the others are alright).  OTOH the overwhelming
247
             * probability is that the whole agent has died somehow.  
248
             */
249
250
0
            if (s != NULL) {
251
0
                netsnmp_transport *t = snmp_sess_transport(s);
252
0
                close_agentx_session(session, -1);
253
254
0
                if (t != NULL) {
255
0
                    DEBUGMSGTL(("agentx/master", "close transport\n"));
256
0
                    t->f_close(t);
257
0
                } else {
258
0
                    DEBUGMSGTL(("agentx/master", "NULL transport??\n"));
259
0
                }
260
0
            } else {
261
0
                DEBUGMSGTL(("agentx/master", "NULL sess_pointer??\n"));
262
0
            }
263
0
            netsnmp_free_delegated_cache(cache);
264
0
            return 0;
265
0
        }
266
267
0
    case NETSNMP_CALLBACK_OP_DISCONNECT:
268
0
    case NETSNMP_CALLBACK_OP_SEND_FAILED:
269
0
        if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) {
270
0
            DEBUGMSGTL(("agentx/master", "disconnect on session %8p\n",
271
0
                        session));
272
0
        } else {
273
0
            DEBUGMSGTL(("agentx/master", "send failed on session %8p\n",
274
0
                        session));
275
0
        }
276
0
        close_agentx_session(session, -1);
277
0
        netsnmp_handler_mark_requests_as_delegated(requests,
278
0
                                                   REQUEST_IS_NOT_DELEGATED);
279
0
        netsnmp_set_request_error(cache->reqinfo, requests,     /* XXXWWW: should be index=0 */
280
0
                                  SNMP_ERR_GENERR);
281
0
        netsnmp_free_delegated_cache(cache);
282
0
        return 0;
283
284
0
    case NETSNMP_CALLBACK_OP_RESEND:
285
0
        DEBUGMSGTL(("agentx/master", "resend on session %8p req=0x%x\n",
286
0
                    session, (unsigned)reqid));
287
0
        return 0;
288
289
0
    case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
290
        /*
291
         * This session is alive 
292
         */
293
0
        CLEAR_SNMP_STRIKE_FLAGS(session->flags);
294
0
        break;
295
0
    default:
296
0
        snmp_log(LOG_ERR, "Unknown operation %d in agentx_got_response\n",
297
0
                 operation);
298
0
        netsnmp_free_delegated_cache(cache);
299
0
        return 0;
300
0
    }
301
302
0
    DEBUGMSGTL(("agentx/master", "got response errstat=%ld, (req=0x%x,trans="
303
0
                "0x%x,sess=0x%x)\n",
304
0
                pdu->errstat, (unsigned)pdu->reqid, (unsigned)pdu->transid,
305
0
    (unsigned)pdu->sessid));
306
307
0
    if (pdu->errstat != AGENTX_ERR_NOERROR) {
308
        /* [RFC 2471 - 7.2.5.2.]
309
         *
310
         *   1) For any received AgentX response PDU, if res.error is
311
         *      not `noError', the SNMP response PDU's error code is
312
         *      set to this value.  If res.error contains an AgentX
313
         *      specific value (e.g.  `parseError'), the SNMP response
314
         *      PDU's error code is set to a value of genErr instead.
315
         *      Also, the SNMP response PDU's error index is set to
316
         *      the index of the variable binding corresponding to the
317
         *      failed VarBind in the subagent's AgentX response PDU.
318
         *
319
         *      All other AgentX response PDUs received due to
320
         *      processing this SNMP request are ignored.  Processing
321
         *      is complete; the SNMP Response PDU is ready to be sent
322
         *      (see section 7.2.6, "Sending the SNMP Response-PDU").
323
         */
324
0
        int err;
325
326
0
        DEBUGMSGTL(("agentx/master",
327
0
                    "agentx_got_response() error branch\n"));
328
329
0
        switch (pdu->errstat) {
330
0
        case AGENTX_ERR_PARSE_FAILED:
331
0
        case AGENTX_ERR_REQUEST_DENIED:
332
0
        case AGENTX_ERR_PROCESSING_ERROR:
333
0
            err = SNMP_ERR_GENERR;
334
0
            break;
335
0
        default:
336
0
            err = pdu->errstat;
337
0
        }
338
339
0
        ret = 0;
340
0
        for (request = requests, i = 1; request;
341
0
             request = request->next, i++) {
342
0
            if (i == pdu->errindex) {
343
                /*
344
                 * Mark this varbind as the one generating the error.
345
                 * Note that the AgentX errindex may not match the
346
                 * position in the original SNMP PDU (request->index)
347
                 */
348
0
                netsnmp_set_request_error(cache->reqinfo, request,
349
0
                                          err);
350
0
                ret = 1;
351
0
            }
352
0
            request->delegated = REQUEST_IS_NOT_DELEGATED;
353
0
        }
354
0
        if (!ret) {
355
            /*
356
             * ack, unknown, mark the first one
357
             */
358
0
            netsnmp_set_request_error(cache->reqinfo, requests,
359
0
                                      SNMP_ERR_GENERR);
360
0
        }
361
0
        netsnmp_free_delegated_cache(cache);
362
0
        DEBUGMSGTL(("agentx/master", "end error branch\n"));
363
0
        return 1;
364
0
    } else if (cache->reqinfo->mode == MODE_GET ||
365
0
               cache->reqinfo->mode == MODE_GETNEXT ||
366
0
               cache->reqinfo->mode == MODE_GETBULK) {
367
        /*
368
         * Replace varbinds for data request types, but not SETs.  
369
         */
370
0
        DEBUGMSGTL(("agentx/master",
371
0
                    "agentx_got_response() beginning...\n"));
372
0
        for (var = pdu->variables, request = requests; request && var;
373
0
             request = request->next, var = var->next_variable) {
374
            /*
375
             * Otherwise, process successful requests
376
             */
377
0
            DEBUGMSGTL(("agentx/master",
378
0
                        "  handle_agentx_response: processing: "));
379
0
            DEBUGMSGOID(("agentx/master", var->name, var->name_length));
380
0
            DEBUGMSG(("agentx/master", "\n"));
381
0
            if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_VERBOSE)) {
382
0
                DEBUGMSGTL(("agentx/master", "    >> "));
383
0
                DEBUGMSGVAR(("agentx/master", var));
384
0
                DEBUGMSG(("agentx/master", "\n"));
385
0
            }
386
387
            /*
388
             * update the oid in the original request 
389
             */
390
0
            if (var->type != SNMP_ENDOFMIBVIEW) {
391
0
                snmp_set_var_typed_value(request->requestvb, var->type,
392
0
                                         var->val.string, var->val_len);
393
0
                snmp_set_var_objid(request->requestvb, var->name,
394
0
                                   var->name_length);
395
0
            }
396
0
            request->delegated = REQUEST_IS_NOT_DELEGATED;
397
0
        }
398
399
0
        if (request || var) {
400
            /*
401
             * ack, this is bad.  The # of varbinds don't match and
402
             * there is no way to fix the problem 
403
             */
404
0
            snmp_log(LOG_ERR,
405
0
                     "response to agentx request illegal.  bailing out.\n");
406
0
            netsnmp_set_request_error(cache->reqinfo, requests,
407
0
                                      SNMP_ERR_GENERR);
408
0
        }
409
410
0
        if (cache->reqinfo->mode == MODE_GETBULK)
411
0
            netsnmp_bulk_to_next_fix_requests(requests);
412
0
    } else {
413
        /*
414
         * mark set requests as handled 
415
         */
416
0
        for (request = requests; request; request = request->next) {
417
0
            request->delegated = REQUEST_IS_NOT_DELEGATED;
418
0
        }
419
0
    }
420
0
    DEBUGMSGTL(("agentx/master",
421
0
                "handle_agentx_response() finishing...\n"));
422
0
    netsnmp_free_delegated_cache(cache);
423
0
    return 1;
424
0
}
425
426
/*
427
 *
428
 * AgentX State diagram.  [mode] = internal mode it's mapped from:
429
 *
430
 * TESTSET -success-> COMMIT -success-> CLEANUP
431
 * [RESERVE1]         [ACTION]          [COMMIT]
432
 *    |                 |
433
 *    |                 \--failure-> UNDO
434
 *    |                              [UNDO]
435
 *    |
436
 *     --failure-> CLEANUP
437
 *                 [FREE]
438
 */
439
int
440
agentx_master_handler(netsnmp_mib_handler *handler,
441
                      netsnmp_handler_registration *reginfo,
442
                      netsnmp_agent_request_info *reqinfo,
443
                      netsnmp_request_info *requests)
444
0
{
445
0
    netsnmp_session *ax_session = (netsnmp_session *) handler->myvoid;
446
0
    netsnmp_request_info *request = requests;
447
0
    netsnmp_pdu    *pdu;
448
0
    void           *cb_data;
449
0
    int             result;
450
451
0
    DEBUGMSGTL(("agentx/master",
452
0
                "agentx master handler starting, mode = 0x%02x\n",
453
0
                reqinfo->mode));
454
455
0
    if (!ax_session) {
456
0
        netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
457
0
        return SNMP_ERR_NOERROR;
458
0
    }        
459
460
    /*
461
     * build a new pdu based on the pdu type coming in 
462
     */
463
0
    switch (reqinfo->mode) {
464
0
    case MODE_GET:
465
0
        pdu = snmp_pdu_create(AGENTX_MSG_GET);
466
0
        break;
467
468
0
    case MODE_GETNEXT:
469
0
        pdu = snmp_pdu_create(AGENTX_MSG_GETNEXT);
470
0
        break;
471
472
0
    case MODE_GETBULK:         /* WWWXXX */
473
0
        pdu = snmp_pdu_create(AGENTX_MSG_GETNEXT);
474
0
        break;
475
476
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
477
0
    case MODE_SET_RESERVE1:
478
0
        pdu = snmp_pdu_create(AGENTX_MSG_TESTSET);
479
0
        break;
480
481
0
    case MODE_SET_RESERVE2:
482
        /*
483
         * don't do anything here for AgentX.  Assume all is fine
484
         * and go on since AgentX only has one test phase. 
485
         */
486
0
        return SNMP_ERR_NOERROR;
487
488
0
    case MODE_SET_ACTION:
489
0
        pdu = snmp_pdu_create(AGENTX_MSG_COMMITSET);
490
0
        break;
491
492
0
    case MODE_SET_UNDO:
493
0
        pdu = snmp_pdu_create(AGENTX_MSG_UNDOSET);
494
0
        break;
495
496
0
    case MODE_SET_COMMIT:
497
0
    case MODE_SET_FREE:
498
0
        pdu = snmp_pdu_create(AGENTX_MSG_CLEANUPSET);
499
0
        break;
500
0
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
501
502
0
    default:
503
0
        snmp_log(LOG_WARNING,
504
0
                 "unsupported mode for agentx/master called\n");
505
0
        return SNMP_ERR_NOERROR;
506
0
    }
507
508
0
    if (!pdu) {
509
0
        netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
510
0
        return SNMP_ERR_NOERROR;
511
0
    }
512
513
0
    pdu->version = AGENTX_VERSION_1;
514
0
    pdu->reqid = snmp_get_next_transid();
515
0
    pdu->transid = reqinfo->asp->pdu->transid;
516
0
    pdu->sessid = ax_session->subsession->sessid;
517
0
    if (reginfo->contextName) {
518
0
        pdu->community = (u_char *) strdup(reginfo->contextName);
519
0
        pdu->community_len = strlen(reginfo->contextName);
520
0
        pdu->flags |= AGENTX_MSG_FLAG_NON_DEFAULT_CONTEXT;
521
0
    }
522
0
    if (ax_session->subsession->flags & AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER)
523
0
        pdu->flags |= AGENTX_MSG_FLAG_NETWORK_BYTE_ORDER;
524
525
0
    while (request) {
526
527
0
        size_t nlen = request->requestvb->name_length;
528
0
        oid   *nptr = request->requestvb->name;
529
        
530
0
        DEBUGMSGTL(("agentx/master","request for variable ("));
531
0
        DEBUGMSGOID(("agentx/master", nptr, nlen));
532
0
        DEBUGMSG(("agentx/master", ")\n"));
533
        
534
        /*
535
         * loop through all the requests and create agentx ones out of them 
536
         */
537
538
0
        if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) {
539
540
0
            if (snmp_oid_compare(nptr, nlen, request->subtree->start_a,
541
0
                                 request->subtree->start_len) < 0) {
542
0
                DEBUGMSGTL(("agentx/master","inexact request preceding region ("));
543
0
                DEBUGMSGOID(("agentx/master", request->subtree->start_a,
544
0
                             request->subtree->start_len));
545
0
                DEBUGMSG(("agentx/master", ")\n"));
546
0
                nptr = request->subtree->start_a;
547
0
                nlen = request->subtree->start_len;
548
0
                request->inclusive = 1;
549
0
            }
550
551
0
            if (request->inclusive) {
552
0
                DEBUGMSGTL(("agentx/master", "INCLUSIVE varbind "));
553
0
                DEBUGMSGOID(("agentx/master", nptr, nlen));
554
0
                DEBUGMSG(("agentx/master", " scoped to "));
555
0
                DEBUGMSGOID(("agentx/master", request->range_end,
556
0
                             request->range_end_len));
557
0
                DEBUGMSG(("agentx/master", "\n"));
558
0
                snmp_pdu_add_variable(pdu, nptr, nlen, ASN_PRIV_INCL_RANGE,
559
0
                                      (u_char *) request->range_end,
560
0
                                      request->range_end_len *
561
0
                                      sizeof(oid));
562
0
                request->inclusive = 0;
563
0
            } else {
564
0
                DEBUGMSGTL(("agentx/master", "EXCLUSIVE varbind "));
565
0
                DEBUGMSGOID(("agentx/master", nptr, nlen));
566
0
                DEBUGMSG(("agentx/master", " scoped to "));
567
0
                DEBUGMSGOID(("agentx/master", request->range_end,
568
0
                             request->range_end_len));
569
0
                DEBUGMSG(("agentx/master", "\n"));
570
0
                snmp_pdu_add_variable(pdu, nptr, nlen, ASN_PRIV_EXCL_RANGE,
571
0
                                      (u_char *) request->range_end,
572
0
                                      request->range_end_len *
573
0
                                      sizeof(oid));
574
0
            }
575
0
        } else {
576
0
            snmp_pdu_add_variable(pdu, request->requestvb->name,
577
0
                                  request->requestvb->name_length,
578
0
                                  request->requestvb->type,
579
0
                                  request->requestvb->val.string,
580
0
                                  request->requestvb->val_len);
581
0
        }
582
583
        /*
584
         * mark the request as delayed 
585
         */
586
0
        if (pdu->command != AGENTX_MSG_CLEANUPSET)
587
0
            request->delegated = REQUEST_IS_DELEGATED;
588
0
        else
589
0
            request->delegated = REQUEST_IS_NOT_DELEGATED;
590
591
        /*
592
         * next... 
593
         */
594
0
        request = request->next;
595
0
    }
596
597
    /*
598
     * When the master sends a CleanupSet PDU, it will never get a response
599
     * back from the subagent. So we shouldn't allocate the
600
     * netsnmp_delegated_cache structure in this case.
601
     */
602
0
    if (pdu->command != AGENTX_MSG_CLEANUPSET)
603
0
        cb_data = netsnmp_create_delegated_cache(handler, reginfo,
604
0
                                                 reqinfo, requests,
605
0
                                                 (void *) ax_session);
606
0
    else
607
0
        cb_data = NULL;
608
609
    /*
610
     * send the requests out.
611
     */
612
0
    DEBUGMSGTL(("agentx/master", "sending pdu (req=0x%x,trans=0x%x,sess=0x%x)\n",
613
0
                (unsigned)pdu->reqid, (unsigned)pdu->transid, (unsigned)pdu->sessid));
614
0
    result = snmp_async_send(ax_session, pdu, agentx_got_response, cb_data);
615
0
    if (result == 0) {
616
0
        snmp_free_pdu(pdu);
617
0
    }
618
619
0
    return SNMP_ERR_NOERROR;
620
0
}