OSDN Git Service

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