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