On Sat, 2005-02-19 at 10:17, Ben Rockwood wrote:
>   I've long been frustrated by the poor documentation available for 
> Net-SNMP so I wrote my own manual a while back....
>   I hope it can be useful.

Thank you for that.  I've had a look through it, and there's
a lot of good stuff there.   However, I also detected a few
areas where either you seem to have misunderstood certain
aspects of SNMP slightly, or else you've phrased things in
such a way that an inexperienced reader could very easily
come away with the wrong impression.

I've therefore taken the liberty of putting together a
series of comments and suggested amendments, which I'm
attaching.

Please don't be alarmed by the length of this list!
It's more an indication of my pedantic nature, rather
than a comment on the quality of your document :-)

  (It also includes various minor typos and grammatical
    corrections - none of which affect the basic quality
    of the content, but I thought I might as well point
    them out so you could get them fixed).


I hope you find this useful.

Dave
1.1 General Overview

    p2, para 2:  "The agent populates these values"
This description makes it sound as if the agent holds an internal
database of key-value pairs, and simply looks things up in this.
That's one possible approach but is not universally true, and the
agent may well retrieve data dynamically from somewhere else.

    p2 typos:  para 2, line  6: "agent's"
               para 2, line 14: "performed"

    p3, para 1:  "... disk usage numbers or port status information"
It might be possible to recognise host names or disk mount points
from the raw SNMP values.  I defy you to interpret disk usage figures
or network ports without a knowledge of the MIB objects that they
represent!

    p3, para 2:  "SNMP can be used in 2 ways"
There are actually three ways: polling, traps and configuration (SETs) 
Polling can be done using either GET or GETNEXT requests.
                 "..contact another SNMP agent when..."
Strictly speaking, traps aren't normally sent to an SNMP agent.  These
tend to be "notification generators" rather than "notification receivers".
It's possible for an agent to receive traps as well, but it's relatively
unusual.  This is repeated in the next paragraph as well.

    p3, para 4:  "Even an OpenSource NMS is now available"
There's actually been an OpenSource NMS (tkined) available for almost
ten years.  It may not have the same polished appearance as OpenNMS
or some of the commercial offerings, but it predates most of these
by quite some time.

    p3 typos:  para 1, line  2: "you're"
               para 1, line  5: "OIDs"
               para 2, line  2: "..that *sends* an SNMP.."
               para 2, line 2/3: "..looking *for* some value.."


1.2 Three Flavors of SNMP

    p4, para 2: "SNMPv2 ... had no message definition"
This is somewhat misleading. SNMPv2 *did* define request structures
(PDUs in SNMP terminology) - with Trap2/Inform being additions to
SNMPv1.  It was only the administrative stuff that was missing.

Your discussion of types isn't quite right either.   Counter32,
Gauge32 and UInteger32 weren't really new - just renamed and more
clearly described.  And BIT STRING is not part of SMIv1 or SMIv2
(though it is part of ASN.1).  You're probably thinking of BITS,
which *was* added to SMIv2.

It's not particularly clear what you mean by "enhancements to
OID tables", though I presume you mean the GETBULK request.
SET support wasn't really altered - SNMPv2 just added better
error reporting.  A more significant difference (that you don't
seem to mention) would be the use of exceptions in GET (and
GETNEXT) requests - this allows "partial" results to be returned.

    p4, para 3: "ASN.1 BER"
These are actually two separate standards - BER is used to encode
ASN.1, but they're not the same thing.  SMIv2 and ASN.1 are probably
more closely linked, although you refer to them separately later
in this paragraph.

    p4 typos:  para 4, line  1: "However" (capital H)


1.3 What we won't discuss

    p4, para 1:
The other thing that isn't covered at all in this document is
the handling of MIB tables.  I can understand why you might omit
covering this, but it's definitely important to mention it here.
Some of your discussion of instance subidentifiers later is a bit
confusing, and could be made clearer if you state that you'll only
be working with scalar objects.  (However you want to phrase that).

    p4, para 2:   "that's referring to applications..."
What is?  You actually mean asynchronous applications, but it's
not immediately clear from the text.  I'd also question whether
GUIs are an example of the asynchronous (SNMP) interface - they're
more an example of something that would need to *use* this approach.
Threads and Forks aren't the same as the asynchronous interface
either - they're almost alternatives to it.

    p4 typos:  para 2, line  2: "that's"


2.1 OIDs

    p5, para 1:
I've been working with SNMP for ten years now, and I can't recall
ever coming across the term "relevant" used in this way.  Where
have you found it used?

    p5, para 3:
There are plenty of OIDs that don't fall under the 'private' subtree
(and hence don't start .1.3.6.1.4) - all "standard" MIB objects,
for instance.  But everything that comes in this tree will *always*
be under the "enterprises(1)" subtree.

The leading dot to indicate a fully-qualified OID is actually a
Net-SNMP convention, and it's perfectly valid to refer to
"iso.org...." without this leading dot.  (And strictly speaking,
the leading dot form probably isn't actually legal!)

    p5, para 5:
Similarly, the "relative" form is also a Net-SNMP convention,
and isn't quite as simple as you make out.  It's primarily
rooted at .iso(1).org(3).dod(6).mgmt(2).mib-2(1), and the
.iso(1).org(3).dod(6).private(4) form is more of an add-on.

    p6, para 2:
On the other hand, the "MIB::key" syntax *is* standard.
Or rather, the syntax "MIB.key" is - the :: form is not
strictly valid, but is widely accepted

Your description of "multiple instances" and "instance value"
is not particularly clear.  In particular, it's probably
worth mentioning that .0 is used for all scalar objects
(where there is only one instance)

    p6 typos:  para 1, line 2: drop the leading '.'


2.2 MIBs

    p6, example:
You'd probably do better to import the standard symbols from
SNMPv2-SMI and SNMPv2-TC (i.e. define MIBs in SMIv2) wherever
possible.

    p6 typos:  para 1, line 3: "you're"
               para 2, line 1: "Let's"
               para 4, line 3/4: drop the leading dots

    p7, para 4:
You describe building up the OID of 'upsBasicOutputStatus' by
walking back through the ancestors of this definitions.  But
none of these ancestral definitions are listed, so it's not
actually particularly clear what's happening.

The last line talks about .0 indicating the first instance of
the key.  It would be more accurate to say that it indicates
the *only* instance of this key (assuming it's not part of a

    p8 typos:  para 2, line 1:  "what's"
               para 2, line 7/8: "you're" (both times)


2.3 OID Data Types

    p8:
I'm not sure how true it is to say that Octet String is typically
limited to 255 characters- at least not without mentioning some
of the standard Textual Conventions that define this.

It doesn't make much sense to refer to Bit String (or BITS) as an
"unsigned" datatype, given that it's a string, rather than numeric.

The format used for representing maximum values is different for
TimeTicks when compared with the other types.

Opaque *is* still used, though not much (and its use is discouraged).
It's how we support floating point values, for example.

    p9, para 1:
The meaning of "otherwise disregard it" is unclear.  I presume you
mean instructing the tools not to display the type string, but
that's not really the same thing.


2.4 MIB-II

All of the MIB groups that you refer to in this section have been
superceded by equivalent or updated SMIv2 MIBs - which is why the
Net-SNMP tools report them using the more modern versions.
Also, none of this information lies under .1.3.6.1.4 (contrary to
what you say on p5)

    p10, para 1:
It's misleading to say that all this data is required.
Each block is required for agents that support that particular MIB
(and that particular protocol), but this is something of a tautology.
It's perfectly valid for a UDP-only box not to support the TCP
group, for example.  And the Address Translation group is officially
deprecated now.


2.5 Adding MIBs

    p10, para 1:
Referring to ${PREFIX} is strictly accurate, but a little unhelpful
for beginners.  It would probably be more useful to talk about
/usr/local/share/snmp/mibs (as you do in your later examples, and
on p13).

Renaming MIBs to follow a particular naming convention is purely for
the convenience of the administrator - the Net-SNMP tools don't care.
They'll use whatever MIB files they find, regardless of name or suffix.

    p10, para 5:
I'm somewhat surprised that '-m ./filename.txt' works.  The -m
flag is primarily intended to take a list of MIB module names
(i.e. "MY_MIB") rather than filenames.   But if it works, then OK.

    p10 typos:  para 1, line 4:  "MIB's"
                para 5, line 5: "Net-SNMP mibs/ directory"
                                (see use in para 3)


3 The Net-SNMP CLI

    p11 typos:  para 1, line 3:  "you're" and "that's"
                        line 4:  "home in", not "hone in"


3.1 Probing a device

    p11 typos:  para 1, line 2:  "what's"
                        line 7:  needs a comma after "reported"
                        line 1:  "what's"

    p12, para 2: "all OIDs will start from that root [enterprises]"
This is not correct - see above.

    p12, second example
The MIB name (PowerNet-MIB) doesn't match the MIB file that you've
requested to be loaded (APC-POWERNET.txt).  While this is perfectly
valid, it's somewhat confusing - particularly since you earlier
suggested using the same name for both.

    p12, last paragraph
Walking the agent is certainly useful, but only reports what devices,
etc that it knows about at that particular time.  If the system or
agent configuration changes later, then this might well add new
MIB objects that weren't present before.  But the saved walk won't
know about them.

    p12 typos:  para 2, line 1:  "you're"
                        line 3:  "what's"
                para 3, line 1:  "Let's"
                para 6, line 4:  "*I* returned" ??
                        line 1:  "what's"


3.2 Polling Individual OIDs

    p13, para 1:  "return [the value to] STDOUT in any form that you wish"
This is perhaps a little optimistic!  'snmpget' and friends offer a range
of possible output formats, but it's not infinitely flexible!

    p13, para 4:  "we might start probing the wrong OID"
Revisions to MIB files are not allowed to change the behaviour of a given
OID, or change the OID associated with a given name.  So it doesn't matter
whether you have the MIB file or not - the data for a given OID/name will
be consistent.


    p13 typos:  para 1, line 2:  Missing "to" before "STDOUT"
                example, line 2: Suggest you omit the leading '>'
                                 (both here and elsewhere)
                para 3, line 1:  "its" (of it) not "it's" (it is) numeric OID


3.3 Net-SNMP CLI Tool Options

    p13, para 1:  "the community name of the target agent"
This is not relevant for SNMPv3 queries, for which there are different
"mandatory" options.  (And these options, the community string and even
the SNMP version can be specified in the $HOME/.snmp/snmp.conf file)

    p13, para 4:
The Net-SNMP library (and hence the tools) don't care about the suffix
used for MIB files.  They'll work with MY-MIB.txt, MY-MIB.mib, MY-MIB.suffix
or even just MY-MIB - it shouldn't make any difference whatsoever.

But there *is* a distinction between the name of the file (including suffix)
and the name of the MIB (the token before DEFINITIONS).  So when anything
refers to the MIB without the suffix, it's usually referring to the name
of the MIB *module*, and is nothing to do with filename at all.

    p14 typos:  second example, last line:  "*has* an Input..."
                (and again in the output that follows)


4.1  Simply Polling with PERL

The name of the language is conventionally written as Perl, not PERL

    p15, example:
If you're requesting a MIB to be loaded using -m, then you don't need
to specify individual objects using the syntax MIB::name.
Conversely, if you're specify objects using MIB::name, then you don't
need the -m option.

    p15 typos: para 1, line 3:  "GETs" (for consistency)
               para 2, line 1:  "Let's"

    p16 typos: para 2, line 1:  "pretty *or* efficient"


4.2 The Net-SNMP Perl Module

    p16, para 1:
Several of the SNMP-related module in CPAN are completely unrelated
to the Net-SNMP project, and it's not appropriate for us to describe
them as deprecated.  It's *only* the "SNMP" module itself that is
ours (and *is* deprecated).

    p16, para 2:
The other thing that is important is to use the version of the Perl
module that matches the SNMP C library.   If these aren't the same,
then things may not work correctly.

    p16, para 3:
Perl applications don't typically use "SNMP::getnext()" in that form.
They're more likely to use "$session->getnext()" or "$session->get()",
calling methods of a particular SNMP::Session variable.

    p17 typos: para 1, line 1:  "its"

    p18, para 1:
Loading "ALL" MIBs relies on the Power-MIB being installed into the
appropriate MIB directory (as in fact the earlier examples in this
chapter do).  This contrasts with the approach used in Chapter 3,
where the MIB file was in the current directory.  It might be worth
mentioning this explicitly - perhaps at the start of the chapter.

    p18 typos:  para 3,  line 1: "previous version [singular]"
                example, line 2: "Serial No" doesn't line up with IP
                                 (and you haven't removed the actual
                                  serial number, as you do elsewhere)


5 Trap Handlers

    p19 typos: para 1, line 4: "that's"


5.1 Trap Daemon Configuration

    p20, para 1:
It might be worth mentioning that snmptrapd.conf entries should always
use the SMIv2-style NOTIFICATION-TYPE OIDs (or equivalent) - even if
the traps actually arrive as SNMPv1 traps.

    p20 typos:  para 1, line 1: "all 4 lines uncommented line"
                                doesn't make sense!
                para 1, line 4: "it is *wise*, and "trap's"


5.2 Simple Trap Handler

    p20, para 1:  Perl, not PERL

    p20, para 2:
This could be mis-read as implying that the snmptrapd.conf arguments
will be passed via STDIN (rather than as command-line options).

    p20, para 3:
VARBIND and VarList are not quite the same thing - a VarList is made
up of one or more VarBinds.

    p21, example:
This output shows very clearly that traps are *always* passed to the
traphandler script in SNMPv2 trap format, even if they actually
arrived as an SNMPv1 trap.  This is probably worth mentioning
somewhere.


5.3 Starting the Trap Daemon

    p21, example:
Your code for starting the trap daemon includes an option (-n) that
you haven't mentioned at all, and which affects the behaviour that you
did mention earlier (passing the hostname to the script).  Either
mention the option here, or drop it from the example.
  I'd also suggest reducing the amount of indentation, so that the
trapd start line doesn't race off to the edge of the page.


6 Net-SNMP C API

    p23, para 1:  Perl, not PERL

    p23, para 2:
This talks about "several aspects" and "these aspects" (both plural),
but the only new aspect that you actually mention is "namely PDUs"
(a single aspect).  Either list some other new aspects, or make
everything singular.
       [Yes, I know - I'm being incredibly picky!
        But both my parents are arts graduates, so I was
        indoctrinated at a very early age and this sort
        of inconsistency grates something horrible! :-)  ]


6.1 SNMP Internals

    p23, bullet 4:  PDU stands for *Protocol* Data Unit
                    (and again on p24, para 3)
         bullet 8:  Free the *response* PDU
                    The request PDU is freed automatically
                    (as long as the request succeeds)

    p24, para 2:
The system MIBs are actually loaded when the library is initialised,
rather than when the session is created.  (Although the session
creation may well be the call that triggers this, depending on what
else happened before).
   "[using] a MIB that isn't installed" is a bit unclear.  I think
you mean installing a MIB in order to use it, though I'm not sure
how removing a MIB enters into things.

    p24, para 3:
A PDU isn't actually just a fancy name for a packet.  There *is*
a difference between an SNMP request PDU, and an SNMP message
(i.e. the packet as commonly understood).  The message comprises
the version and admin information, together with the PDU itself.
So the PDU proper doesn't actually include the version or community
string.

The discussion of how many PDUs are needed is a bit misleading.
The fundamental point is that a single PDU can only handle one
*type* of request at a time.  So if you have a single OID that
you need to both read from and write to, then this will inherently
involve two separate requests (although you could re-use the same
data structure for the second request).
  If you need to read two or more OIDs, or write to two or more OIDs,
these just involve a single type of request, so all the OIDs can be
packed into the one PDU request.  (Or they could be sent individually,
which is then exactly the same situation as the read/write example).

You don't actually need to "read the OID from the MIB" before
adding it to the PDU.  What 'read_objid()' does is convert from
the textual name into the numeric OID (using the MIB).  If you
know what the numeric form of the OID is, you can add it directly
to the PDU without needing to look at the MIB at all.

    p25, structure
It would be sensible to use the current Net-SNMP naming conventions,
rather than the old UCD-SNMP style.  So the name of the PDU structure
would actually be "netsnmp_pdu" (and the capitalisation of "snmp_PDU"
just before is wrong anyway).

    p25, para 4:
The 'reqid' value is provided automatically - the programmer doesn't
need to bother filling this in.  

    p25 typos: para 4, line 4: "you're"
               para 5, line 5: "a break capture" ?

    p25/26, example:
The indentation and spacing of the Ethereal header doesn't match that
on the previous page (which looked somewhat clearer).

    p26, para 1:
If you're only showing two OIDs, why mention that you originally sent
eight?   Why not lie and say you sent two all along?  No-one will know!

    p26, para 2:
This paragraph is not at all clear - is this structure's use of a list
meant to be obvious or not?  ('Cos that's all it is - a linked list of
varbinds)

    p26, structure:
You can safely omit the last five fields - they're internal stuff.
The only important fields are the name/type/value triplet (including
lengths), and the 'next' pointer for the linked list.

    p27 typos: para 1, line 1:  "it's"
               para 2, line 3:  "that's"
               para 3, line 1:  "let's"

      [Sorry to be so picky - but I'm very conscious of the
       proper (and improper) use of the apostrophe.  I don't
       know whether you've come across Lynn Truss' book "Eats,
       Shoots & Leaves", but that's the sort of person I am :-) ]


6.3 Simple Example

    p27 typos: para 1, line 4: "and *receives* the response"

    p28, example code:
Indentation is wrong on lines 1-2 (usage error handling), lines 6-9
(configuring the session settings), lines 15/17 (adding varbinds)
and 20 (printing the results)

    p28, output
This uses a new approach for hiding the serial number (cf p16)

    p29, para 3:
While strictly speakeing, it is perfectly correct that the PDU type
is defined as a "macro", in practise it's really just a named constant.
It might be simpler to refer to it as such.

Once again, 'read_objid()' simply converts from a MIB object name
to the numeric form - it's not really reading the OID from the MIB.

It's probably not true to say that this is typically wrapped in a
loop.  Many SNMP application may well work with specific MIB objects,
in which case they would simply list them in order (exactly as here).
Always assuming that they didn't hardwire the numeric OIDs in the
first place.   Wrapping "read_objid()/snmp_add_null_var()" within
a loop is only necessary for applications that work with arbitrary
OIDs supplied by the user (such as 'snmpget' and friends)

    p29, para 6:
The PDU used for the request will be freed automatically if the
request succeeds.  It's only the response PDU that needs to be
freed by the programmer.
  Of course, if sending the request fails, there won't be a
response PDU to free, but the request PDU will contain information
about the failure, and this PDU *will* need to be freed.

    p29 typos: para 1, line 3: "of *the* agent...."


6.4 Closing Thoughts

    p29 typos: para 1, line 7: "vendor's"

 [Trust Shield to end off with yet another missing apostrophe!!]

Reply via email to