Ejemplo n.º 1
0
/* Find node through oid and get its parent. */
static struct mib_node *
mib_tree_node_search(const oid_t *oid, uint32_t id_len, struct node_pair *pair)
{
  struct mib_group_node *gn;
  struct mib_node *parent = pair->parent = (struct mib_node *)&internet_group;
  struct mib_node *node = pair->child = parent;
  int sub_idx = 0;

  /* Internet group is the dummy root node */
  if (id_len < INTERNET_PREFIX_LENGTH)
    return NULL;

  oid += INTERNET_PREFIX_LENGTH;
  id_len -= INTERNET_PREFIX_LENGTH;

  while (node != NULL && id_len > 0) {
    switch (node->type) {

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)node;
        int i = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
        if (i >= 0) {
          /* Sub-id found, go on loop */
          oid++;
          id_len--;
          sub_idx = i;
          parent = node;
          node = gn->sub_ptr[i];
          continue;
        } else {
          /* Sub-id not found */
          pair->parent = parent;
          pair->child = node;
          pair->sub_idx = sub_idx;
          return NULL;
        }

      case MIB_OBJ_INSTANCE:
        pair->parent = parent;
        pair->child = node;
        pair->sub_idx = sub_idx;
        if (id_len != 1) {
          return NULL;
        }
        return node;

      default:
        assert(0);
        break;
    }
  }

  /* node == NULL || id_len == 0 */
  /* Note: If target oid is the internet group node, then
   * pair->parent == pair->child and pair->sub_idx == 0 */
  pair->parent = parent;
  pair->child = node;
  pair->sub_idx = sub_idx;
  return node;
}
Ejemplo n.º 2
0
/* This function creates one new instance node in mib-tree according to given
 * oid in which the last id number is the first id of the instance. Id number
 * before the last one are regarded as exist group node(s) by default.
 */
static struct mib_instance_node *
mib_tree_instance_insert(const oid_t *oid, uint32_t id_len, const char *lua_callback)
{
  struct mib_node *node;
  struct mib_group_node *gn;

  node = (struct mib_node *)&internet_group;
  oid += INTERNET_PREFIX_LENGTH;
  id_len -= INTERNET_PREFIX_LENGTH;

  while (node != NULL && id_len > 0) {
    switch (node->type) {

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)node;
        if (is_raw_group_node(gn) && id_len == 1) {
          /* Allocate intermediate group node */
          gn->sub_ptr[0] = mib_instance_node_new(lua_callback);
          gn->sub_id[0] = *oid;
          gn->sub_id_cnt++;
          return gn->sub_ptr[0];
        } else {
          /* Search in exist sub-ids */
          int i = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
          if (i >= 0) {
            /* Sub-id found, go on traversing */
            oid++;
            id_len--;
            node = gn->sub_ptr[i];
            continue;
          } else {
            /* Sub-id not found, that's it. */
            i = -i - 1;
            if (id_len == 1) {
              /* The last only oid is for the new instance node */
              group_node_resize(gn, i);
              gn->sub_ptr[i] = mib_instance_node_new(lua_callback);
              gn->sub_id[i] = *oid;
              gn->sub_id_cnt++;
              return gn->sub_ptr[i];
            }
          }
        }

      case MIB_OBJ_INSTANCE:
        /* Bad traversal */
        return NULL;

      default:
        assert(0);
        break;
    }
  }

  /* Bad traversal */
  return NULL;
}
Ejemplo n.º 3
0
/* This function will create an instance node in mib-tree according to oid given
 * in which the prefix can be already created or not existing group node(s), and
 * the last id number must be the not existing instance node.
 */
static struct mib_instance_node *
mib_tree_instance_insert(const oid_t *oid, uint32_t id_len, int callback)
{
  struct mib_node *node = (struct mib_node *)&mib_dummy_node;
  struct mib_group_node *gn;

  while (id_len > 0) {
    switch (node->type) {

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

        if (is_raw_group(gn)) {
          gn->sub_id_cnt++;
          gn->sub_id[0] = *oid++;
          if (--id_len == 0) {
            /* Allocate new instance node */
            node = gn->sub_ptr[0] = mib_instance_node_new(callback);
            return (struct mib_instance_node *)node;
          } else {
            /* Allocate new group node */
            node = gn->sub_ptr[0] = mib_group_node_new();
          }
        } else {
          /* Search in exist sub-ids */
          int i = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
          if (i >= 0) {
            /* Sub-id found, go on traversing */
            oid++;
            id_len--;
            node = gn->sub_ptr[i];
          } else {
            /* Sub-id not found, that's it. */
            i = -i - 1;
            /* resize sub_id[] */
            group_node_expand(gn, i);
            gn->sub_id_cnt++;
            gn->sub_id[i] = *oid++;
            if (--id_len == 0) {
              /* Allocate new instance node */
              node = gn->sub_ptr[i] = mib_instance_node_new(callback);
              return (struct mib_instance_node *)node;
            } else {
              /* Allocate new group node */
              node = gn->sub_ptr[i] = mib_group_node_new();
            }
          }
        }
        continue;

      case MIB_OBJ_INSTANCE:
        /* Bad traversal */
        return NULL;

      default:
        assert(0);
    }
  }

  /* Bad traversal */
  return NULL;
}
Ejemplo n.º 4
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. */
  }
}
Ejemplo n.º 5
0
/* GET request search, depth-first traversal in mib-tree, oid must match */
struct mib_node *
mib_tree_search(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 mib_node *node;
  struct mib_group_node *gn;
  struct mib_instance_node *in;

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

  /* Duplicate OID as return value */
  ret_oid->oid = oid_dup(orig_oid, orig_id_len);
  ret_oid->id_len = orig_id_len;
  ret_oid->err_stat = 0;

  /* Access control */
  if (oid_cover(view->oid, view->id_len, orig_oid, orig_id_len) <= 0) {
    /* Out of range of view */
    tag(&ret_oid->var) = ASN1_TAG_NO_SUCH_OBJ;
    return NULL;
  }

  /* Init something */
  node = (struct mib_node *)&mib_dummy_node;
  oid = ret_oid->oid;
  id_len = ret_oid->id_len;

  while (node != NULL && id_len > 0) {
    switch (node->type) {

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)node;
        int i = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
        if (i >= 0) {
          /* Sub-id found, go on loop */
          oid++;
          id_len--;
          node = gn->sub_ptr[i];
          continue;
        } else {
          /* Sub-id not found */
          ret_oid->inst_id = oid;
          ret_oid->inst_id_len = id_len;
          tag(&ret_oid->var) = ASN1_TAG_NO_SUCH_OBJ;
          return node;
        }

      case MIB_OBJ_INSTANCE:
        in = (struct mib_instance_node *)node;
        /* Find instance variable through lua handler function */
        ret_oid->inst_id = oid;
        ret_oid->inst_id_len = id_len;
        ret_oid->callback = in->callback;
        ret_oid->err_stat = mib_instance_search(ret_oid);
        return node;

      default:
        assert(0);
    }
  }

  /* node == NULL || id_len == 0 */
  ret_oid->inst_id = oid;
  ret_oid->inst_id_len = id_len;
  if (node && node->type == MIB_OBJ_INSTANCE) {
    tag(&ret_oid->var) = ASN1_TAG_NO_SUCH_INST;
  } else {
    tag(&ret_oid->var) = ASN1_TAG_NO_SUCH_OBJ;
  }
  return node;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/* GET request search, depth-first traversal in mib-tree, oid must match */
struct mib_node *
mib_tree_search(const oid_t *orig_oid, uint32_t orig_id_len, struct oid_search_res *ret_oid)
{
  struct mib_node *node;
  struct mib_group_node *gn;
  struct mib_instance_node *in;
  oid_t *oid;
  uint32_t id_len;

  /* Duplicate OID as return */
  ret_oid->oid = oid_dup(orig_oid, orig_id_len);
  ret_oid->id_len = orig_id_len;
  ret_oid->exist_state = 0;

  /* Check dummy root oid prefix */
  if (orig_id_len < INTERNET_PREFIX_LENGTH) {
    node = NULL;
    oid = NULL;
    id_len = 0;
  } else {
    node = (struct mib_node *)&internet_group;
    oid = ret_oid->oid + INTERNET_PREFIX_LENGTH;
    id_len = ret_oid->id_len - INTERNET_PREFIX_LENGTH;
  }

  while (node != NULL && id_len > 0) {
    switch (node->type) {

      case MIB_OBJ_GROUP:
        gn = (struct mib_group_node *)node;
        int i = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
        if (i >= 0) {
          /* Sub-id found, go on loop */
          oid++;
          id_len--;
          node = gn->sub_ptr[i];
          continue;
        } else {
          /* Sub-id not found */
          ret_oid->inst_id = oid;
          ret_oid->inst_id_len = id_len;
          ret_oid->exist_state = BER_TAG_NO_SUCH_OBJ;
          return node;
        }

      case MIB_OBJ_INSTANCE:
        in = (struct mib_instance_node *)node;
        /* Find the instance */
        ret_oid->inst_id = oid;
        ret_oid->inst_id_len = id_len;
        ret_oid->callback = in->callback;
        ret_oid->exist_state = mib_instance_search(ret_oid);
        return node;

      default:
        assert(0);
    }
  }

  /* node == NULL || id_len == 0 */
  ret_oid->inst_id = oid;
  ret_oid->inst_id_len = id_len;
  if (node && node->type == MIB_OBJ_INSTANCE) {
    ret_oid->exist_state = BER_TAG_NO_SUCH_INST;
  } else {
    ret_oid->exist_state = BER_TAG_NO_SUCH_OBJ;
  }
  return node;
}
Ejemplo n.º 8
0
/* This function create group node(s) in mib-tree according to oid given in
 * which the prefix can be already created as group node(s) and the last id
 * number must not be created yet. the id number before the last one will be
 * created as new dummy group node(s).
 */
static struct mib_group_node *
mib_tree_group_insert(const oid_t *oid, uint32_t id_len)
{
  struct mib_node *node;
  struct mib_group_node *gn;
  struct node_pair pair;

  /* Init something */
  pair.parent = pair.child = NULL;
  node = (struct mib_node *)&internet_group;
  oid += INTERNET_PREFIX_LENGTH;
  id_len -= INTERNET_PREFIX_LENGTH;

  while (id_len > 0) {
    switch (node->type) {

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

        if (is_raw_group_node(gn)) {
          /* Allocate intermediate group node */
          node = gn->sub_ptr[0] = mib_group_node_new();
          gn->sub_id_cnt++;
          gn->sub_id[0] = *oid++;
          id_len--;
        } else {
          /* Search in exist sub-ids */
          int i = oid_binary_search(gn->sub_id, gn->sub_id_cnt, *oid);
          if (i >= 0) {
            /* Sub-id found, go on traversing */
            oid++;
            id_len--;
            node = gn->sub_ptr[i];
          } else {
            /* Sub-id not found, that's it. */
            i = -i - 1;
            /* realloc sub_id[] */
            group_node_resize(gn, i);
            /* Allocate new group node */
            node = gn->sub_ptr[i] = mib_group_node_new();
            gn->sub_id_cnt++;
            gn->sub_id[i] = *oid++;
            id_len--;
            /* Record the new allocated root group node */
            if (pair.child == NULL && pair.parent == NULL) {
              pair.parent = (struct mib_node *)gn;
              pair.child = (struct mib_node *)node;
              pair.sub_idx = i;
            }
          }
        }
        continue;

      case MIB_OBJ_INSTANCE:
        /* Bad traversal, clear all temporarily built group nodes */
        __mib_tree_delete(&pair);
        return NULL;

      default:
        assert(0);
        break;
    }
  }

  /* id_len == 0 */
  return (struct mib_group_node *)node;
}
Ejemplo n.º 9
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;
}