summaryrefslogtreecommitdiff
path: root/doc/rfc/rfc1076.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/rfc/rfc1076.txt')
-rw-r--r--doc/rfc/rfc1076.txt2355
1 files changed, 2355 insertions, 0 deletions
diff --git a/doc/rfc/rfc1076.txt b/doc/rfc/rfc1076.txt
new file mode 100644
index 0000000..fe09f2d
--- /dev/null
+++ b/doc/rfc/rfc1076.txt
@@ -0,0 +1,2355 @@
+
+
+
+
+
+
+Network Working Group G. Trewitt
+Request for Comments: 1076 Stanford University
+Obsoletes: RFC 1023 C. Partridge
+ BBN/NNSC
+ November 1988
+
+
+ HEMS Monitoring and Control Language
+
+ TABLE OF CONTENTS
+
+1. Status of This Memo 1
+ Introduction 2
+2. Overview and Scope 2
+3. Overview of Query Processor Operation 4
+4. Encoding of Queries and Responses 5
+4.1 Notation Used in This Proposal 5
+5. Data Organization 6
+5.1 Example Data Tree 7
+5.2 Arrays 8
+6. Components of a Query 9
+7. Reply to a Query 10
+8. Query Language 12
+8.1 Moving Around in the Data Tree 14
+8.2 Retrieving Data 15
+8.3 Data Attributes 16
+8.4 Examining Memory 18
+8.5 Control Operations: Modifying the Data Tree 19
+8.6 Associative Data Access: Filters 21
+8.7 Terminating a Query 26
+9. Extending the Set of Values 27
+10. Authorization 27
+11. Errors 28
+I. ASN.1 Descriptions of Query Language Components 29
+I.1 Operation Codes 30
+I.2 Error Returns 31
+I.3 Filters 33
+I.4 Attributes 34
+I.5 VendorSpecific 36
+II. Implementation Hints 36
+III. Obtaining a Copy of the ASN.1 Specification 42
+
+1. STATUS OF THIS MEMO
+
+ This RFC specifies a query language for monitoring and control of
+ network entities. This RFC supercedes RFC-1023, extending the query
+ language and providing more discussion of the underlying issues.
+
+
+
+
+Trewitt & Partridge [Page 1]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ This language is a component of the High-Level Entity Monitoring
+ System (HEMS) described in RFC-1021 and RFC-1022. Readers may wish
+ to consult these RFCs when reading this memo. RFC-1024 contains
+ detailed assignments of numbers and structures used in this system.
+ Portions of RFC-1024 that define query language structures are
+ superceded by definitions in this memo. This memo assumes a
+ knowledge of the ISO data encoding standard, ASN.1.
+
+ Distribution of this memo is unlimited.
+
+INTRODUCTION
+
+ This RFC specifies the design of a general-purpose, yet efficient,
+ monitoring and control language for managing network entities. The
+ data in the entity is modeled as a hierarchy and specific items are
+ named by giving the path from the root of the tree. Most items are
+ read-only, but some can be "set" in order to perform control
+ operations. Both requests and responses are represented using the
+ ISO ASN.1 data encoding rules.
+
+2. OVERVIEW AND SCOPE
+
+ The basic model of monitoring and control used in this memo is that a
+ query is sent to a monitored entity and the entity sends back a
+ response. The term query is used in the database sense -- it may
+ request information, modify data, or both. We will use gateway-
+ oriented examples, but it should be understood that this query-
+ response mechanism is applicable to any IP entity.
+
+ In particular, there is no notion of an interactive "conversation" as
+ in SMTP [RFC-821] or FTP [RFC-959]. A query is a complete request
+ that stands on its own and elicits a complete response.
+
+ In order to design the query language, we had to define a model for
+ the data to be retrieved by the queries, which required some
+ understanding of and assumptions to be made about the data. We ended
+ up with a fairly flexible data model, which places few limits on the
+ type or size of the data.
+
+ Wherever possible, we give motivations for the design decisions or
+ assumptions that led to particular features or definitions. Some of
+ the important global considerations and assumptions are:
+
+ - The query processor should place as little computational
+ burden on the monitored entity as possible.
+
+ - It should not be necessary for a monitored entity to store
+ the complete query. Nothing in the query language should
+
+
+
+Trewitt & Partridge [Page 2]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ preclude an implementation from being able to process the
+ query on the fly, producing portions of the response while
+ the query is still being read and parsed. There may be
+ other constraints that require large amounts of data to be
+ buffered, but the query language design must not be one.
+
+ - It is assumed that there is some mechanism to transport a
+ sequence of octets to a query processor within the
+ monitored entity and that there is some mechanism to return
+ a sequence of octets to the entity making the query. In
+ HEMS, this is provided by HEMP and its underlying transport
+ layer. The query language design is independent of these
+ details, however, and could be grafted onto some other
+ protocol.
+
+ - The data model must provide organization for the data, so
+ that it can be conveniently named.
+
+ - Much of the data to be monitored will be contained in
+ tables. Some tables may contain other tables. The query
+ language should be able to deal with such tables.
+
+ - We don't provide capabilities for data reduction in the
+ query language. We will provide for data selection, for
+ example, only retrieving certain table entries, but we will
+ not provide general facilities for processing data, such as
+ computing averages.
+
+ - Because one monitoring center may be querying many
+ (possibly hetrogenous) hosts, it must be possible to write
+ generic queries that can be sent to all hosts, and have the
+ query elicit as much information as is available from each
+ host. i.e., queries must not be aborted just because they
+ requested non-existent data.
+
+ There were some assumptions that we specifically did not make:
+
+ - It is up to the implementation to choose what degree of
+ concurrency will be allowed when processing queries. By
+ locking only portions of the database, it should be
+ possible to achieve good concurrency while still preventing
+ deadlock.
+
+ - This specification makes no statement about the use of the
+ "definite" and "indefinite" length forms in ASN.1. There
+ is currently some debate about this usage in the ISO
+ community; implementors should note the recommendations in
+ the ASN.1 specification.
+
+
+
+Trewitt & Partridge [Page 3]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ Other RFCs associated with HEMS are:
+
+ RFC-1021 Overview;
+ RFC-1022 Transport protocol and message encapsulation;
+ RFC-1024 Precise data definitions.
+
+ The rest of this report is organized as follows:
+
+ Section 3 Gives a brief overview of the data model and the
+ operation of the query processor.
+
+ Section 4 Describes the encoding used for queries and
+ responses, and the notation used to represent them
+ in this report.
+
+ Section 5 Describes how the data is organized in the
+ monitored entity, and the view provided of it by
+ the query processor.
+
+ Section 6 Describes the basic data types that may be given
+ to the query processor as input.
+
+ Section 7 Describes how a reply to a query is organized.
+
+ Section 8 Describes the operations available in the query
+ language.
+
+ Section 9 Describes how the set of data in the tree may be
+ extended.
+
+ Section 10 Describes how authorization issues affect the
+ execution of a query.
+
+ Section 11 Describes how errors are reported, and their
+ effect on the processing of the query.
+
+ Appendix I Gives precise ASN.1 definitions of the data types
+ used by the query processor.
+
+ Appendix II Gives extensive implementation hints for the core
+ of the query processor.
+
+3. OVERVIEW OF QUERY PROCESSOR OPERATION
+
+ In this section, we give an overview of the operation of the query
+ processor, to provide a framework for the later sections.
+
+ The query language models the manageable data as a tree, with each
+
+
+
+Trewitt & Partridge [Page 4]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ branch representing a different aspect of the entity, such as
+ different layers of protocols. Subtrees are further divided to
+ provide additional structure to the data. The leaves of the tree
+ contain the actual data.
+
+ Given this data representation, the task of the query processor is to
+ traverse this tree and retrieve (or modify) data specified in a
+ query. A query consists of instructions to move around in the tree
+ and to retrieve (or modify) named data. The result of a query is an
+ exact image of the parts of the tree that the query processor
+ visited.
+
+ The query processor is very simple -- it only understands eight
+ commands, most of which share the same structure. It is helpful to
+ think of the query processor as an automaton that walks around in the
+ tree, directed by commands in the query. As it moves around, it
+ copies the tree structure it traverses to the query result. Data
+ that is requested by the query is copied into the result as well.
+ Data that is changed by a query is copied into the result after the
+ modification is made.
+
+4. ENCODING OF QUERIES AND RESPONSES
+
+ Both queries and responses are encoded using the representation
+ defined in ISO Standard ASN.1 (Abstract Syntax Notation 1). ASN.1
+ represents data as sequences of <tag,length,contents> triples that
+ are encoded as a stream of octets. The data tuples may be
+ recursively nested to represent structured data such as arrays or
+ records. For a full description, see the ISO standards IS 8824 and
+ IS 8825. See appendix for information about obtaining these
+ documents.
+
+4.1 Notation Used in This Proposal
+
+ The notation used in this memo is similar to that used in ASN.1, but
+ less formal, smaller, and (hopefully) easier to read. We will refer
+ to a <tag,length,contents> tuple as a "data object". In this RFC, we
+ will not be concerned with the details of the object lengths. They
+ exist in the actual ASN.1 encoding, but will be omitted in the
+ examples here.
+
+ Data objects that have no internal ASN.1 structure such as integer or
+ octet string are referred to as "simple types" or "simple objects".
+ Objects which are constructed out of other ASN.1 data objects will be
+ referred to as "composite types" or "composite objects".
+
+
+
+
+
+
+Trewitt & Partridge [Page 5]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ The notation
+ ID(value)
+ represents a simple object whose tag is "ID" with the given value. A
+ composite object is represented as
+ ID{ ... contents ... }
+ where contents is a sequence of data objects. The contents may
+ include both simple and structured types, so the structure is fully
+ recursive.
+
+ The difference between simple and composite types is close to the
+ meaning of the "constructor" bit in ASN.1. For the uses here, the
+ distinction is made based upon the semantics of the data, not the
+ representation. Therefore, even though an OctetString can be
+ represented in ASN.1 using either constructed or non-constructed
+ forms, it is conceptually a simple type, with no internal structure,
+ and will always be written as
+ ID("some arbitrary string")
+ in this RFC.
+
+ There are situations where it is necessary to specify a type but give
+ no value, such as when referring to the name of the data. In this
+ situation, the same notation is used, but with the value omitted:
+ ID or ID() or ID{}
+ Such objects have zero length and no contents. The latter two forms
+ are used when a distinction is being made between simple and
+ composite data, but the difference is just notation -- the
+ representation is the same.
+
+ ASN.1 distinguishes between four "classes" of tags: universal,
+ application-specific, context-dependent, and reserved. HEMS and this
+ query language use the first three. Universal tags are assigned in
+ the ASN.1 standard and its addendums for common types, and are
+ understood by any application using ASN.1. Application-specific tags
+ are limited in scope to a particular application. These are used for
+ "well-known" identifiers that must be recognizable in any context,
+ such as derived data types. Finally, context-dependent tags are used
+ for objects whose meaning is dependent upon where they are
+ encountered. Most tags that identify data are context-dependent.
+
+5. DATA ORGANIZATION
+
+ Data in a monitored entity is modeled as a hierarchy.
+ Implementations are not required to organize the data internally as a
+ hierarchy, but they must provide this view of the data through the
+ query language. A hierarchy offers useful structure for the
+ following operations:
+
+
+
+
+
+Trewitt & Partridge [Page 6]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ Organization A hierarchy allows related data to be grouped
+ together in a natural way.
+
+ Naming The name of a piece of data is just the path from the
+ root to the data of interest.
+
+ Mapping onto ASN.1
+ ASN.1 can easily represent a hierarchy by using a
+ "constructor" type as an envelope for an entire
+ subtree.
+
+ Efficient Representation
+ Hierarchical structures are compact and can be
+ traversed quickly.
+
+ Safe Locking If it is necessary to lock part of the hierarchy (for
+ example, when doing an update), locking an entire
+ subtree can be done efficiently and safely, with no
+ danger of deadlock.
+
+ We will use the term "data tree" to refer to this entire structure.
+ Note that this internal model is completely independent of the
+ external ASN.1 representation -- any other suitable representation
+ would do. For the sake of efficiency, we do make a one-to-one
+ mapping between ASN.1 tags and the (internal) names of the nodes.
+ The same could be done for any other external representation.
+
+ Each node in the hierarchy must have names for its component parts.
+ Although we would normally think of names as being ASCII strings such
+ as "input errors", the actual name is just an ASN.1 tag. Such names
+ are small integers (typically, less than 30) and so can easily be
+ mapped by the monitored entity onto its internal representation.
+
+ We use the term "dictionary" to mean an internal node in the
+ hierarchy. Leaf nodes contain the actual data. A dictionary may
+ contain both leaf nodes and other dictionaries.
+
+5.1 Example Data Tree
+
+ Here is a possible organization of the hierarchy in an entity that
+ has several network interfaces and does IP routing. The exact
+ organization of data in entities is specified in RFC-1024. This
+ skeletal data tree will be used throughout this RFC in query
+ examples.
+
+ System {
+ name -- host name
+ clock-msec -- msec since boot
+
+
+
+Trewitt & Partridge [Page 7]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ interfaces -- # of interfaces
+ memory
+ }
+ Interfaces { -- one per interface
+ InterfaceData{ address, mtu, netMask, ARP{...}, ... }
+ InterfaceData{ address, mtu, netMask, ARP{...}, ... }
+ :
+ }
+ IPRouting {
+ Entry{ ip-addr, interface, cost, ... }
+ Entry{ ip-addr, interface, cost, ... }
+ :
+ }
+
+ There are three top-level dictionaries in this hierarchy (System,
+ Interfaces, and IPRouting) and three other dictionary types
+ (InterfaceData, Entry, and ARP), each with multiple instances.
+
+ The "name" of the clock in this entity would be:
+ system{ clock-msec }
+ and the name of a routing table entry's IP address would be:
+ IPRouting{ Entry{ ip-addr } }.
+
+ More than one piece of data can be named by a single ASN.1 object.
+ The entire collection of system information is named by:
+ system
+ and the name of a routing table's IP address and cost would be:
+ IPRouting{ Entry{ ip-addr, cost } }.
+
+5.2 Arrays
+
+ There is one sub-type of a dictionary that is used as the basis for
+ tables of objects with identical types. We call these dictionaries
+ arrays. In the example above, the dictionaries for interfaces,
+ routing tables, and ARP tables are all arrays.
+
+ In the examples above, the "ip-addr" and "cost" fields are named. In
+ fact, these names refer to the field values for ALL of the routing
+ table entries -- the name doesn't (and can't) specify which routing
+ table entry is intended. This ambiguity is a problem wherever data
+ is organized in tables. If there was a meaningful index for such
+ tables (e.g., "routing table entry #1"), there would be no problem.
+ Unfortunately, there usually isn't such an index. The solution to
+ this problem requires that the data be accessed on the basis of some
+ of its content. Filters, discussed in section 8.6, provide this
+ mechanism.
+
+ The primary difference between arrays and plain dictionaries is that
+
+
+
+Trewitt & Partridge [Page 8]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ arrays may contain only one type of item, while dictionaries, in
+ general, will contain many different types of items. For example,
+ the dictionary IPRouting (which is an array) will contain only items
+ of type Entry.
+
+ The fact that these objects are viewed externally as arrays or tables
+ does not mean that they are represented in an implementation as
+ linear lists of objects. Any collection of same-typed objects is
+ viewed as an array, even though it might be stored internally in some
+ other format, for example, as a hash table.
+
+6. COMPONENTS OF A QUERY
+
+ A HEMS query consists of a sequence of ASN.1 objects, interpreted by
+ a simple stack-based interpreter. [Although we define the query
+ language in terms of the operations of a stack machine, the language
+ does not require an implementation to use a stack machine. This is a
+ well-understood model, and is easy to implement.] One ASN.1 tag is
+ reserved for operation codes; all other tags indicate data that will
+ eventually be used by an operation. These objects are pushed onto
+ the stack when received. Opcodes are immediately executed and may
+ remove or add items to the stack. Because ASN.1 itself provides
+ tags, very little needs to be done to the incoming ASN.1 objects to
+ make them suitable for use by the query interpreter.
+
+ Each ASN.1 object in a query will fit into one of the following
+ categories:
+
+ Opcode An opcode tells the query interpreter to perform an action.
+ They are described in detail in section 8. Opcodes are
+ represented by an application-specific type whose value
+ determines the operation.
+
+ Template These are objects that name one or more items in the data
+ tree. Named items may be either simple items (leaf nodes)
+ or entire dictionaries, in which case the entire subtree
+ "underneath" the dictionary is understood. Templates are
+ used to select specific data to be retrieved from the data
+ tree. A template may be either simple or structured,
+ depending upon what it is naming. A template only names
+ the data -- there are no values contained in it. Therefore
+ the leaf objects in a template will all have a length of
+ zero.
+
+ Examples of very simple templates are:
+ name() or System{}
+ Each of these is just one ASN.1 data object, with zero
+ length. The first names a single data item in the "System"
+
+
+
+Trewitt & Partridge [Page 9]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ dictionary (and must appear in that context), and the
+ second names the entire "System" dictionary. A more
+ complex template such as:
+ Interfaces{ InterfaceData{ address, netMask, ARP } }
+ names two simple data items and a dictionary, iterated over
+ all occurrences of "InterfaceData" within the Interfaces
+ array.
+
+ Path A path is a special case of a template that names only a
+ single node in the tree. It specifies a path down into the
+ dictionary tree and names exactly one node in the
+ dictionary tree.
+
+ Value These are used to give data values when needed in a query,
+ for example, when changing a value in the data tree. A
+ value can be thought of as either a filled-in template or
+ as the ASN.1 representation some part of the data tree.
+
+ Filter A boolean expression that can be executed in the context of
+ a particular dictionary that is used to select or not
+ select items in the dictionary. The expressions consist of
+ the primitives "equal", "greater-or-equal",
+ "less-or-equal", and "present" possibly joined by "and",
+ "or", and "not". (See section 8.6.)
+
+ Values, Paths, and Templates usually have names in the context-
+ dependent class, except for a few special cases, which are in the
+ application-specific class.
+
+7. REPLY TO A QUERY
+
+ The data returned to the monitoring entity is a sequence of ASN.1
+ data items. Conceptually, the reply is a subset of the data tree,
+ where the query selects which portions are to be included. This is
+ exactly true for data retrieval requests, and essentially true for
+ data modification requests -- the reply contains the data after it
+ has been modified. The key point is that the data in a reply
+ represents the state of the data tree immediately after the query was
+ executed.
+
+ The sequence of the data is determined by the sequence of query
+ language operations and the order of data items within Templates and
+ Values given as input to these operations. If a query requests data
+ from two of the top-level dictionaries in the data tree, by giving
+ two templates such as:
+
+ System{ name, interfaces }
+ Interfaces{
+
+
+
+Trewitt & Partridge [Page 10]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ InterfaceData { address, netMask, mtu }
+ }
+
+ then the response will consist of two ASN.1 data objects, as follows:
+
+ System {
+ name("system name"),
+ interfaces(2)
+ }
+ Interfaces {
+ InterfaceData { address(36.8.0.1),
+ netMask(FFFF0000),
+ mtu(1500)
+ }
+ InterfaceData { address(10.1.0.1),
+ mtu(1008),
+ netMask(FF000000)
+ }
+ }
+
+ With few exceptions, each of the data items in the hierarchy is named
+ in the context-specific ASN.1 type space. Because of this, the
+ returned objects must be fully qualified. For example, the name of
+ the entity must always be returned encapsulated inside an ASN.1
+ object for "System". If it were not, there would be no way to tell
+ if the object that was returned was "name" inside the "System"
+ dictionary or "address" inside the "interfaces" dictionary (assuming
+ in this case that "name" and "address" were assigned the same integer
+ as their ASN.1 tags).
+
+ Having fully-qualified data simplifies decoding of the data at the
+ receiving end and allows the tags to be locally chosen. Definitions
+ for tags within routing tables won't conflict with definitions for
+ tags within interfaces. Therefore, the people doing the name
+ assignments are less constrained. In addition, most of the
+ identifiers will be fairly small integers, which is an advantage
+ because ASN.1 can fit tag numbers up to 30 in a one-octet tag field.
+ Larger numbers require a second octet.
+
+ If data is requested that doesn't exist, either because the tag is
+ not defined, or because an implementation doesn't provide that data
+ (such as when the data is optional), the response will contain an
+ ASN.1 object that is empty. The tag will be the same as in the
+ query, and the object will have a length of zero.
+
+ The same response is given if the requested data does exist, but the
+ invoker of the query does not have authorization to access it. See
+ section 10 for more discussion of authorization mechanisms.
+
+
+
+Trewitt & Partridge [Page 11]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ This allows completely generic queries to be composed without regard
+ to whether the data is defined or implemented at all of the entities
+ that will receive the query. All of the available data will be
+ returned, without generating errors that might otherwise terminate
+ the processing of the query.
+
+8. QUERY LANGUAGE
+
+ The query language is designed to be expressive enough to write
+ useful queries with, yet simple enough to be easy to implement. The
+ query processor should be as simple and fast as possible, in order to
+ avoid placing a burden on the monitored entity, which may be a
+ critical node such as a gateway.
+
+ Although queries are formed in a flexible way using what we term a
+ "language", this is not a programming language. There are operations
+ that operate on data, but most other features of programming
+ languages are not present. In particular:
+
+ - Programs are not stored in the query processor.
+
+ - The only form of temporary storage is a stack, of limited
+ depth.
+
+ - There are no subroutines.
+
+ - There are no explicit control structures defined in the
+ language.
+
+ The central element of the language is the stack. It may contain
+ templates, (and therefore paths), values, and filters taken from the
+ query. In addition, it can contain dictionaries (and therefore
+ arrays) from the data tree. At the beginning of a query, it contains
+ one item, the root dictionary.
+
+ The overall operation consists of reading ASN.1 objects from the
+ input stream. All objects that aren't opcodes are pushed onto the
+ stack as soon as they are read. Each opcode is executed immediately
+ and may remove items from the stack, may generate ASN.1 objects and
+ send them to the output stream, and may leave items on the stack.
+ Because each input object is dealt with immediately, portions of the
+ response may be generated while the query is still being received.
+
+ In the descriptions below, operator names are in capital letters,
+ preceded by the arguments used from the stack and followed by results
+ left on the stack. For example:
+
+
+
+
+
+Trewitt & Partridge [Page 12]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ OP a b OP a t
+ means that the OP operator takes <a> and <b> off of the
+ stack and leaves <t> on the stack. Most of the operators
+ in the query language leave the first operand (<a> in this
+ example) on the stack for future use.
+
+ If both <a> and <b> were received as part of the query (as opposed to
+ being calculated by previous operations), then this part of the query
+ would have consisted of the sequence:
+ <a>
+ <b>
+ OP
+ So, like other stack-based languages, the arguments and operators
+ must be presented in postfix order, with an operator following its
+ operands.
+
+ Here is a summary of all of the operators defined in the query
+ language. Most of the operators can take several different sets of
+ operands and behave differently based upon the operand types.
+ Details and examples are given later.
+
+ BEGIN dict1 path BEGIN dict1 dict
+ array path filter BEGIN array dict
+ Move down in the data tree, establishing a context for
+ future operations.
+
+ END dict END --
+ Undo the most recent BEGIN.
+
+ GET dict GET dict
+ dict template GET dict
+ array template filter GET array
+ Retrieve data from the data tree.
+
+ GET-ATTRIBUTES
+ dict GET-ATTRIBUTES dict
+ dict template GET-ATTRIBUTES dict
+ array template filter GET-ATTRIBUTES array
+ Retrieve attribute information about data in the data tree.
+
+ GET-RANGE dict path start length GET-RANGE dict
+ Retrieve a subrange of an OctetString. Used for reading
+ memory.
+
+ SET dict value SET dict
+ array value filter SET array
+ Change values in the data tree, possibly performing control
+ functions.
+
+
+
+Trewitt & Partridge [Page 13]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ CREATE array value CREATE dict
+ Create new table entries.
+
+ DELETE array filter DELETE array
+ Delete table entries.
+
+ These operators are defined so that it is impossible to generate an
+ invalid query response. Since a response is supposed to be a
+ snapshot of a portion (or portions) of the data tree, it is important
+ that only data that is actually in the tree be put in the response.
+ Two features of the language help guarantee this:
+
+ - Data is put in the response directly from the tree (by
+ GET-*). Data does not go from the tree to the stack and
+ then into the response.
+
+ - Dictionaries on the stack are all derived from the initial,
+ root dictionary. The operations that manipulate
+ dictionaries (BEGIN and END) also update the response with
+ the new location in the tree.
+
+8.1 Moving Around in the Data Tree
+
+ The initial point of reference in the data tree is the root. That
+ is, operators name data starting at the root of the tree. It is
+ useful to be able to move to some other dictionary in the tree and
+ then name data from that point. The BEGIN operator moves down in the
+ tree and END undoes the last unmatched BEGIN.
+
+ BEGIN is used for two purposes:
+
+ - By moving to a dictionary closer to the data of interest,
+ the name of the data can be shorter than if the full name
+ (from the root) were given.
+
+ - It is used to establish a context for filtered operations
+ to operate in. Filters are discussed in section 8.6.
+
+ BEGIN dict1 path BEGIN dict1 dict
+ Follow <path> down the dictionary starting from <dict1>.
+ Push the final dictionary named by <path> onto the stack.
+ <path> must name a dictionary (not a leaf node). At the
+ same time, produce the beginning octets of an ASN.1 object
+ corresponding to the new dictionary. It is up to the
+ implementation to choose between using the "indefinite
+ length" representation or the "definite length" form and
+ going back and filling the length in later.
+
+
+
+
+Trewitt & Partridge [Page 14]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ END dict END --
+ Pop <dict> off of the stack and terminate the open ASN.1
+ object(s) started by the matching BEGIN. Must be paired
+ with a BEGIN. If an END operation pops the root dictionary
+ off of the stack, the query is terminated.
+
+ <path> must point to a regular dictionary. If any part of it refers
+ to a non-existent node, if it points to a leaf node, or if it refers
+ to a node inside an array-type dictionary, then it is in error, and
+ the query is terminated immediately.
+
+ An additional form of BEGIN, which takes a filter argument, is
+ described later.
+
+8.2 Retrieving Data
+
+ The basic model that all of the data retrieval operations follow is
+ that they take a template and fill in the leaf nodes of the template
+ with the appropriate data values.
+
+ GET dict template GET dict
+ Emit an ASN.1 object with the same "shape" as the given
+ template, except with values filled in for each node. The
+ first ASN.1 tag of <template> should refer to an object in
+ <dict>. If a dictionary tag is supplied anywhere in
+ <template>, the entire dictionary contents are emitted to
+ the response. Any items in the template that are not in
+ <dictionary> (or its components) are represented as objects
+ with a length of zero.
+
+ dict GET dict
+ If there is no template, get all of the items in the
+ dictionary. This is equivalent to providing a template
+ that lists all of the items in the dictionary.
+
+ An additional form of GET, which takes a filter argument, is
+ described later.
+
+ Here is an example of using the BEGIN operator to move down the data
+ tree to the TCP dictionary and then using the GET operator to
+ retrieve 5 data values from the TCP Stats dictionary:
+
+ IPTransport{ TCP } BEGIN
+ Stats{ octetsIn, octetsOut, inputPkts, outputPkts, badtag } GET
+ END
+
+
+
+
+
+
+Trewitt & Partridge [Page 15]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ This might return:
+
+ IPTransport{ TCP
+ Stats{ octetsIn(13255), octetsOut(82323),
+ inputPkts(9213), outputPkts(12425), badtag() }
+ }
+
+ "badtag" is a tag value that is undefined. No value is returned for
+ it, indicating that there is no data value associated with it.
+
+8.3 Data Attributes
+
+ Although ASN.1 "self-describes" the structure and syntax of the data,
+ it gives no information about what the data means. For example, by
+ looking at the raw data, it is possible to tell that an item is of
+ type [context 5] and is 4 octets long. That does not tell how to
+ interpret the data (is this an integer, an IP address, or a 4-
+ character string?) or what the data means (IP address of what?).
+ Even if the data were "tagged", in ASN.1 parlance, that would only
+ give the base type (e.g., IP-address or counter) and not the meaning.
+
+ Most of the time, this information will come from RFC-1024, which
+ defines the ASN.1 tags and their precise meaning. When extensions
+ have been made, it may not be possible to get documentation on the
+ extensions. (Extensions are discussed in section 9.)
+
+ The GET-ATTRIBUTES operator is similar to the GET operator, but
+ returns a set of attributes describing the data rather than the data
+ itself. This information is intended to be sufficient to let a human
+ understand the meaning of the data and to let a sophisticated
+ application treat the data appropriately. Such an application could
+ use the attribute information to format the data on a display and
+ decide whether it is appropriate to subtract one sample from another.
+
+ Some of the attributes are textual descriptions to help a human
+ understand the nature of the data and provide meaningful labels for
+ it. Extensive descriptions of standard data are optional, since they
+ are defined in RFC-1024. Complete descriptions of extensions must be
+ available, even if they are documented in a user's manual. Network
+ firefighters may not have a current manual handy when the network is
+ broken.
+
+ The format of the attributes is not as simple as the format of the
+ data itself. It isn't possible to use the data's tag, since that
+ would look exactly like the data itself. The format is:
+
+ Attributes ::= [APPLICATION 3] IMPLICIT SEQUENCE {
+ tagASN1 [0] IMPLICIT INTEGER,
+
+
+
+Trewitt & Partridge [Page 16]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ valueFormat [1] IMPLICIT INTEGER,
+ longDesc [2] IMPLICIT IA5String OPTIONAL,
+ shortDesc [3] IMPLICIT IA5String OPTIONAL,
+ unitsDesc [4] IMPLICIT IA5String OPTIONAL,
+ precision [5] IMPLICIT INTEGER OPTIONAL,
+ properties [6] IMPLICIT BITSTRING OPTIONAL,
+ valueSet [7] IMPLICIT SET OF valueDesc OPTIONAL
+ }
+
+ The GET-ATTRIBUTES operator is similar to the GET operator. The
+ major difference is that dictionaries named in the template do not
+ elicit data for the entire subtree.
+
+ GET-ATTRIBUTES
+ dict template GET-ATTRIBUTES dict
+ Emit a single ASN.1 Attributes object for each of the
+ objects named in <template>. For each of these, the
+ tagASN1 field will be set to the corresponding tag from the
+ template. The rest of the fields are set as appropriate
+ for the data object. Any items in the template that are
+ not in <dictionary> (or its components) elicit an
+ Attributes object with a valueFormat of NULL, and no other
+ descriptive information.
+
+ or
+ dict GET-ATTRIBUTES dict
+ If there is no template, emit Attribute objects for all of
+ the items in the dictionary. This is equivalent to
+ providing a template that lists all of the items in the
+ dictionary. This allows a complete list of a dictionary's
+ contents to be obtained.
+
+ An additional form of GET-ATTRIBUTES, which takes a filter argument,
+ is described later.
+
+ Here is an example of using the GET-ATTRIBUTES operator to request
+ attributes for three objects in the System dictionary:
+
+ System{ name, badtag, clock-msec } GET-ATTRIBUTES
+
+ "badtag" is some unknown tag. The result might be:
+
+ System{
+ Attributes{
+ tagASN1(name),
+ valueFormat(IA5String),
+ longDesc("The primary hostname."),
+
+
+
+
+Trewitt & Partridge [Page 17]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ shortDesc("hostname")
+ },
+ Attributes{
+ tagASN1(badtag), valueFormat(NULL)
+ }
+ Attributes{
+ tagASN1(clock-msec),
+ valueFormat(Integer),
+ longDesc("milliseconds since boot"),
+ shortDesc("uptime"), unitsDesc("ms")
+ precision(4294967296),
+ properties(1)
+ }
+
+ Note that in this example "name" and "clock-msec" are integer values
+ for the ASN.1 tags for the two data items. "badtag" is an integer
+ value that has no corresponding name in this context.
+
+ There will always be exactly as many Attributes items in the result
+ as there are objects in the template. Attributes objects for items
+ which do not exist in the entity will have a valueFormat of NULL and
+ none of the optional elements will appear.
+
+ [ A much cleaner method would be to store the attributes as
+ sub-components of the data item of interest. For example,
+ requesting
+ System{ clock-msec } GET
+ would normally just get the value of the data. Asking for an
+ additional layer down the tree would now get its attributes:
+ System{ clock-msec{ shortDesc, unitsDesc } GET
+ would get the named attributes. (The attributes would be
+ named with application-specific tags.) Unfortunately, ASN.1
+ doesn't provide a notation to describe this type of
+ organization. So, we're stuck with the GET-ATTRIBUTES
+ operator. However, if a cleaner organization were possible,
+ this decision would have been made differently. ]
+
+8.4 Examining Memory
+
+ Even with the ability to symbolically access all of this information
+ in an entity, there will still be times when it is necessary to get
+ to very low levels and examine memory, as in remote debugging
+ operations. The building blocks outlined so far can easily be
+ extended to allow memory to be examined.
+
+ Memory is modeled as an ordinary object in the data tree, with an
+ ASN.1 representation of OctetString. Because of the variety of
+ addressing architectures in existence, the conversion from the
+
+
+
+Trewitt & Partridge [Page 18]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ internal memory model to OctetString is very machine-dependent. The
+ only simple case is for byte-addressed machines with 8 bits per byte.
+
+ Each address space in an entity is represented by one "memory" data
+ item. In a one-address-space situation, this dictionary will
+ probably be in "System" dictionary. If each process has its own
+ address space, then one "memory" item might exist for each process.
+ Again, this is very machine-dependent.
+
+ Although the GET-RANGE operator is provided primarily for the purpose
+ of retrieving the contents of memory, it can be used on any object
+ whose base type is OctetString.
+
+ GET-RANGE dict path start length GET-RANGE dict
+ Get <length> elements of the OctetString, starting at
+ <start>. <start> and <length> are both ASN.1 INTEGER type.
+ <path>, starting from <dict>, must specify a node
+ representing memory, or some other OctetString.
+
+ The returned data may not be <length> octets long, since it may take
+ more than one octet to represent one memory location.
+
+ Memory items in the data tree are special in that they will not
+ automatically be returned when the entire contents of a dictionary
+ are requested. e.g., If memory is part of the "System" dictionary,
+ then the query
+ System GET
+ will emit the entire contents of the System dictionary, but not the
+ memory item.
+
+8.5 Control Operations: Modifying the Data Tree
+
+ All of the operators defined so far only allow data in an entity to
+ be retrieved. By replacing the template argument used in the GET
+ operators with a value, data in the entity can be changed. Very few
+ items in the data tree can be changed; those that can are noted in
+ RFC-1024.
+
+ Values in the data tree can modified in order to change configuration
+ parameters, patch routing tables, etc. Control functions, such as
+ bringing an interface "down" or "up", do not usually map directly to
+ changing a value. In such cases, an item in the tree can be defined
+ to have arbitrary side-effects when a value is assigned to it.
+ Control operations then consist of "setting" this item to an
+ appropriate command code. Reading the value of such an item might
+ return the current status. Again, details of such data tree items
+ are given in RFC-1024.
+
+
+
+
+Trewitt & Partridge [Page 19]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ This "virtual command-and-status register" model is very powerful,
+ and can be extended by an implementation to provide whatever controls
+ are needed. It has the advantage that the control function is
+ associated with the controlled object in the data tree. In addition,
+ no additional language features are required to support control
+ functions, and the same operations used to locate data for retrieval
+ are used to describe what is being controlled.
+
+ For all of the control and data modification operations, the fill-
+ in-the-blank model used for data retrieval is extended: the response
+ to an operation is the affected part of the data tree, after the
+ operation has been executed. Therefore, for normal execution, SET
+ and CREATE will return the object given as an argument, and DELETE
+ will return nothing (because the affected portion was deleted).
+
+ SET dict value SET dict
+ Set the value(s) of data in the entity to the value(s)
+ given in <value>. The result will be the value of the data
+ after the SET. Attempting to set a non-settable item will
+ not produce an error, but will yield a result in the reply
+ different from what was sent.
+
+ CREATE array value CREATE dict
+ Insert a new entry into <array>. Depending upon the
+ context, there may be severe restrictions about what
+ constitutes a valid <value>. The result will be the actual
+ item added to the <array>. Note that only one item can be
+ added per CREATE operation.
+
+ DELETE array filter DELETE array
+ Delete the entry(s) in <array> that match <filter>.
+ Filters are described later in this document. Normally, no
+ data items will be produced in the response, but if any of
+ the items that matched the filter could not be deleted,
+ they will be returned in the response.
+
+ An additional form of SET, which takes a filter argument, is
+ described later.
+
+ Here is an example of attempting to use SET to change the number of
+ interfaces in an entity:
+ System{ interfaces(5) } SET
+ Since that is not a settable parameter, the result would be:
+ System{ interfaces(2) }
+ giving the old value.
+
+ Here is an example of how CREATE would be used to add a routing table
+ entry for net for 128.89.0.0.
+
+
+
+Trewitt & Partridge [Page 20]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ IPRouting BEGIN -- get dictionary
+ Entries{ DestAddr(128.89.0.0), ... } -- entry to insert
+ CREATE
+ END -- finished with dict
+
+ The result would be what was added:
+ IPRouting{ Entries{ DestAddr(128.89.0.0), ... } }
+
+ The results in the response of these operators is consistent of the
+ global model of the response: it contains a subset of the data in
+ the tree immediately after the query is executed.
+
+ Note that CREATE and DELETE only operate on arrays, and then only on
+ arrays that are specifically intended for it. For example, it is
+ quite reasonable to add and remove entries from routing tables or ARP
+ tables, both of which are arrays. However, it doesn't make sense to
+ add or remove entries in the "Interfaces" dictionary, since the
+ contents of that array is dictated by the hardware. For each array
+ in the data tree, RFC-1024 indicates whether CREATE and DELETE are
+ valid.
+
+ CREATE and DELETE are always invalid in non-array contexts. If
+ DELETE were allowed on monitored data, then the deleted data would
+ become unmonitorable to the entire world. Conversely, if it were
+ possible to CREATE arbitrary dictionary entries, there would be no
+ way to give such entries any meaning. Even with the data in place,
+ there is nothing that would couple the data to the operation of the
+ monitored entity. [Creation and deletion would also add considerable
+ complication to an implementation, because without them, all of the
+ data structures that represent the data tree are essentially static,
+ with the exception of dynamic tables such as the ones mentioned,
+ which already have mechanisms in place for adding and removing
+ entries.]
+
+8.6 Associative Data Access: Filters
+
+ One problem that has not been dealt with was alluded to earlier: When
+ dealing with array data, how do you specify one or more entries based
+ upon some value in the array entries? Consider the situation where
+ there are several interfaces. The data might be organized as:
+
+ Interfaces { -- one per interface
+ InterfaceData { address, mtu, netMask, ARP{...}, ... }
+ InterfaceData { address, mtu, netMask, ARP{...}, ... }
+ :
+ }
+
+ If you only want information about one interface (perhaps because
+
+
+
+Trewitt & Partridge [Page 21]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ there is an enormous amount of data about each), then you have to
+ have some way to name it. One possibility would be to just number
+ the interfaces and refer to the desired interface as
+ InterfaceData(3)
+ for the third one.
+
+ But this is not sufficient, because interface numbers may change over
+ time, perhaps from one reboot to the next. It is even worse when
+ dealing with arrays with many elements, such as routing tables, TCP
+ connections, etc. Large, changing arrays are probably the more
+ common case, in fact. Because of the lack of utility of indexing in
+ this context, there is no general mechanism provided in the language
+ for indexing.
+
+ A better scheme is to select objects based upon some value contained
+ in them, such as the IP address. The query language uses filters to
+ select specific table entries that an operator will operate on. The
+ operators BEGIN, GET, GET-ATTRIBUTES, SET, and DELETE can take a
+ filter argument that restricts their operation to entries that match
+ the filter.
+
+ A filter is a boolean expression that is executed for each element in
+ an array. If an array entry "matches" the filter (i.e., if the filter
+ produces a "true" result), then it is used by the operation. A
+ filter expression is very restricted: it can only compare data
+ contained in the array element and the comparisons are only against
+ constants. Comparisons may be connected by AND, OR and NOT
+ operators.
+
+ The ASN.1 definition of a filter is:
+
+ Filter ::= [APPLICATION 2] CHOICE {
+ present [0] DataPath,
+ equal [1] DataValue,
+ greaterOrEqual [2] DataValue,
+ lessOrEqual [3] DataValue,
+ and [4] SEQUENCE OF Filter,
+ or [5] SEQUENCE OF Filter,
+ not [6] Filter
+ }
+
+ DataPath ::= ANY -- Path with no value
+
+ DataValue ::= ANY -- Single data value
+
+ This definition is similar to the filters used in the ISO monitoring
+ protocol (CMIP) and was derived from that specification.
+
+
+
+
+Trewitt & Partridge [Page 22]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ "DataPath" is the name of a single data item; "DataValue" is the
+ value of a single data item. The three comparisons are all of the
+ form "data OP constant", where "data" is the value from the tree,
+ "constant" is the value from the filter expression, and "OP" is one
+ of equal, greater-than-or-equal, or less-than-or-equal. The last
+ operation, "present", tests to see if the named item exists in the
+ data tree. By its nature, it requires no value, so only a path needs
+ to be given.
+
+ Here is an example of a filter that matches an Interface whose IP
+ address is 10.1.0.1:
+ Filter{ equal{ address(10.0.0.51) } }
+ Note that the name of the data to be compared is relative to the
+ "InterfaceData" dictionary.
+
+ Each operator, when given a filter argument, takes an array
+ (dictionary containing only one type of item) as its first argument.
+ In the current example, this would be "Interfaces". The items in it
+ are all of type "InterfaceData". This tag is referred to as the
+ "iteration tag".
+
+ Before a filtered operation is used, BEGIN must be used to put the
+ array (dictionary) on top of the stack, to establish it as the
+ context that the filter iterates over. The general operation of a
+ filtered operation is then:
+
+ 1. Iterate over the items in the array.
+
+ 2. For each element in the array, execute the filter.
+
+ 3. If the filter succeeds, do the requested operation
+ (GET/SET/etc.) on the matched element, using the
+ template/value/path as input to the operation. At this
+ point, the execution of the operation is the same as in
+ the non-filtered case.
+
+ This is a model of operation; actual implementations may take
+ advantage of whatever lookup techniques are available for the
+ particular table (array) involved.
+
+ Therefore, there are three inputs to a filtered operation:
+
+ 1. The "current dictionary" on the stack. This is the
+ array-type dictionary to be searched, set by an earlier
+ BEGIN.
+
+ 2. A filter, to test each item in the array. Each path or
+ value mentioned in the filter must be named in the context
+
+
+
+Trewitt & Partridge [Page 23]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ of an item in the array, as if it was the current
+ dictionary. For example, in the case where a filtered
+ operation iterates over the set of "InterfaceData" items
+ in the "Interfaces" array, each value or path in the
+ filter should name an item in the "InterfaceData"
+ dictionary, such as "address".
+
+ 3. A template, path, or value associated with the operation
+ to be performed. The leading ASN.1 tag in this must match
+ the iteration tag. In the current example where the
+ filter is searching the "Interfaces" dictionary, the first
+ tag in the template/tag/value must be "InterfaceData".
+
+ The operators which take filters as arguments are:
+
+ BEGIN array path filter BEGIN array dict
+ Find a dictionary in <array> that matches <filter>. Use
+ that as the starting point for <path> and push the
+ dictionary corresponding to <path> onto the stack. If more
+ than one dictionary matches <filter>, then any of the
+ matches may be used. This specification does not state how
+ the choice is made. At least one dictionary must match; it
+ is an error if there are no matches. (Perhaps it should be
+ an error for there to be multiple matches; actual
+ experience is needed to decide.)
+
+ GET array template filter GET array
+ For each item in <array> that matches <filter>, fill in the
+ template with values from the data tree and emit the
+ result. The first tag of <template> must be equal to the
+ iteration tag. Selected parts of matched items are emitted
+ based upon <template>, just as in a non-filtered GET
+ operation.
+
+ GET-ATTRIBUTES
+ array template filter GET-ATTRIBUTES array
+ Same as GET, except emit attributes rather than data
+ values.
+
+ SET array value filter SET array
+ Same as GET, except set the values in <value> rather than
+ retrieving values. Several values in the data tree will be
+ changed if the filter matches more than one item in the
+ array.
+
+ DELETE array filter DELETE array
+ Delete the entry(s) in <array> that match <filter>.
+
+
+
+
+Trewitt & Partridge [Page 24]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ Notes about filter execution:
+
+ - Expressions are executed by inorder tree traversal.
+
+ - Since the filter operations are all GETs and comparisons,
+ there are no side-effects to filter execution, so an
+ implementation is free to execute only as much of the
+ filter as required to produce a result (e.g., don't execute
+ the rest of an AND if the first comparison turns out to be
+ false).
+
+ - It is not an error for a filter to test a data item that
+ isn't in the data tree. In this situation, the comparison
+ just fails (is false). This means that filters don't need
+ to test for the existence of optional data before
+ attempting to compare it.
+
+ Here is an example of how filtering would be used to obtain the input
+ and output packet counts for the interface with IP address 10.0.0.51.
+
+ Interfaces BEGIN -- dictionary
+ InterfaceData{ pktsIn, pktsOut } -- template
+ Filter{ equal{ address(10.0.0.51) } }
+ GET
+ END -- finished with dict
+
+ The returned value would be something like:
+
+ Interfaces{ -- BEGIN
+ InterfaceData{ pktsIn(1345134), pktsOut(1023729) }
+ -- GET
+ } -- END
+
+ The annotations indicate which part of the response is generated by
+ the different operators in the query.
+
+ Here is an example of accessing a table contained within some other
+ table. Suppose we want to get at the ARP table for the interface
+ with IP address 36.8.0.1 and retrieve the entire ARP entry for the
+ host with IP address 36.8.0.23. In order to retrieve a single entry
+ in the ARP table (using a filtered GET), a BEGIN must be used to get
+ down to the ARP table. Since the ARP table is contained within the
+ Interfaces dictionary (an array), a filtered BEGIN must be used.
+
+ Interfaces BEGIN -- dictionary
+ InterfaceData{ ARP } -- path
+ Filter{ equal{ address(36.8.0.1) } } -- filter
+ BEGIN -- filtered BEGIN
+
+
+
+Trewitt & Partridge [Page 25]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ -- Now in ARP table for 38.0.0.1; get entry for 38.8.0.23.
+ addrMap -- whole entry
+ Filter{ equal{ ipAddr(36.8.0.23) } } -- filter
+ GET -- filtered GET
+ END
+ END
+
+ The result would be:
+
+ Interfaces{ -- first BEGIN
+ InterfaceData{ ARP{ -- second BEGIN
+ addrMap{ ipAddr(36.8.0.23), physAddr(..) } -- from GET
+ } } -- first END
+ } -- second END
+
+ Note which parts of the output are generated by different parts of
+ the query.
+
+ Here is an example of how the SET operator would be used to shut down
+ the interface with ip-address 10.0.0.51 by changing its status to
+ "down".
+
+ Interfaces BEGIN -- get dictionary
+ Interface{ Status(down) } -- value to set
+ Filter{ equal{ IP-addr(10.0.0.51) } }
+ SET
+ END
+
+ If the SET is successful, the result would be:
+
+ Interfaces{ -- BEGIN
+ Interface{ Status(down) } -- from SET
+ } -- END
+
+8.7 Terminating a Query
+
+ A query is implicitly terminated when there are no more ASN.1 objects
+ to be processed by the interpreter. For a perfectly-formed query,
+ the interpreter would be back in the state it was when it started:
+ the stack would have only the root dictionary on it, and all of the
+ ASN.1 objects in the result would be terminated.
+
+ If there are still "open" ASN.1 objects in the result (caused by
+ leaving ENDs off of the query), then these are closed, as if a
+ sufficient number of ENDs were provided. This condition would be
+ indicated by the existence of dictionaries other than the root
+ dictionary on the stack.
+
+
+
+
+Trewitt & Partridge [Page 26]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ If an extra END is received that would pop the root dictionary off of
+ the stack, the query is terminated immediately. No error is
+ generated.
+
+9. EXTENDING THE SET OF VALUES
+
+ There are two ways to extend the set of values understood by the
+ query language. The first is to register the data and its meaning
+ and get an ASN.1 tag assigned for it. This is the preferred method
+ because it makes that data specification available for everyone to
+ use.
+
+ The second method is to use the VendorSpecific application type to
+ "wrap" the vendor-specific data. Wherever an implementation defines
+ data that is not in RFC-1024, the "VendorSpecific" tag should be used
+ to label a dictionary containing the vendor-specific data. For
+ example, if a vendor had some data associated with interfaces that
+ was too strange to get standard numbers assigned for, they could,
+ instead represent the data like this:
+
+ interfaces {
+ interface {
+ in-pkts, out-pkts, ...
+ VendorSpecific { ephemeris, declination }
+ }
+ }
+
+ In this case, ephemeris and declination correspond to two context-
+ dependent tags assigned by the vendor for their non-standard data.
+
+ If the vendor-specific method is chosen, the private data MUST have
+ descriptions available through the GET-ATTRIBUTES operator. Even
+ with this descriptive ability, the preferred method is to get
+ standard numbers assigned if possible.
+
+10. AUTHORIZATION
+
+ This specification does not state what type of authorization system
+ is used, if any. Different systems may have needs for different
+ mechanisms (authorization levels, capability sets, etc.), and some
+ systems may not care about authorization at all. The only effect
+ that an authorization system has on a query is to restrict what data
+ items in the tree may be retrieved or modified.
+
+ Therefore, there are no explicit query language features that deal
+ with protection. Instead, protection mechanisms are implicit and may
+ make some of the data invisible (for GET) or non-writable (for SET):
+
+
+
+
+Trewitt & Partridge [Page 27]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ - Each query runs with some level of authorization or set of
+ capabilities, determined by its environment (HEMS and the
+ HEMP header).
+
+ - Associated with each data item in the data tree is some
+ sort of test to determine if a query's authorization should
+ grant it access to the item.
+
+ Authorization tests are only applied to query language operations
+ that retrieve information (GET, GET-ATTRIBUTES, and GET-RANGE) or
+ modify it (SET, CREATE, DELETE). An authorization system must not
+ affect the operation of BEGIN and END. In particular, the
+ authorization must not hide entire dictionaries, because that would
+ make a BEGIN on such a dictionary fail, terminating the entire query.
+
+11. ERRORS
+
+ If some particular information is requested but is not available, it
+ will be returned as "no-value" by giving the ASN.1 length as 0.
+
+ When there is any other kind of error, such as having improper
+ arguments on the top of the stack or trying to execute BEGIN when the
+ path doesn't refer to a dictionary, an ERROR object is emitted.
+
+ The contents of this object identify the exact nature of the error:
+
+ Error ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+ errorCode INTEGER,
+ errorInstance INTEGER,
+ errorOffset INTEGER
+ errorDescription IA5String,
+ errorOp INTEGER,
+ }
+
+ errorCode identifies what the error was, and errorInstance is an
+ implementation-dependent code that gives a more precise indication of
+ where the error occured. errorOffset is the location within the
+ query where the error occurred. If an operation was being executed,
+ errorOp contains its operation code, otherwise zero.
+ errorDescription is a text string that can be printed that gives some
+ description of the error. It will at least describe the errorCode,
+ but may also give details implied by errorInstance. Detailed
+ definitions of all of the fields are given in appendix I.2.
+
+ Since there may be several unterminated ASN.1 objects in progress at
+ the time the error occurs, each one must be terminated. Each
+ unterminated object will be closed with a copy of the ERROR object.
+ Depending upon the type of length encoding used for this object, this
+
+
+
+Trewitt & Partridge [Page 28]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ will involve filling the value for the length (definite length form)
+ or emitting two zero octets (indefinite length form). After all
+ objects are terminated, a final copy of the ERROR object will be
+ emitted. This structure guarantees that the error will be noticed at
+ every level of interpretation on the receiving end.
+
+ In summary, if there was an error before any ASN.1 objects were
+ generated, then the result would simply be:
+ error{...}
+
+ If a couple of ASN.1 objects were unterminated when the error
+ occurred, the result might look like:
+ interfaces{
+ interface { name(...) type(...) error{...} }
+ error{...}
+ }
+ error{...}
+
+ It would be possible to define a "WARNING" object that has a similar
+ (or same) format as ERROR, but that would be used to annotate
+ responses when a non-fatal "error" occurs, such as attempting to
+ SET/CREATE/DELETE and the operation is denied. This would be an
+ additional complication, and we left it out in the interests of
+ simplicity.
+
+I. ASN.1 DESCRIPTIONS OF QUERY LANGUAGE COMPONENTS
+
+ A query consists of a sequence of ASN.1 objects, as follows:
+
+ Query := IMPLICIT SEQUENCE of QueryElement;
+
+ QueryElement ::= CHOICE {
+ Operation,
+ Filter,
+ Template,
+ Path,
+ InputValue
+ }
+
+ Operation and Filter are defined below. The others are:
+
+ Template ::= any
+ Path ::= any
+ InputValue ::= any
+
+ These three are all similar, but have different restrictions on their
+ structure:
+
+
+
+
+Trewitt & Partridge [Page 29]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ Template Specifies a portion of the tree, naming one or more
+ values, but not containing any values.
+
+ Path Specifies a single path from one point in the tree to
+ another, naming exactly one value, but not containing
+ a value.
+
+ InputValue Gives a value to be used by a query language
+ operator.
+
+
+
+ A query response consists of a sequence of ASN.1 objects, as follows:
+
+ Response := IMPLICIT SEQUENCE of ResponseElement;
+
+ ResponseElement ::= CHOICE {
+ ResultValue,
+ Error
+ }
+
+ Error is defined below. The others are:
+
+ ResultValue ::= any
+
+ ResultValue is similar to Template, above:
+
+ ResultValue Specifies a portion of the tree, naming and
+ containing one or more values.
+
+ The distinctions between these are elaborated in section 6.
+
+I.1 Operation Codes
+
+ Operation codes are all encoded in a single application-specific
+ type, whose value determines the operation to be performed. The
+ definition is:
+
+ Operation ::= [APPLICATION 1] IMPLICIT INTEGER {
+ reserved(0),
+ begin(1),
+ end(2),
+ get(3),
+ get-attributes(4),
+ get-range(5),
+ set(6),
+
+
+
+
+
+Trewitt & Partridge [Page 30]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ create(7),
+ delete(8)
+ }
+
+I.2 Error Returns
+
+ An Error object is returned within a reply when an error is
+ encountered during the processing of a query. Note that the
+ definition this object is similar to that of the HEMP protocol error
+ structure. The error codes have been selected to keep the code
+ spaces distinct between the two. This is intended to ease the
+ processing of error messages. See section 11 for more information.
+
+ Error ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+ errorCode INTEGER,
+ errorInstance INTEGER,
+ errorOffset INTEGER
+ errorDescription IA5String,
+ errorOp INTEGER,
+ }
+
+ The fields are defined as follows:
+
+ errorCode Identifies the general cause of the error.
+
+ errorInstance An implementation-dependent code that gives a more
+ precise indication of where the error occured in the
+ query processor. This is most useful when internal
+ errors are reported.
+
+ errorOffset The location within the query where the error was
+ detected. The first octet of the query is numbered
+ zero.
+
+ errorOp If an operation was being executed, this contains its
+ operation code, otherwise zero.
+
+ errorDescription
+ A text string that can be printed that gives some
+ description of the error. It will at least describe
+ the errorCode, but may also give details implied by
+ errorInstance.
+
+ Some errors are associated with the execution of specific operations,
+ and others with the overall operation of the query interpreter. The
+ errorCodes are split into two groups.
+
+ The first group deals with overall interpreter operation. Except for
+
+
+
+Trewitt & Partridge [Page 31]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ "unknown operation", these do not set errorOp.
+
+ 100 Other error.
+ Any error not listed below.
+
+ 101 Format error.
+ An error has been detected in the format of the input
+ stream, preventing further interpretation of the
+ query.
+
+ 102 System error.
+ The query processor has failed in some way due to an
+ internal error.
+
+ 103 Stack overflow.
+ Too many items were pushed on the stack.
+
+ 104 Unknown operation.
+ The operation code is invalid. errorOp is set.
+
+ The second group is errors that are associated with the execution of
+ particular operations. errorOp will always be set for these.
+
+ 200 Other operation error.
+ Any error, associated with an operation, not listed
+ below.
+
+ 201 Stack underflow.
+ An operation expected to see some number of operands
+ on the stack, and there were fewer items on the
+ stack.
+
+ 202 Operand error.
+ An operation expected to see certain operand types on
+ the stack, and something else was there.
+
+ 203 Invalid path for BEGIN.
+ A path given for BEGIN was invalid, because some
+ element in the path didn't exist.
+
+ 204 Non-dictionary for BEGIN.
+ A path given for BEGIN was invalid, because the given
+ node was a leaf node, not a dictionary.
+
+ 205 BEGIN on array element.
+ The path specified an array element. The path must
+ point at a single, unique, node. A filtered BEGIN
+ should have been used.
+
+
+
+Trewitt & Partridge [Page 32]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ 206 Empty filter for BEGIN.
+ The filter for a BEGIN didn't match any array
+ element.
+
+ 207 Filtered operation on non-array.
+ A filtered operation was attempted on a regular
+ dictionary. Filters can only be used on arrays.
+
+ 208 Index out of bounds.
+ The starting address or length for a GET-RANGE
+ operation went outside the bounds for the given
+ object.
+
+ 209 Bad object for GET-RANGE.
+ GET-RANGE can only be applied to objects whose base
+ type is OctetString.
+
+ This list is probably not quite complete, and would need to be
+ extended, based upon implementation experience.
+
+I.3 Filters
+
+ Many of the operations can take a filter argument to select among
+ elements in an array. They are discussed in section 8.6.
+
+
+ Filter ::= [APPLICATION 2] CHOICE {
+ present [0] DataPath,
+ equal [1] DataValue,
+ greaterOrEqual [2] DataValue,
+ lessOrEqual [3] DataValue,
+ and [4] SEQUENCE OF Filter,
+ or [5] SEQUENCE OF Filter,
+ not [6] Filter
+ }
+
+ DataPath ::= ANY -- Path with no value
+
+ DataValue ::= ANY -- Single data value
+
+ A filter is executed by inorder traversal of its ASN.1 structure.
+
+ The basic filter operations are:
+
+ present tests for the existence of a particular data item in
+ the data tree
+
+
+
+
+
+Trewitt & Partridge [Page 33]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ equal tests to see if the named data item is equal to the
+ given value.
+
+ greaterOrEqual tests to see if the named data item is greater than
+ or equal to the given value.
+
+ lessOrEqual tests to see if the named data item is less than or
+ equal to the given value.
+
+ These may be combined with "and", "or", and "not" operators to form
+ arbitrary boolean expressions. The "and" and "or" operators will
+ take any number of terms. Terms are only evaluated up to the point
+ where the outcome of the expression is determined (i.e., an "and"
+ term's value is false or an "or" term's value is true).
+
+I.4 Attributes
+
+ One or more Attributes structure is returned by the GET-ATTRIBUTES
+ operator. This structure provides descriptive information about
+ items in the data tree. See the discussion in section 8.3.
+
+ Attributes ::= [APPLICATION 3] IMPLICIT SEQUENCE {
+ tagASN1 [0] IMPLICIT INTEGER,
+ valueFormat [1] IMPLICIT INTEGER,
+ longDesc [2] IMPLICIT IA5String OPTIONAL,
+ shortDesc [3] IMPLICIT IA5String OPTIONAL,
+ unitsDesc [4] IMPLICIT IA5String OPTIONAL,
+ precision [5] IMPLICIT INTEGER OPTIONAL,
+ properties [6] IMPLICIT BITSTRING OPTIONAL,
+ valueSet [7] IMPLICIT SET OF valueDesc OPTIONAL
+ }
+ valueDesc ::= IMPLICIT SEQUENCE {
+ value [0] ANY, -- Single data value
+ desc [1] IA5String
+ }
+
+ The meanings of the various attributes are given below.
+
+ tagASN1 The ASN.1 tag for this object. This attribute is
+ required.
+
+ valueFormat The underlying ASN.1 type of the object (e.g.,
+ SEQUENCE or OCTETSTRING or Counter). This is not
+ just the tag number, but the entire tag, as it would
+ appear in an ASN.1 object. As such, it includes the
+ class, which should be either UNIVERSAL or
+ APPLICATION. Applications receiving this should
+
+
+
+
+Trewitt & Partridge [Page 34]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ ignore the constructor bit. This attribute is
+ required.
+
+ longDesc A potentially lengthy text description which fully
+ defines the object. This attribute is optional for
+ objects defined in this memo and required for
+ entity-specific objects.
+
+ shortDesc A short mnemonic string of less than 15 characters,
+ suitable for labeling the value on a display. This
+ attribute is optional.
+
+ unitsDesc A short string used for integer values to indicate
+ the units in which the value is measured (e.g., "ms",
+ "sec", "pkts", etc.). This attribute is optional.
+
+ precision For Counter objects, the value at which the Counter
+ will roll-over. Required for all Counter objects.
+
+ properties A bitstring of boolean properties of the object. If
+ the bit is on, it has the given property. This
+ attribute is optional. The bits currently defined
+ are:
+
+ 0 If true, the difference between two values of
+ this object is significant. For example, the
+ changes of a packet count is always significant,
+ it always conveys information. In this case, the
+ 0 bit would be set. On the other hand, the
+ difference between two readings of a queue length
+ may be meaningless.
+
+ 1 If true, the value may be modified with SET,
+ CREATE, and DELETE. Applicability of CREATE and
+ DELETE depends upon whether the object is in an
+ array.
+
+ 2 If true, the object is a dictionary, and a BEGIN
+ may be used on it. If false, the object is leaf
+ node in the data tree.
+
+ 3 If true, the object is an array-type dictionary,
+ and filters may be used to traverse it. (Bit 2
+ will be true also.)
+
+ valueSet For data that is defined as an ASN.1 CHOICE type (an
+ enumerated type), this gives descriptions for each of
+ the possible values that the data object may assume.
+
+
+
+Trewitt & Partridge [Page 35]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ Each valueDesc is a <value,description> pair. This
+ information is especially important for control
+ items, which are very likely to appear in
+ VendorSpecific dictionaries, exactly the situation
+ where descriptive information is needed.
+
+I.5 VendorSpecific
+
+ See the discussion in section 9.
+
+ VendorSpecific ::= [APPLICATION 4] IMPLICIT SET
+ of ANY
+
+II. IMPLEMENTATION HINTS
+
+ Although it is not normally in the spirit of RFCs to define an
+ implementation, the authors feel that some suggestions will be useful
+ to implementors of the query language. This list is not meant to be
+ complete, but merely to give some hints about how the authors imagine
+ that the query processor might be implemented efficiently.
+
+ - It should be understood that the stack is of very limited
+ depth. Because of the nature of the query language, it can
+ get only about 4 entries (for arguments) plus the depth of
+ the tree (up to one BEGIN per level in the tree). This
+ comes out to about a dozen entries in the stack, a modest
+ requirement.
+
+ - The stack is an abstraction -- it should be implemented
+ with pointers, not by copying dictionaries, etc.
+
+ - An object-oriented approach should make implementation
+ fairly easy. Changes to the "shape" if the data items
+ (which will certainly occur, early on) will also be easier
+ to make.
+
+ - Only a few "messages" need to be understood by objects. By
+ having pointers to action routines for each basic operation
+ (GET,SET,...) associated with each node in the tree, common
+ routines (e.g., emit a long integer located at address X)
+ can be shared, and special routines (e.g., set the interface
+ state for interface X) can be implemented in a common
+ framework. Higher levels need know nothing about what data
+ is being dealt with.
+
+ - Most interesting objects are dictionaries, each of which
+ can be implemented using pointers to the data and procedure
+ "hooks" to perform specific operations such as GET, SET,
+
+
+
+Trewitt & Partridge [Page 36]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ filtering, etc.
+
+ - The hardest part is actually extracting the data from
+ existing TCP/IP implementations that weren't designed with
+ detailed monitoring in mind. Query processors interfacing
+ to a UNIX kernel will have to make many system calls in
+ order to extract some of the more intricate structures,
+ such as routing tables. This should be less of a problem
+ if a system is designed with easy monitoring as a goal.
+
+A Skeletal Implementation
+
+ This section gives a rather detailed example of the core of a query
+ processor. This code has not been tested, and is intended only to
+ give implementors ideas about how to tackle some aspects of query
+ processor implementation with finesse, rather than brute force.
+
+ The suggested architecture is for each dictionary to have a
+ "traverse" routine associated with it, which is called when any sort
+ of operation has to be done on that dictionary. Most nodes will
+ share the same traversal routine, but array dictionaries will usually
+ have routines that know about whatever special lookup mechanisms are
+ required.
+
+ Non-dictionary nodes would have two routines, "action", and
+ "compare", which implement query language operations and filter
+ comparisons, respectively. Most nodes would share these routines.
+
+ For example, there should be one "action" routine that does query
+ language operations on 32-bit integers, and another that works on
+ 16-bit integers, etc.
+
+ Any traversal procedure would take arguments like:
+
+ traverse(node, mask, op, filter)
+ Treenode node; /* generic node-in-tree */
+ ASN mask; /* internal ASN.1 form */
+ enum opset op; /* what to do */
+ Filter filter; /* zero if no filter */
+
+ enum opset { begin, get, set, create, delete, geta,
+ c_le, c_ge, c_eq, c_exist };
+
+ The traversal procedure is called whenever anything must be done
+ within a dictionary. The arguments are:
+
+ node the current dictionary.
+
+
+
+
+Trewitt & Partridge [Page 37]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ mask is either the template, path, or value, depending
+ upon the operation being performed. The top-level
+ identifier of this object will be looked up in the
+ context of <node>.
+
+ op is the operation to be performed, either one of the
+ basic operations, or a filter operation.
+
+ filter is the filter to be applied, or zero if none. There
+ will be no filter when <op> is a filter-comparison
+ operation.
+
+ The general idea is that the traversal proc associated with a node
+ has all of the knowledge about how to get around in this subtree
+ encoded within it. Hopefully, this will be the only place this
+ knowledge is coded. Here is a skeleton of the "standard" traversal
+ proc, written mostly in C.
+
+ When the query processor needs to execute a "GET" operation, it would
+ just call:
+ traverse(current, template, GET, 0)
+
+ Notes about this example:
+
+ - This traversal routine handles either query language
+ operations (GET, SET, etc.) or low-level filter operations.
+ Separate routines could be defined for the two classes of
+ operations, but they do much of the same work.
+
+ - Dictionary nodes have a <traversal> proc defined.
+
+ - Leaf nodes have an <action> proc, which implement GET, SET,
+ GET-ATTRIBUTES, CREATE, and DELETE, and a <compare> proc,
+ which performs low-level filter comparisons.
+
+ - In the generic routine, the filter argument is unused,
+ because the generic routine isn't used for array
+ dictionaries, and only array dictionaries use filters.
+
+ - An ASN type contains the top level tag and a list of
+ sub-components.
+
+ - size(mask) takes an ASN.1 object and tells how many
+ sub-items are in it. Zero means that this is a simple
+ object.
+
+ - lookup(node, tag) looks up a tag in the given (tree)node,
+ returning a pointer to the node. If the tag doesn't exist
+
+
+
+Trewitt & Partridge [Page 38]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ in that node, a pointer to a special node "NullItem" is
+ returned. NullItem looks like a leaf node and has procs
+ that perform the correct action for non-existent data.
+
+ - This example does not do proper error handling, or ASN.1
+ generation, both of which would require additional code in
+ this routine.
+
+ /*
+ * For op = GET/SET/etc, return:
+ * true on error, otherwise false.
+ * When op is a filter operation, return:
+ * the result of the comparison.
+ */
+ int std_traverse(node, mask, op, filter)
+ Treenode node; /* current node */
+ ASN mask; /* internal ASN.1 form */
+ enum opset op; /* what to do */
+ Filter filter; /* unused in this routine */
+ {
+ ASN item;
+ Treenode target;
+ boolean rv = false;
+ extern Treenode NullItem;
+
+ if (filter != null) {
+ error(...);
+ return true;
+ }
+
+ target = lookup(node, mask.tag);
+
+ /* We are at the leaf of the template/path/value. */
+ if (size(mask) == 0)
+ switch (op)
+ {
+ case BEGIN:
+ /* non-existent node, or leaf node */
+ if (target == NullItem || target.traverse == 0) {
+ error(...);
+ return true;
+ }
+ else {
+ begin(node, mask.tag);
+ return false;
+ }
+
+ case GET: case SET: case GETA:
+
+
+
+Trewitt & Partridge [Page 39]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ case GETR: case CREATE: case DELETE:
+ /* A leaf in the mask specifies entire directory.
+ For GET, traverse the entire subtree. */
+ if (target.traverse)
+ if (op == GET) {
+ foreach subnode in target
+ /* Need to test to not GET memory. */
+ rv |= (*target.traverse)
+ (target, subnode.tag, op, 0);
+ return rv;
+ }
+ else if (op == SET) /* no-op */
+ return false;
+ else if (op != GETA) {
+ error(...);
+ return true;
+ }
+ /* We're at a leaf in both the mask and the tree.
+ Just execute the operation.
+ */
+ else {
+ if (op == BEGIN) { /* Can't begin on leaf */
+ error(...);
+ return true;
+ else
+ return (*target.action)(target, mask, op);
+ }
+ } /* else */
+
+ default: /* Comparison ops. */
+ return (*target.compare)(target, mask, op);
+ } /* switch */
+
+ /* We only get here if mask has structure. */
+
+ /* can't have multiple targets for BEGIN */
+ if (op == BEGIN && size(mask) != 1) {
+ error(...);
+ return true;
+ }
+ /* or for a single filter operation. */
+ if (op is comparison && size(mask) != 1) {
+ error(...);
+ return false;
+ }
+ /* Iterate over the components in mask */
+ foreach item in mask
+ {
+
+
+
+Trewitt & Partridge [Page 40]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+ if (target.traverse) /* traverse subtree. */
+ rv |= (*component.traverse)(component, item, op, 0);
+ else /* leaf node, at last. */
+ if (op is comparison)
+ return (*target.compare)(target, mask, op);
+ else
+ return (*target.action)(target, mask, op);
+ } /* foreach */
+
+ return rv;
+ } /* std_traverse */
+
+
+ Here is a bare skeleton of an array-type dictionary's traversal proc.
+
+ int array_traverse(node, mask, op, filter)
+ Treenode node; /* current node */
+ ASN mask; /* internal ASN.1 form */
+ enum opset op; /* what to do */
+ Filter filter; /* unused in this routine */
+ {
+ Treenode target;
+ boolean rv = false;
+ extern Treenode NullItem;
+
+ /* Didn't find that key. */
+ if (mask.tag != this array's iteration tag)
+ return false;
+
+ if (op == BEGIN && filter == null) {
+ error(...);
+ return 1;
+ }
+
+ /* The implementation of this loop is the major trick! */
+ /* Needs to stop after first filter success on BEGIN. */
+ foreach target in node {
+ if (filter == null || /* if no filter, or */
+ ExecFilter(target, filter)) /* if it succeeds */
+ rv |= (target.traverse*)(target, mask, op, 0);
+ }
+ } /* array_traverse */
+
+ Object-oriented programming languages, such as C++, Modula, and Ada,
+ are well suited to this style of implementation. There should be no
+ particular difficulty with using a conventional language such as C or
+ Pascal, however.
+
+
+
+
+Trewitt & Partridge [Page 41]
+
+RFC 1076 HEMS Monitoring and Control Language November 1988
+
+
+III. OBTAINING A COPY OF THE ASN.1 SPECIFICATION
+
+ Copies of ISO Standard ASN.1 (Abstract Syntax Notation 1) are
+ available from the following source. It comes in two parts; both are
+ needed:
+
+ IS 8824 -- Specification (meaning, notation)
+ IS 8825 -- Encoding Rules (representation)
+
+ They are available from:
+
+ Omnicom Inc.
+ 115 Park St, S.E. (new address as of March, 1987)
+ Vienna, VA 22180
+ (703) 281-1135
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Trewitt & Partridge [Page 42]
+ \ No newline at end of file