The sysctlmibinfo2 library provides an API to explore the FreeBSD sysctl MIB and to get the info of an object, it is useful to build a sysctl-like tool to get or set the kernel state. For example, sysctlview, a graphical sysctl MIB explorer, depends on it.

This post shows the manual page, for the source code and examples: gitlab.com/alfix/sysctlmibinfo2.

SYSCTLMIBINFO2(3)      FreeBSD Library Functions Manual      SYSCTLMIBINFO2(3)

NAME
     sysctlmif_name, sysctlmif_oidbyname, sysctlmif_oidinputbyname,
     sysctlmif_desc, sysctlmif_descbyname, sysctlmif_label,
     sysctlmif_labelbyname, sysctlmif_fmt, sysctlmif_fmtbyname,
     sysctlmif_kind, sysctlmif_kindbyname, SYSCTLMIF_KINDTYPE,
     SYSCTLMIF_KINDFLAGS, sysctlmif_nextnode, sysctlmif_nextleaf,
     sysctlmif_object, sysctlmif_objectbyname, sysctlmif_freeobject,
     sysctlmif_list, sysctlmif_grouplist, sysctlmif_grouplistbyname,
     sysctlmif_freelist, sysctlmif_tree, sysctlmif_treebyname,
     sysctlmif_freetree, sysctlmif_mib, sysctlmif_freemib - sysctl MIB-Tree
     info 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"

     library "libsysctlmibinfo2"

SYNOPSIS
     #include <sys/types.h>
     #include <sys/queue.h>
     #include <sysctlmibinfo2.h>

     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_oidinputbyname(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_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_nextnode(int *id, size_t idlevel, int *idnext,
         size_t *idnextlevel);

     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_object_list *
     sysctlmif_list();

     struct sysctlmif_object_list *
     sysctlmif_grouplist(int *idroot, size_t idrootlen);

     struct sysctlmif_object_list *
     sysctlmif_grouplistbyname(const char *name);

     void
     sysctlmif_freelist(struct sysctlmif_object_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_object_list *
     sysctlmif_mib();

     void
     sysctlmif_freemib(struct sysctlmif_object_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), it is represented
     by a pair int *id and size_t idlevel, the level should be between 1 and
     CTL_MAXNAME.

     sysctlmif_name(), sysctlmif_desc(), sysctlmif_kind(), sysctlmif_fmt(),
     sysctlmif_label(), sysctlmif_nextnode() and sysctlmif_nextleaf() set name
     and namelen, desc and desclen, kind, label and labellen, idnext and
     idnextlevel like the object with id / idlevel.  sysctlmif_descbyname(),
     sysctlmif_kindbyname(), sysctlmif_fmtbyname() and sysctlmif_labelbyname()
     are equivalet but the object is identified by its name.

     sysctlmif_oidbyname() and sysctlmif_oidinputbyname() set id and idlevel
     like the object with name, sysctlmif_oidinputbyname() can handle the
     nodes with an input with the OID, e.g., "kern.proc.pid.<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.

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

           struct sysctlmif_object {
                   SLIST_ENTRY(sysctlmif_object) object_link;
                   int *id;                     /* array of idlevel items    */
                   size_t idlevel;              /* between 1 and CTL_MAXNAME */
                   char *name;
                   char *desc;
                   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_object_list *children; /* children list  */
           };

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

     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
     returns a list of the objects visited in a "Depth First Traversal", id /
     idlevel or name denote the root, 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.

RETURN VALUES
     The sysctlmif_name(), sysctlmif_oidbyname(), sysctlmif_oidinputbyname(),
     sysctlmif_desc(), sysctlmif_descbyname(), sysctlmif_label(),
     sysctlmif_labelbyname(), sysctlmif_fmt(), sysctlmif_fmtbyname(),
     sysctlmif_kind(), sysctlmif_kindbyname(), sysctlmif_nextnode(), and
     sysctlmif_nextleaf() functions return the value 0 if successful;
     otherwise the value -1 is returned and the global variable errno is set
     to indicate the error.

     The sysctlmif_object(), sysctlmif_objectbyname(), sysctlmif_list(),
     sysctlmif_grouplist(), sysctlmif_grouplistbyname(), 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

     Example to print the Sound Driver objects:

           struct sysctlmif_object_list *list;
           struct sysctlmif_object *obj;

           if ((list = sysctlmif_grouplistbyname("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.

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>

FreeBSD 13.0-CURRENT             April 7, 2020            FreeBSD 13.0-CURRENT