|
|
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.