1.\" $OpenBSD: agentx.3,v 1.7 2021/03/12 05:18:00 jsg Exp $ 2.\" 3.\" Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org> 4.\" 5.\" Permission to use, copy, modify, and distribute this software for any 6.\" purpose with or without fee is hereby granted, provided that the above 7.\" copyright notice and this permission notice appear in all copies. 8.\" 9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" 17.Dd $Mdocdate: March 12 2021 $ 18.Dt AGENTX 3 19.Os 20.Sh NAME 21.Nm agentx_log_fatal , 22.Nm agentx_log_warn , 23.Nm agentx_log_info , 24.Nm agentx_log_debug , 25.Nm agentx , 26.Nm agentx_connect , 27.Nm agentx_read , 28.Nm agentx_write , 29.Nm agentx_wantwrite , 30.Nm agentx_free , 31.Nm agentx_session , 32.Nm agentx_session_free , 33.Nm agentx_context , 34.Nm agentx_context_object_find , 35.Nm agentx_context_object_nfind , 36.Nm agentx_context_uptime , 37.Nm agentx_context_free , 38.Nm agentx_region , 39.Nm agentx_region_free , 40.Nm agentx_agentcaps , 41.Nm agentx_agentcaps_free , 42.Nm agentx_index_integer_new , 43.Nm agentx_index_integer_any , 44.Nm agentx_index_integer_value , 45.Nm agentx_index_integer_dynamic , 46.Nm agentx_index_string_dynamic , 47.Nm agentx_index_nstring_dynamic , 48.Nm agentx_index_oid_dynamic , 49.Nm agentx_index_noid_dynamic , 50.Nm agentx_index_ipaddress_dynamic , 51.Nm agentx_index_free , 52.Nm agentx_object , 53.Nm agentx_object_free , 54.Nm agentx_varbind_integer , 55.Nm agentx_varbind_string , 56.Nm agentx_varbind_nstring , 57.Nm agentx_varbind_printf , 58.Nm agentx_varbind_null , 59.Nm agentx_varbind_oid , 60.Nm agentx_varbind_object , 61.Nm agentx_varbind_index , 62.Nm agentx_varbind_ipaddress , 63.Nm agentx_varbind_counter32 , 64.Nm agentx_varbind_gauge32 , 65.Nm agentx_varbind_unsigned32 , 66.Nm agentx_varbind_timeticks , 67.Nm agentx_varbind_opaque , 68.Nm agentx_varbind_counter64 , 69.Nm agentx_varbind_notfound , 70.Nm agentx_varbind_error , 71.Nm agentx_varbind_request , 72.Nm agentx_varbind_get_index_integer , 73.Nm agentx_varbind_get_index_string , 74.Nm agentx_varbind_get_index_oid , 75.Nm agentx_varbind_get_index_ipaddress , 76.Nm agentx_varbind_set_index_integer , 77.Nm agentx_varbind_set_index_string , 78.Nm agentx_varbind_set_index_nstring , 79.Nm agentx_varbind_set_index_oid , 80.Nm agentx_varbind_set_index_object , 81.Nm agentx_varbind_set_index_ipaddress 82.Nd manage an interface to an agentx master 83.Sh SYNOPSIS 84.In agentx.h 85.Ft extern void 86.Fn (*agentx_log_fatal) "const char *fmt" ... 87.Ft extern void 88.Fn (*agentx_log_warn) "const char *fmt" ... 89.Ft extern void 90.Fn (*agentx_log_info) "const char *fmt" ... 91.Ft extern void 92.Fn (*agentx_log_debug) "const char *fmt" ... 93.Ft struct agentx * 94.Fn agentx "void (*nofd)(struct agentx *, void *, int)" "void *cookie" 95.Ft void 96.Fn agentx_connect "struct agentx *sa" "int fd" 97.Ft void 98.Fn agentx_read "struct agentx *sa" 99.Ft void 100.Fn agentx_write "struct agentx *sa" 101.Ft extern void 102.Fn (*agentx_wantwrite) "struct agentx *sa" "int fd" 103.Ft void 104.Fn agentx_free "struct agentx *sa" 105.Ft struct agentx_session * 106.Fo agentx_session 107.Fa "struct agentx *sa" "uint32_t oid[]" "size_t oidlen" 108.Fa "const char *descr" "uint8_t timeout" 109.Fc 110.Ft void 111.Fn agentx_session_free "struct agentx_session *sas" 112.Ft struct agentx_context * 113.Fn agentx_context "struct agentx_session *sas" "const char *name" 114.Ft struct agentx_object * 115.Fo agentx_context_object_find 116.Fa "struct agentx_context *sac" "const uint32_t oid[]" "size_t oidlen" 117.Fa "int active" "int instance" 118.Fc 119.Ft struct agentx_object * 120.Fo agentx_context_object_nfind 121.Fa "struct agentx_context *" "const uint32_t oid[]" "size_t oidlen" 122.Fa "int active" "int inclusive" 123.Fc 124.Ft uint32_t 125.Fn agentx_context_uptime "struct agentx_context *sac" 126.Ft void 127.Fn agentx_context_free "struct agentx_context *sac" 128.Ft struct agentx_agentcaps * 129.Fo agentx_agentcaps 130.Fa "struct agentx_context *sac" "uint32_t oid[]" "size_t oidlen" 131.Fa "const char *descr" 132.Fc 133.Ft void 134.Fn agentx_agentcaps_free "struct agentx_agentcaps *saa" 135.Ft struct agentx_region * 136.Fo agentx_region 137.Fa "struct agentx_context *sac" "uint32_t oid[]" 138.Fa "size_t oidlen" "uint8_t timeout" 139.Fc 140.Ft void 141.Fn agentx_region_free "struct agentx_region *sar" 142.Ft struct agentx_index * 143.Fo agentx_index_integer_new 144.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 145.Fc 146.Ft struct agentx_index * 147.Fo agentx_index_integer_any 148.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 149.Fc 150.Ft struct agentx_index * 151.Fo agentx_index_integer_value 152.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 153.Fa "int32_t value" 154.Fc 155.Ft struct agentx_index * 156.Fo agentx_index_integer_dynamic 157.Fa "struct agentx_region *sar" "uint32_t oid[] "size_t oidlen" 158.Fc 159.Ft struct agentx_index * 160.Fo agentx_index_string_dynamic 161.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 162.Fc 163.Ft struct agentx_index * 164.Fo agentx_index_nstring_dynamic 165.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 166.Fa "size_t slen" 167.Fc 168.Ft struct agentx_index * 169.Fo agentx_index_oid_dynamic 170.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 171.Fc 172.Ft struct agentx_index * 173.Fo agentx_index_noid_dynamic 174.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 175.Fa "size_t vlen" 176.Fc 177.Ft struct agentx_index * 178.Fo agentx_index_ipaddress_dynamic 179.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 180.Fc 181.Ft void 182.Fn agentx_index_free "struct agentx_index *sai" 183.Ft struct agentx_object * 184.Fo agentx_object 185.Fa "struct agentx_region *sar" "uint32_t oid[]" "size_t oidlen" 186.Fa "struct agentx_index *index[]" "size_t indexlen" "int implied" 187.Fa "void (*getcb)(struct agentx_varbind *)" 188.Fc 189.Ft void 190.Fn agentx_object_free "struct agentx_object *sao" 191.Ft void 192.Fn agentx_varbind_integer "struct agentx_varbind *sav" "int32_t value" 193.Ft void 194.Fn agentx_varbind_string "struct agentx_varbind *sav" "const char *value" 195.Ft void 196.Fo agentx_varbind_nstring 197.Fa "struct agentx_varbind *sav" "const char *value" "size_t slen" 198.Fc 199.Ft void 200.Fo agentx_varbind_printf 201.Fa "struct agentx_varbind *sav" "const char *fmt" ... 202.Fc 203.Ft void 204.Fn agentx_varbind_null "struct agentx_varbind *sav" 205.Ft void 206.Fo agentx_varbind_oid 207.Fa "struct agentx_varbind *sav" "const uint32_t oid[]" "size_t oidlen" 208.Fc 209.Ft void 210.Fo agentx_varbind_object 211.Fa "struct agentx_varbind *sav" "struct agentx_object *sao" 212.Fc 213.Ft void 214.Fo agentx_varbind_index 215.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 216.Fc 217.Ft void 218.Fo agentx_varbind_ipaddress 219.Fa "struct agentx_varbind *sav" "const struct in_addr *addr" 220.Fc 221.Ft void 222.Fn agentx_varbind_counter32 "struct agentx_varbind *sav" "uint32_t value" 223.Ft void 224.Fn agentx_varbind_gauge32 "struct agentx_varbind *sav" "uint32_t value" 225.Ft void 226.Fn agentx_varbind_unsigned32 "struct agentx_varbind *sav" "uint32_t value" 227.Ft void 228.Fo agentx_varbind_timeticks 229.Fa "struct agentx_varbind *sav" "uint32_t value" 230.Fc 231.Ft void 232.Fo agentx_varbind_opaque 233.Fa "struct agentx_varbind *sav" "const char *value" "size_t slen" 234.Fc 235.Ft void 236.Fn agentx_varbind_counter64 "struct agentx_varbind *sav" "uint64_t value" 237.Ft void 238.Fn agentx_varbind_notfound "struct agentx_varbind *sav" 239.Ft void 240.Fn agentx_varbind_error "struct agentx_varbind *sav" 241.Ft enum agentx_request_type 242.Fn agentx_varbind_request "struct agentx_varbind *sav" 243.Ft int32_t 244.Fo agentx_varbind_get_index_integer 245.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 246.Fc 247.Ft const unsigned char * 248.Fo agentx_varbind_get_index_string 249.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" "size_t *slen" 250.Fa "int *implied" 251.Fc 252.Ft const uint32_t * 253.Fo agentx_varbind_get_index_oid 254.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 255.Fa "size_t *oidlen" "int *implied" 256.Fc 257.Ft const struct in_addr * 258.Fo agentx_varbind_get_index_ipaddress 259.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 260.Fc 261.Ft void 262.Fo agentx_varbind_set_index_integer 263.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 264.Fa "int32_t value" 265.Fc 266.Ft void 267.Fo agentx_varbind_set_index_string 268.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 269.Fa "const unsigned char *value" 270.Fc 271.Ft void 272.Fo agentx_varbind_set_index_nstring 273.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 274.Fa "const unsigned char *value" "size_t slen" 275.Fc 276.Ft void 277.Fo agentx_varbind_set_index_oid 278.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 279.Fa "const uint32_t *oid" "size_t oidlen" 280.Fc 281.Ft void 282.Fo agentx_varbind_set_index_object 283.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 284.Fa "struct agentx_object *sao" 285.Fc 286.Ft void 287.Fo agentx_varbind_set_index_ipaddress 288.Fa "struct agentx_varbind *sav" "struct agentx_index *sai" 289.Fa "const struct in_addr *addr" 290.Fc 291.Bd -literal 292enum agentx_request_type { 293 AGENTX_REQUEST_TYPE_GET, 294 AGENTX_REQUEST_TYPE_GETNEXT, 295 AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE 296}; 297.Ed 298.Fd #define AGENTX_MASTER_PATH \(dq/var/agentx/master\(dq 299.Fd #define AGENTX_OID_MAX_LEN 128 300.Fd #define AGENTX_OID_INDEX_MAX_LEN 10 301.Fd #define AGENTX_OID(...) 302.Fd #define AGENTX_MIB2 1, 3, 6, 1, 2, 1 303.Fd #define AGENTX_ENTERPRISES 1, 3, 6, 1, 4, 1 304.Sh DESCRIPTION 305The 306.Nm agentx 307functions allow an application to describe their MIB layout and provide an 308.Fa fd 309based interface to control the internal agentx state. 310.Nm agentx 311is not thread safe. 312.Ss DESCRIBING THE MIB 313.Nm agentx 314is a framework to abstract away the agentx protocol from the application. 315For the framework to report information to the administrator, the 316.Fn agentx_log_fatal , 317.Fn agentx_log_warn , 318.Fn agentx_log_info 319and 320.Fn agentx_log_debug 321functions must be set. 322.Pp 323When 324.Fa sa 325is created by 326.Fn agentx 327or when 328.Fa sa 329detects that there is no connection to the agentx master it calls out to 330.Fa nofd 331with itself, 332.Fa cookie 333and an integer 334.Fa close 335as arguments. 336If 337.Fa close 338is not set 339.Fn nofd 340is expected to set up a new 341.Fa fd 342to the agentx master. 343This one can usually be found at 344.Dv AGENTX_MASTER_PATH . 345This 346.Fa fd 347can be returned to 348.Fa sa 349at any moment via 350.Fn agentx_connect , 351but must always be done as a result of a call to 352.Fn nofd . 353Once 354.Fn agentx_connect 355has been called the application is responsible for retrieving data when available 356on 357.Fa fd 358by calling 359.Fn agentx_read . 360If nonblocking writes are desirable the 361.Fn agentx_wantwrite 362pointer can be set to an application function and will be called as soon as 363there's data available to be written out. 364Once 365.Fa fd 366is ready for write the function 367.Fn agentx_write 368should be called. 369.Pp 370.Fa sa 371can be freed via 372.Fn agentx_free . 373It will close all active sessions and free all derived objects. 374Once freed no new objects can be derived from the freed objects. 375Once all sessions are closed it will call out to 376.Fn nofd 377with 378.Fa close 379set, indicating that the application can clean up any context related to 380.Fa sa . 381.Pp 382On top of the 383.Fa sa 384connection a 385.Vt agentx_session 386must be set up. 387Normally there's only a single session per 388.Fa sa . 389The 390.Fa timeout 391argument specifies the maximum time in seconds the master should wait for a 392reply before determining we're gone. 393If set to 0 the agentx master determines the timeout. 394The 395.Fa oid 396and 397.Fa oidlen 398combination identifies the subagent and will be visible through the 399agentxSessionObjectID object on the agentx master. 400The 401.Fa descr 402is a short displaystring description of the agent and will be visible through 403the agentxSessionDescr object on the agentx master. 404.Pp 405The 406.Vt agentx_context 407is the SNMPv3 context in which the objects operate and is built on top of 408agentx_session 409.Fa sas . 410If the default context is requested 411.Fa name 412must be NULL. 413.Pp 414.Fn agentx_agentcaps 415registers an entry in the agentx master's sysORTable. 416The 417.Fa oid , 418.Fa oidlen 419combination should point to an AGENT-CAPABILITIES object which describes the 420capabilities of the subagent. 421.Fa descr 422should be a textual description of the capabilities. 423If no AGENT-CAPABILITIES object is defined this function can be omitted. 424.Pp 425A 426.Vt agentx_region 427indicates a region inside the object-tree for which get- and set-requests will 428be queried. 429If the OID has already been claimed by another subagent it will try to claim it 430on a lower priority. 431The 432.Fa timeout 433parameter overrules its 434.Vt agentx_session 435counterpart. 436.Pp 437For objects in a table one or more 438.Ft agentx_index 439elements must be supplied. 440.Fn agentx_index_integer_new , 441.Fn agentx_index_integer_any 442and 443.Fn agentx_index_integer_value 444register an integer index at the agentx master. 445Of these 446.Fn agentx_index_integer_new 447registers a new, previously unused, index; 448.Fn agentx_index_integer_any 449registers the first available index; 450and 451.Fn agentx_index_integer_value 452tries to register a specific value. 453If the registration of an index fails an error will be logged and all objects 454using it will remain disabled. 455The OID where the index should be registered is documented by the MIB. 456These registered indices are usually used for tables where multiple subagents 457are registered. 458.Pp 459For dynamic indices the agentx_index_*_dynamic functions can be used, based 460on the data type of the object. 461The data type should match the data type in the MIB at the 462.Fa oid 463object. 464Indices of data type string or oid with a fixed length should be created via 465.Fn agentx_index_nstring_dynamic 466and 467.Fn agentx_index_noid_dynamic 468respectively. 469.Pp 470.Vt agentx_object 471is an object as described in the MIB. 472For scalar objects 473.Pq without indices 474the final zero must be omitted. 475For table entries a list of 1 or more indices must be added via 476.Fa index 477and 478.Fa indexlen . 479The list of indices must match the INDEX list on the ENTRY object in the MIB. 480The total length of the OID, including indices, can't be more than 481.Dv AGENTX_OID_MAX_LEN 482and indexlen can't be more than 483.Dv AGENTX_OID_INDEX_MAX_LEN . 484If 485.Fa implied 486is set the final index must be of type OID or string and will omit the leading 487length indicator. 488This value must only be set if specified in the MIB. 489.Fn getcb 490will be called for each varbind in a GET, GETNEXT or GETBULK request that 491matches the object. 492.Ss HANDLING GET REQUESTS 493A call to 494.Fn getcb 495must eventually result in a call to one of the following functions: 496.Bl -tag -width agentx_varbind_counter32() 497.It Fn agentx_varbind_integer 498Set the return value to an int32_t value. 499.It Fn agentx_varbind_string 500A C string wrapper around 501.Fn agentx_varbind_nstring . 502.It Fn agentx_varbind_nstring 503Set the return value to an octetstring. 504.It Fn agentx_varbind_printf 505A printf wrapper around 506.Fn agentx_varbind_nstring . 507.It Fn agentx_varbind_null 508Set the return value to null. 509.It Fn agentx_varbind_oid 510Set the return value to an OID value. 511.It Fn agentx_varbind_object 512An agentx_object wrapper around 513.Fn agentx_varbind_oid . 514.It Fn agentx_varbind_index 515An agentx_index wrapper around 516.Fn agentx_varbind_oid . 517.It Fn agentx_varbind_ipaddress 518Set the return value to ipaddress. 519.It Fn agentx_varbind_counter32 520Set the return value to an uint32_t of type counter32. 521.It Fn agentx_varbind_gauge32 522Set the return value to an uint32_t of type gauge32. 523.It Fn agentx_varbind_unsigned32 524A wrapper around agentx_varbind_gauge32. 525.It Fn agentx_varbind_timeticks 526Set the return value to an uint32_t of type timeticks. 527.It Fn agentx_varbind_opaque 528Set the return value to an opaque value. 529.It Fn agentx_varbind_counter64 530Set the return value to an uint64_t of type counter64. 531.It Fn agentx_varbind_notfound 532When the request is of type GET return a nosuchinstance error. 533When the request is of type GETNEXT or GETBULK return an endofmibview error. 534On endofmibview the next object is queried. 535This function can only be called on objects that contain one or more *_dynamic 536indices. 537.It Fn agentx_varbind_error 538Returns a GENERR error to the client. 539.El 540.Pp 541For objects containing *_dynamic indices the following support functions are to 542be used: 543.Bl -tag -width Ds 544.It Fn agentx_varbind_request 545Returns whether the request is of type GET, GETNEXT or GETNEXTINCLUSIVE. 546.It Fn agentx_varbind_get_index_integer 547Retrieve a single int32_t index value. 548.It Fn agentx_varbind_get_index_string 549Retrieve an octetstring index value. 550.Fa slen 551is the length of the string and 552.Fa implied 553indicates if the next value for this index should be length sorted before 554alphabetically sorted. 555.It Fn agentx_varbind_get_index_oid 556Retrieve an oid index value. 557.Fa oidlen 558is the length of the oid and 559.Fa implied 560indicates if the next value for this index should be length sorted before 561alphabetically sorted. 562.It Fn agentx_varbind_get_index_ipaddress 563Retrieve an ipaddress index value. 564.It Fn agentx_varbind_set_index_integer 565Sets a single int32_t index value. 566.It Fn agentx_varbind_set_index_string 567A C string wrapper around 568.Fn agentx_varbind_set_index_nstring . 569.It Fn agentx_varbind_set_index_nstring 570Set an octetstring index value. 571.It Fn agentx_varbind_set_index_oid 572Set an oid index value. 573.It Fn agentx_varbind_set_index_object 574A agentx_object wrapper around 575.Fn agentx_varbind_set_index_oid . 576.It Fn agentx_varbind_set_index_ipaddress 577Set an ipaddress index value. 578.El 579.Pp 580For these functions 581.Fa sai 582must be part of the object the request is performed on. 583The function type must also match the data type of 584.Fa sai . 585.Pp 586Other functions that can retrieve information from the agentx context are: 587.Bl -tag -width Ds 588.It Fn agentx_context_object_find 589Find an agentx_object created inside agentx_context 590.Fa sac 591based on 592.Fa oid 593and 594.Fa oidlen . 595If 596.Fa active 597is set the object must be reachable from the agentx master, else NULL is 598returned. 599If 600.Fa oid 601can be an instance, find its parent object. 602.It Fn agentx_context_object_nfind 603Find the next agentx_object created inside agentx_context 604.Fa sac 605based on 606.Fa oid 607and 608.Fa oidlen . 609If 610.Fa active 611is set the object must be reachable from the agentx master, else NULL is 612returned. 613If 614.Fa inclusive 615is set the object returned may also exactly match 616.Fa oid . 617.It Fn agentx_context_uptime 618Returns the sysuptime in seconds for 619.Fa sac 620in timeticks. 621.El 622.Sh SEE ALSO 623.Xr snmp 1 , 624.Xr snmpd 8 625.Sh STANDARDS 626.Rs 627.%A M. Daniele 628.%A B. Wijnen 629.%A M. Ellison, Ed. 630.%A D. Francisco, Ed. 631.%D January 2000 632.%R RFC 2741 633.%T Agent Extensibility (AgentX) Protocol Version 1 634.Re 635.Pp 636.Rs 637.%A L. Heintz 638.%A S. Gudur 639.%A M. Ellison, Ed. 640.%D January 2000 641.%R RFC 2742 642.%T Definitions of Managed Objects for Extensible SNMP Agents 643.Re 644.Sh HISTORY 645The 646.Nm agentx 647API first appeared in 648.Ox 6.9 . 649.Sh AUTHORS 650.An Martijn van Duren Aq Mt martijn@openbsd.org 651