Network Management
Week 3, Feb 7
LT-412, Mon 4:15-6:45 pm
history
ASN.1
table format
interfaces table
at, ip tables
assignment
ASN.1
get, get-next
net-snmp agent configuration
Network planning
BER
Read in M&S:
Chapter 1
Chaper 2: pp 19-39, 43-44
Assignment 1
Write a script (in whatever scripting language you
wish; I'd use unix shell scripting if you don't have an established
favorite) to get ifInOctets and ifOutOctets from ulam2.cs.luc.edu every
15 minutes,
for a day.
Due: Feb 21 (ok if in by end of the week)
Here are some notes on shell scripting.
Every hour, at a certain number of minutes past the hour, ulam2
transfers a large chunk of data across its "loopback" (lo) interface.
Find the amount, and in which quarter-hour it occurs.
1.3.6.1.2.1: mib2
mib2.1: system
mib2.2: interfaces
system.2. iftable
iftable.1: ifentry
ifinoctets: ifentry.10 = 1.3.6.1.2.1.2.2.1.10
ifoutoctets: ifentry.16
individual ifinoctet values for specific interfaces (2 on ulam2):
ifinoctents.1 (loopback), ifinoctets.2 (ethernet)
Run this on random.cs.luc.edu or infinity.cs.luc.edu, probably.
use snmpget or snmpwalk (more likely snmpget).
To run something every 15 minutes:
crontab:
Run "crontab -e" to open up an editor (probably nano), and create the
following entry for your script:
(This runs it when the minutes part of the clock is 0, 15, 30, or 45)
0,15,30,45 * * * * $HOME/myscriptname.sh >> myfile.out 2>&1
(In class I did the >> redirecting in the script file itself,
rather than in the crontab entry. You must redirect one place or the
other, but you do not need both. In class I also expanded $HOME, the
full name of my home directory, manually. You don't actually need that;
see below.)
There must be no spaces in the "0,15,30,45", followed by exactly four asterisks that are
separated by spaces. These represent the five crontab time fields: the
minutes, hours, day-of-month, day-of-week, and year. Asterisk means
that the script is run every hour of every day of every year, at the minutes specified (0,15,30,45).
Alternative: create a script file, keep it running for 24 hours
(either from a home computer through a terminal session on random or infinity
that's just quietly sitting there or using the "nohup" command)
I can be flexible if you run it less than 24 hours; it's fine, for
example, if you leave it running overnight, while your laptop is at
home and you have a terminal window open to random|infinity.
Suppose the script file is foo.sh:
while true
do
script >> myfile.out
sleep 900
# 900 seconds = 15 minutes
done
nohup foo.sh >/dev/null 2>&1
snmpget & snmpwalk are installed in standard places on {random,infinity}.
Updated notes on crontab
When crontab runs your script, it does
run in your home directory, by default. So my first (failed) example in
class did indeed run in my home directory, and created the mydata.text
file there. Unfortunately, I was expecting it to run in the $HOME/netmgmt subdirectory; that was not what was happening. When I checked after class, there was indeed a mydata.text in my home directory, containing all the snmpget values I'd expected at the beginning of class.
I fixed things in class by adding a cd command to move to the correct directory. I used the fully qualified name for the directory:
cd /homes/users/cs/faculty/pld/netmgmt
snmpget -v 1 -c public ulam2.cs.luc.edu $IFTABLE.16.1 >>mydata.text
However, it would have been sufficient to do the following, that is, using the relative path to the subdirectory:
cd netmgmt
snmpget ...
Here's a more or less full script (note that shell variable names, eg
IFTABLE here, are case-sensitive, and uppercase by old tradition). You will probably need more snmpget lines.
IFTABLE=1.3.6.1.2.1.2.2.1
cd netmgmt
date >> mydata.text
snmpget -v 1 -c public ulam2.cs.luc.edu $IFTABLE.10.1 >>mydata.text
Also, in the crontab entry I needed to make this executable:
chmod +x inoctets.sh
Perl
You don't have to do this in perl (and in fact I don't necessarily
recommend it, but perl is certainly a popular scripting language.
Here's a good overview site:
http://search.cpan.org/~rgarcia/perl-5.9.2/pod/perlintro.pod
Here's more on working with hash references:
http://www.cs.mcgill.ca/~abatko/computers/programming/perl/howto/hash/
Perl is a weird language. Things that should be transparent are not. Sigh.
In order to use the SNMP module, it has to be installed. It should generally be installed with the Net-SNMP package, using the --with-perl-modules directive or the winquivalent.
I could not find the SNMP_util package referred to in Mauro &
Schmidt's Appendix E, so I'm using SNMP (which is also in M&S, but
later, starting at page 389, and a little more work to get started).
The SNMP package typically entails creation of a basic session object
at the outset.
simple_get.pl:
#!/usr/bin/perl
use SNMP;
$SNMP::use_sprint_value = 1;
my $host = "localhost";
my $community="public";
$sess = new SNMP::Session(
'DestHost' => $host,
'Community' => $community,
'Version' => 2
);
die "cannot create session: ${SNMP::ErrorStr}\n" unless defined $sess;
my $getvars = new SNMP::VarList(
['sysDescr',0], # this represents sysDescr.0 The 0 is needed for get
['sysContact',0],
['sysUpTime',0],
['ifNumber',0],
['ifSpeed',1],
['ifDescr',2],
['ifInOctets',2],
['ifOutOctets',2]
);
my @response = $sess->get($getvars); # try changing to getnext
print "start foreach\n";
foreach my $val (@response) {
print "$val\n";
}
print "end foreach\n";
print "======================\n";
$ifname = @response[5];
$ifinoctets = @response[6];
$ifoutoctets= @response[7];
$ifnumber = @response[3];
print "there are $ifnumber interfaces\n";
print "$ifname ifinoctets = $ifinoctets\n";
print "$ifname ifoutoctets = $ifoutoctets\n";
out_octets.pl
#!/usr/bin/perl
# use strict;
use SNMP;
$SNMP::use_sprint_value = 1;
my $host = "localhost";
my $community="public";
$sess = new SNMP::Session(
'DestHost' => $host,
'Community' => $community,
'Version' => 2
);
die "cannot create session: ${SNMP::ErrorStr}\n" unless defined $sess;
my $getvars = new SNMP::VarList(
['ifDescr',2], # note how we describe ifDescr.2
['ifInOctets',2],
['ifOutOctets',2]
);
my $count = 0;
my $previnoctets = 0;
my $prevoutoctets = 0;
while ($count < 100) {
$count++;
my @response = $sess->get($getvars);
my $ifname = @response[0];
my $ifinoctets = @response[1];
my $ifoutoctets= @response[2];
print "$ifname ifinoctets = $ifinoctets;";
my $delta = $ifinoctets - $previnoctets;
$previnoctets = $ifinoctets;
print "\t\tdelta = $delta\n";
sleep 10;
}
iftable.pl
Uses gettable()
#!/usr/bin/perl
use SNMP;
use Data::Dumper;
$SNMP::use_sprint_value = 1;
my $host = "localhost";
my $community="public";
$sess = new SNMP::Session(
'DestHost' => $host,
'Community' => $community,
'Version' => 1
);
die "cannot create session: ${SNMP::ErrorStr}\n" unless defined $sess;
my $response = $sess->gettable('ifTable'); # $response is a reference to hash
print "size of response is " . keys(%$response) . "\n";
@keys = keys(%$response);
print "keys are :";
foreach my $k (@keys) {
print "$k ";
}
print "\n";
##================== print values??
my $eth0 = %{$response->{1}}; # weird use of $; this should be another hash.
my @eth0keys = keys %{$response->{1}};
print "eth0 keys: " . @eth0keys . "\n";
foreach my $k (@eth0keys) {
print "$k ";
}
print "\n";
print("========================\n");
# from www.cs.mcgill.ca/~abatko/computers/programming/perl/howto/hash/
# goal: print everything in a two-level hash *reference*
for my $k1 ( sort keys %$response ) {
print "key: $k1\n";
for my $k2 ( keys %{$response->{ $k1 }} ) {
print " $k2 $response->{ $k1 }{ $k2 }\n";
}
}
#=============================
# print Dumper(%$response);
iReasoning tool and tables
demo
History of SNMP
SGMP: Simple Gateway Monitoring Protocol:
started 1987; conflict with OSI approach
The OSI strategy was CMIP: Common management information protocol.
It was too complex and large at the time it was defined for practical
implementation. It does have the advantage of being object-oriented,
which turns out to be a significant win here. This allows inheritance
chains such as:
cisco-device, generic-Ethernet-switch
⟵ cisco-Ethernet-switch
⟵ cisco-catalyst
⟵ cisco-catalyst-2960-series
⟵ cisco-WS-C2960S-48FPD-L (doubles as a space heater for a small room)
Note the multiple inheritance above; whether CMIP actually supports that is unclear.
Any maker of an SNMP device will generate a Management Information Base
(MIB) for their device, consisting of formal definitions for the OID
strings used, and what the responses will be.
CMIP: Basic OSI strategy; too complex and large at the time it was defined for practical implementation.
1988: IAB decided to pursue both SGMP and CMOT: CMIP Over TCP/IP
[note that for an OSI management protocol to run over TCP, and thus not
to require compatibility with OSI networking protocols, was a huge
concession].
This dual strategy failed within a year: CMOT was dropped, SGMP had evolved into SNMPv1.
Technically, we're still waiting for CMIP/CMOP.
(Note that the IAB typically standardizes things a year or so after the thing has been rolled out. In fact, in order to become a standard, two independent implementations must exist.)
1990: SNMP v1 and SMI v1 had both been standardized. See RFC 1155.
1991: the SNMP mib-2 group was published, consisting of system, interfaces, etc.
1993: RFC 1442, SNMP v2 SMI (first version, obsoleted by RFC 1902 in
1996); first SNMPv2 proposal. There is extensive controversy on how
best to improve the security of SNMPv1.
1996: SNMPv2, Experimental (RFC 1901, Jan 1996); SNMPv2 standardization
for the so-called "community-based version", now known as SNMPv2c, is
complete. This proposal represented the abandonment of work done to produce a secure version; "community" is the name given to the SNMPv1 technique of cleartext userid-passwords.
1999: SMI version 2. Note that version 2 and mib 2 have nothing in common.
2002: RFCs 3411-3418 are published, defining SNMPv3. SNMPv3 had in fact
been pretty solid since ~2000. Security support is now thoroughly built
in.
To
enable community-based security for SNMPv1 (or SNMPv2c), you have to
"manually" (that is, outside of SNMP) configure the agent with the
community string, and then configure the manager to contain that
<agent,community> pair. SNMPv3 likewise requires some initial
"manual" configuration of the agent with a suitable key, and then
provide the manager with suitable credentials so that it can prove to
the agent that it has (or knows) the key. So, in that sense, SNMPv3 is
similar to its predecessors. In the details, however, SNMPv3
configuration is decidedly more complex.
ASN.1
See http://luca.ntop.org/Teaching/Appunti/asn1.html.
SNMP uses Abstract Syntax Notation 1 (ASN.1) to define syntax;
encoding into UDP packets is then done using the Basic Encoding Rules
(BER). Right now it sufficies to note the following:
- BER data is tagged with its type.
- ASN.1 and BER supports compound data types. However, SNMP does not use these; all data is atomic. (However, SNMP does support tables, which corresponds roughly to record formats and which can be pressed into service to represent, say, arrays.)
- SNMP
uses the ASN.1 type constructors SEQUENCE (to define lists)
and SEQUENCE OF (to define records). A table is a SEQUENCE of records;
each record is a SEQUENCE OF a specific list of fields. (ASN.1 also has
SET and SET OF constructors, but SNMP does not use these directly.)
- ASN.1 also supports CHOICE types, but these are used in SNMP only for very high-level definitions, eg
SimpleSyntax ::=
CHOICE {
number
INTEGER,
string
OCTET STRING,
object
OBJECT IDENTIFIER,
empty
NULL
}
- SNMP
does not use all the available basic ASN.1/BER data types. In fact,
only INTEGER, OCTET STRING, OBJECT IDENTIFIER, and NULL are allowed.
However, some subtypes of INTEGER are created; these are called defined types.
- The BER encoding is such that the actual size in bytes of the data can be difficult to predict.
Some defined types from RFC 1155:
- IpAddress: (a 4-byte OCTET STRING in network byte order)
- Counter: (a non-negative INTEGER which increases monotonically to 2^32-1 until it wraps around)
- Gauge: a nonnegative
integer which "latches at a maximum value". This generally means that
if it ever hits the maximum, it sticks there and will not decrease.
Thus, if it hits the maximum, you will know.
- TimeTicks: an INTEGER representing time measured in 10ms (0.01 sec) units.
- Opaque: an arbitrary byte string, encoded as an OCTET STRING.
ASN.1 has more built-in data types. Every type is either
Universal, Application-specific, Private, or Context-specific. Some of
the universal types are BITSTRING, UTCTime, and PrintableString.
Some ASN.1:
Some definitions of high-level OID prefixes:
internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }
directory OBJECT IDENTIFIER ::= { internet 1 }
mgmt OBJECT IDENTIFIER ::= { internet 2 }
experimental OBJECT IDENTIFIER ::= { internet 3 }
private OBJECT IDENTIFIER ::= { internet 4 }
For defining records (eg ifEntry, or other table rows):
SEQUENCE { <type1>, ..., <typeN> }
Tables are lists of records, defined with
SEQUENCE OF <entry>
The OBJECT-TYPE macro is ubiquitous in MIB files. It provides a uniform
way to specify the value's type (the SYNTAX) field, and also the ACESS
and STATUS fields. The notation closes with "::= <OIDvalue>".
OBJECT-TYPE MACRO ::=
BEGIN
TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax)
"ACCESS" Access
"STATUS" Status
VALUE NOTATION ::= value (VALUE ObjectName)
Access ::= "read-only"
| "read-write"
| "write-only"
| "not-accessible"
Status ::= "mandatory"
| "optional"
| "obsolete"
END
Here are five examples of OBJECT-TYPE in use to define the (now-deprecated) at table (for ARP data). The OID for the at
group is 1.3.6.1.2.1.3. It defines atTable as at.1 (that is,
1.3.6.1.2.1.3.1), and atEntry as atTable.1, and the three columns as
atEntry.1, atEntry.2, and atEntry.3.
1. atIndex OBJECT-TYPE
SYNTAX INTEGER
ACCESS read-write
STATUS mandatory
::= { atEntry 1 }
2. atPhysAddress OBJECT-TYPE
SYNTAX OCTET STRING
ACCESS read-write
STATUS mandatory
::= { atEntry 2 }
3. atNetAddress OBJECT-TYPE
SYNTAX NetworkAddress
ACCESS read-write
STATUS mandatory
::= { atEntry 3 }
4. atEntry OBJECT-TYPE
SYNTAX AtEntry
ACCESS read-write
STATUS mandatory
::= { atTable 1 }
5. atTable OBJECT-TYPE
SYNTAX SEQUENCE OF AtEntry
ACCESS read-write
STATUS mandatory
::= { at 1 }
The first three entries define columns ("fields") of atEntry. The
fourth defines atEntry as having OID atTable.1, and with syntax the
CAPITALIZED AtEntry. The fifth defines atTable as having OID at.1, and
with syntax SEQUENCE OF AtEntry.
Finally there is
AtEntry ::= SEQUENCE {
atIndex
INTEGER,
atPhysAddress
OCTET STRING,
atNetAddress
NetworkAddress
}
Every table has a row specification like this, with name capitalized by convention. Note that the OBJECT-TYPE is not used here. We could splice AtEntry into the fourth and fifth OBJECT-TYPE entries above, but it's simpler not to.