Annotation of 43BSDReno/contrib/isode-beta/doc/snmp/snmp.tex, revision 1.1.1.1

1.1       root        1: % -*- LaTeX -*-
                      2: 
                      3: \input lcustom
                      4: 
                      5: \documentstyle[12pt,sfwmac]{article}
                      6: 
                      7: \begin{document}
                      8: 
                      9: \begin{center}\Large\bf
                     10: 4BSD/ISODE SNMP Roadmap\\[0.25in]
                     11: \normalsize\bf Marshall T. Rose\\ Performance Systems International, Inc.%
                     12: \footnote{This work was partially supported by the U.S.~Defense Advanced
                     13: Research Projects Agency and the Rome Air Development Center of the U.S.~Air
                     14: Force Systems Command under contract number F30602--88--C-0016.
                     15: The content of the information contained herein does not necessarily reflect
                     16: the position or the policy of the U.S.~Government,
                     17: and no official endorsement should be inferred.}
                     18: \end{center}
                     19: 
                     20: \section*     {Introduction}
                     21: You might consider it strange that the ISODE,
                     22: the openly available implementation of the upper-layers of OSI,
                     23: includes an implementation of the SNMP.
                     24: Inasmuch as the continued survival of the Internet hinges on all nodes
                     25: becoming network manageable,
                     26: this package was developed using the ISODE and is being freely
                     27: distributed with releases of Berkeley \unix/.
                     28: 
                     29: It must be stressed that this package is not a complete network management
                     30: system.
                     31: In particular,
                     32: whilst \pgm{snmpd} provides a minimal agent functionality,
                     33: there are no Network Operation Center (NOC) tools~---~\pgm{snmpi} is a
                     34: debugging aid only.
                     35: 
                     36: The purpose of this {\em Roadmap\/} is simply to point out where you can find
                     37: the various components in the 4BSD/ISODE SNMP package.
                     38: 
                     39: \section*     {SNMP Agent}
                     40: The SNMP agent (the \pgm{snmpd} program) along with the simple initiator
                     41: (the \pgm{snmpi} program) are in the directory \file{snmp/}.
                     42: The \file{READ-ME} file in the top-level directory describes how to generate
                     43: and install these.
                     44: 
                     45: \subsection*   {Streamlined Installation}
                     46: The standard installation directions assume that you wish to install the base
                     47: ISODE system in addition to the 4BSD/ISODE SNMP package.
                     48: However,
                     49: you might wish to install only SNMP software.
                     50: If this is the case,
                     51: then follow these steps and ignore the \file{READ-ME} file.
                     52: \begin{enumerate}
                     53: \item  Configure the ISODE by selecting the appropriate configuration files
                     54: in the \file{config/} directory.
                     55: For example,
                     56: \begin{quote}\small\begin{verbatim}
                     57: % cp config/sunos3.h h/config.h
                     58: % cp config/sunos3.make config/CONFIG.make
                     59: % cp config/*.local support/
                     60: \end{verbatim}\end{quote}
                     61: is all that's required to configure the ISODE on a Sun workstation running
                     62: SunOS~3.5.
                     63: 
                     64: You might wish to consult the {\bf CONFIGURATION\/} section of the
                     65: \file{READ-ME} file for information on other target platforms.
                     66: 
                     67: \item  Generate both the base ISODE system and the SNMP software:
                     68: \begin{quote}\small\begin{verbatim}
                     69: % ./make all all-snmp
                     70: \end{verbatim}\end{quote}
                     71: 
                     72: \item  Make sure the ISODE installation directories are created:
                     73: \begin{quote}\begin{tabular}{|l|l|l|}
                     74: \hline
                     75: \multicolumn{1}{|c|}{\bf name}&
                     76:                \multicolumn{1}{c|}{\bf usually}&
                     77:                                        \multicolumn{1}{c|}{\bf containing}\\
                     78: \hline
                     79: \verb"BINDIR"& \file{/usr/local/bin/}& user programs\\
                     80: \verb"SBINDIR"&        \file{/usr/etc/}&       administrator programs\\
                     81: \verb"ETCDIR"& \file{/usr/etc/}&       administrator files\\
                     82: \verb"INCDIR"& \file{/usr/include/}&   {\em C\/} include files\\
                     83: \verb"LOGDIR"& \file{/usr/spool/isode/}&
                     84:                                        log files\\
                     85: \hline
                     86: \end{tabular}\end{quote}
                     87: 
                     88: \item  Check the \file{/etc/services} file and make sure that these three
                     89:        lines are present:
                     90: \begin{quote}\small\begin{verbatim}
                     91: snmp       161/udp
                     92: snmp-trap  162/udp
                     93: smux       199/tcp
                     94: \end{verbatim}\end{quote}
                     95: If you are running Sun Yellow Pages,
                     96: then you will need to modify this file on the YP master and run a command to
                     97: export the changes to the other YP hosts.
                     98: 
                     99: \item  Add these lines to the \file{/etc/rc.local} file:
                    100: \begin{quote}\small\begin{verbatim}
                    101: if [ -f $(SBINDIR)snmpd ]; then
                    102:     $(SBINDIR)snmpd & (echo -n ' snmp') > /dev/console
                    103: fi
                    104: if [ -f $(SBINDIR)smux.unixd -a -f $(SBINDIR)snmpd ]; then
                    105:     $(SBINDIR)smux.unixd &
                    106:         (echo -n ' smux-unix') > /dev/console
                    107: fi
                    108: \end{verbatim}\end{quote}
                    109: 
                    110: \item  If you wish to have an SNMP trap sink on your system,
                    111:        also add these lines to the \file{/etc/rc.local} file:
                    112: \begin{quote}\small\begin{verbatim}
                    113: if [ -f $(SBINDIR)snmpt ]; then
                    114:     $(SBINDIR)snmpt & (echo -n ' snmp-trap') > /dev/console
                    115: fi
                    116: \end{verbatim}\end{quote}
                    117: Usually the trap sink is started before the agent,
                    118: so if the agent sends any traps initially,
                    119: then can be audited.
                    120: 
                    121: \item  Install a partial ISODE system, as the super-user:
                    122: \begin{quote}\small\begin{verbatim}
                    123: # ./make inst-partial
                    124: \end{verbatim}\end{quote}
                    125: 
                    126: \item  Install the 4BSD/ISODE SNMP software:
                    127: \begin{quote}\small\begin{verbatim}
                    128: # ./make inst-snmp
                    129: \end{verbatim}\end{quote}
                    130: 
                    131: \item  Configure the SNMP agent by editing the file \file{snmpd.rc} in the
                    132: \verb"$ETCDIR" directory:
                    133:     \begin{itemize}
                    134:     \item      Fill-in the value for \verb"sysContact" and \verb"sysLocation".
                    135: 
                    136:     \item      If your site has a management station that listens for traps,
                    137:                fill-in the information for the trap sink, e.g.,
                    138: \begin{quote}\small    \begin{verbatim}
                    139: trap    traps   a.b.c.d
                    140: \end{verbatim}\end{quote}
                    141:        where \verb"traps" is the community that traps should be logged under
                    142:        and \verb"a.b.c.d" is the IP address of the host where a trap sink is
                    143:        listening on UDP port~162.
                    144: 
                    145:     \item      For each of your network interfaces
                    146:                (as reported by the
                    147: \begin{quote}\small\begin{verbatim}
                    148: netstat -i
                    149: \end{verbatim}\end{quote}
                    150:                command)
                    151:                make sure that it is defined in the configuration file with
                    152:                the appropriate type and speed.
                    153:                For the vast majority of BSD-derived systems,
                    154:                the definitions already appear.
                    155:     \end{itemize}
                    156: 
                    157: \item  Finally, start the SNMP agent and SMUX \unix/ daemon.
                    158: The command from \pgm{CShell} is:
                    159: \begin{quote}\small\begin{verbatim}
                    160: # $(SBINDIR)snmpd >& /dev/null
                    161: # $(SBINDIR)smux.unixd >& /dev/null
                    162: \end{verbatim}\end{quote}
                    163: which starts the daemons and directs them to automatically detach.
                    164: If you are going to run a sink for SNMP traps,
                    165: then you will need to start that daemon as well:
                    166: \begin{quote}\small\begin{verbatim}
                    167: # $(SBINDIR)snmpt >& /dev/null
                    168: \end{verbatim}\end{quote}
                    169: \end{enumerate}
                    170: The agent logs activity to the file \file{snmpd.log} in the ISODE
                    171: \verb"LOGDIR" directory.
                    172: 
                    173: By default,
                    174: the trap sink will audit all traps to the file \file{snmp.traps} in the
                    175: ISODE \verb"LOGDIR" directory.
                    176: The \verb"audit" command in \pgm{snmpi} can be used to examine the file.
                    177: 
                    178: \section*     {Exporting MIB Modules}
                    179: You might wish to modify your existing daemons to export MIB modules for
                    180: access via the SNMP agent.
                    181: The SMUX protocol is used for this.
                    182: The SMUX protocol is defined in the file \file{doc/rfcs/smux.txt}.
                    183: You should read this document once just to familiarize yourself with the
                    184: general concepts of SNMP multiplexing.
                    185: 
                    186: However,
                    187: when you instrument your agent to export the MIB,
                    188: you use the SMUX Applications Programming Interface (SMUX API) which is
                    189: defined in the file \file{doc/rfcs/smux-api.txt}.
                    190: This API is fully implemented in the 4BSD/ISODE SNMP software.
                    191: 
                    192: The SMUX \unix/ daemon is an example of a program which uses the software.
                    193: The source for this daemon is in the \file{snmp/} directory.
                    194: At present,
                    195: this daemon exports information on the system's mbufs.
                    196: In the future,
                    197: it is conceivable that it may make generalized process information available.
                    198: 
                    199: \subsection*   {One day}
                    200: $\ldots$ it would be nice to have MIBs defined to allow management
                    201: applications to be written which have equivalent functionality to:
                    202: \begin{quote}\begin{tabular}{l}
                    203: mailq/mailstats\\
                    204: lpq\\
                    205: finger/rwho\\
                    206: iostat/pstat/vmstat\\
                    207: named (DNS)\\
                    208: nntpd (NTP)\\
                    209: bgpd (BGP)\\
                    210: nfsstat/rpcinfo
                    211: \end{tabular}\end{quote}
                    212: 
                    213: \section*     {SNMP and gawk}
                    214: If you are interested in prototyping network management applications,
                    215: then you might find it interesting to run a version of GNU \pgm{awk}
                    216: (the \pgm{gawk} program) which is SNMP capable.
                    217: 
                    218: The directory \file{snmp/gawk-2.11 contains} the modifications to the GNU
                    219: \pgm{awk} 2.11~beta release necessary to achieve this.
                    220: Follow the instructions in the \file{READ-ME-FIRST} file in this directory to
                    221: install this modified \pgm{gawk}.
                    222: 
                    223: \subsection*   {Accessing SNMP variables}
                    224: The current implementation assumes a read-only view of an SNMP MIB.
                    225: This means that MIB objects must occur only as {\em rvalues\/} in expressions.
                    226: 
                    227: \subsubsection*        {Non-tabular variables}
                    228: To access an object which does not occur inside a table,
                    229: simply use the name of that object, e.g.,
                    230: \begin{quote}\small\begin{verbatim}
                    231: % gawk 'BEGIN { print sysDescr; }'
                    232: \end{verbatim}\end{quote}
                    233: Instead,
                    234: if you want to supply a special instance identifier,
                    235: then reference the variable as an array.
                    236: Hence,
                    237: an equivalent command is:
                    238: \begin{quote}\small\begin{verbatim}
                    239: % gawk 'BEGIN { print sysDescr[0]; }'
                    240: \end{verbatim}\end{quote}
                    241: This is less intuitive,
                    242: but it's your choice.
                    243: 
                    244: Of course,
                    245: you may not be able to retrieve a variable.
                    246: For example, \verb"sysDescr[1]", according to the MIB,
                    247: doesn't make much sense.
                    248: There is a special built-in variable,
                    249: \verb"DIAGNOSTIC" which returns a textual description of any problem which
                    250: occurred with the last SNMP operation,
                    251: hence:
                    252: \begin{quote}\small\begin{verbatim}
                    253: % gawk 'BEGIN { print "sysDescr: ", sysDescr, DIAGNOSTIC; }'
                    254: \end{verbatim}\end{quote}
                    255: prints either the system description of the agent you are talking to,
                    256: or a diagnostic,
                    257: depending on what happened with the SNMP interaction.
                    258: 
                    259: \subsubsection*        {Tabular Variables}
                    260: To retrieve the value of an object occurring in a table,
                    261: there are also two methods.
                    262: 
                    263: First,
                    264: you can simply put the instance identifier inside an array reference,
                    265: e.g.,
                    266: \begin{quote}\small\begin{verbatim}
                    267: ifDescr[1]
                    268: \end{verbatim}\end{quote}
                    269: which is equivalent to an SNMP get operation on the variable
                    270: \begin{quote}\small\begin{verbatim}
                    271: ifDescr.1
                    272: \end{verbatim}\end{quote}
                    273: or
                    274: \begin{quote}\small\begin{verbatim}
                    275: ipRouteNextHop["10.0.0.0"]
                    276: \end{verbatim}\end{quote}
                    277: which is equivalent to an SNMP get operation on the variable
                    278: \begin{quote}\small\begin{verbatim}
                    279: ipRouteNextHop.10.0.0.0
                    280: \end{verbatim}\end{quote}
                    281: This is called the ``subscript notation''.
                    282: 
                    283: Note that care should be taken to make sure that the subscript doesn't look
                    284: like a floating-point number to \pgm{gawk}.
                    285: These are all the same, valid, references:
                    286: \begin{quote}\small\begin{verbatim}
                    287: ipRouteNextHop[10,0,0,0]
                    288: ipRouteNextHop["10.0.0.0"]
                    289: \end{verbatim}\end{quote}
                    290: In contrast,
                    291: this is a bogus reference:
                    292: \begin{quote}\small\begin{verbatim}
                    293: ipRouteNextHop[10.0.0.0]
                    294: \end{verbatim}\end{quote}
                    295: 
                    296: Second,
                    297: you can traverse the table (referred to as ``walking the tree'').
                    298: This is done with the \verb"for-in" construct, e.g.,
                    299: \begin{quote}\small\begin{verbatim}
                    300: for (i in ipRouteDest) {
                    301:     printf "route to %s from %s\n",
                    302:         ipRouteDest, ipRouteNextHop;
                    303: }
                    304: \end{verbatim}\end{quote}
                    305: which says to traverse the table containing the object \verb"ipRouteDest".
                    306: The for-loop body will be executed once for each row of the table;
                    307: for each iteration,
                    308: the control variable will be assigned the value of the instance-identifier for
                    309: that row ({\bf not\/} the value of the column in that row).
                    310: This allows you to reference other parts of the MIB using the same
                    311: instance-identifier, e.g.,
                    312: \begin{quote}\small\begin{verbatim}
                    313: for (i in ipRouteDest) {
                    314:     printf "ipRoutingTable[%s]: to %s from %s\n",
                    315:         i, ipRouteDest, ipRouteNextHop;
                    316: }
                    317: \end{verbatim}\end{quote}
                    318: 
                    319: The \verb"for-in" construct retrieves a row of a table using a single powerful
                    320: SNMP get-next operator.
                    321: If a particular column is unsupported by the agent,
                    322: then referencing the corresponding variable will return the empty string.
                    323: Note that within the for-loop body,
                    324: repeated references to a column of a table will not result in additional SNMP
                    325: operations.
                    326: If, for some reason, you want to force a refresh of the variable's value,
                    327: use the subscript notation, e.g.,
                    328: \begin{quote}\small\begin{verbatim}
                    329: for (i in ipRouteDest) {
                    330:     printf "route to %s from %s\n",
                    331:         ipRouteDest, ipRouteNextHop[i];
                    332: }
                    333: \end{verbatim}\end{quote}
                    334: which causes each iteration to use the powerful SNMP get-next operation
                    335: to bind values to each column in the \verb"ipRoutingTable",
                    336: and the corresponding instance-identifier is assigned to \verb"i".
                    337: Then,
                    338: when the \verb"printf" statement is executed,
                    339: a separate SNMP get operation will be used to supply a (possibly) new value
                    340: for \verb"ipRouteNextHop".
                    341: Usually,
                    342: you use the subscript notation when you want to look at a variable in another
                    343: table, e.g.,
                    344: \begin{quote}\small\begin{verbatim}
                    345: for (i in ipRouteDest) {
                    346:     printf "route to %s from %s on %s (interface #%d)\n",
                    347:         ipRouteDest, ipRouteNextHop,;
                    348:         ifDescr[ipRouteIfIndex], ipRouteIfIndex;
                    349: }
                    350: \end{verbatim}\end{quote}
                    351: which causes each iteration to perform the powerful SNMP get-next operation
                    352: being to bind values to each column in the \verb"ipRoutingTable",
                    353: and the corresponding instance-identifier is assigned to \verb"i".
                    354: Then,
                    355: when the \verb"printf" statement is executed,
                    356: a separate SNMP get operation will be used to supply the corresponding value
                    357: of \verb"ifDescr".
                    358: 
                    359: Of course,
                    360: there's always the question of dealing with agents which may not support the
                    361: table or when an error occurs.
                    362: Usually, the following code fragment is sufficient:
                    363: \begin{quote}\small\begin{verbatim}
                    364: didone = 0;
                    365: for (i in tabularVariable) {
                    366:     didone = 1;
                    367: 
                    368: #   handle one row of the table here...
                    369: }
                    370: if (didone == 0) {
                    371:     if (DIAGNOSTIC) {
                    372: #       handle table error here...
                    373:     }
                    374:     else {
                    375: #       handle empty table here...
                    376:     }
                    377: }
                    378: else
                    379:     if (DIAGNOSTIC) {
                    380: #       handle partial table here...
                    381:     }
                    382: \end{verbatim}\end{quote}
                    383: Finding an empty or partial table is often unimportant,
                    384: so the boilerplate usually is:
                    385: \begin{quote}\small\begin{verbatim}
                    386: didone = 0;
                    387: for (i in tabularVariable) {
                    388:     didone = 1;
                    389: 
                    390: #   handle one row of the table here...
                    391: }
                    392: if (!didone && DIAGNOSTIC)
                    393:     printf "table: %s\n", DIAGNOSTIC;
                    394: \end{verbatim}\end{quote}
                    395: 
                    396: \subsubsection*        {Non-tabular variables (revisited)}
                    397: If you are accessing a lot of non-tabular variables sharing a common parent
                    398: (e.g., within the \verb"system" group),
                    399: you can use the \verb"for-in" construct to walk this degenerate tree,
                    400: e.g.,
                    401: \begin{quote}\small\begin{verbatim}
                    402: for (i in sysDescr) {
                    403: #   this for-loop is executed at most once...
                    404: }
                    405: \end{verbatim}\end{quote}
                    406: will cause all the non-tabular variables having the same immediate parent as
                    407: \verb"sysDescr" to be retrieved in a single SNMP operation,
                    408: and the corresponding instance-identifier (i.e., \verb"0") is assigned to
                    409: \verb"i".
                    410: 
                    411: This syntax is used only for optimization of network traffic.
                    412: 
                    413: \subsubsection*        {Illegal References}
                    414: If you do not use the subscript notation,
                    415: then it is illegal to reference a tabular variable outside of a \verb"for-in"
                    416: loop.
                    417: This causes a fatal error in a \pgm{gawk} script.
                    418: 
                    419: Further,
                    420: it is illegal to use an SNMP variable as an ``lvalue''.
                    421: 
                    422: Finally,
                    423: non-leaf variables,
                    424: (e.g., \verb"ifTable") are not recognized by the \pgm{gawk} front-end as being
                    425: accessible via the SNMP.
                    426: These are treated as ordinary \pgm{gawk} variables without any SNMP semantics.
                    427: 
                    428: \subsection*   {Data typing}
                    429: The \pgm{gawk} program has two kinds of data types: numbers and strings.
                    430: When mapping MIB objects to these data types,
                    431: the following conventions are used: 
                    432: \[\begin{tabular}{|r|l|l|l|}
                    433: \hline
                    434: \multicolumn{1}{|c|}{\bf Syntax}&
                    435:                \multicolumn{1}{c|}{\bf Type}&
                    436:                        \multicolumn{1}{c|}{\bf Format}\\
                    437: \hline
                    438: INTEGER&               number&         \\
                    439: OCTET STRING&          string&         \verb|"%02x: ... : %02x"|\\
                    440: DisplayString&         string&         \\
                    441: OBJECT IDENTIFIER&     string&         \verb|"%u. ... .%u"|\\
                    442: NULL&                  string&         \verb|"NULL"|\\
                    443: IpAddress&             string&         \verb|"a.b.c.d"|\\
                    444: NetworkAddress&                string&         \verb|"a.b.c.d"|\\
                    445: Counter&               number&         \\
                    446: Gauge&                 number&         \\
                    447: TimeTicks&             number&         \\
                    448: ClnpAddress&           string&         \verb|"%02x: ... : %02x"|\\
                    449: \hline
                    450: \end{tabular}\]
                    451: 
                    452: \subsection*   {Modifications to gawk}
                    453: The functional changes to \pgm{gawk} are quite straight-forward:
                    454: 
                    455: \subsubsection*        {Switches}
                    456: The \switch"s" turns on SNMP debugging to level 1,
                    457: whilst the \switch"S" turns on SNMP debugging to level 2.
                    458: 
                    459: At level~1 debugging and above,
                    460: exceptional events are reported to the diagnostic output.
                    461: At level~2 debugging and above,
                    462: SNMP PDUs are logged to the standard output.
                    463: For any debugging activity to occur,
                    464: the \file{snmp.c} module in \pgm{gawk} must be compiled with \verb"-DDEBUG".
                    465: 
                    466: \subsubsection*        {Variables}
                    467: There are a few built-in, read-write variables added:
                    468: \begin{small}
                    469: \[\begin{tabular}{|r|l|l|l|}
                    470: \hline
                    471: \multicolumn{1}{|c|}{\bf Variable}&
                    472:                \multicolumn{1}{|c|}{\bf Type}&
                    473:                        \multicolumn{1}{|c|}{\bf Value of}&
                    474:                                        \multicolumn{1}{|c|}{\bf Default}\\
                    475: \hline
                    476: \smaller AGENT&                string& SNMP agent name or address&     localhost\\
                    477: \smaller COMMUNITY&    string& SNMP community name&            public\\
                    478: \smaller DIAGNOSTIC&   string& last thing to go wrong&         \\
                    479: \smaller ERROR&                number& last SNMP error status&         \\
                    480: \smaller RETRIES&      number& times to retry SNMP operation&  3\\
                    481: \smaller TIMEOUT&      number& seconds between retries&        10\\
                    482: \hline
                    483: \end{tabular}\]\normalsize
                    484: The \verb"DIAGNOSTIC" and \verb"ERROR" variables are set after each SNMP
                    485: operation.
                    486: If no error occurs,
                    487: then \verb"DIAGNOSTIC" variable is set to the empty string,
                    488: and \verb"ERROR" varaible is set to \verb"0".
                    489: \end{small}
                    490: 
                    491: \subsubsection*        {Functions}
                    492: There are a few built-in functions added:
                    493: \begin{itemize}
                    494: \item  The \verb"bitwise_and(i,j)" function returns the bit-wise AND of the
                    495:        two unsigned long quantities, \verb"i" and \verb"j".
                    496: 
                    497: \item  The \verb"bitwise_or(i,j)" function returns the bit-wise OR of the
                    498:        two unsigned long quantities, \verb"i" and \verb"j".
                    499: \end{itemize}
                    500: 
                    501: \subsection*   {An Example}
                    502: After installing the SNMP-capable \pgm{gawk},
                    503: the \file{READ-ME-FIRST} file describes how to install \pgm{s-netstat},
                    504: a program which provides the functionality of \pgm{netstat} using the SNMP
                    505: rather than reading \file{/dev/kmem}.
                    506: This script and associated \pgm{gawk} scripts is an excellent example of how
                    507: the new \pgm{gawk} can be used to prototype new management applications.
                    508: 
                    509: \end{document}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.