Print this page
    
5835 fix printf tokens for net-snmp 5.7.2
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/fm/libfmd_snmp/common/problem.c
          +++ new/usr/src/lib/fm/libfmd_snmp/common/problem.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  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   27  #include <sys/fm/protocol.h>
  28   28  #include <fm/fmd_adm.h>
  29   29  #include <fm/fmd_snmp.h>
  30   30  #include <net-snmp/net-snmp-config.h>
  31   31  #include <net-snmp/net-snmp-includes.h>
  32   32  #include <net-snmp/agent/net-snmp-agent-includes.h>
  33   33  #include <pthread.h>
  34   34  #include <stddef.h>
  35   35  #include <errno.h>
  36   36  #include <alloca.h>
  37   37  #include <locale.h>
  38   38  #include <libuutil.h>
  39   39  #include <libnvpair.h>
  40   40  #include "sunFM_impl.h"
  41   41  #include "problem.h"
  42   42  
  43   43  /*
  44   44   * We assume that the number of suspect fault events associated with a
  45   45   * particular case will generally be sufficiently small that the overhead
  46   46   * associated with indexing them in a tree would exceed the gain from
  47   47   * not traversing the fault list for each request.
  48   48   */
  49   49  static uu_avl_pool_t    *problem_uuid_avl_pool;
  50   50  static uu_avl_t         *problem_uuid_avl;
  51   51  
  52   52  #define VALID_AVL_STATE (problem_uuid_avl_pool != NULL &&       \
  53   53          problem_uuid_avl != NULL)
  54   54  
  55   55  #define UPDATE_WAIT_MILLIS      10      /* poll interval in milliseconds */
  56   56  
  57   57  /*
  58   58   * Update types.  Single-index and all are mutually exclusive.
  59   59   */
  60   60  #define UCT_INDEX       0x1
  61   61  #define UCT_ALL         0x2
  62   62  #define UCT_FLAGS       0x3
  63   63  
  64   64  /*
  65   65   * Locking strategy is described in module.c.
  66   66   */
  67   67  static int              valid_stamp;
  68   68  static pthread_mutex_t  update_lock;
  69   69  static pthread_cond_t   update_cv;
  70   70  static volatile enum { US_QUIET, US_NEEDED, US_INPROGRESS } update_status;
  71   71  
  72   72  static Netsnmp_Node_Handler     sunFmProblemTable_handler;
  73   73  static Netsnmp_Node_Handler     sunFmFaultEventTable_handler;
  74   74  
  75   75  static sunFmProblem_data_t *
  76   76  problem_key_build(const char *uuid)
  77   77  {
  78   78          static sunFmProblem_data_t      key;
  79   79  
  80   80          key.d_aci_uuid = uuid;
  81   81  
  82   82          return (&key);
  83   83  }
  84   84  
  85   85  static sunFmProblem_data_t *
  86   86  problem_lookup_uuid_exact(const char *uuid)
  87   87  {
  88   88          sunFmProblem_data_t     *key, *data;
  89   89  
  90   90          key = problem_key_build(uuid);
  91   91  
  92   92          DEBUGMSGTL((MODNAME_STR, "lookup_exact for uuid %s\n", uuid));
  93   93          data = uu_avl_find(problem_uuid_avl, key, NULL, NULL);
  94   94  
  95   95          return (data);
  96   96  }
  97   97  
  98   98  static sunFmProblem_data_t *
  99   99  problem_lookup_uuid_next(const char *uuid)
 100  100  {
 101  101          sunFmProblem_data_t     *key, *data;
 102  102          uu_avl_index_t          idx;
 103  103  
 104  104          key = problem_key_build(uuid);
 105  105  
 106  106          DEBUGMSGTL((MODNAME_STR, "lookup_next for uuid %s\n", uuid));
 107  107          (void) uu_avl_find(problem_uuid_avl, key, NULL, &idx);
 108  108  
 109  109          data = uu_avl_nearest_next(problem_uuid_avl, idx);
 110  110  
 111  111          DEBUGMSGTL((MODNAME_STR, "lookup_next: entry is %p\n", data));
 112  112  
 113  113          return (data);
 114  114  }
 115  115  
 116  116  static sunFmFaultEvent_data_t *
 117  117  faultevent_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index)
 118  118  {
 119  119          if (index > data->d_nsuspects)
 120  120                  return (NULL);
 121  121  
 122  122          if (data->d_suspects == NULL)
 123  123                  return (NULL);
 124  124  
 125  125          return (data->d_suspects[index - 1]);
 126  126  }
 127  127  
 128  128  static sunFmFaultStatus_data_t
 129  129  faultstatus_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index)
 130  130  {
 131  131          if (index > data->d_nsuspects)
 132  132                  return (0);
 133  133  
 134  134          if (data->d_statuses == NULL)
 135  135                  return (0);
 136  136  
 137  137          if (data->d_valid != valid_stamp)
 138  138                  return (0);
 139  139  
 140  140          return (data->d_statuses[index - 1]);
 141  141  }
 142  142  
 143  143  /*ARGSUSED*/
 144  144  static int
 145  145  problem_update_one(const fmd_adm_caseinfo_t *acp, void *arg)
 146  146  {
 147  147          sunFmProblem_data_t             *data;
 148  148          nvlist_t                        *nvl;
 149  149          int64_t                         *diag_time;
 150  150          uint_t                          nelem;
 151  151          uint32_t                        nsusp;
 152  152          int                             err;
 153  153  
 154  154          DEBUGMSGTL((MODNAME_STR, "update_one\n"));
 155  155  
 156  156          ASSERT(acp->aci_uuid != NULL);
 157  157  
 158  158          if ((data = problem_lookup_uuid_exact(acp->aci_uuid)) == NULL) {
 159  159                  uu_avl_index_t idx;
 160  160  
 161  161                  DEBUGMSGTL((MODNAME_STR, "found new problem %s\n",
 162  162                      acp->aci_uuid));
 163  163                  if ((data = SNMP_MALLOC_TYPEDEF(sunFmProblem_data_t)) == NULL) {
 164  164                          (void) snmp_log(LOG_ERR, MODNAME_STR ": Out of memory "
 165  165                              "for new problem data at %s:%d\n", __FILE__,
 166  166                              __LINE__);
 167  167                          return (0);
 168  168                  }
 169  169                  if ((err = nvlist_dup(acp->aci_event, &data->d_aci_event, 0))
 170  170                      != 0) {
 171  171                          (void) snmp_log(LOG_ERR, MODNAME_STR ": Problem data "
 172  172                              "setup failed: %s\n", strerror(err));
 173  173                          SNMP_FREE(data);
 174  174                          return (0);
 175  175                  }
 176  176  
 177  177                  data->d_aci_uuid = data->d_aci_code = data->d_aci_url = "-";
 178  178                  (void) nvlist_lookup_string(data->d_aci_event, FM_SUSPECT_UUID,
 179  179                      (char **)&data->d_aci_uuid);
 180  180                  (void) nvlist_lookup_string(data->d_aci_event,
 181  181                      FM_SUSPECT_DIAG_CODE, (char **)&data->d_aci_code);
 182  182                  data->d_aci_url = strdup(acp->aci_url);
 183  183  
 184  184                  if (nvlist_lookup_nvlist(data->d_aci_event, FM_SUSPECT_DE,
 185  185                      &nvl) == 0)
 186  186                          if ((data->d_diag_engine = sunFm_nvl2str(nvl)) == NULL)
 187  187                                  data->d_diag_engine = "-";
 188  188  
 189  189                  if (nvlist_lookup_int64_array(data->d_aci_event,
 190  190                      FM_SUSPECT_DIAG_TIME, &diag_time, &nelem) == 0 &&
 191  191                      nelem >= 2) {
 192  192                          data->d_diag_time.tv_sec = (long)diag_time[0];
 193  193                          data->d_diag_time.tv_usec = (long)diag_time[1];
 194  194                  }
 195  195  
 196  196                  (void) nvlist_lookup_uint32(data->d_aci_event,
 197  197                      FM_SUSPECT_FAULT_SZ, &nsusp);
 198  198                  data->d_nsuspects = (ulong_t)nsusp;
 199  199  
 200  200                  (void) nvlist_lookup_nvlist_array(data->d_aci_event,
 201  201                      FM_SUSPECT_FAULT_LIST, &data->d_suspects, &nelem);
 202  202  
 203  203                  ASSERT(nelem == data->d_nsuspects);
 204  204  
 205  205                  (void) nvlist_lookup_uint8_array(data->d_aci_event,
 206  206                      FM_SUSPECT_FAULT_STATUS, &data->d_statuses, &nelem);
 207  207  
 208  208                  ASSERT(nelem == data->d_nsuspects);
 209  209  
 210  210                  uu_avl_node_init(data, &data->d_uuid_avl,
 211  211                      problem_uuid_avl_pool);
 212  212                  (void) uu_avl_find(problem_uuid_avl, data, NULL, &idx);
 213  213                  uu_avl_insert(problem_uuid_avl, data, idx);
 214  214  
 215  215                  data->d_valid = valid_stamp;
 216  216  
 217  217                  DEBUGMSGTL((MODNAME_STR, "completed new problem %s@%p\n",
 218  218                      data->d_aci_uuid, data));
 219  219          } else {
 220  220                  uint8_t *statuses;
 221  221                  int i;
 222  222  
 223  223                  (void) nvlist_lookup_uint8_array(acp->aci_event,
 224  224                      FM_SUSPECT_FAULT_STATUS, &statuses, &nelem);
 225  225  
 226  226                  ASSERT(nelem == data->d_nsuspects);
 227  227  
 228  228                  for (i = 0; i < nelem; i++)
 229  229                          data->d_statuses[i] = statuses[i];
 230  230  
 231  231                  data->d_valid = valid_stamp;
 232  232          }
 233  233  
 234  234          /*
 235  235           * We don't touch problems we've seen before; they shouldn't change
 236  236           * in any way we care about, since they've already been solved.  The
 237  237           * state, however, could change, and if we later expose that to the
 238  238           * client we need to update it here.
 239  239           */
 240  240  
 241  241          return (0);
 242  242  }
 243  243  
 244  244  static int
 245  245  problem_update(sunFmProblem_update_ctx_t *update_ctx)
 246  246  {
 247  247          fmd_adm_t *adm;
 248  248  
 249  249          ASSERT(update_ctx != NULL);
 250  250          ASSERT((update_ctx->uc_type & (UCT_INDEX|UCT_ALL)) !=
 251  251              (UCT_INDEX|UCT_ALL));
 252  252          ASSERT((update_ctx->uc_type & ~UCT_FLAGS) == 0);
 253  253          ASSERT(VALID_AVL_STATE);
 254  254  
 255  255          if ((adm = fmd_adm_open(update_ctx->uc_host, update_ctx->uc_prog,
 256  256              update_ctx->uc_version)) == NULL) {
 257  257                  (void) snmp_log(LOG_ERR, MODNAME_STR ": Communication with fmd "
 258  258                      "failed: %s\n", strerror(errno));
 259  259                  return (SNMP_ERR_RESOURCEUNAVAILABLE);
 260  260          }
 261  261  
 262  262          ++valid_stamp;
 263  263          if (fmd_adm_case_iter(adm, SNMP_URL_MSG, problem_update_one,
 264  264              update_ctx) != 0) {
 265  265                  (void) snmp_log(LOG_ERR, MODNAME_STR ": fmd case information "
 266  266                      "update failed: %s\n", fmd_adm_errmsg(adm));
 267  267                  fmd_adm_close(adm);
 268  268                  return (SNMP_ERR_RESOURCEUNAVAILABLE);
 269  269          }
 270  270  
 271  271          DEBUGMSGTL((MODNAME_STR, "case iteration completed\n"));
 272  272  
 273  273          fmd_adm_close(adm);
 274  274          return (SNMP_ERR_NOERROR);
 275  275  }
 276  276  
 277  277  /*ARGSUSED*/
 278  278  static void
 279  279  update_thread(void *arg)
 280  280  {
 281  281          /*
 282  282           * The current problem_update implementation offers minimal savings
 283  283           * for the use of index-only updates; therefore we always do a full
 284  284           * update.  If it becomes advantageous to limit updates to a single
 285  285           * index, the contexts can be queued by the handler instead.
 286  286           */
 287  287          sunFmProblem_update_ctx_t       uc;
 288  288  
 289  289          uc.uc_host = NULL;
 290  290          uc.uc_prog = FMD_ADM_PROGRAM;
 291  291          uc.uc_version = FMD_ADM_VERSION;
 292  292  
 293  293          uc.uc_index = NULL;
 294  294          uc.uc_type = UCT_ALL;
 295  295  
 296  296          for (;;) {
 297  297                  (void) pthread_mutex_lock(&update_lock);
 298  298                  update_status = US_QUIET;
 299  299                  while (update_status == US_QUIET)
 300  300                          (void) pthread_cond_wait(&update_cv, &update_lock);
 301  301                  update_status = US_INPROGRESS;
 302  302                  (void) pthread_mutex_unlock(&update_lock);
 303  303                  (void) problem_update(&uc);
 304  304          }
 305  305  }
 306  306  
 307  307  static void
 308  308  request_update(void)
 309  309  {
 310  310          (void) pthread_mutex_lock(&update_lock);
 311  311          if (update_status != US_QUIET) {
 312  312                  (void) pthread_mutex_unlock(&update_lock);
 313  313                  return;
 314  314          }
 315  315          update_status = US_NEEDED;
 316  316          (void) pthread_cond_signal(&update_cv);
 317  317          (void) pthread_mutex_unlock(&update_lock);
 318  318  }
 319  319  
 320  320  /*ARGSUSED*/
 321  321  static int
 322  322  problem_compare_uuid(const void *l, const void *r, void *private)
 323  323  {
 324  324          sunFmProblem_data_t     *l_data = (sunFmProblem_data_t *)l;
 325  325          sunFmProblem_data_t     *r_data = (sunFmProblem_data_t *)r;
 326  326  
 327  327          ASSERT(l_data != NULL && r_data != NULL);
 328  328  
 329  329          return (strcmp(l_data->d_aci_uuid, r_data->d_aci_uuid));
 330  330  }
 331  331  
 332  332  int
 333  333  sunFmProblemTable_init(void)
 334  334  {
 335  335          static oid sunFmProblemTable_oid[] = { SUNFMPROBLEMTABLE_OID };
 336  336          netsnmp_table_registration_info *table_info;
 337  337          netsnmp_handler_registration *handler;
 338  338          int err;
 339  339  
 340  340          if ((err = pthread_mutex_init(&update_lock, NULL)) != 0) {
 341  341                  (void) snmp_log(LOG_ERR, MODNAME_STR ": mutex_init failure: "
 342  342                      "%s\n", strerror(err));
 343  343                  return (MIB_REGISTRATION_FAILED);
 344  344          }
 345  345          if ((err = pthread_cond_init(&update_cv, NULL)) != 0) {
 346  346                  (void) snmp_log(LOG_ERR, MODNAME_STR ": cond_init failure: "
 347  347                      "%s\n", strerror(err));
 348  348                  return (MIB_REGISTRATION_FAILED);
 349  349          }
 350  350  
 351  351          if ((err = pthread_create(NULL, NULL, (void *(*)(void *))update_thread,
 352  352              NULL)) != 0) {
 353  353                  (void) snmp_log(LOG_ERR, MODNAME_STR ": error creating update "
 354  354                      "thread: %s\n", strerror(err));
 355  355                  return (MIB_REGISTRATION_FAILED);
 356  356          }
 357  357  
 358  358          if ((table_info =
 359  359              SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
 360  360                  return (MIB_REGISTRATION_FAILED);
 361  361  
 362  362          if ((handler = netsnmp_create_handler_registration("sunFmProblemTable",
 363  363              sunFmProblemTable_handler, sunFmProblemTable_oid,
 364  364              OID_LENGTH(sunFmProblemTable_oid), HANDLER_CAN_RONLY)) == NULL) {
 365  365                  SNMP_FREE(table_info);
 366  366                  return (MIB_REGISTRATION_FAILED);
 367  367          }
 368  368  
 369  369          /*
 370  370           * The Net-SNMP template uses add_indexes here, but that
 371  371           * function is unsafe because it does not check for failure.
 372  372           */
 373  373          if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) {
 374  374                  SNMP_FREE(table_info);
 375  375                  SNMP_FREE(handler);
 376  376                  return (MIB_REGISTRATION_FAILED);
 377  377          }
 378  378  
 379  379          table_info->min_column = SUNFMPROBLEM_COLMIN;
 380  380          table_info->max_column = SUNFMPROBLEM_COLMAX;
 381  381  
 382  382          if ((problem_uuid_avl_pool = uu_avl_pool_create("problem_uuid",
 383  383              sizeof (sunFmProblem_data_t),
 384  384              offsetof(sunFmProblem_data_t, d_uuid_avl), problem_compare_uuid,
 385  385              UU_AVL_DEBUG)) == NULL) {
 386  386                  (void) snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl pool "
 387  387                      "creation failed: %s\n", uu_strerror(uu_error()));
 388  388                  snmp_free_varbind(table_info->indexes);
 389  389                  SNMP_FREE(table_info);
 390  390                  SNMP_FREE(handler);
 391  391                  return (MIB_REGISTRATION_FAILED);
 392  392          }
 393  393  
 394  394          if ((problem_uuid_avl = uu_avl_create(problem_uuid_avl_pool, NULL,
 395  395              UU_AVL_DEBUG)) == NULL) {
 396  396                  (void) snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl "
 397  397                      "creation failed: %s\n", uu_strerror(uu_error()));
 398  398                  snmp_free_varbind(table_info->indexes);
 399  399                  SNMP_FREE(table_info);
 400  400                  SNMP_FREE(handler);
 401  401                  uu_avl_pool_destroy(problem_uuid_avl_pool);
 402  402                  return (MIB_REGISTRATION_FAILED);
 403  403          }
 404  404  
 405  405          if ((err = netsnmp_register_table(handler, table_info)) !=
 406  406              MIB_REGISTERED_OK) {
 407  407                  snmp_free_varbind(table_info->indexes);
 408  408                  SNMP_FREE(table_info);
 409  409                  SNMP_FREE(handler);
 410  410                  uu_avl_destroy(problem_uuid_avl);
 411  411                  uu_avl_pool_destroy(problem_uuid_avl_pool);
 412  412                  return (err);
 413  413          }
 414  414  
 415  415          return (MIB_REGISTERED_OK);
 416  416  }
 417  417  
 418  418  int
 419  419  sunFmFaultEventTable_init(void)
 420  420  {
 421  421          static oid sunFmFaultEventTable_oid[] = { SUNFMFAULTEVENTTABLE_OID };
 422  422          netsnmp_table_registration_info *table_info;
 423  423          netsnmp_handler_registration *handler;
 424  424          int err;
 425  425  
 426  426          if ((table_info =
 427  427              SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
 428  428                  return (MIB_REGISTRATION_FAILED);
 429  429  
 430  430          if ((handler =
 431  431              netsnmp_create_handler_registration("sunFmFaultEventTable",
 432  432              sunFmFaultEventTable_handler, sunFmFaultEventTable_oid,
 433  433              OID_LENGTH(sunFmFaultEventTable_oid), HANDLER_CAN_RONLY)) == NULL) {
 434  434                  SNMP_FREE(table_info);
 435  435                  return (MIB_REGISTRATION_FAILED);
 436  436          }
 437  437  
 438  438          /*
 439  439           * The Net-SNMP template uses add_indexes here, but that
 440  440           * function is unsafe because it does not check for failure.
 441  441           */
 442  442          if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) {
 443  443                  SNMP_FREE(table_info);
 444  444                  SNMP_FREE(handler);
 445  445                  return (MIB_REGISTRATION_FAILED);
 446  446          }
 447  447          if (netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED) == NULL) {
 448  448                  snmp_free_varbind(table_info->indexes);
 449  449                  SNMP_FREE(table_info);
 450  450                  SNMP_FREE(handler);
 451  451                  return (MIB_REGISTRATION_FAILED);
 452  452          }
 453  453  
 454  454          table_info->min_column = SUNFMFAULTEVENT_COLMIN;
 455  455          table_info->max_column = SUNFMFAULTEVENT_COLMAX;
 456  456  
 457  457          if ((err = netsnmp_register_table(handler, table_info)) !=
 458  458              MIB_REGISTERED_OK) {
 459  459                  snmp_free_varbind(table_info->indexes);
 460  460                  SNMP_FREE(table_info);
 461  461                  SNMP_FREE(handler);
 462  462                  return (err);
 463  463          }
 464  464  
 465  465          return (MIB_REGISTERED_OK);
 466  466  }
 467  467  
 468  468  /*
 469  469   * Returns the problem data for the problem whose uuid is next according
 470  470   * to ASN.1 lexical ordering after the request in table_info.  Indexes are
 471  471   * updated to reflect the OID of the value being returned.  This allows
 472  472   * us to implement GETNEXT.
 473  473   */
 474  474  static sunFmProblem_data_t *
 475  475  sunFmProblemTable_nextpr(netsnmp_handler_registration *reginfo,
 476  476      netsnmp_table_request_info *table_info)
 477  477  {
 478  478          sunFmProblem_data_t     *data;
 479  479          char                    *uuid = "";
 480  480  
 481  481          if (table_info->number_indexes < 1) {
 482  482                  oid tmpoid[MAX_OID_LEN];
 483  483  
 484  484                  DEBUGMSGTL((MODNAME_STR, "nextpr: no indexes given\n"));
 485  485  
 486  486                  snmp_free_varbind(table_info->indexes);
 487  487                  table_info->indexes =
 488  488                      SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
 489  489                  (void) snmp_set_var_typed_value(table_info->indexes,
 490  490                      ASN_OCTET_STR, (const uchar_t *)uuid, 0);
 491  491                  (void) memcpy(tmpoid, reginfo->rootoid,
 492  492                      reginfo->rootoid_len * sizeof (oid));
 493  493                  tmpoid[reginfo->rootoid_len] = 1;
 494  494                  tmpoid[reginfo->rootoid_len + 1] = table_info->colnum;
 495  495                  if (build_oid_segment(table_info->indexes) != SNMPERR_SUCCESS) {
 496  496                          snmp_free_varbind(table_info->indexes);
 497  497                          return (NULL);
 498  498                  }
 499  499                  table_info->number_indexes = 1;
 500  500                  table_info->index_oid_len = table_info->indexes->name_length;
 501  501                  (void) memcpy(table_info->index_oid, table_info->indexes->name,
 502  502                      table_info->indexes->name_length);
 503  503  
 504  504                  DEBUGMSGTL((MODNAME_STR, "nextpr: built fake index:\n"));
 505  505                  DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
 506  506                  DEBUGMSG((MODNAME_STR, "\n"));
 507  507          } else {
 508  508                  /*
 509  509                   * Construct the next possible UUID to look for.  We can
 510  510                   * simply increment the least significant byte of the last
 511  511                   * UUID because (a) that preserves SNMP lex order and (b)
 512  512                   * the characters that may appear in a UUID do not include
 513  513                   * 127 nor 255.
 514  514                   */
 515  515                  uuid = alloca(table_info->indexes->val_len + 1);
 516  516                  (void) strlcpy(uuid,
 517  517                      (const char *)table_info->indexes->val.string,
 518  518                      table_info->indexes->val_len + 1);
 519  519                  ++uuid[table_info->indexes->val_len - 1];
 520  520  
 521  521                  DEBUGMSGTL((MODNAME_STR, "nextpr: received index:\n"));
 522  522                  DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
 523  523                  DEBUGMSG((MODNAME_STR, "\n"));
 524  524          }
 525  525  
 526  526          if ((data = problem_lookup_uuid_next(uuid)) == NULL) {
 527  527                  DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found for "
 528  528                      "%s; trying next column\n", uuid));
  
    | 
      ↓ open down ↓ | 
    528 lines elided | 
    
      ↑ open up ↑ | 
  
 529  529                  if (table_info->colnum >=
 530  530                      netsnmp_find_table_registration_info(reginfo)->max_column) {
 531  531                          snmp_free_varbind(table_info->indexes);
 532  532                          table_info->indexes = NULL;
 533  533                          table_info->number_indexes = 0;
 534  534                          DEBUGMSGTL((MODNAME_STR, "nextpr: out of columns\n"));
 535  535                          return (NULL);
 536  536                  }
 537  537                  table_info->colnum++;
 538  538                  DEBUGMSGTL((MODNAME_STR, "nextpr: search for col %u empty "
 539      -                    "uuid\n", table_info->colnum, uuid));
      539 +                    "uuid\n", table_info->colnum));
 540  540  
 541  541                  if ((data = problem_lookup_uuid_next("")) == NULL) {
 542  542                          DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found "
 543  543                              "for empty uuid; stopping\n"));
 544  544                          snmp_free_varbind(table_info->indexes);
 545  545                          table_info->indexes = NULL;
 546  546                          table_info->number_indexes = 0;
 547  547                          return (NULL);
 548  548                  }
 549  549          }
 550  550  
 551  551          (void) snmp_set_var_typed_value(table_info->indexes, ASN_OCTET_STR,
 552  552              (uchar_t *)data->d_aci_uuid, strlen(data->d_aci_uuid));
 553  553          table_info->number_indexes = 1;
 554  554  
 555  555          DEBUGMSGTL((MODNAME_STR, "matching data is %s@%p\n", data->d_aci_uuid,
 556  556              data));
 557  557  
 558  558          return (data);
 559  559  }
 560  560  
 561  561  /*
 562  562   * Returns the problem data corresponding to the request in table_info.
 563  563   * All request parameters are unmodified.
 564  564   */
 565  565  /*ARGSUSED*/
 566  566  static sunFmProblem_data_t *
 567  567  sunFmProblemTable_pr(netsnmp_handler_registration *reginfo,
 568  568      netsnmp_table_request_info *table_info)
 569  569  {
 570  570          char                    *uuid;
 571  571  
 572  572          ASSERT(table_info->number_indexes >= 1);
 573  573  
 574  574          uuid = alloca(table_info->indexes->val_len + 1);
 575  575          (void) strlcpy(uuid, (const char *)table_info->indexes->val.string,
 576  576              table_info->indexes->val_len + 1);
 577  577  
 578  578          return (problem_lookup_uuid_exact(uuid));
 579  579  }
 580  580  
 581  581  /*
 582  582   * Returns the ASN.1 lexicographically first fault event after the one
 583  583   * identified by table_info.  Indexes are updated to reflect the OID
 584  584   * of the data returned.  This allows us to implement GETNEXT.
 585  585   */
 586  586  static sunFmFaultEvent_data_t *
 587  587  sunFmFaultEventTable_nextfe(netsnmp_handler_registration *reginfo,
 588  588      netsnmp_table_request_info *table_info, sunFmFaultStatus_data_t *statusp)
 589  589  {
 590  590          sunFmProblem_data_t     *data;
 591  591          sunFmFaultEvent_data_t  *rv;
 592  592          netsnmp_variable_list   *var;
 593  593          ulong_t                 index;
 594  594  
 595  595          for (;;) {
 596  596                  switch (table_info->number_indexes) {
 597  597                  case 2:
 598  598                  default:
 599  599                          DEBUGMSGTL((MODNAME_STR, "nextfe: 2 indices:\n"));
 600  600                          DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
 601  601                          DEBUGMSG((MODNAME_STR, "\n"));
 602  602                          DEBUGMSGVAR((MODNAME_STR,
 603  603                              table_info->indexes->next_variable));
 604  604                          DEBUGMSG((MODNAME_STR, "\n"));
 605  605                          index = *(ulong_t *)
 606  606                              table_info->indexes->next_variable->val.integer + 1;
 607  607  
 608  608                          if ((data = sunFmProblemTable_pr(reginfo,
 609  609                              table_info)) != NULL &&
 610  610                              (*statusp = faultstatus_lookup_index_exact(data,
 611  611                              index)) != 0 &&
 612  612                              (rv = faultevent_lookup_index_exact(data, index)) !=
 613  613                              NULL) {
 614  614                                  (void) snmp_set_var_typed_value(
 615  615                                      table_info->indexes->next_variable,
 616  616                                      ASN_UNSIGNED, (uchar_t *)&index,
 617  617                                      sizeof (index));
 618  618                                  return (rv);
 619  619                          }
 620  620  
 621  621                          if (sunFmProblemTable_nextpr(reginfo, table_info) ==
 622  622                              NULL)
 623  623                                  return (NULL);
 624  624                          break;
 625  625                  case 1:
 626  626                          if ((data = sunFmProblemTable_pr(reginfo,
 627  627                              table_info)) != NULL) {
 628  628                                  oid tmpoid[MAX_OID_LEN];
 629  629                                  index = 0;
 630  630  
 631  631                                  DEBUGMSGTL((MODNAME_STR, "nextfe: 1 index:\n"));
 632  632                                  DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
 633  633                                  DEBUGMSG((MODNAME_STR, "\n"));
 634  634                                  var =
 635  635                                      SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
 636  636                                  (void) snmp_set_var_typed_value(var,
 637  637                                      ASN_UNSIGNED, (uchar_t *)&index,
 638  638                                      sizeof (index));
 639  639                                  (void) memcpy(tmpoid, reginfo->rootoid,
 640  640                                      reginfo->rootoid_len * sizeof (oid));
 641  641                                  tmpoid[reginfo->rootoid_len] = 1;
 642  642                                  tmpoid[reginfo->rootoid_len + 1] =
 643  643                                      table_info->colnum;
 644  644                                  if (build_oid_segment(var) != SNMPERR_SUCCESS) {
 645  645                                          snmp_free_varbind(var);
 646  646                                          return (NULL);
 647  647                                  }
 648  648                                  snmp_free_varbind(
 649  649                                      table_info->indexes->next_variable);
 650  650                                  table_info->indexes->next_variable = var;
 651  651                                  table_info->number_indexes = 2;
 652  652                                  DEBUGMSGTL((MODNAME_STR, "nextfe: built fake "
 653  653                                      "index:\n"));
 654  654                                  DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
 655  655                                  DEBUGMSG((MODNAME_STR, "\n"));
 656  656                                  DEBUGMSGVAR((MODNAME_STR,
 657  657                                      table_info->indexes->next_variable));
 658  658                                  DEBUGMSG((MODNAME_STR, "\n"));
 659  659                          } else {
 660  660                                  if (sunFmProblemTable_nextpr(reginfo,
 661  661                                      table_info) == NULL)
 662  662                                          return (NULL);
 663  663                          }
 664  664                          break;
 665  665                  case 0:
 666  666                          if (sunFmProblemTable_nextpr(reginfo, table_info) ==
 667  667                              NULL)
 668  668                                  return (NULL);
 669  669                          break;
 670  670                  }
 671  671          }
 672  672  }
 673  673  
 674  674  static sunFmFaultEvent_data_t *
 675  675  sunFmFaultEventTable_fe(netsnmp_handler_registration *reginfo,
 676  676      netsnmp_table_request_info *table_info, sunFmFaultStatus_data_t *statusp)
 677  677  {
 678  678          sunFmProblem_data_t     *data;
 679  679  
 680  680          ASSERT(table_info->number_indexes == 2);
 681  681  
 682  682          if ((data = sunFmProblemTable_pr(reginfo, table_info)) == NULL)
 683  683                  return (NULL);
 684  684  
 685  685          *statusp = faultstatus_lookup_index_exact(data,
 686  686              *(ulong_t *)table_info->indexes->next_variable->val.integer);
 687  687          if (*statusp == 0)
 688  688                  return (NULL);
 689  689          return (faultevent_lookup_index_exact(data,
 690  690              *(ulong_t *)table_info->indexes->next_variable->val.integer));
 691  691  }
 692  692  
 693  693  /*ARGSUSED*/
 694  694  static void
 695  695  sunFmProblemTable_return(unsigned int reg, void *arg)
 696  696  {
 697  697          netsnmp_delegated_cache         *cache = (netsnmp_delegated_cache *)arg;
 698  698          netsnmp_request_info            *request;
 699  699          netsnmp_agent_request_info      *reqinfo;
 700  700          netsnmp_handler_registration    *reginfo;
 701  701          netsnmp_table_request_info      *table_info;
 702  702          sunFmProblem_data_t             *data;
 703  703  
 704  704          ASSERT(netsnmp_handler_check_cache(cache) != NULL);
 705  705  
 706  706          (void) pthread_mutex_lock(&update_lock);
 707  707          if (update_status != US_QUIET) {
 708  708                  struct timeval                  tv;
 709  709  
 710  710                  tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 711  711                  tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
 712  712  
 713  713                  (void) snmp_alarm_register_hr(tv, 0, sunFmProblemTable_return,
 714  714                      cache);
 715  715                  (void) pthread_mutex_unlock(&update_lock);
 716  716                  return;
 717  717          }
 718  718  
 719  719          request = cache->requests;
 720  720          reqinfo = cache->reqinfo;
 721  721          reginfo = cache->reginfo;
 722  722  
 723  723          table_info = netsnmp_extract_table_info(request);
 724  724          request->delegated = 0;
 725  725  
 726  726          ASSERT(table_info->colnum >= SUNFMPROBLEM_COLMIN);
 727  727          ASSERT(table_info->colnum <= SUNFMPROBLEM_COLMAX);
 728  728  
 729  729          /*
 730  730           * table_info->colnum contains the column number requested.
 731  731           * table_info->indexes contains a linked list of snmp variable
 732  732           * bindings for the indexes of the table.  Values in the list
 733  733           * have been set corresponding to the indexes of the
 734  734           * request.  We have other guarantees as well:
 735  735           *
 736  736           * - The column number is always within range.
 737  737           * - If we have no index data, table_info->index_oid_len is 0.
 738  738           * - We will never receive requests outside our table nor
 739  739           *   those with the first subid anything other than 1 (Entry)
 740  740           *   nor those without a column number.  This is true even
 741  741           *   for GETNEXT requests.
 742  742           */
 743  743  
 744  744          switch (reqinfo->mode) {
 745  745          case MODE_GET:
 746  746                  if ((data = sunFmProblemTable_pr(reginfo, table_info)) ==
 747  747                      NULL) {
 748  748                          netsnmp_free_delegated_cache(cache);
 749  749                          (void) pthread_mutex_unlock(&update_lock);
 750  750                          return;
 751  751                  }
 752  752                  break;
 753  753          case MODE_GETNEXT:
 754  754          case MODE_GETBULK:
 755  755                  if ((data = sunFmProblemTable_nextpr(reginfo, table_info)) ==
 756  756                      NULL) {
 757  757                          netsnmp_free_delegated_cache(cache);
 758  758                          (void) pthread_mutex_unlock(&update_lock);
 759  759                          return;
 760  760                  }
 761  761                  break;
 762  762          default:
 763  763                  (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
 764  764                      "mode %d\n", reqinfo->mode);
 765  765                  netsnmp_free_delegated_cache(cache);
 766  766                  (void) pthread_mutex_unlock(&update_lock);
 767  767                  return;
 768  768          }
 769  769  
 770  770          switch (table_info->colnum) {
 771  771          case SUNFMPROBLEM_COL_UUID:
 772  772          {
 773  773                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 774  774                      ASN_OCTET_STR, (uchar_t *)data->d_aci_uuid,
 775  775                      strlen(data->d_aci_uuid));
 776  776                  break;
 777  777          }
 778  778          case SUNFMPROBLEM_COL_CODE:
 779  779          {
 780  780                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 781  781                      ASN_OCTET_STR, (uchar_t *)data->d_aci_code,
 782  782                      strlen(data->d_aci_code));
 783  783                  break;
 784  784          }
 785  785          case SUNFMPROBLEM_COL_URL:
 786  786          {
 787  787                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 788  788                      ASN_OCTET_STR, (uchar_t *)data->d_aci_url,
 789  789                      strlen(data->d_aci_url));
 790  790                  break;
 791  791          }
 792  792          case SUNFMPROBLEM_COL_DIAGENGINE:
 793  793          {
 794  794                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 795  795                      ASN_OCTET_STR, (uchar_t *)data->d_diag_engine,
 796  796                      strlen(data->d_diag_engine));
 797  797                  break;
 798  798          }
 799  799          case SUNFMPROBLEM_COL_DIAGTIME:
 800  800          {
 801  801                  /*
 802  802                   * The date_n_time function is not Y2038-safe; this may
 803  803                   * need to be updated when a suitable Y2038-safe Net-SNMP
 804  804                   * API is available.
 805  805                   */
 806  806                  size_t  dt_size;
 807  807                  time_t  dt_time = (time_t)data->d_diag_time.tv_sec;
 808  808                  uchar_t *dt = date_n_time(&dt_time, &dt_size);
 809  809  
 810  810                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 811  811                      ASN_OCTET_STR, dt, dt_size);
 812  812                  break;
 813  813          }
 814  814          case SUNFMPROBLEM_COL_SUSPECTCOUNT:
 815  815          {
 816  816                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 817  817                      ASN_UNSIGNED, (uchar_t *)&data->d_nsuspects,
 818  818                      sizeof (data->d_nsuspects));
 819  819                  break;
 820  820          }
 821  821          default:
 822  822                  break;
 823  823          }
 824  824  
 825  825          netsnmp_free_delegated_cache(cache);
 826  826          (void) pthread_mutex_unlock(&update_lock);
 827  827  }
 828  828  
 829  829  static int
 830  830  sunFmProblemTable_handler(netsnmp_mib_handler *handler,
 831  831      netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
 832  832      netsnmp_request_info *requests)
 833  833  {
 834  834          netsnmp_request_info            *request;
 835  835          struct timeval                  tv;
 836  836  
 837  837          tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 838  838          tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
 839  839  
 840  840          request_update();
 841  841  
 842  842          for (request = requests; request; request = request->next) {
 843  843                  if (request->processed != 0)
 844  844                          continue;
 845  845  
 846  846                  if (netsnmp_extract_table_info(request) == NULL)
 847  847                          continue;
 848  848  
 849  849                  request->delegated = 1;
 850  850                  (void) snmp_alarm_register_hr(tv, 0,
 851  851                      sunFmProblemTable_return,
 852  852                      (void *) netsnmp_create_delegated_cache(handler, reginfo,
 853  853                      reqinfo, request, NULL));
 854  854          }
 855  855  
 856  856          return (SNMP_ERR_NOERROR);
 857  857  }
 858  858  
 859  859  /*ARGSUSED*/
 860  860  static void
 861  861  sunFmFaultEventTable_return(unsigned int reg, void *arg)
 862  862  {
 863  863          netsnmp_delegated_cache         *cache = (netsnmp_delegated_cache *)arg;
 864  864          netsnmp_request_info            *request;
 865  865          netsnmp_agent_request_info      *reqinfo;
 866  866          netsnmp_handler_registration    *reginfo;
 867  867          netsnmp_table_request_info      *table_info;
 868  868          sunFmProblem_data_t             *pdata;
 869  869          sunFmFaultEvent_data_t          *data;
 870  870          sunFmFaultStatus_data_t         status;
 871  871  
 872  872          ASSERT(netsnmp_handler_check_cache(cache) != NULL);
 873  873  
 874  874          (void) pthread_mutex_lock(&update_lock);
 875  875          if (update_status != US_QUIET) {
 876  876                  struct timeval                  tv;
 877  877  
 878  878                  tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
 879  879                  tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
 880  880  
 881  881                  (void) snmp_alarm_register_hr(tv, 0,
 882  882                      sunFmFaultEventTable_return, cache);
 883  883                  (void) pthread_mutex_unlock(&update_lock);
 884  884                  return;
 885  885          }
 886  886  
 887  887          request = cache->requests;
 888  888          reqinfo = cache->reqinfo;
 889  889          reginfo = cache->reginfo;
 890  890  
 891  891          table_info = netsnmp_extract_table_info(request);
 892  892          request->delegated = 0;
 893  893  
 894  894          ASSERT(table_info->colnum >= SUNFMFAULTEVENT_COLMIN);
 895  895          ASSERT(table_info->colnum <= SUNFMFAULTEVENT_COLMAX);
 896  896  
 897  897          /*
 898  898           * table_info->colnum contains the column number requested.
 899  899           * table_info->indexes contains a linked list of snmp variable
 900  900           * bindings for the indexes of the table.  Values in the list
 901  901           * have been set corresponding to the indexes of the
 902  902           * request.  We have other guarantees as well:
 903  903           *
 904  904           * - The column number is always within range.
 905  905           * - If we have no index data, table_info->index_oid_len is 0.
 906  906           * - We will never receive requests outside our table nor
 907  907           *   those with the first subid anything other than 1 (Entry)
 908  908           *   nor those without a column number.  This is true even
 909  909           *   for GETNEXT requests.
 910  910           */
 911  911  
 912  912          switch (reqinfo->mode) {
 913  913          case MODE_GET:
 914  914                  if ((data = sunFmFaultEventTable_fe(reginfo, table_info,
 915  915                      &status)) == NULL) {
 916  916                          netsnmp_free_delegated_cache(cache);
 917  917                          (void) pthread_mutex_unlock(&update_lock);
 918  918                          return;
 919  919                  }
 920  920                  break;
 921  921          case MODE_GETNEXT:
 922  922          case MODE_GETBULK:
 923  923                  if ((data = sunFmFaultEventTable_nextfe(reginfo, table_info,
 924  924                      &status)) == NULL) {
 925  925                          netsnmp_free_delegated_cache(cache);
 926  926                          (void) pthread_mutex_unlock(&update_lock);
 927  927                          return;
 928  928                  }
 929  929                  break;
 930  930          default:
 931  931                  (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
 932  932                      "mode %d\n", reqinfo->mode);
 933  933                  netsnmp_free_delegated_cache(cache);
 934  934                  (void) pthread_mutex_unlock(&update_lock);
 935  935                  return;
 936  936          }
 937  937  
 938  938          switch (table_info->colnum) {
 939  939          case SUNFMFAULTEVENT_COL_PROBLEMUUID:
 940  940          {
 941  941                  if ((pdata = sunFmProblemTable_pr(reginfo, table_info))
 942  942                      == NULL) {
 943  943                          (void) netsnmp_table_build_result(reginfo, request,
 944  944                              table_info, ASN_OCTET_STR, NULL, 0);
 945  945                          break;
 946  946                  }
 947  947                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 948  948                      ASN_OCTET_STR, (uchar_t *)pdata->d_aci_uuid,
 949  949                      strlen(pdata->d_aci_uuid));
 950  950                  break;
 951  951          }
 952  952          case SUNFMFAULTEVENT_COL_CLASS:
 953  953          {
 954  954                  char    *class = "-";
 955  955  
 956  956                  (void) nvlist_lookup_string(data, FM_CLASS, &class);
 957  957                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 958  958                      ASN_OCTET_STR, (uchar_t *)class, strlen(class));
 959  959                  break;
 960  960          }
 961  961          case SUNFMFAULTEVENT_COL_CERTAINTY:
 962  962          {
 963  963                  uint8_t pct = 0;
 964  964                  ulong_t pl;
 965  965  
 966  966                  (void) nvlist_lookup_uint8(data, FM_FAULT_CERTAINTY,
 967  967                      &pct);
 968  968                  pl = (ulong_t)pct;
 969  969                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 970  970                      ASN_UNSIGNED, (uchar_t *)&pl, sizeof (pl));
 971  971                  break;
 972  972          }
 973  973          case SUNFMFAULTEVENT_COL_ASRU:
 974  974          {
 975  975                  nvlist_t        *asru = NULL;
 976  976                  char            *fmri, *str;
 977  977  
 978  978                  (void) nvlist_lookup_nvlist(data, FM_FAULT_ASRU, &asru);
 979  979                  if ((str = sunFm_nvl2str(asru)) == NULL)
 980  980                          fmri = "-";
 981  981                  else
 982  982                          fmri = str;
 983  983  
 984  984                  (void) netsnmp_table_build_result(reginfo, request, table_info,
 985  985                      ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
 986  986                  free(str);
 987  987                  break;
 988  988          }
 989  989          case SUNFMFAULTEVENT_COL_FRU:
 990  990          {
 991  991                  nvlist_t        *fru = NULL;
 992  992                  char            *fmri, *str;
 993  993  
 994  994                  (void) nvlist_lookup_nvlist(data, FM_FAULT_FRU, &fru);
 995  995                  if ((str = sunFm_nvl2str(fru)) == NULL)
 996  996                          fmri = "-";
 997  997                  else
 998  998                          fmri = str;
 999  999  
1000 1000                  (void) netsnmp_table_build_result(reginfo, request, table_info,
1001 1001                      ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
1002 1002                  free(str);
1003 1003                  break;
1004 1004          }
1005 1005          case SUNFMFAULTEVENT_COL_RESOURCE:
1006 1006          {
1007 1007                  nvlist_t        *rsrc = NULL;
1008 1008                  char            *fmri, *str;
1009 1009  
1010 1010                  (void) nvlist_lookup_nvlist(data, FM_FAULT_RESOURCE, &rsrc);
1011 1011                  if ((str = sunFm_nvl2str(rsrc)) == NULL)
1012 1012                          fmri = "-";
1013 1013                  else
1014 1014                          fmri = str;
1015 1015  
1016 1016                  (void) netsnmp_table_build_result(reginfo, request, table_info,
1017 1017                      ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
1018 1018                  free(str);
1019 1019                  break;
1020 1020          }
1021 1021          case SUNFMFAULTEVENT_COL_STATUS:
1022 1022          {
1023 1023                  ulong_t pl = SUNFMFAULTEVENT_STATE_OTHER;
1024 1024  
1025 1025                  if (status & FM_SUSPECT_FAULTY)
1026 1026                          pl = SUNFMFAULTEVENT_STATE_FAULTY;
1027 1027                  else if (status & FM_SUSPECT_NOT_PRESENT)
1028 1028                          pl = SUNFMFAULTEVENT_STATE_REMOVED;
1029 1029                  else if (status & FM_SUSPECT_REPLACED)
1030 1030                          pl = SUNFMFAULTEVENT_STATE_REPLACED;
1031 1031                  else if (status & FM_SUSPECT_REPAIRED)
1032 1032                          pl = SUNFMFAULTEVENT_STATE_REPAIRED;
1033 1033                  else if (status & FM_SUSPECT_ACQUITTED)
1034 1034                          pl = SUNFMFAULTEVENT_STATE_ACQUITTED;
1035 1035                  (void) netsnmp_table_build_result(reginfo, request, table_info,
1036 1036                      ASN_INTEGER, (uchar_t *)&pl, sizeof (pl));
1037 1037                  break;
1038 1038          }
1039 1039          case SUNFMFAULTEVENT_COL_LOCATION:
1040 1040          {
1041 1041                  char    *location = "-";
1042 1042  
1043 1043                  (void) nvlist_lookup_string(data, FM_FAULT_LOCATION, &location);
1044 1044                  (void) netsnmp_table_build_result(reginfo, request, table_info,
1045 1045                      ASN_OCTET_STR, (uchar_t *)location, strlen(location));
1046 1046                  break;
1047 1047          }
1048 1048          default:
1049 1049                  break;
1050 1050          }
1051 1051  
1052 1052          netsnmp_free_delegated_cache(cache);
1053 1053          (void) pthread_mutex_unlock(&update_lock);
1054 1054  }
1055 1055  
1056 1056  static int
1057 1057  sunFmFaultEventTable_handler(netsnmp_mib_handler *handler,
1058 1058      netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
1059 1059      netsnmp_request_info *requests)
1060 1060  {
1061 1061          netsnmp_request_info            *request;
1062 1062          struct timeval                  tv;
1063 1063  
1064 1064          tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
1065 1065          tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
1066 1066  
1067 1067          request_update();
1068 1068  
1069 1069          for (request = requests; request; request = request->next) {
1070 1070                  if (request->processed != 0)
1071 1071                          continue;
1072 1072  
1073 1073                  if (netsnmp_extract_table_info(request) == NULL)
1074 1074                          continue;
1075 1075  
1076 1076                  request->delegated = 1;
1077 1077                  (void) snmp_alarm_register_hr(tv, 0,
1078 1078                      sunFmFaultEventTable_return,
1079 1079                      (void *) netsnmp_create_delegated_cache(handler, reginfo,
1080 1080                      reqinfo, request, NULL));
1081 1081          }
1082 1082  
1083 1083          return (SNMP_ERR_NOERROR);
1084 1084  }
  
    | 
      ↓ open down ↓ | 
    535 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX