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