Sunday, March 7, 2010

Using Net-SNMP - 2

This is the second part of the N part series for understanding and working with Netsnmp.

See http://ashokachakra.blogspot.com/2010/03/using-net-snmp-1.html for details

We had configured and set up Netsnmp in the previous post. Now lets go ahead with writing our MIB

Ok, if you now ask me......whats a MIB....then you are in the wrong place. I assume that you already know what SNMP is, and what MIBs are and what an agent and a Manager does. You can refer to Stallings for more gyan....or else wikipedia and the netsnmp wiki ought to give you a basic idea

Our first MIB will have two scalar values, for which we try and get the values. I have borrowed an enterprises number from another blog I found on the net. Thanks for the same.

MY-COMPANY-MIB DEFINITIONS ::= BEGIN

IMPORTS
MODULE-IDENTITY, OBJECT-TYPE, enterprises, Integer32 FROM SNMPv2-SMI;

-- root of our MIB will point to enterprises

myCompanyMIB MODULE-IDENTITY
LAST-UPDATED
"200804230000Z"
ORGANIZATION
"asholachakra.blogspot.com"
CONTACT-INFO
"email: billgates@gmail.com"
DESCRIPTION
"Example MIB"
REVISION
"200804230000Z"
DESCRIPTION
"First and hopefully not the final revision"
::= { enterprises 3011 }

-- lets group all scalarValues in one node of our MIB

scalarValues OBJECT IDENTIFIER ::= { myCompanyMIB 1 }

-- time to define scalar values

hostLoggedUsers OBJECT-TYPE
SYNTAX Integer32 (0..65535)
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of actually logged users on"
::= { scalarValues 1 }

hostName OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Actual hostname"
::= { scalarValues 2 }

END


Writing modules for MIBs is a long and sometimes troublesome process, much like writing a parser. And just like writing a parser, you don't have to do everything by hand: MIBs can already be processed by computers pretty well, so there is no need to start from square one every time. The tool to convert an existing MIB to some C code is called mib2c and is part of the Net-SNMP distribution


Ok.....now that you have the MIB
At the command prompt, run mib2c as shown

linux-725y:~/.snmp/mib2cdata # mib2c scalarValues
writing to -
mib2c has multiple configuration files depending on the type of
code you need to write. You must pick one depending on your need.

You requested mib2c to be run on the following part of the MIB tree:
OID: scalarValues
numeric translation: .1.3.6.1.4.1.3011.1
number of scalars within: 2
number of tables within: 0
number of notifications within: 0

First, do you want to generate code that is compatible with the
ucd-snmp 4.X line of code, or code for the newer Net-SNMP 5.X code
base (which provides a much greater choice of APIs to pick from):

1) ucd-snmp style code
2) Net-SNMP style code

Select your choice : 2

**********************************************************************
GENERATING CODE FOR SCALAR OBJECTS:
**********************************************************************

It looks like you have some scalars in the mib you requested, so I
will now generate code for them if you wish. You have two choices
for scalar API styles currently. Pick between them, or choose not
to generate any code for the scalars:

1) If you're writing code for some generic scalars
(by hand use: "mib2c -c mib2c.scalar.conf scalarValues")

2) If you want to magically "tie" integer variables to integer
scalars
(by hand use: "mib2c -c mib2c.int_watch.conf scalarValues")

3) Don't generate any code for the scalars

Select your choice: 1
using the mib2c.scalar.conf configuration file to generate your code.
writing to scalarValues.h
writing to scalarValues.c



**********************************************************************
* NOTE WELL: The code generated by mib2c is only a template. *YOU* *
* must fill in the code before it'll work most of the time. In many *
* cases, spots that MUST be edited within the files are marked with *
* /* XXX */ or /* TODO */ comments. *
**********************************************************************
running indent on scalarValues.c
running indent on scalarValues.h
linux-725y:~/.snmp/mib2cdata #


If you now do an........... ls........... on that directory, you will see two files, scalarvalues.c and scalarvalues.h being generated.

mib2c has generated these two files which are, let's say, the framework to create valid SNMP handler.

We need to improve those files in order to support our SNMP queries: hostName, hostLoggedUsers.

Please note that scalarValues.h does not need any changes, so I only modified scalarValues.c as follows.

#include
#include
#include
#include "scalarValues.h"

struct HostStates
{
int loggedUsers;
char hostname[20];

} hostStates;

void
init_scalarValues(void)
{
static oid hostLoggedUsers_oid[] =
{ 1, 3, 6, 1, 4, 1,3011, 1, 1 };
static oid hostName_oid[] =
{ 1, 3, 6, 1, 4, 1,3011, 1, 2 };

netsnmp_register_scalar(
netsnmp_create_handler_registration("hostLoggedUsers", handle_hostLoggedUsers,
hostLoggedUsers_oid, OID_LENGTH(hostLoggedUsers_oid),
HANDLER_CAN_RONLY
));
netsnmp_register_scalar(
netsnmp_create_handler_registration("hostName", handle_hostName,
hostName_oid, OID_LENGTH(hostName_oid),
HANDLER_CAN_RONLY
));
}
int
handle_hostLoggedUsers(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
// obtain number of logged users here
hostStates.loggedUsers = 4;

switch(reqinfo->mode) {

case MODE_GET:
snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
(u_char *) &hostStates.loggedUsers, sizeof(hostStates.loggedUsers));
break;
default:
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
int
handle_hostName(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
// obtain hostname here
strcpy(hostStates.hostname, "flechetHost");

switch(reqinfo->mode) {

case MODE_GET:
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
(u_char *) &hostStates.hostname, strlen(hostStates.hostname));
break;
default:
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;



Ok, so what has changed ?? Mib2c does not know how we want to define the data, it is up to us to use individual data types or a user defined data structure. I have used a user defined data structure to store values for the integer and the octet string, and provided the pointer in memory for the same.

All I am doing at the moment is hardcoding the values of hostLoggedUsers and hostName. Lets get this working first and then see how we can obtain the same dynamically.

After that we will see how to do it for tables (using similar procedure)

Next steps will be to compile the c code into the agent and try to obtain the value.

Now it's time to compile ;) I will compile scalarValues.c to shared library libSnmpHandler.so and than I will install library in /usr/lib directory.

# gcc -shared -fPIC scalarValues.c -o libSnmpHandler.so
#cp libSnmpHandler.so /usr/lib

We can now configure net-snmp daemon to dynamically load our libSnmpHandler.so library on startup. In order to do this we need to create /etc/snmp/snmpd.conf file with following entries.
rocommunity public
rwcommunity public

dlmod scalarValues /usr/lib/libSnmpHandler.so



In snmpd.conf I also added rwcommunity and rocommunity entries. Both are simple passwords used by net-snmp daemon to authenticate SNMP clients. Of course it's possible to protect SNMP in a better way, but it's not area of this article. We're about to finish. Finally we can start net-snmp daemon with command:
# /etc/init.d/snmpd start
* Starting net-snmpd ...

Now it's time to verify if everything is working fine. We can use snmpget and snmpwalk tools to verify our work.
# snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.3011.1
MY-COMPANY-MIB::hostLoggedUsers.0 = INTEGER: 4
MY-COMPANY-MIB::hostName.0 = STRING: "
flechetHost"

# snmpwalk -v 2c -c public localhost scalarValues
MY-COMPANY-MIB::hostLoggedUsers.0 = INTEGER: 4
MY-COMPANY-MIB::hostName.0 = STRING: "
flechetHost"

# snmpwalk -v 2c -c public localhost hostLoggedUsers
MY-COMPANY-MIB::hostLoggedUsers.0 = INTEGER: 4

# snmpget -v 2c -c public localhost hostLoggedUsers.0
MY-COMPANY-MIB::hostLoggedUsers.0 = INTEGER: 4



It's working fine! Now it's easy to add another queries to our MIB and libSnmpHandler.so. Possible enhancement are processor temperature, file system state, CPU usage and more and more. With net-snmp we can easily monitor all aspects of Linux box.

Saturday, March 6, 2010

Using Net-SNMP - 1

Hi,

In this N part series, I shall post about

What SNMP is - very, very briefly
Install NetSNMP
Configure NetSNMP
Write a MIB
Use Mib2c to generate stubs for the agent
Populate the Stub code in the agent for the MIB you just wrote
Try and GET snmp to WALK through the NEXT few steps :)

Write more complex MIBs


Ok lets begin then, shall we..........

SNMP (Simple Network Management Protocol) is application layer protocol, mostly used in network devices (i.e. routers, printers, etc). In typical SNMP usage scenario SNMP client sends SNMP Get package to the network device in order to read its properties. When device reports any problems it is also possible to change device configuration using SNMP Set packages. Every device supports various queries (i.e. device uptime) and all of them are described in MIB (Management Information Base).


You can read more about SNMP protocol here: http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol


I told you guys I will be brief :)


Ok ....Now for the Installation ........

First, You will need a Linux System.......because all that I am going to explain next will be for that particular OS

I use Suse Linux 11.2, although I guess RedHat and Gentoo and Debian work just as fine .........

Ok, Login to the linux system ............By the way..............The download is available @ http://net-snmp.sourceforge.net/download.html

You need to pick up the SOURCE of the latest version ......Do not pick up binary, then you cannot play around with the source code. Get the tar.gz , since you will intend to use it on linux (Zip format is for wussies :) )

Ok, so you have the download in your home folder ........ (/home/ folder , where is whatever name you are using to log in.) all ready to be untarred

You will need root privilege to install so issue this command at prompt

$su - root you will be asked for root password , so give that and you are in

Navigate to the home folder where the net snmp tar.gz is kept
Issue this command at the prompt

#tar -zxvf net-snmp-5.5.tar.gz (I happen to be using version 5.5)

It will untar the whole thing and give you a directory like so

# ll
total 5408
drwxr-xr-x 19 274 500 4096 Mar 6 13:57 net-snmp-5.5
-rw-r--r-- 1 root root 5531055 Mar 3 23:21 net-snmp-5.5.tar.gz
#


Navigate into the net-snmp-5.5 directory and you should see something like so




Just have a look at the various README's etc. Or take a break.....or watch TV :) ....Till you are ready to go cracking again.......

The steps you need to do now are
1) Run ./configure
(type "./configure --help" for a quick usage summary.)
(--prefix=PATH will change the default /usr/local installation path.)

2) Optionally edit include/net-snmp/net-snmp-config.h
(due to prompting done by the configure script, this is very rarely
necessary.)

3) make

4) make test (This usually tells you right away whether everything on
the system is good to go or not)

5) make install


Ok......it will take some time....print what its doing all the while..... and then its done

You now have netsnmp installed and ready to use.

Ha Ha .....not quite.......theres still a lot of stuff that needs to be done before we can say .....yup....thats working beautifully.......

Navigate to

1. See if
/usr/local/share/bin folder has a bunch of snmp stuff like snmpconf snmptranslate and so on
2. See if the
/usr/local/share/snmp/mibs folder and see if all the MIB files are present

Now you have to
try some configurations checking

First, give
#net-snmp-config --default-mibdirs


/root/.snmp/mibs:/usr/local/share/snmp/mibs
You should get the reply like so....a list of the directories which are used to pick up snmp MIB data

Now run
linux-725y:/usr/local # net-snmp-config --snmpconfpath

/usr/local/etc/snmp:/usr/local/share/snmp:/usr/local/lib/snmp:/root/.snmp:/var/net-snmp
You should get the reply like so....a list of the paths which are used to pick up snmp configuration data

Now run

# ldd /usr/local/bin/snmptranslate
linux-gate.so.1 => (0x00110000)
libnetsnmpagent.so.15 => not found
libnetsnmphelpers.so.15 => not found
libnetsnmpmibs.so.15 => not found
libnetsnmp.so.15 => not found

This means that you might get snmp*: error while loading shared libraries:
like for example as mentioned above libnetsnmp.so.20: It cannot open shared object file

If no error comes like above , no need to do anything, but if error comes, then, you have to do the steps below
Edit ld.so.conf in /etc and add the details of the lib path of /usr/local/lib and then run ldconfig
#vi /etc/ld.so.conf

/usr/X11R6/lib/Xaw3d
/usr/X11R6/lib
/usr/lib/Xaw3d
/usr/i386-suse-linux/lib
/usr/local/lib
/opt/kde3/lib
include /etc/ld.so.conf.d/*.conf

#ldconfig

Now you have to tell netsnmp where to look for MIB files. You use the snmpconf command to do this. Issue this command at the prompt
# snmpconf

I can create the following types of configuration files for you.
Select the file type you wish to create:
(you can create more than one as you run this program)

1: snmpd.conf
2: snmptrapd.conf
3: snmp.conf

Other options: quit

Select File: 3

The configuration information which can be put into snmp.conf is divided
into sections. Select a configuration section for snmp.conf
that you wish to create:

1: Debugging output options
2: Textual mib parsing
3: Output style options
4: Default Authentication Options

Other options: finished

Select section: finished

I can create the following types of configuration files for you.
Select the file type you wish to create:
(you can create more than one as you run this program)

1: snmpd.conf
2: snmptrapd.conf
3: snmp.conf

Other options: quit

Select File: quit


The following files were created:

snmp.conf

These files should be moved to /usr/local/share/snmp if you
want them used by everyone on the system. In the future, if you add
the -i option to the command line I'll copy them there automatically for you.

Or, if you want them for your personal use only, copy them to
/root/.snmp . In the future, if you add the -p option to the
command line I'll copy them there automatically for you.

#cp snmp.conf /usr/local/share/snmp/

Finally try this
# snmptranslate -Tp -IR ipMIB
+--ipMIB(48)
|
+--ipMIBConformance(2)
|
+--ipMIBCompliances(1)
| |
| +--ipMIBCompliance(1)
| +--ipMIBCompliance2(2)
|
+--ipMIBGroups(2)
|
+--ipGroup(1)
+--icmpGroup(2)
+--ipv4GeneralGroup(3)
+--ipv4IfGroup(4)
+--ipv6GeneralGroup2(5)
+--ipv6IfGroup(6)
+--ipLastChangeGroup(7)
+--ipSystemStatsGroup(8)
+--ipv4SystemStatsGroup(9)
+--ipSystemStatsHCOctetGroup(10)
+--ipSystemStatsHCPacketGroup(11)
+--ipv4SystemStatsHCPacketGroup(12)
+--ipIfStatsGroup(13)
+--ipv4IfStatsGroup(14)
+--ipIfStatsHCOctetGroup(15)
+--ipIfStatsHCPacketGroup(16)
+--ipv4IfStatsHCPacketGroup(17)
+--ipAddressPrefixGroup(18)
+--ipAddressGroup(19)
+--ipNetToPhysicalGroup(20)
+--ipv6ScopeGroup(21)
+--ipDefaultRouterGroup(22)
+--ipv6RouterAdvertGroup(23)
+--icmpStatsGroup(24)
linux-725y:/usr/local #

This means that everything that you have installed is working

So now the errors are not going to be there because of configuration ......whatever gets screwed up , it will be because of your responsibilty :)

Next part will deal with How to write a MIB and add code from the agent.