Subject: Re: snmpconf New version of the Policy-Based Management MIB

From: Pablo Halpern <[email-masked]>
Date: Fri, 05 Jan 2001 13:09:43 -0500

Sorry I am so late sending this. It got saved in my email program and never 
transmitted.

At 08:17 PM 11/27/00 -0800, Steve Waldbusser wrote:

>Here's the latest version I submitted as an Internet Draft. They
>indicated it may take as long as December 4th before we see the ID.

I have picked out some errors and show them, below. In this email, I have 
tried to stay away from editorializing and stick to just errors or 
ambiguities. I have also limited my comments to the policy language and 
accessor functions, since that is the part that I am most familiar 
with.  Sorry about the large amount of quoting of the original document. 
Just skip around and look for my responses to the quoted material.

>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>                  Policy Based Management MIB
>                 draft-ietf-snmpconf-pm-04.txt
>                       November 22, 2000

[etc.]

>6.  Policy Language
>
>Policy filters and policy actions are expressed with the
>policy language.
>
>The policy language is intended to be familiar to programmers
>in a variety of languages, including Perl and C. There is no
>referenceable standard for the Perl language, so the policy
>language is defined as a subset of the C language. A subset
>was used to provide for easy development of low-cost
>interpreters of the policy language and to take away language
>constructs that are peculiar to the C language.  For example,
>it is expected that both C and Perl programmers will
>understand the constructs allowed in the policy language.
>
>Some examples of the features that have been removed from the
>C language are: function definitions, pointer variables,
>structures, enums, typedefs, floating point and pre-processor
>functions.

Comments are a pre-processor function. If we intend to allow comments, then 
there needs to be an explicit exception made here.

>This language is formally defined as a subset of ISO C [19],
>but only allows those constructs that may be expressed in the
>BNF documented here. This is done because while BNF doesn't
>fully specify syntactical rules (it allows constructs that are
>invalid) and doesn't specify semantic rules, it can
>successfully be used to define the subset of ISO C that is
>required for conformance to this standard. Unless explicitly
>described herein, the meaning of any construct expressed in
>the BNF can be found by reference to the ANSI/ISO C standard.
>
>The use of comments and newlines are allowed and encouraged
>where they will promote readability of policy code.
>
>Policy code in this language must be expressed in the UTF8
>character set.
>
>
>
>6.1.  Formal Definition
>
>The policy language follows the syntax and semantics of ISO C
>[19], but policy code is limited to that which that can be
>expressed in the following EBNF form:

As Steve and I discussed in a phone call, the grammar for the lexical 
analysis (tokens) of the language needs to be separated from the grammar 
for the phrase-structure. The section below, up until my comment, "END OF 
LEXICAL GRAMMAR," is incomplete and inaccurate. Specifically, it does not 
completely or correctly describe the characters and backslash escapes that 
are permitted within single or double quotes.  I have the BNF for a 
complete lexical grammar that can be incorporated in the next draft.

>     letter            : Any lower or upper case letter or underscore
>
>     char              : Any character
>
>     digit             : '0' | '1' | '2' | '3' | '4' |
>                         '5' | '6' | '7' | '8' | '9'
>
>     hexdigit         : digit | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' |
>                                'a' | 'b' | 'c' | 'd' | 'e' | 'f'
>
>     decimal           : digit+
>
>     integer-constant  : decimal | ( '0' 'x' hexdigit+ )
>
>     char-constant     : ( ''' char ''' ) |
>                         ( ''' '' decimal ''' )
>
>     identifier        : letter ( letter | digit )*
>
>     string-literal    : '"' char* '"'

END OF LEXICAL GRAMMAR

>     -- Expressions
>
>     primary-expression:
>           identifier
>         | integer-constant
>         | char-constant
>         | string-literal
>         | '(' expression ')'
>
>     postfix-expression:
>           primary-expression
>         | postfix-expression '(' argument-expression-list? ')'
>         | postfix-expression '++'
>         | postfix-expression '--'
>         | postfix-expression '[' expression ']'
>
>     argument-expression-list:
>           assignment-expression
>         | argument-expression-list ',' assignment-expression
>
>     unary-expression:
>           postfix-expression
>         | unary-operator unary-expression
>
>     unary_operator:
>         '+', '-', ', '!', '++', '--', '&'

My mistake. The above two lines should read:

     unary_operator:
           '+' | '-' | ' | '!' | '++' | '--' | '&'

>     multiplicative-expression:
>           unary-expression
>         | multiplicative-expression '*' unary-expression
>         | multiplicative-expression '/' unary-expression
>         | multiplicative-expression '%' unary-expression
>
>     additive-expression:
>           multiplicative-expression
>         | additive-expression '+' multiplicative-expression
>         | additive-expression '-' multiplicative-expression
>
>     shift-expression:
>           additive-expression
>         | shift-expression '<<' additive-expression
>         | shift-expression '>>' additive-expression
>
>     relational-expression:
>           shift-expression
>         | relational-expression '<' shift-expression
>         | relational-expression '>' shift-expression
>         | relational-expression '<=' shift-expression
>         | relational-expression '>=' shift-expression
>
>     equality-expression:
>           relational-expression
>         | equality-expression '==' relational-expression
>         | equality-expression '!=' relational-expression
>
>     AND-expression:
>           equality-expression
>         | AND-expression '&' equality-expression
>
>     exclusive-OR-expression:
>           AND-expression
>         | exclusive-OR-expression '^' AND-expression
>
>     inclusive-OR-expression:
>           exclusive-OR-expression
>         | inclusive-OR-expression '|' exclusive-OR-expression
>
>     logical-AND-expression:
>           inclusive-OR-expression
>         | logical-AND-expression '&&' inclusive-OR-expression
>
>     logical-OR-expression:
>           logical-AND-expression
>         | logical-OR-expression '||' logical-AND-expression
>
>     assignment-expression:
>           logical-OR-expression
>         | unary-expression assignment-operator assignment-expression
>
>     assignment-operator:
>           '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>='
>         | '&=' | '^=' | '|='
>
>     expression:
>           assignment-expression
>         | expression ',' assignment-expression
>
>     constant-expression:
>         logical-OR-expression

The previous draft of this standard included conditional ( ? : ) 
expressions. Why were they removed?

>     ------------------------------------------------------
>     -- Declarations
>
>     declaration:
>         type-specifier declarator-list ';'
>
>     declarator-list:
>           init-declarator
>         | declarator-list ',' init-declarator
>
>     init-declarator:
>           identifier
>         | identifier '=' assignment-expression
>
>     type-specifier:
>           'char' | 'int' | 'long' | 'long' 'long'
>         | 'unsigned' | 'unsigned' 'int' | 'unsigned' 'long'
>         | 'unsigned' 'long' 'long'
>         | 'string'

My mistake again. I left out some valid combinations. Here's a rewrite:

     type-specifier:
           sign-specifier? 'char'
         | sign-specifier
         | sign-specifier? int-size
         | sign-specifier? int-size? int
         | 'string'

     sign-specifier:
           'signed' | 'unsigned'

     int-size:
           'long' | 'long' 'long'

>     ------------------------------------------------------
>     -- Statements
>
>     statement:
>           if-statement
>         | non-if-statement
>
>     -- if-else-statement is considered a non-if statement for
>     -- purpose of resolving dangling if clauses.
>     non-if-statement:
>           labeled-statement
>         | compound-statement
>         | expression-statement
>         | if-else-statement
>         | iteration-statement
>         | jump-statement

labeled-statement should be removed, above.

>     compound-statement:
>         '{' statement-list? '}'

This should be:

     compound-statement:
           '{' declaration* statement-list? '}'

>     statement-list:
>         statement
>       | statement-list statement
>
>     expression-statement:
>         expression? ';'
>
>     if-statement:
>         'if' '(' expression ')' statement
>
>     if-else-statement:
>         'if' '(' expression ')' non-if-statement 'else' statement
>
>     iteration-statement:
>           'while' '(' expression ')' statement
>         | 'for' '(' expression? ';' expression? ';' expression? ')'
>               statement
>
>     jump-statement:
>           'continue' ';'
>         | 'break' ';'
>         | 'return' expression? ';'
>
>
>     ---------------------------------------------
>     -- Root production.
>
>     policy-code:
>         declaration*
>         statement-list?

This would be less confusing on one line:

     policy-code:
           declaration* statement-list?

>7.  Sizes of variables
>
>While ISO C [19] allows implementation flexibility in choosing
>the size of the integer types, implementations of the policy
>language must use the following sizes:
>
>   type               bits  range
>   ----               ----  -----
>   int                32    -2147483648 to 2147483647
>   long               32    -2147483648 to 2147483647
>   long long          64    -9223372036854775808 to 9223372036854775807
>   unsigned           32    0 to 4294967296
>   unsigned int       32    0 to 4294967296
>   unsigned long      32    0 to 4294967296
>   unsigned long long 64    0 to 18446744073709551616

Add the following (my omission).

     char, unsigned char   8   0 to 255
     signed char        8   -128 to 127

>8.  String type
>
>The string type is available for use in policy code as if
>declared as a typedef prior to a policy's execution (however,
>note that typedef is not provided in the C subset valid for
>policy code itself).
>
>A string represents a sequence of characters. The string type
>is not a null-terminated string and does not need to be pre-
>allocated.  Operations on a string that change its length will
>automatically allocate or free memory as necessary. Strings
>can contain binary data (including null bytes) as well as
>printable data. The length of a string cannot be determined by
>inspection of the contents of the string (i.e. no null
>termination), but can be determined by calling strlen(). When
>a string variable is a parameter to a function, it can be
>modified by that function.
>
>
>
>8.1.  Infix string operators
>
>The following operators are supported for strings. In the
>following list, a and b are variables or expressions of type
>string and i is an expression of type int.
>
>   Assign: a = b;
>
>         Copies the value of b to a. After the copy a and
>         b are equal but do not share storage.
>
>   Concatenate: a + b
>   Append: a += b
>   Index (with range checking): a[i]
>   Test for equality: a == b
>   Test for not equal: a != b
>   Compare: a < b, a > b, a <= b, or a >= b

I think we need a little explanation of equality and comparison, for the 
sake of precision. Something like this will suffice: "The comparison 
criterion is the same as for strcmp(). Specifically, comparisons are 
case-sensitive and do not adhere to any locale-specific collation order."

>9.  Address of `this element'
>
>Policy code needs a convenient way to get the components of
>the index for "this element" so that they can perform SNMP
>operations on it or on related elements.
>
>Two mechanisms are provided.
>
>1. For all oid input parameters to all SNMP Access Functions (but not
>    oid utility functions), the token "$n" ('$' followed by an integer
>    between 0 and 99) can be used in place of any decimal
>    sub-identifier. This token is expanded by the agent at execution
>    time to contain the n'th subid of the index for the current
>    element. For example, if the element is interface #7, and the
>    objectIdentifier is "1.3.6.1.2.1.2.2.1.3.$1", it will be expanded
>    to "1.3.6.1.2.1.2.2.1.3.7".
>
>    If the token specified is beyond the length of the index for the
>    current element, processing of the containing filter or action will
>    be immediately terminated.
>
>2. An array of strings will be available to the policy code. The n'th
>    element of the array contains the ascii decimal string value of the
>    n'th subidentifier in the index for "this element". The array is
>    called iv. The number of subids in the array is called ic.
>
>    For example, if "this element" is frCircuitDLCI.5.57
>                                      (ifIndex = 5, DLCI = 57)
>          then ic == 2
>               iv[0] == 5
>               iv[1] == 57
>
>10.  Accessor Functions
>
>Accessor functions are built-in functions available primarily
>to provide access to information on the local system or to
>more efficiently manipulate this information. A group of
>functions is organized into a library, the unit of conformance
>for function implementation. In order to claim conformance to
>a library, an implementation must implement all functions in a
>library to the specifications of the library.
>
>In order for a management station or policy code to understand
>if a certain library of functions is implemented, each library
>will have a registration OID that it registers in this MIB's
>capabilities table. Thus, conformance to a library can be
>tested with the capMatch library function (in the base
>library) or by inspecting the pmCapabilitiesType objects in
>the pmCapabilitiesTable.
>
>
>11.  Base Accessor Function Library
>
>A standard base library of accessor functions is available to
>all systems that implement this specification. This library is
>known by the capability OID of:
>
>   pmBaseFunctionLibrary ::= { policyMgt pmConformance pmGroups 2 }
>
>This library contains four types of functions:
>
>   - SNMP Access functions
>   - Policy Configuration Access functions
>   - Utility functions
>   - Library Functions
>
>
>11.1.  SNMP Access Functions
>
>Two sets of SNMP Access functions are available with different
>situations in mind:
>
>   - Convenience SNMP Functions
>
>     In an effort to keep simple things simple, these functions are
>     easy to use and promote easy to understand code. These functions
>     will suffice for the majority of situations where a single
>     variable is referenced and the desired error recovery is to simply
>     (and immediately) give up (and move to the next policy-element
>     combination). In more complex cases, the General SNMP Functions
>     can be used at the cost of several times the code complexity.
>
>     The convenience SNMP functions are getint, getvar, exists,
>     setint, setvar, setRowStatus, and searchcolumn.
>
>   - General SNMP Functions
>
>     The General SNMP functions allow nearly any legal SNMP Message to
>     be generated, including those with multiple varbinds, getNext
>     operations, notifications, and messages with explicit addressing
>     or security specifications.
>
>     The general SNMP functions are writeVarbind, readVarbind,
>     and snmpsend.
>
>Many of the accessor functions use a string encoding of a
>value that may be one of many SMI data types as input or
>output parameters. The actual type is not encoded in the
>value, but rather is specified elsewhere, possibly by nature
>of the context in which it is used. The encodings are:
>
>Any Integer value
>     (INTEGER, Integer32, Counter32, Counter64, Gauge32, Unsigned32,
>     TimeTicks, Counter64):
>
>     Ascii-encoded integer in ascii,
>     range: -9223372036854775808 to 9223372036854775807

I think this should be:
     range: -9223372036854775808 to 18446744073709551616

>     Note that getint and setint encode integers as C integer values
>     and do not use this character string encoding.
>
>Octet String
>     The character string contains the unencoded value of the octet
>     string.
>
>Object Identifier
>     A decimal ascii encoded object identifier stored in a string.
>
>     subid:     decimal
>     oid:       subid | subid '.' oid
>
>     Note that ascii descriptors (e.g. "ifIndex") are never used in
>     these encodings "over the wire". They are never returned from
>     accessor functions nor are they ever accepted by them. NMS user
>     interfaces are encouraged to allow humans to view object
>     identifiers with ascii descriptors, but they must translate those
>     descriptors to dotted-decimal format before sending them in MIB
>     objects to policy agents.
>
>
>
>11.1.1.  Convenience SNMP Functions
>
>
>11.1.1.1.  getint()
>
>The getint() function is used to retrieve the value of an SNMP
>MIB instance when it is known to be of a 32 bit unsigned
>integer type. 32-bit signed integer values may be retrieved
>but they may have undefined results if the sign bit is set.
>
>      long getint(string oid)
>
>         Oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         The agent will retrieve the instance in the same SNMP context
>         in which the element resides. Note that no actual SNMP PDU
>         needs to be generated and parsed when the policy MIB module
>         resides on the same system as the managed elements.
>
>         If the queried object identifier value does not exist or is
>         not a 32-bit integer-valued object, execution of the
>         containing code on the current element will immediately
>         terminate and the associated policyAction will not be executed
>         on the current element.
>
>         This function returns the value of the integer-valued MIB
>         instance.
>
>         It is recommended that NMS user interfaces display and allow
>         input of MIB object names by their descriptor values followed
>         by the index in dotted-decimal form (e.g., "ifType.7).
>
>11.1.1.2.  getvar()
>
>The getvar() function is used to retrieve the value of an SNMP
>MIB instance.
>
>      string getvar(string oid, string value)

I don't think we need the second argument.

>         Oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         The agent will retrieve the instance in the same SNMP context
>         in which the element resides. Note that no actual SNMP PDU
>         needs to be generated and parsed when the policy MIB module
>         resides on the same system as the managed elements.
>
>         If the queried object identifier value does not exist
>         execution of the containing code on the current
>         element will immediately terminate and the associated
>         policyAction will not be executed on the current element.
>
>         This function returns a string containing the returned value,
>         encoded according to the returned type.
>
>         The optional argument value will be filled in with
>         the returned value if supplied.

Optional argument?  Why? I think this is a hold-over from pre-string days.

>         It is recommended that NMS user interfaces display and allow
>         input of MIB object names by their descriptor values followed
>         by the index in dotted-decimal form (e.g., "ifType.7).
>
>11.1.1.3.  exists()
>
>The exists() function is used to verify the existence of an
>SNMP MIB instance.
>
>      int exists(string oid)
>
>         oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         The agent will retrieve the instance in the same SNMP context
>         in which the element resides. Note that no actual SNMP PDU
>         needs to be generated and parsed when the policy MIB module
>         resides on the same system as the managed elements.
>
>         This function returns the value 1 if the SNMP instance exists
>         and 0 if it doesn't exist.
>
>         It is recommended that NMS user interfaces display and allow
>         input of MIB object names by their descriptor values followed
>         by the index in dotted-decimal form (e.g., "ifType.7).
>
>11.1.1.4.  setint()
>
>The setint() function is used to set a MIB instance to a
>certain integer value. The setint() function is only valid in
>policyActions.  If when executing a policyFilter, the agent
>encounters a call to the setint() function, execution of the
>policyFilter for the current element will immediately
>terminate and the associated policyAction will not be executed
>on the current element.
>
>     int setint(string oid, long value)
>
>         oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         The agent will set the variable specified by oid
>         to the integer value specified by value.
>
>         The agent will set the instance in the same SNMP context
>         in which the element resides. Note that no actual SNMP PDU
>         needs to be generated and parsed when the policy MIB module
>         resides on the same system as the managed elements.
>
>         If the set encounters any error, 0 is returned. If sucessful,
>         1 is returned.
>
>         It is recommended that NMS user interfaces display and allow
>         input of MIB object names by their descriptor values followed
>         by the index in dotted-decimal form (e.g., "ifType.7).
>
>11.1.1.5.  setvar()
>
>The setvar() function is used to set a MIB instance to a
>certain value. The setvar() function is only valid in
>policyActions.  If when executing a policyFilter, the agent
>encounters a call to the setvar() function, execution of the
>policyFilter for the current element will immediately
>terminate and the associated policyAction will not be executed
>on the current element.
>
>     int setvar(string oid, string value, int type)
>
>         oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         value is a string encoded in the format appropriate to the
>         type parameter. The agent will set the variable specified by
>         oid to the value specified by value.
>
>         type is the type of the value parameter and will be one of the
>         DataType Constants.
>
>         The agent will set the instance in the same SNMP context
>         in which the element resides. Note that no actual SNMP PDU
>         needs to be generated and parsed when the policy MIB module
>         resides on the same system as the managed elements.
>
>         If the set encounters any error, 0 is returned. If sucessful,
>         1 is returned.
>
>         It is recommended that NMS user interfaces display and allow
>         input of MIB object names by their descriptor values followed
>         by the index in dotted-decimal form (e.g., "ifType.7).
>
>11.1.1.6.  searchcolumn()
>
>     int searchcolumn(string columnoid, string startoid,
>                      string value, int type, string oid)

The oid argument is not described below and does not appear in the 
examples. I think it is superfluous.

>         searchcolumn performs an SNMP walk on a portion of the MIB
>         searching for objects with values equal to the `value'
>         parameter.
>
>         columnoid constrains the search to only those variables that
>         share the same OID prefix (i.e. are beneath it in the OID
>         tree).
>
>         startoid is the OID sent in the first getnext packet. While
>         the value has not been found and the returned OID still shares
>         the same prefix wth columnoid, the returned OID will be sent
>         in the next getnext query.
>
>         In the first search of a column, startoid will be set to the
>         same value as columnoid. If the caller wishes to learn of more
>         than one match, it should call searchcolumn multiple times
>         where the startoid value should be set to the value returned
>         from the previous invocation (effectively continuing the
>         search).

This last paragraph is not really precise. I THINK the correct meaning is:

         If startoid is empty (as it normally would be the first time this
         function is called in a particular piece of code), it set to 
columnoid
         before beginning the search. If searchcolumn() succeeds, then
         startoid is set to the oid of the matching object. If not altered 
by the
         caller, this becomes the starting point for the next search. Thus, if
         If the caller wishes to learn of more than one match, it should call
         searchcolumn multiple times.

>         value is the value to be searched for. When a value is found
>         that matches exactly, oid is set to the oid of the matched
>         value.
>
>         type describes the type of the value to be matched.
>
>         If the search traverses beyond columnoid without finding a
>         match, zero is returned.
>
>         For example:
>         To find an ethernet interface
>         searchcolumn("ifType", "ifType", "6", Integer);
>
>         This sends a getnext request for ifType and continues to walk
>         the tree until a value matching 6 is found or a variable
>         returns that is not in the 'ifType' subtree.
>
>         To find the next ethernet interface, assuming interface #3
>         was discovered to be the first:
>         searchcolumn("ifType", "ifType.3", "6", Integer);
>
>
>11.1.1.7.  setRowStatus()
>
>     int setRowStatus(string oid, int maxTries)
>
>         setRowStatus is used to automate the process of finding an
>         unused row in a read-create table that uses RowStatus.
>
>         oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier, with one of
>         the subids replaced with a '*' character
>         (e.g. "1.3.6.1.3.1.99.1.2.1.9.*"). The oid must reference an
>         'instance' of the RowStatus object and the '*' must replace
>         any integer index item that may be set to some random value.
>
>         setRowStatus will come up with a random number for the
>         selected index item and will attempt to create the instance
>         with the createAndWait state. If the attempt fails, it will
>         retry with a different random index value. It will attempt
>         this no more than maxTries times.
>
>         setRowStatus returns the successful integer value for the
>         index. If unsuccessful after maxTries or if more than one
>         '*' is in oid, -1 will be returned.
>
>
>11.1.2.  General SNMP Functions
>
>It is desireable for a general SNMP interface have the ability
>to perform SNMP operations on multiple variables at once and
>for it to allow multiple varbind lists to exist at once. The
>readVarbind and writeVarbind functions exist in order to
>provide these facilities in a language without pointers,
>arrays and memory allocators.
>
>readVarbind and writeVarbind access a data store of variable
>length varbindlists. The index of the varbindlist and the
>index of the variable within that varbindlist are specified in
>every readVarbind and writeVarbind operation. Once a
>varbindlist has been fully specified by one or more calls to
>writeVarbind, it is passed to snmpsend (by referencing the
>varbindlist index) and the number of varbinds to be included
>in the operation. When a response is returned, the contents of
>the response are in the same varbindlist (i.e. the same
>varbindlist index is used) and may be read by one or more
>calls to readVarbind.
>
>Varbinds in this data store are created automatically whenever
>they are written or read by any writeVarbind, readVarbind, or
>snmpsend operation. It is not a runtime error to read a
>varbind that has not been previously written, however the
>values read will be unpredictable.
>
>For example:
>   writeVarbind(0, 0, "sysDescr.0", ...);
>   writeVarbind(0, 1, "sysOID.0", ...);
>   writeVarbind(0, 2, "ifNumber.0", ...);
>   if (snmpsend(0, 3, Get, ...))
>       return;
>   readVarbind(0, 0, iKnowItsSysDescr, iKnowItsaString, value, &len);

The len argument is defunct.

>   readVarbind(0, 1, ...)
>   readVarbind(0, 2, ...)
>   ...
>
>or,
>   writeVarbind(0, 0, "ifIndex", ...);
>   writeVarbind(0, 1, "ifType", ...);
>   while(!done){
>     if (snmpsend(0, 2, Getnext, ...))
>         continue;
>     readVarbind(0, 0, oid1, ...);
>     readVarbind(0, 1, oid2, ...);
>     /* leave OIDs alone, now varbindlist #0 is set up for next step
>        in table walk. */
>     if (oidncmp(oid1, "ifIndex", oidlen("ifIndex")))
>       done = 0;
>     ...
>   }
>
>To be conformant to this specification, implementations must
>support at least 5 varbindlists with at least 32 varbinds per
>list.
>
>Implementations may, but are not required to, initialize the
>varbind database when a new filter or action begins executing.
>A policy filter or action can only depend on the state it has
>written into this datastore or retrieves with accessor
>functions.
>
>
>11.1.2.1.  writeVarbind()
>
>     void writeVarbind(int varbindListIndex, int varBindIndex,
>                       string oid, int type, string value)

In the previous functions, value comes before type, we should be 
consistent, one way or the other.

>         writeVarbind will store the oid, the value and it's type in
>         the specified varbind.
>
>         varbindListIndex is a non-negative integer that identifies the
>         varbindList modified by this call.
>
>         varbindIndex is a non-negative integer that identifies the
>         varbind within the varbindList modified by this call.
>
>         oid is a string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         type is the type of the value parameter and should be set to
>         one of the values for DataType Constants.
>
>         value is a string encoded in the format appropriate to the
>         type parameter.
>
>
>
>11.1.2.2.  readVarbind()
>
>     void readVarbind(int varbindListIndex, int varBindIndex,
>                      string oid, int *type, string value)

Again, which should come first, the value or the type?

>         writeVarbind will retrieve the oid, the value and it's type
>         from the specified varbind.
>
>         varbindListIndex is a non-negative integer that identifies the
>         varbindList read by this call.
>
>         varbindIndex is a non-negative integer that identifies the
>         varbind within the varbindList read by this call.
>
>         The object identifier value of the referenced varbind will be
>         copied into the oid parameter, formatted in an ASCII
>         dotted-decimal representation (e.g. "1.3.6.1.2.1.1.1.0").
>
>         type is the type of the value parameter and will be set to
>         one of the values for DataType Constants.
>
>         value is a string encoded in the format appropriate to the
>         type parameter.
>
>
>11.1.2.3.  snmpsend()
>
>     int snmpsend(int varbindListIndex, int numVarbinds, int opcode)
>
>         snmpsend will perform an SNMP operation using the specified
>         varbindlist. Note that no actual SNMP PDU needs to be
>         generated and parsed when the policy MIB module
>         resides on the same system as the managed elements.
>
>         The results of the operation will be placed in the same
>         varbindList. If an error occurred, the varbindlist will remain
>         unmodified except for the following:
>
>           1) If the response PDU had a nonzero error-index, the
>              varbind specified by the error-index will have its type
>              field replaced with associated error-status constant.
>           2) If the response PDU contained varbinds with exceptions,
>              the type field of those varbinds will be replaced with
>              the appropriate exception (Nosuchobject,
>              NosuchInstance, or Endofmibview).
>           3) If the error-status was zero and there were no
>              exceptions, the varbindlist will remain unmodified. (some
>              examples of situations where this will apply are timeout
>              and authentication failure).
>
>         This function returns zero unless an error occurs in which
>         case it returns the proper SNMP Error Constant.
>
>         varbindListIndex is a non-negative integer that identifies the
>         varbindList used by this operation.
>
>         numVarbinds is a integer greater than zero that specified
>         which varbinds in the varbindList will be used in this
>         operation. The first N varbinds in the varbindList are used.
>
>         opcode is the type of SNMP operation to perform and must be
>         one of the values for SNMP Operation Constants.
>
>
>11.2.  Constants
>
>The following constants are defined for use in all SNMP Access
>Functions. Policy code will be executed in an environment
>where the following constants are declared. (Note that these
>constant declarations will not be visible in the policyFilter
>or policyAction MIB objects.)
>
>While these declarations are expressed here as C 'const's, the
>'const' construct itself is not available to be used inside of
>policy code.
>
>   -- Datatype Constants
>
>   const int Integer       = 1;
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 29]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>   const int String        = 2;
>   const int Oid           = 3;
>   const int Integer32     = 4;
>   const int Ipaddress     = 5;
>   const int Counter32     = 6;
>   const int Gauge32       = 7;
>   const int Unsigned32    = 8;
>   const int Timeticks     = 9;
>   const int Opaque        = 10;
>   const int Counter64     = 11;
>
>   -- SNMP Error Constants
>
>   const int Nosuchobject         = 21;
>   const int Nosuchinstance       = 22;
>   const int Endofmibview         = 23;
>   const int Noerror              = 24;
>   const int Toobig               = 25;
>   const int Nosuchname           = 26;
>   const int Badvalue             = 27;
>   const int Readonly             = 28;
>   const int Generr               = 29;
>   const int Noaccess             = 30;
>   const int Wrongtype            = 31;
>   const int Wronglength          = 32;
>   const int Wrongencoding        = 33;
>   const int Wrongvalue           = 34;
>   const int Nocreation           = 35;
>   const int Inconsistentvalue    = 36;
>   const int Resourceunavailable  = 37;
>   const int Commitfailed         = 38;
>   const int Undofailed           = 39;
>   const int Authorizationerror   = 40;
>   const int Notwritable          = 41;
>
>   const int Badparameter         = 42;
>   const int Toolong              = 43;
>   const int Parseerror           = 44;
>   const int Authfailure          = 45;
>   const int Timeout              = 46;
>
>   -- SNMP Operation Constants
>
>   const int Get                  = 0;
>   const int Getnext              = 1;
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 30]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>   const int Set                  = 3;
>   const int Trap                 = 4;
>   const int Inform               = 6;
>   const int V2trap               = 7;
>
>
>
>11.3.  Policy Configuration Access Functions
>
>Policy Configuration Access Functions provide access to
>information specifically related to the execution of policies.
>
>
>11.3.1.  roleMatch()
>
>The roleMatch() function is used to check to see if the
>current element has been assigned a particular role.
>
>     int roleMatch(string roleString)
>
>         Argument roleString is a string. If this
>         exactly matches (content and length) any role assigned to the
>         current element, the function returns 1. If no roles match,
>         the function returns 0.
>
>11.3.2.  capMatch()
>
>The capMatch() function is used to check to see if the current
>element has a certain capability.
>
>     int capMatch(string capOid)
>
>         Argument capability is a string containing a
>         ASCII dotted-decimal representation of an object identifier
>         that describes a capability as would be found in the
>         pmCapabilitiesTable.
>
>         If the current element has the capability described by
>         capString, this function returns 1, otherwise it returns 0.
>
>11.3.3.  elementName()
>
>The elementName() function is used to determine what the
>current element is and can be used to provide information
>about the type of element as well as how it is indexed.
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 31]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>     string elementName()
>
>         elementName returns a string containing an ASCII
>         dotted-decimal representation of an object identifier
>         (e.g. 1.3.6.1.2.1.1.1.0). This object identifier identifies an
>         instance of a MIB object that is an attribute of this element.
>         .fi .sh 3 "setScratchpad()"
>
>
>11.3.4.  setScratchpad()
>
>     setScratchpad(string varName, int scope, string value)
>
>         Every maxLatency time period, every policy runs once for each
>         element. When the setScratchpad function executes, it stores a
>         value that can be retrieved even after this policy execution
>         code exits. The value of scope controls which policy/element
>         combinations can retrieve this varName/value pair. The options
>         for scope are:
>
>         Global
>             The varName/value combination will be available in the
>             filter or action of any policy while executing on any
>             element.
>
>         Policy
>             The varName/value combination will be available in any
>             future execution of the filter or action of the current
>             policy (regardless of what element the policy is executing
>             on).
>
>         PolicyElement
>             The varName/value combination will be available in future
>             executions of the filter or action of the current policy
>             but only when the policy is executing on the current
>             element.
>
>
>         varName is a string used to identify the value. Subsequent
>         retrievals of the same varName in the proper scope will return
>         the value stored. Note that the namespace for varName is
>         distinct for each scope. varName is case sensitive.
>
>         value is a string containing the value to be stored.
>
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 32]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>11.3.5.  getScratchpad()
>
>     int getScratchpad(string varName, int scope, string value)
>
>         The getScratchpad function allows the retrieval of values that
>         were stored previously in this execution context or in
>         other execution contexts. The value of scope controls which
>         execution contexts can pass a value to this execution context.
>         Refer to the definition of setScratchpad to see which values
>         of scope can pass a value to which execution contexts.
>
>         varName is a string used to identify the value. Subsequent
>         retrievals of the same varName in the proper scope will return
>         the value stored. Note that the namespace for varName is
>         distinct for each scope. As a result, getScratchpad cannot
>         force access to a variable in an inaccessible scope - it can
>         only retrieve variables by referencing the proper scope in
>         which they were set. varName is case sensitive.
>
>         On successful return, value will be set to the value that was
>         previously stored.
>
>         This function returns 1 if a value was previously stored and 0
>         otherwise.
>
>Scratchpad Usage Examples
>
>       Policy  Element    Action
>       A       ifIndex.1  setScratchpad("foo", Global, "55")
>       A       ifIndex.1  getScratchpad("foo", Global, val) == 55

By which I guess you mean

getScratchpad("foo", Global, val) , val == 55

>       A       ifIndex.2  getScratchpad("foo", Global, val) == 55
>       B       ifIndex.2  getScratchpad("foo", Global, val) == 55
>       B       ifIndex.2  setScratchpad("foo", Global, "16")
>       A       ifIndex.1  getScratchpad("foo", Global, val) == 16
>
>       Policy  Element    Action
>       A       ifIndex.1  setScratchpad("bar", Policy, "75")
>       A       ifIndex.1  getScratchpad("bar", Policy, val) == 75
>       A       ifIndex.2  getScratchpad("bar", Policy, val) == 75
>       B       ifIndex.1  getScratchpad("bar", Policy, val) not found
>       B       ifIndex.1  setScratchpad("bar", Policy, "20")
>       A       ifIndex.2  getScratchpad("bar", Policy, val) == 75
>       B       ifIndex.2  getScratchpad("bar", Policy, val) == 20
>
>       Policy  Element    Action
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 33]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>       A       ifIndex.1  setScratchpad("baz", PolicyElement, "43")
>       A       ifIndex.1  getScratchpad("baz", PolicyElement, val) == 43
>       A       ifIndex.2  getScratchpad("baz", PolicyElement, val) not found
>       B       ifIndex.1  getScratchpad("baz", PolicyElement, val) not found
>       A       ifIndex.2  setScratchpad("baz", PolicyElement, "54")
>       B       ifIndex.1  setScratchpad("baz", PolicyElement, "65")
>       A       ifIndex.1  getScratchpad("baz", PolicyElement, val) == 43
>       A       ifIndex.2  getScratchpad("baz", PolicyElement, val) == 54
>       B       ifIndex.1  getScratchpad("baz", PolicyElement, val) == 65
>
>       Policy  Element    Action
>       A       ifIndex.1  setScratchpad("foo", PolicyElement, "11")
>       A       ifIndex.1  setScratchpad("foo", Global, "22")
>       A       ifIndex.1  getScratchpad("foo", PolicyElement, val) == 11
>       A       ifIndex.1  getScratchpad("foo", Global, val) == 22
>
>
>11.3.6.  Constants
>
>The following constants are defined for use for the scratchpad
>functions. Policy code will be executed in an environment
>where the following constants are declared. (Note that these
>constant declarations will not be visible in the policyFilter
>or policyAction MIB objects.)
>
>While these declarations are expressed here as C 'const's, the
>'const' construct itself is not available to be used inside of
>policy code.
>
>   -- Scratchpad Constants
>
>   const int Global           = 0;
>   const int Policy           = 1;
>   const int PolicyElement    = 2;
>
>
>11.4.  Utility Accessor Functions
>
>Utility Accessor Functions are provided to enable more
>efficient use of the other accessor functions.
>
>
>
>
>
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 34]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>11.4.1.  oidlength()
>
>     int oidlen(string oid)
>
>         oidlen returns the number of subidentifiers in oid. oid is a
>         string containing an ASCII dotted-decimal
>         representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>
>11.4.2.  oidncmp()
>
>     int oidncmp(string oid1, string oid2, int n)
>
>         Arguments oid1 and oid2 are strings containing
>         ASCII dotted-decimal representations of object identifiers
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         Compares the first n subidentifiers of oid1 and oid2 and
>         returns -1 if oid1 is less than oid2, 0 if they are equal, and
>         1 if oid1 is greater than oid2.
>
>
>11.4.3.  subid()
>
>     int subid(string oid, int n)
>
>         subid returns the value of the n'th (starting at zero)
>         subidentifier of oid. oid is a string containing an ASCII
>         dotted-decimal representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>         If n specifies a subidentifier beyond the length of oid, a
>         value of -1 is returned.
>
>
>11.4.4.  subidwrite()
>
>     int subidwrite(string oid, int n, int subid)
>
>         subid sets the value of the n'th (starting at zero)
>         subidentifier of oid to `subid'. oid is a string containing an
>         ASCII dotted-decimal representation of an object identifier
>         (e.g. "1.3.6.1.2.1.1.1.0").
>
>
>
>
>
>
>Various Authors      Expires May 22, 2001            [Page 35]
>
>
>
>
>Internet Draft    Policy-Based Management MIB     Nov 22, 2000
>
>
>         If n specifies a subidentifier beyond the length of oid, a
>         value of -1 is returned.
>
>
>11.4.5.  oidsplice()
>
>     string oidsplice(string oid1, int m, string oid2, int n)
>
>         oidsplice replaces n subidentifiers in oid1 with all of the
>         subidentifiers from oid2, starting at the m'th subidentifier
>         in oid1. The oid length will be extended if necessary. The
>         resulting oid is returned.

Rather strange argument order, no? Wouldint oidsplice(oid1, m, n, oid1) 
make more sense, since oid1, m and n all refer to one thing?

>11.5.  Library Accessor Functions
>
>The following standard library accessor functions are
>provided:
>
>   strncmp()
>   strncasecmp()

strncasecmp is not ANSI/ISO standard C. It needs to be described.

>   strncat()
>   strlen()
>   strncpy()
>   atoi()
>   random()
>   memcmp()
>   memmove()

In the absence of pointers, what do memcmp and memmove do?

>   sprintf()

- Pablo
---------------------------------------------------------------------
Pablo Halpern                                    [email-masked]
http://www.halpernwightsoftware.com