Pages: [1] 2 3   Go Down
Author Topic: Agentuino - A lightweight SNMP Agent  (Read 4530 times)
0 Members and 1 Guest are viewing this topic.
Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A project was started (http://code.google.com/p/agentuino/).

Code will be uploaded soon (need to get SVN working on my linux box).  Code licensing will be under GPLv2.

Please let me know if you would like to assist.

Here is a quick snippet on the implementation concept.

Code:
/*
Copyright 2010 Eric C. Gionet <lavco_eg@hotmail.com>
// ******************************************************
// implementation concept
// ******************************************************
static byte ip[] = { 192, 168, 2, 64 };
static byte gateway[] = { 192, 168, 2, 1 };
static byte subnet[] = { 255, 255, 255, 0 };

// SNMP Agent - basic credentials
char getCommName[] PROGMEM   = "public";
char setCommName[] PROGMEM   = "private";
//
// RFC1213-MIB OIDs
char sysDescr[] PROGMEM        = "1.3.6.1.2.1.1.1.0";  // read-only  (DisplayString)
char sysObjectID[] PROGMEM   = "1.3.6.1.2.1.1.2.0";  // read-only  (ObjectIdentifier)
char sysUpTime[] PROGMEM     = "1.3.6.1.2.1.1.3.0";  // read-only  (TimeTicks)
char sysContact[] PROGMEM      = "1.3.6.1.2.1.1.4.0";  // read-write (DisplayString)
char sysName[] PROGMEM        = "1.3.6.1.2.1.1.5.0";  // read-write (DisplayString)
char sysLocation[] PROGMEM     = "1.3.6.1.2.1.1.6.0";  // read-write (DisplayString)
char sysServices[] PROGMEM    = "1.3.6.1.2.1.1.7.0";  // read-only  (Integer)
//
//
/* RFC1213 local values */
char locDescr[] PROGMEM      = "Agentuino, a light-weight SNMP Agent.";  // read-only (static)
char locObjectID[] PROGMEM   = "1.3.6.1.3.2009.0";                       // read-only (static)
long locUpTime                       = 0;                                        // RTC is needed for this unless the NTP Time library is used
char locContact[20]          = "Eric Gionet";
char locName[20]             = "Agentuino";
char locLocation[20]         = "Nova Scotia, CA";
short locServices PROGMEM    = 7;                                        // read-only (static)

Agentiuno agent = Agentuino();

SNMP_SESSION session;

pduReceived() {
      SNMP_PDU request;
      SNMP_PDU response;
      //
      agent.requestPdu(request);
      //
      // process request
      //
      agent.responsePdu(response);
      //
      agent.freePdu(request);
      agent.freePdu(response);
}

setup() {
      Ethernet.begin(mac, ip);
      //
      session.setCommName = getCommName;
      session.getCommName = setCommName;
      session.ip = ip;
      session.port = 161;
      //
      agent.initSession(session);
      agent.onPduReceive(pduReceived);
}

loop() {
      agent.listen();
}

Cheers,

Eric
« Last Edit: August 26, 2010, 11:03:02 pm by LAVco » Logged

Common sense is not so common...

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Count me in.
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 125
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would be willing to help also.
Logged

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

The library is still in alpha stages and very close to getting a response packet out.  The initial development sketch was ported to a library.  Library was sent to John D. and hopefully he will have to time to upload it while I am away.

For those who are interested here is the sketch sample on usage implementation to date.

Code:
/**
* Agentuino SNMP Agent Library Prototyping...
*
* Copyright 2010 Eric C. Gionet <lavco_eg@hotmail.com>
*
*/
#include <Streaming.h>         // Include the Streaming library
#include <Ethernet.h>          // Include the Ethernet library
#include <MemoryFree.h>
#include <Agentuino.h>
//
static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
static byte ip[] = { 192, 168, 2, 64 };
static byte gateway[] = { 192, 168, 2, 1 };
static byte subnet[] = { 255, 255, 255, 0 };
//
//
// RFC1213-MIB OIDs
static char sysDescr[] PROGMEM      = "1.3.6.1.2.1.1.1.0";  // read-only  (DisplayString)
static char sysObjectID[] PROGMEM   = "1.3.6.1.2.1.1.2.0";  // read-only  (ObjectIdentifier)
static char sysUpTime[] PROGMEM     = "1.3.6.1.2.1.1.3.0";  // read-only  (TimeTicks)
static char sysContact[] PROGMEM    = "1.3.6.1.2.1.1.4.0";  // read-write (DisplayString)
static char sysName[] PROGMEM       = "1.3.6.1.2.1.1.5.0";  // read-write (DisplayString)
static char sysLocation[] PROGMEM   = "1.3.6.1.2.1.1.6.0";  // read-write (DisplayString)
static char sysServices[] PROGMEM   = "1.3.6.1.2.1.1.7.0";  // read-only  (Integer)
//
//
/* RFC1213 local values */
static char locDescr[] PROGMEM      = "Agentuino, a light-weight SNMP Agent.";  // read-only (static)
static char locObjectID[] PROGMEM   = "1.3.6.1.3.2009.0";                       // read-only (static)
static long locUpTime               = 0;                                        // RTC is needed for this unless the NTP Time library is used
static char locContact[20]          = "Eric Gionet";
static char locName[20]             = "Agentuino";
static char locLocation[20]         = "Nova Scotia, CA";
static short locServices PROGMEM    = 7;                                        // read-only (static)

Agentuino agent = Agentuino();

SNMP_SESSION session;


void pduReceived()
{
  char oidString[SNMP_MAX_OID_LEN];
  SNMP_PDU pdu;
  //
  Serial << "UDP Packet Received Start.." << " RAM:" << freeMemory() << endl;
  //
  agent.requestPdu(&pdu);
  //
  pdu.OID.toString(oidString);
  //
  Serial << "OID: " << oidString << endl;
  //
  if ( pdu.type == SNMP_PDU_GET || pdu.type == SNMP_PDU_GET_NEXT ) {
    //
    if ( strcmp_P(oidString, sysName) == 0 ) {
      //
      // response packet - locName
      pdu.type = SNMP_PDU_RESPONSE;
      pdu.VALUE.encode(SNMP_SYNTAX_OCTETS, locName);
      //
      Serial << "sysName..." << locName << " " << pdu.VALUE.size << endl;
      //
      agent.responsePdu(&pdu);
    } else {
      // oid does not exist
      //
      // response packet - object not found
    }
  }
  //
  agent.freePdu(&pdu);
}

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  //
  session.getCommName = "public";
  session.setCommName = "private";
  session.port = 161;
  //
  agent.initSession(&session);
  agent.onPduReceive(pduReceived);
  //
  delay(10);
  //
  Serial.println("Initalized...");
}

void loop()
{
  agent.listen();
}

Cheers,

Eric
« Last Edit: August 28, 2010, 09:48:32 pm by LAVco » Logged

Common sense is not so common...

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It works!  Figured out the response issue I was having (issue resided with sequence lengths).

sysName get-request responds with "Agentuino".   I've tested it with iReasoning in Windows and NET-SNMP in Linux using SNMP-V1.

Need to work on a memory issue now as it stops responding after 2-3 concurrent requests.

Cheers,

Eric G.
« Last Edit: August 28, 2010, 09:33:44 pm by LAVco » Logged

Common sense is not so common...

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

Code was uploaded by John D.  The initial code is synchronous and there is still a memory issue.

Feedback on the potential memory problem would be great.

UPDATE
Figured out the problem, silly rabbit, I wasn't treating it like a server (duh) and releasing client connections/sockets once their task was completed.  Working on an update to resolve the problem.

Cheers,

Eric
« Last Edit: August 29, 2010, 05:54:55 pm by LAVco » Logged

Common sense is not so common...

0
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've just committed Eric's latest changes, and his example sketch, to SVN.  The directory structure now mirrors that of an Arduino library and example.  I've also written some notes on getting the code to compile and run, and committed those to SVN.
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6371
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

BTW, GPLv2 isn't usually considered well-matched to libraries, especially for embedded systems.  You may want to make sure that it's not doing more than you want it to (ie; it makes anything that uses your library also need to be open source GPL2.)  LGPL2 is the usual alternative...
Logged

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks westfw.  I'll take look.
Logged

Common sense is not so common...

Offline Offline
Full Member
***
Karma: 0
Posts: 125
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I looked at the code, but I use the eth libs for the ENC28J60.  Alas they never wrote a 'ASocket' layer.  So that will need some work, when I get some more time.

Also thinking the base Agentuino is great, but there should be a generalized interface, as the users will want to add their own data OIDs and code for their purposes.
Logged

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ASocket was chosen for a few reasons so the older Ethernet librarry is not supported and wont be.

Quote
Also thinking the base Agentuino is great, but there should be a generalized interface, as the users will want to add their own data OIDs and code for their purposes

It's as generalized as it can get.  The code provided are basic examples and by virtue sysName etc are base system objects and these can be removed or new objects can be added.  I would suggest reading up SNMP agents and managers or clarify your comment.

Implementing an SNMP agent is not recommended for beginners.
« Last Edit: September 07, 2010, 09:27:21 pm by LAVco » Logged

Common sense is not so common...

Florida
Offline Offline
Newbie
*
Karma: 0
Posts: 32
It is what it is...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow - impressive!

I love being to query the system with a GET at any time. However, sometimes having the unit actually report in on its own is useful...

Any chance support for sending an SNMP trap will be added?

Thanks and keep up the great work!
Logged

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quick update...

Figured out the memory issue and it now works with multiple get-requests.  The issue found is somewhat concerning but perhaps someone may be able to shed some light on the subject of using malloc.  When malloc was used to dynamically size the packet buffer it would hang after 3-4 requests.  When the packet buffer is set to a static size it works fine.

The latest IDE (0019) has a udp library added by default based on bitwiseudp created some time ago, so this may be considered as well, based on the fact that this is what I am testing with now.

An update will be uploaded in a few days.  In the meantime the code.google page has been updated for those of you who are interested.

Quote
Any chance support for sending an SNMP trap will be added?

Charles, yes I agree that it would be some slick to have traps.  We need to finish up common ASN.1 type encoding first, testing them, work on set-requests, and then probe into traps.

Thanks

Eric
« Last Edit: September 13, 2010, 09:40:41 pm by LAVco » Logged

Common sense is not so common...

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Another update...

A Private Enterprise Number (PEN) was requested from iana http://pen.iana.org for the Arduino project.  Basically this allows users to implement their own objects under the following node; .iso.org.dod.internet.private.enterprises.arduino (.1.3.6.1.4.1.?????), ????? to be assigned once the application is processed and accepted.

example;
Code:
.iso.org.dod.internet.private.enterprises.arduino.wxAirTemp (oid: .1.3.6.1.4.1.?????.1.0)

Weather Object (abbreviation: wx)
wxAirTemp MIB definition;
   - SYNTAX: INTEGER
   - MAX: 1000
   - MIN: -1000
   - ERROR: 1001
   - DESCRIPTION: air temperature in 1/10 degree Celsius
A sample MIB file will be created once the PEN value is assigned.

Regards,

Eric
« Last Edit: September 13, 2010, 07:24:34 pm by LAVco » Logged

Common sense is not so common...

Nova Scotia, CA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
A world that runs on bits and bytes!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

We have a working library with example uploaded to the project page.

   1. Null (WIP)
   2. Boolean (WIP)
   3. Bits (WIP)
   4. Octet-String
   5. Object-Identifier (WIP)
   6. Integer and Integer32
   7. Counter and Counter64
   8. Gauge
   9. Time-Ticks
  10. IP-Address (WIP)
  11. Opaque (WIP)
  12. Network-Service-Access-Point (NSAP) Address (WIP)

WIP = Work In Progress.

Cheers,

Eric
Logged

Common sense is not so common...

Pages: [1] 2 3   Go Up
Jump to: