RFC 1856
The Opstat Client-Server Model for Statistics Retrieval
The Opstat Client-Server Model for Statistics Retrieval ๐ฆ
Request For Comments: 1856 ๐ This one's by H. Clark of BBN Planet, and it's marked as Category: Informational, dated September 1995. It doesn't obsolete or update any other RFCs, so it's a fresh little gem on its own. โจ
Status of this Memo
Okay, first the legal bit ๐ . This memo gives information to the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited. ๐ธ
Abstract
Network admins collect a ton of data about how their networks are doing: performance, utilization, usability, and growth ๐. We're talking several megabytes to several gigabytes every single month, which is a LOT ๐ญ. Right now there are basically zero (if any) tools for sharing that raw data between network operators, or between a network service provider (NSP) and its customers. This document defines a model and protocol for a set of tools that NSPs and Network Operation Centers (NOCs) could use to share data with each other and with customers. ๐ง
1.0 Introduction โจ
Network admins gather data on performance, utilization, usability, and growth, just like we said above ๐. The main reason for gathering it is to help with quick problem isolation in the near term and network planning in the long term, inside the organization ๐. Again, the raw data is usually huge, around several megabytes to several gigabytes each month, and the admin turns that raw data into different types of reports ๐. Few (if any) tools exist for sharing that raw data among network operators, or between an NSP and its customers ๐. So this document defines a model and protocol for a set of tools that NSPs and NOCs could use to share data among themselves and with customers. ๐
1.1 The OPSTAT Model
Under the Operational Statistics model [1], there's a shared setup where tools exist to collect, store, retrieve, and present network management data ๐ง .
This document defines a protocol that lets a client on a remote machine pull data from a central server. That server then grabs the data from the common statistics database ๐๏ธ. The client shows the data to the user in whatever form they asked for (maybe in an X-window, or on paper) ๐จ๏ธ.
The retrieval methods in this document use a client-server model, and it's giving clean architecture ๐. Each NOC (or NSP) SHOULD install a server that provides its locally collected info to clients. Using a query language, the client SHOULD be able to define the network object of interest, the interface, the metrics, and the time period to be examined ๐ฏ. Over a reliable transport-layer protocol (e.g., TCP), the server will send the requested data ๐ฆ. Once the client gets that data, it can be processed and presented in a bunch of ways: a graph in an X window, PostScript sent to a printer, or raw data dumped onto the user's terminal ๐.
The rest of this document explains how the client and server interact, describes the protocol they use between them, and talks through a bunch of other issues around sharing data ๐ซถ.
2.0 Client-Server Description ๐
2.1 The Client
The client's whole job is to retrieve data from the server ๐งโโ๏ธ. It takes requests from the user, translates them into the common retrieval protocol, sends them to the server, waits for the server's reply, and then passes that reply back to the user ๐.
Quick note, though: this document does not define how the data should be presented to the user ๐ . There are lots of ways to do it, including:
- use an X-based tool that displays graphs (line, histogram, etc.)
- generate PostScript output to be sent to a printer
- dump the raw data to the user's terminal
Future documents based on the Operational Statistics model MAY define standard graphs and variables to be displayed, but that's still work to be done (as of this writing) ๐.
2.2 The Server
The server's basic job is to accept a connection from a client, take a series of commands from that client, do stuff based on those commands, and then close the connection ๐.
The server MUST have some kind of configuration file, which this document leaves undefined ๐๏ธ. That file would list the users who can access the server, along with the authentication they'll use ๐. The configuration file SHOULD also let you specify the data items each user SHOULD be permitted to access (and, by implication, the ones they're not allowed to access) ๐. Server security is specifically covered in Section 4, so keep that in mind ๐ก๏ธ.
3.0 Protocol Commands ๐
This section defines the commands that MAY be sent to the server, plus the server's responses to them ๐ฌ. The available commands are:
LOGIN - accept new connection
EXIT - disconnect
LIST - show available variables
SELECT - mark data for retrieval
STATUS - show the state of the server
GET - download data to the client
There's also a state machine describing the specific actions the server takes ๐. Server security concerns are covered in Section 4 too ๐.
Heads up: in some descriptions below, you'll see the term <ASCII-STRING>. This means printable ASCII characters, which are all the letters, numbers, and special characters like $, %, or * ๐ค. It specifically leaves out the control characters in the lower part of the character set (0x00 - 0x1F). Any of those control characters received by the server or client SHOULD be ignored ๐ โโ๏ธ.
3.1 Command Return Codes
The server sends its responses to the client in this format:
RETURN-INFO ::= <RETURN-CODE> " <ASCII-STRING> " | <RETURN-CODE>
RETURN-CODE ::= <MAIN-CODE><COMMAND><SUB-CODE>
MAIN-CODE ::= 1..9
COMMAND ::= 1..9
SUB-CODE ::= 0..9
For every command sent to the server, the server returns a three-digit numeric code that says how the operation went, plus optional ASCII text for humans ๐ค. The value of MAIN-CODE tells you what happened ๐:
1 Error
9 Success / Informational
The commands are encoded like this ๐ข:
1 LOGIN
2 SELECT
3 STATUS
4 LIST
5 GET
9 EXIT
These specific error codes MUST be supported by all servers and clients ๐ซถ:
110 Login Invalid
113 Scanning Error during LOGIN
120 SELECT Failed
130 STATUS Failed
140 LIST Failed
141 Bad LIST encoding
150 GET Failed
151 GET doesn't support that type of encoding
910 Login Accepted
920 SELECT successful
931 STATUS Output Starting
932 STATUS Output Done
941 LIST lookup successful, here comes the data!
942 LIST dump done!
951 GET lookup successful, here comes the data!
952 GET dump done!
990 Server closing connection after EXIT received
Other codes may be used, but they may not be supported by all clients or servers ๐คทโโ๏ธ.
3.2 The LOGIN Command ๐
The LOGIN command is how a user authenticates to the server ๐ชช. Its format is:
LOGIN-CMD ::= LOGIN <username> <auth-type>
USERNAME ::= " <ASCII-STRING> "
AUTH-TYPE ::= "none" | "password" | " <ASCII-STRING> "
CHAL-CMD ::= CHAL " <ASCII-STRING> "
AUTH-CMD ::= AUTH " <ASCII-STRING> "
The authentication types each server supports will vary, but they MUST include "none" and "password" ๐. A server MAY choose to allow logins through either of those methods, or not. What it MUST do is recognize those two special authentication types ๐ซก.
When the server processes a LOGIN command sequence, it first checks the username and the authentication type that were requested ๐ต๏ธโโ๏ธ. If the username is invalid (say, there's no such user the server knows about), or the server doesn't support the requested authentication type, the server MUST return a 110 error and MUST close the connection after faking the challenge/authentication process (see the examples below) ๐.
Once the username and authentication type pass those checks, a challenge MUST be sent ๐ฃ. The challenge depends on the type of authentication requested, and the ASCII string MAY be an empty string if no specific challenge is needed (like in the password-only case). The next command the client sends back MUST be an AUTH response, and if it isn't, the server MUST close the connection ๐ช. After processing the authentication info, the server MUST return a 910 code if authentication succeeds, or a 110 error message if it fails. And if authentication fails, the server MUST immediately close the connection ๐.
If a syntax error happens at any point during the LOGIN sequence (like the client sending the wrong number of arguments in the LOGIN command), the server MUST return a 113 error and close the connection ๐ โโ๏ธ.
If the special AUTH-TYPE of "none" is used, and the server allows the specified username (such as anonymous) to log in without authentication, the server SHOULD still send a "CHAL" response to get extra info about the person logging in ๐. The server MAY then choose to allow or disallow the login based on what comes back in the AUTH response ๐ง.
Here's an example of a requested authentication type that isn't valid ๐:
>LOGIN "cow" "s/key"
<CHAL "lo35098 98"
>AUTH "COW DOG BARK CAT MOO MEOW"
<110 "Login invalid"
The server didn't support S/Key, but it made it look to the user like it did ๐ญ. Here's an example of an authentication failure ๐ฌ:
>LOGIN "dog" "securid"
<CHAL "enter passcode"
>AUTH "103945"
<110 "Login invalid"
The user typed the wrong number for SecurID authentication ๐. Here are examples of a successful login โ :
>LOGIN "cat" "password"
<CHAL "send the dumb clear-text password"
>AUTH "foobar"
<910 "Login accepted"
or
>LOGIN "anonymous" "none"
<CHAL "tell me who you are anyway"
>AUTH "bessie@barn.farm.com"
<910 "Login accepted"
And here's an example of an invalid username ๐ โโ๏ธ:
>LOGIN "mule" "skey"
<CHAL "78 lo39065"
>AUTH "COW DOG FRED LOG COLD WAR"
<110 "Login invalid"
The server SHOULD have some kind of logging mechanism that records both successful and unsuccessful login attempts, so a system administrator can look through them ๐.
3.3 The EXIT Command ๐
The EXIT command disconnects the current user from the server ๐ชโจ. Its format is:
EXIT
Important ๐จ: when the server gets an EXIT command, it MUST always close the connection, even if returning an ERROR return code would normally be the right move ๐.
A sample EXIT command looks like this ๐:
>EXIT
<990 "OK, Bye now"
3.4. The SELECT Command โจ
Okay bestie, SELECT is the command that tags data so you can grab it later ๐ท๏ธ๐ Here's the format:
SELECT-COM ::= SELECT <NETWORK> <DEVICE> <INTERFACE> <VARNAME>
<GRANULARITY> <START-DATE> <START-TIME> <END-DATE>
<END-TIME> <AGG> <SELECT-COND>
NETWORK ::= <ASCII-STRING>
DEVICE ::= <ASCII-STRING>
INTERFACE ::= <ASCII-STRING>
VARNAME ::= <ASCII-STRING>
GRANULARITY ::= <ASCII-STRING>
START-DATE ::= <DATE-TYPE>
END-DATE ::= <DATE-TYPE>
DATE-TYPE ::= YYYY-MM-YY
START-TIME ::= <TIME-TYPE>
END-TIME ::= <TIME-TYPE>
TIME-TYPE ::= HH:MM:SS
AGG ::= <AGG-TYPE> | NULL
AGG-TYPE ::= TOTAL | PEAK
SELECT-COND ::= <SELECT-STMT> | NULL
SELECT-STMT ::= WITH DATA <COND-TYPE> <ASCII-STRING>
COND-TYPE ::= LE | GE | EQ | NE | LT | GT
So, if any conditional in your SELECT doesn't match what's actually in the database (like VARNAME, the S-DATE or E-DATE, or GRANULARITY), the server MUST return an ERROR ๐ซ (and hopefully a meaningful error message ๐ฅบ). The time values MUST be specified in GMT, and hours are in the range 0-23 โฐ. The granularity SHOULD always be specified in seconds.
Here's a sample query:
SELECT net rtr1 eth-0 ifInOctets 900 1992-01-01 00:00:00 1992-02-
01 23:59:59
This would select all data from network "net" device "rtr1" interface "eth-0" from Jan 1, 1992 @ 00:00:00 to Feb 1, 1992 @ 23:59:59 ๐
Aggregation tea ๐ต: if the client wants some kind of aggregation done on the data, the AGG field says how to do it (TOTAL or PEAK), and the GRANULARITY says what interval, in seconds, to aggregate to. For more on granularity types, check out [1]. If the server can't do the requested action, it MUST return a 120 error. The server MAY, if it wishes, use the codes 121-129 to say more about the specific error. Either way, it is RECOMMENDED that the server return ASCII text describing the error ๐
When the lookup finishes, SELECT MUST return an indication of whether the lookup worked and, if it did, the tag for that data ๐ฏ If the lookup was successful, the return code SHOULD be encoded as:
920 " TAG <ASCII-STRING> "
The word TAG works as a handle for the selected data on the server. Note that this single handle may refer to one or more specific SNMP variables (refer to [1] for a further explanation). ๐ฆ
If the tag "foobar" were assigned to the select example above, the OK would look like this:
920 "TAG foobar"
It is RECOMMENDED that the return tag string be less than 10 bytes long (this gives you lots of tag combinations ๐), although the server (and client) SHOULD be capable of handling arbitrary length strings. There's no requirement that the TAG have any particular meaning, and it MAY be composed of arbitrary strings ๐
The server MUST keep any internal information it needs during a session so that all SELECT tags can be processed by GET or other commands ๐ง If a server doesn't have the resources to process the given SELECT, it MUST return an error message ๐ฌ
It's the client's job to store information about the data each tag corresponds to. For example, if the server returned a tag "1234" for ifInOctet data for October 1993, the client MUST store that information somewhere, because the variables that match that tag can't be retrieved from the server again ๐ซถ
3.5. The STATUS Command ๐
The STATUS command shows the general state of the server, plus a list of all the data sets that have been tagged via SELECT. STATUS takes no arguments ๐ The output from a STATUS command looks like this:
STATUS-DATA ::= <SERVER-STATUS> <SERVER-TAG-LIST>
SERVER-STATUS ::= "STATUS= " <STATUS-FIELDS>
STATUS-FIELDS ::= "OK" | "NOT-OK"
SERVER-TAG-LIST ::= <SERVER-TAG> | NULL
SERVER-TAG ::= "TAG" <TAG-ID> "SIZE" <NUMBER>
The number in the SIZE field is how many octets of data that TAG represents ๐ฆ The server MUST return a 931 message before the STATUS output starts, and a 932 message at the end of it ๐ If any kind of failure happens, a 130 error message MUST be sent ๐ If the server prefers, it MAY send a message in the range 131-139 instead, but it is RECOMMENDED that the server always return ASCII describing the error that came up.
Here's a sample output:
>STATUS
<931 "STATUS Command Starting"
<STATUS= OK
<TAG 1234 SIZE 123456
<TAG ABCD SIZE 654321
<932 "STATUS Command successful"
or
>STATUS
<130 "Can't get STATUS right now, sorry."
or
>STATUS
<931 "STATUS Command Starting"
<STATUS= OK
<TAG 1234 SIZE 1
<131 "Oops, error reading TAG table, sorry."
3.6. The GET Command ๐
The GET command actually retrieves the data you picked with a previous SELECT ๐คฉ The format is:
GET-CMD ::= GET <TAG> <TYPE>
TAG ::= <ASCII-STRING>
TYPE ::= 1404 | <ASCII-STRING>
If the TAG matches a TAG the server returned from an earlier SELECT, then the tagged data comes back โจ If the TAG is invalid (meaning the server never assigned it), the server MUST return an error ๐ The TYPE sets the encoding of the data stream. All servers MUST support "1404" encoding. Other forms MAY be supported as desired.
If the server runs into trouble while retrieving the data, and some of it can't be pulled (say, some data it found during SELECT disappeared between the SELECT and the GET), then the server MUST return a 150 error ๐ญ If the client asks for an encoding type the server doesn't support, the server MUST return a 151 error ๐ โโ๏ธ
The returned data looks like this:
RETURN-DATA-TYPE ::= START-DATA <RETURN-TYPE> <DATA> END-DATA
RETURN-TYPE ::= 1404 | <ASCII-STRING>
Here's an example:
>GET ABC 1404
<951 "OK, here it comes!"
<START-DATA 1404
1404 data stream here...
<END-DATA
<952 "All done!"
Error examples:
>GET ABC STRONG-CRYPT
<151 "Sorry, that encoding not available here"
or
>GET ABC 1404
<951 "OK, here it comes!"
<START-DATA 1404
1404 data stream here...
<END-DATA
<150 "Whoa, bad data..."
โ ๏ธ If the server returns any type of error code, the client MUST discard all data it received from the server. No keeping the leftovers, bestie ๐๏ธ
3.7. The LIST Command ๐
The LIST command lets the client ask the server what data is available on it ๐ The format is:
LIST-CMD ::= LIST <net> <dev> <intf> <var> <gran> <sdate> <stime>
<edate> <etime>
<net> ::= <ASCII-STRING> | *
<dev> ::= <ASCII-STRING> | *
<intf> ::= <ASCII-STRING> | *
<var> ::= <ASCII-STRING> | *
<gran> ::= <ASCII-STRING> | *
<sdate> ::= <DATE-TYPE> | *
<edate> ::= <DATE-TYPE> | *
<stime> ::= <TIME-TYPE> | *
<etime> ::= <TIME-TYPE> | *
To get a list of the networks the server has data for, you'd send:
LIST * * * * * * * * *
This command:
LIST netx rtry * * * * * * *
will list all interfaces for rtry ๐ And this one:
LIST netx rtry * ifInOctets * 1993-02-01 * * *
will get the list of interfaces on device "rtry" in network "netx" that have values for the variable "ifInOctets" after the start date of February 1, 1993 ๐ฆ
To process wildcards in a LIST command, follow these rules:
- Only the leftmost wildcard will be serviced for a given LIST command.
- If all fields to the right of the leftmost wildcard are wildcards, then all values for the wildcard being processed will be returned.
- If specific values are given for fields to the right of the wildcard being serviced, then the specific values MUST match a known value.
The output from a LIST command is formatted like this:
LIST-RETURN ::= START-LIST <LIST-ENTRY> END-LIST
LIST-ENTRY ::= <net> <device> <intf> <var> <gran> <sdate> <stime>
<edate> <etime>
<net> ::= <ASCII-STRING>
<device> ::= <ASCII-STRING> | <NULL>
<intf> ::= <ASCII-STRING> | <NULL>
<var> ::= <ASCII-STRING> | <NULL>
<gran> ::= <ASCII-STRING> | <NULL>
<sdate> ::= <DATE-TYPE> | <NULL>
<edate> ::= <DATE-TYPE> | <NULL>
<stime> ::= <TIME-TYPE> | <NULL>
<etime> ::= <TIME-TYPE> | <NULL>
Heads up: only the fields that have values get returned by the server ๐ธ For example, here's the query to find the interfaces on rtry:
>LIST netx rtry * * * * * * *
<941 "OK, here comes the list..."
<START-LIST
<netx rtry intf1
<netx rtry intf2
<netx rtry intf3
<END-LIST
<942 "all done"
And the query to find interfaces with ifInOctets data at a 15 minute granularity:
>LIST netx rtry * ifInOctets 15min * * * *
<941 "OK, here comes the list..."
<START-LIST
<netx rtry intf1
<netx rtry intf2
<netx rtry intf3
<END-LIST
<942 "all done"
If the server runs into an error while processing a LIST command, the server MUST return a 140 error message ๐ต If the server can't process the LIST command at all (syntax error, etc.), it MUST return a 141 message ๐ For example:
>LIST netx rtry
<141 "huh, bad list dude"
or
>LIST netx rtry * ifInOctets 15min * * * *
<941 "OK, here comes the list..."
<START-LIST
<netx rtry intf1
<netx rtry intf2
<netx rtry intf3
<END-LIST
<140 "Whoa, bad list dude, please ignore"
3.8. The Server State Machine ๐ฆ
okay so this diagram is the bestie map for how a server SHOULD interact with a client ๐บ๏ธโจ
+------+
+-------->| WAIT |<-----+
| +------+ |
| New | |
| Connect | | LOGIN Failure
EXIT | \ / |
Received | +-------+ |
| | LOGIN |-----+
| +-------+
| |
| | LOGIN Successful
| \ /
| +---------+
+--------| PROCESS |<----+
+---------+ |
| | Process Commands
| |
+----------+
so the server just chills in WAIT (after starting up and initializing) until a client makes a new connection ๐ค The first command a client MUST issue is a LOGIN command, otherwise the server MUST immediately close the connection ๐ โโ๏ธ If the login goes wrong in any way (see 3.2 for the deets), the server MUST immediately close the connection and go back to WAIT ๐
Once a successful LOGIN comes through, the server hops into PROCESS ๐ where it handles a bunch of LIST, GET, STATUS, and SELECT commands. Any other command that shows up in this state MUST be ignored, except for the EXIT command ๐ Once EXIT is received, the server exits right away (after doing any needed internal bookkeeping) and goes back to WAIT. Any command the server gets while it's already busy with another one (like if you send an "EXIT" while a big "GET" is still processing) will be ignored until the command being processed finishes ๐
If the data connection to the client closes for any reason while the server is in PROCESS, the server MUST immediately close its connection, do any associated internal cleanup, and return to the LOGIN state ๐ญ
4.0. Security Issues ๐
okay real talk, there are legal, ethical and political concerns with sharing data ๐ฌ That's why it's super important to keep shared data intact and confidential ๐ This spec doesn't define the exact mechanism, but mechanisms for controlling which user can get at specific data about specific objects MAY need to be built into server implementations ๐ This could potentially be done in a few ways, like a configuration file that listed the objects a user was allowed to access, or limiting file access with file permissions inside a given file system. At a minimum, the server SHOULD NOT allow default access to all data on the server ๐ซ
Additionally, the server SHOULD strictly follow the state diagram shown in section 3.8 ๐บ๏ธ The server SHOULD be tested with arbitrary strings in the command fields so no unexpected security problems get caused by the server ๐งช The server SHOULD specifically discard illegal ASCII characters as discussed in section 3.0 ๐งน If the server executes other programs, then the server MUST verify that no unexpected side-effects will occur from the invocation or from the arguments given to that program ๐ The server SHOULD always verify that all data is contained within the input buffer, and that a long input string from a client will not cause unexpected side-effects ๐ฅ
Finally, given how relatively insecure the global Internet is, and the presence of packet-sniffing capability (yes, sniffers are lurking ๐), several considerations MUST be weighed. The authentication process via the LOGIN process MUST be strictly adhered to, and the use of one-time authentication is strongly encouraged ๐ It's also suggested that the data returned from the server be protected (such as through encryption) so no sensitive data gets revealed by accident ๐ซถ
5.0. Summary ๐
So basically, this doc defines a protocol that could be used in a client-server relationship to pull statistics from a remote database server ๐
There's still a ton of work to do in Operational Statistics, including questions like:
- what "standard" graphs or "variables" should always be made available to the user?
- what additions to the standard MIB would make the network manager's job easier?
6.0. References ๐
[1] Stockman, B., "A Model for Common Operational Statistics", RFC 1404, NORDUnet/SUNET, January 1993.
Appendix A: Sample Client-Server Sessions ๐
Session 1: Check available variables on device rtr1 interface eth0
>LOGIN "henry" "skey"
<CHAL "78 lo35098"
>AUTH "COW MOO DOG BARK CAT MEOW"
<910 "Login OK, what now?"
>LIST OARnet rtr1 eth0 * * * *
<941 "List lookup OK, here it comes!"
<START-LIST
<OARnet rtr1 eth0 ifInOctets
<OARnet rtr1 eth0 ifOutOctets
<OARnet rtr1 eth0 ifInErrors
<OARnet rtr1 eth0 ifOutErrors
<END-LIST
<942 "List done!"
>EXIT
<990 "OK, Bye now!"
Session 2: Retrieve a bit of data from the server
>LOGIN henryc "skey"
<CHAL "78 lo35098"
>AUTH "COW MOO DOG BARK CAT MEOW"
<910 "Login OK, what now?"
>SELECT OARnet rtr1 eth0 InBytes 15min 1993-02-01 00:00:00 1993-03-01 23:59:59
<920 "TAG blah"
>STATUS
<931 "here it comes..."
<STATUS= OK
<TAG blah SIZE 654321
<932 "all done"
>GET blah 1404
<951 "here it comes..."
<START-DATA 1404
1404 data here
<END-DATA
<952 "wow, all done"
>EXIT
<990 "OK, bye"
Author's Address ๐ฎ
Henry Clark
BBN Planet Corp.
150 Cambridge Park Dr.
Cambridge, MA 02140
Phone: (617) 873-4622
EMail: henryc@bbnplanet.com
๐ฆ where this page comes from
- ietf: rfc1856 1995-09
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms