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