Revert changes with new dnscrypto-proxy.
[tomato.git] / release / src / router / snmp / README.thread
blob2b04e7533d392d0c762b66feb913fe1963946cac
1 Improved Error Reporting and Thread-Safe Use of the SNMP Library
3 There is a need in some environments to support multiple threads
4 in a single application.  The SNMP Library provides the Single Session
5 functions which support thread-safe operation when certain precautions
6 are taken.  This document describes the operation of the SNMP Library
7 with a focus on its session management functions.  The Traditional API
8 and the Single API functions are compared and contrasted.
9 A working understanding of the CMU or UCD SNMP Library
10 API is recommended to fully appreciate the concepts discussed.
11 The document ends with a list of restrictions for using the Single API
12 in a multi-threaded application.
14   ***** IMPORTANT ANNOUNCEMENT *****
15   To the point, no resource locks are applied within the SNMP Library.
16   The APDU encoding and some session management functions can be used
17   in thread-safe manners. The MIB file parsing is not thread-safe.
18   The Single Session API was made available in November 1998.
19   Existing applications use the Traditional API, which is not thread-safe.
20   The thread-safe considerations are discussed throughout this document.
22 The research and development of the Single Session API that I've completed
23 was wholly funded by my employer, Internet Security Systems, Inc.
24 and is distributed freely to the Internet community.
26 -Mike Slifcak, 23 April 1999
28 09 July 1999 Removed references to snmp_synch_setup and snmp_synch_reset
31 Availability
33 The Single Session API is integrated into the currently available
34 versions of the CMU SNMP library and the UC-Davis SNMP package.
36  ftp://ftp.net.cmu.edu/pub/snmp/cmu-snmp-V1.13.tar.gz and later
37   Read : snmp_sess_api.3, Changes.SingleSession
39  ftp://ucd-snmp.ucdavis.edu/ucd-snmp-3.6.tar.gz and later
40   Read : snmp_sess_api.3, README.thread (after version 3.6.1)
42 Both libraries work equally well in Windows NT and various
43 UNIX platforms.  Please read this document and refer to
44 the snmp_sess_api section 3 manual page.
46 Glossary of Terms
48 APDU    Application Protocol Data Unit
49 API     Application Programming Interface
50 CMU     Carnegie-Mellon University, Pittsburgh, PA.
51 Library The SNMP library; Both CMU and UCD versions are applicable.
52 Session Concept embodying the management of transacting SNMP APDUS.
53 SNMP    Simple Network Management Protocol
54 UCD     University of California at Davis, CA.
56 Introduction
58 The Library extends the UNIX file concept (open, close, read, write) to a Session.
59 Opening a Session binds a local socket to a well-known port and creates internal
60 structures to help with controlling the transaction of SNMP APDUs.  Closing a
61 Session releases the memory and system resources used for these purposes.
63 Since the mid-1980s, many SNMP applications have used the Traditional Session
64 API to transact SNMP APDUs between the local host and SNMP-enabled devices.
66   The Traditional Session API does not support multi-threaded applications:
68   1)  There are no resource locks to prevent exposing the Library's
69       global data resources to corruption in a multi-threaded application;
71   2)  The Traditional API functions that receive SNMP APDUs
72       do not provide an interface for one of many sessions;
74   3)  Errors discovered by the Library are communicated through global
75       data structures and are not associated with the session
76       in which the error occurred.
78   The Single Session API provides these capabilities:
80   1)  Manage a single SNMP session safely, in multi-threaded or
81       non-threaded applications, by avoiding access to data structures
82       that the Traditional Session API may share between Sessions;
84   2)  Associate errors with the session context for threaded
85       and non-threaded applications.
88 Contrasting and Comparing Traditional API and Single API
90 The Traditional API uses the struct snmp_session pointer returned
91 from snmp_open() to identify one SNMP session.  The Single API uses
92 the opaque pointer returned from snmp_sess_open() to identify one
93 SNMP session.
95    Helpful Hint : The Library copies the contents of the
96    structure which is input to snmp_open() and snmp_sess_open().
97    Once copied, changing that input structure's data
98    has no effect on the opened SNMP Session.
100 The Traditional API uses the snmp_error() function to identify any
101 library and system errors that occurred during the processing for
102 one SNMP session.   The Single API uses snmp_sess_error() for the
103 same purpose.
105 The Traditional API manages the private Sessions list structure;
106 adding to the list during snmp_open(), removing during snmp_close.
108 With few exceptions, the Traditional API calls the Single API
109 for each session that appears on the Sessions list.
111 The Traditional API reads from all Sessions on the Sessions list;
112 The Single API does not use the Sessions list.
113 The Single API can read from only one Session.
115    Helpful Hint :
116    This is the basis for thread-safe-ness of the Library.
117    There are no resource locks applied.
120 Using the Single API
122 A multi-threaded application that deploys the SNMP Library should
123 should complete all MIB file parsing before additional threads
124 are activated.  Drawing from the parsed contents of the MIB does
125 not incur any data corruption exposure once the internal MIB structures
126 are initialised.
128 The application may create threads such that a single thread may manage
129 a single SNMP session.  The thread should call snmp_sess_init()
130 to prepare a struct snmp_session structure.  The thread can adjust
131 session parameters such as the remote UDP port or the local UDP port,
132 which must be set prior to invoking snmp_sess_open().
134 The first call to snmp_sess_init() initialises the SNMP Library,
135 including the MIB parse trees, before any SNMP sessions are created.
136 Applications that call snmp_sess_init() do not need to read MIBs
137 nor setup environment variables to utilize the Library.
139 After the struct snmp_session is setup, the thread must call
140 snmp_sess_open() to create an SNMP session.  If at any time
141 the thread must change the Session configuration,
142 snmp_sess_session() returns the pointer to the internal configuration
143 structure (a struct snmp_session, copied from snmp_sess_open).
144 The thread can adjust parameters such as the session timeout
145 or the community string with this returned struct snmp_session pointer.
146 Changes to the remote or local port values have no effect on an opened Session.
148 The thread can build PDUs and bind variables to PDUs, as it performs its duties.
149 The thread then calls snmp_sess_send() or snmp_sess_async_send() to build and send
150 an SNMP APDU to the remote device. If a Get-Response-PDU is expected, the thread
151 should call snmp_sess_synch_response() instead.
153 When the thread is finished using the session, it must free the resources
154 that the Library used to manage the session.
155 Finally, the thread must call snmp_sess_close() to end the Session.
157 Snmp_sess_init(), snmp_open(), and snmp_sess_open()
158 must use the same calling parameter for a given Session.
159 Other methods should use only the returned parameter from
160 snmp_open() and snmp_sess_open() to access the opened SNMP Session.
163 Error Processing
165 Two calls were added : snmp_error() and snmp_sess_error() return the
166 "errno" and "snmp_errno" values from the per session data, and a string
167 that describes the errors that they represent.  The string must be freed
168 by the caller.
170 Use snmp_error() to process failures after Traditional API calls,
171 or snmp_sess_error() to process failure after Single API calls.
172 In the case where an SNMP session could not be opened,
173 call snmp_error() using the struct snmp_session supplied to either snmp_open()
174 or snmp_sess_open().
177 The following variables and functions are obsolete and may create problems
178 in a multi-threaded application :
180   int    snmp_errno
181   char * snmp_detail
182   snmp_set_detail()
183   snmp_api_errstring()
186 Function Summary
188 The functions in the following table are functionally equivalent,
189 with the exception of these behaviors:
190 - The Traditional API manages many sessions
191 - The Traditional API passes a struct snmp_session pointer,
192        and touches the Sessions list
193 - The Single API manages only one session
194 - The Single API passes an opaque pointer, and does not use Sessions list
196   Traditional        Single                    Comment
197   ===========        ==============            =======
198   snmp_sess_init     snmp_sess_init            Call before either open
199   snmp_open          snmp_sess_open            Single not on Sessions list
200                      snmp_sess_session         Exposes snmp_session pointer
201   snmp_send          snmp_sess_send            Send one APDU
202   snmp_async_send    snmp_sess_async_send      Send one APDU with callback
203   snmp_select_info   snmp_sess_select_info     Which session(s) have input
204   snmp_read          snmp_sess_read            Read APDUs
205   snmp_timeout       snmp_sess_timeout         Check for timeout
206   snmp_close         snmp_sess_close           Single not on Sessions list
207  snmp_synch_response snmp_sess_synch_response  Send/receive one APDU
208   snmp_error         snmp_sess_error           Get library,system errno
211 Example 1 : Traditional API use.
213     #include "snmp_api.h"
214       ...
215       int liberr, syserr;
216       char *errstr;
217       struct snmp_session Session, *sptr;
218       ...
219       snmp_sess_init(&Session);
220       Session.peername = "foo.bar.net";
221       sptr = snmp_open(&Session);
222       if (sptr == NULL) {
223           /* Error codes found in open calling argument */
224           snmp_error(&Session, &liberr, &syserr, &errstr);
225           printf("SNMP create error %s.\n", errstr);
226           free(errstr);
227           return 0;
228       }
229       /* Pass sptr to snmp_error from here forward */
230       ...
231       /* Change the community name */
232       free(sptr->community);
233       sptr->community = strdup("public");
234       sptr->community_len = strlen("public");
235       ...
236       if (0 == snmp_send(sptr, pdu)) {
237           snmp_error(sptr, &liberr, &syserr, &errstr);
238           printf("SNMP write error %s.\n", errstr);
239           free(errstr);
240           return 0;
241       }
242       snmp_close(sptr);
245 Example 2 : Single API use.
247     #include "snmp_api.h"
248       ...
249       int liberr, syserr;
250       char *errstr;
251       void *sessp;  /* <-- an opaque pointer, not a struct pointer */
252       struct snmp_session Session, *sptr;
253       ...
254       snmp_sess_init(&Session);
255       Session.peername = "foo.bar.net";
256       sessp = snmp_sess_open(&Session);
257       if (sessp == NULL) {
258           /* Error codes found in open calling argument */
259           snmp_error(&Session, &liberr, &syserr, &errstr);
260           printf("SNMP create error %s.\n", errstr);
261           free(errstr);
262           return 0;
263       }
264       sptr = snmp_sess_session(sessp); /* <-- get the snmp_session pointer */
266       /* Pass sptr to snmp_sess_error from here forward */
267       ...
268       /* Change the community name */
269       free(sptr->community);
270       sptr->community = strdup("public");
271       sptr->community_len = strlen("public");
272       ...
273       if (0 == snmp_sess_send(sessp, pdu)) {
274           snmp_sess_error(sessp, &liberr, &syserr, &errstr);
275           printf("SNMP write error %s.\n", errstr);
276           free(errstr);
277           return 0;
278       }
279       snmp_sess_close(sessp);
281 Example 3. Differences Between Traditional API and Single API Usage
283 >       void *sessp;  /* <-- an opaque pointer, not a struct pointer */
284 11,13c12,14
285 <       sptr = snmp_open(&Session);
286 <       if (sptr == NULL) {
288 >       sessp = snmp_sess_open(&Session);
289 >       if (sessp == NULL) {
290 19c20,22
291 <       /* Pass sptr to snmp_error from here forward */
293 >       sptr = snmp_sess_session(sessp); /* <-- get the snmp_session pointer */
295 >       /* Pass sptr to snmp_sess_error from here forward */
296 26,27c29,30
297 <       if (0 == snmp_send(sptr, pdu)) {
298 <           snmp_error(sptr, &liberr, &syserr, &errstr);
300 >       if (0 == snmp_sess_send(sessp, pdu)) {
301 >           snmp_sess_error(sessp, &liberr, &syserr, &errstr);
302 33c36
303 <       snmp_close(sptr);
305 >       snmp_sess_close(sessp);
308 Restrictions on Multi-threaded Use of the SNMP Library
310   1. Invoke SOCK_STARTUP or SOCK_CLEANUP from the main thread only.
312   2. The MIB parsing functions use global shared data and are not
313      multi-thread safe when the MIB tree is under construction.
314      Once the tree is built, the data can be safely referenced from
315      any thread.  There is no provision for freeing the MIB tree.
316      Suggestion: Read the MIB files before an SNMP session is created.
317      This can be accomplished by invoking snmp_sess_init from the main
318      thread and discarding the buffer which is initialised.
320   3. Invoke the SNMPv2p initialisation before an SNMP session is created,
321      for reasons similar to reading the MIB file.
322      The SNMPv2p structures should be available to all SNMP sessions.
323      CAUTION: These structures have not been tested in a multi-threaded
324      application.
326   4. Sessions created using the Single API do not interact with other
327      SNMP sessions.  If you choose to use Traditional API calls, call
328      them from a single thread.  The Library cannot reference an SNMP
329      session using both Traditional and Single API calls.
331   5. Using the callback mechanism for asynchronous response PDUs
332      requires additional caution in a multi-threaded application.
333      This means a callback function probably should probably not use
334      Single API calls to further process the session.
336   6. Each call to snmp_sess_open() creates an IDS.  Only a call to
337      snmp_sess_close() releases the resources used by the IDS.