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