예제 #1
0
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;
  }
}
예제 #2
0
파일: mib_tree.c 프로젝트: tedaz/smartsnmp
/* 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;
}
예제 #3
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;
}
예제 #4
0
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);

}
예제 #5
0
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, &param, 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;
}
예제 #6
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. */
  }
}
예제 #7
0
파일: mib_tree.c 프로젝트: tedaz/smartsnmp
/* 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;
}
예제 #8
0
/*
 * 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;
}
예제 #9
0
파일: mib.c 프로젝트: Candouble/smartsnmp
/* 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;
}