2 .\" Copyright (c) 2004-2005
4 .\" All rights reserved.
5 .\" Copyright (c) 2001-2003
6 .\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
7 .\" All rights reserved.
9 .\" Author: Harti Brandt <harti@freebsd.org>
11 .\" Redistribution and use in source and binary forms, with or without
12 .\" modification, are permitted provided that the following conditions
14 .\" 1. Redistributions of source code must retain the above copyright
15 .\" notice, this list of conditions and the following disclaimer.
16 .\" 2. Redistributions in binary form must reproduce the above copyright
17 .\" notice, this list of conditions and the following disclaimer in the
18 .\" documentation and/or other materials provided with the distribution.
20 .\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 .\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 .\" $Begemot: bsnmp/lib/bsnmpagent.3,v 1.10 2005/10/04 08:46:49 brandt_h Exp $
49 .Nm snmp_make_errresp ,
51 .Nm snmp_init_context ,
53 .Nm snmp_dep_rollback ,
55 .Nd "SNMP agent library"
64 .Fn (*snmp_depop_t) "struct snmp_context *ctx" "struct snmp_dependency *dep" "enum snmp_depop op"
66 .Fn (*snmp_op_t) "struct snmp_context *ctx" "struct snmp_value *val" "u_int len" "u_int idx" "enum snmp_op op"
67 .Vt extern struct snmp_node *tree ;
68 .Vt extern u_int tree_size ;
69 .Vt extern u_int snmp_trace ;
70 .Vt extern void (*snmp_debug)(const char *fmt, ...) ;
72 .Fn snmp_get "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
74 .Fn snmp_getnext "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
76 .Fn snmp_getbulk "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
78 .Fn snmp_set "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
80 .Fn snmp_make_errresp "const struct snmp_pdu *pdu" "struct asn_buf *req_b" "struct asn_buf *resp_b"
81 .Ft struct snmp_dependency *
82 .Fn snmp_dep_lookup "struct snmp_context *ctx" "const struct asn_oid *base" "const struct asn_oid *idx" "size_t alloc" "snmp_depop_t func"
83 .Ft struct snmp_context *
84 .Fn snmp_init_context "void"
86 .Fn snmp_dep_commit "struct snmp_context *ctx"
88 .Fn snmp_dep_rollback "struct snmp_context *ctx"
90 .Fn snmp_dep_finish "struct snmp_context *ctx"
92 The SNMP library contains routines to easily build SNMP agent applications
93 that use SNMP versions 1 or 2.
94 Note, however, that it may be even easier to build an
96 loadable module, that handles the new MIB (see
99 Most of the agent routines operate on a global array that the describes the
100 complete MIB served by the agent.
101 This array is held in the two variables:
102 .Bd -literal -offset indent
103 extern struct snmp_node *tree;
104 extern u_int tree_size;
107 The elements of the array are of type
108 .Vt struct snmp_node :
109 .Bd -literal -offset indent
110 typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *,
111 u_int, u_int, enum snmp_op);
115 const char *name; /* name of the leaf */
116 enum snmp_node_type type; /* type of this node */
117 enum snmp_syntax syntax;
120 u_int32_t index; /* index data */
121 void *data; /* application data */
122 void *tree_data; /* application data */
126 The fields of this structure are described below.
127 .Bl -tag -width "syntax"
129 Base OID of the scalar or table column.
131 Name of this variable.
133 Type of this variable.
135 .Bd -literal -offset indent
136 enum snmp_node_type {
142 The SNMP syntax of this variable.
144 The user supplied handler for this variable.
145 The handler is called with the following arguments:
146 .Bl -tag -width "ctx"
148 A pointer to the context (see below).
151 The value to be set or retrieved.
152 For GETNEXT and GETBULK operations the oid in
153 this value is the current OID.
154 The function (called in this case only for
155 table rows) must find the lexically next existing OID within the same column and
156 set the oid and value subfields accordingly.
157 If the table column is exhausted the
159 .Li SNMP_ERR_NOSUCHNAME .
160 For all other operations the oid in
162 is the oid to fetch or set.
164 The length of the base oid without index.
166 For table columns this is the index expression from the node (see below).
168 This is the operation to execute, one of:
169 .Bd -literal -offset indent
180 The user handler must return an appropriate SNMP v2 error code.
182 PDU was a version 1 PDU, the error code is mapped automatically.
184 Currently only the flag
185 .Li SNMP_NODE_CANSET is defined and set for nodes, that can be written or
188 This word describes the index for table columns.
189 Each part of the index takes 4 bits starting at bit 4.
190 Bits 0 to 3 hold the number of index parts.
191 This arrangement allows for tables with up to seven indexes.
192 Each bit group contains the syntax for the index part.
193 There are a number of macros to help in parsing this field:
194 .Bd -literal -offset indent
195 #define SNMP_INDEXES_MAX 7
196 #define SNMP_INDEX_SHIFT 4
197 #define SNMP_INDEX_MASK 0xf
198 #define SNMP_INDEX_COUNT(V) ((V) & SNMP_INDEX_MASK)
199 #define SNMP_INDEX(V,I) \e
200 (((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) & \e
204 This field may contain arbitrary data and is not used by the library.
207 The easiest way to construct the node table is
209 Note, that one must be careful when changing the tree while executing a SET
211 Consult the sources for
216 together with the function pointed to by
218 help in debugging the library and the agent.
219 .Va snmp_trace is a bit mask with the following bits:
220 .Bd -literal -offset indent
230 Setting a bit to true causes the library to call
232 in strategic places with a debug string.
233 The library contains a default
234 implementation for the debug function that prints a message to standard error.
236 Many of the functions use a so called context:
237 .Bd -literal -offset indent
238 struct snmp_context {
240 struct snmp_scratch *scratch;
241 struct snmp_dependency *dep;
242 void *data; /* user data */
243 enum snmp_ret code; /* return code */
246 struct snmp_scratch {
254 The fields are used as follows:
255 .Bl -tag -width ".It Va var_index"
257 For the node operation callback this is the
258 index of the variable binding that should be returned if an error occurs.
260 In all other functions this is undefined.
262 For the node operation callback this is a pointer to a per variable binding
263 scratch area that can be used to implement the commit and rollback.
266 In the dependency callback function (see below) this is a pointer to the
272 argument from the call to the library and is not used by the library.
275 The next three functions execute different kinds of GET requests.
278 executes an SNMP GET operation, the function
280 executes an SNMP GETNEXT operation and the function
282 executes an SNMP GETBULK operation.
283 For all three functions the response PDU is constructed and encoded
285 If everything is ok, the response PDU is returned in
291 to free the response PDU in this case.
292 One of the following values may be returned:
293 .Bl -tag -width ".It Li SNMP_RET_ERR"
295 Operation successful, response PDU may be sent.
297 Operation failed, no response PDU constructed.
301 The error code and index have been set in
303 No response PDU has been constructed.
304 The caller may construct an error response PDU via
305 .Fn snmp_make_errresp .
310 executes an SNMP SET operation.
311 The arguments are the same as for the previous
313 The operation of this functions is, however, much more complex.
315 The SET operation occurs in several stages:
316 .Bl -enum -offset indent
318 For each binding search the corresponding nodes, check that the
319 variable is writeable and the syntax is ok.
320 The writeable check can be done only for scalars.
321 For columns it must be done in the node's operation callback function.
323 For each binding call the node's operation callback with function SNMP_OP_SET.
324 The callback may create dependencies or finalizers (see below).
326 scalars the scratch area may be enough to handle commit and rollback, for
327 interdependent table columns dependencies may be necessary.
329 If the previous step fails at any point, the node's operation callback
330 functions are called for all bindings for which SNMP_OP_SET was executed
331 with SNMP_OP_ROLLBACK, in the opposite order.
332 This allows all variables to undo the effect of the SET operation.
333 After this all the dependencies are freed
334 and the finalizers are executed with a fail flag of 1.
336 returns to the caller with an appropriate error indication.
338 If the SET step was successful for all bindings, the dependency callbacks
339 are executed in the order in which the dependencies were created with an
340 operation of SNMP_DEPOP_COMMIT.
341 If any of the dependencies fails, all the
342 committed dependencies are called again in the opposite order
343 with SNMP_DEPOP_ROLLBACK.
344 Than for all bindings from the last to the first
345 the node's operation callback is called with SNMP_OP_ROLLBACK to undo
346 the effect of SNMP_OP_SET.
347 At the end the dependencies are freed and the finalizers are called with
348 a fail flag of 1 and the function returns to the caller with an appropriate
351 If the dependency commits were successful, for each binding the node's
352 operation callback is called with SNMP_OP_COMMIT.
353 Any error returned from
354 the callbacks is ignored (an error message is generated via
357 Now the dependencies are freed and the finalizers are called
358 with a fail flag of 0.
359 For each dependency just before freeing it
360 its callback is called with
361 .Li SNMP_DEPOP_FINISH.
362 Then the function returns
366 There are to mechanisms to help in complex SET operations: dependencies and
368 A dependency is used if several bindings depend on each other.
369 A typical example is the creation of a conceptual row, which requires
370 the setting of several columns to succeed.
371 A dependency is identified by
373 In the table case, the first oid is typically the table's base OID
374 and the second one the index.
375 Both of these can easily be generated from the
380 tries to find a dependency based on these two OIDs and, if it cannot find one
382 This means for the table example, that the function
383 returns the same dependency for each of the columns of the same table row.
384 This allows during the SNMP_OP_SET processing to collect all information
385 about the row into the dependency.
388 are: the two OIDs to identify the dependency (they are copied into newly
389 created dependencies), the size of the structure to allocate and
390 the dependency callback.
392 When all SNMP_OP_SET operations have succeeded the dependencies are executed.
393 At this stage the dependency callback has all information about the given
394 table row that was available in this SET PDU and can operate accordingly.
396 It is guaranteed that each dependency callback is executed at minimum once
397 - with an operation of
398 .Li SNMP_OP_ROLLBACK .
399 This ensures that all dynamically allocated resources in a callback can be
403 .Fn snmp_make_errresp
404 makes an error response if an operation has failed.
405 It takes the original request PDU (it will look only on the error code and
406 index fields), the buffer containing the original PDU and a buffer for the
408 It copies the bindings field from the original PDUs buffer directly to
409 the response PDU and thus does not depend on the decodability of this field.
410 It may return the same values as the operation functions.
412 The next four functions allow some parts of the SET operation to be executed.
415 to implement the configuration as a single transaction.
417 .Fn snmp_init_context
418 creates and initializes a context.
421 executes SNMP_DEPOP_COMMIT for all dependencies in the context stopping at
424 .Fn snmp_dep_rollback
425 executes SNMP_DEPOP_ROLLBACK starting at the previous of the current
426 dependency in the context.
429 executes SNMP_DEPOP_FINISH for all dependencies.
431 If an error occurs in any of the function an error indication as described
433 Additionally the functions may call snmp_error on unexpected errors.
441 This implementation conforms to the applicable IETF RFCs and ITU-T
444 .An Hartmut Brandt Aq harti@freebsd.org