|
|
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}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.