Пример #1
0
/* Remove sub-node(s) in mib-tree. */
static void
__mib_tree_delete(struct node_pair *pair)
{
  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 = pair->child;
  struct mib_group_node *gn;
  struct mib_instance_node *in;

  if (node == (struct mib_node *)&mib_dummy_node) {
    SMARTSNMP_LOG(L_WARNING, "MIB dummy root node cannot be deleted!\n");
    return;
  }

  /* Init something */
  p_nbl = NULL;
  stk_top = stk_buttom = nbl_stk;

  for (; ;) {

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

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)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) {
          /* Sub-tree is empty, delete this node and go on backtracking */
          mib_group_node_delete(gn);
          break;
        }

        if (i + 1 >= gn->sub_id_cnt) {
          /* Last sub-id, mark n_idx = -1. */
          nbl.n_idx = -1;
        } else {
          nbl.n_idx = i + 1;
        }
        nbl.node = node;

        /* Backlog the current node and move down. */
        nbl_push(&nbl, &stk_top, &stk_buttom);
        node = gn->sub_ptr[i++];
        continue;

      case MIB_OBJ_INSTANCE:
        in = (struct mib_instance_node *)node;
        mib_instance_node_delete(in);
        break;

      default :
        assert(0);
    }

    /* Backtracking */
    p_nbl = nbl_pop(&stk_top, &stk_buttom);
    if (p_nbl == NULL) {
      /* End of traversal. */
      group_node_shrink((struct mib_group_node *)pair->parent, pair->sub_idx);
      return;
    }
    node = p_nbl->node;
  }
}
Пример #2
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. */
  }
}
Пример #3
0
/* Remove specified node int mib-tree. */
static void
__mib_tree_delete(struct node_pair *pair)
{
  struct node_backlog nbl, *p_nbl;
  struct node_backlog nbl_stk[NBL_STACK_SIZE];
  struct node_backlog *stk_top, *stk_buttom;

  struct mib_node *node = pair->child;
  struct mib_group_node *gn;
  struct mib_instance_node *in;

  /* Internet group is the dummy root node */
  if (node == (struct mib_node *)&internet_group) {
    CREDO_SNMP_LOG(SNMP_LOG_WARNING, "OID .1.3.6.1 is the dummy root node in this mib tree which cannot be deleted.\n");
    return;
  }

  /* Init something */
  p_nbl = NULL;
  stk_top = stk_buttom = nbl_stk;

  for (; ;) {

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

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)node;

        int i;
        if (p_nbl != NULL) {
          /* That pop-up backlog recorded the next index. */
          i = p_nbl->n_idx;
          p_nbl = NULL;
        } else {
          /* Else we get the first sub-id. */
          i = 0;
        }

        if (i == -1) {
          /* All sub-trees empty, free this node and go on backtracking */
          mib_group_node_delete(gn);
          break;
        }

        do {
          if (i + 1 >= gn->sub_id_cnt) {
            /* Last sub-id, mark n_idx = -1. */
            nbl.n_idx = -1;
          } else {
            nbl.n_idx = i + 1;
          }
          nbl.node = node;
          node = gn->sub_ptr[i++];
        } while (node == NULL && i < gn->sub_id_cnt);

        /* Backlog the current node and move down. */
        nbl_push(&nbl, &stk_top, &stk_buttom);
        continue;

      case MIB_OBJ_INSTANCE:
        in = (struct mib_instance_node *)node;
        mib_instance_node_delete(in);
        break;

      default :
        assert(0);
        break;
    }

    /* Backtracking */
    p_nbl = nbl_pop(&stk_top, &stk_buttom);
    if (p_nbl == NULL) {
      /* End of traversal. */
      group_node_shrink((struct mib_group_node *)pair->parent, pair->sub_idx);
      return;
    }
    node = p_nbl->node;
  }
}
Пример #4
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;
}
Пример #5
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;
  const oid_t dummy_oid[] = { 1, 3, 6, 1 };
  uint32_t id_len;
  uint8_t immediate; /* This is the search state machine */

  struct node_backlog nbl, *p_nbl;
  struct node_backlog nbl_stk[NBL_STACK_SIZE];
  struct node_backlog *stk_top, *stk_buttom;

  struct mib_node *node;
  struct mib_group_node *gn;
  struct mib_instance_node *in;

  /* Init something first */
  stk_top = stk_buttom = nbl_stk;
  node = (struct mib_node *)&internet_group;
  p_nbl = NULL;

  /* Check dummy root oid prefix */
  if (orig_id_len > INTERNET_PREFIX_LENGTH) {
    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, OID_ARRAY_SIZE(dummy_oid), dummy_oid, OID_ARRAY_SIZE(dummy_oid)) > 0) {
      /* END_OF_MIB_VIEW */
      oid = ret_oid->oid + orig_id_len;
      id_len = ret_oid->id_len - orig_id_len;
      node = NULL;
    } else {
      oid = ret_oid->oid + INTERNET_PREFIX_LENGTH;
      id_len = ret_oid->id_len - INTERNET_PREFIX_LENGTH;
    }
  } else {
    immediate = 1;  /* 1 is to get the immediate closest instance */
    if (oid_cmp(orig_oid, orig_id_len, dummy_oid, OID_ARRAY_SIZE(dummy_oid)) > 0) {
      /* END_OF_MIB_VIEW */
      ret_oid->oid = oid_dup(orig_oid, orig_id_len);
      ret_oid->id_len = orig_id_len;
      oid = ret_oid->oid + orig_id_len;
      id_len = ret_oid->id_len - orig_id_len;
      node = NULL;
    } else {
      ret_oid->oid = oid_dup(dummy_oid, OID_ARRAY_SIZE(dummy_oid));
      ret_oid->id_len = OID_ARRAY_SIZE(dummy_oid);
      oid = ret_oid->oid + INTERNET_PREFIX_LENGTH;
      id_len = ret_oid->id_len - INTERNET_PREFIX_LENGTH;
    }
  }
  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) {
          /* Get the immediate closest instance. */
          int i;

          if (p_nbl != NULL) {
            /* That pop-up backlog recorded the next index. */
            i = p_nbl->n_idx;
            p_nbl = NULL;
          } else {
            /* else we fetch the immediate 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, oid matching is ignored since here */
            immediate = 1;

            /* Reverse the sign to locate the next sub-id. */
            i = -i - 1;
            if (i == gn->sub_id_cnt) {
              /* All sub-ids are greater than target;
               * Backtrack and get the next one. */
              break;
            } else if (i == 0) {
              /* 1. All sub-ids are less than target;
               * 2. No sub-id in this group node;
               * Just switch to immediate 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 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) {
          /* Get the first instance */
          ret_oid->inst_id_len = 0;
        } else {
          /* Search the closest instance whose oid greater than target */
          ret_oid->inst_id_len = id_len;
        }

        /* Find instance */
        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->id_len = oid - ret_oid->oid + ret_oid->inst_id_len;
          assert(ret_oid->id_len <= MIB_OID_MAX_LEN);
          return node;
        }

        break;  /* Instance not found */

      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. */
      ret_oid->id_len = oid - ret_oid->oid;
      ret_oid->inst_id = NULL;
      ret_oid->inst_id_len = 0;
      ret_oid->exist_state = BER_TAG_END_OF_MIB_VIEW;
      return (struct mib_node *)&internet_group;
    }
    oid--;  /* OID length is ignored once backtracking. */
    node = p_nbl->node;
    immediate = 1;  /* Switch to the 'immediate' mode. */
  }

  assert(0);
  return node;
}