0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

SNMP: Add documentation

This commit is contained in:
Vojtech Vilimek 2023-11-08 10:55:42 +01:00
parent 332fc82142
commit bcbb56bef6
3 changed files with 632 additions and 188 deletions

View File

@ -29,13 +29,13 @@
* | SNMP_OPEN | socket created, starting subagent
* +-----------------+
* |
* | BIRD recieve response for Open-PDU
* | BIRD receive response for Open-PDU
* V
* +-----------------+
* | SNMP_REGISTER | session was established, subagent registers MIBs
* +-----------------+
* |
* | subagent recieved responses for all registration requests
* | subagent received responses for all registration requests
* V
* +-----------------+
* | SNMP_CONN | everything is set
@ -68,7 +68,7 @@
* session is establised and the GetNext request should be responsed
* without regard to MIB registration.
*
* When the session has been closed for some reason (socket error, reciept of
* When the session has been closed for some reason (socket error, receipt of
* Close-PDU) SNMP cleans the session information and message queue and goes
* back to the SNMP_LOCKED state.
*
@ -98,6 +98,13 @@ static const char * const snmp_state[] = {
[SNMP_DOWN] = "SNMP DOWN",
};
/*
* snmp_init - preinitialize SNMP instance
* @CF - SNMP configuration generic handle
*
* Return value is generic handle pointing to preinitialized SNMP procotol
* instance.
*/
static struct proto *
snmp_init(struct proto_config *CF)
{
@ -123,6 +130,15 @@ snmp_init(struct proto_config *CF)
return P;
}
/*
* snmp_cleanup - free all resources allocated by SNMP protocol
* @p - SNMP protocol instance
*
* This function forcefully stops and cleans all resources and memory acqiured
* by given SNMP protocol instance, such as timers, lists, hash tables etc.
* Function snmp_cleanup() does not change the protocol state to PS_DOWN for
* practical reasons, it should be done by the caller.
*/
static inline void
snmp_cleanup(struct snmp_proto *p)
{
@ -163,6 +179,13 @@ snmp_cleanup(struct snmp_proto *p)
p->state = SNMP_DOWN;
}
/*
* snmp_down - stop the SNMP protocol and free resources
* @p - SNMP protocol instance
*
* AgentX session is destroyed by closing underlying socket and all resources
* are freed. Afterwards, the PS_DOWN protocol state is announced.
*/
void
snmp_down(struct snmp_proto *p)
{
@ -170,12 +193,17 @@ snmp_down(struct snmp_proto *p)
proto_notify_state(&p->p, PS_DOWN);
}
/* this function is internal and shouldn't be used outside the snmp module */
/*
* snmp_connected - start AgentX session on established channel
* @sk - socket owned by SNMP protocol instance
*
* Starts the AgentX communication by sending an agentx-Open-PDU.
* This function is internal and shouldn't be used outside the SNMP module.
*/
void
snmp_connected(sock *sk)
{
struct snmp_proto *p = sk->data;
snmp_log("connection created");
p->state = SNMP_OPEN;
@ -189,7 +217,16 @@ snmp_connected(sock *sk)
tm_set(p->ping_timer, current_time() + p->timeout S);
}
/* this function is internal and shouldn't be used outside the snmp module */
/*
* snmp_sock_disconnect - end or reset socket connection
* @p - SNMP protocol instance
*
* If the @reconnect flags is set, we close the socket and then reestablish
* the AgentX session by reentering the start procedure as from the
* snmp_start_locked() function.
* Otherwise we simply shutdown the SNMP protocol if the flag is clear.
* This function is internal and shouldn't be used outside the SNMP module.
*/
void
snmp_sock_disconnect(struct snmp_proto *p, int reconnect)
{
@ -210,6 +247,11 @@ snmp_sock_disconnect(struct snmp_proto *p, int reconnect)
tm_start(p->startup_timer, 4 S); // TODO make me configurable
}
/*
* snmp_sock_err - handle errors on socket by reopenning the socket
* @sk - socket owned by SNMP protocol instance
* @err - socket error errno
*/
static void
snmp_sock_err(sock *sk, int UNUSED err)
{
@ -220,6 +262,15 @@ snmp_sock_err(sock *sk, int UNUSED err)
snmp_sock_disconnect(p, 1);
}
/*
* snmp_start_locked - open the socket on locked address
* @lock - object lock guarding the communication mean (address, ...)
*
* This function is called when the object lock is acquired. Main goal is to set
* socket parameters and try to open configured socket. Function
* snmp_connected() handles next stage of SNMP protocol start. When the socket
* coundn't be opened, a new try is scheduled after a small delay.
*/
static void
snmp_start_locked(struct object_lock *lock)
{
@ -257,13 +308,19 @@ snmp_start_locked(struct object_lock *lock)
p->errs = 0;
}
snmp_log("opening socket");
/* Try opening the socket, schedule a retry on fail */
if (sk_open(s) < 0)
tm_set(p->startup_timer, current_time() + p->timeout S);
}
/* this function is internal and shouldn't be used outside the snmp module */
/*
* snmp_reconnect - helper restarting the AgentX session on packet errors
* @tm - the startup_timer holding the SNMP protocol instance
*
* Rerun the SNMP module start procedure. Used in situations when the master
* agent returns an agentx-Response-PDU with 'Not Opened' error. We do not close
* the socket if have one.
*/
void
snmp_reconnect(timer *tm)
{
@ -283,8 +340,15 @@ snmp_reconnect(timer *tm)
snmp_connected(p->sock);
}
/* this function is internal and shouldn't be used outside the snmp module */
/*
* snmp_startup - start initialized SNMP protocol
* @p - SNMP protocol to start
*
* Starting of SNMP protocols begins with address acqusition through object
* lock. Next step is handled by snmp_start_locked() function.
* This function is internal and shouldn't be used outside the SNMP
* module.
*/
void
snmp_startup(struct snmp_proto *p)
{
@ -301,7 +365,6 @@ snmp_startup(struct snmp_proto *p)
return;
}
snmp_log("preparing object lock");
p->state = SNMP_INIT;
struct object_lock *lock;
@ -318,21 +381,42 @@ snmp_startup(struct snmp_proto *p)
olock_acquire(lock);
}
/* this function is internal and shouldn't be used outside the snmp module */
/*
* snmp_startup_timeout - start the initiliazed SNMP protocol
* @tm - the startup_timer holding the SNMP protocol instance.
*
* When the timer rings, the function snmp_startup() is invoked.
* This function is internal and shoudln't be used outside the SNMP module.
* Used when we delaying the start procedure, or we want to resend
* an agentx-Open-PDU for non-responding master agent.
*/
void
snmp_startup_timeout(timer *t)
snmp_startup_timeout(timer *tm)
{
snmp_log("startup timer triggered");
snmp_startup(t->data);
snmp_startup(tm->data);
}
/*
* snmp_stop_timeout - a timeout for nonresponding master agent
* @tm - the startup_timer holding the SNMP protocol instance.
*
* We are shutting down the SNMP protocol instance and we sent the
* agentx-Close-PDU. This function forcefully closes the AgentX session and
* stops the SNMP protocol instance. Used only when we did not receive any
* agentx-Response-PDU for the sent closed packet (before timeout).
*/
static void
snmp_stop_timeout(timer *t)
snmp_stop_timeout(timer *tm)
{
snmp_log("stop timer triggered");
snmp_down(t->data);
snmp_down(tm->data);
}
/*
* snmp_ping_timeout - send a agentx-Ping-PDU
* @tm - the ping_timer holding the SNMP protocol instance.
*
* Send an agentx-Ping-PDU and reset the timer for next ping.
*/
static void
snmp_ping_timeout(timer *tm)
{
@ -342,11 +426,18 @@ snmp_ping_timeout(timer *tm)
p->state == SNMP_CONN)
{
snmp_ping(p);
tm_set(tm, current_time() + p->timeout S);
}
tm_set(tm, current_time() + p->timeout S);
}
/*
* snmp_start - Initialize the SNMP protocol instance
* @P - SNMP protocol generic handle
*
* The first step in AgentX subagent startup is protocol initialition.
* We must prepare lists, find BGP peers and finally asynchornously open
* a AgentX subagent session through snmp_startup() function call.
*/
static int
snmp_start(struct proto *P)
{
@ -391,6 +482,15 @@ snmp_start(struct proto *P)
return PS_START;
}
/*
* snmp_reconfigure - Test if SNMP instance is reconfigurable
* @P - SNMP protocol generic handle, current state
* @CF - SNMP protocol configuration generic handle carring new values
*
* We accept the reconfiguration if the new configuration @CF is identical with
* the currently deployed. Otherwise we deny reconfiguration because
* the implementation would be cumbersome.
*/
static int
snmp_reconfigure(struct proto *P, struct proto_config *CF)
{
@ -417,6 +517,10 @@ skip:;
&& ! strncmp(old->description, new->description, UINT32_MAX);
}
/*
* snmp_show_proto_info - Print basic information about SNMP protocol instance
* @P - SNMP protocol generic handle
*/
static void
snmp_show_proto_info(struct proto *P)
{
@ -491,6 +595,10 @@ snmp_show_proto_info(struct proto *P)
}
}
/*
* snmp_postconfig - Check configuration correctness
* @CF - SNMP procotol configuration generic handle
*/
static void
snmp_postconfig(struct proto_config *CF)
{
@ -499,6 +607,16 @@ snmp_postconfig(struct proto_config *CF)
cf_error("local as not specified");
}
/*
* snmp_shutdown - Forcefully stop the SNMP protocol instance
* @P - SNMP protocol generic handle
*
* If we have established connection, we firstly stop the subagent and then
* later cleanup the protocol. The subagent stopping consist of sending the
* agentx-Close-PDU and changing the current protocol state to PS_STOP.
* If we have no connection created, we simple do the cleanup.
* The cleanup is transition straight to PS_DOWN state with snmp_cleanup() call.
*/
static int
snmp_shutdown(struct proto *P)
{
@ -527,6 +645,11 @@ snmp_shutdown(struct proto *P)
}
}
/*
* Protocol infrastructure
*/
struct protocol proto_snmp = {
.name = "Snmp",
.template = "snmp%d",

View File

@ -27,12 +27,25 @@
*
*/
/**
* Handling of malformed packet:
* When we find an error in PDU data, we create and send a response with error
* defined by the RFC. We await until the packet is send and then we close the
* communication socket. This also closes the established session. We chose
* this approach because we cannot easily mark the boundary between packets.
* When we are reseting the connection, we change the snmp_state to SNMP_RESET.
* In SNMP_RESET state we skip all received bytes and wait for snmp_tx()
* to be called. The socket's tx_hook is called when the TX-buffer is empty,
* meaning our response (agentx-Response-PDU) was send.
*
*/
static void snmp_mib_fill2(struct snmp_proto *p, struct oid *oid, struct snmp_pdu *c);
static uint parse_response(struct snmp_proto *p, byte *buf, uint size);
static void do_response(struct snmp_proto *p, byte *buf, uint size);
static uint parse_gets2_pdu(struct snmp_proto *p, byte *buf, uint size, uint *skip);
static struct agentx_response *prepare_response(struct snmp_proto *p, struct snmp_pdu *c);
static void response_err_ind(struct agentx_response *res, uint err, uint ind);
static void response_err_ind(struct agentx_response *res, enum agentx_response_errs err, u16 ind);
static uint update_packet_size(struct snmp_proto *p, const byte *start, byte *end);
static struct oid *search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_end, struct oid *o_curr, struct snmp_pdu *c, enum snmp_search_res *result);
static void snmp_tx(sock *sk);
@ -40,20 +53,33 @@ static void snmp_tx(sock *sk);
u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
static const char * const snmp_errs[] UNUSED = {
#define SNMP_ERR_SHIFT 256
[AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT] = "Open failed",
[AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT] = "Not open",
[AGENTX_RES_INDEX_WRONG_TYPE - SNMP_ERR_SHIFT] = "Index wrong type",
[AGENTX_RES_INDEX_ALREADY_ALLOC - SNMP_ERR_SHIFT] = "Index already allocated",
[AGENTX_RES_INDEX_NONE_AVAIL - SNMP_ERR_SHIFT] = "Index none availlable",
[AGENTX_RES_NOT_ALLOCATED - SNMP_ERR_SHIFT] = "Not allocated",
[AGENTX_RES_UNSUPPORTED_CONTEXT - SNMP_ERR_SHIFT] = "Unsupported contex",
[AGENTX_RES_DUPLICATE_REGISTER - SNMP_ERR_SHIFT] = "Duplicate registration",
[AGENTX_RES_UNKNOWN_REGISTER - SNMP_ERR_SHIFT] = "Unknown registration",
[AGENTX_RES_UNKNOWN_AGENT_CAPS - SNMP_ERR_SHIFT] = "Unknown agent caps",
[AGENTX_RES_PARSE_ERROR - SNMP_ERR_SHIFT] = "Parse error",
[AGENTX_RES_REQUEST_DENIED - SNMP_ERR_SHIFT] = "Request denied",
[AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT] = "Processing error",
[AGENTX_RES_NO_ERROR ] = "No error",
[AGENTX_RES_GEN_ERROR ] = "General error",
[AGENTX_RES_NO_ACCESS ] = "No access",
[AGENTX_RES_WRONG_TYPE ] = "Wrong type",
[AGENTX_RES_WRONG_LENGTH ] = "Wrong length",
[AGENTX_RES_WRONG_ENCODING ] = "Wrong encoding",
[AGENTX_RES_WRONG_VALUE ] = "Wrong value",
[AGENTX_RES_NO_CREATION ] = "No creation",
[AGENTX_RES_INCONSISTENT_VALUE ] = "Inconsistent value",
[AGENTX_RES_RESOURCE_UNAVAILABLE ] = "Resource unavailable",
[AGENTX_RES_COMMIT_FAILED ] = "Commit failed",
[AGENTX_RES_UNDO_FAILED ] = "Undo failed",
[AGENTX_RES_NOT_WRITABLE ] = "Not writable",
[AGENTX_RES_INCONSISTENT_NAME ] = "Inconsistent name",
[AGENTX_RES_OPEN_FAILED ] = "Open failed",
[AGENTX_RES_NOT_OPEN ] = "Not open",
[AGENTX_RES_INDEX_WRONG_TYPE ] = "Index wrong type",
[AGENTX_RES_INDEX_ALREADY_ALLOC ] = "Index already allocated",
[AGENTX_RES_INDEX_NONE_AVAIL ] = "Index none availlable",
[AGENTX_RES_NOT_ALLOCATED ] = "Not allocated",
[AGENTX_RES_UNSUPPORTED_CONTEXT ] = "Unsupported contex",
[AGENTX_RES_DUPLICATE_REGISTER ] = "Duplicate registration",
[AGENTX_RES_UNKNOWN_REGISTER ] = "Unknown registration",
[AGENTX_RES_UNKNOWN_AGENT_CAPS ] = "Unknown agent caps",
[AGENTX_RES_PARSE_ERROR ] = "Parse error",
[AGENTX_RES_REQUEST_DENIED ] = "Request denied",
[AGENTX_RES_PROCESSING_ERR ] = "Processing error",
};
static const char * const snmp_pkt_type[] UNUSED = {
@ -78,6 +104,16 @@ static const char * const snmp_pkt_type[] UNUSED = {
};
/*
* snmp_register_ok - registration of OID was successful
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @oid: OID that was successfully registered
* @class: MIB subtree of @oid
*
* Send a notification to MIB (selected by @class) about successful registration
* of @oid.
*/
static void
snmp_register_ok(struct snmp_proto *p, struct agentx_response *res, struct oid *oid, u8 UNUSED class)
{
@ -85,6 +121,16 @@ snmp_register_ok(struct snmp_proto *p, struct agentx_response *res, struct oid *
snmp_bgp_reg_ok(p, res, oid);
}
/*
* snmp_regsiter_failed - registration of OID failed
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @oid: OID whose registration failed
* @class: MIB subtree of @oid
*
* Send a notification to MIB (selected by @class) about @oid registraion
* failure.
*/
static void
snmp_register_failed(struct snmp_proto *p, struct agentx_response *res, struct oid *oid, u8 UNUSED class)
{
@ -92,6 +138,12 @@ snmp_register_failed(struct snmp_proto *p, struct agentx_response *res, struct o
snmp_bgp_reg_failed(p, res, oid);
}
/*
* snmp_register_ack - handle response to agentx-Register-PDU
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @class: MIB subtree associated with agentx-Register-PDU
*/
void
snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class)
{
@ -123,12 +175,27 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class)
}
}
/*
* snmp_rx_skip - skip all received data
* @sk: communication socket
* @size: size of received PDUs
*
* Socket rx_hook used when we are reseting the connection due to malformed PDU.
*/
static int
snmp_rx_skip(sock UNUSED *sk, uint UNUSED size)
{
return 1;
}
/*
* snmp_error - handle a malformed packet
* @p: SNMP protocol instance
*
* We wait until all packets are send. Then we close the socket which also
* closes the established session on given socket. Finally we try to start a new
* session.
*/
static inline void
snmp_error(struct snmp_proto *p)
{
@ -139,8 +206,14 @@ snmp_error(struct snmp_proto *p)
p->sock->tx_hook = snmp_tx;
}
/*
* snmp_simple_response - send an agentx-Response-PDU with no data payload
* @p: SNMP protocol instance
* @error: PDU error fields value
* @index: PDU error index field value
*/
static void
snmp_simple_response(struct snmp_proto *p, enum agentx_response_err error, u16 index)
snmp_simple_response(struct snmp_proto *p, enum agentx_response_errs error, u16 index)
{
sock *sk = p->sock;
struct snmp_pdu c = SNMP_PDU_CONTEXT(sk);
@ -153,6 +226,14 @@ snmp_simple_response(struct snmp_proto *p, enum agentx_response_err error, u16 i
sk_send(sk, sizeof(struct agentx_response));
}
/*
* open_pdu - send an agentx-Open-PDU
* @p: SNMP protocol instance
* @oid: PDU OID description field value
*
* Other fields are filled based on @p configuratin (timeout, subagent string
* description)
*/
static void
open_pdu(struct snmp_proto *p, struct oid *oid)
{
@ -185,6 +266,14 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
#undef TIMEOUT_SIZE
}
/*
* send_notify_pdu - send an agentx-Notify-PDU
* @p: SNMP protocol instance
* @oid: PDU notification Varbind name (OID)
* @data: PDU Varbind payload
* @size - PDU Varbind payload size
* @include_uptime: flag enabling inclusion of sysUpTime.0 OID
*/
void
snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime)
{
@ -257,17 +346,27 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
#undef UPTIME_SIZE
}
/* index allocate / deallocate pdu * /
#if 0
/*
* de_allocate_pdu - common functionality for allocation PDUs
* @p: SNMP protocol instance
* @oid: OID to allocate/deallocate
* @type: allocate/deacollcate PDU type
* @flags: type of allocation (NEW_INDEX, ANY_INDEX)
*
* This function is internal and shouldn't be used outside the SNMP module.
*/
static void
de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type)
de_allocate_pdu(struct snmp_proto *p, struct oid *oid, enum agentx_pdu_types type, u8 flags)
{
sock *sk = p->sock;
byte *buf, *pkt;
buf = pkt = sk->tbuf;
uint size = sk->tbsize;
struct snmp_pdu = SNMP_PDU_CONTEXT(p->sock);
if (size > AGENTX_HEADER_SIZE + )
if (size > AGENTX_HEADER_SIZE + 0) // TODO additional size
{
struct agentx_header *h;
SNMP_CREATE(pkt, struct agentx_header, h);
@ -275,22 +374,57 @@ de_allocate_pdu(struct snmp_proto *p, struct oid *oid, u8 type)
SNMP_SESSION(h,p);
struct agentx_varbind *vb = (struct agentx_varbind *) pkt;
// TODO
STORE_16(vb->type, AGENTX_OBJECT_ID);
STORE(vb->oid,
STORE(vb->oid, 0);
}
}
*/
/* Register-PDU / Unregister-PDU */
void
snmp_allocate(struct snmp_proto *p, struct oid *oid, u8 flags)
{
/* TODO - call the de_allocate_pdu() */
}
void
snmp_deallocate(struct snmp_proto *p, struct oid *oid, u8 flags)
{
/* TODO - call the de_allocate_pdu() */
}
#endif
/*
* un_register_pdu - common functionality for registration PDUs
* @p: SNMP protocol instance
* @oid: OID to register/unregister
* @bound: OIDs registration upper bound
* @index: OIDs registration n_subid index
* @type: register/unregister PDU type
* @is_instance: flag enabling instance registration (used only for register)
* @contid: context ID to register in (currently unsupported)
*
* Both register and unregister PDUs are capable of specifing a number of OIDs
* by using pair of index and upper bound. The index (r.range_subid) points into
* the OID's n_subid array to ID being threated as variable. The upper bound
* (r.upper_bound) determins maximal value for n_subid selected by index.
* The index and upper bound are passed as @index, and @bound respectively.
*
* Zero value for @is_instance means we want to register/unregister OID as a MIB
* subtree, for nonzero value we are registering MIB tree an instance (leaf).
*
* This function in internal and shoulnd't be used outside the SNMP module,
* see snmp_register() and snmp_unregister() functions.
*/
static void
un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 type, u8 is_instance, uint UNUSED contid)
un_register_pdu(struct snmp_proto *p, struct oid *oid, uint bound, uint index, enum agentx_pdu_types type, u8 is_instance, uint UNUSED contid)
{
const struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
sock *sk = p->sock;
struct snmp_pdu c = SNMP_PDU_CONTEXT(sk);
/* conditional +4 for upper-bound (optinal field) */
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) + ((len > 1) ? 4 : 0);
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) + ((bound > 1) ? 4 : 0);
if (c.size < sz)
snmp_manage_tbuf(p, &c);
@ -298,7 +432,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8
struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
SNMP_HEADER(h, type, is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : 0);
SNMP_HEADER(h, (u8) type, is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : 0);
p->packet_id++;
SNMP_SESSION(h, p);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
@ -309,7 +443,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8
STORE_U8(ur->timeout, p->timeout);
/* default priority */
STORE_U8(ur->priority, cf->priority);
STORE_U8(ur->range_subid, (len > 1) ? index : 0);
STORE_U8(ur->range_subid, (bound > 1) ? index : 0);
STORE_U8(ur->pad, 0);
ADVANCE(c.buffer, c.size, sizeof(struct agentx_un_register_hdr));
@ -317,9 +451,9 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8
ADVANCE(c.buffer, c.size, snmp_oid_size(oid));
/* place upper-bound if needed */
if (len > 1)
if (bound > 1)
{
STORE_PTR(c.buffer, len);
STORE_PTR(c.buffer, bound);
ADVANCE(c.buffer, c.size, 4);
}
@ -328,22 +462,46 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8
sk_send(sk, s);
}
/* Register-PDU */
/*
* snmp_register - send an agentx-Register-PDU
* @p: SNMP protocol instance
* @oid: OID to register
* @bound: OIDs registration upper bound
* @index: OIDs registration n_subid index
* @is_instance: flag enabling instance registration
* @contid: context ID to register in (currently unsupported)
*
* For more detailed description see un_register_pdu() function.
*/
void
snmp_register(struct snmp_proto *p, struct oid *oid, uint len, uint index, u8 is_instance, uint contid)
snmp_register(struct snmp_proto *p, struct oid *oid, uint bound, uint index, u8 is_instance, uint contid)
{
un_register_pdu(p, oid, len, index, AGENTX_REGISTER_PDU, is_instance, contid);
un_register_pdu(p, oid, bound, index, AGENTX_REGISTER_PDU, is_instance, contid);
}
/* Unregister-PDU */
/*
* snmp_unregister - send an agentx-Unregister-PDU
* @p: SNMP protocol instance
* @oid: OID to uregister
* @bound: OIDs unregistration upper bound
* @index: OIDs unregistration n_subid index
* @contid: context ID to unregister from (currently unsupported)
*
* For more detailed description see un_register_pdu() function.
*/
void UNUSED
snmp_unregister(struct snmp_proto *p, struct oid *oid, uint len, uint index, uint contid)
{
un_register_pdu(p, oid, len, index, AGENTX_UNREGISTER_PDU, 0, contid);
}
/*
* close_pdu - send an agentx-Close-PDU
* @p: SNMP protocol instance
* @reason: reason for closure
*/
static void
close_pdu(struct snmp_proto *p, u8 reason)
close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
{
sock *sk = p->sock;
struct snmp_pdu c = SNMP_PDU_CONTEXT(sk);
@ -359,7 +517,7 @@ close_pdu(struct snmp_proto *p, u8 reason)
SNMP_SESSION(h, p);
c.byte_ord = h->flags & AGENTX_NETWORK_BYTE_ORDER;
snmp_put_fbyte(c.buffer, reason);
snmp_put_fbyte(c.buffer, (u8) reason);
ADVANCE(c.buffer, c.size, 4);
uint s = update_packet_size(p, sk->tpos, c.buffer);
@ -367,6 +525,14 @@ close_pdu(struct snmp_proto *p, u8 reason)
#undef REASON_SIZE
}
/*
* parse_close_pdu - parse an agentx-Close-PDU
* @p: SNMP protocol instance
* @pkt_start: pointer to first byte of PDU
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_close_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
{
@ -389,10 +555,23 @@ parse_close_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
return AGENTX_HEADER_SIZE;
}
/*
* snmp_testset - check possibility of VarBind name and data setting
* @p: SNMP protocol instance
* @vb: checked VarBind
* @oid: pool-allocated prefixed copy of VarBind name
* @pkt_size: number of not parsed bytes in processed PDU
*
* Check done by specialized function for specific MIB subtree whether
* the VarBind is valid for set action (changing to current value to value
* in VarBind).
*
* Return 1 if the VarBind setting is possible, 0 otherwise.
*/
/* MUCH better signature would be
static int snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, uint pkt_size);
*/
/* return 1 if the value could be set */
static int UNUSED
snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, struct oid *oid, uint pkt_size)
{
@ -497,6 +676,11 @@ removeagentcaps_pdu(struct snmp_proto *p, struct oid *cap)
}
#endif
/*
* refresh_ids - Copy current ids from packet to protocol
* @p: SNMP protocol instance
* @h: PDU header with new transaction_id and packet_id ids.
*/
static inline void
refresh_ids(struct snmp_proto *p, struct agentx_header *h)
{
@ -505,6 +689,14 @@ refresh_ids(struct snmp_proto *p, struct agentx_header *h)
p->packet_id = LOAD_U32(h->packet_id, byte_ord);
}
/*
* parse_test_set_pdu - parse an agentx-TestSet-PDU in buffer
* @p: SNMP protocol instance
* @pkt_start: first byte of test set PDU
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
{
@ -553,14 +745,16 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
if (sz > pkt_size)
{
c.error = AGENTX_RES_PARSE_ERROR;
goto error;
all_possible = 0;
break;
}
/* Unknown VarBind type check */
if (!snmp_test_varbind(vb))
{
c.error = AGENTX_RES_PARSE_ERROR;
goto error;
all_possible = 0;
break;
}
ADVANCE(pkt, size, snmp_varbind_size(vb, 0));
@ -572,8 +766,6 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
}
mb_free(tr);
#endif
goto error;
error:
s = update_packet_size(p, sk->tpos, c.buffer);
if (c.error != AGENTX_RES_NO_ERROR)
@ -593,12 +785,16 @@ error:
}
/*
* Common code for packets:
* agentx-CommitSet-PDU
* agentx-UndoSet-PDU
* parse_set_pdu - common functionality for commit set and undo set PDUs
* @p: SNMP protocol instance
* @pkt_start: pointer to first byte of on of set related PDU
* @size: number of bytes received from a socket
* @error: error status to use
*
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint err)
parse_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, enum agentx_response_errs err)
{
byte *pkt = pkt_start;
struct agentx_header *h = (void *) pkt;
@ -622,15 +818,15 @@ parse_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint err)
if (size < pkt_size)
{
c.error = AGENTX_RES_PARSE_ERROR;
goto error;
}
else
{
// TODO: free resource allocated by parse_test_set_pdu()
// TODO: do something meaningful
//mb_free(tr);
c.error = err;
}
// TODO: free resource allocated by parse_test_set_pdu()
// TODO: do something meaningful
//mb_free(tr);
c.error = err;
error:;
response_err_ind(r, c.error, 0);
sk_send(p->sock, AGENTX_HEADER_SIZE);
@ -641,7 +837,14 @@ error:;
return pkt - pkt_start;
}
/* agentx-CommitSet-PDU */
/*
* parse_commit_set_pdu - parse an agentx-CommitSet-PDU
* @p: SNMP protocol instance
* @pkt: pointer to first byte of PDU inside RX-buffer
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_commit_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
{
@ -650,7 +853,14 @@ parse_commit_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
return parse_set_pdu(p, pkt, size, AGENTX_RES_COMMIT_FAILED);
}
/* agentx-UndoSet-PDU */
/*
* parse_undo_set_pdu - parse an agentx-UndoSet-PDU
* @p: SNMP protocol instance
* @pkt: pointer to first byte of PDU inside RX-buffer
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from buffer.
*/
static uint
parse_undo_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
{
@ -659,7 +869,14 @@ parse_undo_set_pdu(struct snmp_proto *p, byte *pkt, uint size)
return parse_set_pdu(p, pkt, size, AGENTX_RES_UNDO_FAILED);
}
/* agentx-CleanupSet-PDU */
/*
* parse_cleanup_set_pdu - parse an agentx-CleanupSet-PDU
* @p: SNMP protocol instance
* @pkt_start: pointer to first byte of PDU inside RX-buffer
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
{
@ -684,13 +901,13 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start, uint size)
}
/**
* parse_pkt - parse recieved AgentX packet
* @p:
* @pkt: packet buffer
* @size: number of packet bytes in buffer
* retval number of byte parsed
* parse_pkt - parse received AgentX packet
* @p: SNMP protocol instance
* @pkt: first byte of PDU inside RX-buffer
* @size: number of bytes received from a socket
* @skip: length of header that stays still in partial processing
*
* Returns number of bytes parsed from RX-buffer.
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip)
@ -771,6 +988,14 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size, uint *skip)
}
/*
* parse_response - parse an agentx-Response-PDU
* @p: SNMP protocol instance
* @res: pointer of agentx-Response-PDU header in RX-buffer
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from RX-buffer.
*/
static uint
parse_response(struct snmp_proto *p, byte *res, uint size)
{
@ -833,13 +1058,17 @@ parse_response(struct snmp_proto *p, byte *res, uint size)
default:
/* erronous packet should be dropped quietly */
// TODO correct error?
snmp_log("recieved response with error '%s'", snmp_errs[get_u16(&r->error) - SNMP_ERR_SHIFT]);
snmp_log("received response with error '%s'", snmp_errs[get_u16(&r->error)]);
break;
}
return pkt_size + AGENTX_HEADER_SIZE;
}
/*
* snmp_register_mibs - register all MIB subtrees
* @p: SNMP protocol instance
*/
static void
snmp_register_mibs(struct snmp_proto *p)
{
@ -847,6 +1076,14 @@ snmp_register_mibs(struct snmp_proto *p)
/* snmp_ospf_regsiter(p); ... */
}
/*
* do_response - act on agentx-Response-PDU and protocol state
* @p: SNMP protocol instance
* @buf: RX-buffer with PDU bytes
* @size: number of bytes received from a socket
*
* Return number of bytes parsed from RX-buffer.
*/
static void
do_response(struct snmp_proto *p, byte *buf, uint size)
{
@ -859,11 +1096,11 @@ do_response(struct snmp_proto *p, byte *buf, uint size)
{
case SNMP_INIT:
case SNMP_LOCKED:
/* silent drop of recieved packet */
/* silent drop of received packet */
break;
case SNMP_OPEN:
/* copy session info from recieved packet */
/* copy session info from received packet */
p->session_id = LOAD_U32(h->session_id, byte_ord);
refresh_ids(p, h);
@ -902,6 +1139,10 @@ do_response(struct snmp_proto *p, byte *buf, uint size)
}
}
/*
* snmp_get_mib_class - classify MIB tree belongings of OID
* @oid: OID to be classified based on prefix
*/
u8
snmp_get_mib_class(const struct oid *oid)
{
@ -919,7 +1160,15 @@ snmp_get_mib_class(const struct oid *oid)
}
}
/* return 0 if the created varbind type is END_OF_MIB_VIEW, 1 otherwise */
/*
* snmp_get_next - process single agentx-GetNext-PDU search range
* @p: SNMP protocol instance
* @o_start: SearchRange start OID
* @o_end: SearchRange end OID
* @c: transmit PDU context to use
*
* Return 0 if the created VarBind type is endOfMibView, 1 otherwise.
*/
static int
snmp_get_next2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
struct snmp_pdu *c)
@ -984,7 +1233,16 @@ snmp_get_next2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
return 0;
}
/* returns 0 if the created varbind has type EndOfMibView, 1 otherwise */
/*
* snmp_get_bulk - process one iteration of get bulk PDU
* @p: SNMP protocol instance
* @o_start: SearchRange start OID
* @o_end: SearchRange end OID
* @state: state of get bulk PDU processing
* @c: transmit PDU context to use
*
* Return 0 if the created VarBind has type endOfMibView, 1 otherwise.
*/
static int
snmp_get_bulk2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
struct agentx_bulk_state *state, struct snmp_pdu *c)
@ -1002,7 +1260,7 @@ snmp_get_bulk2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
} while (o_curr && i < state->repetition);
// TODO check if the approach below works
// it need to generate varbinds that will be only of type EndOfMibView
// it need to generate varbinds that will be only of type endOfMibView
/* Object Identifier fall-backs */
if (!o_curr)
o_curr = o_predecessor;
@ -1042,6 +1300,14 @@ snmp_get_bulk2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
}
}
/*
* update_packet_size - set PDU size
* @p - SNMP protocol instance
* @start - pointer to PDU data start (excluding header size)
* @end - pointer after the last PDU byte
*
* Return number of bytes in TX-buffer (including header size).
*/
static inline uint
update_packet_size(struct snmp_proto *p, const byte *start, byte *end)
{
@ -1051,16 +1317,35 @@ update_packet_size(struct snmp_proto *p, const byte *start, byte *end)
return AGENTX_HEADER_SIZE + s;
}
/*
* response_err_ind - update response error and index
* @res: response PDU header
* @err: error status
* @ind: index of error, ignored for noAgentXError
*
* Update agentx-Response-PDU header fields res.error and it's res.index.
*/
static inline void
response_err_ind(struct agentx_response *res, uint err, uint ind)
response_err_ind(struct agentx_response *res, enum agentx_response_errs err, u16 ind)
{
STORE_U32(res->error, err);
STORE_U32(res->error, (u16) err);
if (err != AGENTX_RES_NO_ERROR && err != AGENTX_RES_PARSE_ERROR)
STORE_U32(res->index, ind);
else
STORE_U32(res->index, 0);
}
/*
* parse_gets_pdu - parse received gets PDUs
* @p: SNMP protocol instance
* @pkt_start: pointer to first byte of received PDU
* @size: number of bytes received from a socket
* @skip: length of header that stays still in partial processing
*
* Gets PDUs are agentx-Get-PDU, agentx-GetNext-PDU, agentx-GetBulk-PDU.
*
* Return number of bytes parsed from RX-buffer
*/
static uint
parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *skip)
{
@ -1137,7 +1422,7 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
/*
* If we already have written same relevant data to the TX buffer, then
* we send processed part, otherwise we don't have anything to send and
* need to wait for more data to be recieved.
* need to wait for more data to be received.
*/
if (sz > size && c.index > 0)
{
@ -1281,6 +1566,12 @@ free:
return ret;
}
/*
* snmp_start_subagent - send session open request
* @p: SNMP protocol instance
*
* Send agentx-Open-PDU with configured OID and string description.
*/
void
snmp_start_subagent(struct snmp_proto *p)
{
@ -1293,23 +1584,26 @@ snmp_start_subagent(struct snmp_proto *p)
mb_free(blank);
}
/*
* snmp_stop_subagent - close established session
* @p: SNMP protocol instance
*
* Send agentx-Close-PDU on established session.
*/
void
snmp_stop_subagent(struct snmp_proto *p)
{
if (p->state == SNMP_STOP)
if (p->state == SNMP_OPEN ||
p->state == SNMP_REGISTER ||
p->state == SNMP_CONN)
close_pdu(p, AGENTX_CLOSE_SHUTDOWN);
}
static inline int
oid_prefix(struct oid *o, u32 *prefix, uint len)
{
for (uint i = 0; i < len; i++)
if (o->ids[i] != prefix[i])
return 0;
return 1;
}
/*
* snmp_rx - handle received PDUs in RX-buffer in normal operation
* @sk: communication socket
* @size: number of bytes received
*/
int
snmp_rx(sock *sk, uint size)
{
@ -1345,8 +1639,13 @@ snmp_rx(sock *sk, uint size)
return 1;
}
/* snmp_tx - used to reset the connection when the
* agentx-Response-PDU was sent
/*
* snmp_tx - handle empty TX-buffer during session reset
* @sk: communication socket
*
* The socket tx_hook is called when the TX-buffer is empty, i.e. all data was
* send. This function is used only when we found malformed PDU and we are
* resetting the established session. If called we direcly reset the session.
*/
static void
snmp_tx(sock *sk)
@ -1355,7 +1654,10 @@ snmp_tx(sock *sk)
snmp_sock_disconnect(p, 1);
}
/* Ping-PDU */
/*
* snmp_ping - send an agentx-Ping-PDU
* @p: SNMP protocol instance
*/
void
snmp_ping(struct snmp_proto *p)
{
@ -1378,24 +1680,6 @@ snmp_ping(struct snmp_proto *p)
sk_send(sk, s);
}
static inline int
is_bgp4_mib_prefix(struct oid *o)
{
if (o->prefix == SNMP_MGMT && o->ids[0] == SNMP_MIB_2 &&
o->ids[1] == SNMP_BGP4_MIB)
return 1;
else
return 0;
}
static inline int
has_inet_prefix(struct oid *o)
{
return (o->n_subid > 4 && o->ids[0] == 1 &&
o->ids[1] == 3 && o->ids[2] == 6 &&
o->ids[3] == 1);
}
/**
* snmp_search_check_end_oid - check if oid is before SearchRange end
*
@ -1405,7 +1689,8 @@ has_inet_prefix(struct oid *o)
* check if found oid meet the SearchRange upper bound condition in
* lexicographical order, returns boolean value
*/
int snmp_search_check_end_oid(const struct oid *found, const struct oid *bound)
int
snmp_search_check_end_oid(const struct oid *found, const struct oid *bound)
{
if (snmp_is_oid_empty(bound))
return 1;
@ -1413,6 +1698,24 @@ int snmp_search_check_end_oid(const struct oid *found, const struct oid *bound)
return (snmp_oid_compare(found, bound) < 0);
}
/*
* search_mib - search for successor of given OID
* @p: SNMP protocol instance
* @o_start: search starting OID
* @o_end: search ending OID
* @o_curr: current OID inside @o_start, @o_end interval
* @c: transmit PDU context to use
* @result: search result state
*
* Perform a search in MIB tree in SearchRange from @o_start to @o_end.
* If the @o_start has set include the search is inclusive, the @o_end has
* always the include flag cleared. For agentx-GetNext-PDU, the o_curr is always
* NULL, for agentx-GetBulk-PDU it could have non-NULL value. In such case the
* @o_curr effectively replaces the role of @o_start. It is mandatory to pass
* @o_start and @o_end only allocated from @p protocol's memory pool.
*
* Return found OID or NULL.
*/
/* tree is tree with "internet" prefix .1.3.6.1
working only with o_start, o_end allocated in heap (not from buffer)*/
static struct oid *
@ -1466,20 +1769,21 @@ search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_
}
if (o_end == blank)
mb_free((void *) blank);
/* cast drops const qualifier */
mb_free((struct oid *)blank);
return o_curr;
}
/**
* snmp_prefixize - return prefixed oid copy if possible
* snmp_prefixize - return prefixed OID copy if possible
* @proto: allocation pool holder
* @oid: from packet loaded object identifier
* @byte_ord: byte order of @oid
*
* Returns prefixed (meaning with nonzero prefix field) oid copy of @oid if
* Return prefixed (meaning with nonzero prefix field) oid copy of @oid if
* possible, NULL otherwise. Returned pointer is always allocated from @proto's
* pool not a pointer to recieve buffer (from which is most likely @oid).
* pool not a pointer to RX-buffer (from which is most likely @oid).
*/
struct oid *
snmp_prefixize(struct snmp_proto *proto, const struct oid *oid, int byte_ord)
@ -1523,9 +1827,18 @@ snmp_prefixize(struct snmp_proto *proto, const struct oid *oid, int byte_ord)
return new;
}
/*
* snmp_mib_fill - append a AgentX VarBind to PDU
* @p: SNMP protocol instance
* @oid: OID to use as VarBind v.name
* @c: transmit PDU context to use
*
* Append new AgentX VarBind at the end of created PDU. The content (v.data)
* is handled in function specialized for given MIB subtree. The binding is
* created only if the v.name matches some variable name precisely.
*/
static void
snmp_mib_fill2(struct snmp_proto *p, struct oid *oid,
struct snmp_pdu *c)
snmp_mib_fill2(struct snmp_proto *p, struct oid *oid, struct snmp_pdu *c)
{
ASSUME(oid != NULL);
@ -1557,7 +1870,10 @@ snmp_mib_fill2(struct snmp_proto *p, struct oid *oid,
}
}
/**
/*
* snmp_manage_tbuf - handle situation with too short transmit buffer
* @p: SNMP protocol instance
* @c: transmit packet context to use
*
* Important note: After managing insufficient buffer size all in buffer pointers
* are invalidated!
@ -1571,6 +1887,13 @@ snmp_manage_tbuf(struct snmp_proto UNUSED *p, struct snmp_pdu *c)
c->size += 2048;
}
/*
* prepare_response - fill buffer with AgentX PDU header
* @p: SNMP protocol instance
* @c: transmit PDU context to use
*
* Prepare known parts of AgentX packet header into the TX-buffer held by @c.
*/
static struct agentx_response *
prepare_response(struct snmp_proto *p, struct snmp_pdu *c)
{
@ -1588,6 +1911,3 @@ prepare_response(struct snmp_proto *p, struct snmp_pdu *c)
ADVANCE(c->buffer, c->size, sizeof(struct agentx_response));
return r;
}
#undef SNMP_ERR_SHIFT

View File

@ -169,6 +169,7 @@ struct agentx_varbind {
u16 pad;
/* oid part */
struct oid name;
byte data[];
};
/* this does not work */
@ -208,29 +209,27 @@ struct agentx_bulk_state {
u32 repeaters;
};
enum agentx_pdu {
AGENTX_OPEN_PDU = 1,
AGENTX_CLOSE_PDU = 2,
AGENTX_REGISTER_PDU = 3,
AGENTX_UNREGISTER_PDU = 4,
AGENTX_GET_PDU = 5,
AGENTX_GET_NEXT_PDU = 6,
AGENTX_GET_BULK_PDU = 7,
AGENTX_TEST_SET_PDU = 8,
AGENTX_COMMIT_SET_PDU = 9,
AGENTX_UNDO_SET_PDU = 10,
AGENTX_CLEANUP_SET_PDU = 11,
AGENTX_NOTIFY_PDU = 12,
AGENTX_PING_PDU = 13,
AGENTX_INDEX_ALLOCATE_PDU = 14,
AGENTX_INDEX_DEALLOCATE_PDU = 15,
AGENTX_ADD_AGENT_CAPS_PDU = 16,
AGENTX_REMOVE_AGENT_CAPS_PDU = 17,
AGENTX_RESPONSE_PDU = 18,
enum agentx_pdu_types {
AGENTX_OPEN_PDU = 1, /* agentx-Open-PDU */
AGENTX_CLOSE_PDU = 2, /* agentx-Close-PDU */
AGENTX_REGISTER_PDU = 3, /* agentx-Regiter-PDU */
AGENTX_UNREGISTER_PDU = 4, /* agentx-Unregister-PDU */
AGENTX_GET_PDU = 5, /* agentx-Get-PDU */
AGENTX_GET_NEXT_PDU = 6, /* agentx-GetNext-PDU */
AGENTX_GET_BULK_PDU = 7, /* agentx-GetBulk-PDU */
AGENTX_TEST_SET_PDU = 8, /* agentx-TestSet-PDU */
AGENTX_COMMIT_SET_PDU = 9, /* agentx-CommitSet-PDU */
AGENTX_UNDO_SET_PDU = 10, /* agentx-UndoSet-PDU */
AGENTX_CLEANUP_SET_PDU = 11, /* agentx-CleanupSet-PDU */
AGENTX_NOTIFY_PDU = 12, /* agentx-Notify-PDU */
AGENTX_PING_PDU = 13, /* agentx-Ping-PDU */
AGENTX_INDEX_ALLOCATE_PDU = 14, /* agentx-IndexAllocate-PDU */
AGENTX_INDEX_DEALLOCATE_PDU = 15, /* agentx-IndexDeallocate-PDU */
AGENTX_ADD_AGENT_CAPS_PDU = 16, /* agentx-AddAgentCaps-PDU */
AGENTX_REMOVE_AGENT_CAPS_PDU = 17, /* agentx-RemoveAgentCaps-PDU */
AGENTX_RESPONSE_PDU = 18, /* agentx-Response-PDU */
} PACKED;
#define AGENTX_FLAGS_MASK 0x1F
enum agentx_flags {
AGENTX_FLAG_BLANK = 0x00,
AGENTX_FLAG_INSTANCE_REGISTRATION = 0x01,
@ -240,13 +239,13 @@ enum agentx_flags {
AGENTX_NETWORK_BYTE_ORDER = 0x10,
} PACKED;
#define AGENTX_FLAGS (AGENTX_FLAG_INSTANCE_REGISTRATION \
#define AGENTX_FLAGS_MASK (AGENTX_FLAG_INSTANCE_REGISTRATION \
| AGENTX_FLAG_NEW_INDEX \
| AGENTX_FLAG_ANY_INDEX \
| AGENTX_NON_DEFAULT_CONTEXT \
| AGENTX_NETWORK_BYTE_ORDER)
/* CLOSE_PDU close reasons */
/* agentx-Close-PDU close reasons */
enum agentx_close_reasons {
AGENTX_CLOSE_OTHER = 1,
AGENTX_CLOSE_PARSE_ERROR = 2,
@ -257,38 +256,38 @@ enum agentx_close_reasons {
} PACKED;
/* RESPONSE_PDU - result error */
enum agentx_response_err {
/* response OK master <-> subagent */
AGENTX_RES_NO_ERROR = 0,
/* TEST_SET_PDU response errors (subagent -> master) */
AGENTX_RES_GEN_ERROR = 5,
AGENTX_RES_NO_ACCESS = 6,
AGENTX_RES_WRONG_TYPE = 7,
AGENTX_RES_WRONG_LENGTH = 8,
AGENTX_RES_WRONG_ENCODING = 9,
AGENTX_RES_WRONG_VALUE = 10,
AGENTX_RES_NO_CREATION = 11,
AGENTX_RES_INCONSISTENT_VALUE = 12,
AGENTX_RES_RESOURCE_UNAVAILABLE = 13,
AGENTX_RES_COMMIT_FAILED = 14,
AGENTX_RES_UNDO_FAILED = 15,
AGENTX_RES_NOT_WRITABLE = 17,
AGENTX_RES_INCONSISTENT_NAME = 18,
/* end of TEST_SET_PDU resonse errs (master -> subagent) */
AGENTX_RES_OPEN_FAILED = 256,
AGENTX_RES_NOT_OPEN = 257,
AGENTX_RES_INDEX_WRONG_TYPE = 258,
AGENTX_RES_INDEX_ALREADY_ALLOC = 259,
AGENTX_RES_INDEX_NONE_AVAIL = 260,
AGENTX_RES_NOT_ALLOCATED = 261,
AGENTX_RES_UNSUPPORTED_CONTEXT = 262,
AGENTX_RES_DUPLICATE_REGISTER = 263,
AGENTX_RES_UNKNOWN_REGISTER = 264,
AGENTX_RES_UNKNOWN_AGENT_CAPS = 265,
AGENTX_RES_PARSE_ERROR = 266,
AGENTX_RES_REQUEST_DENIED = 267,
AGENTX_RES_PROCESSING_ERR = 268,
/* agentx-Response-PDU - result errors */
enum agentx_response_errs {
/* response error to both Administrative and SNMP messages */
AGENTX_RES_NO_ERROR = 0, /* noAgentXError */
/* response errors to SNMP messages */
AGENTX_RES_GEN_ERROR = 5, /* genError */
AGENTX_RES_NO_ACCESS = 6, /* noAccess */
AGENTX_RES_WRONG_TYPE = 7, /* wrongType */
AGENTX_RES_WRONG_LENGTH = 8, /* wrongLength */
AGENTX_RES_WRONG_ENCODING = 9, /* wrongEncoding */
AGENTX_RES_WRONG_VALUE = 10, /* wrongValue*/
AGENTX_RES_NO_CREATION = 11, /* noCreation */
AGENTX_RES_INCONSISTENT_VALUE = 12, /* inconsistentValue */
AGENTX_RES_RESOURCE_UNAVAILABLE = 13, /* resourceUnavailable */
AGENTX_RES_COMMIT_FAILED = 14, /* commitFailed */
AGENTX_RES_UNDO_FAILED = 15, /* undoFailed */
AGENTX_RES_NOT_WRITABLE = 17, /* notWritable */
AGENTX_RES_INCONSISTENT_NAME = 18, /* inconsistentName */
/* response error to Administrative messages */
AGENTX_RES_OPEN_FAILED = 256, /* openFailed */
AGENTX_RES_NOT_OPEN = 257, /* notOpen */
AGENTX_RES_INDEX_WRONG_TYPE = 258, /* indexWrongType */
AGENTX_RES_INDEX_ALREADY_ALLOC = 259, /* indexAlreadyAlloc */
AGENTX_RES_INDEX_NONE_AVAIL = 260, /* indexNoneAvail */
AGENTX_RES_NOT_ALLOCATED = 261, /* notAllocated */
AGENTX_RES_UNSUPPORTED_CONTEXT = 262, /* unsupportedContext */
AGENTX_RES_DUPLICATE_REGISTER = 263, /* duplicateRegister */
AGENTX_RES_UNKNOWN_REGISTER = 264, /* unknownRegister */
AGENTX_RES_UNKNOWN_AGENT_CAPS = 265, /* unknownAgentCaps */
AGENTX_RES_PARSE_ERROR = 266, /* parseError */
AGENTX_RES_REQUEST_DENIED = 267, /* requestDenied */
AGENTX_RES_PROCESSING_ERR = 268, /* processingError */
} PACKED;
/* SNMP PDU buffer info */
@ -296,10 +295,11 @@ struct snmp_pdu {
byte *buffer; /* pointer to buffer */
uint size; /* unused space in buffer */
int byte_ord; /* flag signaling NETWORK_BYTE_ORDER */
enum agentx_response_err error; /* storage for result of current action */
uint index; /* index on which the error was found */
enum agentx_response_errs error; /* storage for result of current action */
u32 index; /* index on which the error was found */
};
#if 0
struct agentx_alloc_context {
u8 is_instance; /* flag INSTANCE_REGISTRATION */
u8 new_index; /* flag NEW_INDEX */
@ -307,6 +307,7 @@ struct agentx_alloc_context {
char *context; /* context to allocate in */
uint clen; /* length of context string */
};
#endif
int snmp_rx(sock *sk, uint size);
int snmp_rx_stop(sock *sk, uint size);