Print this page
NEX-18695 libfmd_snmp is unable to handle multiple OIDs in GET request
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17777 snmptable produces bogus output for FM tables
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-3125 libfmd_snmp should compile with newer net-snmp
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/fm/libfmd_snmp/common/resource.c
          +++ new/usr/src/lib/fm/libfmd_snmp/common/resource.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
       27 +/*
       28 + * Copyright 2018 Nexenta Systems, Inc.
       29 + */
       30 +
  27   31  #include <fm/fmd_adm.h>
  28   32  #include <fm/fmd_snmp.h>
       33 +
  29   34  #include <net-snmp/net-snmp-config.h>
  30   35  #include <net-snmp/net-snmp-includes.h>
  31   36  #include <net-snmp/agent/net-snmp-agent-includes.h>
  32      -#include <pthread.h>
  33      -#include <stddef.h>
       37 +
  34   38  #include <errno.h>
  35   39  #include <libuutil.h>
       40 +#include <pthread.h>
       41 +#include <stddef.h>
       42 +
  36   43  #include "sunFM_impl.h"
  37   44  #include "resource.h"
  38   45  
  39   46  static uu_avl_pool_t    *rsrc_fmri_avl_pool;
  40   47  static uu_avl_pool_t    *rsrc_index_avl_pool;
  41   48  static uu_avl_t         *rsrc_fmri_avl;
  42   49  static uu_avl_t         *rsrc_index_avl;
  43   50  
  44   51  #define VALID_AVL_STATE (rsrc_fmri_avl_pool != NULL &&          \
  45   52          rsrc_index_avl_pool != NULL && rsrc_fmri_avl != NULL && \
  46   53          rsrc_index_avl != NULL)
  47   54  
  48      -#define UPDATE_WAIT_MILLIS      10      /* poll interval in milliseconds */
  49      -
  50   55  /*
  51   56   * Update types: single-index and all are mutually exclusive; a count
  52   57   * update is optional.
  53   58   */
  54   59  #define UCT_INDEX       0x1
  55   60  #define UCT_ALL         0x2
  56   61  #define UCT_COUNT       0x4
  57   62  #define UCT_FLAGS       0x7
  58   63  
  59   64  #define RESOURCE_DATA_VALID(d)  ((d)->d_valid == valid_stamp)
  60   65  
  61      -/*
  62      - * Locking strategy is described in module.c.
  63      - */
  64   66  static ulong_t          max_index;
  65   67  static int              valid_stamp;
  66   68  static uint32_t         rsrc_count;
  67   69  static pthread_mutex_t  update_lock;
  68      -static pthread_cond_t   update_cv;
  69      -static volatile enum { US_QUIET, US_NEEDED, US_INPROGRESS } update_status;
  70   70  
  71   71  static Netsnmp_Node_Handler     sunFmResourceTable_handler;
  72   72  static Netsnmp_Node_Handler     sunFmResourceCount_handler;
  73   73  
  74   74  static sunFmResource_data_t *
  75   75  key_build(const char *fmri, const ulong_t index)
  76   76  {
  77   77          static sunFmResource_data_t     key;
  78   78  
  79   79          key.d_index = index;
↓ open down ↓ 178 lines elided ↑ open up ↑
 258  258  
 259  259          if (err != 0) {
 260  260                  (void) snmp_log(LOG_ERR, MODNAME_STR ": fmd resource "
 261  261                      "information update failed: %s\n", fmd_adm_errmsg(adm));
 262  262                  return (SNMP_ERR_RESOURCEUNAVAILABLE);
 263  263          }
 264  264  
 265  265          return (SNMP_ERR_NOERROR);
 266  266  }
 267  267  
 268      -/*ARGSUSED*/
 269  268  static void
 270      -update_thread(void *arg)
      269 +request_update(void)
 271  270  {
      271 +        sunFmResource_update_ctx_t      uc;
      272 +
 272  273          /*
 273  274           * The current rsrcinfo_update implementation offers minimal savings
 274  275           * for the use of index-only updates; therefore we always do a full
 275  276           * update.  If it becomes advantageous to limit updates to a single
 276  277           * index, the contexts can be queued by the handler instead.
 277  278           */
 278      -        sunFmResource_update_ctx_t      uc;
 279  279  
 280  280          uc.uc_host = NULL;
 281  281          uc.uc_prog = FMD_ADM_PROGRAM;
 282  282          uc.uc_version = FMD_ADM_VERSION;
 283  283  
 284  284          uc.uc_all = 0;
 285  285          uc.uc_index = 0;
 286  286          uc.uc_type = UCT_ALL;
 287  287  
 288      -        for (;;) {
 289      -                (void) pthread_mutex_lock(&update_lock);
 290      -                update_status = US_QUIET;
 291      -                while (update_status == US_QUIET)
 292      -                        (void) pthread_cond_wait(&update_cv, &update_lock);
 293      -                update_status = US_INPROGRESS;
 294      -                (void) pthread_mutex_unlock(&update_lock);
 295      -                (void) rsrcinfo_update(&uc);
 296      -        }
      288 +        (void) rsrcinfo_update(&uc);
 297  289  }
 298  290  
 299      -static void
 300      -request_update(void)
 301      -{
 302      -        (void) pthread_mutex_lock(&update_lock);
 303      -        if (update_status != US_QUIET) {
 304      -                (void) pthread_mutex_unlock(&update_lock);
 305      -                return;
 306      -        }
 307      -        update_status = US_NEEDED;
 308      -        (void) pthread_cond_signal(&update_cv);
 309      -        (void) pthread_mutex_unlock(&update_lock);
 310      -}
 311      -
 312  291  /*ARGSUSED*/
 313  292  static int
 314  293  resource_compare_fmri(const void *l, const void *r, void *private)
 315  294  {
 316  295          sunFmResource_data_t    *l_data = (sunFmResource_data_t *)l;
 317  296          sunFmResource_data_t    *r_data = (sunFmResource_data_t *)r;
 318  297  
 319  298          ASSERT(l_data != NULL && r_data != NULL);
 320  299  
 321  300          return (strcmp(l_data->d_ari_fmri, r_data->d_ari_fmri));
↓ open down ↓ 19 lines elided ↑ open up ↑
 341  320          static oid sunFmResourceCount_oid[] = { SUNFMRESOURCECOUNT_OID, 0 };
 342  321          netsnmp_table_registration_info *table_info;
 343  322          netsnmp_handler_registration *handler;
 344  323          int err;
 345  324  
 346  325          if ((err = pthread_mutex_init(&update_lock, NULL)) != 0) {
 347  326                  (void) snmp_log(LOG_ERR, MODNAME_STR ": mutex_init failure: "
 348  327                      "%s\n", strerror(err));
 349  328                  return (MIB_REGISTRATION_FAILED);
 350  329          }
 351      -        if ((err = pthread_cond_init(&update_cv, NULL)) != 0) {
 352      -                (void) snmp_log(LOG_ERR, MODNAME_STR ": cond_init failure: "
 353      -                    "%s\n", strerror(err));
 354      -                return (MIB_REGISTRATION_FAILED);
 355      -        }
 356  330  
 357      -        if ((err = pthread_create(NULL, NULL, (void *(*)(void *))update_thread,
 358      -            NULL)) != 0) {
 359      -                (void) snmp_log(LOG_ERR, MODNAME_STR ": error creating update "
 360      -                    "thread: %s\n", strerror(err));
 361      -                return (MIB_REGISTRATION_FAILED);
 362      -        }
 363      -
 364  331          if ((table_info =
 365  332              SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
 366  333                  return (MIB_REGISTRATION_FAILED);
 367  334  
 368  335          if ((handler = netsnmp_create_handler_registration("sunFmResourceTable",
 369  336              sunFmResourceTable_handler, sunFmResourceTable_oid,
 370  337              OID_LENGTH(sunFmResourceTable_oid), HANDLER_CAN_RONLY)) == NULL) {
 371  338                  SNMP_FREE(table_info);
 372  339                  return (MIB_REGISTRATION_FAILED);
 373  340          }
↓ open down ↓ 80 lines elided ↑ open up ↑
 454  421                   * There's no way to unregister the table handler, so we
 455  422                   * can't free any of the data, either.
 456  423                   */
 457  424                  return (err);
 458  425          }
 459  426  
 460  427          return (MIB_REGISTERED_OK);
 461  428  }
 462  429  
 463  430  /*
 464      - * These two functions form the core of GET/GETNEXT/GETBULK handling (the
      431 + * These two functions form the core of GET/GETNEXT handling (the
 465  432   * only kind we do).  They perform two functions:
 466  433   *
 467  434   * - First, frob the request to set all the index variables to correspond
 468  435   *   to the value that's going to be returned.  For GET, this is a nop;
 469      - *   for GETNEXT/GETBULK it always requires some work.
      436 + *   for GETNEXT it always requires some work.
 470  437   * - Second, find and return the fmd resource information corresponding to
 471  438   *   the (possibly updated) indices.
 472  439   *
 473  440   * These should be as fast as possible; they run in the agent thread.
 474  441   */
 475  442  static sunFmResource_data_t *
 476  443  sunFmResourceTable_nextrsrc(netsnmp_handler_registration *reginfo,
 477  444      netsnmp_table_request_info *table_info)
 478  445  {
 479  446          sunFmResource_data_t    *data;
↓ open down ↓ 72 lines elided ↑ open up ↑
 552  519  static sunFmResource_data_t *
 553  520  sunFmResourceTable_rsrc(netsnmp_handler_registration *reginfo,
 554  521      netsnmp_table_request_info *table_info)
 555  522  {
 556  523          ASSERT(table_info->number_indexes == 1);
 557  524  
 558  525          return (resource_lookup_index_exact(table_info->index_oid[0]));
 559  526  }
 560  527  
 561  528  /*ARGSUSED*/
 562      -static void
 563      -sunFmResourceTable_return(unsigned int reg, void *arg)
      529 +static int
      530 +sunFmResourceTable_handler(netsnmp_mib_handler *handler,
      531 +    netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
      532 +    netsnmp_request_info *request)
 564  533  {
 565      -        netsnmp_delegated_cache         *cache = (netsnmp_delegated_cache *)arg;
 566      -        netsnmp_request_info            *request;
 567      -        netsnmp_agent_request_info      *reqinfo;
 568      -        netsnmp_handler_registration    *reginfo;
 569  534          netsnmp_table_request_info      *table_info;
 570  535          sunFmResource_data_t            *data;
 571  536          ulong_t                         rsrcstate;
      537 +        int                             ret = SNMP_ERR_NOERROR;
 572  538  
 573      -        ASSERT(netsnmp_handler_check_cache(cache) != NULL);
      539 +        /*
      540 +         * We don't support MODE_GETBULK directly, so all bulk requests should
      541 +         * come through bulk_to_next helper.  Make sure it stays that way.
      542 +         */
      543 +        ASSERT(reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT);
 574  544  
 575  545          (void) pthread_mutex_lock(&update_lock);
 576      -        if (update_status != US_QUIET) {
 577      -                struct timeval                  tv;
      546 +        request_update();
 578  547  
 579      -                tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 580      -                tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
      548 +        for (; request != NULL; request = request->next) {
      549 +                table_info = netsnmp_extract_table_info(request);
      550 +                if (table_info == NULL)
      551 +                        continue;
 581  552  
 582      -                (void) snmp_alarm_register_hr(tv, 0, sunFmResourceTable_return,
 583      -                    cache);
 584      -                (void) pthread_mutex_unlock(&update_lock);
 585      -                return;
 586      -        }
      553 +                ASSERT(table_info->colnum >= SUNFMRESOURCE_COLMIN);
      554 +                ASSERT(table_info->colnum <= SUNFMRESOURCE_COLMAX);
 587  555  
 588      -        request = cache->requests;
 589      -        reqinfo = cache->reqinfo;
 590      -        reginfo = cache->reginfo;
 591      -
 592      -        table_info = netsnmp_extract_table_info(request);
 593      -        request->delegated = 0;
 594      -
 595      -        ASSERT(table_info->colnum >= SUNFMRESOURCE_COLMIN);
 596      -        ASSERT(table_info->colnum <= SUNFMRESOURCE_COLMAX);
 597      -
 598      -        /*
 599      -         * table_info->colnum contains the column number requested.
 600      -         * table_info->indexes contains a linked list of snmp variable
 601      -         * bindings for the indexes of the table.  Values in the list
 602      -         * have been set corresponding to the indexes of the
 603      -         * request.  We have other guarantees as well:
 604      -         *
 605      -         * - The column number is always within range.
 606      -         * - If we have no index data, table_info->index_oid_len is 0.
 607      -         * - We will never receive requests outside our table nor
 608      -         *   those with the first subid anything other than 1 (Entry)
 609      -         *   nor those without a column number.  This is true even
 610      -         *   for GETNEXT requests.
 611      -         */
 612      -
 613      -        switch (reqinfo->mode) {
 614      -        case MODE_GET:
 615      -                if ((data = sunFmResourceTable_rsrc(reginfo, table_info)) ==
 616      -                    NULL) {
 617      -                        netsnmp_free_delegated_cache(cache);
 618      -                        (void) pthread_mutex_unlock(&update_lock);
 619      -                        return;
      556 +                /*
      557 +                 * table_info->colnum contains the column number requested.
      558 +                 * table_info->indexes contains a linked list of snmp variable
      559 +                 * bindings for the indexes of the table.  Values in the list
      560 +                 * have been set corresponding to the indexes of the
      561 +                 * request.  We have other guarantees as well:
      562 +                 *
      563 +                 * - The column number is always within range.
      564 +                 * - If we have no index data, table_info->index_oid_len is 0.
      565 +                 * - We will never receive requests outside our table nor
      566 +                 *   those with the first subid anything other than 1 (Entry)
      567 +                 *   nor those without a column number.  This is true even
      568 +                 *   for GETNEXT requests.
      569 +                 */
      570 +                switch (reqinfo->mode) {
      571 +                case MODE_GET:
      572 +                        data = sunFmResourceTable_rsrc(reginfo, table_info);
      573 +                        if (data == NULL)
      574 +                                goto out;
      575 +                        break;
      576 +                case MODE_GETNEXT:
      577 +                        data = sunFmResourceTable_nextrsrc(reginfo, table_info);
      578 +                        if (data == NULL)
      579 +                                goto out;
      580 +                        break;
      581 +                default:
      582 +                        (void) snmp_log(LOG_ERR, MODNAME_STR
      583 +                            ": unsupported request mode %d\n", reqinfo->mode);
      584 +                        ret = SNMP_ERR_GENERR;
      585 +                        goto out;
 620  586                  }
 621      -                break;
 622      -        case MODE_GETNEXT:
 623      -        case MODE_GETBULK:
 624      -                if ((data = sunFmResourceTable_nextrsrc(reginfo, table_info)) ==
 625      -                    NULL) {
 626      -                        netsnmp_free_delegated_cache(cache);
 627      -                        (void) pthread_mutex_unlock(&update_lock);
 628      -                        return;
 629      -                }
 630      -                break;
 631      -        default:
 632      -                (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
 633      -                    "mode %d\n", reqinfo->mode);
 634      -                netsnmp_free_delegated_cache(cache);
 635      -                (void) pthread_mutex_unlock(&update_lock);
 636      -                return;
 637      -        }
 638  587  
 639      -        switch (table_info->colnum) {
 640      -        case SUNFMRESOURCE_COL_FMRI:
 641      -                (void) netsnmp_table_build_result(reginfo, request, table_info,
 642      -                    ASN_OCTET_STR, (uchar_t *)data->d_ari_fmri,
 643      -                    strlen(data->d_ari_fmri));
 644      -                break;
 645      -        case SUNFMRESOURCE_COL_STATUS:
 646      -                switch (data->d_ari_flags &
 647      -                    (FMD_ADM_RSRC_FAULTY|FMD_ADM_RSRC_UNUSABLE)) {
 648      -                default:
 649      -                        rsrcstate = SUNFMRESOURCE_STATE_OK;
      588 +                switch (table_info->colnum) {
      589 +                case SUNFMRESOURCE_COL_FMRI:
      590 +                        (void) netsnmp_table_build_result(reginfo, request,
      591 +                            table_info, ASN_OCTET_STR,
      592 +                            (uchar_t *)data->d_ari_fmri,
      593 +                            strlen(data->d_ari_fmri));
 650  594                          break;
 651      -                case FMD_ADM_RSRC_FAULTY:
 652      -                        rsrcstate = SUNFMRESOURCE_STATE_DEGRADED;
      595 +                case SUNFMRESOURCE_COL_STATUS:
      596 +                        switch (data->d_ari_flags &
      597 +                            (FMD_ADM_RSRC_FAULTY|FMD_ADM_RSRC_UNUSABLE)) {
      598 +                        default:
      599 +                                rsrcstate = SUNFMRESOURCE_STATE_OK;
      600 +                                break;
      601 +                        case FMD_ADM_RSRC_FAULTY:
      602 +                                rsrcstate = SUNFMRESOURCE_STATE_DEGRADED;
      603 +                                break;
      604 +                        case FMD_ADM_RSRC_UNUSABLE:
      605 +                                rsrcstate = SUNFMRESOURCE_STATE_UNKNOWN;
      606 +                                break;
      607 +                        case FMD_ADM_RSRC_FAULTY | FMD_ADM_RSRC_UNUSABLE:
      608 +                                rsrcstate = SUNFMRESOURCE_STATE_FAULTED;
      609 +                                break;
      610 +                        }
      611 +                        (void) netsnmp_table_build_result(reginfo, request,
      612 +                            table_info, ASN_INTEGER, (uchar_t *)&rsrcstate,
      613 +                            sizeof (rsrcstate));
 653  614                          break;
 654      -                case FMD_ADM_RSRC_UNUSABLE:
 655      -                        rsrcstate = SUNFMRESOURCE_STATE_UNKNOWN;
      615 +                case SUNFMRESOURCE_COL_DIAGNOSISUUID:
      616 +                        (void) netsnmp_table_build_result(reginfo, request,
      617 +                            table_info, ASN_OCTET_STR,
      618 +                            (uchar_t *)data->d_ari_case,
      619 +                            strlen(data->d_ari_case));
 656  620                          break;
 657      -                case FMD_ADM_RSRC_FAULTY | FMD_ADM_RSRC_UNUSABLE:
 658      -                        rsrcstate = SUNFMRESOURCE_STATE_FAULTED;
      621 +                default:
 659  622                          break;
 660  623                  }
 661      -                (void) netsnmp_table_build_result(reginfo, request, table_info,
 662      -                    ASN_INTEGER, (uchar_t *)&rsrcstate,
 663      -                    sizeof (rsrcstate));
 664      -                break;
 665      -        case SUNFMRESOURCE_COL_DIAGNOSISUUID:
 666      -                (void) netsnmp_table_build_result(reginfo, request, table_info,
 667      -                    ASN_OCTET_STR, (uchar_t *)data->d_ari_case,
 668      -                    strlen(data->d_ari_case));
 669      -                break;
 670      -        default:
 671      -                break;
 672  624          }
 673      -        netsnmp_free_delegated_cache(cache);
      625 +
      626 +out:
 674  627          (void) pthread_mutex_unlock(&update_lock);
      628 +        return (ret);
 675  629  }
 676  630  
      631 +/*ARGSUSED*/
 677  632  static int
 678      -sunFmResourceTable_handler(netsnmp_mib_handler *handler,
      633 +sunFmResourceCount_handler(netsnmp_mib_handler *handler,
 679  634      netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
 680      -    netsnmp_request_info *requests)
      635 +    netsnmp_request_info *request)
 681  636  {
 682      -        netsnmp_request_info            *request;
 683      -        struct timeval                  tv;
 684      -
 685      -        tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 686      -        tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
 687      -
 688      -        request_update();
 689      -
 690      -        for (request = requests; request; request = request->next) {
 691      -                if (request->processed != 0)
 692      -                        continue;
 693      -
 694      -                if (netsnmp_extract_table_info(request) == NULL)
 695      -                        continue;
 696      -
 697      -                request->delegated = 1;
 698      -                (void) snmp_alarm_register_hr(tv, 0, sunFmResourceTable_return,
 699      -                    (void *) netsnmp_create_delegated_cache(handler, reginfo,
 700      -                    reqinfo, request, NULL));
 701      -        }
 702      -
 703      -        return (SNMP_ERR_NOERROR);
 704      -}
 705      -
 706      -/*ARGSUSED*/
 707      -static void
 708      -sunFmResourceCount_return(unsigned int reg, void *arg)
 709      -{
 710      -        netsnmp_delegated_cache         *cache = (netsnmp_delegated_cache *)arg;
 711      -        netsnmp_request_info            *request;
 712      -        netsnmp_agent_request_info      *reqinfo;
 713  637          ulong_t                         rsrc_count_long;
      638 +        int                             ret = SNMP_ERR_NOERROR;
 714  639  
 715      -        ASSERT(netsnmp_handler_check_cache(cache) != NULL);
 716      -
 717      -        (void) pthread_mutex_lock(&update_lock);
 718      -        if (update_status != US_QUIET) {
 719      -                struct timeval  tv;
 720      -
 721      -                tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 722      -                tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
 723      -
 724      -                (void) snmp_alarm_register_hr(tv, 0, sunFmResourceCount_return,
 725      -                    cache);
 726      -                (void) pthread_mutex_unlock(&update_lock);
 727      -                return;
 728      -        }
 729      -
 730      -        request = cache->requests;
 731      -        reqinfo = cache->reqinfo;
 732      -
 733      -        request->delegated = 0;
 734      -
 735      -        switch (reqinfo->mode) {
 736  640          /*
 737      -         * According to the documentation, it's not possible for us ever to
 738      -         * be called with MODE_GETNEXT.  However, Net-SNMP does the following:
 739      -         * - set reqinfo->mode to MODE_GET
 740      -         * - invoke the handler
 741      -         * - set reqinfo->mode to MODE_GETNEXT (even if the request was not
 742      -         *   actually processed; i.e. it's been delegated)
 743      -         * Since we're called back later with the same reqinfo, we see
 744      -         * GETNEXT.  Therefore this case is needed to work around the
 745      -         * Net-SNMP bug.
      641 +         * We don't support MODE_GETBULK directly, so all bulk requests should
      642 +         * come through bulk_to_next helper.  Make sure it stays that way.
 746  643           */
 747      -        case MODE_GET:
 748      -        case MODE_GETNEXT:
 749      -                DEBUGMSGTL((MODNAME_STR, "resource count is %u\n", rsrc_count));
 750      -                rsrc_count_long = (ulong_t)rsrc_count;
 751      -                (void) snmp_set_var_typed_value(request->requestvb, ASN_GAUGE,
 752      -                    (uchar_t *)&rsrc_count_long, sizeof (rsrc_count_long));
 753      -                break;
 754      -        default:
 755      -                (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
 756      -                    "mode %d\n", reqinfo->mode);
 757      -        }
      644 +        ASSERT(reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT);
 758  645  
 759      -        netsnmp_free_delegated_cache(cache);
 760      -        (void) pthread_mutex_unlock(&update_lock);
 761      -}
 762      -
 763      -static int
 764      -sunFmResourceCount_handler(netsnmp_mib_handler *handler,
 765      -    netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
 766      -    netsnmp_request_info *requests)
 767      -{
 768      -        struct timeval  tv;
 769      -
 770      -        tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 771      -        tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
 772      -
      646 +        (void) pthread_mutex_lock(&update_lock);
 773  647          request_update();
 774  648  
 775      -        /*
 776      -         * We are never called for a GETNEXT when registered as an
 777      -         * instance; it's handled for us and converted to a GET.
 778      -         * Also, an instance handler is given only one request at a time, so
 779      -         * we don't need to loop over a list of requests.
 780      -         */
      649 +        for (; request != NULL; request = request->next) {
      650 +                switch (reqinfo->mode) {
      651 +                /*
      652 +                 * According to the documentation, it's not possible for us ever
      653 +                 * to be called with MODE_GETNEXT.  However, Net-SNMP does the
      654 +                 * following:
      655 +                 * - set reqinfo->mode to MODE_GET
      656 +                 * - invoke the handler
      657 +                 * - set reqinfo->mode to MODE_GETNEXT (even if the request was
      658 +                 *   not actually processed; i.e. it's been delegated)
      659 +                 * Since we're called back later with the same reqinfo, we see
      660 +                 * GETNEXT.  Therefore this case is needed to work around the
      661 +                 * Net-SNMP bug.
      662 +                 */
      663 +                case MODE_GET:
      664 +                case MODE_GETNEXT:
      665 +                        DEBUGMSGTL((MODNAME_STR, "resource count is %u\n",
      666 +                            rsrc_count));
      667 +                        rsrc_count_long = (ulong_t)rsrc_count;
      668 +                        (void) snmp_set_var_typed_value(request->requestvb,
      669 +                            ASN_GAUGE, (uchar_t *)&rsrc_count_long,
      670 +                            sizeof (rsrc_count_long));
      671 +                        break;
      672 +                default:
      673 +                        (void) snmp_log(LOG_ERR, MODNAME_STR
      674 +                            ": unsupported request mode: %d\n", reqinfo->mode);
      675 +                        ret = SNMP_ERR_GENERR;
      676 +                }
      677 +        }
 781  678  
 782      -        if (requests->processed != 0)
 783      -                return (SNMP_ERR_NOERROR);
 784      -
 785      -        requests->delegated = 1;
 786      -        (void) snmp_alarm_register_hr(tv, 0, sunFmResourceCount_return,
 787      -            (void *) netsnmp_create_delegated_cache(handler, reginfo,
 788      -            reqinfo, requests, NULL));
 789      -
 790      -        return (SNMP_ERR_NOERROR);
      679 +        (void) pthread_mutex_unlock(&update_lock);
      680 +        return (ret);
 791  681  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX