Annotation of 43BSDReno/contrib/isode-beta/doc/rfcs/smux-api.txt, revision 1.1

1.1     ! root        1: 
        !             2: 
        !             3: 
        !             4: 
        !             5:           draft            Exporting MIBs for BSD UNIX          May 1990
        !             6: 
        !             7: 
        !             8:                             How to export a MIB module
        !             9:                               from a BSD UNIX daemon
        !            10:                           using the 4BSD/ISODE SMUX API
        !            11: 
        !            12:                              Sun May 13 14:54:13 1990
        !            13: 
        !            14: 
        !            15:                                  Marshall T. Rose
        !            16: 
        !            17:                      Performance Systems International, Inc.
        !            18:                             11800 Sunrise Valley Drive
        !            19:                                     Suite 1100
        !            20:                                 Reston, VA  22091
        !            21: 
        !            22:                                   [email protected]
        !            23: 
        !            24: 
        !            25: 
        !            26: 
        !            27: 
        !            28: 
        !            29:           1.  Status of this Memo
        !            30: 
        !            31:           This document defines an API for UNIX daemons wishing to
        !            32:           implement a MIB module on a BSD UNIX system using the
        !            33:           4BSD/ISODE SNMP software.  This is a local mechanism.
        !            34: 
        !            35: 
        !            36: 
        !            37: 
        !            38: 
        !            39: 
        !            40: 
        !            41: 
        !            42: 
        !            43: 
        !            44: 
        !            45: 
        !            46: 
        !            47: 
        !            48: 
        !            49: 
        !            50: 
        !            51: 
        !            52: 
        !            53: 
        !            54: 
        !            55: 
        !            56: 
        !            57: 
        !            58:           M.T. Rose                                             [Page 1]
        !            59: 
        !            60: 
        !            61: 
        !            62: 
        !            63: 
        !            64:           draft            Exporting MIBs for BSD UNIX          May 1990
        !            65: 
        !            66: 
        !            67:           2.  The Environment
        !            68: 
        !            69:           This document gives an overview of how one modifies a UNIX
        !            70:           program to export a MIB module to the local SNMP agent.
        !            71: 
        !            72:           All of the files necessary to interface to the SNMP agent is
        !            73:           contained in the ISODE source tree, in the snmp/ directory.
        !            74:           Since this document avoids giving the actual C procedural
        !            75:           definitions, you should familiarize yourself with the lint
        !            76:           library, llib-lisnmp.
        !            77: 
        !            78:           For the purposes of example, throughout this document we will
        !            79:           reference a simple UNIX daemon, unixd, which implements a MIB
        !            80:           module for "mbuf statistics".
        !            81: 
        !            82: 
        !            83:           2.1.  The ISODE
        !            84: 
        !            85:           As you might have guessed, this document assumes that you're
        !            86:           running the ISODE on your system.  You should read the READ-ME
        !            87:           file at the base of the source tree for instructions on how to
        !            88:           configure, generate, and install the ISODE.  In the future, an
        !            89:           abbreviated set of instructions, for those interested in
        !            90:           running the only 4BSD/ISODE SNMP software, will be written.
        !            91: 
        !            92:           For now, follow the READ-ME, generate the base system and
        !            93:           SNMP, e.g.,
        !            94: 
        !            95:                % ./make all all-snmp
        !            96: 
        !            97:           and then install only the 4BSD/ISODE SNMP software:
        !            98: 
        !            99:                # ./make inst-all inst-snmp
        !           100: 
        !           101:           However, be sure to read the entire READ-ME file, as there are
        !           102:           other steps involved in installing the SNMP software.
        !           103: 
        !           104: 
        !           105: 
        !           106: 
        !           107: 
        !           108: 
        !           109: 
        !           110: 
        !           111: 
        !           112: 
        !           113: 
        !           114: 
        !           115: 
        !           116: 
        !           117:           M.T. Rose                                             [Page 2]
        !           118: 
        !           119: 
        !           120: 
        !           121: 
        !           122: 
        !           123:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           124: 
        !           125: 
        !           126:           3.  MIB Modules
        !           127: 
        !           128:           The first thing you need to do is to define the actual managed
        !           129:           objects which your program will implement.  This is done by
        !           130:           writing a "MIB module".  The syntax of the module is defined
        !           131:           in the Internet-standard SMI, RFC1155.  It is not the purpose
        !           132:           of this document to describe the rules used for writing a MIB
        !           133:           module.  However, here are the basics to speed you on your
        !           134:           way.
        !           135: 
        !           136:           The MIB module is defined in a file called module.my, e.g.,
        !           137:           unix.my.  In general, there are three kinds of MIB modules:
        !           138: 
        !           139:           (1)  If you are defining a MIB module for something UNIX
        !           140:                specific, it should probably go under the BSD UNIX MIB
        !           141:                (contact Marshall Rose or Keith Sklower to get a number
        !           142:                under the UNIX enterprise tree).  In this case, the
        !           143:                definition might start something like this:
        !           144: 
        !           145:                     SendMail-MIB { iso org(3) dod(6) internet(1) private(4)
        !           146:                                    enterprises(1) unix (4) sendmail (99) }
        !           147: 
        !           148:                     DEFINITIONS ::= BEGIN
        !           149: 
        !           150:                     IMPORTS
        !           151:                             unix --*, OBJECT-TYPE *--
        !           152:                                 FROM RFC1155-SMI;
        !           153: 
        !           154:                     sendMail OBJECT IDENTIFIER ::= { unix 99 }
        !           155: 
        !           156: 
        !           157:           (2)  If you are defining a MIB module on a multilateral,
        !           158:                experimental basis, e.g., for a protocol like the NTP,
        !           159:                then you should contact the Internet Assigned Numbers
        !           160:                Authority ([email protected]) and ask for an experimental
        !           161:                number.  In this case, the definition might start
        !           162:                something like this:
        !           163: 
        !           164:                     FIZBIN-MIB DEFINITIONS ::= BEGIN
        !           165: 
        !           166:                     IMPORTS
        !           167:                             experimental, OBJECT-TYPE
        !           168:                                 FROM RFC1155-SMI;
        !           169: 
        !           170:                     fizBin OBJECT IDENTIFIER ::= { experimental 99 }
        !           171: 
        !           172: 
        !           173: 
        !           174: 
        !           175: 
        !           176:           M.T. Rose                                             [Page 3]
        !           177: 
        !           178: 
        !           179: 
        !           180: 
        !           181: 
        !           182:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           183: 
        !           184: 
        !           185:           (3)  Otherwise, if you are defining a MIB module for something
        !           186:                specific to your enterprise, then you contact the
        !           187:                Internet Assigned Numbers Authority ([email protected]) and
        !           188:                ask for an enterprise number (assuming you don't already
        !           189:                have one).  In this case, the definition might start
        !           190:                something like this:
        !           191: 
        !           192:                     FIZZBIN-MIB DEFINITIONS ::= BEGIN
        !           193: 
        !           194:                     IMPORTS
        !           195:                             enterprises, OBJECT-TYPE
        !           196:                                 FROM RFC1155-SMI;
        !           197: 
        !           198:                     cheetah OBJECT IDENTIFIER ::= { enterprises 9999 }
        !           199: 
        !           200:                     fizBin OBJECT IDENTIFIER ::= { cheetah 1 }
        !           201: 
        !           202: 
        !           203:           Regardless of the kind of MIB module, this last OBJECT
        !           204:           IDENTIFIER points to the root of the tree which your agent is
        !           205:           going to export.
        !           206: 
        !           207:           Following this start, you have the actual definitions of the
        !           208:           MIB objects, followed by
        !           209: 
        !           210:                END
        !           211: 
        !           212: 
        !           213: 
        !           214:           3.1.  Compiling MIB modules
        !           215: 
        !           216:           The next step is to compile the MIB module into a form that
        !           217:           your program can read.  This is done using the mosy program:
        !           218: 
        !           219:                % others/mosy/xmosy module.my
        !           220: 
        !           221:           which will create the file module.defs.  In most cases you
        !           222:           will need to prefix this file with definitions from the root
        !           223:           of the OBJECT IDENTIFIER tree, e.g.,
        !           224: 
        !           225:                % cat $(INCDIR)isode/snmp/smi.defs module.defs > daemon.defs
        !           226: 
        !           227:           where the daemon.defs file will be the one which you install
        !           228:           with your program binary.
        !           229: 
        !           230: 
        !           231: 
        !           232: 
        !           233: 
        !           234: 
        !           235:           M.T. Rose                                             [Page 4]
        !           236: 
        !           237: 
        !           238: 
        !           239: 
        !           240: 
        !           241:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           242: 
        !           243: 
        !           244:           3.1.1.  The Syntax of compiled MIB modules
        !           245: 
        !           246:           The syntax is pretty simple:
        !           247: 
        !           248:           (1)  Comments start with "--" or "#" at the beginning of a
        !           249:                line.
        !           250: 
        !           251:           (2)  Object identifiers are defined like this:
        !           252: 
        !           253:                     name            value
        !           254: 
        !           255:                e.g.,
        !           256: 
        !           257:                     internet        iso.3.6.1
        !           258: 
        !           259: 
        !           260:           (3)  Object types are defined like this:
        !           261: 
        !           262:                     name      oid       syntax         access     status
        !           263: 
        !           264:                e.g.,
        !           265: 
        !           266:                     sysDescr  system.1  DisplayString  read-only  mandatory
        !           267: 
        !           268:                where "name" and "oid" are fairly obvious.  For the rest:
        !           269: 
        !           270:                     "syntax" is the name of a defined syntax;
        !           271: 
        !           272:                     "access" is one of read-only, read-write", or none;
        !           273:                     and,
        !           274: 
        !           275:                     "status" is one of mandatory, optional,
        !           276:                     deprecated, or obsolete.
        !           277: 
        !           278:                Names of objects are always case-sensitive.
        !           279: 
        !           280: 
        !           281: 
        !           282: 
        !           283: 
        !           284: 
        !           285: 
        !           286: 
        !           287: 
        !           288: 
        !           289: 
        !           290: 
        !           291: 
        !           292: 
        !           293: 
        !           294:           M.T. Rose                                             [Page 5]
        !           295: 
        !           296: 
        !           297: 
        !           298: 
        !           299: 
        !           300:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           301: 
        !           302: 
        !           303:           4.  SMUX Peers
        !           304: 
        !           305:           A program which exports a MIB module is termed a "SMUX peer"
        !           306:           (SMUX is the name of the protocol used by these programs to
        !           307:           communicate with an SNMP agent.)
        !           308: 
        !           309:           There is a textual database, $(ETCDIR)snmpd.peers, which
        !           310:           defines the SMUX peers known to the local SNMP agent.  The
        !           311:           syntax of this file is pretty simple:
        !           312: 
        !           313:           (1)  Comments start with "#" at the beginning of a line.
        !           314: 
        !           315:           (2)  Each peer is identified in a single line:
        !           316: 
        !           317:                     name        oid         password    [priority]
        !           318: 
        !           319:                where "name" and "oid" are fairly obvious.  For the rest:
        !           320: 
        !           321:                     "password" is a string which the agent will use to
        !           322:                     authenticate the SMUX peer;
        !           323:                     and,
        !           324: 
        !           325:                     "priority",
        !           326:                     if present,
        !           327:                     is the highest priority with which the SMUX peer can register subtrees.
        !           328: 
        !           329:                The name/oid pairs are assigned by the authority for the
        !           330:                BSD UNIX MIB (contact Marshall Rose or Keith Sklower to
        !           331:                register the name of your program and get an for your
        !           332:                program).
        !           333: 
        !           334:           Note that this file contains things resembling passwords in
        !           335:           the clear.  As such, it should be protected mode 0600 and
        !           336:           owned by root.
        !           337: 
        !           338: 
        !           339: 
        !           340: 
        !           341: 
        !           342: 
        !           343: 
        !           344: 
        !           345: 
        !           346: 
        !           347: 
        !           348: 
        !           349: 
        !           350: 
        !           351: 
        !           352: 
        !           353:           M.T. Rose                                             [Page 6]
        !           354: 
        !           355: 
        !           356: 
        !           357: 
        !           358: 
        !           359:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           360: 
        !           361: 
        !           362:           5.  Daemon Skeleton
        !           363: 
        !           364:           Now it's time to modify your daemon to export the MIB.  Your
        !           365:           source code should include these lines:
        !           366: 
        !           367:                #include <isode/snmp/smux.h>
        !           368:                #include <isode/snmp/objects.h>
        !           369:                #include <isode/tailor.h>
        !           370: 
        !           371:           which will include the definitions for: talking to the SNMP
        !           372:           agent via the SMUX protocol, the object management package,
        !           373:           and the ISODE tailoring subsystem.
        !           374: 
        !           375:           When loading your daemon, you should add this to the end of
        !           376:           your command to the loader:
        !           377: 
        !           378:                -lisnmp -lisode
        !           379: 
        !           380:           which includes the 4BSD/SNMP and ISODE libraries.
        !           381: 
        !           382:           You should decide if you want to use the ISODE logging
        !           383:           subsystem.  This is a convenient mechanism for using a unified
        !           384:           logging system.  If you are modifying an already existing
        !           385:           daemon, you probably have your own logging package.
        !           386:           Otherwise, you should consider using the ISODE subsystem.
        !           387: 
        !           388: 
        !           389:           5.1.  Declarations
        !           390: 
        !           391:           There are some global variables that your program will have to
        !           392:           declare:
        !           393: 
        !           394:                int     debug = 0;
        !           395:                static  char   *myname = "unixd";
        !           396: 
        !           397:                static LLog     _pgm_log = {
        !           398:                    "unixd.log", NULLCP, NULLCP,
        !           399:                    LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE,
        !           400:                    LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK
        !           401:                };
        !           402:                static  LLog   *pgm_log = &_pgm_log;
        !           403: 
        !           404:                static  OID     subtree = NULLOID;
        !           405:                static  struct smuxEntry *se = NULL;
        !           406: 
        !           407: 
        !           408: 
        !           409: 
        !           410: 
        !           411: 
        !           412:           M.T. Rose                                             [Page 7]
        !           413: 
        !           414: 
        !           415: 
        !           416: 
        !           417: 
        !           418:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           419: 
        !           420: 
        !           421:                static  int     smux_fd = NOTOK;
        !           422:                static  int     rock_and_roll = 0;
        !           423:                static  int     dont_bother_anymore = 0;
        !           424: 
        !           425:                static  int     quantum = 0;
        !           426: 
        !           427:           You only need the definition of _pgm_log and pgm_log if you
        !           428:           will be using the ISODE logging subsystem.
        !           429: 
        !           430: 
        !           431:           5.2.  Initialization
        !           432: 
        !           433:           When your program initializes itself, it should contain some
        !           434:           code like this:
        !           435: 
        !           436:                    if (myname = rindex (argv[0], '/'))
        !           437:                        myname++;
        !           438:                    if (myname == NULL || *myname == NULL)
        !           439:                        myname = argv[0];
        !           440: 
        !           441:                    isodetailor (myname, 0);
        !           442:                    ll_hdinit (pgm_log, myname);
        !           443: 
        !           444:                /* scan argv, set debug if need be... */
        !           445: 
        !           446:                    if (debug)
        !           447:                        ll_dbinit (pgm_log, myname);
        !           448: 
        !           449:           Of course, if you're not using the ISODE logging subsystem,
        !           450:           you don't have the calls to ll_hdinit or ll_dbinit.
        !           451: 
        !           452:           After cracking argv, your program should do the usual
        !           453:           detaching actions.  Usually at this point, your program reads
        !           454:           the compiled MIB module definitions and starts talking to the
        !           455:           SNMP agent.
        !           456: 
        !           457: 
        !           458:           5.3.  Reading the compiled MIB module
        !           459: 
        !           460:           You program should call the readobjects routine to read the
        !           461:           module, look-up the subtree which it will export to the SNMP
        !           462:           agent, and call the getsmuxEntrybyname routine to find its
        !           463:           entry in the snmpd.peers database.  Finally, it should call a
        !           464:           routine you define, e.g., init_mib, to initialize it's
        !           465:           internal MIB structures.  (We'll look at this routine in
        !           466: 
        !           467: 
        !           468: 
        !           469: 
        !           470: 
        !           471:           M.T. Rose                                             [Page 8]
        !           472: 
        !           473: 
        !           474: 
        !           475: 
        !           476: 
        !           477:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           478: 
        !           479: 
        !           480:           greater detail later on.)
        !           481: 
        !           482:                    OT      ot;
        !           483: 
        !           484:                    if (readobjects ("unixd.defs") == NOTOK)
        !           485:                        error ("readobjects: %s", PY_pepy);
        !           486: 
        !           487:                    if ((ot = text2obj ("mbuf")) == NULL)
        !           488:                        error ("object
        !           489:                    subtree = ot -> ot_name;
        !           490: 
        !           491:                    if (se = getsmuxEntrybyname ("unixd")) == NULL)
        !           492:                        error ("no SMUX entry for
        !           493: 
        !           494:                    init_mib ();
        !           495: 
        !           496:           If any of these routines fail, then don't bother trying to
        !           497:           export the MIB module.
        !           498: 
        !           499: 
        !           500:           5.4.  Talking to the SNMP agent
        !           501: 
        !           502:           All of the SMUX routines return NOTOK on failure.  Unless
        !           503:           otherwise noted, these routines also return OK on success.  On
        !           504:           failure, the variable
        !           505: 
        !           506:                extern int  smux_errno;
        !           507: 
        !           508:           is set to a symbolic value defined in smux.h, one of:
        !           509: 
        !           510:                invalidOperation
        !           511:                parameterMissing
        !           512:                systemError
        !           513:                youLoseBig
        !           514:                congestion
        !           515:                inProgress
        !           516: 
        !           517:           In addition, the variable
        !           518: 
        !           519:                extern char smux_info[BUFSIZ];
        !           520: 
        !           521:           contains a printable explanation of what happened on failure.
        !           522: 
        !           523:           All errors are FATAL except for inProgress.  This means retry
        !           524:           your operation later on.
        !           525: 
        !           526: 
        !           527: 
        !           528: 
        !           529: 
        !           530:           M.T. Rose                                             [Page 9]
        !           531: 
        !           532: 
        !           533: 
        !           534: 
        !           535: 
        !           536:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           537: 
        !           538: 
        !           539:           5.4.1.  Initialization
        !           540: 
        !           541:           You program should call the routine smux_init, which
        !           542:           initializes a SMUX connection to the local SNMP agent.  This
        !           543:           starts a TCP connection, but most likely does not complete it.
        !           544:           You program will need to call an open routine (there is only
        !           545:           one at present) to finish the connect and establish the SMUX
        !           546:           association.
        !           547: 
        !           548:           If successful, the return value is a file-descriptor, suitable
        !           549:           for use with select, etc.
        !           550: 
        !           551:           On failure, smux_errno will be set to one of congestion,
        !           552:           youLoseBig, or systemError.  In this case, you should probably
        !           553:           have your program retry the operation every 5 minutes or so.
        !           554: 
        !           555:                if ((smux_fd = smux_init (debug)) == NOTOK)
        !           556:                    error ("smux_init: %s [%s]",
        !           557:                           smux_error (smux_errno), smux_info);
        !           558:                else
        !           559:                    rock_and_roll = 0;
        !           560: 
        !           561: 
        !           562: 
        !           563:           5.4.2.  Opening
        !           564: 
        !           565:           Once smux_init returns OK, you should start selecting for
        !           566:           writability on the file-descriptor returned.  Once select says
        !           567:           your program can write to the fd, your program should call the
        !           568:           routine smux_simple_open, which establishes the SMUX
        !           569:           association.
        !           570: 
        !           571:           On failure, smux_error will be set to one of parameterMissing,
        !           572:           invalidOperation, inProgress, systemError, congestion, or
        !           573:           youLoseBig.  If the error code is inProgress, then your
        !           574:           program should continue retrying the fd for writability, and
        !           575:           then call smux_simple_open again.  Otherwise, your program
        !           576:           should take the appropriate action based on the error code
        !           577:           returned.
        !           578: 
        !           579:                if (smux_simple_open (&se -> se_identity,
        !           580:                                      "SMUX UNIX daemon",
        !           581:                                      se -> se_password,
        !           582:                                      strlen (se -> se_password))
        !           583:                        == NOTOK) {
        !           584: 
        !           585: 
        !           586: 
        !           587: 
        !           588: 
        !           589:           M.T. Rose                                            [Page 10]
        !           590: 
        !           591: 
        !           592: 
        !           593: 
        !           594: 
        !           595:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           596: 
        !           597: 
        !           598:                    if (smux_errno == inProgress)
        !           599:                        return;
        !           600: 
        !           601:                    error ("smux_simple_open: %s [%s]",
        !           602:                           smux_error (smux_errno), smux_info);
        !           603:                    smux_fd = NOTOK;
        !           604:                }
        !           605:                else
        !           606:                    rock_and_roll = 1;
        !           607: 
        !           608: 
        !           609: 
        !           610:           5.4.3.  Closing
        !           611: 
        !           612:           If, for some reason, your program wishes to close the SMUX
        !           613:           association.  There are several reasons that are allowed:
        !           614: 
        !           615:                goingDown
        !           616:                unsupportedVersion
        !           617:                packetFormat
        !           618:                protocolError
        !           619:                internalError
        !           620:                authenticationFailure
        !           621: 
        !           622:           On failure, smux_error will be set to one of invalidOperation,
        !           623:           congestion, or youLoseBig.
        !           624: 
        !           625: 
        !           626:           5.4.4.  Registering Subtrees
        !           627: 
        !           628:           Once smux_simple_open returns OK, your program should register
        !           629:           the MIB module that your daemon will export by calling
        !           630:           smux_register.  A subtree can be registered in one of three
        !           631:           modes:
        !           632: 
        !           633:                readOnly
        !           634:                readWrite
        !           635:                delete
        !           636: 
        !           637:           which are all fairly obvious.
        !           638: 
        !           639:           Note that a return value of OK from smux_register means only
        !           640:           that the registration request was queued for the SNMP agent
        !           641:           via the SMUX protocol.  Some time later the SNMP agent's
        !           642:           response will be forthcoming.
        !           643: 
        !           644: 
        !           645: 
        !           646: 
        !           647: 
        !           648:           M.T. Rose                                            [Page 11]
        !           649: 
        !           650: 
        !           651: 
        !           652: 
        !           653: 
        !           654:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           655: 
        !           656: 
        !           657:           On failure, smux_error will be set to one of parameterMissing,
        !           658:           invalidOperation, congestion, or youLoseBig.  Your program
        !           659:           should take the appropriate action based on the error code
        !           660:           returned.
        !           661: 
        !           662:                if (smux_register (subtree, -1, readOnly) == NOTOK) {
        !           663:                    error ("smux_register: %s [%s]",
        !           664:                            smux_error (smux_errno), smux_info);
        !           665:                    smux_fd = NOTOK;
        !           666:                }
        !           667: 
        !           668: 
        !           669: 
        !           670:           5.4.5.  Main Loop
        !           671: 
        !           672:           At this point, your program is more or less in it's main loop
        !           673:           (actually, it probably entered the main loop after the very
        !           674:           first call to smux_init).
        !           675: 
        !           676:                int     nfds;   /* these are set for other fd's... */
        !           677: 
        !           678:                fd_set  ifds;
        !           679:                fd_set  ofds;
        !           680: 
        !           681:                    for (;;) {
        !           682:                        int     n,
        !           683:                                secs;
        !           684:                        fd_set  rfds,
        !           685:                                wfds;
        !           686: 
        !           687:                        secs = NOTOK;
        !           688: 
        !           689:                        rfds = ifds;    /* struct copy */
        !           690:                        wfds = ofds;    /*   .. */
        !           691: 
        !           692:                        if (smux_fd == NOTOK && !dont_bother_anymore)
        !           693:                            secs = 5 * 60L;
        !           694:                        else
        !           695:                            if (rock_and_roll)
        !           696:                                FD_SET (smux_fd, &rfds);
        !           697:                            else
        !           698:                                FD_SET (smux_fd, &wfds);
        !           699:                        if (smux_fd >= nfds)
        !           700:                            nfds = smux_fd + 1;
        !           701: 
        !           702: 
        !           703: 
        !           704: 
        !           705: 
        !           706: 
        !           707:           M.T. Rose                                            [Page 12]
        !           708: 
        !           709: 
        !           710: 
        !           711: 
        !           712: 
        !           713:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           714: 
        !           715: 
        !           716:                        if ((n = xselect (nfds, &rfds, &wfds, NULLFD, secs))
        !           717:                                == NOTOK) {
        !           718:                            error ("xselect failed");
        !           719:                             ...
        !           720:                        }
        !           721: 
        !           722:                /* check fd's for other purposes here... */
        !           723: 
        !           724:                        if (smux_fd == NOTOK && !dont_bother_anymore) {
        !           725:                            if (n == 0) {
        !           726:                                if ((smux_fd = smux_init (debug)) == NOTOK)
        !           727:                                    error ("smux_init: %s [%s]",
        !           728:                                           smux_error (smux_errno),
        !           729:                                           smux_info);
        !           730:                                else
        !           731:                                    rock_and_roll = 0;
        !           732:                            }
        !           733:                        }
        !           734:                        else
        !           735:                            if (rock_and_roll) {
        !           736:                                if (FD_ISSET (smux_fd, &rfds))
        !           737:                                    doit_smux ();
        !           738:                            }
        !           739:                            else
        !           740:                                if (FD_ISSET (smux_fd, &wfds)) {
        !           741:                                    if (smux_simple_open (&se -> se_identity,
        !           742:                                                  "SMUX UNIX daemon",
        !           743:                                                  se -> se_password,
        !           744:                                                  strlen (se -> se_password))
        !           745:                                            == NOTOK) {
        !           746:                                        if (smux_errno != inProgress) {
        !           747:                                            error ("smux_simple_open: %s [%s]",
        !           748:                                                   smux_error (smux_errno),
        !           749:                                                   smux_info);
        !           750:                                            smux_fd = NOTOK;
        !           751:                                        }
        !           752:                                    }
        !           753:                                    else {
        !           754:                                        rock_and_roll = 1;
        !           755: 
        !           756:                                        if (smux_register (subtree, -1,
        !           757:                                                    readOnly) == NOTOK) {
        !           758:                                            error ("smux_register: %s [%s]",
        !           759:                                                   smux_error (smux_errno),
        !           760:                                                   smux_info);
        !           761: 
        !           762: 
        !           763: 
        !           764: 
        !           765: 
        !           766:           M.T. Rose                                            [Page 13]
        !           767: 
        !           768: 
        !           769: 
        !           770: 
        !           771: 
        !           772:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           773: 
        !           774: 
        !           775:                                            smux_fd = NOTOK;
        !           776:                                        }
        !           777:                                }
        !           778:                    }
        !           779: 
        !           780:           So, all that remains is to take a look at the routine
        !           781:           doit_smux mentioned above.  This is called when select
        !           782:           indicates the SMUX file-descriptor is ready for reading.
        !           783: 
        !           784: 
        !           785:           5.4.6.  Events
        !           786: 
        !           787:           When select indicates the SMUX file-descriptor is ready for
        !           788:           reading, your program calls the routine smux_wait to return
        !           789:           the next event from the SNMP agent.
        !           790: 
        !           791:           Note that the event is filled-in from a static area.  On the
        !           792:           next call to smux_init, smux_close, or smux_wait, the value
        !           793:           will be overwritten.  As such, do not free this structure
        !           794:           yourself.
        !           795: 
        !           796:           On failure, smux_error will be set to one of parameterMissing,
        !           797:           invalidOperation, inProgress, or youLoseBig.  Your program
        !           798:           should take the appropriate action based on the error code
        !           799:           returned.
        !           800: 
        !           801:                    struct type_SNMP_SMUX__PDUs *event;
        !           802: 
        !           803:                    if (smux_wait (&event, NOTOK) == NOTOK) {
        !           804:                        if (smux_errno == inProgress)
        !           805:                            return;
        !           806: 
        !           807:                        error ("smux_wait: %s [%s]",
        !           808:                               smux_error (smux_errno), smux_info);
        !           809:                losing: ;
        !           810:                        smux_fd = NOTOK;
        !           811:                        return;
        !           812:                    }
        !           813: 
        !           814:           Next, your program should switch based on the actual event
        !           815:           returned:
        !           816: 
        !           817:                type_SNMP_SMUX__PDUs_registerResponse
        !           818:                type_SNMP_SMUX__PDUs_get_request
        !           819:                type_SNMP_SMUX__PDUs_get__next__request
        !           820: 
        !           821: 
        !           822: 
        !           823: 
        !           824: 
        !           825:           M.T. Rose                                            [Page 14]
        !           826: 
        !           827: 
        !           828: 
        !           829: 
        !           830: 
        !           831:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           832: 
        !           833: 
        !           834:                type_SNMP_SMUX__PDUs_close
        !           835: 
        !           836:           The actual code is fairly straight-forward:
        !           837: 
        !           838:                switch (event -> offset) {
        !           839:                    case type_SNMP_SMUX__PDUs_registerResponse:
        !           840:                        {
        !           841:                            struct type_SNMP_RRspPDU *rsp =
        !           842:                                        event -> un.registerResponse;
        !           843: 
        !           844:                            if (rsp -> parm == int_SNMP_RRspPDU_failure) {
        !           845:                                error ("SMUX registration of %s failed",
        !           846:                                       oid2ode (subtree));
        !           847:                                dont_bother_anymore = 1;
        !           848:                                (void) smux_close (goingDown);
        !           849:                                break;
        !           850:                            }
        !           851:                        }
        !           852:                        if (smux_trap (int_SNMP_generic__trap_coldStart,
        !           853:                                       0, (struct type_SNMP_VarBindList *) 0)
        !           854:                                == NOTOK) {
        !           855:                            error ("smux_trap: %s [%s]",
        !           856:                                   smux_error (smux_errno), smux_info);
        !           857:                            break;
        !           858:                        }
        !           859:                        return;
        !           860: 
        !           861:                    case type_SNMP_SMUX__PDUs_get_request:
        !           862:                    case type_SNMP_SMUX__PDUs_get__next__request:
        !           863:                        get_smux (event -> un.get__request, event -> offset);
        !           864:                        return;
        !           865: 
        !           866:                    case type_SNMP_SMUX__PDUs_close:
        !           867:                        notice ("SMUX close: %s",
        !           868:                                smux_error (event -> un.close -> parm));
        !           869:                        break;
        !           870: 
        !           871:                    default:
        !           872:                        error ("bad SMUX operation: %d", event -> offset);
        !           873:                        (void) smux_close (protocolError);
        !           874:                        break;
        !           875:                }
        !           876:                smux_fd = NOTOK;
        !           877: 
        !           878:           Note the use of the smux_trap routine to send a coldStart trap
        !           879: 
        !           880: 
        !           881: 
        !           882: 
        !           883: 
        !           884:           M.T. Rose                                            [Page 15]
        !           885: 
        !           886: 
        !           887: 
        !           888: 
        !           889: 
        !           890:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           891: 
        !           892: 
        !           893:           once the daemon has successful registered the MIB module it is
        !           894:           exporting.  The trap codes are:
        !           895: 
        !           896:                int_SNMP_generic__trap_coldStart
        !           897:                int_SNMP_generic__trap_warmStart
        !           898:                int_SNMP_generic__trap_linkDown
        !           899:                int_SNMP_generic__trap_linkUp
        !           900:                int_SNMP_generic__trap_authenticationFailure
        !           901:                int_SNMP_generic__trap_egpNeighborLoss
        !           902:                int_SNMP_generic__trap_enterpriseSpecific
        !           903: 
        !           904:           If this routine fails, smux_errno will be set to one of
        !           905:           invalidOperation, congestion, or youLoseBig.
        !           906: 
        !           907:           So, all that remains is to take a look at the routine get_smux
        !           908:           which implements the SNMP get and powerful get-next operators.
        !           909:           We will return to this routine once the structures and
        !           910:           routines which implement the managed object abstraction are
        !           911:           explained.
        !           912: 
        !           913: 
        !           914: 
        !           915: 
        !           916: 
        !           917: 
        !           918: 
        !           919: 
        !           920: 
        !           921: 
        !           922: 
        !           923: 
        !           924: 
        !           925: 
        !           926: 
        !           927: 
        !           928: 
        !           929: 
        !           930: 
        !           931: 
        !           932: 
        !           933: 
        !           934: 
        !           935: 
        !           936: 
        !           937: 
        !           938: 
        !           939: 
        !           940: 
        !           941: 
        !           942: 
        !           943:           M.T. Rose                                            [Page 16]
        !           944: 
        !           945: 
        !           946: 
        !           947: 
        !           948: 
        !           949:           draft            Exporting MIBs for BSD UNIX          May 1990
        !           950: 
        !           951: 
        !           952:           6.  Managed Objects
        !           953: 
        !           954:           A managed object is an abstraction with a syntax and a
        !           955:           semantics.  The syntax defines what instances of the object
        !           956:           look like on the network.  The semantics define what the
        !           957:           object actually is.
        !           958: 
        !           959: 
        !           960:           6.1.  Syntax
        !           961: 
        !           962:           The syntax of MIB objects is modeled by the OS structure:
        !           963: 
        !           964:                typedef struct object_syntax {
        !           965:                    char   *os_name;                    /* syntax name */
        !           966: 
        !           967:                    IFP     os_encode;                  /* data -> PE */
        !           968:                    IFP     os_decode;                  /* PE -> data */
        !           969:                    IFP     os_free;                    /* free data */
        !           970: 
        !           971:                    IFP     os_parse;                   /* str -> data */
        !           972:                    IFP     os_print;                   /* data -> tty */
        !           973: 
        !           974:                         ...
        !           975:                }               object_syntax, *OS;
        !           976:                #define NULLOS  ((OS) 0)
        !           977: 
        !           978:           The syntaxes defined by the Internet-standard MIB are already
        !           979:           implemented:
        !           980: 
        !           981:                syntax  structure
        !           982:                INTEGER integer
        !           983:                OctetString     struct qbuf (OCTET STRING)
        !           984:                ObjectID        struct OIDentifier (OBJECT IDENTIFIER)
        !           985:                NULL    char
        !           986:                DisplayString   struct qbuf
        !           987:                IpAddress       struct sockaddr_in
        !           988:                NetworkAddress  struct sockaddr_in
        !           989:                Counter integer
        !           990:                Gauge   integer
        !           991:                TimeTicks       integer
        !           992:                ClnpAddress     struct sockaddr_iso
        !           993: 
        !           994:           where "syntax" is the name appearing in a compiled MIB module,
        !           995:           and "structure" is the C language data type corresponding to
        !           996:           the object's syntax.
        !           997: 
        !           998: 
        !           999: 
        !          1000: 
        !          1001: 
        !          1002:           M.T. Rose                                            [Page 17]
        !          1003: 
        !          1004: 
        !          1005: 
        !          1006: 
        !          1007: 
        !          1008:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1009: 
        !          1010: 
        !          1011:           To take a syntax name and get back the structure, use the
        !          1012:           routine text2syn.
        !          1013: 
        !          1014: 
        !          1015:           6.1.1.  Abstractions for Standard Syntaxes
        !          1016: 
        !          1017:           Here are the structures and routine used to implement the
        !          1018:           low-level MIB abstractions.
        !          1019: 
        !          1020: 
        !          1021:           6.1.1.1.  integer
        !          1022: 
        !          1023:           This is used for the INTEGER, Counter, Gauge, and TimeTicks
        !          1024:           syntax.
        !          1025: 
        !          1026:           The definition is:
        !          1027: 
        !          1028:                typedef int integer;
        !          1029: 
        !          1030:           which is hardly surprising.
        !          1031: 
        !          1032: 
        !          1033:           6.1.1.2.  struct qbuf
        !          1034: 
        !          1035:           This is used for the OctetString (OBJECT IDENTIFIER) and
        !          1036:           DisplayString syntaxes.
        !          1037: 
        !          1038:           The definition is:
        !          1039: 
        !          1040:                struct qbuf {
        !          1041:                    struct qbuf *qb_forw;   /* doubly-linked list */
        !          1042:                    struct qbuf *qb_back;   /*   .. */
        !          1043: 
        !          1044:                    int     qb_len;         /* length of data */
        !          1045:                    char   *qb_data;        /* current pointer into data */
        !          1046:                    char    qb_base[1];     /* extensible... */
        !          1047:                };
        !          1048: 
        !          1049:           The macro QBFREE is used to traverse qb_forw to free all qbufs
        !          1050:           in the ring:
        !          1051: 
        !          1052:                QBFREE (qb)
        !          1053:                struct qbuf *qb;
        !          1054: 
        !          1055:           To allocate a new string from the qbuf use:
        !          1056: 
        !          1057: 
        !          1058: 
        !          1059: 
        !          1060: 
        !          1061:           M.T. Rose                                            [Page 18]
        !          1062: 
        !          1063: 
        !          1064: 
        !          1065: 
        !          1066: 
        !          1067:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1068: 
        !          1069: 
        !          1070:                char *qb2str (q)
        !          1071:                struct qbuf *q
        !          1072: 
        !          1073:           The string is NULL-terminated, but there may be other NULLs in
        !          1074:           the string to foil things like strlen.
        !          1075: 
        !          1076:           To allocate a new qbuf of len octets from string s, use:
        !          1077: 
        !          1078:                struct qbuf str2qb (s, len, head)
        !          1079:                char    *s;
        !          1080:                int      len,
        !          1081:                         head;
        !          1082: 
        !          1083:           (head should always be 1).
        !          1084: 
        !          1085:           To free an allocated qbuf, use qb_free which calls QBFREE and
        !          1086:           then free on its argument.
        !          1087: 
        !          1088: 
        !          1089:           6.1.1.3.  struct OIDentifier
        !          1090: 
        !          1091:           This is used for the ObjectID (OBJECT IDENTIFIER) syntax.  The
        !          1092:           definition is:
        !          1093: 
        !          1094:                typedef struct OIDentifier {
        !          1095:                    int     oid_nelem;  /* number of sub-identifiers */
        !          1096: 
        !          1097:                    unsigned int *oid_elements;
        !          1098:                        /* the (ordered) list of sub-identifiers */
        !          1099:                }                       OIDentifier, *OID;
        !          1100:                #define NULLOID ((OID) 0)
        !          1101: 
        !          1102:           To compare two OIDs, use
        !          1103: 
        !          1104:                int     oid_cmp (p, q)
        !          1105:                OID     p,
        !          1106:                        q;
        !          1107: 
        !          1108:           which returns -1 if p<q, 1 if p>q, 0 otherwise.
        !          1109: 
        !          1110:           To allocate a new OID and copy it from another, use oid_cpy.
        !          1111: 
        !          1112:           To free an allocated OID, use oid_free.
        !          1113: 
        !          1114: 
        !          1115: 
        !          1116: 
        !          1117: 
        !          1118: 
        !          1119: 
        !          1120:           M.T. Rose                                            [Page 19]
        !          1121: 
        !          1122: 
        !          1123: 
        !          1124: 
        !          1125: 
        !          1126:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1127: 
        !          1128: 
        !          1129:           To take an OID and produce a string in numeric form use
        !          1130: 
        !          1131:                char   *sprintoid (oid)
        !          1132:                OID     oid;
        !          1133: 
        !          1134:           The result is returned in a static area.  The inverse routine
        !          1135:           is:
        !          1136: 
        !          1137:                OID     str2oid (s)
        !          1138:                char    *s;
        !          1139: 
        !          1140:           which returns an OID from a static area
        !          1141: 
        !          1142: 
        !          1143:           6.1.1.4.  struct sockaddr_in
        !          1144: 
        !          1145:           This is used for the IpAddress and NetworkAddress syntaxes.
        !          1146:           Presumably you are overly familiar with this structure.
        !          1147: 
        !          1148: 
        !          1149:           6.1.1.5.  struct sockaddr_iso
        !          1150: 
        !          1151:           This is used for the ClnpAddress syntax.  If your are not
        !          1152:           running a BSD/OSI system, don't worry about this.
        !          1153: 
        !          1154: 
        !          1155:           6.1.2.  Defining a new Syntax
        !          1156: 
        !          1157:           The routine add_syntax is used to define a new syntax.  (if
        !          1158:           this routine returns NOTOK, then the internal syntax table has
        !          1159:           overflowed; adjust the constant MAXSYN in the file syntax.c).
        !          1160:           The first argument is the name of the syntax.  The other five
        !          1161:           are pointers to integer-valued routines that are called to
        !          1162:           operate on an opaque pointer:
        !          1163: 
        !          1164:                /* returns OK if x is encoded into pe (allocates pe),
        !          1165:                   NOTOK otherwise */
        !          1166: 
        !          1167:                f_encode (x, pe)
        !          1168:                pointer *x;
        !          1169:                PE      *pe;
        !          1170: 
        !          1171: 
        !          1172:                /* returns OK if pe is decoded into x (allocates x),
        !          1173:                   NOTOK otherwise */
        !          1174: 
        !          1175: 
        !          1176: 
        !          1177: 
        !          1178: 
        !          1179:           M.T. Rose                                            [Page 20]
        !          1180: 
        !          1181: 
        !          1182: 
        !          1183: 
        !          1184: 
        !          1185:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1186: 
        !          1187: 
        !          1188:                f_decode (x, pe)
        !          1189:                pointer **x;
        !          1190:                PE        pe;
        !          1191: 
        !          1192: 
        !          1193:                /* free's an allocated x (from f_decode or f_parse) */
        !          1194: 
        !          1195:                f_free (x)
        !          1196:                pointer *x;
        !          1197: 
        !          1198: 
        !          1199:                /* returns OK if s is decoded into x (allocates x),
        !          1200:                   NOTOK otherwise */
        !          1201: 
        !          1202:                f_parse (x, s)
        !          1203:                pointer **x;
        !          1204:                char     *s;
        !          1205: 
        !          1206: 
        !          1207:                /* prints x on the user's tty */
        !          1208: 
        !          1209:                f_print (x, os)
        !          1210:                pointer *x;
        !          1211:                OS       os;
        !          1212: 
        !          1213:           Presentation elements (PEs) are discussed later on.
        !          1214: 
        !          1215: 
        !          1216:           6.2.  Objects
        !          1217: 
        !          1218:           MIB objects are modeled by the OT structure:
        !          1219: 
        !          1220:                typedef struct object_type {
        !          1221:                    char   *ot_text;                /* OBJECT DESCRIPTOR */
        !          1222:                    char   *ot_id;                  /* OBJECT IDENTIFIER */
        !          1223:                    OID     ot_name;                /*   .. */
        !          1224: 
        !          1225:                    OS      ot_syntax;              /* SYNTAX */
        !          1226: 
        !          1227:                    int     ot_access;              /* ACCESS */
        !          1228:                #define OT_NONE         0x00
        !          1229:                #define OT_RDONLY       0x01
        !          1230:                #define OT_RDWRITE      0x02
        !          1231: 
        !          1232:                    int     ot_status;              /* STATUS */
        !          1233: 
        !          1234: 
        !          1235: 
        !          1236: 
        !          1237: 
        !          1238:           M.T. Rose                                            [Page 21]
        !          1239: 
        !          1240: 
        !          1241: 
        !          1242: 
        !          1243: 
        !          1244:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1245: 
        !          1246: 
        !          1247:                #define OT_OBSOLETE     0x00
        !          1248:                #define OT_MANDATORY    0x01
        !          1249:                #define OT_OPTIONAL     0x02
        !          1250:                #define OT_DEPRECATED   0x03
        !          1251: 
        !          1252:                     ...
        !          1253:                }               object_type, *OT;
        !          1254:                #define NULLOT  ((OT) 0)
        !          1255: 
        !          1256:           There are lots of routines to manipulate MIB objects.
        !          1257: 
        !          1258:           The routine name2obj takes an object identifier and returns
        !          1259:           the object type, either exact or prefix, e.g.,
        !          1260: 
        !          1261:                name2obj ( OID { ipRouteDest.0.0.0.0 } )
        !          1262: 
        !          1263:           returns the object type for "ipRouteDest"
        !          1264: 
        !          1265:           The routine text2obj takes a string and returns the exact
        !          1266:           object type, e.g.,
        !          1267: 
        !          1268:                text2obj ("ipRouteDest")
        !          1269: 
        !          1270:           will succeed, but
        !          1271: 
        !          1272:                text2obj ("ipRouteDest.0.0.0.0")
        !          1273: 
        !          1274:           will fail.
        !          1275: 
        !          1276:           The routine text2oid takes a string and returns the object
        !          1277:           identifier associated with the corresponding object.  The
        !          1278:           string can be numeric (e.g., "1.3.6.1"), symbolic (e.g.,
        !          1279:           "internet"), or symbolic.numeric (e.g., "iso.3.6.1").
        !          1280: 
        !          1281:           The routine oid2ode takes an OID and returns a string suitable
        !          1282:           for pretty-printing, in the form symbolic or symbolic.numeric.
        !          1283: 
        !          1284: 
        !          1285:           6.3.  Instances
        !          1286: 
        !          1287:           MIB instances are modeled by the OI structure:
        !          1288: 
        !          1289:                typedef struct object_instance {
        !          1290:                    OID     oi_name;                /* instance OID */
        !          1291: 
        !          1292: 
        !          1293: 
        !          1294: 
        !          1295: 
        !          1296: 
        !          1297:           M.T. Rose                                            [Page 22]
        !          1298: 
        !          1299: 
        !          1300: 
        !          1301: 
        !          1302: 
        !          1303:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1304: 
        !          1305: 
        !          1306:                    OT      oi_type;                /* prototype */
        !          1307:                }               object_instance, *OI;
        !          1308:                #define NULLOI  ((OI) 0)
        !          1309: 
        !          1310:           There are lots of routines to manipulate MIB instances.
        !          1311: 
        !          1312:           The routine name2inst takes a variable name and returns the
        !          1313:           corresponding instance, e.g.,
        !          1314: 
        !          1315:                name2inst ( OID { ipRouteDest.0.0.0.0 } )
        !          1316: 
        !          1317:           will return an OI with oi_name set to its argument and oi_type
        !          1318:           set to the object type for "ipRouteDest".
        !          1319: 
        !          1320:           The routine next2inst finds the closest object type before the
        !          1321:           variable name and returns an OI corresponding to that object
        !          1322:           type.
        !          1323: 
        !          1324:           The routine text2inst first calls text2oid to get the OID
        !          1325:           corresponding to the argument, then calls name2obj to get the
        !          1326:           type associated with that OID.
        !          1327: 
        !          1328: 
        !          1329: 
        !          1330: 
        !          1331: 
        !          1332: 
        !          1333: 
        !          1334: 
        !          1335: 
        !          1336: 
        !          1337: 
        !          1338: 
        !          1339: 
        !          1340: 
        !          1341: 
        !          1342: 
        !          1343: 
        !          1344: 
        !          1345: 
        !          1346: 
        !          1347: 
        !          1348: 
        !          1349: 
        !          1350: 
        !          1351: 
        !          1352: 
        !          1353: 
        !          1354: 
        !          1355: 
        !          1356:           M.T. Rose                                            [Page 23]
        !          1357: 
        !          1358: 
        !          1359: 
        !          1360: 
        !          1361: 
        !          1362:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1363: 
        !          1364: 
        !          1365:           7.  Linkage
        !          1366: 
        !          1367:           It is now time to tie up all the loose ends.  When your
        !          1368:           program starts, it needs to establish some linkage between the
        !          1369:           objects defined in the compiled MIB module and the data
        !          1370:           structures in your program.  Further, when the SNMP agent asks
        !          1371:           to manipulate the object instances in the MIB module your
        !          1372:           program exported (e.g., using the powerful SNMP get-next
        !          1373:           operator), you need to have a small protocol engine to field
        !          1374:           these requests.
        !          1375: 
        !          1376:           The way the linkage is established is to associate a C routine
        !          1377:           with each of the leaf objects defined in the compiled MIB
        !          1378:           module.  When the protocol engine fields a request from the
        !          1379:           SNMP agent, it will invoke that routine to "do the right
        !          1380:           thing".  Typically, for each table in the compiled MIB module,
        !          1381:           you define a C routine to handle requests for the leaf objects
        !          1382:           of that table.  In addition, there is usually one more routine
        !          1383:           defined to handle those leaf objects not found under any one
        !          1384:           table.  For each C routine you define, you define a group of
        !          1385:           constant integer symbols which identify a leaf object that is
        !          1386:           handled by that routine (e.g., for each routine, you start
        !          1387:           numbering the symbols starting at 0 and going up).  By
        !          1388:           convention, these symbols have the same name as the leaf
        !          1389:           objects.
        !          1390: 
        !          1391: 
        !          1392:           7.1.  Initialization
        !          1393: 
        !          1394:           Earlier it was noted that your program will probably call a
        !          1395:           routine called init_mib which initializes it's internal MIB
        !          1396:           structures.  The routine should look something like this:
        !          1397: 
        !          1398:                register OT     ot;
        !          1399: 
        !          1400:                if (ot = text2obj ("mbufS"))
        !          1401:                    ot -> ot_getfnx = o_mbuf,
        !          1402:                    ot -> ot_info = (caddr_t) mbufS;
        !          1403: 
        !          1404:                 ...
        !          1405: 
        !          1406:                if (ot = text2obj ("mbufType"))
        !          1407:                    ot -> ot_getfnx = o_mbufType,
        !          1408:                    ot -> ot_info = (caddr_t) mbufType;
        !          1409: 
        !          1410: 
        !          1411: 
        !          1412: 
        !          1413: 
        !          1414: 
        !          1415:           M.T. Rose                                            [Page 24]
        !          1416: 
        !          1417: 
        !          1418: 
        !          1419: 
        !          1420: 
        !          1421:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1422: 
        !          1423: 
        !          1424:           where we can imagine that o_mbuf and o_mbufType are routines
        !          1425:           that are defined in your program, and mbufS and mbufType are
        !          1426:           constant symbols defined with those routines.
        !          1427: 
        !          1428: 
        !          1429:           7.2.  Generic Event Handling
        !          1430: 
        !          1431:           Earlier it was noted that your program will probably call a
        !          1432:           routine called get_smux which implements the SNMP get and
        !          1433:           powerful get-next operators.  The routine should look
        !          1434:           something like this:
        !          1435: 
        !          1436:                static  get_smux (pdu, offset)
        !          1437:                register struct type_SNMP_GetRequest__PDU *pdu;
        !          1438:                int     offset;
        !          1439:                {
        !          1440:                    int     idx,
        !          1441:                            status;
        !          1442:                    object_instance ois;
        !          1443:                    register struct type_SNMP_VarBindList *vp;
        !          1444: 
        !          1445:                    quantum = pdu -> request__id;
        !          1446:                    idx = 0;
        !          1447:                    for (vp = pdu -> variable__bindings; vp; vp = vp -> next) {
        !          1448:                        register OI     oi;
        !          1449:                        register OT     ot;
        !          1450:                        register struct type_SNMP_VarBind *v = vp -> VarBind;
        !          1451: 
        !          1452:                        idx++;
        !          1453: 
        !          1454:                        if (offset == type_SNMP_SMUX__PDUs_get__next__request) {
        !          1455:                            if ((oi = name2inst (v -> name)) == NULLOI
        !          1456:                                    && (oi = next2inst (v -> name)) == NULLOI)
        !          1457:                                goto no_name;
        !          1458: 
        !          1459:                            if ((ot = oi -> oi_type) -> ot_getfnx == NULLIFP)
        !          1460:                                goto get_next;
        !          1461:                        }
        !          1462:                        else
        !          1463:                            if ((oi = name2inst (v -> name)) == NULLOI
        !          1464:                                    || (ot = oi -> oi_type) -> ot_getfnx
        !          1465:                                            == NULLIFP) {
        !          1466:                no_name: ;
        !          1467:                                pdu -> error__status =
        !          1468:                                        int_SNMP_error__status_noSuchName;
        !          1469: 
        !          1470: 
        !          1471: 
        !          1472: 
        !          1473: 
        !          1474:           M.T. Rose                                            [Page 25]
        !          1475: 
        !          1476: 
        !          1477: 
        !          1478: 
        !          1479: 
        !          1480:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1481: 
        !          1482: 
        !          1483:                                goto out;
        !          1484:                            }
        !          1485: 
        !          1486:                try_again: ;
        !          1487:                        switch (ot -> ot_access) {
        !          1488:                            case OT_NONE:
        !          1489:                                if (offset ==
        !          1490:                                        type_SNMP_SMUX__PDUs_get__next__request)
        !          1491:                                    goto get_next;
        !          1492:                                goto no_name;
        !          1493: 
        !          1494:                            case OT_RDONLY:
        !          1495:                                if (offset ==
        !          1496:                                        type_SNMP_SMUX__PDUs_set__request) {
        !          1497:                                    pdu -> error__status =
        !          1498:                                                int_SNMP_error__status_readOnly;
        !          1499:                                    goto out;
        !          1500:                                }
        !          1501:                                break;
        !          1502: 
        !          1503:                            case OT_RDWRITE:
        !          1504:                                break;
        !          1505:                        }
        !          1506: 
        !          1507:                        switch (status = (*ot -> ot_getfnx) (oi, v, offset)) {
        !          1508:                            case NOTOK:     /* get-next wants a bump */
        !          1509:                get_next: ;
        !          1510:                                oi = &ois;
        !          1511:                                for (;;) {
        !          1512:                                    if ((ot = ot -> ot_next) == NULLOT) {
        !          1513:                                        pdu -> error__status =
        !          1514:                                              int_SNMP_error__status_noSuchName;
        !          1515:                                        goto out;
        !          1516:                                    }
        !          1517:                                    oi -> oi_name =
        !          1518:                                                (oi -> oi_type = ot) -> ot_name;
        !          1519:                                    if (ot -> ot_getfnx)
        !          1520:                                        goto try_again;
        !          1521:                                }
        !          1522: 
        !          1523:                            case int_SNMP_error__status_noError:
        !          1524:                                break;
        !          1525: 
        !          1526:                            default:
        !          1527:                                pdu -> error__status = status;
        !          1528: 
        !          1529: 
        !          1530: 
        !          1531: 
        !          1532: 
        !          1533:           M.T. Rose                                            [Page 26]
        !          1534: 
        !          1535: 
        !          1536: 
        !          1537: 
        !          1538: 
        !          1539:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1540: 
        !          1541: 
        !          1542:                                goto out;
        !          1543:                        }
        !          1544:                    }
        !          1545:                    idx = 0;
        !          1546: 
        !          1547:                out: ;
        !          1548:                    pdu -> error__index = idx;
        !          1549: 
        !          1550:                    if (smux_response (pdu) == NOTOK) {
        !          1551:                        error ("smux_response: %s [%s]",
        !          1552:                               smux_error (smux_errno), smux_info);
        !          1553:                        smux_fd = NOTOK;
        !          1554:                    }
        !          1555:                }
        !          1556: 
        !          1557:           The actual code is fairly straight-forward: First, the
        !          1558:           variable quantum is set to the request ID for this
        !          1559:           transaction.  The SMUX protocol requires that this number
        !          1560:           change for each SNMP operation that the SNMP agent fields, so
        !          1561:           your program can use it as a cookie to see when it should re-
        !          1562:           read kernel variables.  (A single SNMP operation received by
        !          1563:           the SNMP agent might result in multiple SMUX protocol
        !          1564:           transactions with your program.)
        !          1565: 
        !          1566:           Next, the code loops through the list of variables requested.
        !          1567:           The object instance is determined and loaded into oin and the
        !          1568:           corresponding object type is loaded into ot, and the access is
        !          1569:           checked.
        !          1570: 
        !          1571:           Finally, the user-defined routine is invoked.  This routine
        !          1572:           returns one of these values:
        !          1573: 
        !          1574:                NOTOK
        !          1575:                int_SNMP_error__status_noError
        !          1576:                int_SNMP_error__status_tooBig
        !          1577:                int_SNMP_error__status_noSuchName
        !          1578:                int_SNMP_error__status_badValue
        !          1579:                int_SNMP_error__status_readOnly
        !          1580:                int_SNMP_error__status_genErr
        !          1581: 
        !          1582:           the first value is returned only if the powerful get-next
        !          1583:           operator is being invoked and the routine didn't have any more
        !          1584:           object instances for the object type in question.  The
        !          1585:           remainder are all self-explanatory.
        !          1586: 
        !          1587: 
        !          1588: 
        !          1589: 
        !          1590: 
        !          1591: 
        !          1592:           M.T. Rose                                            [Page 27]
        !          1593: 
        !          1594: 
        !          1595: 
        !          1596: 
        !          1597: 
        !          1598:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1599: 
        !          1600: 
        !          1601:           Once an answer is returned, the loop either continues or is
        !          1602:           broken and a response is written back using the smux_response
        !          1603:           routine.  On failure, smux_error will be set to one of
        !          1604:           parameterMissing, invalidOperation, or youLoseBig.
        !          1605: 
        !          1606: 
        !          1607:           7.3.  Specific Event Handling: Outside a table
        !          1608: 
        !          1609:           Now let's look at one of these user-defined routines, which
        !          1610:           handles leaf objects that are not part of a table:
        !          1611: 
        !          1612:                static  int     lastq = -1;
        !          1613:                static  struct mbstat mbstat;
        !          1614: 
        !          1615: 
        !          1616:                #define mbufS           0
        !          1617:                #define mbufClusters    1
        !          1618:                 ...
        !          1619:                #define mbufFrees       6
        !          1620: 
        !          1621: 
        !          1622:                static int  o_mbuf (oi, v, offset)
        !          1623:                OI      oi;
        !          1624:                register struct type_SNMP_VarBind *v;
        !          1625:                int     offset;
        !          1626:                {
        !          1627:                    int     ifvar;
        !          1628:                    register struct mbstat *m = &mbstat;
        !          1629:                    register OID    oid = oi -> oi_name;
        !          1630:                    register OT     ot = oi -> oi_type;
        !          1631: 
        !          1632:                    ifvar = (int) ot -> ot_info;
        !          1633:                    switch (offset) {
        !          1634:                        case type_SNMP_SMUX__PDUs_get__request:
        !          1635:                            if (oid -> oid_nelem !=
        !          1636:                                        ot -> ot_name -> oid_nelem + 1
        !          1637:                                    || oid -> oid_elements[oid -> oid_nelem - 1]
        !          1638:                                            != 0)
        !          1639:                                return int_SNMP_error__status_noSuchName;
        !          1640:                            break;
        !          1641: 
        !          1642:                        case type_SNMP_SMUX__PDUs_get__next__request:
        !          1643:                            if (oid -> oid_nelem
        !          1644:                                    == ot -> ot_name -> oid_nelem) {
        !          1645:                                OID     new;
        !          1646: 
        !          1647: 
        !          1648: 
        !          1649: 
        !          1650: 
        !          1651:           M.T. Rose                                            [Page 28]
        !          1652: 
        !          1653: 
        !          1654: 
        !          1655: 
        !          1656: 
        !          1657:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1658: 
        !          1659: 
        !          1660:                                if ((new = oid_extend (oid, 1)) == NULLOID)
        !          1661:                                    return int_SNMP_error__status_genErr;
        !          1662:                                new -> oid_elements[new -> oid_nelem - 1] = 0;
        !          1663: 
        !          1664:                                if (v -> name)
        !          1665:                                    free_SNMP_ObjectName (v -> name);
        !          1666:                                v -> name = new;
        !          1667:                            }
        !          1668:                            else
        !          1669:                                return NOTOK;
        !          1670:                            break;
        !          1671: 
        !          1672:                        default:
        !          1673:                            return int_SNMP_error__status_genErr;
        !          1674:                    }
        !          1675: 
        !          1676:                    if (quantum != lastq) {
        !          1677:                        lastq = quantum;
        !          1678: 
        !          1679:                        if (getkmem (nl + N_MBSTAT, (caddr_t) m, sizeof *m)
        !          1680:                                == NOTOK)
        !          1681:                            return int_SNMP_error__status_genErr;
        !          1682:                    }
        !          1683: 
        !          1684:                    switch (ifvar) {
        !          1685:                        case mbufS:
        !          1686:                            return o_integer (oi, v, m -> m_mbufs);
        !          1687: 
        !          1688:                        case mbufClusters:
        !          1689:                            return o_integer (oi, v, m -> m_clusters);
        !          1690: 
        !          1691:                 ...
        !          1692: 
        !          1693:                        case mbufFrees:
        !          1694:                            return o_integer (oi, v, m -> m_mbfree);
        !          1695: 
        !          1696:                        default:
        !          1697:                            return int_SNMP_error__status_noSuchName;
        !          1698:                    }
        !          1699:                }
        !          1700: 
        !          1701:           The actual code is fairly straight-forward: First, the
        !          1702:           constant offsets are defined.  Then, the o_mbuf routine is
        !          1703:           defined.
        !          1704: 
        !          1705: 
        !          1706: 
        !          1707: 
        !          1708: 
        !          1709: 
        !          1710:           M.T. Rose                                            [Page 29]
        !          1711: 
        !          1712: 
        !          1713: 
        !          1714: 
        !          1715: 
        !          1716:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1717: 
        !          1718: 
        !          1719:           The first action is to determine which leaf object is being
        !          1720:           referenced.  This corresponding symbolic constant is placed in
        !          1721:           the variable ifvar.  Then a switch is made based on the
        !          1722:           operation.
        !          1723: 
        !          1724:           (1)  For the get operation, all instances are identified by
        !          1725:                the object type followed by ".0" (e.g., "mbufS.0").  So,
        !          1726:                the code checks to see if the OID associated with the
        !          1727:                object instance is exactly one longer than the OID
        !          1728:                associated with the object type, and that the extra sub-
        !          1729:                identifier has the value 0.
        !          1730: 
        !          1731:           (2)  For the powerful get-next operation, there are really two
        !          1732:                cases, depending on whether some instance identifier is
        !          1733:                present.  If some instance identifier is present, then
        !          1734:                for a non-tabular leaf object, the next variable belongs
        !          1735:                to some other object type, so the routine simply returns
        !          1736:                the value NOTOK, and the get_smux routine will find the
        !          1737:                next object accordingly.  Otherwise, if no instance is
        !          1738:                identified, a new OID is constructed and initialized.
        !          1739:                The old OID is free'd and the new one inserted in its
        !          1740:                place.
        !          1741: 
        !          1742:           Now that the correct instance has been identified, a check is
        !          1743:           made to see if kmem should be consulted.  (Obviously other
        !          1744:           programs might consult other data stores.) Finally, the
        !          1745:           instance value is encoded and the routine returns.
        !          1746: 
        !          1747: 
        !          1748:           7.3.1.  Instance handling
        !          1749: 
        !          1750:           Several routines are provided to encode instance values:
        !          1751: 
        !          1752:           The o_number routine encodes an integer value, such as an
        !          1753:           INTEGER, Counter, Guage, or TimeTick.  The macro o_integer is
        !          1754:           simply a synonym for o_number.
        !          1755: 
        !          1756:           The o_string routine encodes a string value, such as an
        !          1757:           OctetString or DisplayString, e.g.,
        !          1758: 
        !          1759:                o_string (oi, v, "lo0", strlen ("lo0"));
        !          1760: 
        !          1761:           or
        !          1762: 
        !          1763:                o_string (oi, v, ether_addr, sizeof ether_addr);
        !          1764: 
        !          1765: 
        !          1766: 
        !          1767: 
        !          1768: 
        !          1769:           M.T. Rose                                            [Page 30]
        !          1770: 
        !          1771: 
        !          1772: 
        !          1773: 
        !          1774: 
        !          1775:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1776: 
        !          1777: 
        !          1778:           The o_specific routine takes a structure corresponding to a
        !          1779:           syntax, such as an OID for ObjectID, and does the encoding,
        !          1780:           e.g.,
        !          1781: 
        !          1782:                OID nullSpecific = ...;
        !          1783: 
        !          1784:                o_specific (oi, v, nullSpecific);
        !          1785: 
        !          1786: 
        !          1787: 
        !          1788:           7.3.2.  A special case
        !          1789: 
        !          1790:           A special user-defined routine is provided for those cases for
        !          1791:           leaf-objects containing information that is initialized on
        !          1792:           start-up, o_generic.  For example:
        !          1793: 
        !          1794:                char    buffer[BUFSIZ];
        !          1795: 
        !          1796:                if (ot = text2obj ("sysName"))
        !          1797:                    ot -> ot_getfnx = o_generic,
        !          1798:                    ot -> ot_info = (caddr_t) sysName;
        !          1799: 
        !          1800:                (void) gethostname (buffer, sizeof buffer);
        !          1801:                (void) (*ot -> ot_syntax -> os_parse)
        !          1802:                                ((struct qbuf **) &ot -> ot_info, buffer);
        !          1803: 
        !          1804:           The idea is that the ot_info field contains a pointer to a
        !          1805:           data structure corresponding to the syntax of the object.
        !          1806:           Since all of the structures are rather strange (except for
        !          1807:           integers), o_generic probably won't receive a lot of use.
        !          1808: 
        !          1809: 
        !          1810:           7.4.  Specific Event Handling: Inside a table
        !          1811: 
        !          1812:           Now let's look at one of these user-defined routines, which
        !          1813:           handles leaf objects that are part of a table:
        !          1814: 
        !          1815:                #define mbufType        0
        !          1816:                #define mbufAllocates   1
        !          1817: 
        !          1818: 
        !          1819:                static int  o_mbufType (oi, v, offset)
        !          1820:                OI      oi;
        !          1821:                register struct type_SNMP_VarBind *v;
        !          1822:                int     offset;
        !          1823: 
        !          1824: 
        !          1825: 
        !          1826: 
        !          1827: 
        !          1828:           M.T. Rose                                            [Page 31]
        !          1829: 
        !          1830: 
        !          1831: 
        !          1832: 
        !          1833: 
        !          1834:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1835: 
        !          1836: 
        !          1837:                {
        !          1838:                    int     ifnum,
        !          1839:                            ifvar;
        !          1840:                    register struct mbstat *m = &mbstat;
        !          1841:                    register OID    oid = oi -> oi_name;
        !          1842:                    register OT     ot = oi -> oi_type;
        !          1843: 
        !          1844:                    ifvar = (int) ot -> ot_info;
        !          1845:                    switch (offset) {
        !          1846:                        case type_SNMP_SMUX__PDUs_get__request:
        !          1847:                            if (oid -> oid_nelem
        !          1848:                                    != ot -> ot_name -> oid_nelem + 1)
        !          1849:                                return int_SNMP_error__status_noSuchName;
        !          1850:                            ifnum =
        !          1851:                                  oid -> oid_elements[oid -> oid_nelem - 1];
        !          1852:                            if (ifvar >= sizeof m -> m_mtypes /
        !          1853:                                            sizeof m -> m_mtypes[0])
        !          1854:                                return int_SNMP_error__status_noSuchName;
        !          1855:                            break;
        !          1856: 
        !          1857:                        case type_SNMP_SMUX__PDUs_get__next__request:
        !          1858:                            if (oid -> oid_nelem
        !          1859:                                    == ot -> ot_name -> oid_nelem) {
        !          1860:                                OID     new;
        !          1861: 
        !          1862:                                ifnum = 0;
        !          1863: 
        !          1864:                                if ((new = oid_extend (oid, 1)) == NULLOID)
        !          1865:                                    return int_SNMP_error__status_genErr;
        !          1866:                                new -> oid_elements[new -> oid_nelem - 1] =
        !          1867:                                                ifnum;
        !          1868: 
        !          1869:                                if (v -> name)
        !          1870:                                    free_SNMP_ObjectName (v -> name);
        !          1871:                                v -> name = new;
        !          1872:                            }
        !          1873:                            else {
        !          1874:                                int     i = ot -> ot_name -> oid_nelem;
        !          1875: 
        !          1876:                                ifnum = oid -> oid_elements[i] + 1;
        !          1877:                                if (ifnum >= sizeof m -> m_mtypes /
        !          1878:                                                sizeof m -> m_mtypes[0])
        !          1879:                                    return NOTOK;
        !          1880: 
        !          1881:                                oid -> oid_elements[i] = ifnum;
        !          1882: 
        !          1883: 
        !          1884: 
        !          1885: 
        !          1886: 
        !          1887:           M.T. Rose                                            [Page 32]
        !          1888: 
        !          1889: 
        !          1890: 
        !          1891: 
        !          1892: 
        !          1893:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1894: 
        !          1895: 
        !          1896:                                oid -> oid_nelem = i + 1;
        !          1897:                            }
        !          1898:                            break;
        !          1899: 
        !          1900:                        default:
        !          1901:                            return int_SNMP_error__status_genErr;
        !          1902:                    }
        !          1903: 
        !          1904:                    if (quantum != lastq) {
        !          1905:                        lastq = quantum;
        !          1906: 
        !          1907:                        if (getkmem (nl + N_MBSTAT, (caddr_t) m, sizeof *m)
        !          1908:                                == NOTOK)
        !          1909:                            return int_SNMP_error__status_genErr;
        !          1910:                    }
        !          1911: 
        !          1912:                    switch (ifvar) {
        !          1913:                        case mbufType:
        !          1914:                            return o_integer (oi, v, ifnum);
        !          1915: 
        !          1916:                        case mbufAllocates:
        !          1917:                            return o_integer (oi, v,
        !          1918:                                              m -> m_mtypes[ifnum]);
        !          1919: 
        !          1920:                        default:
        !          1921:                            return int_SNMP_error__status_noSuchName;
        !          1922:                    }
        !          1923:                }
        !          1924: 
        !          1925:           The actual code is fairly straight-forward: First, the
        !          1926:           constant offsets are defined.  Then, the o_mbufType routine is
        !          1927:           defined.
        !          1928: 
        !          1929:           The first action is to determine which leaf object is being
        !          1930:           referenced.  This corresponding symbolic constant is placed in
        !          1931:           the variable ifvar.  Then a switch is made based on the
        !          1932:           operation.  Because these are tabular objects, the instance
        !          1933:           refers to a row in the table (and the leaf object refers to a
        !          1934:           column in the table, of course).
        !          1935: 
        !          1936:           (1)  For the get operation, all instances are identified by
        !          1937:                the object type followed by ".rowno" (e.g.,
        !          1938:                "mbufAllocates.10") refers to the value in the
        !          1939:                mbufAllocates column of the thenth row).  So, the code
        !          1940:                checks to see if the OID associated with the object
        !          1941: 
        !          1942: 
        !          1943: 
        !          1944: 
        !          1945: 
        !          1946:           M.T. Rose                                            [Page 33]
        !          1947: 
        !          1948: 
        !          1949: 
        !          1950: 
        !          1951: 
        !          1952:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          1953: 
        !          1954: 
        !          1955:                instance is exactly one longer than the OID associated
        !          1956:                with the object type, and that the extra sub-identifier
        !          1957:                is within the range 0..rowno-1.
        !          1958: 
        !          1959:           (2)  For the powerful get-next operation, there are really two
        !          1960:                cases, depending on whether some instance identifier is
        !          1961:                present.  If no instance is identified, a new OID is
        !          1962:                constructed and initialized for the first row (row 0) of
        !          1963:                the table. The old OID is free'd and the new one inserted
        !          1964:                in its place.  Otherwise, if some instance identifier is
        !          1965:                present, then the corresponding row must be identified,
        !          1966:                the row number incremented, and a check made to see if
        !          1967:                this is still in range (if not, NOTOK is returned to
        !          1968:                signal that the next object type should be used).
        !          1969:                Otherwise, the OID is updated in place.
        !          1970: 
        !          1971:           Now that the correct instance has been identified, a check is
        !          1972:           made to see if kmem should be consulted.  (Obviously other
        !          1973:           programs might consult other data stores.) Finally, the
        !          1974:           instance value is encoded and the routine returns.
        !          1975: 
        !          1976: 
        !          1977:           7.4.1.  The general case
        !          1978: 
        !          1979:           Obviously, this is a simple example of table handling.  In
        !          1980:           general, the table will be implemented via linked lists,
        !          1981:           sorted according to object instance.  In this case, there is
        !          1982:           usually a special routine that is called to get a particular
        !          1983:           instance or the next instance.  Take a look at the routines
        !          1984:           get_tbent and o_smuxTree in the file snmpd.c.  These implement
        !          1985:           the smuxTree table.
        !          1986: 
        !          1987: 
        !          1988: 
        !          1989: 
        !          1990: 
        !          1991: 
        !          1992: 
        !          1993: 
        !          1994: 
        !          1995: 
        !          1996: 
        !          1997: 
        !          1998: 
        !          1999: 
        !          2000: 
        !          2001: 
        !          2002: 
        !          2003: 
        !          2004: 
        !          2005:           M.T. Rose                                            [Page 34]
        !          2006: 
        !          2007: 
        !          2008: 
        !          2009: 
        !          2010: 
        !          2011:           draft            Exporting MIBs for BSD UNIX          May 1990
        !          2012: 
        !          2013: 
        !          2014:           Table of Contents
        !          2015: 
        !          2016: 
        !          2017:           1 Status of this Memo ...................................    1
        !          2018:           2 The Environment .......................................    2
        !          2019:           2.1 The ISODE ...........................................    2
        !          2020:           3 MIB Modules ...........................................    3
        !          2021:           3.1 Compiling MIB modules ...............................    4
        !          2022:           3.1.1 The Syntax of compiled MIB modules ................    5
        !          2023:           4 SMUX Peers ............................................    6
        !          2024:           5 Daemon Skeleton .......................................    7
        !          2025:           5.1 Declarations ........................................    7
        !          2026:           5.2 Initialization ......................................    8
        !          2027:           5.3 Reading the compiled MIB module .....................    8
        !          2028:           5.4 Talking to the SNMP agent ...........................    9
        !          2029:           5.4.1 Initialization ....................................   10
        !          2030:           5.4.2 Opening ...........................................   10
        !          2031:           5.4.3 Closing ...........................................   11
        !          2032:           5.4.4 Registering Subtrees ..............................   11
        !          2033:           5.4.5 Main Loop .........................................   12
        !          2034:           5.4.6 Events ............................................   14
        !          2035:           6 Managed Objects .......................................   17
        !          2036:           6.1 Syntax ..............................................   17
        !          2037:           6.1.1 Abstractions for Standard Syntaxes ................   18
        !          2038:           6.1.1.1 integer .........................................   18
        !          2039:           6.1.1.2 struct qbuf .....................................   18
        !          2040:           6.1.1.3 struct OIDentifier ..............................   19
        !          2041:           6.1.1.4 struct sockaddr_in ..............................   20
        !          2042:           6.1.1.5 struct sockaddr_iso .............................   20
        !          2043:           6.1.2 Defining a new Syntax .............................   20
        !          2044:           6.2 Objects .............................................   21
        !          2045:           6.3 Instances ...........................................   22
        !          2046:           7 Linkage ...............................................   24
        !          2047:           7.1 Initialization ......................................   24
        !          2048:           7.2 Generic Event Handling ..............................   25
        !          2049:           7.3 Specific Event Handling: Outside a table ............   28
        !          2050:           7.3.1 Instance handling .................................   30
        !          2051:           7.3.2 A special case ....................................   31
        !          2052:           7.4 Specific Event Handling: Inside a table .............   31
        !          2053:           7.4.1 The general case ..................................   34
        !          2054: 
        !          2055: 
        !          2056: 
        !          2057: 
        !          2058: 
        !          2059: 
        !          2060: 
        !          2061: 
        !          2062: 
        !          2063: 
        !          2064:           M.T. Rose                                            [Page 35]
        !          2065: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.