SYSCTLMIBINFO2(3)

NAME
SYSCTLMIF_VERSION, sysctlmif_name, sysctlmif_oidbyname, sysctlmif_oidextendedbyname, sysctlmif_desc, sysctlmif_descbyname, sysctlmif_label, sysctlmif_labelbyname, sysctlmif_fmt, sysctlmif_fmtbyname, sysctlmif_hashandler, sysctlmif_hashandlerbyname, sysctlmif_kind, sysctlmif_kindbyname, SYSCTLMIF_KINDTYPE, SYSCTLMIF_KINDFLAGS, sysctlmif_nextnode, sysctlmif_nextnodebyname, sysctlmif_nextleaf, sysctlmif_nextleafbyname, sysctlmif_object, sysctlmif_objectbyname, sysctlmif_freeobject, sysctlmif_list, sysctlmif_grouplist, sysctlmif_grouplistbyname, sysctlmif_leaves, sysctlmif_leavesbyname, sysctlmif_freelist, sysctlmif_tree, sysctlmif_treebyname, sysctlmif_freetree, sysctlmif_mib, sysctlmif_freemib - sysctl MIB-Tree API

LIBRARY
To load the required kernel modules at boot time, place the following lines in loader.conf(5):

    sysctlinfo_load="YES"
    sysctlbyname_improved_load="YES"

libsysctlmibinfo2

SYNOPSIS
#include <sysctlmibinfo2.h>
#define SYSCTLMIF_VERSION
int
sysctlmif_name(int *id, size_t idlevel, char *name, size_t *namelen);
int
sysctlmif_oidbyname(const char *name, int *id, size_t *idlevel);
int
sysctlmif_oidextendedbyname(const char *name, int *id, size_t *idlevel);
int
sysctlmif_desc(int *id, size_t idlevel, char *desc, size_t *desclen);
int
sysctlmif_descbyname(const char *name, char *desc, size_t *desclen);
int
sysctlmif_label(int *id, size_t idlevel, char *label, size_t *labellen);
int
sysctlmif_labelbyname(const char *name, char *label, size_t *labellen);
int
sysctlmif_fmt(int *id, size_t idlevel, char *fmt, size_t *fmtlen);
int
sysctlmif_fmtbyname(const char *name, char *fmt, size_t *fmtlen);
int
sysctlmif_hashandler(int *id, size_t idlevel, bool *handler);
int
sysctlmif_hashandlerbyname(const char *name, bool *handler);
int
sysctlmif_kind(int *id, size_t idlevel, unsigned int *kind);
int
sysctlmif_kindbyname(const char *name, unsigned int *kind);
unsigned int
SYSCTLMIF_KINDTYPE(unsigned int kind);
unsigned int
SYSCTLMIF_KINDFLAGS(unsigned int kind);
int
sysctlmif_nextleaf(int *id, size_t idlevel, int *idnext, size_t *idnextlevel);
int
sysctlmif_nextleafbyname(const char *name, char *next, size_t *nextlen);
int
sysctlmif_nextnode(int *id, size_t idlevel, int *idnext, size_t *idnextlevel);
int
sysctlmif_nextnodebyname(const char *name, char *next, size_t *nextlen);
struct sysctlmif_object *
sysctlmif_object(int *id, size_t idlevel);
struct sysctlmif_object *
sysctlmif_objectbyname(const char *name);
void
sysctlmif_freeobject(struct sysctlmif_object *object);
struct sysctlmif_list *
sysctlmif_list();
struct sysctlmif_list *
sysctlmif_grouplist(int *idroot, size_t idrootlen);
struct sysctlmif_list *
sysctlmif_grouplistbyname(const char *name);
struct sysctlmif_list *
sysctlmif_leaves(int *idroot, size_t idrootlen);
struct sysctlmif_list *
sysctlmif_leavesbyname(const char *name);
void
sysctlmif_freelist(struct sysctlmif_list *list);
struct sysctlmif_object *
sysctlmif_tree(int *idroot, size_t idrootlevel);
struct sysctlmif_object *
sysctlmif_treebyname(const char *name);
void
sysctlmif_freetree(struct sysctlmif_object *node);
struct sysctlmif_list *
sysctlmif_mib();
void
sysctlmif_freemib(struct sysctlmif_list *mib);

DESCRIPTION
The sysctlmibinfo2 library is an interface to the kernel sysctl MIB-Tree. It implements wrappers around the sysctlinfo(4) interface and sysctlbyname-improved to explore the sysctl MIB and to get the info of an object, moreover it defines a struct sysctlmif_object and provides a convenient API to build data structures of sysctlmif_object; as it is not designed to get and set object values, anyone wishing to do this should see sysctl(3).

An object is identified by an Object Identifier (OID), a series of numbers, represented by a pair int *id and size_t idlevel, the level should be between 1 and CTL_MAXNAME. It is possible to replace a number with a string to obtain an object name, e.g., [1.1] → “kern.ostype”.

SYSCTLMIF_VERSION is set to 2 to differentiate between this library and sysctlmibinfo(3).

  Wrappers
sysctlmif_name() sets name and namelen like the object with id / idlevel.

sysctlmif_desc(), sysctlmif_fmt() and sysctlmif_label() set desc and desclen, fmt and fmtlen, label and labellen like the object with id / idlevel. sysctlmif_descbyname(), sysctlmif_fmtbyname() and sysctlmif_labelbyname() are equivalent but the object is identified by its name.

sysctlmif_kind() and sysctlmif_kindbyname() set kind like the object with id / idlevel or name, it represents the object type and flags, defined in <sys/sysctl.h>. Macros to deal with kind:
SYSCTLMIF_KINDFLAGS(kind) returns flags,

SYSCTLMIF_KINDTYPE(kind) returns type.

sysctlmif_nextleaf() and sysctlmif_nextnode() set nextid and nextidlevel like the next leaf or also internal node visited in a “Depth First Traversal” of the object id / idlevel.

sysctlmif_nextleafbyname() and sysctlmif_nextnodebyname() set next and nextlen like the next leaf or also internal node visited in a “Depth First Traversal” of the object name.

sysctlmif_oidbyname() and sysctlmif_oidextendedbyname() set id and idlevel like the object with name, sysctlmif_oidextendedbyname() can convert a name extended with an input for the handler of a CTLTPYE_NODE, e.g., “kern.proc.pid.<input>” → [1.14.1.<input>].

The previous functions seek the object with id / idlevel or name, then the property is copied into the buffer (e.g., desc, label, idnext, etc.). Before the call buflen (e.g., desclen, lebellen, idnextlevel, etc.) gives the size of buffer, after a successful call buflen gives the amount of data copied; the size of the property can be determined with the NULL argument for the buffer, the size will be returned in the location pointed to by buflen.

  sysctlmif_object API
The sysctlmibinfo2 library defines a struct for the info of an object:

    SLIST_HEAD(sysctlmif_list, sysctlmif_object);
    struct sysctlmif_object {
    	SLIST_ENTRY(sysctlmif_object) object_link;
    	int      *id;            /* array of idlevel entries  */
    	size_t   idlevel;        /* between 1 and CTL_MAXNAME */
    	char     *name;          /* name in MIB notation      */
    	char     *desc;          /* description               */
    	char     *label;         /* aggregation label         */
    	uint8_t  type;           /* defined in <sys/sysctl.h> */
    	uint32_t flags;          /* defined in <sys/sysctl.h> */
    	char     *fmt;           /* format string             */
    	struct sysctlmif_list *children; /* children list     */
    };

and a list of objects, struct sysctlmif_list, iterable by the SLIST macros, see queue(3) and EXAMPLES.

sysctlmif_object() and sysctlmif_objectbyname() return a pointer to the allocated memory for a struct sysctlmif_object of the object with id / idlevel or name, the pointer can be passed to sysctlmif_freeobject() to free the memory.

sysctlmif_list() allocates memory and returns a list with all the objects of the MIB, sysctlmif_freelist() frees the allocated memory.

sysctlmif_grouplist() and sysctlmif_grouplistbyname() allocate memory and return a list of the objects, internal nodes and leaves, visited in a “Depth First Traversal”, id / idlevel or name denote the root, sysctlmif_freelist() frees the allocated memory.

sysctlmif_leaves() and sysctlmif_leavesbyname() allocate memory for a list of objects, if id / idlevel or name is a leaf the list contains only it, otherwise the list of its descendant leaves; sysctlmif_freelist() frees the allocated memory.

sysctlmif_tree() and sysctlmif_treebyname() allocate memory for a tree of sysctlmif_object and returns a pointer to the root, id / idlevel or name denote the root, object.children is set and iterable by SLIST macros, sysctlmif_freetree() frees the allocated memory.

sysctlmif_mib() allocates memory for a collection of trees and returns a list where the entries are the roots representing the top-level objects, sysctlmif_freemib() frees the allocated memory.

  Capability Mode
In “capability mode”, see cap_enter(2), sysctlmibinfo2 checks if the object has CTLFLAG_CAPRD or CTLFLAG_CAPWR before to return its info, sysctlmif_nextnode(), sysctlmif_nextnodebyname(), sysctlmif_nextleaf() and sysctlmif_nextleafbyname() ignore capability flags to traverse the tree also in capability mode; properly sysctlmibinfo2 provides “capability mode” via sysctlinfo(4) interface.

RETURN VALUES

The sysctlmif_object(), sysctlmif_objectbyname(), sysctlmif_list(), sysctlmif_grouplist(), sysctlmif_grouplistbyname(), sysctlmif_leaves(), sysctlmif_leavesbyname(), sysctlmif_tree(), sysctlmif_treebyname(), sysctlmif_mib() functions return NULL upon error or a pointer to allocated memory for success.

EXAMPLES
Complete set of examples: https://gitlab.com/alfix/sysctlmibinfo2/tree/master/examples

If installed:
    /usr/local/share/examples/sysctlmibinfo2/

Example to print the Sound Driver objects:

    struct sysctlmif_list *list;
    struct sysctlmif_object *obj;
    if ((list = sysctlmif_leavesbyname("hw.snd")) == NULL)
    	return (1);
    SLIST_FOREACH(obj, list, object_link) {
    	printf("name:   %s\n", obj->name);
    	printf("descr.: %s\n", obj->desc);
    	printf("label:  %s\n", obj->label);
    	printf("flags:  %u\n", obj->flags);
    	printf("type:   %u\n", obj->type);
    	printf("fmt:    %s\n", obj->fmt);
    	printf("----------------------\n");
    }
    sysctlmif_freelist(list);

ERRORS
The following errors may be reported:

[ECAPMODE]
    The node has not the CTLFLAG_CAPRD or CTLFLAG_CAPWR flag in capability mode.

[EINVAL]
    name has more than CTL_MAXNAME levels.

[EINVAL]
    idlevel is either greater CTL_MAXNAME, equal to zero or is not an integer.

[ENAMETOOLONG]
    name is >= MAXPATHLEN.

[ENOATTR]
    The node exists but its info is NULL.

[ENOENT]
    The node does not exist.

[ENOMEM]
    Cannot allocate memory.

SEE ALSO
cap_enter(2), queue(3), sysctl(3), sysctlinfo(3), sysctlinfo(4)

HISTORY
The sysctlmibinfo2 library first appeared in FreeBSD 13.0.

AUTHORS
sysctlmibinfo2 was written by Alfonso Sabato Siciliano <alf.siciliano@gmail.com>.