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