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