xref: /freebsd/contrib/bsnmp/lib/bsnmpagent.3 (revision 6af83ee0d2941d18880b6aaa2b4facd1d30c6106)
1.\"
2.\" Copyright (c) 2001-2003
3.\"	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4.\"	All rights reserved.
5.\"
6.\" Author: Harti Brandt <harti@freebsd.org>
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\"    notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\"    notice, this list of conditions and the following disclaimer in the
15.\"    documentation and/or other materials provided with the distribution.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20.\" ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27.\" SUCH DAMAGE.
28.\"
29.\" $Begemot: bsnmp/lib/bsnmpagent.3,v 1.6 2004/08/06 08:46:51 brandt Exp $
30.\"
31.Dd August 16, 2002
32.Dt bsnmpagent 3
33.Os
34.Sh NAME
35.Nm bsnmpagent
36.Nm snmp_depop_t ,
37.Nm snmp_op_t ,
38.Nm tree ,
39.Nm tree_size ,
40.Nm snmp_trace ,
41.Nm snmp_debug ,
42.Nm snmp_get ,
43.Nm snmp_getnext ,
44.Nm snmp_getbulk ,
45.Nm snmp_set ,
46.Nm snmp_make_errresp ,
47.Nm snmp_dep_lookup ,
48.Nm snmp_init_context ,
49.Nm snmp_dep_commit ,
50.Nm snmp_dep_rollback ,
51.Nm snmp_dep_finish
52.Nd "SNMP agent library"
53.Sh LIBRARY
54Begemot SNMP library
55.Pq libbsnmp, -lbsnmp
56.Sh SYNOPSIS
57.In asn1.h
58.In snmp.h
59.In snmpagent.h
60.Ft typedef int
61.Fn (*snmp_depop_t) "struct snmp_context *ctx" "struct snmp_dependency *dep" "enum snmp_depop op"
62.Ft typedef int
63.Fn (*snmp_op_t) "struct snmp_context *ctx" "struct snmp_value *val" "u_int len" "u_int idx" "enum snmp_op op"
64.Vt extern struct snmp_node *tree ;
65.Vt extern u_int tree_size ;
66.Vt extern u_int snmp_trace ;
67.Vt extern void (*snmp_debug)(const char *fmt, ...) ;
68.Ft enum snmp_ret
69.Fn snmp_get "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
70.Ft enum snmp_ret
71.Fn snmp_getnext "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
72.Ft enum snmp_ret
73.Fn snmp_getbulk "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
74.Ft enum snmp_ret
75.Fn snmp_set "struct snmp_pdu *pdu" "struct asn_buf *resp_b" "struct snmp_pdu *resp" "void *data"
76.Ft enum snmp_ret
77.Fn snmp_make_errresp "const struct snmp_pdu *pdu" "struct asn_buf *req_b" "struct asn_buf *resp_b"
78.Ft struct snmp_dependency *
79.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"
80.Ft struct snmp_context *
81.Fn snmp_init_context "void"
82.Ft int
83.Fn snmp_dep_commit "struct snmp_context *ctx"
84.Ft int
85.Fn snmp_dep_rollback "struct snmp_context *ctx"
86.Ft void
87.Fn snmp_dep_finish "struct snmp_context *ctx"
88.Sh DESCRIPTION
89The SNMP library contains routines to easily build SNMP agent applications
90that use SNMP versions 1 or 2. Note, however, that it may be even easier to
91build an
92.Xr snmpd 1
93loadable module, that handles the new MIB (see
94.Xr snmpmod 3 ).
95.Pp
96Most of the agent routines operate on a global array that the describes the
97complete MIB served by the agent. This array is held in the two variables:
98.Bd -literal -offset indent
99extern struct snmp_node *tree;
100extern u_int  tree_size;
101.Ed
102.Pp
103The elements of the array are of type
104.Vt struct snmp_node :
105.Bd -literal -offset indent
106typedef int (*snmp_op_t)(struct snmp_context *, struct snmp_value *,
107    u_int, u_int, enum snmp_op);
108
109struct snmp_node {
110	struct asn_oid oid;
111	const char	*name;		/* name of the leaf */
112	enum snmp_node_type type;	/* type of this node */
113	enum snmp_syntax syntax;
114	snmp_op_t	op;
115	u_int		flags;
116	u_int32_t	index;		/* index data */
117	void		*data;		/* application data */
118	void		*tree_data;	/* application data */
119};
120.Ed
121.Pp
122The fields of this structure are described below.
123.Bl -tag -width "syntax"
124.It Va oid
125Base OID of the scalar or table column.
126.It Va name
127Name of this variable.
128.It Va type
129Type of this variable. One of:
130.Bd -literal -offset indent
131enum snmp_node_type {
132	SNMP_NODE_LEAF = 1,
133	SNMP_NODE_COLUMN
134};
135.Ed
136.It Va syntax
137The SNMP syntax of this variable.
138.It Va op
139The user supplied handler for this variable. The handler is called with
140the following arguments:
141.Bl -tag -width "ctx"
142.It Fa ctx
143A pointer to the context (see below).
144.Li NULL .
145.It Fa val
146The value to be set or retrieved. For GETNEXT and GETBULK operations the oid in
147this value is the current OID. The function (called in this case only for
148table rows) must find the lexically next existing OID within the same column and
149set the oid and value subfields accordingly. If the table column is exhausted the
150function must return
151.Li SNMP_ERR_NOSUCHNAME .
152For all other operations the oid in
153.Fa val
154is the oid to fetch or set.
155.It Fa len
156The length of the base oid without index.
157.It Fa idx
158For table columns this is the index expression from the node (see below).
159.It Fa op
160This is the operation to execute, one of:
161.Bd -literal -offset indent
162enum snmp_op {
163	SNMP_OP_GET 	= 1,
164	SNMP_OP_GETNEXT,
165	SNMP_OP_SET,
166	SNMP_OP_COMMIT,
167	SNMP_OP_ROLLBACK,
168};
169.Ed
170.El
171.Pp
172The user handler must return an appropiate SNMP v2 error code. If the original
173PDU was a version 1 PDU, the error code is mapped automatically.
174.It Va flags
175Currently only the flag
176.Li SNMP_NODE_CANSET is defined and set for nodes, that can be written or
177created.
178.It Va index
179This word describes the index for table columns. Each part of the index
180takes 4 bits starting at bit 4. Bits 0 to 3 hold the number of index parts.
181This arrangment allows for tables with up to seven indexes. Each bit group
182contains the syntax for the index part. There are a number of macros to
183help in parsing this field:
184.Bd -literal -offset indent
185#define SNMP_INDEXES_MAX	7
186#define SNMP_INDEX_SHIFT	4
187#define SNMP_INDEX_MASK	0xf
188#define SNMP_INDEX_COUNT(V)	((V) & SNMP_INDEX_MASK)
189#define SNMP_INDEX(V,I) \e
190	(((V) >> (((I) + 1) * SNMP_INDEX_SHIFT)) & \e
191	SNMP_INDEX_MASK)
192.Ed
193.It Va data
194This field may contain arbitrary data and is not used by the library.
195.El
196.Pp
197The easiest way to construct the node table is
198.Xr gensnmptree 1 .
199Note, that one must be careful when changing the tree while executing a SET
200operation. Consult the sources for
201.Xr snmpd 1 .
202.Pp
203The global variable
204.Va snmp_trace
205together with the function pointed to by
206.Va snmp_debug
207help in debugging the library and the agent.
208.Va snmp_trace is a bit mask with the following bits:
209.Bd -literal -offset indent
210enum {
211	SNMP_TRACE_GET,
212	SNMP_TRACE_GETNEXT,
213	SNMP_TRACE_SET,
214	SNMP_TRACE_DEPEND,
215	SNMP_TRACE_FIND,
216};
217.Ed
218.Pp
219Setting a bit to true causes the library to call
220.Fn snmp_debug
221in strategic places with a debug string. The library contains a default
222implementation for the debug function that prints a message to standard error.
223.Pp
224Many of the functions use a so called context:
225.Bd -literal -offset indent
226struct snmp_context {
227	u_int	var_index;
228	struct snmp_scratch *scratch;
229	struct snmp_dependency *dep;
230	void	*data;		/* user data */
231	enum snmp_ret code;	/* return code */
232};
233
234struct snmp_scratch {
235	void		*ptr1;
236	void		*ptr2;
237	u_int32_t	int1;
238	u_int32_t	int2;
239};
240.Ed
241.Pp
242The fields are used as follows:
243.Bl -tag -width ".It Va var_index"
244.It Va va_index
245For the node operation callback this is the
246index of the variable binding that should be returned if an error occures.
247Set by the library. In all other functions this is undefined.
248.It Va scratch
249For the node operation callback this is a pointer to a per variable binding
250scratch area that can be used to implement the commit and rollback. Set
251by the library.
252.It Va dep
253In the dependency callback function (see below) this is a pointer to the
254current dependency. Set by the library.
255.It Va data
256This is the
257.Fa data
258argument from the call to the library and is not used by the library.
259.El
260.Pp
261The next three functions execute different kinds of GET requests.
262The function
263.Fn snmp_get
264executes an SNMP GET operation, the function
265.Fn snmp_getnext
266executes an SNMP GETNEXT operation and the function
267.Fn snmp_getbulk
268executes an SNMP GETBULK operation.
269For all three functions the response PDU is constructed and encoded
270on the fly. If everything is ok, the response PDU is returned in
271.Fa resp
272and
273.Fa resp_b .
274The caller must call
275.Fn snmp_pdu_free
276to free the response PDU in this case. One of the following values may be
277returned:
278.Bl -tag -width ".It Li SNMP_RET_ERR"
279.It Li SNMP_RET_OK
280Operation successful, response PDU may be sent.
281.It Li SNMP_RET_IGN
282Operation failed, no response PDU constructed. Request is ignored.
283.It Li SNMP_RET_ERR
284Error in operation. The error code and index have been set in
285.Fa pdu .
286No response PDU has been constructed.
287The caller may construct an error response PDU via
288.Fn snmp_make_errresp .
289.El
290.Pp
291The function
292.Fn snmp_set
293executes an SNMP SET operation. The arguments are the same as for the previous
294three functions. The operation of this functions is, however, much more complex.
295.Pp
296The SET operation occures in several stages:
297.Bl -enum -offset indent
298.It
299For each binding search the corresponding nodes, check that the
300variable is writeable and the syntax is ok. The writeable check can be done
301only for scalars. For columns it must be done in the node's operation callback
302function.
303.It
304For each binding call the node's operation callback with function SNMP_OP_SET.
305The callback may create dependencies or finalizers (see below). For simple
306scalars the scratch area may be enough to handle commit and rollback, for
307interdependend table columns dependencies may be necessary.
308.It
309If the previous step fails at any point, the node's operation callback
310functions are called for all bindings for which SNMP_OP_SET was executed
311with SNMP_OP_ROLLBACK, in the opposite order. This allows all variables to
312undo the effect of the SET operation. After this all the dependencies
313are freed
314and the finalizers are executed with a fail flag of 1. Then the function
315returns to the caller with an appropriate error indication.
316.It
317If the SET step was successful for all bindings, the dependency callbacks
318are executed in the order in which the dependencies were created with an
319operation of SNMP_DEPOP_COMMIT. If any of the dependencies fails, all the
320committed dependencies are called again in the opposite order
321with SNMP_DEPOP_ROLLBACK. Than for all bindings from the last to the first
322the node's operation callback is called with SNMP_OP_ROLLBACK to undo
323the effect of SNMP_OP_SET. At the end the dependencies are freed
324and the finalizers are called with a fail flag
325of 1 and the function returns to the caller with an appropriate error indication.
326.It
327If the dependency commits were successful, for each binding the node's
328operation callback is called with SNMP_OP_COMMIT. Any error returned from
329the callbacks is ignored (an error message is generated via
330.Fn snmp_error ).
331.It
332Now the dependencies are freed and the finalizers are called
333with a fail flag of 0. For each dependency just before freeing it
334its callback is called with
335.Li SNMP_DEPOP_FINISH.
336Then the function returns
337.Li SNMP_ERR_OK .
338.El
339.Pp
340There are to mechanisms to help in complex SET operations: dependencies and
341finalizers. A dependency is used if several bindings depend on each other.
342A typical example is the creation of a conceptual row, which requires
343the setting of several columns to succeed. A dependency is identified by
344two OIDs. In the table case, the first oid is typically the table's base OID
345and the second one the index. Both of these can easily be generated from the
346variables OID with
347.Fn asn_slice_oid .
348The function
349.Fn snmp_dep_lookup
350tries to find a dependency based on these two OIDs and, if it cannot find one
351creates a new one. This means for the table example, that the function
352returns the same dependency for each of the columns of the same table row.
353This allows during the SNMP_OP_SET processing to collect all information
354about the row into the dependency. The arguments to
355.Fn snmp_dep_lookup
356are: the two OIDs to identify the dependency (they are copied into newly
357created dependencies), the size of the structure to allocate and
358the dependency callback.
359.Pp
360When all SNMP_OP_SET operations have succeeded the dependencies are executed.
361At this stage the dependency callback has all information about the given
362table row that was available in this SET PDU and can operate accordingly.
363.Pp
364It is guaranteed that each dependency callback is executed at minimum once
365- with an operation of
366.Li SNMP_OP_ROLLBACK .
367This ensures that all dynamically allocated resources in a callback can be
368freed correctly.
369.Pp
370The function
371.Fn snmp_make_errresp
372makes an error response if an operation has failed. It takes the original
373request PDU (it will look only on the error code and index fields), the
374buffer containing the original PDU and a buffer for the error PDU. It copies
375the bindings field from the original PDUs buffer directly to the response
376PDU and thus does not depend on the decodability of this field. It may return
377the same values as the operation functions.
378.Pp
379The next four functions allow some parts of the SET operation to be executed.
380This is only used in
381.Xr snmpd 1
382to implement the configuration as a single transaction.
383The function
384.Fn snmp_init_context
385creates and initializes a context.
386The function
387.Fn snmp_dep_commit
388executes SNMP_DEPOP_COMMIT for all dependencies in the context stopping at
389the first error.
390The function
391.Fn snmp_dep_rollback
392executes SNMP_DEPOP_ROLLBACK starting at the previous of the current
393dependency in the context.
394The function
395.Fn snmp_dep_finish
396executes SNMP_DEPOP_FINISH for all dependencies.
397.Sh DIAGNOSTICS
398If an error occures in any of the function an error indication as described
399above is returned. Additionally the functions may call snmp_error on unexected
400errors.
401.Sh SEE ALSO
402.Xr snmpd 1 ,
403.Xr gensnmptree 1 ,
404.Xr bsnmplib 3
405.Xr bsnmpclient 3 ,
406.Xr snmpmod 3
407.Sh STANDARDS
408This implementation conforms to the applicable IETF RFCs and ITU-T
409recommendations.
410.Sh AUTHORS
411.An Hartmut Brandt Aq harti@freebsd.org
412