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