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