diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-11-27 20:54:24 +0100 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-11-27 20:54:24 +0100 |
commit | 4bfd864f10b68b71482b35c818559068ef8d5797 (patch) | |
tree | e3989f47a7994642eb325063d46e8f08ffa681dc /doc/rfc/rfc1076.txt | |
parent | ea76e11061bda059ae9f9ad130a9895cc85607db (diff) |
doc: Add RFC documents
Diffstat (limited to 'doc/rfc/rfc1076.txt')
-rw-r--r-- | doc/rfc/rfc1076.txt | 2355 |
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 |