~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to README.thread

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
  ***** 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.
 
21
 
 
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.
 
25
 
 
26
-Mike Slifcak, 23 April 1999
 
27
 
 
28
09 July 1999 Removed references to snmp_synch_setup and snmp_synch_reset
 
29
 
 
30
 
 
31
Availability
 
32
 
 
33
The Single Session API is integrated into the currently available
 
34
versions of the CMU SNMP library and the UC-Davis SNMP package.
 
35
 
 
36
 ftp://ftp.net.cmu.edu/pub/snmp/cmu-snmp-V1.13.tar.gz and later
 
37
  Read : snmp_sess_api.3, Changes.SingleSession
 
38
 
 
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)
 
41
 
 
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.
 
45
 
 
46
Glossary of Terms
 
47
 
 
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.
 
55
 
 
56
Introduction
 
57
 
 
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.
 
62
 
 
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.
 
65
 
 
66
  The Traditional Session API does not support multi-threaded applications:
 
67
 
 
68
  1)  There are no resource locks to prevent exposing the Library's
 
69
      global data resources to corruption in a multi-threaded application;
 
70
 
 
71
  2)  The Traditional API functions that receive SNMP APDUs
 
72
      do not provide an interface for one of many sessions;
 
73
 
 
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.
 
77
 
 
78
  The Single Session API provides these capabilities:
 
79
 
 
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;
 
83
 
 
84
  2)  Associate errors with the session context for threaded
 
85
      and non-threaded applications.
 
86
 
 
87
 
 
88
Contrasting and Comparing Traditional API and Single API
 
89
 
 
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.
 
94
 
 
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.
 
99
 
 
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.
 
104
 
 
105
The Traditional API manages the private Sessions list structure;
 
106
adding to the list during snmp_open(), removing during snmp_close.
 
107
 
 
108
With few exceptions, the Traditional API calls the Single API
 
109
for each session that appears on the Sessions list.
 
110
 
 
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.
 
114
 
 
115
   Helpful Hint :
 
116
   This is the basis for thread-safe-ness of the Library.
 
117
   There are no resource locks applied.
 
118
 
 
119
 
 
120
Using the Single API
 
121
 
 
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.
 
127
 
 
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().
 
133
 
 
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.
 
138
 
 
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.
 
147
 
 
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.
 
152
 
 
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.
 
156
 
 
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.
 
161
 
 
162
 
 
163
Error Processing
 
164
 
 
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.
 
169
 
 
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().
 
175
 
 
176
 
 
177
The following variables and functions are obsolete and may create problems
 
178
in a multi-threaded application :
 
179
 
 
180
  int    snmp_errno
 
181
  char * snmp_detail
 
182
  snmp_set_detail()
 
183
  snmp_api_errstring()
 
184
 
 
185
 
 
186
Function Summary
 
187
 
 
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
 
195
 
 
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
 
209
 
 
210
 
 
211
Example 1 : Traditional API use.
 
212
 
 
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);
 
243
 
 
244
 
 
245
Example 2 : Single API use.
 
246
 
 
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 */
 
265
 
 
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);
 
280
 
 
281
Example 3. Differences Between Traditional API and Single API Usage
 
282
5a6
 
283
>       void *sessp;  /* <-- an opaque pointer, not a struct pointer */
 
284
11,13c12,14
 
285
<       sptr = snmp_open(&Session);
 
286
<       if (sptr == NULL) {
 
287
---
 
288
>       sessp = snmp_sess_open(&Session);
 
289
>       if (sessp == NULL) {
 
290
19c20,22
 
291
<       /* Pass sptr to snmp_error from here forward */
 
292
---
 
293
>       sptr = snmp_sess_session(sessp); /* <-- get the snmp_session pointer */
 
294
 
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);
 
299
---
 
300
>       if (0 == snmp_sess_send(sessp, pdu)) {
 
301
>           snmp_sess_error(sessp, &liberr, &syserr, &errstr);
 
302
33c36
 
303
<       snmp_close(sptr);
 
304
---
 
305
>       snmp_sess_close(sessp);
 
306
 
 
307
 
 
308
Restrictions on Multi-threaded Use of the SNMP Library
 
309
 
 
310
  1. Invoke SOCK_STARTUP or SOCK_CLEANUP from the main thread only.
 
311
 
 
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.
 
319
 
 
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.
 
325
 
 
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.
 
330
 
 
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.
 
335
 
 
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.
 
338