sysctlmibinfo is an open source (2-Clause BSD License) library for FreeBSD. It provides an easy userspace API to the kernel sysctl mib to get mib-entry information, to traverse the mib and then to build quickly a custom sysctl(8) tool.

This post shows the manual page, tutorial, examples and extra stuff are in wiki.freebsd.org/AlfonsoSiciliano/sysctlmibinfo.

SYSCTLMIBINFO(3)       FreeBSD Library Functions Manual       SYSCTLMIBINFO(3)

NAME
     SYSCTLMIF_MAXIDLEVEL, sysctlmif_nametoid, sysctlmif_name,
     SYSCTLMIF_NAMELEN, sysctlmif_desc, SYSCTLMIF_DESCLEN, sysctlmif_label,
     SYSCTLMIF_LABELLEN, sysctlmif_info, SYSCTLMIF_INFOKIND,
     SYSCTLMIF_INFOTYPE, SYSCTLMIF_INFOFLAGS, SYSCTLMIF_INFOFMT,
     sysctlmif_nextnode, sysctlmif_nextleaf, sysctlmif_object,
     sysctlmif_freeobject, sysctlmif_filterlist, SYSCTLMIF_LIST,
     SYSCTLMIF_MAXDEPTH, sysctlmif_grouplist, sysctlmif_freelist,
     sysctlmif_tree, sysctlmif_freetree - get sysctl mib information

LIBRARY
     System Utilities Library (libutil, -lutil)

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

     #define SYSCTLMIF_MAXIDLEVEL;

     int
     sysctlmif_nametoid(const char *name, size_t namelen, int *id,
         size_t *idlevel);

     int
     sysctlmif_name(int *id, size_t idlevel, char *name, size_t *namelen);

     int
     SYSCTLMIF_NAMELEN(int *id, size_t idlevel, size_t *namelen);

     int
     sysctlmif_desc(int *id, size_t idlevel, char *desc, size_t *desclen);

     int
     SYSCTLMIF_DESCLEN(int *id, size_t idlevel, size_t *desclen);

     int
     sysctlmif_label(int *id, size_t idlevel, char *label, size_t *labellen);

     int
     SYSCTLMIF_LABELLEN(int *id, size_t idlevel, size_t *labellen);

     int
     sysctlmif_info(int *id, size_t idlevel, void *info, size_t *infolen);

     uint32_t
     SYSCTLMIF_INFOKIND(info);

     uint8_t
     SYSCTLMIF_INFOTYPE(info);

     uint32_t
     SYSCTLMIF_INFOFLAGS(info);

     char *
     SYSCTLMIF_INFOFMT(info);

     int
     sysctlmif_nextleaf(int *id, size_t idlevel, int *nextid,
         size_t *nextidlevel);

     int
     sysctlmif_nextnode(int *id, size_t idlevel, int *nextid,
         size_t *nextidlevel);

     struct sysctlmif_object *
     sysctlmif_object(int *id, size_t idlevel, unsigned int flags);

     void
     sysctlmif_freeobject(struct sysctlmif_object *object);

     #define SYSCTLMIF_MAXDEPTH

     struct sysctlmif_object_list *
     sysctlmif_filterlist(sysctlmif_filterfunc_t *filterfunc,
         unsigned int flags);

     struct sysctlmif_object_list *
     SYSCTLMIF_LIST(unsigned int flags);

     struct sysctlmif_object_list *
     sysctlmif_grouplist(int *idstart, size_t idstartlen, unsigned int flags,
         unsigned int max_depth);

     void
     sysctlmif_freelist(struct sysctlmif_object_list *list);

     struct sysctlmif_object *
     sysctlmif_tree(int *id, size_t idlevel, unsigned int flags,
         unsigned int max_depth);

     void
     sysctlmif_freetree(struct sysctlmif_object *node);

DESCRIPTION
     The sysctlmibinfo library is an interface to the kernel sysctl mib.
     It implements wrappers around undocumented "sysctl.*" kernel states to
     get mib information and provides a convenient API to build a mib-entry,
     entries-list and entries-tree in userspace; as it is not designed to get 
     and set entry values, anyone wishing to do this should see sysctl(3).

     A mib-entry is identified by a pair int *id and size_t idlevel, the level
     should be between 1 and SYSCTLMIF_MAXIDLEVEL, see sysctlmif_next().

     sysctlmif_nametoid() sets id and idlevel like the entry with name and
     namelen.

     SYSCTLMIF_NAMELEN(), SYSCTLMIF_DESCLEN() and SYSCTLMIF_LABELLEN() set
     namelen, desclen, and labellen like the entry with id and idlevel.

     sysctlmif_name(), sysctlmif_desc() and sysctlmif_label() set name and
     namelen, desc and desclen, label and labellen like the entry with id and
     idlevel.

     sysctlmif_info() sets info and infolen like the entry with id and
     idlevel, info has the format: 3 bytes for flags, 1 byte for type and a
     string for the "format string"; flags and type are defined in
     <sys/sysctl.h>.  Macros to deal with info:
           SYSCTLMIF_INFOFLAGS(info) returns flags;
           SYSCTLMIF_INFOTYPE(info) returns entry type;
           SYSCTLMIF_INFOKIND(info) returns flags following by type;
           SYSCTLMIF_INFOFMT(info) returns a pointer to the "format string".

     sysctlmif_nextleaf() sets nextid and nextidlevel like the next-leaf-entry
     of the entry with id and idlevel.  sysctlmif_nextnode() sets nextid and
     nextidlevel like the next-[node|leaf]-entry of the entry with id and
     idlevel.  Notes: nextid should have size SYSCTLMIF_MAXIDLEVEL and
     nextidlevel should be set to SYSCTLMIF_MAXIDLEVEL before to call
     sysctlmif_nextleaf() or sysctlmif_nextnode().

     sysctlmif_object() returns a pointer to allocated memory for a struct
     sysctlmif_object (setting flags members) of the entry with id and
     idlevel.  A mib userspace entry is defined:

           /* 'struct sysctlmif_object': userspace mib entry definition */

           SLIST_HEAD(sysctlmif_object_list, sysctlmif_object);

           struct sysctlmif_object {
                   SLIST_ENTRY(sysctlmif_object) object_link;
                   int *id;
                   size_t idlevel; /* between 1 and SYSCTLMIF_MAXIDLEVEL */
                   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 */
                                   /* children is set by sysctlmif_tree() */
                   struct sysctlmif_object_list *children;
           };

           /*
            * OR_FLAGS: object fields to set,
            * .id and .idlevel are always set
            * .children is default for sysctlmif_tree()
            */
           #define SYSCTLMIF_FNAME         0x01    /* .name  */
           #define SYSCTLMIF_FDESC         0x02    /* .desc  */
           #define SYSCTLMIF_FLABEL        0x04    /* .label */
           #define SYSCTLMIF_FTYPE         0x08    /* .type  */
           #define SYSCTLMIF_FFLAGS        0x10    /* .flags */
           #define SYSCTLMIF_FFMT          0x20    /* .fmt   */
           #define SYSCTLMIF_FALL                  /*  all   */

     SYSCTLMIF_LIST() allocates memory and returns a SLIST of sysctlmif_object
     (setting flags members), it is an alias for sysctlmif_filterlist(NULL,
     flags).

     sysctlmif_filterlist() allocates memory for a SLIST of sysctlmif_object
     (setting flags members), an object "o" is added if
           int sysctlmif_filterfunc_t (struct sysctlmif_object *o)
     returns 0 or filterfunc is NULL; notes: sysctlmif_filterlist() uses
     sysctlmif_nextnode() and object.children is not set.

     sysctlmif_grouplist() allocates memory and returns a SLIST of
     sysctlmif_object (setting flags members) visited in a "Depth First
     Traversal" until max_depth, id and idlevel denote the root.  Notes:
     sysctlmif_grouplist() uses sysctlmif_nextnode(), object.children is not
     set and max_depth can be set to SYSCTLMIF_MAXDEPTH.

     sysctlmif_tree() allocates memory for a tree of sysctlmif_object nodes
     (setting flags members) until max_depth and returns a pointer to the
     root: the entry with id and idlevel.  Notes: max_depth can be set to
     SYSCTLMIF_MAXDEPTH, object.children is set and iterable by SLIST macros.

     sysctlmif_freeobject(), sysctlmif_freelist() and sysctlmif_freetree()
     free allocated memory.

IMPLEMENTATION NOTES
     sysctlmibinfo uses sysctl() syscall for wrapping 0.[1-6] entries defined
     in kern_sysctl.c.  The kernel returns only next leaf,
     sysctlmif_nextnode() requires extra computation.

RETURN VALUES
     The sysctlmif_nametoid(), SYSCTLMIF_NAMELEN(), sysctlmif_name(),
     SYSCTLMIF_DESCLEN(), sysctlmif_desc(), SYSCTLMIF_LABELLEN(),
     sysctlmif_label(), sysctlmif_info(), 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_filterlist(), SYSCTLMIF_LIST(),
     sysctlmif_grouplist(), sysctlmif_tree() functions return NULL upon error
     or a pointer to allocated memory for success.

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

SEE ALSO
     queue(3), sysctl(3)

HISTORY
     The sysctlmibinfo library first appeared in FreeBSD 13.0.

AUTHORS
     sysctlmibinfo and this manual page were written by Alfonso S. Siciliano
     <alf.siciliano@gmail.com>

BUGS
     Problems from the kernel space:
           sysctlmif_name() false positive.
           sysctlmif_desc() could set desc to: "" or NULL for entries without
           description.

FreeBSD 13.0-CURRENT           January 29, 2019           FreeBSD 13.0-CURRENT