NETSNMP_CONFIG_API(3)

NETSNMP_CONFIG_API πŸ’–

okay bestie, welcome to the Net-SNMP config api page β€” this is NETSNMP_CONFIG_API(3), section three of the manual, and it's the whole entire vibe for how net-snmp reads its config files at runtime. pull up a chair, grab a strawberry πŸ“, we're doing this.


🌸 NAME 🌸

the squad. the whole roster. these are the netsnmp_config_api functions:

  • register_config_handler
  • register_const_config_handler
  • register_prenetsnmp_mib_handler
  • unregister_config_handler
  • register_mib_handlers
  • unregister_all_config_handlers
  • register_app_config_handler
  • register_app_prenetsnmp_mib_handler
  • unregister_app_config_handler
  • read_configs
  • read_premib_configs
  • read_config_print_usage
  • config_perror
  • config_pwarn

✨ SYNOPSIS ✨

#include <net-snmp/config_api.h>

πŸŽ€ Config Handlers πŸŽ€

struct config_line *
  register_config_handler(const char *filePrefix,
                     const char *token,
                     void (*parser)(const char *, char *),
                     void (*releaser)(void),
                     const char *usageLine);

struct config_line *
  register_const_config_handler(const char *filePrefix,
                     const char *token,
                     void (*parser)(const char *, const char *),
                     void (*releaser)(void),
                     const char *usageLine);

struct config_line *
  register_prenetsnmp_mib_handler(const char *filePrefix,
                     const char *token,
                     void (*parser)(const char *, char *),
                     void (*releaser)(void),
                     const char *usageLine);

void unregister_config_handler(const char *filePrefix,
                     const char *token);

void register_mib_handlers(void);
void unregister_all_config_handlers(void);

πŸ¦‹ Application Handlers πŸ¦‹

struct config_line *
  register_app_config_handler(const char *token,
                     void (*parser)(const char *, char *),
                     void (*releaser)(void),
                     const char *usageLine);

struct config_line *
  register_app_prenetsnmp_mib_handler(const char *token,
                     void (*parser)(const char *, char *),
                     void (*releaser)(void),
                     const char *usageLine);

void unregister_app_config_handler(const char *token);

πŸ“– Reading Configuration Files πŸ“–

void read_premib_configs(void);
void read_configs(void);

πŸ’… Help Strings and Errors πŸ’…

void read_config_print_usage(char *lead);
void config_pwarn(const char *string);
void config_perror(const char *string);

πŸ’œ DESCRIPTION πŸ’œ

okay so these functions are a whole fairly extensible system for parsing all kinds of configuration files while your application is already running. runtime parsing, we love to see it.

the config file flow is broken into these phases, in this exact order, no skipping:

  1. Registration of handlers. πŸ“
  2. Reading of the configuration files for pre-MIB parsing requirements. 🌱
  3. Reading and parsing of the textual MIB files. πŸ“š
  4. Reading of the configuration files for configuration directives. βš™οΈ
  5. Optionally re-reading the configuration files at a future date. πŸ”

the whole idea: your calling application gets to register handlers for certain tokens in certain named config files. then you call read_configs(), and it goes looking through all the relevant config files, matches the first word on each line against the list of registered tokens, and hands the rest of the line over to the matching registered handler. it's giving matchmaking but for config lines. πŸ’˜


πŸŽ€ REGISTERING A HANDLER πŸŽ€

register_config_handler()

registers a config handler routine, which should be called to process config directives that start with the specified token. for example:

register_config_handler("snmp", "exampleToken",
example_handler, NULL, "ARG1 [ARG2]");

this would register the example_handler() function so it gets called every single time the first word of a line in the snmp.conf configuration file(s) matches "exampleToken".

and who actually calls the appropriate handlers to process those config file directives? that's on read_configs() (peep below πŸ‘€).

register_const_config_handler()

basically the same as register_config_handler(), but the parser routine is explicitly constrained to not modify the string being parsed. no touchy. πŸ™…β™€οΈ

register_prenetsnmp_mib_handler()

also similar to register_config_handler(), except the registered handler routine gets called before the textual MIBs are read in. typically this is for tokens that affect the configuration of the MIB parser, and it'll normally only be used within the SNMP library itself. iykyk.

register_mib_handlers()

initialisation routine that registers the internal SNMP library configuration handlers. ✨

unregister_config_handler()

removes the registered config handler for the specified filePrefix and token. bye girl πŸ‘‹

unregister_all_config_handlers()

removes all registered config handlers. nuclear option, but make it cute. πŸ’₯

🧚 Token Handlers 🧚

handler functions should have this signature:

void handler(const char *token, char *line);
or
void handler(const char *token, const char *line); br (if
registered using register_const_config_handler)

the function gets called with two arguments:

  • the first is the token that triggered the call (i.e. the token you used when registering the handler),
  • the second is the remainder of the config file line β€” meaning everything after the whitespace that follows the matched token.

🫢 Freeing Handlers 🫢

if your token handler function dynamically allocates resources while processing a config entry, those might need to be released before the config files get re-read. so: if the fourth parameter (releaser) you passed to register_config_handler is non-NULL, then that's a function that gets called before re-reading the configuration files.

that function should free any resources allocated by the token handler and reset its notion of the configuration back to its default. after that, the token handler can safely be called again. 🧼

no arguments are passed to the resource-freeing function.

⚠️ heads up bestie: this function is not called when the handler is unregistered individually. it is called as part of unregister_all_config_handlers() though.

🌈 Application Handlers 🌈

register_app_config_handler()

register_app_prenetsnmp_mib_handler()

unregister_app_config_handler()

these three are analogous to register_config_handler(), register_prenetsnmp_mib_handler() and unregister_config_handler() β€” but they don't require the file type argument, because the application fills that in itself.

the intention: MIB modules written for the agent use these functions so the agent gets more control over which config files actually get read (typically the snmpd.conf files). πŸ‘‘


πŸ“š READING CONFIGURATION FILES πŸ“š

read_premib_configs()

read_configs()

these routines process the configuration files found in the configuration search path (see below ⬇️). for each entry, the handler registered for that config token gets called.

read_premib_configs() runs before the MIB files are read in, and it processes those config tokens registered using register_prenetsnmp_mib_handler() (or register_app_prenetsnmp_mib_handler()). all other entries are ignored. 🚫

read_configs() runs after the MIB files have been read in, and it processes those config tokens registered using register_config_handler() (or register_app_config_handler()). if it runs into a config token that has no handler registered (either pre- or post-mib), then it'll show a warning message and keep on processing with the next line of the config file. not me getting ignored at the function party 😭

🌸 Configuration Search Path 🌸

the config files to be read are found by searching a list of configuration directories for appropriately named files. in each such directory, the library looks for files named:

  • snmp.conf
  • snmp.local.conf
  • app.conf
  • app.local.conf

(where app is the application-specific filePrefix used to register configuration handlers).

it is not necessary for any or all of these files to be present in each directory β€” missing files get silently skipped. no drama. ✨

the idea behind the two different suffixes: the first file can be shared (via rdist or an NFS mount) across a large number of machines, and the second file can be used to configure local settings for one particular machine. one for the group chat, one for your diary. πŸ’Œ

the default list of directories to search is:

  1. /etc/snmp
  2. then /usr/share/snmp
  3. then /usr/lib(64)/snmp
  4. then $HOME/.snmp

and you can change this whole list by setting the environment variable SNMPCONFPATH to be a (colon-separated) list of directories to search. slay. πŸ’…

πŸ‘‘ init_snmp() πŸ‘‘

the normal mode of operation: register the application-specific configuration handlers, then invoke init_snmp(). that would call the routines listed above to register the internal library configuration handlers, process any config tokens registered with register_prenetsnmp_mib_handler(), read in the textual MIB files using init_mib(), and finally parse the config file tokens registered with register_config_handler().

and if you use the init_snmp() function, then none of these functions need to be explicitly called by the application. it just handles it. main character energy. 🌟


πŸ’– HELP STRINGS AND ERRORS πŸ’–

the usageLine parameter you pass to register_config_handler() and similar calls is what displays help info when the read_config_print_usage() function gets called. this function is used by all of the applications when the -H flag is passed on the command line.

it prints a summary of all the configuration file lines, and the associated files, that the config system understands. so the usageLine parameter should be a list of arguments expected after the token β€” not a lengthy description (that belongs in a manual page instead, bestie, we don't do essays in usage strings πŸ“).

the lead prefix gets prepended to each line that the function prints to stderr, which is where it displays its output.

🫢 and pls: the init_snmp() function should be called before the read_config_print_usage() function is called, so the library can register its own configuration file directives as well, for read_config_print_usage() to display.

πŸ“ Error Handling Functions πŸ“

the two functions config_pwarn() and config_perror() both take an error string as an argument and print it to stderr, along with the file and line number that caused the error. πŸ”

and a call to the second one β€” config_perror() β€” will also force read_configs() to eventually return with an error code, telling its calling function that it should abort the operation of the application. so yeah, that one's the serious one. πŸ’€

🌸 ENVIRONMENT VARIABLES 🌸

okay bestie this is the part where the environment gets a say in things, and honestly? it's giving main character energy for one single variable πŸ’…

  • SNMPCONFPATH β€” a colon-separated list of directories to go hunting through for configuration files πŸ”βœ¨ like, it's a whole lil scavenger hunt and every directory between the colons is a spot to check. the default is:
/etc/snmp:/usr/share/snmp:/usr/lib(64)/snmp:$HOME/.snmp
no cap, that's the actual default string, (64) and $HOME and all β€” copy it exactly as it's written, don't get cute with it πŸ™ˆ

πŸ¦‹ SEE ALSO πŸ¦‹

go read these next, fr fr, they're the besties of this page:


and that's a wrap on this one, gorgeous πŸŽ€ you made it all the way to the end of the page, which is honestly iconic behavior πŸ‘‘

this whole thing is NETSNMP_CONFIG_API(3) β€” version V5.9.5.2, dated 13 Aug 2010 ✨

periodt. go configure something πŸ’…πŸ’–

πŸ“¦ where this page comes from