Example #1
0
/* GETNEXT request search, depth-first traversal in mib-tree, find the closest next oid. */
void
mib_tree_search_next(struct mib_view *view, const oid_t *orig_oid, uint32_t orig_id_len, struct oid_search_res *ret_oid)
{
  oid_t *oid;
  uint32_t id_len;
  struct node_backlog nbl, *p_nbl;
  struct node_backlog nbl_stk[MIB_OID_MAX_LEN];
  struct node_backlog *stk_top, *stk_buttom;
  struct mib_node *node;
  struct mib_group_node *gn;
  struct mib_instance_node *in;
  /* 'immediate' is the search state indicator.
   * 0 is to get the matched instance according to the given oid;
   * 1 is to get the immediate first instance regardless of the given oid. */
  uint8_t immediate = 0;

  assert(view != NULL && orig_oid != NULL && ret_oid != NULL);

  /* Access control */
  if (oid_cover(view->oid, view->id_len, orig_oid, orig_id_len) > 0) {
    /* In the range of view, search the root node at view oid */
    ret_oid->request = MIB_REQ_GET;
    node = mib_tree_search(view, view->oid, view->id_len, ret_oid);
    assert(node != NULL);
    ret_oid->request = MIB_REQ_GETNEXT;
    /* Duplicate the given oid */
    oid_cpy(ret_oid->oid, orig_oid, orig_id_len);
    ret_oid->id_len = orig_id_len;
    if (ret_oid->id_len > ret_oid->inst_id - ret_oid->oid) {
      /* Given oid is longer than the search result's, we need to search according to the given oid */
      immediate = 0;
    } else {
      /* Otherwise, ignore the given oid */
      immediate = 1;
    }
  } else {
    /* Out of range of view */
    if (oid_cmp(orig_oid, orig_id_len, view->oid, view->id_len) < 0) {
      /* Given oid is ahead of view, search the root node at view oid */
      ret_oid->request = MIB_REQ_GET;
      node = mib_tree_search(view, view->oid, view->id_len, ret_oid);
      assert(node != NULL);
      ret_oid->request = MIB_REQ_GETNEXT;
      /* Set the search mode according to node type */
      if (node->type == MIB_OBJ_GROUP) {
        immediate = 1;
      } else {
        immediate = 0;
      }
    } else {
      /* END_OF_MIB_VIEW */
      node = NULL;
      ret_oid->oid = oid_dup(view->oid, view->id_len);
      ret_oid->id_len = view->id_len;
    }
  }

  /* Init something */
  p_nbl = NULL;
  stk_top = stk_buttom = nbl_stk;
  ret_oid->err_stat = 0;
  oid = ret_oid->inst_id;
  id_len = ret_oid->id_len - (oid - ret_oid->oid);

  for (; ;) {

    if (node != NULL) {
      switch (node->type) {

        case MIB_OBJ_GROUP:
          gn = (struct mib_group_node *)node;
          if (immediate) {
            /* Fetch the immediate instance node. */
            int i;
            if (p_nbl != NULL) {
              /* Fetch the sub-id next to the pop-up backlogged one. */
              i = p_nbl->n_idx;
              p_nbl = NULL;
            } else {
              /* Fetch the first sub-id. */
              i = 0;
            }

            if (i + 1 >= gn->sub_id_cnt) {
              /* Last sub-id, mark NULL and -1. */
              nbl.node = NULL;
              nbl.n_idx = -1;
            } else {
              nbl.node = node;
              nbl.n_idx = i + 1;
            }
            /* Backlog the current node and move on. */
            nbl_push(&nbl, &stk_top, &stk_buttom);
            *oid++ = gn->sub_id[i];
            node = gn->sub_ptr[i];
          } else {
            /* Search the match sub-id */
            int index = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
            int i = index;
            if (index < 0) {
              /* Not found, switch to the immediate search mode */
              immediate = 1;
              /* Reverse the sign to locate the right position. */
              i = -i - 1;
              if (i == gn->sub_id_cnt) {
                /* All sub-ids are greater than the target;
                 * Backtrack and fetch the next one. */
                break;
              } else if (i == 0) {
                /* 1. All sub-ids are less than the target;
                 * 2. No sub-id in this group node;
                 * Just switch to the immediate search mode */
                continue;
              } /* else {
                   Target is between the two sub-ids and [i] is the next one,
                   switch to immediate mode and move on.
              } */
            }

            /* Sub-id found is greater or just equal to the target,
             * Anyway, record the next node and push it into stack. */
            if (i + 1 >= gn->sub_id_cnt) {
              /* Last sub-id, mark NULL and -1. */
              nbl.node = NULL;
              nbl.n_idx = -1;
            } else {
              nbl.node = node;
              nbl.n_idx = i + 1;
            }

            /* Backlog the current node and move on. */
            nbl_push(&nbl, &stk_top, &stk_buttom);
            *oid++ = gn->sub_id[i];
            node = gn->sub_ptr[i];
            if (--id_len == 0 && node->type == MIB_OBJ_GROUP) {
              /* When oid length is decreased to zero, switch to the immediate mode */
              immediate = 1;
            }
          }

          continue; /* Go on loop */

        case MIB_OBJ_INSTANCE:
          in = (struct mib_instance_node *)node;
          if (immediate || id_len == 0) {
            /* Fetch the first instance variable */
            ret_oid->inst_id_len = 0;
          } else {
            /* Search the closest instance whose oid is greater than the target */
            ret_oid->inst_id_len = id_len;
          }
          /* Find instance variable through lua handler function */
          ret_oid->inst_id = oid;
          ret_oid->callback = in->callback;
          ret_oid->err_stat = mib_instance_search(ret_oid);
          if (MIB_TAG_VALID(tag(&ret_oid->var))) {
            ret_oid->id_len = oid - ret_oid->oid + ret_oid->inst_id_len;
            assert(ret_oid->id_len <= MIB_OID_MAX_LEN);
            if (!oid_cover(view->oid, view->id_len, ret_oid->oid, ret_oid->id_len)) {
              /* End of mib view */
              break;
            }
            return;
          } else {
            /* Instance not found */
            break;
          }

        default:
          assert(0);
      }
    }

    /* Backtracking condition:
     * 1. No greater sub-id in group node;
     * 2. Seek the immediate closest instance node;
     * 3. Node not exists(node == NULL).
     */
    p_nbl = nbl_pop(&stk_top, &stk_buttom);
    if (p_nbl == NULL) {
      /* End of traversal. */
      oid_cpy(ret_oid->oid, orig_oid, orig_id_len);
      ret_oid->id_len = orig_id_len;
      ret_oid->inst_id = NULL;
      ret_oid->inst_id_len = 0;
      ret_oid->err_stat = 0;
      tag(&ret_oid->var) = ASN1_TAG_END_OF_MIB_VIEW;
      return;
    }
    oid--;  /* OID length is ignored once backtracking. */
    node = p_nbl->node;
    immediate = 1;  /* Switch to the immediate search mode. */
  }
}
Example #2
0
/* GETNEXT request search, depth-first traversal in mib-tree, find the closest next oid. */
struct mib_node *
mib_tree_search_next(const oid_t *orig_oid, uint32_t orig_id_len, struct oid_search_res *ret_oid)
{
  oid_t *oid;
  uint32_t id_len;
  uint8_t immediate; /* This is the search state indicator */
  struct node_backlog nbl, *p_nbl;
  struct node_backlog nbl_stk[MIB_OID_MAX_LEN];
  struct node_backlog *stk_top, *stk_buttom;
  struct oid_search_res tmp_res;
  struct mib_node *node;
  struct mib_group_node *gn;
  struct mib_instance_node *in;

  /* Check dummy root oid prefix */
  if (orig_id_len > root_oid_len) {
    immediate = 0;  /* 0 is to search the first match node in mib tree. */
    ret_oid->oid = oid_dup(orig_oid, orig_id_len);
    ret_oid->id_len = orig_id_len;
    if (oid_cmp(orig_oid, root_oid_len, root_oid, root_oid_len) > 0) {
      /* END_OF_MIB_VIEW */
      node = NULL;
    } else {
      node = mib_tree_search(root_oid, root_oid_len, &tmp_res);
      free(tmp_res.oid);
    }
  } else {
    immediate = 1;  /* 1 is to get the immediate closest instance */
    ret_oid->oid = oid_dup(root_oid, root_oid_len);
    ret_oid->id_len = root_oid_len;
    if (oid_cmp(orig_oid, orig_id_len, root_oid, root_oid_len) > 0) {
      /* END_OF_MIB_VIEW */
      node = NULL;
    } else {
      node = mib_tree_search(root_oid, root_oid_len, &tmp_res);
      free(tmp_res.oid);
    }
  }

  /* Init something */
  p_nbl = NULL;
  stk_top = stk_buttom = nbl_stk;
  oid = ret_oid->oid + root_oid_len;
  id_len = ret_oid->id_len - root_oid_len;
  ret_oid->inst_id = NULL;
  ret_oid->inst_id_len = 0;
  ret_oid->exist_state = 0;

  for (; ;) {

    if (node != NULL)
    switch (node->type) {

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)node;
        if (immediate) {
          /* Fetch the immediate instance node. */
          int i;
          if (p_nbl != NULL) {
            /* Fetch the sub-id next to the pop-up backlogged one. */
            i = p_nbl->n_idx;
            p_nbl = NULL;
          } else {
            /* Fetch the first sub-id. */
            i = 0;
          }

          if (i + 1 >= gn->sub_id_cnt) {
            /* Last sub-id, mark NULL and -1. */
            nbl.node = NULL;
            nbl.n_idx = -1;
          } else {
            nbl.node = node;
            nbl.n_idx = i + 1;
          }
          /* Backlog the current node and move on. */
          nbl_push(&nbl, &stk_top, &stk_buttom);
          *oid++ = gn->sub_id[i];
          node = gn->sub_ptr[i];
        } else {
          /* Search the match sub-id */
          int index = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
          int i = index;
          if (index < 0) {
            /* Not found, switch to the immediate search mode */
            immediate = 1;
            /* Reverse the sign to locate the right position. */
            i = -i - 1;
            if (i == gn->sub_id_cnt) {
              /* All sub-ids are greater than the target;
               * Backtrack and fetch the next one. */
              break;
            } else if (i == 0) {
              /* 1. All sub-ids are less than the target;
               * 2. No sub-id in this group node;
               * Just switch to the immediate search mode */
              continue;
            } /* else {
              Target is between the two sub-ids and [i] is the next one,
              switch to immediate mode and move on.
            } */
          }

          /* Sub-id found is greater or just equal to the target,
           * Anyway, record the next node and push it into stack. */
          if (i + 1 >= gn->sub_id_cnt) {
            /* Last sub-id, mark NULL and -1. */
            nbl.node = NULL;
            nbl.n_idx = -1;
          } else {
            nbl.node = node;
            nbl.n_idx = i + 1;
          }

          /* Backlog the current node and move on. */
          nbl_push(&nbl, &stk_top, &stk_buttom);
          *oid++ = gn->sub_id[i];
          node = gn->sub_ptr[i];
          if (--id_len == 0 && node->type == MIB_OBJ_GROUP) {
            /* When oid length is decreased to zero, switch to the immediate mode */
            immediate = 1;
          }
        }

        continue; /* Go on loop */

      case MIB_OBJ_INSTANCE:
        in = (struct mib_instance_node *)node;
        if (immediate || id_len == 0) {
          /* Fetch the first instance variable */
          ret_oid->inst_id_len = 0;
        } else {
          /* Search the closest instance whose oid is greater than the target */
          ret_oid->inst_id_len = id_len;
        }
        /* Find instance variable through lua handler function */
        ret_oid->inst_id = oid;
        ret_oid->callback = in->callback;
        ret_oid->exist_state = mib_instance_search(ret_oid);
        if (ret_oid->exist_state == 0 || ret_oid->exist_state < ASN1_TAG_NO_SUCH_OBJ) {
          ret_oid->id_len = oid - ret_oid->oid + ret_oid->inst_id_len;
          assert(ret_oid->id_len <= MIB_OID_MAX_LEN);
          return node;
        } else {
          /* Instance not found */
          break;
        }

      default:
        assert(0);
    }

    /* Backtracking condition:
     * 1. No greater sub-id in group node;
     * 2. Seek the immediate closest instance node;
     * 3. Node not exists(node == NULL).
     */
    p_nbl = nbl_pop(&stk_top, &stk_buttom);
    if (p_nbl == NULL) {
      /* End of traversal. */
      oid_cpy(ret_oid->oid, orig_oid, orig_id_len);
      ret_oid->id_len = orig_id_len;
      ret_oid->inst_id = NULL;
      ret_oid->inst_id_len = 0;
      ret_oid->exist_state = ASN1_TAG_END_OF_MIB_VIEW;
      return (struct mib_node *)&mib_dummy_node;
    }
    oid--;  /* OID length is ignored once backtracking. */
    node = p_nbl->node;
    immediate = 1;  /* Switch to the immediate search mode. */
  }

  assert(0);
  return node;
}