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