snmpa(3)

πŸ“¦
version 29.0.6 Β· 3 versions
, in ubuntu stonking

πŸ‘‘ snmpa β€” the Erlang/OTP manual page, bestie edition πŸ’…

okay so this is snmpa(3), aka Erlang Module Definition energy, and it's literally the interface you use to talk to the SNMP toolkit agent. she's long, she's iconic, and she comes in parts β€” this is part 1, so buckle up πŸŽ€


🌸 NAME 🌸

snmpa β€” Interface Functions to the SNMP toolkit agent. no cap, that's the whole name, that's her πŸ’–


✨ DESCRIPTION ✨

so the module snmpa contains interface functions to the SNMP agent. that's it, that's the vibe, she's the plug between you and the agent 🫢


πŸ¦‹ DATA TYPES πŸ¦‹

let's do the type tour bestie, don't skip it, these are the building blocks:

  • db() :: volatile | persistent | mnesia β€” the three flavours of database, pick your fighter 🌈
  • discovery_handler() :: module() β€” a module that implements the snmpa_discovery_handler behaviour 🧚
  • me() :: snmp:me() β€” just snmp's me() type, nothing new here πŸ’œ
  • mib_storage() :: [mib_storage_opt()] β€” a list of mib storage options, cute list energy ✨
  • mib_storage_module() :: atom() β€” an atom. so simple. so powerful. πŸ’…
  • mib_storage_opt() ::
{module, mib_storage_module()} |
{options, mib_storage_options()}

the two shapes a mib storage option can take πŸŽ€

  • mib_storage_options() :: list() β€” yes bestie, just a plain list πŸ“‹
  • name() :: table_name() | variable_name() β€” could be a table name, could be a variable name, she contains multitudes πŸ‘‘
  • name_db() :: {name(), db()} β€” a name() and its db(), holding hands 🫢
  • nfilter_id() :: term() β€” literally any term, she's chill like that 🌸
  • nfilter_position() ::
first | last |
{insert_before, nfilter_id()} |
{insert_after, nfilter_id()}

where you wanna slot your notification filter in, front, back, or snuggled up next to another one πŸ¦‹

  • notification_delivery_info() :: snmpa_notification_delivery_info_receiver:notification_delivery_info() β€” how shall (notification) delivery info be reported? exactly like that, bestie πŸ’–
  • pdu_type() :: snmp:pdu_type() β€” straight from snmp, no notes πŸ“¦
  • table_name() :: atom() β€” an atom, serving atom realness ⭐
  • transport_kind() :: req_responder | trap_sender β€” are you the request responder or the trap sender? both are valid, both are main characters πŸ’Œ
  • variable_name() :: atom() β€” also an atom. twin energy with table_name(), periodt ✨

πŸ”₯ FUNCTIONS πŸ”₯

here comes the actual menu, this is where it gets good πŸ˜­πŸ‘‡

πŸ’– add_agent_caps(Oid, Descr) -> Index

add_agent_caps(Oid, Descr) -> Index
    when
        Oid :: snmp:oid(),
        Descr :: string(),
        Index :: integer().

this function can be used to add an AGENT-CAPABILITY statement to the sysORTable in the agent. the table is defined in the SNMPv2-MIB. adding capabilities? we love to see it πŸŽ€

πŸ’– backup(Agent, BackupDir) -> ok | {error, Reason}

backup(Agent, BackupDir) -> ok | {error, Reason}
    when
        Agent :: pid() | AgentName,
        AgentName :: atom(),
        BackupDir :: string(),
        Reason :: backup_in_progress | term().

backup the persistent/permanent data handled by the agent (such as local-db, mib-data and vacm). self-care is backing up your data, bestie πŸ’Ύβœ¨

data stored by mnesia is not handled. nope, not her, mnesia handles herself πŸ’…

BackupDir cannot be identical to DbDir. that's a hard no πŸ™…

simultaneous backup calls are not allowed. that is, two different processes cannot simultaneously successfully call this function. one of them will be first, and succeed. the second will fail with the error reason backup_in_progress. it's giving "one at a time, we're not doing chaos here" 😀

no gatekeeping: only one backup can win. the other one gets backup_in_progress and has to wait her turn.

πŸ’– change_log_size(NewSize) -> ok | {error, Reason}

change_log_size(NewSize) -> ok | {error, Reason}
    when
        NewSize :: snmp:log_size(),
        Reason :: term().

changes the log size of the Audit Trail Log. the application must be configured to use the audit trail log function. please refer to disk_log(3) in Kernel Reference Manual for a description of how to change the log size πŸ“–

the change is permanent, as long as the log is not deleted. that means, the log size is remembered across reboots. she remembers πŸ‘‘πŸ’–

πŸ’– convert_config(OldConfig) -> NewConfig

convert_config(OldConfig) -> NewConfig
    when OldConfig :: list(), NewConfig :: list().

this off-line utility function can be used to convert the old snmp application config (pre snmp-4.0) to the new snmp agent config (as of snmp-4.0). glow-up machine fr fr βœ¨πŸ¦‹

for information about the old config (OldConfig) see the OTP R9C documentation.

for information about the current agent config (AgentConfig), see the Configuring the application chapter of the SNMP user's guide.

πŸ’– current_address() -> {value, Address} | false

current_address() -> {value, Address} | false
    when Address :: term().

get the address of the request currently being processed by the agent πŸ“¬

note that this function is intended to be called by the instrumentation functions and only if it is executed in the context of the agent process (e.g. it does not work if called from a spawned process). so like, stay in your lane β€” the agent process lane πŸ’€

πŸ’– current_community() -> {value, Community} | false

current_community() -> {value, Community} | false
    when Community :: snmp_community_mib:name().

get the community of the request currently being processed by the agent 🌍

note that this function is intended to be called by the instrumentation functions and only if it is executed in the context of the agent process (e.g. it does not work if called from a spawned process). same rules, bestie, no exceptions πŸ™ˆ

πŸ’– current_context() -> {value, Context} | false

current_context() -> {value, Context} | false
    when
        Context :: snmp_community_mib:context_name().

get the context of the request currently being processed by the agent πŸ“Ž

note that this function is intended to be called by the instrumentation functions and only if it is executed in the context of the agent process (e.g. it does not work if called from a spawned process). context is everything, literally πŸ’œ

πŸ’– current_request_id() -> {value, RequestId} | false

current_request_id() -> {value, RequestId} | false
    when RequestId :: integer().

get the request-id of the request currently being processed by the agent πŸ†”

note that this function is intended to be called by the instrumentation functions and only if it is executed in the context of the agent process (e.g. it does not work if called from a spawned process). do not try this from a spawned process, she will simply not answer 😭

πŸ’– del_agent_caps(Index) -> snmp:void()

del_agent_caps(Index) -> snmp:void()
    when Index :: integer().

this function can be used to delete an AGENT-CAPABILITY statement to the sysORTable in the agent. this table is defined in the SNMPv2-MIB. add era over, now we're in the delete era πŸ—‘οΈβœ¨

πŸ’– disable_mibs_cache(Agent) -> snmp:void()

disable_mibs_cache(Agent) -> snmp:void()
    when
        Agent :: pid() | AgentName,
        AgentName :: atom().

disable the mib server cache. we're going caches-off, raw dogging the mib server (respectfully) πŸ’…

πŸ’– disable_mibs_cache_autogc(Agent) -> snmp:void()

disable_mibs_cache_autogc(Agent) -> snmp:void()
    when
        Agent :: pid() | AgentName,
        AgentName :: atom().

disable automatic gc of the mib server cache. auto-cleanup? not today bestie, we're doing it manually 🧹

πŸ’– discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler, ExtraInfo) -> {ok, ManagerEngineID} | {error, Reason}

discovery(TargetName, Notification, ContextName, Varbinds,
          DiscoHandler, ExtraInfo) ->
    {ok, ManagerEngineID} | {error, Reason}
    when
        TargetName :: string(),
        Notification :: atom(),
        ContextName :: snmp_community_mib:context_name(),
        Varbinds :: [Varbind],
        Varbind ::
            {Variable, Value} |
            {Column, RowIndex, Value} |
            {OID, Value},
        Variable :: atom(),
        Column :: atom(),
        RowIndex :: snmp:row_index(),
        OID :: snmp:oid(),
        Value :: term(),
        DiscoHandler :: discovery_handler(),
        ExtraInfo :: term(),
        ManagerEngineID :: snmp_framework_mib:engine_id(),
        Reason :: term().

initiate the discovery process with the manager identified by TargetName using the notification Notification. it's giving first contact πŸ€πŸ›Έ

this function is synchronous, which means that it will return when the discovery process has been completed or failed. she waits. she commits. no half-sending πŸ“¨

the DiscoHandler module is used during the discovery process. see discovery handler for more info.

the ExtraInfo argument is passed on to the callback functions of the DiscoHandler. little gift-wrapped parcel of data 🎁

NOTE: if we are not at security-level noAuthNoPriv, this could be complicated, since the agent will then continue with stage 2, before which the usm-related updates must be done. 😳
NOTE: the default discovery handler will require additional actions by the caller and the discovery will not work if the security-level is higher then noAuthNoPriv. hello? yes, that's a real warning, read it twice πŸ”₯

πŸ’– enable_mibs_cache(Agent) -> snmp:void()

enable_mibs_cache(Agent) -> snmp:void()
    when
        Agent :: pid() | AgentName,
        AgentName :: atom().

enable the mib server cache. we're so back, caching era 😌🌟

πŸ’– enable_mibs_cache_autogc(Agent) -> snmp:void()

enable_mibs_cache_autogc(Agent) -> snmp:void()
    when
        Agent :: pid() | AgentName,
        AgentName :: atom().

enable automatic gc of the mib server cache. the cache cleans itself now, she's independent, we love a self-sufficient queen πŸ‘‘πŸ§Ή

πŸ’– enum_to_int(Db, Name, Enum) -> {value, Int} | false

enum_to_int(Db, Name, Enum) -> {value, Int} | false
    when
        Db :: term(),
        Name :: atom(),
        Enum :: atom(),
        Int :: integer().

converts the symbolic value Enum to the corresponding integer of the enumerated object or type Name in a MIB. the MIB must be loaded πŸ“š

false is returned if the object or type is not defined in any loaded MIB, or if it does not define the symbolic value as enumerated. false really said "not my problem" πŸ™…β™€οΈ

Db is a reference to the symbolic store database (retrieved by a call to get_symbolic_store_db/0). yes, that exact call, write it down πŸ“

πŸ’– gc_mibs_cache(Agent, Age, GcLimit) -> {ok, NumElementsGCed} | {error, Reason}

gc_mibs_cache(Agent, Age, GcLimit) ->
    {ok, NumElementsGCed} | {error, Reason}
    when
        Agent :: pid() | AgentName,
        AgentName :: atom(),
        Age :: pos_integer(),
        GcLimit :: pos_integer() | infinity,
        NumElementsGCed :: non_neg_integer(),
        Reason :: term().

perform mib server cache gc 🧼

manually performs a mib server cache gc. this can be done regardless of the value of the autogc option. the NumElementsGCed value indicates how many elements where actually removed from the cache. that's the receipt, bestie, count your deleted elements πŸ’…

πŸ’– get(Agent, Vars, Context) -> Values | {error, Reason}

get(Agent, Vars, Context) -> Values | {error, Reason}
    when
        Agent :: pid() | AgentName,
        AgentName :: atom(),
        Vars :: [snmp:oid()],
        Context :: snmp_community_mib:context_name(),
        Values :: [term()],
        Reason :: term().

performs a GET operation on the agent. all loaded MIB objects are visible in this operation. the agent calls the corresponding instrumentation functions just as if it was a GET request coming from a manager πŸ“₯✨

note that the request specific parameters (such as current_request_id/0) are not accessible for the instrumentation functions if this function is used. nope, not available, don't even try, she said no πŸ™ˆ


get_agent_caps()

get_agent_caps() -> Caps
                        when
                            Caps :: [[Cap]],
                            Cap ::
                                SysORIndex | SysORID | SysORDescr |
                                SysORUpTime,
                            SysORIndex :: integer(),
                            SysORID :: snmp:oid(),
                            SysORDescr :: string(),
                            SysORUpTime :: integer().

okay so bestie, this one hands you back literally every single AGENT-CAPABILITY statement chilling in the agent's sysORTable 🫢 and that table? it lives in the SNMPv2-MIB, so you know it's iconic πŸ’…

ngl the Erlang type language is out here refusing to properly describe what this function returns 😭 so here's the actual tea, no cap: the exact return is [[SysORIndex, SysORID, SysORDescr, SysORUpTime]] ✨

get_next(Agent, Vars, Context) -> Values | {error, Reason}

get_next(Agent, Vars, Context) -> Values | {error, Reason}
                  when
                      Agent :: pid() | AgentName,
                      AgentName :: atom(),
                      Vars :: [snmp:oid()],
                      Context :: snmp_community_mib:context_name(),
                      Values :: [{snmp:oid(), term()}],
                      Reason :: {atom(), snmp:oid()}.

This does a GET-NEXT operation on the agent πŸ”₯ Every loaded MIB object is visible in this operation β€” all of them, periodt. The agent calls the corresponding instrumentation functions exactly like it was a GET request coming from a manager, so the whole vibe is identical πŸ’–

heads up though: the request specific parameters (like snmpa:current_request_id/0) are not accessible for the instrumentation functions if this function is used πŸ™ˆ

info(Agent) -> Info

info(Agent) -> Info
              when
                  Agent :: pid() | AgentName,
                  AgentName :: atom(),
                  Info :: [{Key, Value}],
                  Key :: term(),
                  Value :: term().

Returns a list (a dictionary, iykyk) stuffed with information about the agent 🌸 The info includes loaded MIBs, registered sub-agents, and some information about the memory allocation πŸ‘‘

int_to_enum(Db, Name, Int) -> {value, Enum} | false

int_to_enum(Db, Name, Int) -> {value, Enum} | false
                     when
                         Db :: term(),
                         Name :: atom(),
                         Int :: integer(),
                         Enum :: atom().

Converts the integer Int into the corresponding symbolic value of the enumerated object or type Name in a MIB πŸ¦‹ The MIB must be loaded, no exceptions bestie.

false gets returned if the object or type isn't defined in any loaded MIB, or if it doesn't define the symbolic value as enumerated πŸ’€

And Db? That's a reference to the symbolic store database (you get it by calling get_symbolic_store_db/0) ✨

invalidate_mibs_cache(Agent) -> snmp:void()

invalidate_mibs_cache(Agent) -> snmp:void()
                               when
                                   Agent :: pid() | AgentName,
                                   AgentName :: atom().

Invalidates the mib server cache. That's it, that's the whole thing 😌 The entire contents of the cache will be deleted β€” like, gone gone. Total main character move, wipe the whole slate πŸ’…

load_mib(Agent, Mib) -> ok | {error, Reason}

load_mib(Agent, Mib) -> ok | {error, Reason}
                  when
                      Agent :: pid() | AgentName,
                      AgentName :: atom(),
                      Mib :: string(),
                      Reason :: already_loaded | term().

Loads a single Mib into an agent 🌈 The MibName is the name of the Mib, and yes bestie that includes the path to where the compiled mib is found πŸŽ€ For example:

Dir = code:priv_dir(my_app) ++ "/mibs/",
snmpa:load_mib(snmp_master_agent, Dir ++ "MY-MIB").

load_mibs(Agent, Mibs, Force) -> ok | {error, Reason}

load_mibs(Agent, Mibs, Force) -> ok | {error, Reason}
                   when
                       Agent :: pid() | AgentName,
                       AgentName :: atom(),
                       Mibs :: [MibName],
                       MibName :: string(),
                       Force :: boolean(),
                       Reason ::
                           {'load aborted at', MibName, InternalReason},
                       InternalReason :: already_loaded | term().

Loads Mibs into an agent, plural, we're doing a whole batch now πŸ’– If the agent can't load all the MIBs (the default value of the Force argument is false), it will indicate where loading was aborted β€” so you know exactly where it gave up 😭 The MibName is the name of the Mib, including the path to where the compiled mib is found πŸ”₯ For example:

Dir = code:priv_dir(my_app) ++ "/mibs/",
snmpa:load_mibs(snmp_master_agent, [Dir ++ "MY-MIB"]).

If Force = true then the agent will keep attempting to load each mib even after failing to load a previous mib πŸ‘€

fr fr use with care β€” that's the original warning, I'm just making it sparkle ✨

log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}

log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) ->
                   ok | {ok, Cnt} | {error, Reason}
                   when
                       LogDir :: string(),
                       Mibs :: [snmp:mib_name()],
                       LogName :: string(),
                       LogFile :: string(),
                       Block :: boolean(),
                       Start :: null | snmp:log_time(),
                       Stop :: null | snmp:log_time(),
                       Cnt :: {NumOK, NumERR},
                       NumOK :: non_neg_integer(),
                       NumERR :: pos_integer(),
                       Reason :: term().

Converts an Audit Trail Log into a readable format and prints it right on stdio πŸ“Ί LogName defaults to "snmpa_log" and LogFile defaults to "snmpa.log" πŸ“

The Block option says whether the log should be blocked during conversion 🫢 This is lowkey so useful when converting large logs (because otherwise the log could wrap during conversion and ruin everything 😭). It defaults to true.

See snmp:log_to_io/7 for more info ✨

log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> snmp:void()

log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start,
                 Stop) ->
                    snmp:void()
                    when
                        LogDir :: snmp:dir(),
                        Mibs :: [snmp:mib_name()],
                        OutFile :: file:filename(),
                        LogName :: string(),
                        LogFile :: string(),
                        Block :: boolean(),
                        Start :: null | snmp:log_time(),
                        Stop :: null | snmp:log_time().

Same energy as above but it converts an Audit Trail Log into a readable text file instead πŸ“„ OutFile defaults to "./snmpa_log.txt", LogName defaults to "snmpa_log", and LogFile defaults to "snmpa.log" 🌸

Block again decides whether the log gets blocked during conversion β€” great for those big chonky logs where wrapping would otherwise happen mid-conversion πŸ’… defaults to true.

See snmp:log_to_txt/8 for more info πŸ’œ

me_of(Agent, Oid) -> {ok, Me} | {error, Reason}

me_of(Agent, Oid) -> {ok, Me} | {error, Reason}
               when
                   Agent :: pid() | AgentName,
                   AgentName :: atom(),
                   Oid :: snmp:oid(),
                   Me :: snmp:me(),
                   Reason :: term().

Finds the mib entry corresponding to the Oid πŸ”

But listen carefully bestie, the Oid has to be in the right shape or it's not gonna work:

  • if it's a variable, the Oid must be <Oid for var>.0
  • if it's a table, Oid must be <table>.<entry>.<col>.<any>

periodt πŸ’…

mib_of(Agent, Oid) -> {ok, MibName} | {error, Reason}

mib_of(Agent, Oid) -> {ok, MibName} | {error, Reason}
                when
                    Agent :: pid() | AgentName,
                    AgentName :: atom(),
                    Oid :: snmp:oid(),
                    MibName :: atom(),
                    Reason :: term().

Finds the mib corresponding to the Oid 🌈

Same shape rules, no skipping:

  • if it's a variable, the Oid must be <Oid for var>.0
  • if it's a table, Oid must be <table>.<entry>.<col>.<any>.

name_to_oid(Db, Name) -> {value, Oid} | false

name_to_oid(Db, Name) -> {value, Oid} | false
                     when
                         Db :: term(), Name :: atom(), Oid :: snmp:oid().

Looks up the OBJECT IDENTIFIER of a MIB object, given the symbolic name πŸ”Ž

Note: the OBJECT IDENTIFIER is given for the object, not for an instance πŸ‘‘

false is returned if the object isn't defined in any loaded MIB πŸ’€

Db is a reference to the symbolic store database (retrieved by a call to get_symbolic_store_db/0) ✨

oid_to_name(Db, Oid) -> {value, Name} | false

oid_to_name(Db, Oid) -> {value, Name} | false
                     when
                         Db :: term(), Oid :: snmp:oid(), Name :: atom().

The glow-up of the previous one β€” looks up the symbolic name of a MIB object, given the OBJECT IDENTIFIER πŸ¦‹

false is returned if the object isn't defined in any loaded MIB 😭

Db is a reference to the symbolic store database (retrieved by a call to get_symbolic_store_db/0) πŸ’œ

Prints the content of all the (snmp) tables and variables for all mibs handled by the snmp agent πŸ–¨οΈβœ¨ everything, all at once, the whole buffet.

Prints the content of all the (snmp) tables for all mibs handled by the snmp agent πŸŽ€ just the tables this time, tables only vibes.

Prints the content of all the (snmp) variables for all mibs handled by the snmp agent 🌸 variables only, we're being selective bestie.


register_notification_filter(Agent | Id, Id | Mod, Mod | Data, Data | Where) -> ok | {error, Reason}

register_notification_filter(Agent | Id,
                                   Id | Mod,
                                   Mod | Data,
                                   Data | Where) ->
                                      ok | {error, Reason}
                                      when
                                          Agent :: pid() | AgentName,
                                          AgentName :: atom(),
                                          Id :: nfilter_id(),
                                          Mod :: module(),
                                          Data :: term(),
                                          Where :: nfilter_position(),
                                          Reason :: term().

Accepted type specifications are:

-spec register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}.
-spec register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}.

register_notification_filter(Agent, Id, Mod, Data, Where) -> ok | {error, Reason}

register_notification_filter(Agent, Id, Mod, Data, Where) ->
                                      ok | {error, Reason}
                                      when
                                          Agent :: pid() | AgentName,
                                          AgentName :: atom(),
                                          Id :: nfilter_id(),
                                          Mod :: module(),
                                          Data :: term(),
                                          Where :: nfilter_position(),
                                          Reason :: term().

okay so wrapping up the notification-filter registration real quick πŸ’… β€” yes, it registers a notification filter. Mod is a module implementing the snmpa_notification_filter behaviour, and that Data you hand in gets passed on to the filter whenever the behaviour's functions get called. cute, simple, done. πŸŽ€


πŸ¦‹ register_subagent

register_subagent(Agent, SubTree, SubAgent) ->
                          ok | {error, Reason}
                          when
                              Agent :: pid() | AgentName,
                              AgentName :: atom(),
                              SubTree :: snmp:oid(),
                              SubAgent :: pid(),
                              Reason :: term().

Registers a sub-agent under a sub-tree of another agent. 🌈

⚠️ bestie, LISTEN. it is so easy to mess up sub-agent registration, and this is a "do it carefully" situation, no cap. like, check out this config and tell me it isn't giving total chaos:
snmp_agent:register_subagent(MAPid,[1,2,3,4],SA1),
snmp_agent:register_subagent(SA1,[1,2,3], SA2).

SA2 will not get requests starting with object identifier [1,2,3] since SA1 does not. yeah. πŸ’€ that's just how it goes. register responsibly.


πŸ”₯ restart_set_worker

restart_set_worker(Agent) -> snmp:void()
                           when
                               Agent :: pid | AgentName,
                               AgentName :: atom().

Restarts the set worker process of a multi-threaded agent. ✨

This one is a utility function, and it's genuinely useful when you're like… debugging your instrumentation functions. lowkey a lifesaver fr fr. 🫢


πŸ‘‘ restart_worker

restart_worker(Agent) -> snmp:void()
                       when
                           Agent :: pid | AgentName,
                           AgentName :: atom().

Restarts the worker process of a multi-threaded agent. ✨

Also a utility function, also useful when you're e.g. debugging instrumentation functions. same energy, different worker. πŸ’…


🌸 send_notification

send_notification(Agent, Notification, Receiver, NotifyName,
                       ContextName, Varbinds, LocalEngineID) ->
                          snmp:void()
                          when
                              Agent :: pid() | AgentName,
                              AgentName :: atom(),
                              Notification :: atom(),
                              Receiver ::
                                  no_receiver |
                                  {Tag, Recv} |
                                  notification_delivery_info(),
                              Tag :: term(),
                              Recv :: pid() | atom() | MFA,
                              MFA :: {Mod, Func, Args},
                              Mod :: module(),
                              Func :: atom(),
                              Args :: list(),
                              NotifyName ::
                                  snmp_notification_mib:notify_name(),
                              ContextName ::
                                  snmp_community_mib:context_name(),
                              Varbinds :: [Varbind],
                              Varbind ::
                                  {Variable, Value} |
                                  {Column, RowIndex, Value} |
                                  {Oid, Value},
                              Variable :: atom(),
                              Column :: atom(),
                              RowIndex :: snmp:row_index(),
                              Oid :: snmp:oid(),
                              Value :: term(),
                              LocalEngineID ::
                                  snmp_framework_mib:engine_id().

okay this is the big one, the main character of the whole file, the icon, the legend. πŸ’–

It sends the notification Notification to the management targets defined for NotifyName in the snmpNotifyTable in SNMP-NOTIFICATION-MIB from the specified context. periodt.

If no NotifyName is specified (or if it's ""), the notification goes out to all management targets (that's Addresses down below, keep reading bestie). 🎯

If no ContextName is specified, the default "" context is used. easy.

The parameter Receiver specifies where info about the delivery of Inform-Requests should be sent. The agent sends Inform-Requests and then waits for acknowledgments from the managers. Receiver can have three values:

  • no_receiver β€” no information is delivered. silence. the void. πŸ•³οΈ
  • notification_delivery_info/0 β€” the information is delivered via a function call according to this data.
  • {Tag, Recv} β€” the information is delivered either via messages or via a function call, according to the value of Recv.

If Receiver has the value {Tag, Recv}, the delivery is done according to Recv:

  • pid() | atom() β€” the info gets delivered in the following messages:
    • {snmp_targets, Tag, Addresses} β€” this informs the user which target addresses the notification was sent to.
    • {snmp_notification, Tag, {got_response, Address}} β€” this informs the user that this target address acknowledged the notification. πŸŽ‰
    • {snmp_notification, Tag, {no_response, Address}} β€” this informs the user that this target address did not acknowledge the notification. 😭

The notification is sent as an Inform-Request to each target address in Addresses, and if there are no targets for which an Inform-Request is sent, Addresses is the empty list [].

The receiver first gets the snmp_targets message, and then for each address in the Addresses list, one of the two snmp_notification messages. in that order, every time. ✨

  • {Mod, Func, Args} β€” the info gets delivered via the function call:
Mod:Func([Msg | Args])

where Msg has the same content and purpose as the messages descrived above.

Address is a management target address and Addresses is a list of management target addresses. They are defined as followes:

               Addresses  = [address()]
               Address    = address()
               address()  = v1_address() | v3_address()
               v1_address() = {TDomain, TAddress}
               v3_address() = {{TDomain, TAddress}, V3MsgData}
               TDomain    = tdoamin()
               TAddress   = taddress()
               tdomain()  = The oid of snmpUDPDomain
                            This is the only supported transport domain.
               taddress() = [A1, A2, A3, A4, P1, P3]
                            The 4 first bytes makes up the IP-address and the last 2,
                            the UDP-port number.
               V3MsgData  = v3_msg_data()
               v3_msg_data() = term()

If Receiver is a notification_delivery_info/0 record, then the information about the notification delivery gets delivered to the receiver via the callback functions defined by the snmpa_notification_delivery_info_receiver behaviour, according to the content of that notification_delivery_info/0 record. ✨

The optional argument Varbinds defines values for the objects in the notification. If no value is given for an object, the Agent performs a get-operation to retrieve the value. (yes, it'll go ask for you, it's helpful like that 🫢)

Varbinds is a list of Varbind, where each Varbind is one of:

  • {Variable, Value}, where Variable is the symbolic name of a scalar variable referred to in the notification specification.
  • {Column, RowIndex, Value}, where Column is the symbolic name of a column variable. RowIndex is a list of indices for the specified element. If this is the case, the OBJECT IDENTIFIER sent in the notification is the RowIndex appended to the OBJECT IDENTIFIER for the table column. This is the OBJECT IDENTIFIER which specifies the element.
  • {OID, Value}, where OID is the OBJECT IDENTIFIER for an instance of an object, scalar variable, or column variable.

For example, to specify that sysLocation should have the value "upstairs" in the notification, we could use one of:

  • {sysLocation, "upstairs"} or
  • {[1,3,6,1,2,1,1,6,0], "upstairs"} or
  • {?sysLocation_instance, "upstairs"} (provided that the generated .hrl file is included)

If a variable in the notification is a table element, the RowIndex for the element must be given in the Varbinds list. In this case, the OBJECT IDENTIFIER sent in the notification is the OBJECT IDENTIFIER that identifies this element. That OBJECT IDENTIFIER could be used in a get operation later. iykyk πŸ’…

This function is asynchronous, and does not return any information. If an error occurs, user_err/2 of the error report module is called and the notification is discarded. so… no return value bestie, don't go looking for one. πŸ’€

🚨 NOTE: note that the use of the LocalEngineID argument is only intended for special cases, like if the agent is to "emulate" multiple EngineIDs! By default, the agent uses the value of SnmpEngineID (see SNMP-FRAMEWORK-MIB). so like, don't just use it for funsies, okay? πŸ™ˆ

ExtraInfo is not normally used in any way by the agent. It is intended to be passed along to the net-if process, which is a component that a user can implement themself. The users own net-if may then make use of ExtraInfo. The net-if provided with this application does not process ExtraInfo.

There is one exception. πŸ”₯ Any tuple containing the atom snmpa_default_notification_extra_info will, in this context, be considered belonging to this application, and may be processed by the agent. so that's the one little loophole, and it's iconic for it. πŸ‘‘


✨ send_notification2/3 ✨

send_notification2(Agent, Notification, SendOpts) -> snmp:void()
                                   when
                                       Agent :: pid() | AgentName,
                                       AgentName :: atom(),
                                       Notification :: atom(),
                                       SendOpts :: [SendOpt],
                                       SendOpt ::
                                           {receiver, Receiver} |
                                           {name,
                                            snmp_notification_mib:notify_name()}
       |
                                           {context,
                                            snmp_community_mib:context_name()}
       |
                                           {varbinds, [Varbind]} |
                                           {local_engine_id,
                                            snmp_framework_mib:engine_id()} |
                                           {extra, term()},
                                       Receiver ::
                                           no_receiver |
                                           {Tag, Recv} |
                                           notification_delivery_info(),
                                       Tag :: term(),
                                       Recv :: pid() | atom() | MFA,
                                       MFA :: {Mod, Func, Args},
                                       Mod :: module(),
                                       Func :: atom(),
                                       Args :: list(),
                                       Varbind ::
                                           {Variable, Value} |
                                           {Column, RowIndex, Value} |
                                           {Oid, Value},
                                       Variable :: atom(),
                                       Column :: atom(),
                                       RowIndex :: snmp:row_index(),
                                       Oid :: snmp:oid(),
                                       Value :: term().

Okay bestie, so this one sends the notification Notification to the management targets defined for notify-name (name) in the snmpNotifyTable in SNMP-NOTIFICATION-MIB from the specified context. πŸ’…

If no name is specified (or if it is ""), the notification is sent to all management targets. No cap.

If no context is specified, the default context, "", is used. The vibes are default. 🌸

The send option receiver specifies where information about delivery of Inform-Requests should be sent. The agent sends Inform-Requests and waits for acknowledgments from the management targets. The receiver can have three values:

  • no_receiver β€” no information is delivered. It's giving silent treatment. πŸ™ˆ
  • notification_delivery_info/0 β€” the information is delivered via a function call according to this data.
  • {tag(), tag_receiver()} β€” the information is delivered either via messages or via a function call according to the value of tag_receiver().

Delivery is done differently depending on the value of tag_receiver():

  • pid() | registered_name() β€” the info will be delivered in the following messages:
    • {snmp_targets, tag(), Addresses} β€” this informs the user which target addresses the notification was sent to.
    • {snmp_notification, tag(), {got_response, Address}} β€” this informs the user that this target address acknowledged the notification.
    • {snmp_notification, tag(), {no_response, Address}} β€” this informs the user that this target address did not acknowledge the notification.

The notification is sent as an Inform-Request to each target address in Addresses and if there are no targets for which an Inform-Request is sent, Addresses is the empty list [].

The tag_receiver() will first be sent the snmp_targets message, and then for each address in Addresses list, one of the two snmp_notification messages.

  • {Mod, Func, Args} β€” the info will be delivered via the function call:
Mod:Func([Msg | Args])

where Msg has the same content and purpose as the messages descrived above. (Yes, "descrived" β€” we're keeping the original typo, periodt. πŸ’€)

The 'process oid' "tag" that can be provided with the variable name / oids is intended to be used for oid post processing. The value 'keep', which is the default, leaves the oid as is. The value 'truncate', will cause the oid to be "truncated". That is, any trailing ".0" will be removed. Slay. ✨

NOTE: There is a way to exclude a varbind from the notification. In the normal varbinds list, providing the special value '$ignore-oid' (instead of a normal value) will exclude this varbind from the notification. A define for this has been added to the snmp_types.hrl include file, NOTIFICATION_IGNORE_VB_VALUE.
NOTE: The extra info is not normally interpreted by the agent, instead it is passed through to the net-if process. It is up to the implementor of that process to make use of this data. The version of net-if provided by this application makes no use of this data, with one exception: Any tuple containing the atom snmpa_default_notification_extra_info may be used by the agent and is therefore reserved. See the net-if incoming messages for sending a trap and notification for more info.

✨ set_log_type/2 ✨

set_log_type(Agent, NewType) -> {ok, OldType} | {error, Reason}
                             when
                                 Agent :: pid() | AgentName,
                                 AgentName :: atom(),
                                 NewType :: snmp:atl_type(),
                                 OldType :: snmp:atl_type(),
                                 Reason :: term().

Changes the run-time Audit Trail log type. πŸ’–

Note that this has no effect on the application configuration as defined by configuration files, so a node restart will revert the config to whatever is in those files. (So don't think it's permanent, bestie. 😭)

This function is primarily useful in testing/debugging scenarios. πŸ§ͺ


✨ set_request_limit/2 ✨

set_request_limit(Agent, NewLimit) ->
                                  {ok, OldLimit} | {error, Reason}
                                  when
                                      Agent :: pid() | AgentName,
                                      AgentName :: atom(),
                                      NewLimit :: infinity | non_neg_integer(),
                                      OldLimit :: infinity | non_neg_integer(),
                                      Reason :: term().

Changes the request limit. πŸ”₯

Note that this has no effect on the application configuration as defined by configuration files, so a node restart will revert the config to whatever is in those files.

This function is primarily useful in load regulation scenarios. βš–οΈ


✨ unload_mib/2 ✨

unload_mib(Agent, Mib) -> ok | {error, Reason}
                           when
                               Agent :: pid() | AgentName,
                               AgentName :: atom(),
                               Mib :: string(),
                               Reason :: not_loaded | term().

Unload a single Mib from an agent. Bye bye little Mib. πŸ¦‹


✨ unload_mibs/3 ✨

unload_mibs(Agent, Mibs, Force) -> ok | {error, Reason}
                            when
                                Agent :: pid() | AgentName,
                                AgentName :: atom(),
                                Mibs :: [MibName],
                                MibName :: string(),
                                Force :: boolean(),
                                Reason ::
                                    {'unload aborted at', MibName,
                                     InternalReason},
                                InternalReason :: not_loaded | term().

Unload Mibs from an agent. If it cannot unload all MIBs (the default value of the Force argument is false), it will indicate where unloading was aborted.

If Force = true then the agent will continue attempting to unload each mib even after failing to unload a previous mib. Use with care. ⚠️


✨ unregister_notification_filter/2 ✨

unregister_notification_filter(Agent, Id) -> ok | {error, Reason}
                                               when
                                                   Agent :: pid() | AgentName,
                                                   AgentName :: atom(),
                                                   Id :: nfilter_id(),
                                                   Reason :: term().

Unregister a notification filter. πŸ‘‘


✨ unregister_subagent/2 ✨

unregister_subagent(Agent, SubAgentOidOrPid) ->
                                    ok | {error, Reason}
                                    when
                                        Agent :: pid() | AgentName,
                                        AgentName :: atom(),
                                        SubAgentOidOrPid :: snmp:oid() | pid(),
                                        Reason :: term().

Unregister a sub-agent. If the second argument is a pid, then that sub-agent will be unregistered from all trees in Agent. All trees, bestie. Every single one. 🌳


✨ update_mibs_cache_age/2 ✨

update_mibs_cache_age(Agent, Age) -> ok | {error, Reason}
                                      when
                                          Agent :: pid() | AgentName,
                                          AgentName :: atom(),
                                          Age :: pos_integer(),
                                          Reason :: term().

Change the mib server cache age property. ⏳


✨ update_mibs_cache_gclimit/2 ✨

update_mibs_cache_gclimit(Agent, GcLimit) -> ok | {error, Reason}
                                          when
                                              Agent :: pid() | AgentName,
                                              AgentName :: atom(),
                                              GcLimit :: pos_integer(),
                                              Reason :: term().

Change the mib server cache gclimit property. 🧹


✨ verbosity/2 ✨

verbosity(Target, Verbosity) -> snmp:void()
                          when
                              Target :: all | LogicalName | PidOrAgentName,
                              LogicalName ::
                                  net_if | note_store | mib_server |
                                  symbolic_store | local_db,
                              PidOrAgentName :: pid() | master_agent | atom(),
                              Verbosity :: SNMPVerb | SubAgent,
                              SNMPVerb :: snmp:verbosity(),
                              SubAgent :: {subagents, snmp:verbosity()}.

Sets 'verbosity' for the indicated process(s):

  • all β€” Sets verbosity for all the agent processes; net_if, note_store, mib_server, symbolic_store, local_db and master_agent (and sub-agents).
  • net_if β€” Sets verbosity for the net-if process.
  • note_store β€” Sets verbosity for the note store process.

okay so back to the verbosity target tea, bestie β€” here's the whole lineup:

  • mib_server β€” sets verbosity for the mib server process. πŸ’…
  • symbolic_store β€” sets verbosity for the symbolic store process. πŸŽ€
  • local_db β€” sets verbosity for the local-db process. πŸ¦‹
  • master_agent | pid() when Verbosity = {subagents, snmp:verbosity()} β€” sets verbosity for all sub-agent(s) controlled by this (master) agent. πŸ‘‘
  • master_agent | pid() | atom() β€” sets verbosity for the agent process. ✨

the following text documents expected input-output relations, fr fr:

  • if Target :: all | net_if | note_store | mib_server | symbolic_store | local_db, then Verbosity :: snmp:verbosity(). 🌈
  • if Target :: master_agent, then Verbosity :: {subagents, snmp:verbosity()}. πŸ’–
  • if Target :: pid() | atom(), then Verbosity :: snmp:verbosity() | {subagents, snmp:verbosity()}. πŸ”₯

whereis_mib(Agent, MibName) -> {ok, MibFile} | {error, Reason}

when
    Agent :: pid() | AgentName,
    AgentName :: atom(),
    MibName :: atom(),
    MibFile :: string(),
    Reason :: term().

get the full path to the (compiled) mib-file. πŸ’…

which_aliasnames() -> AliasNames

when
    AliasNames :: [AliasName],
    AliasName :: atom().

retrieve all alias-names known to the agent. ✨

which_mibs(Agent) -> Mibs

when
    Agent :: pid() | AgentName,
    AgentName :: atom(),
    Mibs :: [{MibName, MibFile}],
    MibName :: atom(),
    MibFile :: string().

retrieve the list of all the mibs loaded into this agent. default is the master agent. πŸ¦‹

which_mibs_cache_size(Agent) -> {ok, Size} | {error, Reason}

when
    Agent :: pid() | AgentName,
    AgentName :: atom(),
    Size :: non_neg_integer(),
    Reason :: term().

retrieve the size of the mib server cache. πŸŽ€

which_notification_filter(Agent) -> Filters

when
    Agent :: pid() | AgentName,
    AgentName :: atom(),
    Filters :: [FilterId],
    FilterId :: nfilter_id().

list all notification filters in an agent. πŸ’–

which_notifications() -> Notifications

when
    Notifications :: [{Name, MibName, Info}],
    Name :: atom(),
    MibName :: atom(),
    Info :: term().

retrieve all notifications (and traps) known to the agent. πŸ‘‘

which_tables() -> Tables

when
    Tables :: [Table],
    Table :: atom().

retrieve all tables known to the agent. 🌸

which_transports() -> Transports

when
    Transports :: [Transport],
    Transport :: {TDomain, TAddress} | {TDomain, TAddress, Kind},
    TDomain :: snmp:tdomain(),
    TAddress :: {IpAddr, IpPort},
    IpAddr :: inet:ip_address(),
    IpPort :: inet:port_number(),
    Kind :: transport_kind().

retrieve all configured transports. 🌈

which_variables() -> Variables

when
    Variables :: [Variable],
    Variable :: atom().

retrieve all variables known to the agent. πŸ”₯


that's the whole snmpa manual page, bestie! you ate that. made with πŸ’– by Ericsson AB Β· snmp 5.20.5 Β· snmpa(3) Β· periodt.

πŸ“¦ where this page comes from