ADC Home > Reference Library > Technical Notes > Legacy Documents > Mac OS 9 & Earlier >

Legacy Documentclose button

Important: This document is part of the Legacy section of the ADC Reference Library. This information should not be used for new development.

Current information on this Reference Library topic can be found here:

SNMP Transports

CONTENTS

This Technical Note explains how to write an SNMP (Simple Network Management Protocol) Transport. An SNMP Transport is responsible for communicating between the SNMP Manager and a particular network layer. Thus, if you were writing a new network stack for the Macintosh and wanted it to use the SNMP Manager, you would write an SNMP Transport for your network stack.

[Jun 01 1993]






Introduction

It is assumed in this document that you understand MacSNMP, object-oriented programming and the Shared Library Manager. The SNMP Manager is built using the Shared Library Manager and is a set of shared libraries. The SNMP Manager shared library contains the implementation of the base class for an SNMP Transport. Your transport must be a subclass of this SNMP Transport class. For more information on MacSNMP and the Shared Library Manager see the E.T.O. CD ROM.

This Technote provides some additional information needed to construct an SNMP Transport for a particular network stack. An SNMP Transport is required to know about all of the specific idiosyncrasies of SNMP for a particular network stack. SNMP was originally defined to run over the TCP stack using UDP. The IETF (Internet Engineering Task Force) has also defined how to run SNMP over three other network stacks: AppleTalk, IPX, and OSI. These methods are documented by the IETF proposed standards: RFC 1419--SNMP over AppleTalk, RFC 1420--SNMP over IPX, and RFC 1418--SNMP over OSI. There is also an informational RFC draft that describes what must be defined to allow SNMP to run over any particular network stack.

Apple provides SNMP transports that support the TCP stack and the AppleTalk stack. The TCP SNMP Transport provides knowledge of IP addresses, listens on the well-known SNMP sockets, sends SNMP packets on UDP, and resolves addresses in dotted notation into IP addresses for sending Traps. (An SNMP Trap is the method that SNMP entities use to send unsolicited warning messages to each other and should not be confused with a Macintosh Operating System Trap.) The AppleTalk SNMP Transport likewise provides knowledge of AppleTalk addresses, listens on the well-known SNMP sockets, sends SNMP packets on DDP, and resolves NBP (Name Binding Protocol) names into AppleTalk addresses for sending Traps. Similarly, a new SNMP Transport would have to provide these same services: understanding the new network addresses, listening for SNMP packets, sending SNMP packets, and resolving stored console addresses to network addresses for sending Traps.

Back to top

SNMP Transports

Figure 1. An SNMP Transport provides the
interface between the SNMP Manager and a particular network stack.

Figure 1. An SNMP Transport provides the interface between the SNMP Manager and a particular network stack.

Creating an SNMP Transport

The file Transport.h defines the SNMP Transport class. To create an SNMP Transport, you must subclass the SNMP Transport class. The Shared Library Manager allows a run-time link of your SNMP Transport subclass with the base object SNMP Transport provided in the SNMP Manager shared library. The definition of the SNMP Transport object is as follows:

/**********************************************************************
** Class TSNMPTransport
***********************************************************************/
#define kTSNMPTransportID     "snmp:mgr$TSNMPTrans"
#define kLIB_TransID      "snmp:trans$"    // Library ID for an SNMP Transport

class TSNMPTransport : public TDynamic
{
public:

                TSNMPTransport();
    virtual        ~TSNMPTransport();
    virtual Boolean    IsValid() const;        // returns valid or not
    virtual OSErr     InitSNMPTransport(
        TransportTag        aTag,
        TIAddressPtr        aTrapSocketPtr,
        TIAddressPtr        aReqSocketPtr,
        Boolean        ahandlesresolution,
        short            aWritebufsize,
        TransportRWProcPtr    aWriteProcPtr,
        short            aNumofReads,
        short            aReadTIAddrSRCmax,
        short            aReadTIAddrDESTmax,
        short            aReadbufsize,
        TransportRWProcPtr    aReadProcPtr);

    virtual void        SNMPWriteDone(SNMPTransportBlockPtr snmpPtr);
    virtual void        SNMPReadDone(SNMPTransportBlockPtr snmpPtr);

    TSNMPManagerPrv*    fSNMPManagerPtr;

friend TSNMPManagerPrv;

protected:
        Boolean    fValid;
        Boolean    fhandlesresolution;
        short        fNumofReads;
        short        fReadTIAddrSRCmax;
        short        fReadTIAddrDESTmax;
        short        fReadbufsize;
        short        fWritebufsize;

private:

        TransportTag        fTag;
        TIAddressPtr        fTrapSocketPtr;
        TIAddressPtr        fReqSocketPtr;
        TransportRWProcPtr    fWriteProcPtr;
        TransportRWProcPtr    fReadProcPtr;

To start an SNMP Transport you must instantiate it. For the AppleTalk SNMP Transport, we install a process on the AppleTalk transition queue that tells us when AppleTalk is coming up or going down and instantiate or destroy the Transport as appropriate. For the TCP SNMP Transport, an INIT31 instantiates the Transport and it is never destroyed. For your Transport you must provide the code that instantiates and destroys your Transport.

When a Transport is instantiated the base class constructor is called first. The base class constructor fills in the fSNMPManagerPtr field with a pointer to a class TSNMPManagerPrv, which can be cast to a pointer to the class TSNMPManager defined in TSNMP.h. This pointer can be used to access the members of the TSNMPManager class. The constructor also adds a pointer to your SNMP Transport object to a queue of transports so that it can find you later, and if everything worked, sets the fValid field to true. Your constructor is then called. If the fValid field is not set to true on the entrance to your constructor, you should bail out of the constructor immediately. If your constructor fails for some reason, you should set the fValid field to false. The Shared Library Manager will then clean up the object so that a partially constructed one does not remain.

Initializing an SNMP Transport

After your Transport is constructed it must be initialized. Your transport will not work until InitSNMPTransport() is called. This routine sets all of the fields in the SNMP Transport from the parameter values that you pass in. You must call the inherited InitSNMPTransport member function if you override it. The following fields must be set.

->    TransportTag        aTag
A long that uniquely identifies a transport (analogous to OSType)
->    TIAddressPtr        aTrapSocketPtr
Opaque address of where the Transport listens for Traps
->    TIAddressPtr        aReqSocketPtr
Opaque address of where the Transport listens for Requests
->    Boolean            ahandlesresolution
True if the transport can send Traps
->    short            aWritebufsize
Maximum size of write buffers
->    TransportRWProcPtr        aWriteProcPtr
Address of the write procedure
->    short            aNumofReads
Maximum number of reads issued at once
->    short            aReadTIAddrSRCmax
Maximum length of source address for read operations
->    short            aReadTIAddrDESTmax
Maximum length of destination address for read operations
->    short            aReadbufsize
Maximum size of a read buffer
->    TransportRWProcPtr        aReadProcPtr

It is recommended that the TransportTag be four human readable ASCII characters that describe the network layer that the Transport talks to. If multiple Transports with the same TransportTag are instantiated, the SNMP Manager will ignore all but the first one instantiated. For the AppleTalk SNMP Transport the tag is 'DDP ', for the TCP SNMP Transport the tag is 'UDP '. This value is used in the Trap Table in the Macintosh Agent to determine which Transport understands the console address stored in a particular row of the table. The sockets are where the Transport listens for Traps and Requests. The SNMP Manager does not understand the format of these addresses and just passes them along to your Transport. They are also used as the source of Traps or Responses sent. Finally, they allow the SNMP Manager to determine what type of packet it is decoding before parsing the raw ASN.1 data. In our Transports we have stored pointers to the actual bits of the network layer addresses in these fields. The aWritebufsize and aReadbufsize are the size of buffers that the SNMP Manager allocates for your Transport to use.

Reading SNMP Packets

Finally, InitSNMPTransport() tries to issue aNumofReads outstanding reads by calling your aReadProc() with a filled in SNMPTransportBlock as shown in Figure 2. The SNMPTransportBlock is defined as follows:

struct SNMPTransportBlock {
    unsigned long        qLink;        // reserved for pointer to next block
    short            qType;        // reserved for queue routines
    TSNMPTransport*     transport;    // who was asked to read or write block
    SNMPError        result;    // after request is serviced
    void*             destopaqueData;// destination address to be resolved
                                     // (used in write trap only)
    TIAddressPtr        destination;    // who the packet was sent to
    TIAddressPtr        source;    // who sent the packet to us
    void *            UserDataPtr;    // Transport work space
    Boolean        freeFlag;    // is the write finished?
    Boolean        readFlag;    // managed by SNMP Manager
    PacketElementPtr    pktelementPtr;// managed by SNMP Manager
    SNMPPacketStructPtr    packetPtr;    // managed by SNMP Manager

The aReadProc() must be able to catch both incoming Traps and Requests. It must also be able to be called at any time, thus you must not allocate memory using the normal Macintosh memory calls. You may use the area pointed to by UserDataPtr for any scratch you might need. The SNMP Manager has preallocated this area for you according to the sizes you set in aReadbufsize. It must also return immediately. When a read actually completes you must call SNMPReadDone() after filling in the data, the source and destination addresses, the actual number of bytes read (in packetPtr->packetPiece.dataSize), the freeFlag (set to false), and the result (snmpNoError if it worked.)


Warning:
If the freeFlag is incorrectly set, the SNMP Manager will become hopelessly confused.


After the read packet is processed by the SNMP Manager it issues another read call to aReadProc() so that there will always be some number of outstanding reads. If there are no outstanding reads at any time it is allowable for your transport to drop SNMP packets.

Figure 2. Layout of SNMPTransportBlock when 
aReadProc() called. Only the fields that the Transport may need to access are shown.

Figure 2. Layout of SNMPTransportBlock when aReadProc() called. Only the fields that the Transport may need to access are shown.

When your Transport is deleted you must ensure that your completion routines will not be called after your destructor is finished and your Transport object is gone. You may have to wait for asynchronous writes to complete and cancel any outstanding reads. The base class destructor will ensure that any packets you have queued up for processing will be thrown away.

Figure 3. Layout of SNMPTransportBlock 
when the SNMP Manager calls aWriteProc() with a response to an SNMP Request.

Figure 3. Layout of SNMPTransportBlock when the SNMP Manager calls aWriteProc() with a response to an SNMP Request. *
* Only the fields that the Transport may need to access are shown.

Writing SNMP Packets

After a packet is processed by the SNMP Manager, it will almost always generate a Response packet. The SNMP Manager will either respond to a Request or generate a Trap. In the cases of a simple Response the SNMP Manager will call your aWriteProc() with an SNMPTransportBlock filled out as shown in Figure 3. Your aWriteProc() may be called at any time, thus you must not allocate memory using the normal Macintosh memory calls. You may use the area pointed to by UserDatPtr for any scratch memory you need. The SNMP Manager has preallocated this area for you according to the sizes you set in aWritebufsize. The destination socket is the same block as was passed in on the read as the source socket, the source socket is your initialized fRequestSocketPtr, the packetPtr points to the SNMP data to put on the wire. You must return immediately from the call to aWriteProc(). After the write completes you should fill in the result, set the freeFlag to true, and call SNMPWriteDone() so that the SNMP Manager can free up the memory it allocated.


Warning:
If the freeFlag is incorrectly set the SNMP Manager will become hopelessly confused.


If your Transport can send Traps it must set the fHandlesResolution field to true. It is strongly encouraged that your transport handle Traps, if it did not, it would not be fully compliant with the SNMP standard. When a Trap is generated, the SNMP Manager will determine if the Trap is supposed to be sent to a console that supports your Transport type by looking through the Trap table in the Macintosh System MIB implemented by the Macintosh Agent. If so, it will issue a call to your aWriteProc() as above, except that the destOpaqueData will point to a block that the SNMP Manager has procured from the trapDestination field in the Trap Table in the Macintosh Agent. It is up to you to define how this address will be stored. However, it must be nonvolatile between reboots of the system. For the AppleTalk SNMP transport, we store the NBP name of the console as specified in the AppleTalk over SNMP RFC. For the TCP SNMP Transport, we store the IP address of the console in dotted notation The Transport is responsible for turning this address into the wire address of the console. Everything else is as above. You must return immediately after the call to your aWriteProc() and call SNMPWriteDone() when the Trap write completes.

The Trap Table is implemented by the Macintosh Agent and is defined in ASN.1 by the Macintosh System MIB as:

TrapRequestEntry     ::= SEQUENCE {
trapIndex        INTEGER,            // unsigned long
trapCommunity        MacintoshDisplayString,    // opaque data
trapProtocol        MacOSType,            // four bytes
trapDestination    OCTET STRING,            // opaque data
trapValidity        INTEGER            // 1 = valid, 2 = invalid

The two fields that an SNMP Transport author must define are the trapProtocol and the trapDestination. The trapProtocol is compared by the SNMP Manager to the TransportTag and is used to identify which SNMP Transport will be able to resolve the trapDestination entry and send the Trap. The trapProtocol field must contain the same value that was initialized in the transportTag field. Some care should be given to the format of the trapDestination as network managers will have to enter these addresses by hand from a console.

Back to top

Summary

An SNMP Transport provides an interface between the SNMP Manager and a network layer of a particular network stack. It must be able to be called at any time, thus cannot depend on the Macintosh memory calls. A Transport must understand how a Trap destination (console address) is to be stored in the Macintosh Agent's Trap Table. This address format must be stable between reboots of the system and must be resolvable into a network address for the console. It is the responsibility of the Transport developer to inform network managers of how to store this address. For IPX, AppleTalk, and OSI, these standards have been specified in RFCs (Request For Comments). These documents are available on-line off of the Internet and are maintained in various repositories and formats by the IETF.

Back to top

References

MacSNMP Programmer's Guide

Shared Library Manager Programmer's Guide

RFC 1157, A Simple Network Management Protocol (SNMP)

RFC 1155, Structure and Identification of Management Information for TCP/IP-based Internets

RFC 1419, SNMP over AppleTalk, Internet Proposed Standard

Macintosh System MIB

Back to top

Downloadables

Acrobat gif

Acrobat version of this Note (312K)

Download


Back to top


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.