int oid_cover(const oid_t *oid1, uint32_t len1, const oid_t *oid2, uint32_t len2) { if (len1 <= len2 && !oid_cmp(oid1, len1, oid2, len1)) { /* oid1 covers oid2 */ return 1; } else if (len2 <= len1 && !oid_cmp(oid1, len2, oid2, len2)) { /* oid2 covers oid1 */ return -1; } else { return 0; } }
/* Register one instance node in mib-tree according to given oid with lua callback. */ int mib_node_reg(const oid_t *oid, uint32_t len, int callback) { int i; struct mib_instance_node *in; mib_tree_init_check(); /* Prefix must match root oid */ if (len < root_oid_len || oid_cmp(oid, root_oid_len, root_oid, root_oid_len)) { return -1; } if (len > MIB_OID_MAX_LEN) { SMARTSNMP_LOG(L_WARNING, "The length of oid cannot be longer than %d\n", MIB_OID_MAX_LEN); return -1; } in = mib_tree_instance_insert(oid, len, callback); if (in == NULL) { SMARTSNMP_LOG(L_WARNING, "Register oid: "); for (i = 0; i < len; i++) { SMARTSNMP_LOG(L_WARNING, "%d ", oid[i]); } SMARTSNMP_LOG(L_WARNING, "fail, node already exists or oid overlaps.\n"); return -1; } return 0; }
/* * Find an object in the MIB corresponding to the oid in the snmp-get request. */ mib_object_t* mib_get(varbind_t* req) { u16t oid_len; mib_iterator_init(); while (!mib_iterator_is_end()) { oid_len = oid_length(ptr->varbind.oid_ptr); if (!GET_NEXT_OID_PTR) { // scalar if (oid_len == req->oid_ptr->len && !oid_cmp(req->oid_ptr, ptr->varbind.oid_ptr)) { break; } /* check noSuchInstance */ if (oid_len - 1 <= req->oid_ptr->len + 1 && !oid_cmpn(req->oid_ptr, ptr->varbind.oid_ptr, oid_len - 1)) { req->value_type = BER_TYPE_NO_SUCH_INSTANCE; snmp_log("noSuchInstance\n"); return 0; } } if (GET_NEXT_OID_PTR && oid_len < req->oid_ptr->len && !oid_cmp(req->oid_ptr, ptr->varbind.oid_ptr)) { // tabular break; } mib_iterator_next(); } if (mib_iterator_is_end()) { req->value_type = BER_TYPE_NO_SUCH_OBJECT; snmp_log("noSuchObject\n"); return 0; } if (ptr->get_fnc_ptr) { if ((ptr->get_fnc_ptr)(ptr, &req->oid_ptr->ptr[oid_len], req->oid_ptr->len - oid_len) == -1) { req->value_type = BER_TYPE_NO_SUCH_INSTANCE; snmp_log("noSuchInstance - get value function\n"); return 0; } } /* copy the value */ memcpy(&req->value, &ptr->varbind.value, sizeof(varbind_value_t)); req->value_type = ptr->varbind.value_type; return ptr; }
static attribute_not_cached (Entry ptr, DN dn, OID at, DN target, int level, int dfltacl) { struct acl_attr * aa; struct oid_seq * oidptr; /* see if more than cached data is required */ if (ptr->e_acl->ac_attributes == NULLACL_ATTR) return (dfltacl); for ( aa = ptr->e_acl->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next) for ( oidptr=aa->aa_types; oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next) if (oid_cmp (oidptr->oid_oid,at) == 0) { /* The attribute is in the attribute ACL list */ /* Would a referral help the DUA ? */ if (check_acl (NULLDN,level,aa->aa_acl,target) == NOTOK) if (check_acl (dn,level,aa->aa_acl,target) == OK) return TRUE; return FALSE; } return (dfltacl); }
static int putaux (char* src, char* dst, int append, int fd, PE pe,struct vfsmap*vf, int size) #endif { int n; int cc, effector, gd, nc, reason, result; PE de, param; #ifdef BRIDGE char line[BUFSIZ]; #endif struct FADUidentity faduids; struct FADUidentity *faduid = &faduids; struct FTAMgroup ftgs; struct FTAMgroup *ftg = &ftgs; struct FTAMindication ftis; struct FTAMindication *fti = &ftis; struct FTAMabort *fta = &fti -> fti_abort; FILE *fp; pe -> pe_context = vf -> vf_id; param = NULLPE; if (vf -> vf_parameter && enc_f (vf -> vf_number, &_ZDOCS_mod, ¶m, 1, 0, NULLCP, vf -> vf_parameter) == NOTOK) { advise (NULLCP, "unable to build document type parameter: %s", PY_pepy); return NOTOK; } bzero ((char *) ftg, sizeof *ftg); ftg -> ftg_flags |= FTG_BEGIN | FTG_END; ftg -> ftg_threshold = 0; if (omode == FOVER_SELECT) append = 1; if (units & FUNIT_LIMITED) { ftg -> ftg_flags |= FTG_CREATE; { struct FTAMcreate *ftce = &ftg -> ftg_create; struct FTAMattributes *fa = &ftce -> ftce_attrs; ftce -> ftce_override = append ? FOVER_SELECT : omode; fa -> fa_present = FA_FILENAME; fa -> fa_nfile = 0; fa -> fa_files[fa -> fa_nfile++] = dst; fa -> fa_present |= FA_ACTIONS; fa -> fa_permitted = FA_PERM_READ | FA_PERM_REPLACE | FA_PERM_EXTEND | FA_PERM_READATTR | FA_PERM_CHNGATTR | FA_PERM_DELETE | FA_PERM_TRAV; fa -> fa_present |= FA_CONTENTS; fa -> fa_contents = vf -> vf_oid; fa -> fa_parameter = param; ftce -> ftce_access = append ? FA_PERM_EXTEND : FA_PERM_REPLACE; FCINIT (&ftce -> ftce_conctl); } } else { ftg -> ftg_flags |= FTG_SELECT; { struct FTAMselect *ftse = &ftg -> ftg_select; struct FTAMattributes *fa = &ftse -> ftse_attrs; if (!append && omode == FOVER_FAIL) { advise (NULLCP, "lack of limited-file-management conflicts with setting of \"override\" variable"); return NOTOK; } fa -> fa_present = FA_FILENAME; fa -> fa_nfile = 0; fa -> fa_files[fa -> fa_nfile++] = dst; ftse -> ftse_access = append ? FA_PERM_EXTEND : FA_PERM_REPLACE; FCINIT (&ftse -> ftse_conctl); } } ftg -> ftg_threshold++; ftg -> ftg_flags |= FTG_OPEN; { struct FTAMopen *ftop = &ftg -> ftg_open; ftop -> ftop_contents = vf -> vf_oid; ftop -> ftop_parameter = param; FCINIT (&ftop -> ftop_conctl); if (append) { ftop -> ftop_mode = FA_PERM_EXTEND; if (concurrency) ftop -> ftop_conctl.fc_extendlock = FLOCK_EXCLUSIVE; } else { ftop -> ftop_mode = FA_PERM_REPLACE; if (concurrency) ftop -> ftop_conctl.fc_replacelock = FLOCK_EXCLUSIVE; } } ftg -> ftg_threshold++; result = FBulkBeginRequest (ftamfd, ftg, fti); if (param) pe_free (param); if (result == NOTOK) { ftam_advise (fta, "F-BULK-BEGIN.REQUEST"); return NOTOK; } ftg = &fti -> fti_group; if (ftg -> ftg_flags & FTG_SELECT) { struct FTAMselect *ftse = &ftg -> ftg_select; ftam_diag (ftse -> ftse_diags, ftse -> ftse_ndiag, 1, ftse -> ftse_action); if (ftse -> ftse_state != FSTATE_SUCCESS) goto you_lose; } else if (ftg -> ftg_flags & FTG_CREATE) { struct FTAMcreate *ftce = &ftg -> ftg_create; ftam_diag (ftce -> ftce_diags, ftce -> ftce_ndiag, 1, ftce -> ftce_action); if (ftce -> ftce_state != FSTATE_SUCCESS) goto you_lose; } if (ftg -> ftg_flags & FTG_OPEN) { struct FTAMopen *ftop = &ftg -> ftg_open; ftam_diag (ftop -> ftop_diags, ftop -> ftop_ndiag, 1, ftop -> ftop_action); if (ftop -> ftop_state != FSTATE_SUCCESS) goto you_lose; for (myvf = vfs; myvf -> vf_entry; myvf++) if (oid_cmp (myvf -> vf_oid, ftop -> ftop_contents) == 0) break; switch (myvf - vfs) { case VFS_UTF: pe -> pe_id = (PElementID) ((struct type_DOCS_FTAM__1__Parameters *) myvf -> vf_parameter) -> universal__class__number; /* and fall... */ case VFS_UBF: effector = 1; if (ftop -> ftop_parameter && myvf -> vf_number >= 0) { caddr_t parm = NULL; if (dec_f (myvf -> vf_number, &_ZDOCS_mod, ftop -> ftop_parameter, 1, NULLIP, NULLVP, &parm) == NOTOK) advise (NULLCP, "unable to parse document type parameter: %s", PY_pepy); else switch (myvf - vfs) { case VFS_UTF: { struct type_DOCS_FTAM__1__Parameters *p1 = (struct type_DOCS_FTAM__1__Parameters *) parm; if (p1 -> optionals & opt_DOCS_FTAM__1__Parameters_universal__class__number) pe -> pe_id = (PElementID) p1 -> universal__class__number; else pe -> pe_id = PE_DEFN_GFXS; switch (pe -> pe_id) { case PE_DEFN_GFXS: if (getenv ("HP-FTAM")) { effector = 1; break; } /* else fall... */ case PE_DEFN_PRTS: case PE_DEFN_VISS: effector = 0; break; case PE_DEFN_T61S: case PE_DEFN_VTXS: case PE_DEFN_IA5S: case PE_DEFN_GENS: effector = 1; break; default: break; } } break; case VFS_UBF: default: break; } if (parm) fre_obj (parm, _ZDOCS_mod.md_dtab[myvf -> vf_number], &_ZDOCS_mod, 1); } if (debug) advise (NULLCP, "effector=%d id=0x%x", effector, pe -> pe_id); if (myvf != vf || watch) { advise (NULLCP, "%s transfer", myvf -> vf_text); vf = myvf; } break; default: vf = &vfs[VFS_UBF]; advise (NULLCP, "document type mismatch; assuming %s (%s)", vf -> vf_text, vf -> vf_entry); break; } } myvf = vf; FTGFREE (ftg); faduid -> fa_type = FA_FIRSTLAST; faduid -> fa_firstlast = FA_FIRST; if (FReadWriteRequest (ftamfd, append ? FA_OPS_EXTEND : FA_OPS_REPLACE, faduid, myvf -> vf_context, NOTOK, 0, fti) == NOTOK) { ftam_advise (fta, "F-READWRITE.REQUEST"); return NOTOK; } switch (myvf - vfs) { case VFS_UTF: if ((gd = dup (fd)) == NOTOK || (fp = fdopen (gd, "r")) == NULL) { if (gd != NOTOK) close (gd); #ifdef BRIDGE advise (dst, gd != NOTOK ? "fdopen failed" : "unable to dup"); #else advise (src, gd != NOTOK ? "fdopen failed on" : "unable to dup"); #endif reason = FS_ACC_LCL; goto do_cancel; } break; case VFS_UBF: default: fp = NULL; break; } cc = 0; if (verbose) timer (cc, NULLCP); if (hash) marks = BUFSIZ - 1; #ifdef BRIDGE line[0] = '\0'; #endif for (;;) { char *bp, *ep; if (!interrupted) { int nfds; fd_set wfds; nfds = 0; FD_ZERO (&wfds); /* interrupt causes EINTR */ if (FSelectMask (ftamfd, &wfds, &nfds, fti) == OK) xselect (nfds, NULLFD, &wfds, NULLFD, NOTOK); } if (interrupted) { advise (NULLCP, "cancelling transfer"); reason = FS_GEN_INITIATOR; errno = EINTR; goto do_cancel; } for (ep = (bp = (char *) pe -> pe_prim) + size - (fp ? 2 : 0), nc = 0; bp < ep; ) { if (fp) { char *cp; #ifdef BRIDGE if (strlen (line) || fgets (line, BUFSIZ, fp)) { if ((int)(strlen(line) + 1) < (ep - bp - 1)) { strcpy (bp, line); line[0] = NULL; } else break; } else { #else if (fgets (bp, ep - bp + 1, fp) == NULL) { #endif n = (ferror (fp) && !feof (fp)) ? NOTOK : OK; break; } cp = bp + strlen (bp) - 1; if (!effector) { if (*cp == '\n') { #ifndef BRIDGE *cp = NULL; #else if (cp > bp) { if (*--cp == '\r') *cp = NULL; else *++cp = NULL; } else *cp = NULL; #endif n = cp - bp; bp = cp; } else { /* XXX: losing! */ n = cp - bp + 1; bp = cp + 1; } } else { if (*cp == '\n') { #ifndef BRIDGE *cp++ = '\r'; #endif *cp++ = '\n'; n = cp - bp; bp = cp; nc++; continue; } n = cp - bp + 1; bp = cp + 1; } } else { #ifdef BRIDGE switch (n = read (fd, bp, ep - bp)) { #else switch (n = read (fd, bp, ep - bp)) { #endif case NOTOK: case OK: break; default: bp += n; continue; } } break; } if (n == NOTOK || (n = bp - (char *) pe -> pe_prim) == 0) break; pe -> pe_len = n; if (fp && !effector) { if ((de = pe_cpy (pe)) == NULLPE) { reason = FS_ACC_LCL; errno = ENOMEM; goto do_cancel; } } else de = pe; if (debug) { if (fp) { WATCHP (DOCS_FTAM__1__Datatype1, de, 0); } else WATCHP (DOCS_FTAM__3__Datatype1, de, 0); } switch (de2fadu (de, pe != de ? 1 : 0)) { case NOTOK: if (fp) fclose (fp); return NOTOK; case OK: default: if (verbose || hash) cc += (n - nc), nc = 0; if (hash) { if (hash > 1) printf ("%d\r", cc); else for (; marks < cc; marks += BUFSIZ) putchar ('#'); fflush (stdout); } break; case DONE: de2fadu (NULLPE, 0); if (fp) fclose (fp); goto done_transfer; } } if (verbose) timer (cc, "sent"); if (fp) fclose (fp); if (n == NOTOK) { struct FTAMdiagnostic diags[NFDIAG]; struct FTAMdiagnostic *dp; #ifdef BRIDGE advise (dst, "error reading"); #else advise (src, "error reading"); #endif reason = FS_ACC_LCLDEV; do_cancel: ; dp = diags; dp -> ftd_type = DIAG_PERM; dp -> ftd_identifier = reason; dp -> ftd_observer = dp -> ftd_source = EREF_IFSU; dp -> ftd_delay = DIAG_NODELAY; strcpy (dp -> ftd_data, sys_errname (errno)); dp -> ftd_cc = strlen (dp -> ftd_data); dp++; de2fadu (NULLPE, 0); if (FCancelRequest (ftamfd, FACTION_PERM, NULLPE, diags, dp - diags, fti) == NOTOK) { ftam_advise (fta, "F-CANCEL.REQUEST"); return NOTOK; } if (fti -> fti_type == FTI_CANCEL) { struct FTAMcancel *ftcn = &fti -> fti_cancel; ftam_diag (ftcn -> ftcn_diags, ftcn -> ftcn_ndiag, 1, ftcn -> ftcn_action); FTCNFREE (ftcn); } goto done_transfer; } if (n == OK) n = de2fadu (NULLPE, 1); if (FDataEndRequest (ftamfd, FACTION_SUCCESS, (struct FTAMdiagnostic *) 0, 0, fti) == NOTOK) { ftam_advise (fta, "F-DATA-END.REQUEST"); return NOTOK; } if (FTransEndRequest (ftamfd, NULLPE, fti) == NOTOK) { ftam_advise (fta, "F-TRANSFER-END.REQUEST"); return NOTOK; } switch (fti -> fti_type) { case FTI_TRANSEND: { struct FTAMtransend *ftre = &fti -> fti_transend; ftam_diag (ftre -> ftre_diags, ftre -> ftre_ndiag, 1, ftre -> ftre_action); FTREFREE (ftre); } break; case FTI_CANCEL: { struct FTAMcancel *ftcn = &fti -> fti_cancel; advise (NULLCP, "data transfer canceled!"); ftam_diag (ftcn -> ftcn_diags, ftcn -> ftcn_ndiag, 1, ftcn -> ftcn_action); FTCNFREE (ftcn); if (FCancelResponse (ftamfd, FACTION_SUCCESS, NULLPE, (struct FTAMdiagnostic *) 0, 0, fti) == NOTOK) { ftam_advise (fta, "F-CANCEL.RESPONSE"); return NOTOK; } } break; default: adios (NULLCP, "unexpected indication type=%d", fti -> fti_type); } done_transfer: ; ftg = &ftgs; bzero ((char *) ftg, sizeof *ftg); ftg -> ftg_flags |= FTG_BEGIN | FTG_END; ftg -> ftg_threshold = 0; ftg -> ftg_flags |= FTG_CLOSE; ftg -> ftg_threshold++; ftg -> ftg_flags |= FTG_DESELECT; ftg -> ftg_threshold++; if (FBulkEndRequest (ftamfd, ftg, fti) == NOTOK) { ftam_advise (fta, "F-BULK-END.REQUEST"); return NOTOK; } ftg = &fti -> fti_group; if (ftg -> ftg_flags & FTG_CLOSE) { struct FTAMclose *ftcl = &ftg -> ftg_close; ftam_diag (ftcl -> ftcl_diags, ftcl -> ftcl_ndiag, 1, ftcl -> ftcl_action); } if (ftg -> ftg_flags & FTG_DESELECT) { struct FTAMdeselect *ftde = &ftg -> ftg_deselect; ftam_diag (ftde -> ftde_diags, ftde -> ftde_ndiag, 1, ftde -> ftde_action); ftam_chrg (&ftde -> ftde_charges); } FTGFREE (ftg); return OK; you_lose: ; FTGFREE (ftg); return NOTOK; } /* */ int de2fadu (pe, concat) PE pe; int concat; { int result; struct FTAMindication ftis; struct FTAMindication *fti = &ftis; struct FTAMabort *fta = &fti -> fti_abort; static int ninfo = 0; static int size = 0; static PE info[NPDATA]; if (pe == NULLPE) { result = OK; if (concat && ninfo > 0 && FDataRequest (ftamfd, info, ninfo, fti) == NOTOK) { ftam_advise (fta, "F-DATA.REQUEST"); result = NOTOK; } while (ninfo > 0) pe_free (info[--ninfo]); size = 0; return result; } if (concat) { int flush, n; if (size + (n = ps_get_abs (pe) + MAGIC_OCTET2) >= fadusize && ninfo > 0) { if (debug) advise (NULLCP, "de2fadu flushing on %d FADUs, estimated size %d/%d", ninfo, size, fadusize); if ((result = de2fadu (NULLPE, 1)) != OK) return result; flush = 1; } else flush = 0; info[ninfo++] = pe; size += n; if (ninfo < NPDATA && size < fadusize) { if (!flush) return OK; } else { if ((result = FDataRequest (ftamfd, info, ninfo, fti)) == NOTOK) ftam_advise (fta, "F-DATA.REQUEST"); while (ninfo > 0) pe_free (info[--ninfo]); size = 0; if (result == NOTOK) return result; } } else if (FDataRequest (ftamfd, &pe, 1, fti) == NOTOK) { ftam_advise (fta, "F-DATA.REQUEST"); return NOTOK; } if (FWaitRequest (ftamfd, OK, fti) == NOTOK) { if (fta -> fta_peer || fta -> fta_action != FACTION_TRANS || fta -> fta_ndiag < 1 || fta -> fta_diags[0].ftd_type != DIAG_TRANS || fta -> fta_diags[0].ftd_identifier != FS_PRO_TIMEOUT) { ftam_advise (fta, "F-WAIT.REQUEST"); return NOTOK; } return OK; } if (fti -> fti_type == FTI_CANCEL) { struct FTAMcancel *ftcn = &fti -> fti_cancel; advise (NULLCP, "data transfer cancelled!"); ftam_diag (ftcn -> ftcn_diags, ftcn -> ftcn_ndiag, 1, ftcn -> ftcn_action); FTCNFREE (ftcn); if (FCancelResponse (ftamfd, FACTION_SUCCESS, NULLPE, (struct FTAMdiagnostic *) 0, 0, fti) == NOTOK) { ftam_advise (fta, "F-CANCEL.RESPONSE"); return NOTOK; } } return DONE; }
/* 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. */ } }
/* 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; }
/* * Find an object in the MIB that is the lexicographical successor of the given one. */ mib_object_t* mib_get_next(varbind_t* req) { int cmp; u16t oid_len; mib_iterator_init(); while (!mib_iterator_is_end()) { // find the object cmp = oid_cmp(req->oid_ptr, ptr->varbind.oid_ptr); oid_len = oid_length(ptr->varbind.oid_ptr); if (!GET_NEXT_OID_PTR) { // handle a scalar object if (cmp < 0 || (cmp == 0 && req->oid_ptr->len < oid_len)) { #if ENABLE_MIB_TABLE || ENABLE_PROGMEM oid_copy(req->oid_ptr, ptr->varbind.oid_ptr, 0); CHECK_PTR_U(req->oid_ptr->ptr); #else req->oid_ptr.len = ptr->varbind.oid_ptr.len; req->oid_ptr.ptr = ptr->varbind.oid_ptr.ptr; #endif break; } } else { #if ENABLE_MIB_TABLE /* handle a tabular object */ if (cmp < 0 || cmp == 0) { ptr_t* table_oid_ptr; if ((table_oid_ptr = (ptr->get_next_oid_fnc_ptr)(ptr, (cmp < 0 ? 0 : &req->oid_ptr->ptr[oid_len]), cmp < 0 ? 0 : req->oid_ptr->len - oid_len)) != 0) { /* copy the mib object's oid */ oid_copy(req->oid_ptr, ptr->varbind.oid_ptr, oid_len + table_oid_ptr->len); CHECK_PTR_U(req->oid_ptr->ptr); memcpy(&req->oid_ptr->ptr[oid_len], table_oid_ptr->ptr, table_oid_ptr->len); req->oid_ptr->len += table_oid_ptr->len; free(table_oid_ptr->ptr); oid_free(table_oid_ptr); break; } } #endif } mib_iterator_next(); } if (mib_iterator_is_end()) { req->value_type = BER_TYPE_END_OF_MIB; snmp_log("mib does not contain next object\n"); return 0; } if (ptr->get_fnc_ptr) { if ((ptr->get_fnc_ptr)(ptr, &req->oid_ptr->ptr[oid_len], req->oid_ptr->len - oid_len) == -1) { snmp_log("can not get the value of the object\n"); return 0; } } /* copy the value */ memcpy(&req->value, &ptr->varbind.value, sizeof(varbind_value_t)); req->value_type = ptr->varbind.value_type; return ptr; }
/* 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; }