xref: /freebsd/contrib/bsnmp/lib/bsnmpclient.3 (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
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 of this software and documentation and use in source and
9.\" binary forms, with or without modification, are permitted provided that
10.\" the following conditions are met:
11.\"
12.\" 1. Redistributions of source code or documentation must retain the above
13.\"    copyright notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\" 3. Neither the name of the Institute nor the names of its contributors
18.\"    may be used to endorse or promote products derived from this software
19.\"    without specific prior written permission.
20.\"
21.\" THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS
22.\" AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24.\" FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
25.\" FRAUNHOFER FOKUS OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
26.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28.\" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32.\"
33.\" $Begemot: bsnmp/lib/bsnmpclient.3,v 1.6 2004/04/13 17:01:31 novo Exp $
34.\"
35.Dd August 15, 2002
36.Dt bsnmpclient 3
37.Os
38.Sh NAME
39.Nm snmp_client ,
40.Nm snmp_send_cb_f ,
41.Nm snmp_timeout_cb_f ,
42.Nm snmp_timeout_start_f ,
43.Nm snmp_timeout_stop_f ,
44.Nm snmp_open ,
45.Nm snmp_close ,
46.Nm snmp_pdu_create ,
47.Nm snmp_add_binding ,
48.Nm snmp_pdu_check ,
49.Nm snmp_pdu_send ,
50.Nm snmp_oid_append ,
51.Nm snmp_receive ,
52.Nm snmp_table_cb_f ,
53.Nm snmp_table_fetch ,
54.Nm snmp_table_fetch_async ,
55.Nm snmp_dialog
56.Nd "SNMP client library"
57.Sh LIBRARY
58Begemot SNMP library
59.Pq libbsnmp, -lbsnmp
60.Sh SYNOPSIS
61.In asn1.h
62.In snmp.h
63.In snmpclient.h
64.Ft typedef void
65.Fn (*snmp_send_cb_f) "struct snmp_pdu *req" "struct snmp_pdu *resp" "void *uarg"
66.Ft typedef void
67.Fn (*snmp_timeout_cb_f) "void *uarg"
68.Ft typedef void *
69.Fn (*snmp_timeout_start_f) "struct timeval *timeout" "snmp_timeout_cb_f callback" "void *uarg"
70.Ft typedef void
71.Fn (*snmp_timeout_stop_f) "void *timeout_id"
72.Vt extern struct snmp_client snmp_client ;
73.Ft void
74.Fn snmp_client_init "struct snmp_client *client"
75.Ft int
76.Fn snmp_client_set_host "struct snmp_client *client" "const char *host"
77.Ft int
78.Fn snmp_client_set_port "struct snmp_client *client" "const char *port"
79.Ft int
80.Fn snmp_open "const char *host" "const char *port" "const char *read_community" "const char *write_community"
81.Ft void
82.Fn snmp_close "void"
83.Ft void
84.Fn snmp_pdu_create "struct snmp_pdu *pdu" "u_int op"
85.Ft int
86.Fn snmp_add_binding "struct snmp_pdu *pdu" "..."
87.Ft int
88.Fn snmp_pdu_check "const struct snmp_pdu *req" "const struct snmp_pdu *resp"
89.Ft int32_t
90.Fn snmp_pdu_send "struct snmp_pdu *pdu" "snmp_send_cb_f func" "void *uarg"
91.Ft int
92.Fn snmp_oid_append "struct asn_oid *oid" "const char *fmt" "..."
93.Ft int
94.Fn snmp_receive "int blocking"
95.Ft typedef void
96.Fn (*snmp_table_cb_f) "void *list" "void *arg" "int res"
97.Ft int
98.Fn snmp_table_fetch "const struct snmp_table *descr" "void *list"
99.Ft int
100.Fn snmp_table_fetch_async "const struct snmp_table *descr" "void *list" "snmp_table_cb_f callback" "void *uarg"
101.Ft int
102.Fn snmp_dialog "struct snmp_pdu *req" "struct snmp_pdu *resp"
103.Sh DESCRIPTION
104The SNMP library contains routines to easily build SNMP client applications
105that use SNMP versions 1 or 2. Most of the routines use a
106.Vt struct snmp_client :
107.Bd -literal -offset indent
108struct snmp_client {
109	enum snmp_version version;
110	int	trans;	/* transport type to use */
111
112	/* these two are read-only for the application */
113	char	*cport;	/* port number as string */
114	char	*chost;	/* host name or IP address as string */
115
116	char	read_community[SNMP_COMMUNITY_MAXLEN + 1];
117	char	write_community[SNMP_COMMUNITY_MAXLEN + 1];
118
119	struct timeval	timeout;
120	u_int	retries;
121
122	int	dump_pdus;
123
124	size_t	txbuflen;
125	size_t	rxbuflen;
126
127	int	fd;
128
129	int32_t	next_reqid;
130	int32_t	max_reqid;
131	int32_t	min_reqid;
132
133	char	error[SNMP_STRERROR_LEN];
134
135	snmp_timeout_start_f timeout_start;
136	snmp_timeout_stop_f timeout_stop;
137
138	/* private */
139	char	local_path[sizeof(SNMP_LOCAL_PATH)];
140};
141.Ed
142.Pp
143The fields of this structure are described below.
144.Bl -tag -width "timeout_start"
145.It Va version
146This is the version of SNMP to use. See
147.Xr bsnmplib 3
148for applicable values. The default version is
149.Li SNMP_V2c .
150.It Va trans
151If this is
152.Dv SNMP_TRANS_LOC_DGRAM
153a local datagram socket is used.
154If it is
155.Dv SNMP_TRANS_LOC_STREAM
156a local stream socket is used.
157For
158.Dv SNMP_TRANS_UDP
159a UDP socket is created.
160It uses the
161.Va chost
162field as the path to the server's socket for local sockets.
163.It Va cport
164The SNMP agent's UDP port number. This may be a symbolic port number (from
165.Pa /etc/services
166or a numeric port number. If this field is
167.Li NULL
168(the default) the standard SNMP port is used. This field should not be changed
169directly but rather by calling
170.Fn snmp_client_set_port .
171.It Va chost
172The SNMP agent's host name, IP address or
173.Ux
174domain socket path name.
175If this is
176.Li NULL
177(the default)
178.Li localhost
179is assumed. This field should not be changed directly but rather through
180calling
181.Fn snmp_client_set_host .
182.It Va read_community
183This is the community name to be used for all requests except SET requests.
184The default is
185.Sq public .
186.It Va write_community
187The community name to be used for SET requests. The default is
188.Sq private .
189.It Va timeout
190The maximum time to wait for responses to requests. If the time elapses, the
191request is resent up to
192.Va retries
193times. The default is 3 seconds.
194.It Va retries
195Number of times a request PDU is to be resent. If set to 0, the request is
196sent only once. The default is 3 retransmissions.
197.It Va dump_pdus
198If set to a non-zero value all received and sent PDUs are dumped via
199.Xr snmp_pdu_dump 3 .
200The default is not to dump PDUs.
201.It Va txbuflen
202The encoding buffer size to be allocated for transmitted PDUs. The default is
20310000 octets.
204.It Va rxbuflen
205The decoding buffer size to be allocated for received PDUs. This is the size
206of the maximum PDU that can be received. The default is 10000 octets.
207.It Va fd
208After calling
209.Fn snmp_open
210this is the file socket file descriptor used for sending and receiving PDUs.
211.It Va next_reqid
212The request id of the next PDU to send. Used internal by the library.
213.It Va max_reqid
214The maximum request id to use for outging PDUs. The default is
215.Li INT32_MAX .
216.It Va min_reqid
217The minimum request id to use for outgoing PDUs. Request ids are allocated
218linerily starting at
219.Va min_reqid
220up to
221.Va max_reqid .
222.It Va error
223If an error happens, this field is set to a printable string describing the
224error.
225.It Va timeout_start
226This field must point to a function setting up a one shot timeout. After the
227timeout has elapsed, the given callback function must be called with the
228user argument. The
229.Fn timeout_start
230function must return a
231.Vt void *
232identifying the timeout.
233.It Va timeout_stop
234This field must be set to a function that stops a running timeout. The function
235will be called with the return value of the corresponding
236.Fn timeout_start
237function.
238.It Va local_path
239If in local socket mode, the name of the clients socket. Not needed by the
240application.
241.El
242.Pp
243In the current implementation there is a global variable
244.Bd -unfilled -offset indent
245.Vt extern struct snmp_client snmp_client ;
246.Ed
247.Pp
248that is used by all the library functions. The first call into the library must
249be a call to
250.Fn snmp_client_init
251to initialize this global variable to the default values.
252After this call and before calling
253.Fn snmp_open
254the fields of the variable may be modified by the user.
255The modification of the
256.Va chost
257and
258.Va cport
259fields should be done only via the functions
260.Fn snmp_client_set_host
261and
262.Fn snmp_client_set_port .
263.Pp
264The function
265.Fn snmp_open
266creates a UDP or
267.Ux
268domain socket and connects it to the agent's IP address and port.
269If any of the arguments of the call is not
270.Li NULL
271the corresponding field in the global
272.Va snmp_client
273is set from the argument. Otherwise the values that are already in that variable
274are used.
275The function
276.Fn snmp_close
277closes the socket, stops all timeouts and frees all dynamically allocated
278resources.
279.Pp
280The next three functions are used to create request PDUs. The function
281.Fn snmp_pdu_create
282initializes a PDU of type
283.Va op .
284It does not allocate space for the PDU itself. This is the responsibility of
285the caller.
286.Fn snmp_add_binding
287adds bindings to the PDU and returns the (zero based) index of the first new
288binding. The arguments are pairs of pointer to the OIDs and syntax constants,
289terminated by a NULL. The call
290.Bd -literal -offset indent
291snmp_add_binding(&pdu,
292    &oid1, SNMP_SYNTAX_INTEGER,
293    &oid2, SNMP_SYNTAX_OCTETSTRING,
294    NULL);
295.Ed
296.Pp
297adds two new bindings to the PDU and returns the index of the first one.
298It is the responsibility of the caller to set the value part of the binding
299if neccesary. The functions returns -1 if the maximum number of bindings
300is exhausted.
301The function
302.Fn snmp_oid_append
303can be used to construct variable OIDs for requests. It takes a pointer
304to an
305.Vt struct asn_oid
306that is to be constructed, a format string, and a number of arguments
307the type of which depends on the format string. The format string is interpreted
308character by character in the following way:
309.Bl -tag -width ".It Li ( Va N Ns Li )"
310.It Li i
311This format expects an argument of type
312.Vt asn_subid_t
313and appends this as a single integer to the OID.
314.It Li a
315This format expects an argument of type
316.Vt struct in_addr
317and appends to four parts of the IP address to the OID.
318.It Li s
319This format expects an argument of type
320.Vt const char *
321and appends the length of the string (as computed by
322.Xr strlen 3 )
323and each of the characters in the string to the OID.
324.It Li ( Va N Ns Li )
325This format expects no argument.
326.Va N
327must be a decimal number and is stored into an internal variable
328.Va size .
329.It Li b
330This format expects an argument of type
331.Vt const char *
332and appends
333.Va size
334characters from the string to the OID. The string may contain
335.Li NUL
336characters.
337.It Li c
338This format expects two arguments: one of type
339.Vt size_t
340and one of type
341.Vt const u_char * .
342The first argument gives the number of bytes to append to the OID from the string
343pointed to by the second argument.
344.El
345.Pp
346The function
347.Fn snmp_pdu_check
348may be used to check a response PDU. A number of checks are performed
349(error code, equal number of bindings, syntaxes and values for SET PDUs).
350The function returns +1 if everything is ok, 0 if a NOSUCHNAME or similar
351error was detected, -1 if the response PDU had fatal errors
352and -2 if
353.Fa resp
354is
355.Li NULL
356(a timeout occured).
357.Pp
358The function
359.Fn snmp_pdu_send
360encodes and sends the given PDU. It records the PDU together with the callback
361and user pointers in an internal list and arranges for retransmission if no
362response is received. When a response is received or the retransmission count
363is exceeded the callback
364.Fa func
365is called with the orignal request PDU, the response PDU and the user argument
366.Fa uarg .
367If the retransmit count is exceeded,
368.Fa func
369is called with the original request PDU, the reponse pointer set to
370.Li NULL
371and the user argument
372.Fa uarg .
373The caller should not free the request PDU until the callback function is
374called. The callback function must free the request PDU and the response
375PDU (if not
376.Li NULL ).
377.Pp
378The function
379.Fn snmp_receive
380tries to receive a PDU. If the argument is zero, the function polls to see
381whether a packet is available, if the argument is non-zero, the function blocks
382until the next packet is received. The packet is delivered via the usual callback
383mechanism (non-response packets are silently dropped).
384The function returns 0, if a packet was received and successfully dispatched,
385-1 if an error occured or no packet was available (in polling mode).
386.Pp
387The next two functions are used to retrieve tables from SNMP agents. The use
388the following input structure, that describes the table:
389.Bd -literal -offset indent
390struct snmp_table {
391	struct asn_oid		table;
392	struct asn_oid		last_change;
393	u_int			max_iter;
394	size_t			entry_size;
395	u_int			index_size;
396	u_int64_t		req_mask;
397
398	struct snmp_table_entry {
399	    asn_subid_t		subid;
400	    enum snmp_syntax	syntax;
401	    off_t		offset;
402	}			entries[];
403};
404.Ed
405.Pp
406The fields of this structure have the following meaning:
407.Bl -tag -width "last_change"
408.It Va table
409This is the base OID of the table.
410.It Va last_change
411Some tables have a scalar variable of type TIMETICKS attached to them,
412that holds the time when the table was last changed. This OID should be
413the OID of this variable (without the \&.0 index). When the table is retrieved
414with multiple GET requests, and the variable changes between two request,
415the table fetch is restarted.
416.It Va max_iter
417Maximum number of tries to fetch the table.
418.It Va entry_size
419The table fetching routines return a list of structure one for each table
420row. This variable is the size of one structure and used to
421.Xr malloc 3
422the structure.
423.It Va index_size
424This is the number of index columns in the table.
425.It Va req_mask
426This is a bit mask with a 1 for each table column that is required.
427Bit 0 corresponds to the first element (index 0) in the array
428.Va entries ,
429bit 1 to the second (index 1) and so on. SNMP tables may be sparse. For sparse
430columns the bit should not be set. If the bit for a given column is set and
431the column value cannot be retrieved for a given row, the table fetch is
432restarted assuming that the table is currently beeing modified by the agent.
433The bits for the index columns are ignored.
434.It Va entries
435This is a variable sized array of column descriptors. This array is terminated
436by an element with syntax
437.Li SNMP_SYNTAX_NULL .
438The first
439.Va index_size
440elements describe all the index columns of the table, the rest are normal
441columns. If for a the column at
442.Ql entries[N]
443the expression
444.Ql req_mask & (1 << N)
445yields true, the column is considered a required column.
446The fields of this the array elements have the following meaning:
447.Bl -tag -width "syntax"
448.It Va subid
449This is the OID subid of the column. This is ignored for index entries. Index
450entries are decoded according to the
451.Va syntax
452field.
453.It Va syntax
454This is the syntax of the column or index. A syntax of
455.Li SNMP_SYNTAX_NULL
456terminates the array.
457.It Va offset
458This is the starting offset of the value of the column in the return structures.
459This field can be set with the ISO-C
460.Fn offsetof
461macro.
462.El
463.El
464.Pp
465Both table fetching functions return TAILQ (see
466.Xr queue 3 )
467of structures--one for each table row. These structures must start with a
468.Fn TAILQ_ENTRY
469and a
470.Vt u_int64_t
471and are allocated via
472.Xr malloc 3 .
473The
474.Fa list
475argument of the table functions must point to a
476.Fn TAILQ_HEAD .
477The
478.Vt u_int64_t
479fields, usually called
480.Va found
481is used to indicate which of the columns have been found for the given
482row. It is encoded like the
483.Fa req_mask
484field.
485.Pp
486The function
487.Fn snmp_table_fetch
488synchronuosly fetches the given table. If everything is ok 0 is returned.
489Otherwise the function returns -1 and sets an appropriate error string.
490The function
491.Fn snmp_table_fetch_async
492fetches the tables asynchronuosly. If either the entire table is fetch, or
493an error occures the callback function
494.Fa callback
495is called with the callers arguments
496.Fa list
497and
498.Fa uarg
499and a parameter that is either 0 if the table was fetched, or
500-1 if there was an error. The function itself returns -1 if it could not
501initialize fetching of the table.
502.Pp
503The following table description is used to fetch the ATM interface table:
504.Bd -literal -offset indent
505/*
506 * ATM interface table
507 */
508struct atmif {
509	TAILQ_ENTRY(atmif) link;
510	u_int64_t	found;
511	int32_t		index;
512	u_char		*ifname;
513	size_t		ifnamelen;
514	u_int32_t	node_id;
515	u_int32_t	pcr;
516	int32_t		media;
517	u_int32_t	vpi_bits;
518	u_int32_t	vci_bits;
519	u_int32_t	max_vpcs;
520	u_int32_t	max_vccs;
521	u_char		*esi;
522	size_t		esilen;
523	int32_t		carrier;
524};
525TAILQ_HEAD(atmif_list, atmif);
526
527/* list of all ATM interfaces */
528struct atmif_list atmif_list;
529
530static const struct snmp_table atmif_table = {
531	OIDX_begemotAtmIfTable,
532	OIDX_begemotAtmIfTableLastChange, 2,
533	sizeof(struct atmif),
534	1, 0x7ffULL,
535	{
536	  { 0, SNMP_SYNTAX_INTEGER,
537		offsetof(struct atmif, index) },
538	  { 1, SNMP_SYNTAX_OCTETSTRING,
539		offsetof(struct atmif, ifname) },
540	  { 2, SNMP_SYNTAX_GAUGE,
541		offsetof(struct atmif, node_id) },
542	  { 3, SNMP_SYNTAX_GAUGE,
543		offsetof(struct atmif, pcr) },
544	  { 4, SNMP_SYNTAX_INTEGER,
545		offsetof(struct atmif, media) },
546	  { 5, SNMP_SYNTAX_GAUGE,
547		offsetof(struct atmif, vpi_bits) },
548	  { 6, SNMP_SYNTAX_GAUGE,
549		offsetof(struct atmif, vci_bits) },
550	  { 7, SNMP_SYNTAX_GAUGE,
551		offsetof(struct atmif, max_vpcs) },
552	  { 8, SNMP_SYNTAX_GAUGE,
553		offsetof(struct atmif, max_vccs) },
554	  { 9, SNMP_SYNTAX_OCTETSTRING,
555		offsetof(struct atmif, esi) },
556	  { 10, SNMP_SYNTAX_INTEGER,
557		offsetof(struct atmif, carrier) },
558          { 0, SNMP_SYNTAX_NULL, 0 }
559	}
560};
561
562\&...
563	if (snmp_table_fetch(&atmif_table, &atmif_list) != 0)
564		errx(1, "AtmIf table: %s", snmp_client.error);
565\&...
566.Ed
567.Pp
568The function
569.Fn snmp_dialog
570is used to execute a synchonuous dialog with the agent. The request PDU
571.Fa req
572is sent and the function blocks until the response PDU is received. Note,
573that asynchonuous receives are handled (i.e. callback functions of other send
574calls or table fetches may be called while in the function). The response
575PDU is returned in
576.Fa resp .
577If no reponse could be received after all timeouts and retries, the function
578returns -1. If a response was received 0 is returned.
579.Sh DIAGNOSTICS
580If an error occures in any of the function an error indication as described
581above is returned. Additionally the function sets a printable error string
582in the
583.Va error
584filed of
585.Va snmp_client .
586.Sh SEE ALSO
587.Xr snmpd 1 ,
588.Xr gensnmptree 1 ,
589.Xr bsnmplib 3
590.Xr bsnmpagent 3
591.Sh STANDARDS
592This implementation conforms to the applicable IETF RFCs and ITU-T
593recommendations.
594.Sh AUTHORS
595.An Hartmut Brandt Aq harti@freebsd.org
596.An Kendy Kutzner Aq kutzner@fokus.gmd.de
597