sysctlmibinfo(3)

The sysctlmibinfo API is an interface to the sysctl MIB. It implements wrappers around undocumented "sysctl.*" kernel states to get mib-entry information, defines an userland entry (sysctlmif_object) and provides a convenient API to build entry-list and entry-tree.

Critics and Suggestions: review D18696, git repo and feel free to edit this wiki page.

1. Introduction

1.1. Before to start

To read:

1.2. Why sysctlmibinfo?

/sbin/sysctl (and sysctl(3)) can get or set a kernel state:

        % sysctl kern.ostype
        # sysctl kern.hostname=myBSD

Moreover /sbin/sysctl can traverse the sysctl-tree and display other info: name, type, description, etc.

        % sysctl -aN
        % sysctl -t kern.ostype
        % sysctl -d kern.ostype

How is it possible?

A kernel state is a struct sysctl_oid defined in <sys/sysctl.h>, kern_sysctl.c implements 6 entries (with static toplevel 0) to get the value of some sysctl_oid member in userland, they are:

Their documentation is just a comment in kern_sysctl.c, the purpose of sysctlmibinfo is to wrap this undocumented interface and provide new features. The advantages to use sysctlmibinfo are:

1.3. Compiling

Download and install

% git clone https://gitlab.com/alfix/sysctlmibinfo.git/
% cd sysctlmibinfo
% make 
% su
# make install

To compile mysysctl.c

   1 #include <sys/types.h>
   2 #include <sys/queue.h>
   3 
   4 #include <sysctlmibinfo.h>
   5 
   6 int main() {
   7 
   8         /* ...sysctlmibinfo stuff... */
   9         
  10         return (0);
  11 }

% cc -I/usr/local/include mysysctl.c -L/usr/local/lib -lsysctlmibinfo -o mysysctl

2. API Documentation

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

2.1. Wrappers

The following functions call sysctl() for wrapping 0.[1-6] entries/'kernel state', return the value 0 if successful otherwise the value -1 is returned and the global variable errno is set to indicate the error.

2.1.1. name to id

sysctlmif_nametoid() sets id and idlevel like the entry with name and namelen, id should have size SYSCTLMIF_MAXIDLEVEL and idlevel should be set to SYSCTLMIF_MAXIDLEVEL.

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

2.1.2. name, description and label

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

   1 int sysctlmif_name(int *id, size_t idlevel, char *name, size_t *namelen);
   2 int sysctlmif_desc(int *id, size_t idlevel, char *desc, size_t *desclen);
   3 int sysctlmif_label(int *id, size_t idlevel, char *label, size_t *labellen);

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

   1 int SYSCTLMIF_NAMELEN(int *id, size_t idlevel, size_t *namelen);
   2 int SYSCTLMIF_DESCLEN(int *id, size_t idlevel, size_t *desclen);
   3 int SYSCTLMIF_LABELLEN(int *id, size_t idlevel, size_t *labellen);

2.1.3. info

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 char* for the "format string"; flags and types are defined in <sys/sysctl.h>.

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

Macros to deal with void *info:

   1 uint32_t sysctlmif_INFOKIND(info);  /* returns flags following by type */
   2 uint8_t  sysctlmif_INFOTYPE(info);  /* returns entry type */
   3 uint32_t sysctlmif_INFOFLAGS(info); /* returns flags */
   4 char *   sysctlmif_INFOFMT(info);   /* returns a pointer to the “format string” */

2.1.4. nextnode and nextleaf

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-entry or next-leaf-entry of the entry with id and idlevel. nextid should have size SYSCTLMIF_MAXIDLEVEL and nextidlevel should be set to SYSCTLMIF_MAXIDLEVEL before to call sysctlmif_nextleaf() or sysctlmif_nextnode().

The kernel returns only next leaf, next node requires extra computation.

   1 int sysctlmif_nextnode(int *id, size_t idlevel, int *idnext, size_t *idnextlevel);
   2 int sysctlmif_nextleaf(int *id, size_t idlevel, int *idnext, size_t *idnextlevel);

2.2. Userspace mib entry

The following functions are related to struct sysctlmif_object,
return a pointer to allocated memory for success or NULL for failure.

2.2.1. struct sysctlmif_object

sysctlmibinfo defines a userspace mib entry: struct sysctlmif_object.

   1 SLIST_HEAD(sysctlmif_object_list, sysctlmif_object);
   2 
   3 struct sysctlmif_object {
   4         SLIST_ENTRY(sysctlmif_object) object_link;
   5         int *id;
   6         size_t idlevel; /* between 1 and SYSCTLMIF_MAXIDLEVEL */
   7         char *name;
   8         char *desc;
   9         char *label;    /* aggregation label */
  10         uint8_t type;   /* defined in <sys/sysctl.h> */
  11         uint32_t flags; /* defined in <sys/sysctl.h> */
  12         char *fmt;      /* format string */
  13                         /* children is set by sysctlmif_tree() */
  14         struct sysctlmif_object_list *children;
  15 };
  16 
  17 /*
  18  * OR_FLAGS: object fields to set,
  19  * .id and .idlevel are always set
  20  * .children is default for sysctlmif_tree()
  21  */
  22 #define sysctlmif_FNAME         0x01    /* .name  */
  23 #define sysctlmif_FDESC         0x02    /* .desc  */
  24 #define sysctlmif_FLABEL        0x04    /* .label */
  25 #define sysctlmif_FTYPE         0x08    /* .type  */
  26 #define sysctlmif_FFLAGS        0x10    /* .flags */
  27 #define sysctlmif_FFMT          0x20    /* .fmt   */
  28 #define sysctlmif_FALL                  /*  all   */
  29 

2.2.2. Object functions

sysctlmif_object() returns a pointer to allocated memory for a struct sysctlmif_object (setting flags members) of the entry with id and idlevel; the pointer may subsequently be used as an argument to sysctlmif_freeobject().

   1 struct sysctlmif_object *
   2 sysctlmif_object(int *id, size_t idlevel, unsigned int flags);
   3 
   4 void sysctlmif_freeobject(struct sysctlmif_object *object);

2.2.3. List functions

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

   1 struct sysctlmif_object_list *SYSCTLMIF_LIST(flags);

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

   1 typedef int sysctlmif_filterfunc_t (struct sysctlmif_object *object);
   2 
   3 struct sysctlmif_object_list *
   4 sysctlmif_filterlist(sysctlmif_filterfunc_t *filterfunc, unsigned int flags);

sysctlmif_grouplist() allocates memory and returns a SLIST(3) of struct 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.

   1 struct sysctlmif_object_list *
   2 sysctlmif_grouplist(int *id, size_t idlevel, unsigned int flags, unsigned int max_depth);

sysctlmif_freelist() free allocated memory by SYSCTLMIF_LIST(), sysctlmif_filterlist() and sysctlmif_grouplist().

   1 void sysctlmif_freelist(struct sysctlmif_object_list *list);

2.2.4. Tree functions

sysctlmif_tree() allocates memory for a tree of struct 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 LIST(3) macros.

The root may subsequently be used as an argument to sysctlmif_freetree().

   1 struct sysctlmif_object *
   2 sysctlmif_tree(int *id, size_t idlevel, unsigned int flags, unsigned int max_depth);
   3 
   4 void sysctlmif_freetree(struct sysctlmif_object *object_root);

2.3. Get/Set value

use sysctl(3) to get and set entry value:

   1 sysctl(id, idlevel, oldp, oldplen, newp, newplen);
   2 
   3 // or for a "struct sysctlmif_object obj"
   4 sysctl(obj->id, obj->idlevel, oldp, oldplen, newp, newplen);

2.4. Examples

2.5. Manual Page

Manual page: sysctlmibinfo.html or sysctlmibinfo.3.

2.6. Bugs

Problems from the kernel space:

3. Extra

3.1. Ideas

   1 /* 
   2  * flag for SYSCTLMIF_LIST, sysctlmif_filterlist and sysctlmif_grouplist,
   3  * use nextleaf() instead of default nextnode() 
   4  */
   5 #define SYSCTLMIF_FUSENEXTLEAF
   6 
   7 /*
   8  * flag for SYSCTLMIF_LIST, sysctlmif_filterlist sysctlmif_grouplist ant sysctlmif_tree(),
   9  * add "sysctl.*" entries
  10  */
  11 #define SYSCTLMIF_FINCLMIBMGR
  12 

3.2. Tools depending on sysctlmibinfo

AlfonsoSiciliano/sysctlmibinfo (last edited 2019-02-25 00:56:42 by AlfonsoSiciliano)