xref: /openbsd/lib/libagentx/agentx.3 (revision 4bdff4be)
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