README.thread
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:13k
- Improved Error Reporting and Thread-Safe Use of the SNMP Library
- There is a need in some environments to support multiple threads
- in a single application. The SNMP Library provides the Single Session
- functions which support thread-safe operation when certain precautions
- are taken. This document describes the operation of the SNMP Library
- with a focus on its session management functions. The Traditional API
- and the Single API functions are compared and contrasted.
- A working understanding of the CMU or UCD SNMP Library
- API is recommended to fully appreciate the concepts discussed.
- The document ends with a list of restrictions for using the Single API
- in a multi-threaded application.
- Unfortunately, the SNMPv3 support was added about the same time as
- the thread support and since they occurred in parallel the SNMPv3
- support was never checked for multi-threading correctness. It is
- most likely that it is not thread-safe at this time.
- ***** IMPORTANT ANNOUNCEMENT *****
- To the point, no resource locks are applied within the SNMP Library.
- The APDU encoding and some session management functions can be used
- in thread-safe manners. The MIB file parsing is not thread-safe.
- The Single Session API was made available in November 1998.
- Existing applications use the Traditional API, which is not thread-safe.
- The thread-safe considerations are discussed throughout this document.
- The research and development of the Single Session API that I've completed
- was wholly funded by my employer, Internet Security Systems, Inc.
- and is distributed freely to the Internet community.
- -Mike Slifcak, 23 April 1999
- 09 July 1999 Removed references to snmp_synch_setup and snmp_synch_reset
- Availability
- The Single Session API is integrated into the currently available
- versions of the CMU SNMP library and the UC-Davis SNMP package.
- ftp://ftp.net.cmu.edu/pub/snmp/cmu-snmp-V1.13.tar.gz and later
- Read : snmp_sess_api.3, Changes.SingleSession
- ftp://ucd-snmp.ucdavis.edu/ucd-snmp-3.6.tar.gz and later
- Read : snmp_sess_api.3, README.thread (after version 3.6.1)
- Both libraries work equally well in Windows NT and various
- UNIX platforms. Please read this document and refer to
- the snmp_sess_api section 3 manual page.
- Glossary of Terms
- APDU Application Protocol Data Unit
- API Application Programming Interface
- CMU Carnegie-Mellon University, Pittsburgh, PA.
- Library The SNMP library; Both CMU and UCD versions are applicable.
- Session Concept embodying the management of transacting SNMP APDUS.
- SNMP Simple Network Management Protocol
- UCD University of California at Davis, CA.
- Introduction
- The Library extends the UNIX file concept (open, close, read, write) to a Session.
- Opening a Session binds a local socket to a well-known port and creates internal
- structures to help with controlling the transaction of SNMP APDUs. Closing a
- Session releases the memory and system resources used for these purposes.
- Since the mid-1980s, many SNMP applications have used the Traditional Session
- API to transact SNMP APDUs between the local host and SNMP-enabled devices.
- The Traditional Session API does not support multi-threaded applications:
- 1) There are no resource locks to prevent exposing the Library's
- global data resources to corruption in a multi-threaded application;
- 2) The Traditional API functions that receive SNMP APDUs
- do not provide an interface for one of many sessions;
- 3) Errors discovered by the Library are communicated through global
- data structures and are not associated with the session
- in which the error occurred.
- The Single Session API provides these capabilities:
- 1) Manage a single SNMP session safely, in multi-threaded or
- non-threaded applications, by avoiding access to data structures
- that the Traditional Session API may share between Sessions;
- 2) Associate errors with the session context for threaded
- and non-threaded applications.
- Contrasting and Comparing Traditional API and Single API
- The Traditional API uses the struct snmp_session pointer returned
- from snmp_open() to identify one SNMP session. The Single API uses
- the opaque pointer returned from snmp_sess_open() to identify one
- SNMP session.
- Helpful Hint : The Library copies the contents of the
- structure which is input to snmp_open() and snmp_sess_open().
- Once copied, changing that input structure's data
- has no effect on the opened SNMP Session.
- The Traditional API uses the snmp_error() function to identify any
- library and system errors that occurred during the processing for
- one SNMP session. The Single API uses snmp_sess_error() for the
- same purpose.
- The Traditional API manages the private Sessions list structure;
- adding to the list during snmp_open(), removing during snmp_close.
- With few exceptions, the Traditional API calls the Single API
- for each session that appears on the Sessions list.
- The Traditional API reads from all Sessions on the Sessions list;
- The Single API does not use the Sessions list.
- The Single API can read from only one Session.
- Helpful Hint :
- This is the basis for thread-safe-ness of the Library.
- There are no resource locks applied.
- Using the Single API
- A multi-threaded application that deploys the SNMP Library should
- should complete all MIB file parsing before additional threads
- are activated. Drawing from the parsed contents of the MIB does
- not incur any data corruption exposure once the internal MIB structures
- are initialised.
- The application may create threads such that a single thread may manage
- a single SNMP session. The thread should call snmp_sess_init()
- to prepare a struct snmp_session structure. The thread can adjust
- session parameters such as the remote UDP port or the local UDP port,
- which must be set prior to invoking snmp_sess_open().
- The first call to snmp_sess_init() initialises the SNMP Library,
- including the MIB parse trees, before any SNMP sessions are created.
- Applications that call snmp_sess_init() do not need to read MIBs
- nor setup environment variables to utilize the Library.
- After the struct snmp_session is setup, the thread must call
- snmp_sess_open() to create an SNMP session. If at any time
- the thread must change the Session configuration,
- snmp_sess_session() returns the pointer to the internal configuration
- structure (a struct snmp_session, copied from snmp_sess_open).
- The thread can adjust parameters such as the session timeout
- or the community string with this returned struct snmp_session pointer.
- Changes to the remote or local port values have no effect on an opened Session.
-
- The thread can build PDUs and bind variables to PDUs, as it performs its duties.
- The thread then calls snmp_sess_send() or snmp_sess_async_send() to build and send
- an SNMP APDU to the remote device. If a Get-Response-PDU is expected, the thread
- should call snmp_sess_synch_response() instead.
- When the thread is finished using the session, it must free the resources
- that the Library used to manage the session.
- Finally, the thread must call snmp_sess_close() to end the Session.
- Snmp_sess_init(), snmp_open(), and snmp_sess_open()
- must use the same calling parameter for a given Session.
- Other methods should use only the returned parameter from
- snmp_open() and snmp_sess_open() to access the opened SNMP Session.
- Error Processing
- Two calls were added : snmp_error() and snmp_sess_error() return the
- "errno" and "snmp_errno" values from the per session data, and a string
- that describes the errors that they represent. The string must be freed
- by the caller.
- Use snmp_error() to process failures after Traditional API calls,
- or snmp_sess_error() to process failure after Single API calls.
- In the case where an SNMP session could not be opened,
- call snmp_error() using the struct snmp_session supplied to either snmp_open()
- or snmp_sess_open().
- The following variables and functions are obsolete and may create problems
- in a multi-threaded application :
- int snmp_errno
- char * snmp_detail
- snmp_set_detail()
- snmp_api_errstring()
- Function Summary
-
- The functions in the following table are functionally equivalent,
- with the exception of these behaviors:
- - The Traditional API manages many sessions
- - The Traditional API passes a struct snmp_session pointer,
- and touches the Sessions list
- - The Single API manages only one session
- - The Single API passes an opaque pointer, and does not use Sessions list
-
- Traditional Single Comment
- =========== ============== =======
- snmp_sess_init snmp_sess_init Call before either open
- snmp_open snmp_sess_open Single not on Sessions list
- snmp_sess_session Exposes snmp_session pointer
- snmp_send snmp_sess_send Send one APDU
- snmp_async_send snmp_sess_async_send Send one APDU with callback
- snmp_select_info snmp_sess_select_info Which session(s) have input
- snmp_read snmp_sess_read Read APDUs
- snmp_timeout snmp_sess_timeout Check for timeout
- snmp_close snmp_sess_close Single not on Sessions list
- snmp_synch_response snmp_sess_synch_response Send/receive one APDU
- snmp_error snmp_sess_error Get library,system errno
- Example 1 : Traditional API use.
- #include "snmp_api.h"
- ...
- int liberr, syserr;
- char *errstr;
- struct snmp_session Session, *sptr;
- ...
- snmp_sess_init(&Session);
- Session.peername = "foo.bar.net";
- sptr = snmp_open(&Session);
- if (sptr == NULL) {
- /* Error codes found in open calling argument */
- snmp_error(&Session, &liberr, &syserr, &errstr);
- printf("SNMP create error %s.n", errstr);
- free(errstr);
- return 0;
- }
- /* Pass sptr to snmp_error from here forward */
- ...
- /* Change the community name */
- free(sptr->community);
- sptr->community = strdup("public");
- sptr->community_len = strlen("public");
- ...
- if (0 == snmp_send(sptr, pdu)) {
- snmp_error(sptr, &liberr, &syserr, &errstr);
- printf("SNMP write error %s.n", errstr);
- free(errstr);
- return 0;
- }
- snmp_close(sptr);
- Example 2 : Single API use.
- #include "snmp_api.h"
- ...
- int liberr, syserr;
- char *errstr;
- void *sessp; /* <-- an opaque pointer, not a struct pointer */
- struct snmp_session Session, *sptr;
- ...
- snmp_sess_init(&Session);
- Session.peername = "foo.bar.net";
- sessp = snmp_sess_open(&Session);
- if (sessp == NULL) {
- /* Error codes found in open calling argument */
- snmp_error(&Session, &liberr, &syserr, &errstr);
- printf("SNMP create error %s.n", errstr);
- free(errstr);
- return 0;
- }
- sptr = snmp_sess_session(sessp); /* <-- get the snmp_session pointer */
- /* Pass sptr to snmp_sess_error from here forward */
- ...
- /* Change the community name */
- free(sptr->community);
- sptr->community = strdup("public");
- sptr->community_len = strlen("public");
- ...
- if (0 == snmp_sess_send(sessp, pdu)) {
- snmp_sess_error(sessp, &liberr, &syserr, &errstr);
- printf("SNMP write error %s.n", errstr);
- free(errstr);
- return 0;
- }
- snmp_sess_close(sessp);
-
- Example 3. Differences Between Traditional API and Single API Usage
- 5a6
- > void *sessp; /* <-- an opaque pointer, not a struct pointer */
- 11,13c12,14
- < sptr = snmp_open(&Session);
- < if (sptr == NULL) {
- ---
- > sessp = snmp_sess_open(&Session);
- > if (sessp == NULL) {
- 19c20,22
- < /* Pass sptr to snmp_error from here forward */
- ---
- > sptr = snmp_sess_session(sessp); /* <-- get the snmp_session pointer */
- >
- > /* Pass sptr to snmp_sess_error from here forward */
- 26,27c29,30
- < if (0 == snmp_send(sptr, pdu)) {
- < snmp_error(sptr, &liberr, &syserr, &errstr);
- ---
- > if (0 == snmp_sess_send(sessp, pdu)) {
- > snmp_sess_error(sessp, &liberr, &syserr, &errstr);
- 33c36
- < snmp_close(sptr);
- ---
- > snmp_sess_close(sessp);
- Restrictions on Multi-threaded Use of the SNMP Library
- 1. Invoke SOCK_STARTUP or SOCK_CLEANUP from the main thread only.
- 2. The MIB parsing functions use global shared data and are not
- multi-thread safe when the MIB tree is under construction.
- Once the tree is built, the data can be safely referenced from
- any thread. There is no provision for freeing the MIB tree.
- Suggestion: Read the MIB files before an SNMP session is created.
- This can be accomplished by invoking snmp_sess_init from the main
- thread and discarding the buffer which is initialised.
- 3. Invoke the SNMPv2p initialisation before an SNMP session is created,
- for reasons similar to reading the MIB file.
- The SNMPv2p structures should be available to all SNMP sessions.
- CAUTION: These structures have not been tested in a multi-threaded
- application.
- 4. Sessions created using the Single API do not interact with other
- SNMP sessions. If you choose to use Traditional API calls, call
- them from a single thread. The Library cannot reference an SNMP
- session using both Traditional and Single API calls.
- 5. Using the callback mechanism for asynchronous response PDUs
- requires additional caution in a multi-threaded application.
- This means a callback function probably should probably not use
- Single API calls to further process the session.
- 6. Each call to snmp_sess_open() creates an IDS. Only a call to
- snmp_sess_close() releases the resources used by the IDS.