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