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 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[] = { 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 static 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;
00412 int all_eoMib;
00413 netsnmp_variable_list *prev = NULL;
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
00433
00434
00435
00436
00437 for (i = 0; i < r - 1; i++) {
00438 prev = NULL;
00439 for (j = 0; j < repeats; j++) {
00440
00441
00442
00443
00444
00445 if (asp->bulkcache[i * repeats + j]->name_length == 0
00446 && prev) {
00447 snmp_set_var_objid(
00448 asp->bulkcache[i * repeats + j],
00449 prev->name, prev->name_length);
00450 snmp_set_var_typed_value(
00451 asp->bulkcache[i * repeats + j],
00452 SNMP_ENDOFMIBVIEW, NULL, 0);
00453 }
00454 prev = asp->bulkcache[i * repeats + j];
00455
00456 asp->bulkcache[i * repeats + j]->next_variable =
00457 asp->bulkcache[(i + 1) * repeats + j];
00458 }
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468 if (r > 0) {
00469 prev = NULL;
00470 for (j = 0; j < repeats - 1; j++) {
00471
00472
00473
00474 if (asp->bulkcache[(r - 1) * repeats + j]->name_length == 0
00475 && prev) {
00476 snmp_set_var_objid(
00477 asp->bulkcache[(r - 1) * repeats + j],
00478 prev->name, prev->name_length);
00479 snmp_set_var_typed_value(
00480 asp->bulkcache[(r - 1) * repeats + j],
00481 SNMP_ENDOFMIBVIEW, NULL, 0);
00482 }
00483 prev = asp->bulkcache[(r - 1) * repeats + j];
00484 asp->bulkcache[(r - 1) * repeats + j]->next_variable =
00485 asp->bulkcache[j + 1];
00486 }
00487
00488
00489
00490 if (asp->bulkcache[r * repeats - 1]->name_length == 0
00491 && prev) {
00492 snmp_set_var_objid(
00493 asp->bulkcache[r * repeats - 1],
00494 prev->name, prev->name_length);
00495 snmp_set_var_typed_value(
00496 asp->bulkcache[r * repeats - 1],
00497 SNMP_ENDOFMIBVIEW, NULL, 0);
00498 }
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 all_eoMib = 0;
00514 for (i = 0; i < repeats; i++) {
00515 if (asp->bulkcache[i]->type == SNMP_ENDOFMIBVIEW) {
00516 all_eoMib = 1;
00517 for (j = 1, prev=asp->bulkcache[i];
00518 j < r;
00519 j++, prev=prev->next_variable) {
00520 if (prev->type != SNMP_ENDOFMIBVIEW) {
00521 all_eoMib = 0;
00522 break;
00523 }
00524 }
00525 if (all_eoMib) {
00526
00527
00528
00529
00530 snmp_free_varbind( prev->next_variable );
00531 prev->next_variable = NULL;
00532 break;
00533 }
00534 }
00535 }
00536 }
00537
00538
00539 int
00540 getNextSessID()
00541 {
00542 static int SessionID = 0;
00543
00544 return ++SessionID;
00545 }
00546
00559 int
00560 agent_check_and_process(int block)
00561 {
00562 int numfds;
00563 fd_set fdset;
00564 struct timeval timeout = { LONG_MAX, 0 }, *tvp = &timeout;
00565 int count;
00566 int fakeblock = 0;
00567
00568 numfds = 0;
00569 FD_ZERO(&fdset);
00570 snmp_select_info(&numfds, &fdset, tvp, &fakeblock);
00571 if (block != 0 && fakeblock != 0) {
00572
00573
00574
00575
00576
00577 tvp = NULL;
00578 } else if (block != 0 && fakeblock == 0) {
00579
00580
00581
00582
00583
00584
00585 } else if (block == 0) {
00586
00587
00588
00589
00590 tvp->tv_sec = 0;
00591 tvp->tv_usec = 0;
00592 }
00593
00594 count = select(numfds, &fdset, 0, 0, tvp);
00595
00596 if (count > 0) {
00597
00598
00599
00600 snmp_read(&fdset);
00601 } else
00602 switch (count) {
00603 case 0:
00604 snmp_timeout();
00605 break;
00606 case -1:
00607 if (errno != EINTR) {
00608 snmp_log_perror("select");
00609 }
00610 return -1;
00611 default:
00612 snmp_log(LOG_ERR, "select returned %d\n", count);
00613 return -1;
00614 }
00615
00616
00617
00618
00619 run_alarms();
00620
00621 netsnmp_check_outstanding_agent_requests();
00622
00623 return count;
00624 }
00625
00626
00627
00628
00629
00630 void
00631 netsnmp_addrcache_initialise(void)
00632 {
00633 int i = 0;
00634
00635 for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00636 addrCache[i].addr = NULL;
00637 addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
00638 }
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 int
00657 netsnmp_addrcache_add(const char *addr)
00658 {
00659 int oldest = -1;
00660 int unused = -1;
00661 int i;
00662 int rc = -1;
00663 struct timeval now;
00664 struct timeval aged;
00665
00666
00667
00668
00669 gettimeofday(&now, (struct timezone*) NULL);
00670 aged.tv_sec = now.tv_sec - SNMP_ADDRCACHE_MAXAGE;
00671 aged.tv_usec = now.tv_usec;
00672
00673
00674
00675
00676 for(i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00677 if (addrCache[i].status == SNMP_ADDRCACHE_UNUSED) {
00678
00679
00680
00681 if (unused < 0)
00682 unused = i;
00683 }
00684 else {
00685 if ((NULL != addr) && (strcmp(addrCache[i].addr, addr) == 0)) {
00686
00687
00688
00689 memcpy(&addrCache[i].lastHit, &now, sizeof(struct timeval));
00690 if (timercmp(&addrCache[i].lastHit, &aged, <))
00691 rc = 1;
00692 else
00693 rc = 0;
00694 break;
00695 }
00696 else {
00697
00698
00699
00700 if (timercmp(&addrCache[i].lastHit, &aged, <)) {
00701
00702
00703
00704 SNMP_FREE(addrCache[i].addr);
00705 addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
00706
00707
00708
00709 if (unused < 0)
00710 unused = i;
00711 }
00712 else {
00713
00714
00715
00716 if (oldest < 0)
00717 oldest = i;
00718 else if (timercmp(&addrCache[i].lastHit,
00719 &addrCache[oldest].lastHit, <))
00720 oldest = i;
00721 }
00722 }
00723 }
00724 }
00725
00726 if ((-1 == rc) && (NULL != addr)) {
00727
00728
00729
00730 if (unused >= 0) {
00731
00732
00733
00734 addrCache[unused].addr = strdup(addr);
00735 addrCache[unused].status = SNMP_ADDRCACHE_USED;
00736 memcpy(&addrCache[unused].lastHit, &now, sizeof(struct timeval));
00737 }
00738 else {
00739 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00740 NETSNMP_DS_AGENT_VERBOSE))
00741 snmp_log(LOG_INFO, "Purging address from address cache: %s",
00742 addrCache[oldest].addr);
00743
00744 free(addrCache[oldest].addr);
00745 addrCache[oldest].addr = strdup(addr);
00746 memcpy(&addrCache[oldest].lastHit, &now, sizeof(struct timeval));
00747 }
00748 rc = 1;
00749 }
00750 if ((log_addresses && (1 == rc)) ||
00751 netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00752 NETSNMP_DS_AGENT_VERBOSE)) {
00753 snmp_log(LOG_INFO, "Received SNMP packet(s) from %s\n", addr);
00754 }
00755
00756 return rc;
00757 }
00758
00759
00760
00761
00762
00763
00764 void
00765 netsnmp_addrcache_age(void)
00766 {
00767 (void)netsnmp_addrcache_add(NULL);
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 int
00787 netsnmp_agent_check_packet(netsnmp_session * session,
00788 netsnmp_transport *transport,
00789 void *transport_data, int transport_data_length)
00790 {
00791 char *addr_string = NULL;
00792 #ifdef USE_LIBWRAP
00793 char *tcpudpaddr, *name;
00794
00795 name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
00796 NETSNMP_DS_LIB_APPTYPE);
00797 #endif
00798
00799
00800
00801
00802
00803
00804 if (transport != NULL && transport->f_fmtaddr != NULL) {
00805
00806
00807
00808 addr_string = transport->f_fmtaddr(transport, transport_data,
00809 transport_data_length);
00810
00811
00812
00813 }
00814 #ifdef USE_LIBWRAP
00815
00816 tcpudpaddr = strstr(addr_string, "[");
00817 if ( tcpudpaddr != 0 ) {
00818 char sbuf[64];
00819 char *xp;
00820 strncpy(sbuf, tcpudpaddr + 1, sizeof(sbuf));
00821 sbuf[sizeof(sbuf)-1] = '\0';
00822 xp = strstr(sbuf, "]");
00823 if (xp)
00824 *xp = '\0';
00825
00826 if (hosts_ctl(name, STRING_UNKNOWN, sbuf, STRING_UNKNOWN)) {
00827 snmp_log(allow_severity, "Connection from %s\n", addr_string);
00828 } else {
00829 snmp_log(deny_severity, "Connection from %s REFUSED\n",
00830 addr_string);
00831 SNMP_FREE(addr_string);
00832 return 0;
00833 }
00834 } else {
00835
00836
00837
00838
00839 if (0 == strncmp(addr_string, "callback", 8))
00840 ;
00841 else if (hosts_ctl(name, STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN)){
00842 snmp_log(allow_severity, "Connection from <UNKNOWN> (%s)\n", addr_string);
00843 addr_string = strdup("<UNKNOWN>");
00844 } else {
00845 snmp_log(deny_severity, "Connection from <UNKNOWN> (%s) REFUSED\n", addr_string);
00846 return 0;
00847 }
00848 }
00849 #endif
00850
00851 snmp_increment_statistic(STAT_SNMPINPKTS);
00852
00853 if (addr_string != NULL) {
00854 netsnmp_addrcache_add(addr_string);
00855 SNMP_FREE(addr_string);
00856 }
00857 return 1;
00858 }
00859
00860
00861 int
00862 netsnmp_agent_check_parse(netsnmp_session * session, netsnmp_pdu *pdu,
00863 int result)
00864 {
00865 if (result == 0) {
00866 if (snmp_get_do_logging() &&
00867 netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
00868 NETSNMP_DS_AGENT_VERBOSE)) {
00869 netsnmp_variable_list *var_ptr;
00870
00871 switch (pdu->command) {
00872 case SNMP_MSG_GET:
00873 snmp_log(LOG_DEBUG, " GET message\n");
00874 break;
00875 case SNMP_MSG_GETNEXT:
00876 snmp_log(LOG_DEBUG, " GETNEXT message\n");
00877 break;
00878 case SNMP_MSG_RESPONSE:
00879 snmp_log(LOG_DEBUG, " RESPONSE message\n");
00880 break;
00881 case SNMP_MSG_SET:
00882 snmp_log(LOG_DEBUG, " SET message\n");
00883 break;
00884 case SNMP_MSG_TRAP:
00885 snmp_log(LOG_DEBUG, " TRAP message\n");
00886 break;
00887 case SNMP_MSG_GETBULK:
00888 snmp_log(LOG_DEBUG, " GETBULK message, non-rep=%ld, max_rep=%ld\n",
00889 pdu->errstat, pdu->errindex);
00890 break;
00891 case SNMP_MSG_INFORM:
00892 snmp_log(LOG_DEBUG, " INFORM message\n");
00893 break;
00894 case SNMP_MSG_TRAP2:
00895 snmp_log(LOG_DEBUG, " TRAP2 message\n");
00896 break;
00897 case SNMP_MSG_REPORT:
00898 snmp_log(LOG_DEBUG, " REPORT message\n");
00899 break;
00900
00901 case SNMP_MSG_INTERNAL_SET_RESERVE1:
00902 snmp_log(LOG_DEBUG, " INTERNAL RESERVE1 message\n");
00903 break;
00904
00905 case SNMP_MSG_INTERNAL_SET_RESERVE2:
00906 snmp_log(LOG_DEBUG, " INTERNAL RESERVE2 message\n");
00907 break;
00908
00909 case SNMP_MSG_INTERNAL_SET_ACTION:
00910 snmp_log(LOG_DEBUG, " INTERNAL ACTION message\n");
00911 break;
00912
00913 case SNMP_MSG_INTERNAL_SET_COMMIT:
00914 snmp_log(LOG_DEBUG, " INTERNAL COMMIT message\n");
00915 break;
00916
00917 case SNMP_MSG_INTERNAL_SET_FREE:
00918 snmp_log(LOG_DEBUG, " INTERNAL FREE message\n");
00919 break;
00920
00921 case SNMP_MSG_INTERNAL_SET_UNDO:
00922 snmp_log(LOG_DEBUG, " INTERNAL UNDO message\n");
00923 break;
00924
00925 default:
00926 snmp_log(LOG_DEBUG, " UNKNOWN message, type=%02X\n",
00927 pdu->command);
00928 snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
00929 return 0;
00930 }
00931
00932 for (var_ptr = pdu->variables; var_ptr != NULL;
00933 var_ptr = var_ptr->next_variable) {
00934 size_t c_oidlen = 256, c_outlen = 0;
00935 u_char *c_oid = (u_char *) malloc(c_oidlen);
00936
00937 if (c_oid) {
00938 if (!sprint_realloc_objid
00939 (&c_oid, &c_oidlen, &c_outlen, 1, var_ptr->name,
00940 var_ptr->name_length)) {
00941 snmp_log(LOG_DEBUG, " -- %s [TRUNCATED]\n",
00942 c_oid);
00943 } else {
00944 snmp_log(LOG_DEBUG, " -- %s\n", c_oid);
00945 }
00946 SNMP_FREE(c_oid);
00947 }
00948 }
00949 }
00950 return 1;
00951 }
00952 return 0;
00953
00954
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 netsnmp_session *main_session = NULL;
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 int
00979 netsnmp_register_agent_nsap(netsnmp_transport *t)
00980 {
00981 netsnmp_session *s, *sp = NULL;
00982 agent_nsap *a = NULL, *n = NULL, **prevNext = &agent_nsap_list;
00983 int handle = 0;
00984 void *isp = NULL;
00985
00986 if (t == NULL) {
00987 return -1;
00988 }
00989
00990 DEBUGMSGTL(("netsnmp_register_agent_nsap", "fd %d\n", t->sock));
00991
00992 n = (agent_nsap *) malloc(sizeof(agent_nsap));
00993 if (n == NULL) {
00994 return -1;
00995 }
00996 s = (netsnmp_session *) malloc(sizeof(netsnmp_session));
00997 if (s == NULL) {
00998 SNMP_FREE(n);
00999 return -1;
01000 }
01001 memset(s, 0, sizeof(netsnmp_session));
01002 snmp_sess_init(s);
01003
01004
01005
01006
01007
01008 s->version = SNMP_DEFAULT_VERSION;
01009 s->callback = handle_snmp_packet;
01010 s->authenticator = NULL;
01011 s->flags = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
01012 NETSNMP_DS_AGENT_FLAGS);
01013 s->isAuthoritative = SNMP_SESS_AUTHORITATIVE;
01014
01015 sp = snmp_add(s, t, netsnmp_agent_check_packet,
01016 netsnmp_agent_check_parse);
01017 if (sp == NULL) {
01018 SNMP_FREE(s);
01019 SNMP_FREE(n);
01020 return -1;
01021 }
01022
01023 isp = snmp_sess_pointer(sp);
01024 if (isp == NULL) {
01025 SNMP_FREE(s);
01026 SNMP_FREE(n);
01027 return -1;
01028 }
01029
01030 n->s = isp;
01031 n->t = t;
01032
01033 if (main_session == NULL) {
01034 main_session = snmp_sess_session(isp);
01035 }
01036
01037 for (a = agent_nsap_list; a != NULL && handle + 1 >= a->handle;
01038 a = a->next) {
01039 handle = a->handle;
01040 prevNext = &(a->next);
01041 }
01042
01043 if (handle < INT_MAX) {
01044 n->handle = handle + 1;
01045 n->next = a;
01046 *prevNext = n;
01047 SNMP_FREE(s);
01048 return n->handle;
01049 } else {
01050 SNMP_FREE(s);
01051 SNMP_FREE(n);
01052 return -1;
01053 }
01054 }
01055
01056 void
01057 netsnmp_deregister_agent_nsap(int handle)
01058 {
01059 agent_nsap *a = NULL, **prevNext = &agent_nsap_list;
01060 int main_session_deregistered = 0;
01061
01062 DEBUGMSGTL(("netsnmp_deregister_agent_nsap", "handle %d\n", handle));
01063
01064 for (a = agent_nsap_list; a != NULL && a->handle < handle; a = a->next) {
01065 prevNext = &(a->next);
01066 }
01067
01068 if (a != NULL && a->handle == handle) {
01069 *prevNext = a->next;
01070 if (main_session == snmp_sess_session(a->s)) {
01071 main_session_deregistered = 1;
01072 }
01073 snmp_close(snmp_sess_session(a->s));
01074
01075
01076
01077 SNMP_FREE(a);
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 if (main_session_deregistered) {
01089 if (agent_nsap_list != NULL) {
01090 DEBUGMSGTL(("snmp_agent",
01091 "WARNING: main_session ptr changed from %p to %p\n",
01092 main_session, snmp_sess_session(agent_nsap_list->s)));
01093 main_session = snmp_sess_session(agent_nsap_list->s);
01094 } else {
01095 DEBUGMSGTL(("snmp_agent",
01096 "WARNING: main_session ptr changed from %p to NULL\n",
01097 main_session));
01098 main_session = NULL;
01099 }
01100 }
01101 }
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 int
01129 init_master_agent(void)
01130 {
01131 netsnmp_transport *transport;
01132 char *cptr;
01133 char buf[SPRINT_MAX_LEN];
01134 char *st;
01135
01136
01137 netsnmp_set_lookup_cache_size(-1);
01138
01139 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
01140 NETSNMP_DS_AGENT_ROLE) != MASTER_AGENT) {
01141 DEBUGMSGTL(("snmp_agent",
01142 "init_master_agent; not master agent\n"));
01143
01144 netsnmp_assert("agent role !master && !sub_agent");
01145
01146 return 0;
01147 }
01148 #ifdef USING_AGENTX_MASTER_MODULE
01149 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
01150 NETSNMP_DS_AGENT_AGENTX_MASTER) == 1)
01151 real_init_master();
01152 #endif
01153 #ifdef USING_SMUX_MODULE
01154 if(should_init("smux"))
01155 real_init_smux();
01156 #endif
01157
01158
01159
01160
01161 cptr = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
01162 NETSNMP_DS_AGENT_PORTS);
01163
01164 if (cptr) {
01165 snprintf(buf, sizeof(buf), "%s", cptr);
01166 buf[ sizeof(buf)-1 ] = 0;
01167 } else {
01168
01169
01170
01171 if (netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_FLAGS) & SNMP_FLAGS_STREAM_SOCKET) {
01172 sprintf(buf, "tcp:%d", SNMP_PORT);
01173 } else {
01174 sprintf(buf, "udp:%d", SNMP_PORT);
01175 }
01176 }
01177
01178 DEBUGMSGTL(("snmp_agent", "final port spec: %s\n", buf));
01179 cptr = strtok_r(buf, ",", &st);
01180 while (cptr) {
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 DEBUGMSGTL(("snmp_agent", "installing master agent on port %s\n",
01194 cptr));
01195
01196 if (!cptr || !(*cptr)) {
01197 snmp_log(LOG_ERR, "improper port specification\n");
01198 return 1;
01199 }
01200
01201 if (strncasecmp(cptr, "none", 4) == 0) {
01202 DEBUGMSGTL(("snmp_agent",
01203 "init_master_agent; pseudo-transport \"none\" requested\n"));
01204 return 0;
01205 }
01206 transport = netsnmp_tdomain_transport(cptr, 1, "udp");
01207
01208 if (transport == NULL) {
01209 snmp_log(LOG_ERR, "Error opening specified endpoint \"%s\"\n",
01210 cptr);
01211 return 1;
01212 }
01213
01214 if (netsnmp_register_agent_nsap(transport) == 0) {
01215 snmp_log(LOG_ERR,
01216 "Error registering specified transport \"%s\" as an agent NSAP\n",
01217 cptr);
01218 return 1;
01219 } else {
01220 DEBUGMSGTL(("snmp_agent",
01221 "init_master_agent; \"%s\" registered as an agent NSAP\n",
01222 cptr));
01223 }
01224
01225
01226
01227
01228 cptr = strtok_r(NULL, ",", &st);
01229 }
01230
01231 return 0;
01232 }
01233
01234 void
01235 clear_nsap_list(void)
01236 {
01237 DEBUGMSGTL(("clear_nsap_list", "clear the nsap list\n"));
01238
01239 while (agent_nsap_list != NULL)
01240 netsnmp_deregister_agent_nsap(agent_nsap_list->handle);
01241 }
01242
01243 void
01244 shutdown_master_agent(void)
01245 {
01246 clear_nsap_list();
01247 }
01248
01249
01250 netsnmp_agent_session *
01251 init_agent_snmp_session(netsnmp_session * session, netsnmp_pdu *pdu)
01252 {
01253 netsnmp_agent_session *asp = (netsnmp_agent_session *)
01254 calloc(1, sizeof(netsnmp_agent_session));
01255
01256 if (asp == NULL) {
01257 return NULL;
01258 }
01259
01260 DEBUGMSGTL(("snmp_agent","agent_sesion %08p created\n", asp));
01261 asp->session = session;
01262 asp->pdu = snmp_clone_pdu(pdu);
01263 asp->orig_pdu = snmp_clone_pdu(pdu);
01264 asp->rw = READ;
01265 asp->exact = TRUE;
01266 asp->next = NULL;
01267 asp->mode = RESERVE1;
01268 asp->status = SNMP_ERR_NOERROR;
01269 asp->index = 0;
01270 asp->oldmode = 0;
01271 asp->treecache_num = -1;
01272 asp->treecache_len = 0;
01273 asp->reqinfo = SNMP_MALLOC_TYPEDEF(netsnmp_agent_request_info);
01274 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p created\n",
01275 asp, asp->reqinfo));
01276
01277 return asp;
01278 }
01279
01280 void
01281 free_agent_snmp_session(netsnmp_agent_session *asp)
01282 {
01283 if (!asp)
01284 return;
01285
01286 DEBUGMSGTL(("snmp_agent","agent_session %08p released\n", asp));
01287
01288 netsnmp_remove_from_delegated(asp);
01289
01290 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p freed\n",
01291 asp, asp->reqinfo));
01292 if (asp->orig_pdu)
01293 snmp_free_pdu(asp->orig_pdu);
01294 if (asp->pdu)
01295 snmp_free_pdu(asp->pdu);
01296 if (asp->reqinfo)
01297 netsnmp_free_agent_request_info(asp->reqinfo);
01298 if (asp->treecache) {
01299 SNMP_FREE(asp->treecache);
01300 }
01301 if (asp->bulkcache) {
01302 SNMP_FREE(asp->bulkcache);
01303 }
01304 if (asp->requests) {
01305 int i;
01306 for (i = 0; i < asp->vbcount; i++) {
01307 netsnmp_free_request_data_sets(&asp->requests[i]);
01308 }
01309 SNMP_FREE(asp->requests);
01310 }
01311 if (asp->cache_store) {
01312 netsnmp_free_cachemap(asp->cache_store);
01313 asp->cache_store = NULL;
01314 }
01315 SNMP_FREE(asp);
01316 }
01317
01318 int
01319 netsnmp_check_for_delegated(netsnmp_agent_session *asp)
01320 {
01321 int i;
01322 netsnmp_request_info *request;
01323
01324 if (NULL == asp->treecache)
01325 return 0;
01326
01327 for (i = 0; i <= asp->treecache_num; i++) {
01328 for (request = asp->treecache[i].requests_begin; request;
01329 request = request->next) {
01330 if (request->delegated)
01331 return 1;
01332 }
01333 }
01334 return 0;
01335 }
01336
01337 int
01338 netsnmp_check_delegated_chain_for(netsnmp_agent_session *asp)
01339 {
01340 netsnmp_agent_session *asptmp;
01341 for (asptmp = agent_delegated_list; asptmp; asptmp = asptmp->next) {
01342 if (asptmp == asp)
01343 return 1;
01344 }
01345 return 0;
01346 }
01347
01348 int
01349 netsnmp_check_for_delegated_and_add(netsnmp_agent_session *asp)
01350 {
01351 if (netsnmp_check_for_delegated(asp)) {
01352 if (!netsnmp_check_delegated_chain_for(asp)) {
01353
01354
01355
01356 asp->next = agent_delegated_list;
01357 agent_delegated_list = asp;
01358 DEBUGMSGTL(("snmp_agent", "delegate session == %08p\n", asp));
01359 }
01360 return 1;
01361 }
01362 return 0;
01363 }
01364
01365 int
01366 netsnmp_remove_from_delegated(netsnmp_agent_session *asp)
01367 {
01368 netsnmp_agent_session *curr, *prev = NULL;
01369
01370 for (curr = agent_delegated_list; curr; prev = curr, curr = curr->next) {
01371
01372
01373
01374 if (curr != asp)
01375 continue;
01376
01377
01378
01379
01380 if (prev != NULL)
01381 prev->next = asp->next;
01382 else
01383 agent_delegated_list = asp->next;
01384
01385 DEBUGMSGTL(("snmp_agent", "remove delegated session == %08p\n", asp));
01386
01387 return 1;
01388 }
01389
01390 return 0;
01391 }
01392
01393
01394
01395
01396
01397
01398
01399
01400 int
01401 netsnmp_remove_delegated_requests_for_session(netsnmp_session *sess)
01402 {
01403 netsnmp_agent_session *asp;
01404 int count = 0;
01405
01406 for (asp = agent_delegated_list; asp; asp = asp->next) {
01407
01408
01409
01410 netsnmp_request_info *request;
01411 for(request = asp->requests; request; request = request->next) {
01412
01413
01414
01415 netsnmp_assert(NULL!=request->subtree);
01416 if(request->subtree->session != sess)
01417 continue;
01418
01419
01420
01421
01422 netsnmp_request_set_error(request, SNMP_ERR_GENERR);
01423 ++count;
01424 }
01425 }
01426
01427
01428
01429
01430 if(count) {
01431 DEBUGMSGTL(("snmp_agent", "removed %d delegated request(s) for session "
01432 "%08p\n", count, sess));
01433 netsnmp_check_outstanding_agent_requests();
01434 }
01435
01436 return count;
01437 }
01438
01439 int
01440 netsnmp_check_queued_chain_for(netsnmp_agent_session *asp)
01441 {
01442 netsnmp_agent_session *asptmp;
01443 for (asptmp = netsnmp_agent_queued_list; asptmp; asptmp = asptmp->next) {
01444 if (asptmp == asp)
01445 return 1;
01446 }
01447 return 0;
01448 }
01449
01450 int
01451 netsnmp_add_queued(netsnmp_agent_session *asp)
01452 {
01453 netsnmp_agent_session *asp_tmp;
01454
01455
01456
01457
01458 if (NULL == netsnmp_agent_queued_list) {
01459 netsnmp_agent_queued_list = asp;
01460 return 1;
01461 }
01462
01463
01464
01465
01466
01467 asp_tmp = netsnmp_agent_queued_list;
01468 for (; asp_tmp; asp_tmp = asp_tmp->next) {
01469
01470
01471
01472 if (asp_tmp == asp)
01473 break;
01474
01475
01476
01477
01478 if (NULL == asp_tmp->next)
01479 asp_tmp->next = asp;
01480 }
01481 return 1;
01482 }
01483
01484
01485 int
01486 netsnmp_wrap_up_request(netsnmp_agent_session *asp, int status)
01487 {
01488 netsnmp_variable_list *var_ptr;
01489 int i;
01490
01491
01492
01493
01494
01495 if (asp == netsnmp_processing_set) {
01496 DEBUGMSGTL(("snmp_agent", "SET request complete, asp = %08p\n",
01497 asp));
01498 netsnmp_processing_set = NULL;
01499 }
01500
01501 if (asp->pdu) {
01502
01503
01504
01505
01506 if ( status != 0 && asp->status == 0 )
01507 asp->status = status;
01508
01509 switch (asp->pdu->command) {
01510 case SNMP_MSG_INTERNAL_SET_BEGIN:
01511 case SNMP_MSG_INTERNAL_SET_RESERVE1:
01512 case SNMP_MSG_INTERNAL_SET_RESERVE2:
01513 case SNMP_MSG_INTERNAL_SET_ACTION:
01514
01515
01516
01517 save_set_cache(asp);
01518 break;
01519
01520 case SNMP_MSG_GETBULK:
01521
01522
01523
01524 _reorder_getbulk(asp);
01525 break;
01526 }
01527
01528
01529
01530
01531
01532 #ifndef DISABLE_SNMPV1
01533 if ((asp->pdu->command == SNMP_MSG_SET) &&
01534 (asp->pdu->version == SNMP_VERSION_1)) {
01535 switch (asp->status) {
01536 case SNMP_ERR_WRONGVALUE:
01537 case SNMP_ERR_WRONGENCODING:
01538 case SNMP_ERR_WRONGTYPE:
01539 case SNMP_ERR_WRONGLENGTH:
01540 case SNMP_ERR_INCONSISTENTVALUE:
01541 status = SNMP_ERR_BADVALUE;
01542 asp->status = SNMP_ERR_BADVALUE;
01543 break;
01544 case SNMP_ERR_NOACCESS:
01545 case SNMP_ERR_NOTWRITABLE:
01546 case SNMP_ERR_NOCREATION:
01547 case SNMP_ERR_INCONSISTENTNAME:
01548 case SNMP_ERR_AUTHORIZATIONERROR:
01549 status = SNMP_ERR_NOSUCHNAME;
01550 asp->status = SNMP_ERR_NOSUCHNAME;
01551 break;
01552 case SNMP_ERR_RESOURCEUNAVAILABLE:
01553 case SNMP_ERR_COMMITFAILED:
01554 case SNMP_ERR_UNDOFAILED:
01555 status = SNMP_ERR_GENERR;
01556 asp->status = SNMP_ERR_GENERR;
01557 break;
01558 }
01559 }
01560
01561
01562
01563
01564
01565 if ((asp->pdu->command != SNMP_MSG_SET) &&
01566 (asp->pdu->version == SNMP_VERSION_1)) {
01567 for (var_ptr = asp->pdu->variables, i = 1;
01568 var_ptr != NULL; var_ptr = var_ptr->next_variable, i++) {
01569 switch (var_ptr->type) {
01570 case SNMP_NOSUCHOBJECT:
01571 case SNMP_NOSUCHINSTANCE:
01572 case SNMP_ENDOFMIBVIEW:
01573 case ASN_COUNTER64:
01574 status = SNMP_ERR_NOSUCHNAME;
01575 asp->status = SNMP_ERR_NOSUCHNAME;
01576 asp->index = i;
01577 break;
01578 }
01579 }
01580 }
01581 #endif
01582 }
01584
01585
01586
01587
01588 #define INCLUDE_V2ERRORS_IN_V1STATS
01589
01590 switch (status) {
01591 #ifdef INCLUDE_V2ERRORS_IN_V1STATS
01592 case SNMP_ERR_WRONGVALUE:
01593 case SNMP_ERR_WRONGENCODING:
01594 case SNMP_ERR_WRONGTYPE:
01595 case SNMP_ERR_WRONGLENGTH:
01596 case SNMP_ERR_INCONSISTENTVALUE:
01597 #endif
01598 case SNMP_ERR_BADVALUE:
01599 snmp_increment_statistic(STAT_SNMPOUTBADVALUES);
01600 break;
01601 #ifdef INCLUDE_V2ERRORS_IN_V1STATS
01602 case SNMP_ERR_NOACCESS:
01603 case SNMP_ERR_NOTWRITABLE:
01604 case SNMP_ERR_NOCREATION:
01605 case SNMP_ERR_INCONSISTENTNAME:
01606 case SNMP_ERR_AUTHORIZATIONERROR:
01607 #endif
01608 case SNMP_ERR_NOSUCHNAME:
01609 snmp_increment_statistic(STAT_SNMPOUTNOSUCHNAMES);
01610 break;
01611 #ifdef INCLUDE_V2ERRORS_IN_V1STATS
01612 case SNMP_ERR_RESOURCEUNAVAILABLE:
01613 case SNMP_ERR_COMMITFAILED:
01614 case SNMP_ERR_UNDOFAILED:
01615 #endif
01616 case SNMP_ERR_GENERR:
01617 snmp_increment_statistic(STAT_SNMPOUTGENERRS);
01618 break;
01619
01620 case SNMP_ERR_TOOBIG:
01621 snmp_increment_statistic(STAT_SNMPOUTTOOBIGS);
01622 break;
01623 }
01624
01625 if ((status == SNMP_ERR_NOERROR) && (asp->pdu)) {
01626 snmp_increment_statistic_by((asp->pdu->command == SNMP_MSG_SET ?
01627 STAT_SNMPINTOTALSETVARS :
01628 STAT_SNMPINTOTALREQVARS),
01629 count_varbinds(asp->pdu->variables));
01630 } else {
01631
01632
01633
01634
01635 snmp_free_pdu(asp->pdu);
01636 asp->pdu = asp->orig_pdu;
01637 asp->orig_pdu = NULL;
01638 }
01639 if (asp->pdu) {
01640 asp->pdu->command = SNMP_MSG_RESPONSE;
01641 asp->pdu->errstat = asp->status;
01642 asp->pdu->errindex = asp->index;
01643 if (!snmp_send(asp->session, asp->pdu)) {
01644 netsnmp_variable_list *var_ptr;
01645 snmp_perror("send response");
01646 for (var_ptr = asp->pdu->variables; var_ptr != NULL;
01647 var_ptr = var_ptr->next_variable) {
01648 size_t c_oidlen = 256, c_outlen = 0;
01649 u_char *c_oid = (u_char *) malloc(c_oidlen);
01650
01651 if (c_oid) {
01652 if (!sprint_realloc_objid (&c_oid, &c_oidlen, &c_outlen, 1,
01653 var_ptr->name,
01654 var_ptr->name_length)) {
01655 snmp_log(LOG_ERR, " -- %s [TRUNCATED]\n", c_oid);
01656 } else {
01657 snmp_log(LOG_ERR, " -- %s\n", c_oid);
01658 }
01659 SNMP_FREE(c_oid);
01660 }
01661 }
01662 snmp_free_pdu(asp->pdu);
01663 asp->pdu = NULL;
01664 }
01665 snmp_increment_statistic(STAT_SNMPOUTPKTS);
01666 snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);
01667 asp->pdu = NULL;
01668 netsnmp_remove_and_free_agent_snmp_session(asp);
01669 }
01670 return 1;
01671 }
01672
01673 void
01674 dump_sess_list(void)
01675 {
01676 netsnmp_agent_session *a;
01677
01678 DEBUGMSGTL(("snmp_agent", "DUMP agent_sess_list -> "));
01679 for (a = agent_session_list; a != NULL; a = a->next) {
01680 DEBUGMSG(("snmp_agent", "%08p[session %08p] -> ", a, a->session));
01681 }
01682 DEBUGMSG(("snmp_agent", "[NIL]\n"));
01683 }
01684
01685 void
01686 netsnmp_remove_and_free_agent_snmp_session(netsnmp_agent_session *asp)
01687 {
01688 netsnmp_agent_session *a, **prevNext = &agent_session_list;
01689
01690 DEBUGMSGTL(("snmp_agent", "REMOVE session == %08p\n", asp));
01691
01692 for (a = agent_session_list; a != NULL; a = *prevNext) {
01693 if (a == asp) {
01694 *prevNext = a->next;
01695 a->next = NULL;
01696 free_agent_snmp_session(a);
01697 asp = NULL;
01698 break;
01699 } else {
01700 prevNext = &(a->next);
01701 }
01702 }
01703
01704 if (a == NULL && asp != NULL) {
01705
01706
01707
01708 free_agent_snmp_session(asp);
01709 }
01710 }
01711
01712 void
01713 netsnmp_free_agent_snmp_session_by_session(netsnmp_session * sess,
01714 void (*free_request)
01715 (netsnmp_request_list *))
01716 {
01717 netsnmp_agent_session *a, *next, **prevNext = &agent_session_list;
01718
01719 DEBUGMSGTL(("snmp_agent", "REMOVE session == %08p\n", sess));
01720
01721 for (a = agent_session_list; a != NULL; a = next) {
01722 if (a->session == sess) {
01723 *prevNext = a->next;
01724 next = a->next;
01725 free_agent_snmp_session(a);
01726 } else {
01727 prevNext = &(a->next);
01728 next = a->next;
01729 }
01730 }
01731 }
01732
01734 int
01735 handle_snmp_packet(int op, netsnmp_session * session, int reqid,
01736 netsnmp_pdu *pdu, void *magic)
01737 {
01738 netsnmp_agent_session *asp;
01739 int status, access_ret, rc;
01740
01741
01742
01743
01744 if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
01745 return 1;
01746 }
01747
01748
01749
01750
01751
01752 if (pdu->command == SNMP_MSG_TRAP || pdu->command == SNMP_MSG_INFORM ||
01753 pdu->command == SNMP_MSG_TRAP2) {
01754 DEBUGMSGTL(("snmp_agent", "received trap-like PDU (%02x)\n",
01755 pdu->command));
01756 pdu->command = SNMP_MSG_TRAP2;
01757 snmp_increment_statistic(STAT_SNMPUNKNOWNPDUHANDLERS);
01758 return 1;
01759 }
01760
01761
01762
01763
01764 if (pdu->version == SNMP_VERSION_3 &&
01765 session->s_snmp_errno == SNMPERR_USM_AUTHENTICATIONFAILURE) {
01766 send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
01767 return 1;
01768 }
01769
01770 if (magic == NULL) {
01771 asp = init_agent_snmp_session(session, pdu);
01772 status = SNMP_ERR_NOERROR;
01773 } else {
01774 asp = (netsnmp_agent_session *) magic;
01775 status = asp->status;
01776 }
01777
01778 if ((access_ret = check_access(asp->pdu)) != 0) {
01779 if (access_ret == VACM_NOSUCHCONTEXT) {
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789 snmp_increment_statistic(STAT_SNMPUNKNOWNCONTEXTS);
01790
01791
01792
01793
01794 netsnmp_remove_and_free_agent_snmp_session(asp);
01795 return 0;
01796 } else {
01797
01798
01799
01800 send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
01801 #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
01802 #if defined(DISABLE_SNMPV1)
01803 if (asp->pdu->version != SNMP_VERSION_2c) {
01804 #else
01805 #if defined(DISABLE_SNMPV2C)
01806 if (asp->pdu->version != SNMP_VERSION_1) {
01807 #else
01808 if (asp->pdu->version != SNMP_VERSION_1
01809 && asp->pdu->version != SNMP_VERSION_2c) {
01810 #endif
01811 #endif
01812 asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR;
01813 asp->pdu->command = SNMP_MSG_RESPONSE;
01814 snmp_increment_statistic(STAT_SNMPOUTPKTS);
01815 if (!snmp_send(asp->session, asp->pdu))
01816 snmp_free_pdu(asp->pdu);
01817 asp->pdu = NULL;
01818 netsnmp_remove_and_free_agent_snmp_session(asp);
01819 return 1;
01820 } else {
01821 #endif
01822
01823
01824
01825 netsnmp_remove_and_free_agent_snmp_session(asp);
01826 return 0;
01827 #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
01828 }
01829 #endif
01830 }
01831 }
01832
01833 rc = netsnmp_handle_request(asp, status);
01834
01835
01836
01837
01838 DEBUGMSGTL(("snmp_agent", "end of handle_snmp_packet, asp = %08p\n",
01839 asp));
01840 return rc;
01841 }
01842
01843 netsnmp_request_info *
01844 netsnmp_add_varbind_to_cache(netsnmp_agent_session *asp, int vbcount,
01845 netsnmp_variable_list * varbind_ptr,
01846 netsnmp_subtree *tp)
01847 {
01848 netsnmp_request_info *request = NULL;
01849 int cacheid;
01850
01851 DEBUGMSGTL(("snmp_agent", "add_vb_to_cache(%8p, %d, ", asp, vbcount));
01852 DEBUGMSGOID(("snmp_agent", varbind_ptr->name,
01853 varbind_ptr->name_length));
01854 DEBUGMSG(("snmp_agent", ", %8p)\n", tp));
01855
01856 if (tp &&
01857 (asp->pdu->command == SNMP_MSG_GETNEXT ||
01858 asp->pdu->command == SNMP_MSG_GETBULK)) {
01859 int result;
01860 int prefix_len;
01861
01862 prefix_len = netsnmp_oid_find_prefix(tp->start_a,
01863 tp->start_len,
01864 tp->end_a, tp->end_len);
01865 result =
01866 netsnmp_acm_check_subtree(asp->pdu, tp->start_a, prefix_len);
01867
01868 while (result == VACM_NOTINVIEW) {
01869
01877 tp = tp->next;
01878 if (tp) {
01879 prefix_len = netsnmp_oid_find_prefix(tp->start_a,
01880 tp->start_len,
01881 tp->end_a,
01882 tp->end_len);
01883 result =
01884 netsnmp_acm_check_subtree(asp->pdu,
01885 tp->start_a, prefix_len);
01886 }
01887 else
01888 break;
01889 }
01890 }
01891 if (tp == NULL) {
01892
01893
01894
01895
01896
01897
01898 switch (asp->pdu->command) {
01899 case SNMP_MSG_GETNEXT:
01900 case SNMP_MSG_GETBULK:
01901 varbind_ptr->type = SNMP_ENDOFMIBVIEW;
01902 break;
01903
01904 case SNMP_MSG_SET:
01905 case SNMP_MSG_GET:
01906 varbind_ptr->type = SNMP_NOSUCHOBJECT;
01907 break;
01908
01909 default:
01910 return NULL;
01911 }
01912 } else {
01913 DEBUGMSGTL(("snmp_agent", "tp->start "));
01914 DEBUGMSGOID(("snmp_agent", tp->start_a, tp->start_len));
01915 DEBUGMSG(("snmp_agent", ", tp->end "));
01916 DEBUGMSGOID(("snmp_agent", tp->end_a, tp->end_len));
01917 DEBUGMSG(("snmp_agent", ", \n"));
01918
01919
01920
01921
01922 request = &(asp->requests[vbcount - 1]);
01923 request->index = vbcount;
01924 request->delegated = 0;
01925 request->processed = 0;
01926 request->status = 0;
01927 request->subtree = tp;
01928 request->agent_req_info = asp->reqinfo;
01929 if (request->parent_data) {
01930 netsnmp_free_request_data_sets(request);
01931 }
01932 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p assigned to request\n",
01933 asp, asp->reqinfo));
01934
01935
01936
01937
01938 if (!MODE_IS_SET(asp->pdu->command)) {
01939 DEBUGMSGTL(("verbose:asp", "asp %p reqinfo %p assigned to request\n",
01940 asp, asp->reqinfo));
01941 if (varbind_ptr->type == ASN_PRIV_INCL_RANGE) {
01942 DEBUGMSGTL(("snmp_agent", "varbind %d is inclusive\n",
01943 request->index));
01944 request->inclusive = 1;
01945 }
01946 varbind_ptr->type = ASN_NULL;
01947 }
01948
01949
01950
01951
01952 if (tp->global_cacheid) {
01953
01954
01955
01956 if (asp->cache_store && -1 !=
01957 (cacheid = netsnmp_get_local_cachid(asp->cache_store,
01958 tp->global_cacheid))) {
01959 } else {
01960 cacheid = ++(asp->treecache_num);
01961 netsnmp_get_or_add_local_cachid(&asp->cache_store,
01962 tp->global_cacheid,
01963 cacheid);
01964 goto mallocslot;
01965 }
01966 } else if (tp->cacheid > -1 && tp->cacheid <= asp->treecache_num &&
01967 asp->treecache[tp->cacheid].subtree == tp) {
01968
01969
01970
01971
01972 cacheid = tp->cacheid;
01973 } else {
01974 cacheid = ++(asp->treecache_num);
01975 mallocslot:
01976
01977
01978
01979 if (asp->treecache_num >= asp->treecache_len) {
01980
01981
01982
01983
01984
01985
01986 #define CACHE_GROW_SIZE 16
01987 asp->treecache_len =
01988 (asp->treecache_len + CACHE_GROW_SIZE);
01989 asp->treecache =
01990 realloc(asp->treecache,
01991 sizeof(netsnmp_tree_cache) *
01992 asp->treecache_len);
01993 if (asp->treecache == NULL)
01994 return NULL;
01995 memset(&(asp->treecache[cacheid]), 0x00,
01996 sizeof(netsnmp_tree_cache) * (CACHE_GROW_SIZE));
01997 }
01998 asp->treecache[cacheid].subtree = tp;
01999 asp->treecache[cacheid].requests_begin = request;
02000 tp->cacheid = cacheid;
02001 }
02002
02003
02004
02005
02006 if (asp->pdu->command == SNMP_MSG_GETNEXT ||
02007 asp->pdu->command == SNMP_MSG_GETBULK) {
02008 request->range_end = tp->end_a;
02009 request->range_end_len = tp->end_len;
02010 } else {
02011 request->range_end = NULL;
02012 request->range_end_len = 0;
02013 }
02014
02015
02016
02017
02018 if (asp->treecache[cacheid].requests_end)
02019 asp->treecache[cacheid].requests_end->next = request;
02020 request->