00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00046 #include <net-snmp/net-snmp-config.h>
00047
00048 #include <sys/types.h>
00049 #ifdef HAVE_LIMITS_H
00050 #include <limits.h>
00051 #endif
00052 #ifdef HAVE_STDLIB_H
00053 #include <stdlib.h>
00054 #endif
00055 #if HAVE_UNISTD_H
00056 #include <unistd.h>
00057 #endif
00058 #if HAVE_STRING_H
00059 #include <string.h>
00060 #endif
00061 #if TIME_WITH_SYS_TIME
00062 # ifdef WIN32
00063 # include <sys/timeb.h>
00064 # else
00065 # include <sys/time.h>
00066 # endif
00067 # include <time.h>
00068 #else
00069 # if HAVE_SYS_TIME_H
00070 # include <sys/time.h>
00071 # else
00072 # include <time.h>
00073 # endif
00074 #endif
00075 #if HAVE_SYS_SELECT_H
00076 #include <sys/select.h>
00077 #endif
00078 #if HAVE_NETINET_IN_H
00079 #include <netinet/in.h>
00080 #endif
00081 #include <errno.h>
00082 #if HAVE_WINSOCK_H
00083 #include <winsock.h>
00084 #endif
00085
00086 #define SNMP_NEED_REQUEST_LIST
00087 #include <net-snmp/net-snmp-includes.h>
00088 #include <net-snmp/agent/net-snmp-agent-includes.h>
00089 #include <net-snmp/library/snmp_assert.h>
00090
00091 #if HAVE_SYSLOG_H
00092 #include <syslog.h>
00093 #endif
00094
00095 #ifdef NETSNMP_USE_LIBWRAP
00096 #include <tcpd.h>
00097 int allow_severity = LOG_INFO;
00098 int deny_severity = LOG_WARNING;
00099 #endif
00100
00101 #include "snmpd.h"
00102 #include "mibgroup/struct.h"
00103 #include "mibgroup/util_funcs.h"
00104 #include <net-snmp/agent/mib_module_config.h>
00105 #include <net-snmp/agent/mib_modules.h>
00106
00107 #ifdef USING_AGENTX_PROTOCOL_MODULE
00108 #include "agentx/protocol.h"
00109 #endif
00110
00111 #ifdef USING_AGENTX_MASTER_MODULE
00112 #include "agentx/master.h"
00113 #endif
00114
00115 #ifdef USING_SMUX_MODULE
00116 #include "smux/smux.h"
00117 #endif
00118
00119 oid version_sysoid[] = { NETSNMP_SYSTEM_MIB };
00120 int version_sysoid_len = OID_LENGTH(version_sysoid);
00121
00122 #define SNMP_ADDRCACHE_SIZE 10
00123 #define SNMP_ADDRCACHE_MAXAGE 300
00124
00125 enum {
00126 SNMP_ADDRCACHE_UNUSED = 0,
00127 SNMP_ADDRCACHE_USED = 1
00128 };
00129
00130 struct addrCache {
00131 char *addr;
00132 int status;
00133 struct timeval lastHit;
00134 };
00135
00136 static struct addrCache addrCache[SNMP_ADDRCACHE_SIZE];
00137 int log_addresses = 0;
00138
00139
00140
00141 typedef struct _agent_nsap {
00142 int handle;
00143 netsnmp_transport *t;
00144 void *s;
00145 struct _agent_nsap *next;
00146 } agent_nsap;
00147
00148 static agent_nsap *agent_nsap_list = NULL;
00149 static netsnmp_agent_session *agent_session_list = NULL;
00150 netsnmp_agent_session *netsnmp_processing_set = NULL;
00151 netsnmp_agent_session *agent_delegated_list = NULL;
00152 netsnmp_agent_session *netsnmp_agent_queued_list = NULL;
00153
00154
00155 int netsnmp_agent_check_packet(netsnmp_session *,
00156 struct netsnmp_transport_s *,
00157 void *, int);
00158 int netsnmp_agent_check_parse(netsnmp_session *, netsnmp_pdu *,
00159 int);
00160 void delete_subnetsnmp_tree_cache(netsnmp_agent_session *asp);
00161 int handle_pdu(netsnmp_agent_session *asp);
00162 int netsnmp_handle_request(netsnmp_agent_session *asp,
00163 int status);
00164 int netsnmp_wrap_up_request(netsnmp_agent_session *asp,
00165 int status);
00166 int check_delayed_request(netsnmp_agent_session *asp);
00167 int handle_getnext_loop(netsnmp_agent_session *asp);
00168 int handle_set_loop(netsnmp_agent_session *asp);
00169
00170 int netsnmp_check_queued_chain_for(netsnmp_agent_session *asp);
00171 int netsnmp_add_queued(netsnmp_agent_session *asp);
00172 int netsnmp_remove_from_delegated(netsnmp_agent_session *asp);
00173
00174
00175 static int current_globalid = 0;
00176
00177 int netsnmp_running = 1;
00178
00179 int
00180 netsnmp_allocate_globalcacheid(void)
00181 {
00182 return ++current_globalid;
00183 }
00184
00185 int
00186 netsnmp_get_local_cachid(netsnmp_cachemap *cache_store, int globalid)
00187 {
00188 while (cache_store != NULL) {
00189 if (cache_store->globalid == globalid)
00190 return cache_store->cacheid;
00191 cache_store = cache_store->next;
00192 }
00193 return -1;
00194 }
00195
00196 netsnmp_cachemap *
00197 netsnmp_get_or_add_local_cachid(netsnmp_cachemap **cache_store,
00198 int globalid, int localid)
00199 {
00200 netsnmp_cachemap *tmpp;
00201
00202 tmpp = SNMP_MALLOC_TYPEDEF(netsnmp_cachemap);
00203 if (*cache_store) {
00204 tmpp->next = *cache_store;
00205 *cache_store = tmpp;
00206 } else {
00207 *cache_store = tmpp;
00208 }
00209
00210 tmpp->globalid = globalid;
00211 tmpp->cacheid = localid;
00212 return tmpp;
00213 }
00214
00215 void
00216 netsnmp_free_cachemap(netsnmp_cachemap *cache_store)
00217 {
00218 netsnmp_cachemap *tmpp;
00219 while (cache_store) {
00220 tmpp = cache_store;
00221 cache_store = cache_store->next;
00222 SNMP_FREE(tmpp);
00223 }
00224 }
00225
00226
00227 typedef struct agent_set_cache_s {
00228
00229
00230
00231 int transID;
00232 netsnmp_session *sess;
00233
00234
00235
00236
00237 netsnmp_tree_cache *treecache;
00238 int treecache_len;
00239 int treecache_num;
00240
00241 int vbcount;
00242 netsnmp_request_info *requests;
00243 netsnmp_variable_list *saved_vars;
00244 netsnmp_data_list *agent_data;
00245
00246
00247
00248
00249 struct agent_set_cache_s *next;
00250 } agent_set_cache;
00251
00252 static agent_set_cache *Sets = NULL;
00253
00254 agent_set_cache *
00255 save_set_cache(netsnmp_agent_session *asp)
00256 {
00257 agent_set_cache *ptr;
00258
00259 if (!asp || !asp->reqinfo || !asp->pdu)
00260 return NULL;
00261
00262 ptr = SNMP_MALLOC_TYPEDEF(agent_set_cache);
00263 if (ptr == NULL)
00264 return NULL;
00265
00266
00267
00268
00269 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p saved in cache (mode %d)\n",
00270 asp, asp->reqinfo, asp->pdu->command));
00271 ptr->transID = asp->pdu->transid;
00272 ptr->sess = asp->session;
00273 ptr->treecache = asp->treecache;
00274 ptr->treecache_len = asp->treecache_len;
00275 ptr->treecache_num = asp->treecache_num;
00276 ptr->agent_data = asp->reqinfo->agent_data;
00277 ptr->requests = asp->requests;
00278 ptr->saved_vars = asp->pdu->variables;
00279 ptr->vbcount = asp->vbcount;
00280
00281
00282
00283
00284 asp->treecache = NULL;
00285 asp->reqinfo->agent_data = NULL;
00286 asp->pdu->variables = NULL;
00287 asp->requests = NULL;
00288
00289 ptr->next = Sets;
00290 Sets = ptr;
00291
00292 return ptr;
00293 }
00294
00295 int
00296 get_set_cache(netsnmp_agent_session *asp)
00297 {
00298 agent_set_cache *ptr, *prev = NULL;
00299
00300 for (ptr = Sets; ptr != NULL; ptr = ptr->next) {
00301 if (ptr->sess == asp->session && ptr->transID == asp->pdu->transid) {
00302
00303
00304
00305 if (prev)
00306 prev->next = ptr->next;
00307 else
00308 Sets = ptr->next;
00309
00310
00311
00312
00313 asp->treecache = ptr->treecache;
00314 asp->treecache_len = ptr->treecache_len;
00315 asp->treecache_num = ptr->treecache_num;
00316
00317
00318
00319
00320
00321 if (asp->requests) {
00322
00323
00324
00325
00326
00327 int i;
00328 netsnmp_assert(NULL == asp->requests);
00329 for (i = 0; i < asp->vbcount; i++) {
00330 netsnmp_free_request_data_sets(&asp->requests[i]);
00331 }
00332 free(asp->requests);
00333 }
00334
00335
00336
00337
00338
00339
00340 if (ptr->saved_vars) {
00341 if (asp->pdu->variables)
00342 snmp_free_varbind(asp->pdu->variables);
00343 asp->pdu->variables = ptr->saved_vars;
00344 asp->vbcount = ptr->vbcount;
00345 } else {
00346
00347
00348
00349
00350 netsnmp_assert(NULL != ptr->saved_vars);
00351 }
00352 asp->requests = ptr->requests;
00353
00354 netsnmp_assert(NULL != asp->reqinfo);
00355 asp->reqinfo->asp = asp;
00356 asp->reqinfo->agent_data = ptr->agent_data;
00357
00358
00359
00360
00361
00362
00363 if(asp->requests->agent_req_info != asp->reqinfo) {
00364
00365
00366
00367
00368 netsnmp_request_info *tmp = asp->requests;
00369 DEBUGMSGTL(("verbose:asp",
00370 " reqinfo %p doesn't match cached reqinfo %p\n",
00371 asp->reqinfo, asp->requests->agent_req_info));
00372 for(; tmp; tmp = tmp->next)
00373 tmp->agent_req_info = asp->reqinfo;
00374 } else {
00375
00376
00377
00378 DEBUGMSGTL(("verbose:asp",
00379 " reqinfo %p matches cached reqinfo %p\n",
00380 asp->reqinfo, asp->requests->agent_req_info));
00381 }
00382
00383 SNMP_FREE(ptr);
00384 return SNMP_ERR_NOERROR;
00385 }
00386 prev = ptr;
00387 }
00388 return SNMP_ERR_GENERR;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 NETSNMP_STATIC_INLINE void
00407 _reorder_getbulk(netsnmp_agent_session *asp)
00408 {
00409 int i, n = 0, r = 0;
00410 int repeats = asp->pdu->errindex;
00411 int j, k;
00412 int all_eoMib;
00413 netsnmp_variable_list *prev = NULL, *curr;
00414
00415 if (asp->vbcount == 0)
00416 return;
00417
00418 if (asp->pdu->errstat < asp->vbcount) {
00419 n = asp->pdu->errstat;
00420 } else {
00421 n = asp->vbcount;
00422 }
00423 if ((r = asp->vbcount - n) < 0) {
00424 r = 0;
00425 }
00426
00427
00428 if (r == 0)
00429 return;
00430
00431
00432 for (i = 0; i < r; i++) {
00433 prev = NULL;
00434 for (j = 0; j < repeats; j++) {
00435 curr = asp->bulkcache[i * repeats + j];
00436
00437
00438
00439
00440
00441
00442
00443
00444 if (curr->name_length == 0 || curr->type == SNMP_ENDOFMIBVIEW) {
00445 if (prev == NULL) {
00446
00447 prev = asp->orig_pdu->variables;
00448 for (k = i; prev && k > 0; k--)
00449 prev = prev->next_variable;
00450 }
00451 if (prev) {
00452 snmp_set_var_objid(curr, prev->name, prev->name_length);
00453 snmp_set_var_typed_value(curr, SNMP_ENDOFMIBVIEW, NULL, 0);
00454 }
00455 }
00456 prev = curr;
00457 }
00458 }
00459
00460
00461
00462
00463
00464
00465
00466 for (i = 0; i < r - 1; i++) {
00467 for (j = 0; j < repeats; j++) {
00468 asp->bulkcache[i * repeats + j]->next_variable =
00469 asp->bulkcache[(i + 1) * repeats + j];
00470 }
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 for (j = 0; j < repeats - 1; j++) {
00482 asp->bulkcache[(r - 1) * repeats + j]->next_variable =
00483 asp->bulkcache[j + 1];
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 all_eoMib = 0;
00499 for (i = 0; i < repeats; i++) {
00500 if (asp->bulkcache[i]->type == SNMP_ENDOFMIBVIEW) {
00501 all_eoMib = 1;
00502 for (j = 1, prev=asp->bulkcache[i];
00503 j < r;
00504 j++, prev=prev->next_variable) {
00505 if (prev->type != SNMP_ENDOFMIBVIEW) {
00506 all_eoMib = 0;
00507 break;
00508 }
00509 }
00510 if (all_eoMib) {
00511
00512
00513
00514
00515 snmp_free_varbind( prev->next_variable );
00516 prev->next_variable = NULL;
00517 break;
00518 }
00519 }
00520 }
00521 }
00522
00523
00524
00525
00526
00527
00528
00529 NETSNMP_STATIC_INLINE void
00530 _fix_endofmibview(netsnmp_agent_session *asp)
00531 {
00532 netsnmp_variable_list *vb, *ovb;
00533
00534 if (asp->vbcount == 0)
00535 return;
00536
00537 for (vb = asp->pdu->variables, ovb = asp->orig_pdu->variables;
00538 vb && ovb; vb = vb->next_variable, ovb = ovb->next_variable) {
00539 if (vb->type == SNMP_ENDOFMIBVIEW)
00540 snmp_set_var_objid(vb, ovb->name, ovb->name_length);
00541 }
00542 }
00543
00544
00545 int
00546 getNextSessID()
00547 {
00548 static int SessionID = 0;
00549
00550 return ++SessionID;
00551 }
00552
00565 int
00566 agent_check_and_process(int block)
00567 {
00568 int numfds;
00569 fd_set fdset;
00570 struct timeval timeout = { LONG_MAX, 0 }, *tvp = &timeout;
00571 int count;
00572 int fakeblock = 0;
00573
00574 numfds = 0;
00575 FD_ZERO(&fdset);
00576 snmp_select_info(&numfds, &fdset, tvp, &fakeblock);
00577 if (block != 0 && fakeblock != 0) {
00578
00579
00580
00581
00582
00583 tvp = NULL;
00584 } else if (block != 0 && fakeblock == 0) {
00585
00586
00587
00588
00589
00590
00591 } else if (block == 0) {
00592
00593
00594
00595
00596 tvp->tv_sec = 0;
00597 tvp->tv_usec = 0;
00598 }
00599
00600 count = select(numfds, &fdset, 0, 0, tvp);
00601
00602 if (count > 0) {
00603
00604
00605
00606 snmp_read(&fdset);
00607 } else
00608 switch (count) {
00609 case 0:
00610 snmp_timeout();
00611 break;
00612 case -1:
00613 if (errno != EINTR) {
00614 snmp_log_perror("select");
00615 }
00616 return -1;
00617 default:
00618 snmp_log(LOG_ERR, "select returned %d\n", count);
00619 return -1;
00620 }
00621
00622
00623
00624
00625 run_alarms();
00626
00627 netsnmp_check_outstanding_agent_requests();
00628
00629 return count;
00630 }
00631
00632
00633
00634
00635
00636 void
00637 netsnmp_addrcache_initialise(void)
00638 {
00639 int i = 0;
00640
00641 for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00642 addrCache[i].addr = NULL;
00643 addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
00644 }
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 int
00663 netsnmp_addrcache_add(const char *addr)
00664 {
00665 int oldest = -1;
00666 int unused = -1;
00667 int i;
00668 int rc = -1;
00669 struct timeval now;
00670 struct timeval aged;
00671
00672
00673
00674
00675 gettimeofday(&now, (struct timezone*) NULL);
00676 aged.tv_sec = now.tv_sec - SNMP_ADDRCACHE_MAXAGE;
00677 aged.tv_usec = now.tv_usec;
00678
00679
00680
00681
00682 for(i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00683 if (addrCache[i].status == SNMP_ADDRCACHE_UNUSED) {
00684
00685
00686
00687 if (unused < 0)
00688 unused = i;
00689 }
00690 else {
00691 if ((NULL != addr) && (strcmp(addrCache[i].addr, addr) == 0)) {
00692
00693
00694
00695 memcpy(&addrCache[i].lastHit, &now, sizeof(struct timeval));
00696 if (timercmp(&addrCache[i].lastHit, &aged, <))
00697 rc = 1;
00698 else
00699 rc = 0;
00700 break;
00701 }
00702 else {
00703
00704
00705
00706 if (timercmp(&addrCache[i].lastHit, &aged, <)) {
00707
00708
00709
00710 SNMP_FREE(addrCache[i].addr);
00711 addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
00712
00713
00714
00715 if (unused < 0)
00716 unused = i;
00717 }
00718 else {
00719
00720
00721
00722 if (oldest < 0)
00723 oldest = i;
00724 else if (timercmp(&addrCache[i].lastHit,
00725 &addrCache[oldest].lastHit, <))
00726 oldest = i;
00727 }
00728 }
00729 }
00730 }
00731
00732 if ((-1 == rc) && (NULL != addr)) {
00733
00734
00735
00736 if (unused >= 0) {
00737
00738
00739
00740 addrCache[unused].addr = strdup(addr);
00741 addrCache[unused].status = SNMP_ADDRCACHE_USED;
00742 memcpy(&addrCache[unused].lastHit, &now, sizeof(struct timeval));
00743 }
00744 else {
00745 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00746 NETSNMP_DS_AGENT_VERBOSE))
00747 snmp_log(LOG_INFO, "Purging address from address cache: %s",
00748 addrCache[oldest].addr);
00749
00750 free(addrCache[oldest].addr);
00751 addrCache[oldest].addr = strdup(addr);
00752 memcpy(&addrCache[oldest].lastHit, &now, sizeof(struct timeval));
00753 }
00754 rc = 1;
00755 }
00756 if ((log_addresses && (1 == rc)) ||
00757 netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00758 NETSNMP_DS_AGENT_VERBOSE)) {
00759 snmp_log(LOG_INFO, "Received SNMP packet(s) from %s\n", addr);
00760 }
00761
00762 return rc;
00763 }
00764
00765
00766
00767
00768
00769
00770 void
00771 netsnmp_addrcache_age(void)
00772 {
00773 (void)netsnmp_addrcache_add(NULL);
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792 int
00793 netsnmp_agent_check_packet(netsnmp_session * session,
00794 netsnmp_transport *transport,
00795 void *transport_data, int transport_data_length)
00796 {
00797 char *addr_string = NULL;
00798 #ifdef NETSNMP_USE_LIBWRAP
00799 char *tcpudpaddr, *name;
00800 short not_log_connection;
00801
00802 name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00803 NETSNMP_DS_LIB_APPTYPE);
00804
00805
00806 not_log_connection = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00807 NETSNMP_DS_AGENT_DONT_LOG_TCPWRAPPERS_CONNECTS);
00808
00809
00810
00811
00812
00813 if (not_log_connection == SNMPERR_GENERR) not_log_connection = 0;
00814 #endif
00815
00816
00817
00818
00819
00820
00821 if (transport != NULL && transport->f_fmtaddr != NULL) {
00822
00823
00824
00825 addr_string = transport->f_fmtaddr(transport, transport_data,
00826 transport_data_length);
00827
00828
00829
00830 }
00831 #ifdef NETSNMP_USE_LIBWRAP
00832
00833 tcpudpaddr = strstr(addr_string, "[");
00834 if ( tcpudpaddr != 0 ) {
00835 char sbuf[64];
00836 char *xp;
00837 strncpy(sbuf, tcpudpaddr + 1, sizeof(sbuf));
00838 sbuf[sizeof(sbuf)-1] = '\0';
00839 xp = strstr(sbuf, "]");
00840 if (xp)
00841 *xp = '\0';
00842
00843 if (hosts_ctl(name, STRING_UNKNOWN, sbuf, STRING_UNKNOWN)) {
00844 if (!not_log_connection) {
00845 snmp_log(allow_severity, "Connection from %s\n", addr_string);
00846 }
00847 } else {
00848 snmp_log(deny_severity, "Connection from %s REFUSED\n",
00849 addr_string);
00850 SNMP_FREE(addr_string);
00851 return 0;
00852 }
00853 } else {
00854
00855
00856
00857
00858 if (0 == strncmp(addr_string, "callback", 8))
00859 ;
00860 else if (hosts_ctl(name, STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN)){
00861 if (!not_log_connection) {
00862 snmp_log(allow_severity, "Connection from <UNKNOWN> (%s)\n", addr_string);
00863 };
00864 SNMP_FREE(addr_string);
00865 addr_string = strdup("<UNKNOWN>");
00866 } else {
00867 snmp_log(deny_severity, "Connection from <UNKNOWN> (%s) REFUSED\n", addr_string);
00868 SNMP_FREE(addr_string);
00869 return 0;
00870 }
00871 }
00872 #endif
00873
00874 snmp_increment_statistic(STAT_SNMPINPKTS);
00875
00876 if (addr_string != NULL) {
00877 netsnmp_addrcache_add(addr_string);
00878 SNMP_FREE(addr_string);
00879 }
00880 return 1;
00881 }
00882
00883
00884 int
00885 netsnmp_agent_check_parse(netsnmp_session * session, netsnmp_pdu *pdu,
00886 int result)
00887 {
00888 if (result == 0) {
00889 if (snmp_get_do_logging() &&
00890 netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00891 NETSNMP_DS_AGENT_VERBOSE)) {
00892 netsnmp_variable_list *var_ptr;
00893
00894 switch (pdu->command) {
00895 case SNMP_MSG_GET:
00896 snmp_log(LOG_DEBUG, " GET message\n");
00897 break;
00898 case SNMP_MSG_GETNEXT:
00899 snmp_log(LOG_DEBUG, " GETNEXT message\n");
00900 break;
00901 case SNMP_MSG_RESPONSE:
00902 snmp_log(LOG_DEBUG, " RESPONSE message\n");
00903 break;
00904 case SNMP_MSG_SET:
00905 snmp_log(LOG_DEBUG, " SET message\n");
00906 break;
00907 case SNMP_MSG_TRAP:
00908 snmp_log(LOG_DEBUG, " TRAP message\n");
00909 break;
00910 case SNMP_MSG_GETBULK:
00911 snmp_log(LOG_DEBUG, " GETBULK message, non-rep=%ld, max_rep=%ld\n",
00912 pdu->errstat, pdu->errindex);
00913 break;
00914 case SNMP_MSG_INFORM:
00915 snmp_log(LOG_DEBUG, " INFORM message\n");
00916 break;
00917 case SNMP_MSG_TRAP2:
00918 snmp_log(LOG_DEBUG, " TRAP2 message\n");
00919 break;
00920 case SNMP_MSG_REPORT:
00921 snmp_log(LOG_DEBUG, " REPORT message\n");
00922 break;
00923
00924 case SNMP_MSG_INTERNAL_SET_RESERVE1:
00925 snmp_log(LOG_DEBUG, " INTERNAL RESERVE1 message\n");
00926 break;
00927
00928 case SNMP_MSG_INTERNAL_SET_RESERVE2:
00929 snmp_log(LOG_DEBUG, " INTERNAL RESERVE2 message\n");
00930 break;
00931
00932 case SNMP_MSG_INTERNAL_SET_ACTION:
00933 snmp_log(LOG_DEBUG, " INTERNAL ACTION message\n");
00934 break;
00935
00936 case SNMP_MSG_INTERNAL_SET_COMMIT:
00937 snmp_log(LOG_DEBUG, " INTERNAL COMMIT message\n");
00938 break;
00939
00940 case SNMP_MSG_INTERNAL_SET_FREE:
00941 snmp_log(LOG_DEBUG, " INTERNAL FREE message\n");
00942 break;
00943
00944 case SNMP_MSG_INTERNAL_SET_UNDO:
00945 snmp_log(LOG_DEBUG, " INTERNAL UNDO message\n");
00946 break;
00947
00948 default:
00949 snmp_log(LOG_DEBUG, " UNKNOWN message, type=%02X\n",
00950 pdu->command);
00951 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
00952 return 0;
00953 }
00954
00955 for (var_ptr = pdu->variables; var_ptr != NULL;
00956 var_ptr = var_ptr->next_variable) {
00957 size_t c_oidlen = 256, c_outlen = 0;
00958 u_char *c_oid = (u_char *) malloc(c_oidlen);
00959
00960 if (c_oid) {
00961 if (!sprint_realloc_objid
00962 (&c_oid, &c_oidlen, &c_outlen, 1, var_ptr->name,
00963 var_ptr->name_length)) {
00964 snmp_log(LOG_DEBUG, " -- %s [TRUNCATED]\n",
00965 c_oid);
00966 } else {
00967 snmp_log(LOG_DEBUG, " -- %s\n", c_oid);
00968 }
00969 SNMP_FREE(c_oid);
00970 }
00971 }
00972 }
00973 return 1;
00974 }
00975 return 0;
00976
00977
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 netsnmp_session *main_session = NULL;
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 int
01002 netsnmp_register_agent_nsap(netsnmp_transport *t)
01003 {
01004 netsnmp_session *s, *sp = NULL;
01005 agent_nsap *a = NULL, *n = NULL, **prevNext = &agent_nsap_list;
01006 int handle = 0;
01007 void *isp = NULL;
01008
01009 if (t == NULL) {
01010 return -1;
01011 }
01012
01013 DEBUGMSGTL(("netsnmp_register_agent_nsap", "fd %d\n", t->sock));
01014
01015 n = (agent_nsap *) malloc(sizeof(agent_nsap));
01016 if (n == NULL) {
01017 return -1;
01018 }
01019 s = (netsnmp_session *) malloc(sizeof(netsnmp_session));
01020 if (s == NULL) {
01021 SNMP_FREE(n);
01022 return -1;
01023 }
01024 memset(s, 0, sizeof(netsnmp_session));
01025 snmp_sess_init(s);
01026
01027
01028
01029
01030
01031 s->version = SNMP_DEFAULT_VERSION;
01032 s->callback = handle_snmp_packet;
01033 s->authenticator = NULL;
01034 s->flags = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
01035 NETSNMP_DS_AGENT_FLAGS);
01036 s->isAuthoritative = SNMP_SESS_AUTHORITATIVE;
01037
01038 sp = snmp_add(s, t, netsnmp_agent_check_packet,
01039 netsnmp_agent_check_parse);
01040 if (sp == NULL) {
01041 SNMP_FREE(s);
01042 SNMP_FREE(n);
01043 return -1;
01044 }
01045
01046 isp = snmp_sess_pointer(sp);
01047 if (isp == NULL) {
01048 SNMP_FREE(s);
01049 SNMP_FREE(n);
01050 return -1;
01051 }
01052
01053 n->s = isp;
01054 n->t = t;
01055
01056 if (main_session == NULL) {
01057 main_session = snmp_sess_session(isp);
01058 }
01059
01060 for (a = agent_nsap_list; a != NULL && handle + 1 >= a->handle;
01061 a = a->next) {
01062 handle = a->handle;
01063 prevNext = &(a->next);
01064 }
01065
01066 if (handle < INT_MAX) {
01067 n->handle = handle + 1;
01068 n->next = a;
01069 *prevNext = n;
01070 SNMP_FREE(s);
01071 return n->handle;
01072 } else {
01073 SNMP_FREE(s);
01074 SNMP_FREE(n);
01075 return -1;
01076 }
01077 }
01078
01079 void
01080 netsnmp_deregister_agent_nsap(int handle)
01081 {
01082 agent_nsap *a = NULL, **prevNext = &agent_nsap_list;
01083 int main_session_deregistered = 0;
01084
01085 DEBUGMSGTL(("netsnmp_deregister_agent_nsap", "handle %d\n", handle));
01086
01087 for (a = agent_nsap_list; a != NULL && a->handle < handle; a = a->next) {
01088 prevNext = &(a->next);
01089 }
01090
01091 if (a != NULL && a->handle == handle) {
01092 *prevNext = a->next;
01093 if (main_session == snmp_sess_session(a->s)) {
01094 main_session_deregistered = 1;
01095 }
01096 snmp_close(snmp_sess_session(a->s));
01097
01098
01099
01100 SNMP_FREE(a);
01101 }
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111 if (main_session_deregistered) {
01112 if (agent_nsap_list != NULL) {
01113 DEBUGMSGTL(("snmp_agent",
01114 "WARNING: main_session ptr changed from %p to %p\n",
01115 main_session, snmp_sess_session(agent_nsap_list->s)));
01116 main_session = snmp_sess_session(agent_nsap_list->s);
01117 } else {
01118 DEBUGMSGTL(("snmp_agent",
01119 "WARNING: main_session ptr changed from %p to NULL\n",
01120 main_session));
01121 main_session = NULL;
01122 }
01123 }
01124 }
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 int
01152 init_master_agent(void)
01153 {
01154 netsnmp_transport *transport;
01155 char *cptr;
01156 char buf[SPRINT_MAX_LEN];
01157 char *st;
01158
01159
01160 netsnmp_set_lookup_cache_size(-1);
01161
01162 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
01163 NETSNMP_DS_AGENT_ROLE) != MASTER_AGENT) {
01164 DEBUGMSGTL(("snmp_agent",
01165 "init_master_agent; not master agent\n"));
01166
01167 netsnmp_assert("agent role !master && !sub_agent");
01168
01169 return 0;
01170 }
01171 #ifdef USING_AGENTX_MASTER_MODULE
01172 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
01173 NETSNMP_DS_AGENT_AGENTX_MASTER) == 1)
01174 real_init_master();
01175 #endif
01176 #ifdef USING_SMUX_MODULE
01177 if(should_init("smux"))
01178 real_init_smux();
01179 #endif
01180
01181
01182
01183
01184 cptr = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
01185 NETSNMP_DS_AGENT_PORTS);
01186
01187 if (cptr) {
01188 snprintf(buf, sizeof(buf), "%s", cptr);
01189 buf[ sizeof(buf)-1 ] = 0;
01190 } else {
01191
01192
01193
01194 buf[0] = 0;
01195 }
01196
01197 DEBUGMSGTL(("snmp_agent", "final port spec: \"%s\"\n", buf));
01198 st = buf;
01199 do {
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 cptr = st;
01213 st = strchr(st, ',');
01214 if (st)
01215 *st++ = '\0';
01216
01217 DEBUGMSGTL(("snmp_agent", "installing master agent on port %s\n",
01218 cptr));
01219
01220 if (strncasecmp(cptr, "none", 4) == 0) {
01221 DEBUGMSGTL(("snmp_agent",
01222 "init_master_agent; pseudo-transport \"none\" "
01223 "requested\n"));
01224 return 0;
01225 }
01226 transport = netsnmp_transport_open_server("snmp", cptr);
01227
01228 if (transport == NULL) {
01229 snmp_log(LOG_ERR, "Error opening specified endpoint \"%s\"\n",
01230 cptr);
01231 return 1;
01232 }
01233
01234 if (netsnmp_register_agent_nsap(transport) == 0) {
01235 snmp_log(LOG_ERR,
01236 "Error registering specified transport \"%s\" as an "
01237 "agent NSAP\n", cptr);
01238 return 1;
01239 } else {
01240 DEBUGMSGTL(("snmp_agent",
01241 "init_master_agent; \"%s\" registered as an agent "
01242 "NSAP\n", cptr));
01243 }
01244 } while(st && *st != '\0');
01245
01246 return 0;
01247 }
01248
01249 void
01250 clear_nsap_list(void)
01251 {
01252 DEBUGMSGTL(("clear_nsap_list", "clear the nsap list\n"));
01253
01254 while (agent_nsap_list != NULL)
01255 netsnmp_deregister_agent_nsap(agent_nsap_list->handle);
01256 }
01257
01258 void
01259 shutdown_master_agent(void)
01260 {
01261 clear_nsap_list();
01262 }
01263
01264
01265 netsnmp_agent_session *
01266 init_agent_snmp_session(netsnmp_session * session, netsnmp_pdu *pdu)
01267 {
01268 netsnmp_agent_session *asp = (netsnmp_agent_session *)
01269 calloc(1, sizeof(netsnmp_agent_session));
01270
01271 if (asp == NULL) {
01272 return NULL;
01273 }
01274
01275 DEBUGMSGTL(("snmp_agent","agent_sesion %08p created\n", asp));
01276 asp->session = session;
01277 asp->pdu = snmp_clone_pdu(pdu);
01278 asp->orig_pdu = snmp_clone_pdu(pdu);
01279 asp->rw = READ;
01280 asp->exact = TRUE;
01281 asp->next = NULL;
01282 asp->mode = RESERVE1;
01283 asp->status = SNMP_ERR_NOERROR;
01284 asp->index = 0;
01285 asp->oldmode = 0;
01286 asp->treecache_num = -1;
01287 asp->treecache_len = 0;
01288 asp->reqinfo = SNMP_MALLOC_TYPEDEF(netsnmp_agent_request_info);
01289 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p created\n",
01290 asp, asp->reqinfo));
01291
01292 return asp;
01293 }
01294
01295 void
01296 free_agent_snmp_session(netsnmp_agent_session *asp)
01297 {
01298 if (!asp)
01299 return;
01300
01301 DEBUGMSGTL(("snmp_agent","agent_session %08p released\n", asp));
01302
01303 netsnmp_remove_from_delegated(asp);
01304
01305 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p freed\n",
01306 asp, asp->reqinfo));
01307 if (asp->orig_pdu)
01308 snmp_free_pdu(asp->orig_pdu);
01309 if (asp->pdu)
01310 snmp_free_pdu(asp->pdu);
01311 if (asp->reqinfo)
01312 netsnmp_free_agent_request_info(asp->reqinfo);
01313 if (asp->treecache) {
01314 SNMP_FREE(asp->treecache);
01315 }
01316 if (asp->bulkcache) {
01317 SNMP_FREE(asp->bulkcache);
01318 }
01319 if (asp->requests) {
01320 int i;
01321 for (i = 0; i < asp->vbcount; i++) {
01322 netsnmp_free_request_data_sets(&asp->requests[i]);
01323 }
01324 SNMP_FREE(asp->requests);
01325 }
01326 if (asp->cache_store) {
01327 netsnmp_free_cachemap(asp->cache_store);
01328 asp->cache_store = NULL;
01329 }
01330 SNMP_FREE(asp);
01331 }
01332
01333 int
01334 netsnmp_check_for_delegated(netsnmp_agent_session *asp)
01335 {
01336 int i;
01337 netsnmp_request_info *request;
01338
01339 if (NULL == asp->treecache)
01340 return 0;
01341
01342 for (i = 0; i <= asp->treecache_num; i++) {
01343 for (request = asp->treecache[i].requests_begin; request;
01344 request = request->next) {
01345 if (request->delegated)
01346 return 1;
01347 }
01348 }
01349 return 0;
01350 }
01351
01352 int
01353 netsnmp_check_delegated_chain_for(netsnmp_agent_session *asp)
01354 {
01355 netsnmp_agent_session *asptmp;
01356 for (asptmp = agent_delegated_list; asptmp; asptmp = asptmp->next) {
01357 if (asptmp == asp)
01358 return 1;
01359 }
01360 return 0;
01361 }
01362
01363 int
01364 netsnmp_check_for_delegated_and_add(netsnmp_agent_session *asp)
01365 {
01366 if (netsnmp_check_for_delegated(asp)) {
01367 if (!netsnmp_check_delegated_chain_for(asp)) {
01368
01369
01370
01371 asp->next = agent_delegated_list;
01372 agent_delegated_list = asp;
01373 DEBUGMSGTL(("snmp_agent", "delegate session == %08p\n", asp));
01374 }
01375 return 1;
01376 }
01377 return 0;
01378 }
01379
01380 int
01381 netsnmp_remove_from_delegated(netsnmp_agent_session *asp)
01382 {
01383 netsnmp_agent_session *curr, *prev = NULL;
01384
01385 for (curr = agent_delegated_list; curr; prev = curr, curr = curr->next) {
01386
01387
01388
01389 if (curr != asp)
01390 continue;
01391
01392
01393
01394
01395 if (prev != NULL)
01396 prev->next = asp->next;
01397 else
01398 agent_delegated_list = asp->next;
01399
01400 DEBUGMSGTL(("snmp_agent", "remove delegated session == %08p\n", asp));
01401
01402 return 1;
01403 }
01404
01405 return 0;
01406 }
01407
01408
01409
01410
01411
01412
01413
01414
01415 int
01416 netsnmp_remove_delegated_requests_for_session(netsnmp_session *sess)
01417 {
01418 netsnmp_agent_session *asp;
01419 int count = 0;
01420
01421 for (asp = agent_delegated_list; asp; asp = asp->next) {
01422
01423
01424
01425 netsnmp_request_info *request;
01426 for(request = asp->requests; request; request = request->next) {
01427
01428
01429
01430 netsnmp_assert(NULL!=request->subtree);
01431 if(request->subtree->session != sess)
01432 continue;
01433
01434
01435
01436
01437 netsnmp_request_set_error(request, SNMP_ERR_GENERR);
01438 ++count;
01439 }
01440 }
01441
01442
01443
01444
01445 if(count) {
01446 DEBUGMSGTL(("snmp_agent", "removed %d delegated request(s) for session "
01447 "%08p\n", count, sess));
01448 netsnmp_check_outstanding_agent_requests();
01449 }
01450
01451 return count;
01452 }
01453
01454 int
01455 netsnmp_check_queued_chain_for(netsnmp_agent_session *asp)
01456 {
01457 netsnmp_agent_session *asptmp;
01458 for (asptmp = netsnmp_agent_queued_list; asptmp; asptmp = asptmp->next) {
01459 if (asptmp == asp)
01460 return 1;
01461 }
01462 return 0;
01463 }
01464
01465 int
01466 netsnmp_add_queued(netsnmp_agent_session *asp)
01467 {
01468 netsnmp_agent_session *asp_tmp;
01469
01470
01471
01472
01473 if (NULL == netsnmp_agent_queued_list) {
01474 netsnmp_agent_queued_list = asp;
01475 return 1;
01476 }
01477
01478
01479
01480
01481
01482 asp_tmp = netsnmp_agent_queued_list;
01483 for (; asp_tmp; asp_tmp = asp_tmp->next) {
01484
01485
01486
01487 if (asp_tmp == asp)
01488 break;
01489
01490
01491
01492
01493 if (NULL == asp_tmp->next)
01494 asp_tmp->next = asp;
01495 }
01496 return 1;
01497 }
01498
01499
01500 int
01501 netsnmp_wrap_up_request(netsnmp_agent_session *asp, int status)
01502 {
01503 netsnmp_variable_list *var_ptr;
01504 int i;
01505
01506
01507
01508
01509
01510 if (asp == netsnmp_processing_set) {
01511 DEBUGMSGTL(("snmp_agent", "SET request complete, asp = %08p\n",
01512 asp));
01513 netsnmp_processing_set = NULL;
01514 }
01515
01516 if (asp->pdu) {
01517
01518
01519
01520
01521 if ( status != 0 && asp->status == 0 )
01522 asp->status = status;
01523
01524 switch (asp->pdu->command) {
01525 case SNMP_MSG_INTERNAL_SET_BEGIN:
01526 case SNMP_MSG_INTERNAL_SET_RESERVE1:
01527 case SNMP_MSG_INTERNAL_SET_RESERVE2:
01528 case SNMP_MSG_INTERNAL_SET_ACTION:
01529
01530
01531
01532 save_set_cache(asp);
01533 break;
01534
01535 case SNMP_MSG_GETNEXT:
01536 _fix_endofmibview(asp);
01537 break;
01538
01539 case SNMP_MSG_GETBULK:
01540
01541
01542
01543 _reorder_getbulk(asp);
01544 break;
01545 }
01546
01547
01548
01549
01550
01551 #ifndef NETSNMP_DISABLE_SNMPV1
01552 if ((asp->pdu->command == SNMP_MSG_SET) &&
01553 (asp->pdu->version == SNMP_VERSION_1)) {
01554 switch (asp->status) {
01555 case SNMP_ERR_WRONGVALUE:
01556 case SNMP_ERR_WRONGENCODING:
01557 case SNMP_ERR_WRONGTYPE:
01558 case SNMP_ERR_WRONGLENGTH:
01559 case SNMP_ERR_INCONSISTENTVALUE:
01560 status = SNMP_ERR_BADVALUE;
01561 asp->status = SNMP_ERR_BADVALUE;
01562 break;
01563 case SNMP_ERR_NOACCESS:
01564 case SNMP_ERR_NOTWRITABLE:
01565 case SNMP_ERR_NOCREATION:
01566 case SNMP_ERR_INCONSISTENTNAME:
01567 case SNMP_ERR_AUTHORIZATIONERROR:
01568 status = SNMP_ERR_NOSUCHNAME;
01569 asp->status = SNMP_ERR_NOSUCHNAME;
01570 break;
01571 case SNMP_ERR_RESOURCEUNAVAILABLE:
01572 case SNMP_ERR_COMMITFAILED:
01573 case SNMP_ERR_UNDOFAILED:
01574 status = SNMP_ERR_GENERR;
01575 asp->status = SNMP_ERR_GENERR;
01576 break;
01577 }
01578 }
01579
01580
01581
01582
01583
01584 if ((asp->pdu->command != SNMP_MSG_SET) &&
01585 (asp->pdu->version == SNMP_VERSION_1)) {
01586 for (var_ptr = asp->pdu->variables, i = 1;
01587 var_ptr != NULL; var_ptr = var_ptr->next_variable, i++) {
01588 switch (var_ptr->type) {
01589 case SNMP_NOSUCHOBJECT:
01590 case SNMP_NOSUCHINSTANCE:
01591 case SNMP_ENDOFMIBVIEW:
01592 case ASN_COUNTER64:
01593 status = SNMP_ERR_NOSUCHNAME;
01594 asp->status = SNMP_ERR_NOSUCHNAME;
01595 asp->index = i;
01596 break;
01597 }
01598 }
01599 }
01600 #endif
01601 }
01603
01604
01605
01606
01607 #define INCLUDE_V2ERRORS_IN_V1STATS
01608
01609 switch (status) {
01610 #ifdef INCLUDE_V2ERRORS_IN_V1STATS
01611 case SNMP_ERR_WRONGVALUE:
01612 case SNMP_ERR_WRONGENCODING:
01613 case SNMP_ERR_WRONGTYPE:
01614 case SNMP_ERR_WRONGLENGTH:
01615 case SNMP_ERR_INCONSISTENTVALUE:
01616 #endif
01617 case SNMP_ERR_BADVALUE:
01618 snmp_increment_statistic(STAT_SNMPOUTBADVALUES);
01619 break;
01620 #ifdef INCLUDE_V2ERRORS_IN_V1STATS
01621 case SNMP_ERR_NOACCESS:
01622 case SNMP_ERR_NOTWRITABLE:
01623 case SNMP_ERR_NOCREATION:
01624 case SNMP_ERR_INCONSISTENTNAME:
01625 case SNMP_ERR_AUTHORIZATIONERROR:
01626 #endif
01627 case SNMP_ERR_NOSUCHNAME:
01628 snmp_increment_statistic(STAT_SNMPOUTNOSUCHNAMES);
01629 break;
01630 #ifdef INCLUDE_V2ERRORS_IN_V1STATS
01631 case SNMP_ERR_RESOURCEUNAVAILABLE:
01632 case SNMP_ERR_COMMITFAILED:
01633 case SNMP_ERR_UNDOFAILED:
01634 #endif
01635 case SNMP_ERR_GENERR:
01636 snmp_increment_statistic(STAT_SNMPOUTGENERRS);
01637 break;
01638
01639 case SNMP_ERR_TOOBIG:
01640 snmp_increment_statistic(STAT_SNMPOUTTOOBIGS);
01641 break;
01642 }
01643
01644 if ((status == SNMP_ERR_NOERROR) && (asp->pdu)) {
01645 snmp_increment_statistic_by((asp->pdu->command == SNMP_MSG_SET ?
01646 STAT_SNMPINTOTALSETVARS :
01647 STAT_SNMPINTOTALREQVARS),
01648 count_varbinds(asp->pdu->variables));
01649 } else {
01650
01651
01652
01653
01654 snmp_free_pdu(asp->pdu);
01655 asp->pdu = asp->orig_pdu;
01656 asp->orig_pdu = NULL;
01657 }
01658 if (asp->pdu) {
01659 asp->pdu->command = SNMP_MSG_RESPONSE;
01660 asp->pdu->errstat = asp->status;
01661 asp->pdu->errindex = asp->index;
01662 if (!snmp_send(asp->session, asp->pdu)) {
01663 netsnmp_variable_list *var_ptr;
01664 snmp_perror("send response");
01665 for (var_ptr = asp->pdu->variables; var_ptr != NULL;
01666 var_ptr = var_ptr->next_variable) {
01667 size_t c_oidlen = 256, c_outlen = 0;
01668 u_char *c_oid = (u_char *) malloc(c_oidlen);
01669
01670 if (c_oid) {
01671 if (!sprint_realloc_objid (&c_oid, &c_oidlen, &c_outlen, 1,
01672 var_ptr->name,
01673 var_ptr->name_length)) {
01674 snmp_log(LOG_ERR, " -- %s [TRUNCATED]\n", c_oid);
01675 } else {
01676 snmp_log(LOG_ERR, " -- %s\n", c_oid);
01677 }
01678 SNMP_FREE(c_oid);
01679 }
01680 }
01681 snmp_free_pdu(asp->pdu);
01682 asp->pdu = NULL;
01683 }
01684 snmp_increment_statistic(STAT_SNMPOUTPKTS);
01685 snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);
01686 asp->pdu = NULL;
01687 netsnmp_remove_and_free_agent_snmp_session(asp);
01688 }
01689 return 1;
01690 }
01691
01692 void
01693 dump_sess_list(void)
01694 {
01695 netsnmp_agent_session *a;
01696
01697 DEBUGMSGTL(("snmp_agent", "DUMP agent_sess_list -> "));
01698 for (a = agent_session_list; a != NULL; a = a->next) {
01699 DEBUGMSG(("snmp_agent", "%08p[session %08p] -> ", a, a->session));
01700 }
01701 DEBUGMSG(("snmp_agent", "[NIL]\n"));
01702 }
01703
01704 void
01705 netsnmp_remove_and_free_agent_snmp_session(netsnmp_agent_session *asp)
01706 {
01707 netsnmp_agent_session *a, **prevNext = &agent_session_list;
01708
01709 DEBUGMSGTL(("snmp_agent", "REMOVE session == %08p\n", asp));
01710
01711 for (a = agent_session_list; a != NULL; a = *prevNext) {
01712 if (a == asp) {
01713 *prevNext = a->next;
01714 a->next = NULL;
01715 free_agent_snmp_session(a);
01716 asp = NULL;
01717 break;
01718 } else {
01719 prevNext = &(a->next);
01720 }
01721 }
01722
01723 if (a == NULL && asp != NULL) {
01724
01725
01726
01727 free_agent_snmp_session(asp);
01728 }
01729 }
01730
01731 void
01732 netsnmp_free_agent_snmp_session_by_session(netsnmp_session * sess,
01733 void (*free_request)
01734 (netsnmp_request_list *))
01735 {
01736 netsnmp_agent_session *a, *next, **prevNext = &agent_session_list;
01737
01738 DEBUGMSGTL(("snmp_agent", "REMOVE session == %08p\n", sess));
01739
01740 for (a = agent_session_list; a != NULL; a = next) {
01741 if (a->session == sess) {
01742 *prevNext = a->next;
01743 next = a->next;
01744 free_agent_snmp_session(a);
01745 } else {
01746 prevNext = &(a->next);
01747 next = a->next;
01748 }
01749 }
01750 }
01751
01753 int
01754 handle_snmp_packet(int op, netsnmp_session * session, int reqid,
01755 netsnmp_pdu *pdu, void *magic)
01756 {
01757 netsnmp_agent_session *asp;
01758 int status, access_ret, rc;
01759
01760
01761
01762
01763 if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
01764 return 1;
01765 }
01766
01767
01768
01769
01770
01771 if (pdu->command == SNMP_MSG_TRAP || pdu->command == SNMP_MSG_INFORM ||
01772 pdu->command == SNMP_MSG_TRAP2) {
01773 DEBUGMSGTL(("snmp_agent", "received trap-like PDU (%02x)\n",
01774 pdu->command));
01775 pdu->command = SNMP_MSG_TRAP2;
01776 snmp_increment_statistic(STAT_SNMPUNKNOWNPDUHANDLERS);
01777 return 1;
01778 }
01779
01780
01781
01782
01783 if (pdu->version == SNMP_VERSION_3 &&
01784 session->s_snmp_errno == SNMPERR_USM_AUTHENTICATIONFAILURE) {
01785 send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
01786 return 1;
01787 }
01788
01789 if (magic == NULL) {
01790 asp = init_agent_snmp_session(session, pdu);
01791 status = SNMP_ERR_NOERROR;
01792 } else {
01793 asp = (netsnmp_agent_session *) magic;
01794 status = asp->status;
01795 }
01796
01797 if ((access_ret = check_access(asp->pdu)) != 0) {
01798 if (access_ret == VACM_NOSUCHCONTEXT) {
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808 snmp_increment_statistic(STAT_SNMPUNKNOWNCONTEXTS);
01809
01810
01811
01812
01813 netsnmp_remove_and_free_agent_snmp_session(asp);
01814 return 0;
01815 } else {
01816
01817
01818
01819 send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
01820 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
01821 #if defined(NETSNMP_DISABLE_SNMPV1)
01822 if (asp->pdu->version != SNMP_VERSION_2c) {
01823 #else
01824 #if defined(NETSNMP_DISABLE_SNMPV2C)
01825 if (asp->pdu->version != SNMP_VERSION_1) {
01826 #else
01827 if (asp->pdu->version != SNMP_VERSION_1
01828 && asp->pdu->version != SNMP_VERSION_2c) {
01829 #endif
01830 #endif
01831 asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR;
01832 asp->pdu->command = SNMP_MSG_RESPONSE;
01833 snmp_increment_statistic(STAT_SNMPOUTPKTS);
01834 if (!snmp_send(asp->session, asp->pdu))
01835 snmp_free_pdu(asp->pdu);
01836 asp->pdu = NULL;
01837 netsnmp_remove_and_free_agent_snmp_session(asp);
01838 return 1;
01839 } else {
01840 #endif
01841
01842
01843
01844 netsnmp_remove_and_free_agent_snmp_session(asp);
01845 return 0;
01846 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
01847 }
01848 #endif
01849 }
01850 }
01851
01852 rc = netsnmp_handle_request(asp, status);
01853
01854
01855
01856
01857 DEBUGMSGTL(("snmp_agent", "end of handle_snmp_packet, asp = %08p\n",
01858 asp));
01859 return rc;
01860 }
01861
01862 netsnmp_request_info *
01863 netsnmp_add_varbind_to_cache(netsnmp_agent_session *asp, int vbcount,
01864 netsnmp_variable_list * varbind_ptr,
01865 netsnmp_subtree *tp)
01866 {
01867 netsnmp_request_info *request = NULL;
01868 int cacheid;
01869
01870 DEBUGMSGTL(("snmp_agent", "add_vb_to_cache(%8p, %d, ", asp, vbcount));
01871 DEBUGMSGOID(("snmp_agent", varbind_ptr->name,
01872 varbind_ptr->name_length));
01873 DEBUGMSG(("snmp_agent", ", %8p)\n", tp));
01874
01875 if (tp &&
01876 (asp->pdu->command == SNMP_MSG_GETNEXT ||
01877 asp->pdu->command == SNMP_MSG_GETBULK)) {
01878 int result;
01879 int prefix_len;
01880
01881 prefix_len = netsnmp_oid_find_prefix(tp->start_a,
01882 tp->start_len,
01883 tp->end_a, tp->end_len);
01884 if (prefix_len < 1) {
01885 result = VACM_NOTINVIEW;
01886 } else {
01887 result =
01888 netsnmp_acm_check_subtree(asp->pdu, tp->start_a, prefix_len);
01889 }
01890
01891 while (result == VACM_NOTINVIEW) {
01892
01900 tp = tp->next;
01901 if (tp) {
01902 prefix_len = netsnmp_oid_find_prefix(tp->start_a,
01903 tp->start_len,
01904 tp->end_a,
01905 tp->end_len);
01906 if (prefix_len < 1) {
01907
01908 result = VACM_NOTINVIEW;
01909 } else {
01910 result =
01911 netsnmp_acm_check_subtree(asp->pdu,
01912 tp->start_a, prefix_len);
01913 }
01914 }
01915 else
01916 break;
01917 }
01918 }
01919 if (tp == NULL) {
01920
01921
01922
01923
01924
01925
01926 switch (asp->pdu->command) {
01927 case SNMP_MSG_GETNEXT:
01928 case SNMP_MSG_GETBULK:
01929 varbind_ptr->type = SNMP_ENDOFMIBVIEW;
01930 break;
01931
01932 case SNMP_MSG_SET:
01933 case SNMP_MSG_GET:
01934 varbind_ptr->type = SNMP_NOSUCHOBJECT;
01935 break;
01936
01937 default:
01938 return NULL;
01939 }
01940 } else {
01941 DEBUGMSGTL(("snmp_agent", "tp->start "));
01942 DEBUGMSGOID(("snmp_agent", tp->start_a, tp->start_len));
01943 DEBUGMSG(("snmp_agent", ", tp->end "));
01944 DEBUGMSGOID(("snmp_agent", tp->end_a, tp->end_len));
01945 DEBUGMSG(("snmp_agent", ", \n"));
01946
01947
01948
01949
01950 request = &(asp->requests[vbcount - 1]);
01951 request->index = vbcount;
01952 request->delegated = 0;
01953 request->processed = 0;
01954 request->status = 0;
01955 request->subtree = tp;
01956 request->agent_req_info = asp->reqinfo;
01957 if (request->parent_data) {
01958 netsnmp_free_request_data_sets(request);
01959 }
01960 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p assigned to request\n",
01961 asp, asp->reqinfo));
01962
01963
01964
01965
01966 if (!MODE_IS_SET(asp->pdu->command)) {
01967 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p assigned to request\n",
01968 asp, asp->reqinfo));
01969 if (varbind_ptr->type == ASN_PRIV_INCL_RANGE) {
01970 DEBUGMSGTL(("snmp_agent", "varbind %d is inclusive\n",
01971 request->index));
01972 request->inclusive = 1;
01973 }
01974 varbind_ptr->type = ASN_NULL;
01975 }
01976
01977
01978
01979
01980 if (tp->global_cacheid) {
01981
01982
01983
01984 if (asp->cache_store && -1 !=
01985 (cacheid = netsnmp_get_local_cachid(asp->cache_store,
01986 tp->global_cacheid))) {
01987 } else {
01988 cacheid = ++(asp->treecache_num);
01989 netsnmp_get_or_add_local_cachid(&asp->cache_store,
01990 tp->global_cacheid,
01991 cacheid);
01992 goto mallocslot;
01993 }
01994 } else if (tp->cacheid > -1 && tp->cacheid <= asp->treecache_num &&
01995 asp->treecache[tp->cacheid].subtree == tp) {
01996
01997
01998
01999
02000 cacheid = tp->cacheid;
02001 } else {
02002 cacheid = ++(asp->treecache_num);
02003 mallocslot:
02004
02005
02006
02007 if (asp->treecache_num >= asp->treecache_len) {
02008
02009
02010
02011
02012
02013
02014 #define CACHE_GROW_SIZE 16
02015 asp->treecache_len =
02016 (asp->treecache_len + CACHE_GROW_SIZE);
02017 asp->treecache =
02018 realloc(asp->treecache,
02019 sizeof(netsnmp_tree_cache) *
02020 asp->treecache_len);
02021 if (asp->treecache == NULL)
02022 return NULL;
02023 memset(&(asp->treecache[cacheid]), 0x00,
02024 sizeof(netsnmp_tree_cache) * (CACHE_GROW_SIZE));
02025 }
02026 asp->treecache[cacheid].subtree = tp;
02027 asp->treecache[cacheid].requests_begin = request;
02028 tp->cacheid = cacheid;
02029 }
02030
02031
02032
02033
02034 if (asp->pdu->command == SNMP_MSG_GETNEXT ||
02035 asp->pdu->command == SNMP_MSG_GETBULK) {
02036 request->range_end = tp->end_a;
02037 request->range_end_len = tp->end_len;
02038 } else {
02039 request->range_end = NULL;
02040 request->range_end_len = 0;
02041 }
02042
02043
02044
02045
02046 if (asp->treecache[cacheid].requests_end)
02047 asp->treecache[cacheid].requests_end->next = request;
02048 request->next = NULL;
02049 request->prev = asp->treecache[cacheid].requests_end;
02050 asp->treecache[cacheid].requests_end = request;
02051
02052
02053
02054
02055
02056 request->requestvb = request->requestvb_start = varbind_ptr;
02057 }
02058 return request;
02059 }
02060
02061
02062
02063
02064
02065
02066
02067 int
02068 check_acm(netsnmp_agent_session *asp, u_char type)
02069 {
02070 int view;
02071 int i, j, k;
02072 netsnmp_request_info *request;
02073 int ret = 0;
02074 netsnmp_variable_list *vb, *vb2, *vbc;
02075 int earliest = 0;
02076
02077 for (i = 0; i <= asp->treecache_num; i++) {
02078 for (request = asp->treecache[i].requests_begin;
02079 request; request = request->next) {
02080
02081
02082
02083 earliest = 0;
02084 for(j = request->repeat, vb = request->requestvb_start;
02085 vb && j > -1;
02086 j--, vb = vb->next_variable) {
02087 if (vb->type != ASN_NULL &&
02088 vb->type != ASN_PRIV_RETRY) {
02089 view =
02090 in_a_view(vb->name, &vb->name_length,
02091 asp->pdu, vb->type);
02092
02093
02094
02095
02096 if (view != VACM_SUCCESS) {
02097 ret++;
02098 if (request->repeat < request->orig_repeat) {
02099
02100 request->repeat++;
02101 if (!earliest) {
02102 request->requestvb = vb;
02103 earliest = 1;
02104 }
02105
02106
02107
02108
02109
02110 if (j > -1 && vb->next_variable &&
02111 vb->next_variable->type != ASN_NULL &&
02112 vb->next_variable->type != ASN_PRIV_RETRY) {
02113 for(k = j, vbc = vb, vb2 = vb->next_variable;
02114 k > -2 && vbc && vb2;
02115 k--, vbc = vb2, vb2 = vb2->next_variable) {
02116
02117 snmp_clone_var(vb2, vbc);
02118 vbc->next_variable = vb2;
02119 }
02120 }
02121 }
02122 snmp_set_var_typed_value(vb, type, NULL, 0);
02123 }
02124 }
02125 }
02126 }
02127 }
02128 return ret;
02129 }
02130
02131
02132 int
02133 netsnmp_create_subtree_cache(netsnmp_agent_session *asp)
02134 {
02135 netsnmp_subtree *tp;
02136 netsnmp_variable_list *varbind_ptr, *vbsave, *vbptr, **prevNext;
02137 int view;
02138 int vbcount = 0;
02139 int bulkcount = 0, bulkrep = 0;
02140 int i = 0, n = 0, r = 0;
02141 netsnmp_request_info *request;
02142
02143 if (asp->treecache == NULL && asp->treecache_len == 0) {
02144 asp->treecache_len = SNMP_MAX(1 + asp->vbcount / 4, 16);
02145 asp->treecache =
02146 calloc(asp->treecache_len, sizeof(netsnmp_tree_cache));
02147 if (asp->treecache == NULL)
02148 return SNMP_ERR_GENERR;
02149 }
02150 asp->treecache_num = -1;
02151
02152 if (asp->pdu->command == SNMP_MSG_GETBULK) {
02153
02154
02155
02156 int count = count_varbinds(asp->pdu->variables);
02157 if (asp->pdu->errstat < 0) {
02158 asp->pdu->errstat = 0;
02159 }
02160 if (asp->pdu->errindex < 0) {
02161 asp->pdu->errindex = 0;
02162 }
02163
02164 if (asp->pdu->errstat < count) {
02165 n = asp->pdu->errstat;
02166 } else {
02167 n = count;
02168 }
02169 if ((r = count - n) <= 0) {
02170 r = 0;
02171 asp->bulkcache = NULL;
02172 } else {
02173 int numresponses;
02174 int maxbulk =
02175 netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
02176 NETSNMP_DS_AGENT_MAX_GETBULKREPEATS);
02177 int maxresponses =
02178 netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
02179 NETSNMP_DS_AGENT_MAX_GETBULKRESPONSES);
02180
02181 if (maxresponses == 0)
02182 maxresponses = 100;
02183
02184 if (maxbulk == 0)
02185 maxbulk = -1;
02186
02187
02188 if (asp->pdu->errindex > maxbulk && maxbulk != -1) {
02189 asp->pdu->errindex = maxbulk;
02190 }
02191
02192 numresponses = asp->pdu->errindex * r;
02193
02194
02195 if (maxresponses != -1 && numresponses > maxresponses) {
02196
02197 asp->pdu->errindex = maxresponses/r;
02198 numresponses = asp->pdu->errindex * r;
02199 DEBUGMSGTL(("snmp_agent", "truncating number of getbulk repeats to %d\n", asp->pdu->errindex));
02200 }
02201
02202 asp->bulkcache =
02203 (netsnmp_variable_list **) malloc(numresponses *
02204 sizeof(struct
02205 varbind_list *));
02206 if (!asp->bulkcache) {
02207 DEBUGMSGTL(("snmp_agent", "Bulkcache malloc failed\n"));
02208 return SNMP_ERR_GENERR;
02209 }
02210 }
02211 DEBUGMSGTL(("snmp_agent", "GETBULK N = %d, M = %d, R = %d\n",
02212 n, asp->pdu->errindex, r));
02213 }
02214
02215
02216
02217
02218 prevNext = &(asp->pdu->variables);
02219 for (varbind_ptr = asp->pdu->variables; varbind_ptr;
02220 varbind_ptr = vbsave) {
02221
02222
02223
02224
02225 vbsave = varbind_ptr->next_variable;
02226
02227 if (asp->pdu->command == SNMP_MSG_GETBULK) {
02228 if (n > 0) {
02229 n--;
02230 } else {
02231
02232
02233
02234
02235
02236
02237 bulkrep = asp->pdu->errindex - 1;
02238 if (asp->pdu->errindex > 0) {
02239 vbptr = varbind_ptr;
02240 asp->bulkcache[bulkcount++] = vbptr;
02241
02242 for (i = 1; i < asp->pdu->errindex; i++) {
02243 vbptr->next_variable =
02244 SNMP_MALLOC_STRUCT(variable_list);
02245
02246
02247
02248
02249 if (!vbptr->next_variable) {
02250
02251
02252
02253 DEBUGMSGTL(("snmp_agent", "NextVar malloc failed\n"));
02254 } else {
02255 vbptr = vbptr->next_variable;
02256 vbptr->name_length = 0;
02257 vbptr->type = ASN_NULL;
02258 asp->bulkcache[bulkcount++] = vbptr;
02259 }
02260 }
02261 vbptr->next_variable = vbsave;
02262 } else {
02263
02264
02265
02266
02267 vbptr = varbind_ptr;
02268 *prevNext = vbptr->next_variable;
02269 vbptr->next_variable = NULL;
02270 snmp_free_varbind(vbptr);
02271 asp->vbcount--;
02272 continue;
02273 }
02274 }
02275 }
02276
02277
02278
02279
02280 ++vbcount;
02281
02282
02283
02284
02285 tp = netsnmp_subtree_find(varbind_ptr->name, varbind_ptr->name_length,
02286 NULL, asp->pdu->contextName);
02287
02288
02289
02290
02291 switch (asp->pdu->command) {
02292 case SNMP_MSG_GET:
02293 view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,
02294 asp->pdu, varbind_ptr->type);
02295 if (view != VACM_SUCCESS)
02296 snmp_set_var_typed_value(varbind_ptr, SNMP_NOSUCHOBJECT,
02297 NULL, 0);
02298 break;
02299
02300 case SNMP_MSG_SET:
02301 view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,
02302 asp->pdu, varbind_ptr->type);
02303 if (view != VACM_SUCCESS)
02304 return SNMP_ERR_NOACCESS;
02305 break;
02306
02307 case SNMP_MSG_GETNEXT:
02308 case SNMP_MSG_GETBULK:
02309 default:
02310 view = VACM_SUCCESS;
02311
02312
02313
02314 }
02315 if (view == VACM_SUCCESS) {
02316 request = netsnmp_add_varbind_to_cache(asp, vbcount, varbind_ptr,
02317 tp);
02318 if (request && asp->pdu->command == SNMP_MSG_GETBULK) {
02319 request->repeat = request->orig_repeat = bulkrep;
02320 }
02321 }
02322
02323 prevNext = &(varbind_ptr->next_variable);
02324 }
02325
02326 return SNMPERR_SUCCESS;
02327 }
02328
02329
02330
02331
02332 int
02333 netsnmp_reassign_requests(netsnmp_agent_session *asp)
02334 {
02335
02336
02337
02338
02339
02340
02341 int i;
02342
02343
02344
02345
02346 netsnmp_tree_cache *old_treecache = asp->treecache;
02347
02348
02349
02350
02351 asp->treecache =
02352 (netsnmp_tree_cache *) calloc(asp->treecache_len,
02353 sizeof(netsnmp_tree_cache));
02354 asp->treecache_num = -1;
02355 if (asp->cache_store) {
02356 netsnmp_free_cachemap(asp->cache_store);
02357 asp->cache_store = NULL;
02358 }
02359
02360 for (i = 0; i < asp->vbcount; i++) {
02361 if (asp->requests[i].requestvb == NULL) {
02362
02363
02364
02365
02366 continue;
02367 }
02368 if (asp->requests[i].requestvb->type == ASN_NULL) {
02369 if (!netsnmp_add_varbind_to_cache(asp, asp->requests[i].index,
02370 asp->requests[i].requestvb,
02371 asp->requests[i].subtree->next)) {
02372 if (old_treecache != NULL) {
02373 SNMP_FREE(old_treecache);
02374 old_treecache = NULL;
02375 }
02376 }
02377 } else if (asp->requests[i].requestvb->type == ASN_PRIV_RETRY) {
02378
02379
02380
02381 asp->requests[i].requestvb->type = ASN_NULL;
02382 if (!netsnmp_add_varbind_to_cache(asp, asp->requests[i].index,
02383 asp->requests[i].requestvb,
02384 asp->requests[i].subtree)) {
02385 if (old_treecache != NULL) {
02386 SNMP_FREE(old_treecache);
02387 old_treecache = NULL;
02388 }
02389 }
02390 }
02391 }
02392
02393 if (old_treecache != NULL) {
02394 SNMP_FREE(old_treecache);
02395 }
02396 return SNMP_ERR_NOERROR;
02397 }
02398
02399 void
02400 netsnmp_delete_request_infos(netsnmp_request_info *reqlist)
02401 {
02402 while (reqlist) {
02403 netsnmp_free_request_data_sets(reqlist);
02404 reqlist = reqlist->next;
02405 }
02406 }
02407
02408 void
02409 netsnmp_delete_subtree_cache(netsnmp_agent_session *asp)
02410 {
02411 while (asp->treecache_num >= 0) {
02412
02413
02414
02415 netsnmp_delete_request_infos(asp->treecache[asp->treecache_num].
02416 requests_begin);
02417 asp->treecache_num--;
02418 }
02419 }
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433 int
02434 netsnmp_check_all_requests_error(netsnmp_agent_session *asp,
02435 int look_for_specific)
02436 {
02437 int i;
02438
02439
02440
02441
02442 for( i = 0; i < asp->vbcount; ++i ) {
02443 if ((SNMP_ERR_NOERROR != asp->requests[i].status) &&
02444 (!look_for_specific ||
02445 asp->requests[i].status == look_for_specific))
02446 return asp->requests[i].status;
02447 }
02448
02449 return SNMP_ERR_NOERROR;
02450 }
02451
02452 int
02453 netsnmp_check_requests_error(netsnmp_request_info *requests)
02454 {
02455
02456
02457
02458 for (;requests;requests = requests->next) {
02459 if (requests->status != SNMP_ERR_NOERROR)
02460 return requests->status;
02461 }
02462 return SNMP_ERR_NOERROR;
02463 }
02464
02465 int
02466 netsnmp_check_requests_status(netsnmp_agent_session *asp,
02467 netsnmp_request_info *requests,
02468 int look_for_specific)
02469 {
02470
02471
02472
02473 while (requests) {
02474 if(requests->agent_req_info != asp->reqinfo) {
02475 DEBUGMSGTL(("verbose:asp",
02476 "**reqinfo %p doesn't match cached reqinfo %p\n",
02477 asp->reqinfo, requests->agent_req_info));
02478 }
02479 if (requests->status != SNMP_ERR_NOERROR &&
02480 (!look_for_specific || requests->status == look_for_specific)
02481 && (look_for_specific || asp->index == 0
02482 || requests->index < asp->index)) {
02483 asp->index = requests->index;
02484 asp->status = requests->status;
02485 }
02486 requests = requests->next;
02487 }
02488 return asp->status;
02489 }
02490
02491 int
02492 netsnmp_check_all_requests_status(netsnmp_agent_session *asp,
02493 int look_for_specific)
02494 {
02495 int i;
02496 for (i = 0; i <= asp->treecache_num; i++) {
02497 netsnmp_check_requests_status(asp,
02498 asp->treecache[i].requests_begin,
02499 look_for_specific);
02500 }
02501 return asp->status;
02502 }
02503
02504 int
02505 handle_var_requests(netsnmp_agent_session *asp)
02506 {
02507 int i, retstatus = SNMP_ERR_NOERROR,
02508 status = SNMP_ERR_NOERROR, final_status = SNMP_ERR_NOERROR;
02509 netsnmp_handler_registration *reginfo;
02510
02511 asp->reqinfo->asp = asp;
02512 asp->reqinfo->mode = asp->mode;
02513
02514
02515
02516
02517 for (i = 0; i <= asp->treecache_num; i++) {
02518
02519
02520
02521
02522
02523
02524 if(NULL != asp->treecache[i].subtree->reginfo) {
02525 reginfo = asp->treecache[i].subtree->reginfo;
02526 status = netsnmp_call_handlers(reginfo, asp->reqinfo,
02527 asp->treecache[i].requests_begin);
02528 }
02529 else
02530 status = SNMP_ERR_GENERR;
02531
02532
02533
02534
02535
02536
02537
02538 switch (asp->mode) {
02539 case MODE_SET_COMMIT:
02540 retstatus = netsnmp_check_requests_status(asp,
02541 asp->treecache[i].
02542 requests_begin,
02543 SNMP_ERR_COMMITFAILED);
02544 break;
02545
02546 case MODE_SET_UNDO:
02547 retstatus = netsnmp_check_requests_status(asp,
02548 asp->treecache[i].
02549 requests_begin,
02550 SNMP_ERR_UNDOFAILED);
02551 break;
02552
02553 default:
02554 retstatus = netsnmp_check_requests_status(asp,
02555 asp->treecache[i].
02556 requests_begin, 0);
02557 break;
02558 }
02559
02560
02561
02562
02563 if (retstatus != SNMP_ERR_NOERROR) {
02564 status = retstatus;
02565 }
02566
02567
02568
02569
02570
02571
02572
02573 if (final_status == SNMP_ERR_NOERROR && status != SNMP_ERR_NOERROR) {
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583 final_status = status;
02584 }
02585 }
02586
02587 return final_status;
02588 }
02589
02590
02591
02592
02593
02594
02595 void
02596 netsnmp_check_outstanding_agent_requests(void)
02597 {
02598 netsnmp_agent_session *asp, *prev_asp = NULL, *next_asp = NULL;
02599
02600
02601
02602
02603 for (asp = agent_delegated_list; asp; asp = next_asp) {
02604 next_asp = asp->next;
02605 if (!netsnmp_check_for_delegated(asp)) {
02606
02607
02608
02609
02610 if (prev_asp != NULL)
02611 prev_asp->next = asp->next;
02612 else
02613 agent_delegated_list = asp->next;
02614 asp->next = NULL;
02615
02616
02617
02618
02619 netsnmp_check_all_requests_status(asp, 0);
02620
02621
02622
02623
02624 check_delayed_request(asp);
02625
02626
02627
02628
02629
02630 if ((prev_asp == NULL) && (agent_delegated_list == asp)) {
02631 prev_asp = asp;
02632 }
02633 } else {
02634
02635
02636
02637
02638 prev_asp = asp;
02639 }
02640 }
02641
02642
02643
02644
02645
02646 if (netsnmp_processing_set && (NULL != agent_delegated_list))
02647 return;
02648
02649 while (netsnmp_agent_queued_list) {
02650
02651
02652
02653
02654
02655 netsnmp_assert((!netsnmp_processing_set) ||
02656 (netsnmp_processing_set == netsnmp_agent_queued_list));
02657
02658
02659
02660
02661
02662 if ((netsnmp_agent_queued_list->pdu->command == SNMP_MSG_SET) &&
02663 (agent_delegated_list)) {
02664
02665 netsnmp_assert(netsnmp_processing_set == NULL);
02666
02667 netsnmp_processing_set = netsnmp_agent_queued_list;
02668 DEBUGMSGTL(("snmp_agent", "SET request remains queued while "
02669 "delegated requests finish, asp = %08p\n", asp));
02670 break;
02671 }
02672
02673
02674
02675
02676 asp = netsnmp_agent_queued_list;
02677 netsnmp_agent_queued_list = asp->next;
02678 DEBUGMSGTL(("snmp_agent",
02679 "processing queued request, asp = %08p\n", asp));
02680
02681 netsnmp_handle_request(asp, asp->status);
02682
02683
02684
02685
02686 if (NULL != netsnmp_processing_set)
02687 break;
02688 }
02689 }
02690
02696 int
02697 netsnmp_check_transaction_id(int transaction_id)
02698 {
02699 netsnmp_agent_session *asp, *prev_asp = NULL;
02700
02701 for (asp = agent_delegated_list; asp; prev_asp = asp, asp = asp->next) {
02702 if (asp->pdu->transid == transaction_id)
02703 return SNMPERR_SUCCESS;
02704 }
02705 return SNMPERR_GENERR;
02706 }
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717 int
02718 check_delayed_request(netsnmp_agent_session *asp)
02719 {
02720 int status = SNMP_ERR_NOERROR;
02721
02722 DEBUGMSGTL(("snmp_agent", "processing delegated request, asp = %08p\n",
02723 asp));
02724
02725 switch (asp->mode) {
02726 case SNMP_MSG_GETBULK:
02727 case SNMP_MSG_GETNEXT:
02728 netsnmp_check_all_requests_status(asp, 0);
02729 handle_getnext_loop(asp);
02730 if (netsnmp_check_for_delegated(asp) &&
02731 netsnmp_check_transaction_id(asp->pdu->transid) !=
02732 SNMPERR_SUCCESS) {
02733
02734
02735
02736 if (!netsnmp_check_delegated_chain_for(asp)) {
02737 asp->next = agent_delegated_list;
02738 agent_delegated_list = asp;
02739 }
02740 }
02741 break;
02742
02743 case MODE_SET_COMMIT:
02744 netsnmp_check_all_requests_status(asp, SNMP_ERR_COMMITFAILED);
02745 goto settop;
02746
02747 case MODE_SET_UNDO:
02748 netsnmp_check_all_requests_status(asp, SNMP_ERR_UNDOFAILED);
02749 goto settop;
02750
02751 case MODE_SET_BEGIN:
02752 case MODE_SET_RESERVE1:
02753 case MODE_SET_RESERVE2:
02754 case MODE_SET_ACTION:
02755 case MODE_SET_FREE:
02756 settop:
02757
02758
02759 if ((asp->pdu->flags & UCD_MSG_FLAG_ONE_PASS_ONLY)) {
02760
02761
02762 break;
02763 }
02764 handle_set_loop(asp);
02765 if (asp->mode != FINISHED_SUCCESS && asp->mode != FINISHED_FAILURE) {
02766
02767 if (netsnmp_check_for_delegated_and_add(asp)) {
02768
02769
02770
02771 if (!asp->status)
02772 asp->status = status;
02773 }
02774
02775 return SNMP_ERR_NOERROR;
02776 }
02777 break;
02778
02779 default:
02780 break;
02781 }
02782
02783
02784
02785
02786 if (!netsnmp_check_for_delegated(asp))
02787 return netsnmp_wrap_up_request(asp, status);
02788
02789 return 1;
02790 }
02791
02793 int
02794 check_getnext_results(netsnmp_agent_session *asp)
02795 {
02796
02797
02798
02799 netsnmp_tree_cache *old_treecache = asp->treecache;
02800 int old_treecache_num = asp->treecache_num;
02801 int count = 0;
02802 int i, special = 0;
02803 netsnmp_request_info *request;
02804
02805 if (asp->mode == SNMP_MSG_GET) {
02806
02807
02808
02809
02810 DEBUGMSGTL(("snmp_agent",
02811 "asp->mode == SNMP_MSG_GET in ch_getnext\n"));
02812 asp->mode = asp->oldmode;
02813 special = 1;
02814 }
02815
02816 for (i = 0; i <= old_treecache_num; i++) {
02817 for (request = old_treecache[i].requests_begin; request;
02818 request = request->next) {
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828 if (special) {
02829 if (!request->inclusive) {
02830 DEBUGMSGTL(("snmp_agent",
02831 "request %d wasn't inclusive\n",
02832 request->index));
02833 snmp_set_var_typed_value(request->requestvb,
02834 ASN_PRIV_RETRY, NULL, 0);
02835 } else if (request->requestvb->type == ASN_NULL ||
02836 request->requestvb->type == SNMP_NOSUCHINSTANCE ||
02837 request->requestvb->type == SNMP_NOSUCHOBJECT) {
02838
02839
02840
02841
02842 snmp_set_var_typed_value(request->requestvb,
02843 ASN_PRIV_RETRY, NULL, 0);
02844 }
02845 }
02846
02847
02848
02849
02850 if (snmp_oid_compare(request->requestvb->name,
02851 request->requestvb->name_length,
02852 request->range_end,
02853 request->range_end_len) >= 0) {
02854
02855
02856
02857
02858
02859
02860 DEBUGMSGTL(("check_getnext_results",
02861 "request response %d out of range\n",
02862 request->index));
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874 request->inclusive = 2;
02875
02876
02877
02878 snmp_set_var_objid(request->requestvb,
02879 request->range_end,
02880 request->range_end_len);
02881 snmp_set_var_typed_value(request->requestvb, ASN_NULL,
02882 NULL, 0);
02883 }
02884
02885
02886
02887
02888 if (request->requestvb->type == SNMP_ENDOFMIBVIEW) {
02889
02890
02891
02892
02893 request->requestvb->type = ASN_NULL;
02894 request->inclusive = 1;
02895 }
02896
02897 if (request->requestvb->type == ASN_NULL ||
02898 request->requestvb->type == ASN_PRIV_RETRY ||
02899 (asp->reqinfo->mode == MODE_GETBULK
02900 && request->repeat > 0))
02901 count++;
02902 }
02903 }
02904 return count;
02905 }
02906
02910 int
02911 handle_getnext_loop(netsnmp_agent_session *asp)
02912 {
02913 int status;
02914 netsnmp_variable_list *var_ptr;
02915
02916
02917
02918
02919 while (netsnmp_running) {
02920
02921
02922
02923
02924 if (netsnmp_check_for_delegated(asp)) {
02925 return SNMP_ERR_NOERROR;
02926 }
02927
02928
02929
02930
02931 check_acm(asp, ASN_PRIV_RETRY);
02932
02933
02934
02935
02936 if (!check_getnext_results(asp))
02937
02938
02939
02940 break;
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954 DEBUGIF("results") {
02955 DEBUGMSGTL(("results",
02956 "getnext results, before next pass:\n"));
02957 for (var_ptr = asp->pdu->variables; var_ptr;
02958 var_ptr = var_ptr->next_variable) {
02959 DEBUGMSGTL(("results", "\t"));
02960 DEBUGMSGVAR(("results", var_ptr));
02961 DEBUGMSG(("results", "\n"));
02962 }
02963 }
02964
02965 netsnmp_reassign_requests(asp);
02966 status = handle_var_requests(asp);
02967 if (status != SNMP_ERR_NOERROR) {
02968 return status;
02969 }
02970 }
02971 return SNMP_ERR_NOERROR;
02972 }
02973
02974 int
02975 handle_set(netsnmp_agent_session *asp)
02976 {
02977 int status;
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993 if (!(asp->pdu->flags & UCD_MSG_FLAG_ONE_PASS_ONLY)) {
02994 switch (asp->mode) {
02995 case MODE_SET_BEGIN:
02996 snmp_increment_statistic(STAT_SNMPINSETREQUESTS);
02997 asp->rw = WRITE;
02998 asp->mode = MODE_SET_RESERVE1;
02999 asp->status = SNMP_ERR_NOERROR;
03000 break;
03001
03002 case MODE_SET_RESERVE1:
03003
03004 if (asp->status != SNMP_ERR_NOERROR)
03005 asp->mode = MODE_SET_FREE;
03006 else
03007 asp->mode = MODE_SET_RESERVE2;
03008 break;
03009
03010 case MODE_SET_RESERVE2:
03011 if (asp->status != SNMP_ERR_NOERROR)
03012 asp->mode = MODE_SET_FREE;
03013 else
03014 asp->mode = MODE_SET_ACTION;
03015 break;
03016
03017 case MODE_SET_ACTION:
03018 if (asp->status != SNMP_ERR_NOERROR)
03019 asp->mode = MODE_SET_UNDO;
03020 else
03021 asp->mode = MODE_SET_COMMIT;
03022 break;
03023
03024 case MODE_SET_COMMIT:
03025 if (asp->status != SNMP_ERR_NOERROR) {
03026 asp->mode = FINISHED_FAILURE;
03027 } else {
03028 asp->mode = FINISHED_SUCCESS;
03029 }
03030 break;
03031
03032 case MODE_SET_UNDO:
03033 asp->mode = FINISHED_FAILURE;
03034 break;
03035
03036 case MODE_SET_FREE:
03037 asp->mode = FINISHED_FAILURE;
03038 break;
03039 }
03040 }
03041
03042 if (asp->mode != FINISHED_SUCCESS && asp->mode != FINISHED_FAILURE) {
03043 DEBUGMSGTL(("agent_set", "doing set mode = %d (%s)\n", asp->mode,
03044 se_find_label_in_slist("agent_mode", asp->mode)));
03045 status = handle_var_requests(asp);
03046 DEBUGMSGTL(("agent_set", "did set mode = %d, status = %d\n",
03047 asp->mode, status));
03048 if ((status != SNMP_ERR_NOERROR && asp->status == SNMP_ERR_NOERROR) ||
03049 status == SNMP_ERR_COMMITFAILED ||
03050 status == SNMP_ERR_UNDOFAILED) {
03051 asp->status = status;
03052 }
03053 }
03054 return asp->status;
03055 }
03056
03057 int
03058 handle_set_loop(netsnmp_agent_session *asp)
03059 {
03060 while (asp->mode != FINISHED_FAILURE && asp->mode != FINISHED_SUCCESS) {
03061 handle_set(asp);
03062 if (netsnmp_check_for_delegated(asp)) {
03063 return SNMP_ERR_NOERROR;
03064 }
03065 if (asp->pdu->flags & UCD_MSG_FLAG_ONE_PASS_ONLY) {
03066 return asp->status;
03067 }
03068 }
03069 return asp->status;
03070 }
03071
03072 int
03073 netsnmp_handle_request(netsnmp_agent_session *asp, int status)
03074 {
03075
03076
03077
03078
03079
03080
03081 if ((0 == netsnmp_check_delegated_chain_for(asp)) &&
03082 (asp != netsnmp_processing_set)) {
03083
03084
03085
03086
03087 if (netsnmp_processing_set) {
03088 netsnmp_add_queued(asp);
03089 DEBUGMSGTL(("snmp_agent",
03090 "request queued while processing set, "
03091 "asp = %08p\n", asp));
03092 return 1;
03093 }
03094
03095
03096
03097
03098 if (asp->pdu->command == SNMP_MSG_SET) {
03099 netsnmp_processing_set = asp;
03100
03101
03102
03103
03104
03105 if (agent_delegated_list) {
03106 DEBUGMSGTL(("snmp_agent", "SET request queued while "
03107 "delegated requests finish, asp = %08p\n",
03108 asp));
03109 netsnmp_add_queued(asp);
03110 return 1;
03111 }
03112 }
03113 }
03114
03115
03116
03117
03118 status = handle_pdu(asp);
03119
03120
03121
03122
03123 DEBUGIF("results") {
03124 netsnmp_variable_list *var_ptr;
03125 DEBUGMSGTL(("results", "request results (status = %d):\n",
03126 status));
03127 for (var_ptr = asp->pdu->variables; var_ptr;
03128 var_ptr = var_ptr->next_variable) {
03129 DEBUGMSGTL(("results", "\t"));
03130 DEBUGMSGVAR(("results", var_ptr));
03131 DEBUGMSG(("results", "\n"));
03132 }
03133 }
03134
03135
03136
03137
03138 if (netsnmp_check_for_delegated_and_add(asp)) {
03139
03140
03141
03142 asp->status = status;
03143 } else {
03144
03145
03146
03147 return netsnmp_wrap_up_request(asp, status);
03148 }
03149
03150 return 1;
03151 }
03152
03204 int
03205 handle_pdu(netsnmp_agent_session *asp)
03206 {
03207 int status, inclusives = 0;
03208 netsnmp_variable_list *v = NULL;
03209
03210
03211
03212
03213 switch (asp->pdu->command) {
03214
03215 case SNMP_MSG_INTERNAL_SET_RESERVE2:
03216 case SNMP_MSG_INTERNAL_SET_ACTION:
03217 case SNMP_MSG_INTERNAL_SET_COMMIT:
03218 case SNMP_MSG_INTERNAL_SET_FREE:
03219 case SNMP_MSG_INTERNAL_SET_UNDO:
03220 status = get_set_cache(asp);
03221 if (status != SNMP_ERR_NOERROR)
03222 return status;
03223 break;
03224
03225 case SNMP_MSG_GET:
03226 case SNMP_MSG_GETNEXT:
03227 case SNMP_MSG_GETBULK:
03228 for (v = asp->pdu->variables; v != NULL; v = v->next_variable) {
03229 if (v->type == ASN_PRIV_INCL_RANGE) {
03230
03231
03232
03233
03234
03235
03236
03237
03238 inclusives++;
03239 } else {
03240 snmp_set_var_typed_value(v, ASN_NULL, NULL, 0);
03241 }
03242 }
03243
03244
03245
03246
03247 case SNMP_MSG_INTERNAL_SET_BEGIN:
03248 case SNMP_MSG_INTERNAL_SET_RESERVE1:
03249 default:
03250 asp->vbcount = count_varbinds(asp->pdu->variables);
03251 if (asp->vbcount)
03252 asp->requests = (netsnmp_request_info *)
03253 calloc(asp->vbcount, sizeof(netsnmp_request_info));
03254
03255
03256
03257 status = netsnmp_create_subtree_cache(asp);
03258 if (status != SNMP_ERR_NOERROR)
03259 return status;
03260 }
03261
03262 asp->mode = asp->pdu->command;
03263 switch (asp->mode) {
03264 case SNMP_MSG_GET:
03265
03266
03267
03268 snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
03269
03270
03271
03272
03273 check_acm(asp, SNMP_NOSUCHOBJECT);
03274
03275
03276
03277
03278 status = handle_var_requests(asp);
03279
03280
03281
03282
03283
03284
03285
03286 if (status == SNMP_ERR_NOERROR)
03287 snmp_replace_var_types(asp->pdu->variables, ASN_NULL,
03288 SNMP_NOSUCHINSTANCE);
03289 break;
03290
03291 case SNMP_MSG_GETNEXT:
03292 snmp_increment_statistic(STAT_SNMPINGETNEXTS);
03293
03294
03295
03296
03297 case SNMP_MSG_GETBULK:
03298
03299
03300
03301
03302
03303 if (inclusives) {
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314 DEBUGMSGTL(("snmp_agent", "inclusive range(s) in getNext\n"));
03315 asp->oldmode = asp->mode;
03316 asp->mode = SNMP_MSG_GET;
03317 }
03318
03319
03320
03321
03322 status = handle_var_requests(asp);
03323 if (status != SNMP_ERR_NOERROR) {
03324 if (!inclusives)
03325 return status;
03326 else
03327 asp->status = SNMP_ERR_NOERROR;
03328 }
03329
03330
03331
03332
03333
03334
03335 status = handle_getnext_loop(asp);
03336 break;
03337
03338 case SNMP_MSG_SET:
03339 #ifdef NETSNMP_DISABLE_SET_SUPPORT
03340 return SNMP_ERR_NOTWRITABLE;
03341 #else
03342
03343
03344
03345 if (check_acm(asp, SNMP_NOSUCHOBJECT))
03346 return SNMP_ERR_NOTWRITABLE;
03347
03348 asp->mode = MODE_SET_BEGIN;
03349 status = handle_set_loop(asp);
03350 #endif
03351 break;
03352
03353 case SNMP_MSG_INTERNAL_SET_BEGIN:
03354 case SNMP_MSG_INTERNAL_SET_RESERVE1:
03355 case SNMP_MSG_INTERNAL_SET_RESERVE2:
03356 case SNMP_MSG_INTERNAL_SET_ACTION:
03357 case SNMP_MSG_INTERNAL_SET_COMMIT:
03358 case SNMP_MSG_INTERNAL_SET_FREE:
03359 case SNMP_MSG_INTERNAL_SET_UNDO:
03360 asp->pdu->flags |= UCD_MSG_FLAG_ONE_PASS_ONLY;
03361 status = handle_set_loop(asp);
03362
03363
03364
03365 break;
03366
03367 case SNMP_MSG_RESPONSE:
03368 snmp_increment_statistic(STAT_SNMPINGETRESPONSES);
03369 return SNMP_ERR_NOERROR;
03370
03371 case SNMP_MSG_TRAP:
03372 case SNMP_MSG_TRAP2:
03373 snmp_increment_statistic(STAT_SNMPINTRAPS);
03374 return SNMP_ERR_NOERROR;
03375
03376 default:
03377
03378
03379
03380 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
03381 return SNMPERR_GENERR;
03382
03383
03384
03385 }
03386 return status;
03387 }
03388
03392 NETSNMP_STATIC_INLINE int
03393 _request_set_error(netsnmp_request_info *request, int mode, int error_value)
03394 {
03395 if (!request)
03396 return SNMPERR_NO_VARS;
03397
03398 request->processed = 1;
03399 request->delegated = REQUEST_IS_NOT_DELEGATED;
03400
03401 switch (error_value) {
03402 case SNMP_NOSUCHOBJECT:
03403 case SNMP_NOSUCHINSTANCE:
03404 case SNMP_ENDOFMIBVIEW:
03405
03406
03407
03408
03409
03410 switch (mode) {
03411 case MODE_GET:
03412 case MODE_GETNEXT:
03413 case MODE_GETBULK:
03414 request->requestvb->type = error_value;
03415 return SNMPERR_SUCCESS;
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428 default:
03429 request->status = SNMP_ERR_NOSUCHNAME;
03430 return SNMPERR_SUCCESS;
03431 }
03432 break;
03433
03434 default:
03435 if (error_value < 0) {
03436
03437
03438
03439
03440
03441
03442 snmp_log(LOG_ERR, "Illegal error_value %d translated to %d\n",
03443 error_value, SNMP_ERR_GENERR);
03444 request->status = SNMP_ERR_GENERR;
03445 } else {
03446
03447
03448
03449 request->status = error_value;
03450 }
03451 return SNMPERR_SUCCESS;
03452 }
03453 return SNMPERR_SUCCESS;
03454 }
03455
03460 int
03461 netsnmp_request_set_error(netsnmp_request_info *request, int error_value)
03462 {
03463 if (!request || !request->agent_req_info)
03464 return SNMPERR_NO_VARS;
03465
03466 return _request_set_error(request, request->agent_req_info->mode,
03467 error_value);
03468 }
03469
03475 int
03476 netsnmp_request_set_error_idx(netsnmp_request_info *request,
03477 int error_value, int idx)
03478 {
03479 int i;
03480 netsnmp_request_info *req = request;
03481
03482 if (!request || !request->agent_req_info)
03483 return SNMPERR_NO_VARS;
03484
03485
03486
03487
03488 for ( i=2; i<idx; i++) {
03489 req = req->next;
03490 if (!req)
03491 return SNMPERR_NO_VARS;
03492 }
03493
03494 return _request_set_error(req, request->agent_req_info->mode,
03495 error_value);
03496 }
03497
03503 NETSNMP_INLINE int
03504 netsnmp_request_set_error_all( netsnmp_request_info *requests, int error)
03505 {
03506 int mode, rc, result = SNMPERR_SUCCESS;
03507
03508 if((NULL == requests) || (NULL == requests->agent_req_info))
03509 return SNMPERR_NO_VARS;
03510
03511 mode = requests->agent_req_info->mode;
03512
03513 for(; requests ; requests = requests->next) {
03514
03516 netsnmp_assert(NULL != requests->agent_req_info);
03517 netsnmp_assert(mode == requests->agent_req_info->mode);
03518
03519
03520
03521
03522
03523 if((rc = _request_set_error(requests, mode, error))) {
03524 snmp_log(LOG_WARNING,"got %d while setting request error\n", rc);
03525 result = rc;
03526 }
03527 }
03528 return result;
03529 }
03530
03531 extern struct timeval starttime;
03532
03533
03534
03535
03536 u_long
03537 netsnmp_marker_uptime(marker_t pm)
03538 {
03539 u_long res;
03540 marker_t start = (marker_t) & starttime;
03541
03542 res = uatime_hdiff(start, pm);
03543 return res;
03544 }
03545
03546
03547
03548
03549 u_long
03550 netsnmp_timeval_uptime(struct timeval * tv)
03551 {
03552 return netsnmp_marker_uptime((marker_t) tv);
03553 }
03554
03555
03556
03557
03558 u_long
03559 netsnmp_get_agent_uptime(void)
03560 {
03561 struct timeval now;
03562 gettimeofday(&now, NULL);
03563
03564 return netsnmp_timeval_uptime(&now);
03565 }
03566
03567
03568
03569 NETSNMP_INLINE void
03570 netsnmp_agent_add_list_data(netsnmp_agent_request_info *ari,
03571 netsnmp_data_list *node)
03572 {
03573 if (ari) {
03574 if (ari->agent_data) {
03575 netsnmp_add_list_data(&ari->agent_data, node);
03576 } else {
03577 ari->agent_data = node;
03578 }
03579 }
03580 }
03581
03582 NETSNMP_INLINE int
03583 netsnmp_agent_remove_list_data(netsnmp_agent_request_info *ari,
03584 const char * name)
03585 {
03586 if ((NULL == ari) || (NULL == ari->agent_data))
03587 return 1;
03588
03589 return netsnmp_remove_list_node(&ari->agent_data, name);
03590 }
03591
03592 NETSNMP_INLINE void *
03593 netsnmp_agent_get_list_data(netsnmp_agent_request_info *ari,
03594 const char *name)
03595 {
03596 if (ari) {
03597 return netsnmp_get_list_data(ari->agent_data, name);
03598 }
03599 return NULL;
03600 }
03601
03602 NETSNMP_INLINE void
03603 netsnmp_free_agent_data_set(netsnmp_agent_request_info *ari)
03604 {
03605 if (ari) {
03606 netsnmp_free_list_data(ari->agent_data);
03607 }
03608 }
03609
03610 NETSNMP_INLINE void
03611 netsnmp_free_agent_data_sets(netsnmp_agent_request_info *ari)
03612 {
03613 if (ari) {
03614 netsnmp_free_all_list_data(ari->agent_data);
03615 }
03616 }
03617
03618 NETSNMP_INLINE void
03619 netsnmp_free_agent_request_info(netsnmp_agent_request_info *ari)
03620 {
03621 if (ari) {
03622 if (ari->agent_data) {
03623 netsnmp_free_all_list_data(ari->agent_data);
03624 }
03625 SNMP_FREE(ari);
03626 }
03627 }
03628
03629
03630
03631
03632
03633
03634
03642 int
03643 netsnmp_set_request_error(netsnmp_agent_request_info *reqinfo,
03644 netsnmp_request_info *request, int error_value)
03645 {
03646 if (!request || !reqinfo)
03647 return error_value;
03648
03649 _request_set_error(request, reqinfo->mode, error_value);
03650
03651 return error_value;
03652 }
03653
03661 int
03662 netsnmp_set_mode_request_error(int mode, netsnmp_request_info *request,
03663 int error_value)
03664 {
03665 _request_set_error(request, mode, error_value);
03666
03667 return error_value;
03668 }
03669
03677 int
03678 netsnmp_set_all_requests_error(netsnmp_agent_request_info *reqinfo,
03679 netsnmp_request_info *requests,
03680 int error_value)
03681 {
03682 netsnmp_request_set_error_all(requests, error_value);
03683 return error_value;
03684 }